diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e90ed6abbde55dfde1710e68989dd0c1ba63e8cd..a0049c32f1db1ae947edf3fdd366393b79dca999 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -35,7 +35,7 @@ unit_tests:
    - npm i
    - npm test
 
-.sonar:
+sonar:
   stage: codestyle
   only:
     - staging
@@ -62,7 +62,7 @@ ngbuild:
     paths:
       - "$BUILD_DIR"
 
-.deploy_staging:
+deploy_staging:
   stage: deploy
   only:
     - staging
diff --git a/angular.json b/angular.json
index 94cb7e5259bcd28c9dd604dd9d4629300e7244f4..d109071a53ca7e13a25df694b60b47c3543dc1a9 100644
--- a/angular.json
+++ b/angular.json
@@ -23,10 +23,20 @@
             ],
             "styles": [
               "src/styles.scss",
-              "./node_modules/material-design-icons/iconfont/material-icons.css"
+              "./node_modules/material-design-icons/iconfont/material-icons.css",
+              "node_modules/prismjs/themes/prism-okaidia.css",
+              "node_modules/prismjs/plugins/line-highlight/prism-line-highlight.css",
+              "node_modules/prismjs/plugins/line-numbers/prism-line-numbers.css"
             ],
             "scripts": [
-              "node_modules/marked/lib/marked.js"
+              "node_modules/marked/lib/marked.js",
+              "node_modules/emoji-toolkit/lib/js/joypixels.min.js",
+              "node_modules/prismjs/prism.js",
+              "node_modules/prismjs/components/prism-csharp.min.js",
+              "node_modules/prismjs/components/prism-css.min.js",
+              "node_modules/prismjs/plugins/line-highlight/prism-line-highlight.js",
+              "node_modules/prismjs/plugins/line-numbers/prism-line-numbers.js",
+              "node_modules/katex/dist/katex.min.js"
             ]
           },
           "configurations": {
diff --git a/docs/diagrams/Business_Use-Case_Diagram.svg b/docs/diagrams/Business_Use-Case_Diagram.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b3de799d169b28d555062796a0a8bd67f3b0e6ce
--- /dev/null
+++ b/docs/diagrams/Business_Use-Case_Diagram.svg
@@ -0,0 +1,225 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="3489px" preserveAspectRatio="none" style="width:2147px;height:3489px;background:#FAF0E6;" version="1.1" viewBox="0 0 2147 3489" width="2147px" zoomAndPan="magnify"><defs><filter height="300%" id="f167jbufqzj78x" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><!--MD5=[99d0713b2e5d7da82e17adab78c10e4b]
+cluster frag.jetzt | use-case diagram \n--><rect fill="#FAF0E6" filter="url(#f167jbufqzj78x)" height="2604" style="stroke:#000000;stroke-width:1.5;" width="1576" x="386" y="7"/><text fill="#000000" font-family="sans-serif" font-size="24" font-style="italic" lengthAdjust="spacing" textLength="122" x="1113" y="40.3999">«Business»</text><text fill="#000000" font-family="sans-serif" font-size="24" font-weight="bold" lengthAdjust="spacing" textLength="322" x="1009.5" y="78.6958">frag.jetzt | use-case diagram</text><text fill="#000000" font-family="sans-serif" font-size="24" font-weight="bold" lengthAdjust="spacing" textLength="0" x="1177.5" y="107.4958"/><ellipse cx="582.8289" cy="1853.1658" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="168.8289" ry="36.1658" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="247" x="459.3289" y="1859.0617">Join session as student</text><ellipse cx="582.7792" cy="1145.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="130.2792" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="158" x="503.7792" y="1151.8317">Create session</text><ellipse cx="1123.9576" cy="1410.7915" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="141.9576" ry="30.7915" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="177" x="1035.4576" y="1416.6875">Export questions</text><ellipse cx="1124.064" cy="1247.0128" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="153.064" ry="33.0128" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="207" x="1020.564" y="1252.9088">Create question tag</text><ellipse cx="1123.9627" cy="1073.0925" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="190.9627" ry="40.5925" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="300" x="973.9627" y="1078.9885">Assign moderator to session</text><ellipse cx="1124.2229" cy="1594.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="114.7229" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="136" x="1056.2229" y="1600.8317">Ask question</text><ellipse cx="1123.9109" cy="899.9822" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="150.4109" ry="32.4822" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="200" x="1023.9109" y="905.8781">Evaluate questions</text><ellipse cx="1124.066" cy="736.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="109.066" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="128" x="1060.066" y="742.8317">Edit session</text><ellipse cx="1123.9655" cy="375.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="118.9655" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="142" x="1052.9655" y="381.8317">Question wall</text><ellipse cx="1811.033" cy="165.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="56.033" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="53" x="1784.533" y="171.8317">Filter</text><ellipse cx="1811.1396" cy="487.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="66.6396" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="68" x="1777.1396" y="493.8317">Delete</text><ellipse cx="1811.0955" cy="850.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="92.0955" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="104" x="1759.0955" y="856.8317">Republish</text><ellipse cx="1811.0477" cy="326.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="47.5477" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="41" x="1790.5477" y="332.8317">Tag</text><ellipse cx="1811.229" cy="1337.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="135.229" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="165" x="1728.729" y="1343.8317">Mark as correct</text><ellipse cx="1810.865" cy="662.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="128.865" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="156" x="1732.865" y="668.8317">Mark as wrong</text><ellipse cx="1811.2168" cy="2487.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="94.2168" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="107" x="1757.7168" y="2493.8317">Bookmark</text><ellipse cx="1810.9178" cy="1066.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="74.4178" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="79" x="1771.4178" y="1072.8317">Answer</text><ellipse cx="1811.1371" cy="2319.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="116.1371" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="138" x="1742.1371" y="2325.8317">Ban question</text><ellipse cx="1811.169" cy="1718.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="49.669" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="44" x="1789.169" y="1724.8317">Star</text><ellipse cx="1123.7792" cy="1777.9357" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="130.2792" ry="30.4357" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="158" x="1044.7792" y="1783.8317">Rate questions</text><ellipse cx="1124.0389" cy="1942.9078" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="160.0389" ry="34.4078" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="225" x="1011.5389" y="1948.8038">Redeem bonus token</text><ellipse cx="583.2111" cy="2111.1422" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="181.2111" ry="38.6422" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="277" x="444.7111" y="2117.0382">Join session as moderator</text><ellipse cx="1123.9459" cy="2111.0892" fill="#98FB98" filter="url(#f167jbufqzj78x)" rx="153.4459" ry="33.0892" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="208" x="1019.9459" y="2116.9852">Moderate questions</text><!--MD5=[9642be9e27d3356614e146876c7fe741]
+entity Lecturer--><ellipse cx="290.5" cy="1103.5" fill="#FEFECE" filter="url(#f167jbufqzj78x)" rx="8" ry="8" style="stroke:#A80036;stroke-width:1.5;"/><path d="M290.5,1111.5 L290.5,1138.5 M277.5,1119.5 L303.5,1119.5 M290.5,1138.5 L277.5,1153.5 M290.5,1138.5 L303.5,1153.5 " fill="none" filter="url(#f167jbufqzj78x)" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="87" x="247" y="1186.2959">Lecturer</text><!--MD5=[494c489cc4328319247ec2e1625e02a3]
+entity Student--><ellipse cx="290.5" cy="1810.5" fill="#FEFECE" filter="url(#f167jbufqzj78x)" rx="8" ry="8" style="stroke:#A80036;stroke-width:1.5;"/><path d="M290.5,1818.5 L290.5,1845.5 M277.5,1826.5 L303.5,1826.5 M290.5,1845.5 L277.5,1860.5 M290.5,1845.5 L303.5,1860.5 " fill="none" filter="url(#f167jbufqzj78x)" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="82" x="249.5" y="1893.2959">Student</text><!--MD5=[751c087365caa72459e8e7ad1438504b]
+entity Moderator--><ellipse cx="60" cy="2068.5" fill="#FEFECE" filter="url(#f167jbufqzj78x)" rx="8" ry="8" style="stroke:#A80036;stroke-width:1.5;"/><path d="M60,2076.5 L60,2103.5 M47,2084.5 L73,2084.5 M60,2103.5 L47,2118.5 M60,2103.5 L73,2118.5 " fill="none" filter="url(#f167jbufqzj78x)" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="108" x="6" y="2151.2959">Moderator</text><path d="M1484,2627 L1484,2733.3997 L2138,2733.3997 L2138,2637 L2128,2627 L1484,2627 " fill="#FBFB77" filter="url(#f167jbufqzj78x)" style="stroke:#A80036;stroke-width:1.0;"/><path d="M2128,2627 L2128,2637 L2138,2637 L2128,2627 " fill="#FBFB77" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="556" x="1495" y="2659.2959">If a lecturer is registered and logs in with an account,</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="616" x="1495" y="2688.0958">the sessions remain stored for 180 days after the last visit,</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="465" x="1495" y="2716.8958">otherwise they are deleted when logged out.</text><path d="M1577,2833 L1577,2939.3997 L2045,2939.3997 L2045,2843 L2035,2833 L1577,2833 " fill="#FBFB77" filter="url(#f167jbufqzj78x)" style="stroke:#A80036;stroke-width:1.0;"/><path d="M2035,2833 L2035,2843 L2045,2843 L2035,2833 " fill="#FBFB77" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="307" x="1588" y="2865.2959">Students can receive a token</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="380" x="1588" y="2894.0958">for particularly interesting questions.</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="437" x="1588" y="2922.8958">The tokens can later be used as a bonus.</text><!--MD5=[57359153de7cc5a4f7a2dcc17dfc37b1]
+link Join session as student to NoteForJoinSession--><path d="M638.99,1887.05 C681.58,1916.83 737.62,1964.3 764,2022 C797.94,2096.23 738.83,2695.84 794,2756 C988.26,2967.82 1342.21,2963.99 1576.77,2932.38 " fill="none" id="Join session as student-NoteForJoinSession" style="stroke:#008000;stroke-width:2.0;"/><!--MD5=[f33f0083b43779a952bb31043b621586]
+link Create session to NoteForCreateSession--><path d="M594.21,1176.69 C623.82,1266.57 710.97,1537.31 764,1767 C781.56,1843.03 768.25,1866.33 794,1940 C836.46,2061.48 850.65,2095.11 933,2194 C1131.61,2432.49 1196.22,2506.77 1484,2623 C1487.33,2624.34 1490.69,2625.65 1494.08,2626.94 " fill="none" id="Create session-NoteForCreateSession" style="stroke:#008000;stroke-width:2.0;"/><!--MD5=[869ec2c1f0f4b3f7f156fd9f5e4df075]
+link Lecturer to Create session--><path d="M339.14,1146 C370.05,1146 411.93,1146 452.2,1146 " fill="none" id="Lecturer-Create session" style="stroke:#008000;stroke-width:2.0;"/><!--MD5=[4ad2529de28aae003702c093f8566999]
+reverse link Create session to Export questions--><path d="M632.72,1177.55 C674.62,1204.06 737.12,1242.13 794,1271 C880.91,1315.1 984.96,1357.76 1052.44,1384.17 " fill="none" id="Create session-backto-Export questions" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="628.48,1174.86,633.9399,1183.0569,632.703,1177.537,638.223,1176.3001,628.48,1174.86" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="800" y="1259.2959">«extend»</text><!--MD5=[1124252c85a8ce6300d05156e60b9541]
+reverse link Create session to Create question tag--><path d="M690.54,1165.96 C782.17,1183.13 914.06,1207.84 1008.06,1225.46 " fill="none" id="Create session-backto-Create question tag" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="685.38,1164.99,693.4808,1170.5915,690.2931,1165.9183,694.9662,1162.7306,685.38,1164.99" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="800" y="1176.2959">«extend»</text><!--MD5=[0b0e7a1c01aea1e1d139ec993a23d908]
+reverse link Create session to Assign moderator to session--><path d="M701.34,1130.1 C777.83,1119.74 878.63,1106.09 962.5,1094.73 " fill="none" id="Create session-backto-Assign moderator to session" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="696.34,1130.78,705.7965,1133.5322,701.2945,1130.107,704.7197,1125.605,696.34,1130.78" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="800" y="1091.2959">«extend»</text><!--MD5=[44237e1e472c9a5c0032c80bc2f30a4e]
+reverse link Create session to Ask question--><path d="M610.18,1180.32 C648.05,1228.94 721.56,1319.44 794,1387 C850.62,1439.8 867.9,1450.1 933,1492 C977.17,1520.42 1029.85,1548.56 1068.53,1568.23 " fill="none" id="Create session-backto-Ask question" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="607.07,1176.32,609.4452,1185.8781,610.1427,1180.2645,615.7564,1180.9619,607.07,1176.32" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="800" y="1375.2959">«extend»</text><!--MD5=[a908750067da40d8d99027ad74c6bc3f]
+reverse link Create session to Evaluate questions--><path d="M640.17,1115.6 C682.13,1093.26 741.12,1062.64 794,1038 C881.16,997.38 983.6,955.27 1050.74,928.42 " fill="none" id="Create session-backto-Evaluate questions" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="635.65,1118,645.4732,1117.2892,640.0606,1115.6448,641.7049,1110.2322,635.65,1118" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="800" y="979.2959">«extend»</text><!--MD5=[125dbe06e7289af99acfb6915be233ef]
+reverse link Create session to Edit session--><path d="M611.21,1111.6 C665.47,1045.23 793.95,898.8 933,817 C971.41,794.4 1017.39,774.86 1054.51,760.75 " fill="none" id="Create session-backto-Edit session" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="607.74,1115.86,616.5198,1111.3973,610.893,1111.9794,610.3109,1106.3526,607.74,1115.86" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="800" y="826.2959">«extend»</text><!--MD5=[7dfe2385d2633f8f8a3d5420420b59a9]
+reverse link Create session to Question wall--><path d="M601.2,1110.68 C634.75,1042.96 712.79,891.1 794,773 C894.17,627.32 1035.6,470.13 1095,405.89 " fill="none" id="Create session-backto-Question wall" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="598.86,1115.41,606.4385,1109.1199,601.0789,1110.9293,599.2694,1105.5697,598.86,1115.41" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="800" y="625.2959">«extend»</text><!--MD5=[833c4a05a00a3ffa447e96f152d14591]
+reverse link Question wall to Filter--><path d="M1183.78,346.67 C1227.46,325.72 1288.93,298 1345,279 C1491.35,229.39 1670.5,192.21 1757.54,175.59 " fill="none" id="Question wall-backto-Filter" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1179.08,348.93,1188.9244,348.6334,1183.5858,346.7626,1185.4566,341.4241,1179.08,348.93" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="237.2959">«extend»</text><!--MD5=[35ad29ab624e48f4c731265a9cca1897]
+reverse link Evaluate questions to Delete--><path d="M1230.89,874.08 C1262.09,861.6 1293.57,843.38 1315,817 C1356.22,766.25 1308.18,727.02 1345,673 C1386.59,611.98 1416.89,612.79 1484,582 C1572.47,541.4 1682.56,514.05 1749.5,499.75 " fill="none" id="Evaluate questions-backto-Delete" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1225.89,876.03,1235.7281,876.4902,1230.5489,874.215,1232.8241,869.0359,1225.89,876.03" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="585.2959">«extend»</text><!--MD5=[452a0555efe51dfd24c382d6bee38e01]
+reverse link Evaluate questions to Republish--><path d="M1234.81,875.8 C1269.85,869.09 1308.89,862.65 1345,859 C1474.54,845.9 1625.38,846.13 1719.29,848.09 " fill="none" id="Evaluate questions-backto-Republish" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1229.67,876.8,1239.2625,879.0325,1234.5804,875.8579,1237.7551,871.1758,1229.67,876.8" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="840.2959">«extend»</text><!--MD5=[29343977b60ea2dd034f269ff448c5bc]
+reverse link Evaluate questions to Tag--><path d="M1233.92,874.76 C1264.73,862.36 1295.22,844.01 1315,817 C1390.23,714.22 1287.13,645.46 1345,532 C1382.75,457.98 1410.56,445.84 1484,407 C1575.95,358.36 1698.17,338.65 1763.74,331.18 " fill="none" id="Evaluate questions-backto-Tag" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1228.98,876.7,1238.8197,877.1237,1233.6322,874.8678,1235.8881,869.6802,1228.98,876.7" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="412.2959">«extend»</text><!--MD5=[63a6b23d86ba17c281cc49f0935eb543]
+reverse link Evaluate questions to Mark as correct--><path d="M1223.56,927.25 C1255.65,939.86 1289.53,957.6 1315,982 C1337.11,1003.17 1325.47,1020.42 1345,1044 C1455.44,1177.3 1642.59,1269.22 1742.46,1311.53 " fill="none" id="Evaluate questions-backto-Mark as correct" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1218.84,925.43,1225.7927,932.4056,1223.5038,927.2326,1228.6768,924.9436,1218.84,925.43" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="1032.2959">«extend»</text><!--MD5=[97eaf76393834e8e320a1a760897c65d]
+reverse link Evaluate questions to Mark as wrong--><path d="M1210.62,870.52 C1244.61,856.84 1283.11,838.75 1315,817 C1330.58,806.37 1328.66,796.41 1345,787 C1454.48,723.88 1596.91,692.06 1695.14,676.59 " fill="none" id="Evaluate questions-backto-Mark as wrong" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1205.64,872.51,1215.4819,872.8814,1210.2824,870.653,1212.5107,865.4536,1205.64,872.51" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="726.2959">«extend»</text><!--MD5=[3c03ba6923aecc2dbfb6e4c2a6b63875]
+reverse link Evaluate questions to Bookmark--><path d="M1236.57,924.84 C1266.75,937.05 1296.23,955.17 1315,982 C1381.6,1077.21 1289.55,1401.89 1345,1504 C1373.68,1556.8 1425.87,1530.9 1454,1584 C1496.47,1664.17 1427.52,2328.99 1484,2400 C1538.83,2468.93 1641.6,2487.26 1717.14,2490.64 " fill="none" id="Evaluate questions-backto-Bookmark" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1231.72,922.93,1238.6355,929.9426,1236.3741,924.7574,1241.5593,922.496,1231.72,922.93" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="1492.2959">«extend»</text><!--MD5=[1d5b344beb6824be3b9b014107f12236]
+reverse link Evaluate questions to Answer--><path d="M1229.68,925.52 C1373.71,960.63 1628.55,1022.76 1746.65,1051.55 " fill="none" id="Evaluate questions-backto-Answer" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1224.6,924.28,1232.3946,930.3003,1229.4574,925.4658,1234.2919,922.5285,1224.6,924.28" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="943.2959">«extend»</text><!--MD5=[6e7365dc6184bc23c1299532b8869c27]
+reverse link Evaluate questions to Ban question--><path d="M1235.73,924.91 C1266.07,937.13 1295.84,955.24 1315,982 C1363.93,1050.33 1304.08,1285.59 1345,1359 C1374.26,1411.48 1424.64,1386.56 1454,1439 C1493.22,1509.04 1458.66,1722.82 1484,1799 C1552.79,2005.79 1719.33,2214.25 1783.85,2290.08 " fill="none" id="Evaluate questions-backto-Ban question" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1230.86,923,1237.7755,930.0126,1235.5141,924.8274,1240.6993,922.566,1230.86,923" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="1347.2959">«extend»</text><!--MD5=[4ab1b68341f3be81a9e6e4ac9ad3a330]
+reverse link Evaluate questions to Star--><path d="M1234.43,925.33 C1264.9,937.57 1295.07,955.59 1315,982 C1377.1,1064.28 1293.08,1122.93 1345,1212 C1375.53,1264.37 1420.7,1243.34 1454,1294 C1485.15,1341.37 1455.27,1369.11 1484,1418 C1559.82,1547 1708.27,1653.54 1775.48,1697.42 " fill="none" id="Evaluate questions-backto-Star" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1229.54,923.41,1236.4555,930.4226,1234.1941,925.2374,1239.3793,922.976,1229.54,923.41" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="1200.2959">«extend»</text><!--MD5=[5522a805a19e2ea4957daad1d6e2f58e]
+link Student to Join session as student--><path d="M336.57,1853 C358.09,1853 385.32,1853 413.76,1853 " fill="none" id="Student-Join session as student" style="stroke:#008000;stroke-width:2.0;"/><!--MD5=[7a8249f42ba6261bb0a479119a0bcc7b]
+reverse link Join session as student to Ask question--><path d="M657.62,1817.76 C766.85,1765.47 969.42,1668.51 1067.25,1621.68 " fill="none" id="Join session as student-backto-Ask question" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="652.81,1820.06,662.6551,1819.7887,657.3214,1817.9042,659.2059,1812.5705,652.81,1820.06" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="800" y="1689.2959">«extend»</text><!--MD5=[6c60ee904a7dfa8094b95003dcbf3f67]
+reverse link Join session as student to Rate questions--><path d="M742.87,1837.8 C794.08,1832.3 851.03,1825.56 903,1818 C942.66,1812.22 986.12,1804.6 1023.86,1797.56 " fill="none" id="Join session as student-backto-Rate questions" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="737.61,1838.36,746.9825,1841.386,742.582,1837.8314,746.1367,1833.4309,737.61,1838.36" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="800" y="1806.2959">«extend»</text><!--MD5=[a92cdc9a95c4d08d028b2aa7578fe7b6]
+reverse link Join session as student to Redeem bonus token--><path d="M705.63,1879.94 C734.52,1885.93 765.29,1891.99 794,1897 C856.5,1907.9 926.03,1917.93 985.01,1925.82 " fill="none" id="Join session as student-backto-Redeem bonus token" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="700.64,1878.9,708.6424,1884.6413,705.5362,1879.9135,710.264,1876.8073,700.64,1878.9" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="800" y="1885.2959">«extend»</text><!--MD5=[73a1e0b333cddd24de9e39d7c3fd3508]
+link Moderator to Join session as moderator--><path d="M119.25,2111 C187.29,2111 303.14,2111 401.9,2111 " fill="none" id="Moderator-Join session as moderator" style="stroke:#008000;stroke-width:2.0;"/><!--MD5=[216f2233c28dd9af53bddf2570c0f5d2]
+reverse link Join session as moderator to Moderate questions--><path d="M769.34,2111 C834.91,2111 907.86,2111 970.4,2111 " fill="none" id="Join session as moderator-backto-Moderate questions" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="764.23,2111,773.23,2115,769.23,2111,773.23,2107,764.23,2111" style="stroke:#008000;stroke-width:2.0;"/><!--MD5=[596368ba3f9b5cfa7f2506d9fd6c1d65]
+reverse link Moderate questions to Ban question--><path d="M1143.18,2148.49 C1174.66,2208.49 1245.59,2324 1345,2370 C1478.93,2431.96 1657.07,2380.74 1749.14,2345.81 " fill="none" id="Moderate questions-backto-Ban question" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1140.8,2143.92,1141.3983,2153.7507,1143.1045,2148.3573,1148.4979,2150.0635,1140.8,2143.92" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="2358.2959">«extend»</text><!--MD5=[58509d3cd86d9229d66ace7253e950d0]
+reverse link Moderate questions to Mark as correct--><path d="M1241.34,2134.1 C1312.69,2140.98 1400.34,2135.08 1454,2080 C1522.7,2009.48 1441.41,1726.76 1484,1638 C1544.89,1511.09 1685.31,1412.32 1760.45,1366.31 " fill="none" id="Moderate questions-backto-Mark as correct" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1236.23,2133.58,1244.7859,2138.4581,1241.205,2134.0789,1245.5842,2130.498,1236.23,2133.58" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="2068.2959">«extend»</text><!--MD5=[f300e0b511c5aabb8568aefce0a13f04]
+reverse link Moderate questions to Mark as wrong--><path d="M1234.49,2085.04 C1265.15,2072.48 1295.4,2054.02 1315,2027 C1393.15,1919.23 1280.33,1845.35 1345,1729 C1374.71,1675.54 1426.07,1699.41 1454,1645 C1498.42,1558.45 1425.6,847.79 1484,770 C1530.67,707.83 1614.47,681.24 1685.42,670.11 " fill="none" id="Moderate questions-backto-Mark as wrong" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1229.57,2087.01,1239.4108,2087.4075,1234.2173,2085.1654,1236.4594,2079.9718,1229.57,2087.01" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="1633.2959">«extend»</text><!--MD5=[679d69c509a4b70cc0eea01a520dd089]
+reverse link Moderate questions to Answer--><path d="M1204.24,2080.16 C1292.72,2043.88 1427.07,1982.55 1454,1935 C1528.3,1803.76 1405.99,1386.07 1484,1257 C1542.62,1160.01 1670.89,1107.33 1747.9,1083.38 " fill="none" id="Moderate questions-backto-Answer" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1199.54,2082.08,1209.384,2082.3887,1204.1705,2080.1935,1206.3656,2074.98,1199.54,2082.08" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="1923.2959">«extend»</text><!--MD5=[23e52ed03cc32ef66e605affcd82554c]
+reverse link Moderate questions to Star--><path d="M1166.58,2146.37 C1230.58,2196.25 1356.09,2275.82 1454,2225 C1656.34,2119.95 1767.88,1841.26 1800.09,1749.08 " fill="none" id="Moderate questions-backto-Star" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1162.46,2143.13,1167.067,2151.8349,1166.3921,2146.2185,1172.0085,2145.5436,1162.46,2143.13" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="2213.2959">«extend»</text><!--MD5=[e5b3ae8615b23ce7d58853667e9a823a]
+reverse link Moderate questions to Bookmark--><path d="M1135.83,2149.02 C1159.53,2224.37 1223.83,2391.52 1345,2463 C1464.94,2533.75 1634,2520.61 1731.77,2504.44 " fill="none" id="Moderate questions-backto-Bookmark" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1134.32,2144.19,1133.2032,2153.9753,1135.8195,2148.9599,1140.835,2151.5761,1134.32,2144.19" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="2451.2959">«extend»</text><!--MD5=[4d8cfbab1f8b0019c7892bc1ed6236a3]
+reverse link Moderate questions to Republish--><path d="M1231.57,2084.46 C1262.62,2071.83 1293.85,2053.48 1315,2027 C1358.25,1972.86 1308.55,1932.93 1345,1874 C1377.17,1821.98 1425.99,1844.36 1454,1790 C1494.94,1710.53 1432.95,1059.38 1484,986 C1538.39,907.8 1646.99,874.79 1723.87,860.92 " fill="none" id="Moderate questions-backto-Republish" style="stroke:#008000;stroke-width:2.0;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1226.59,2086.44,1236.4308,2086.8375,1231.2373,2084.5954,1233.4794,2079.4018,1226.59,2086.44" style="stroke:#008000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="97" x="1351" y="1778.2959">«extend»</text><rect fill="#F8E7C0" height="491.9998" rx="5" ry="5" style="stroke:#F8E7C0;stroke-width:0.0;" width="686" x="1437" y="2981.82"/><image height="128" width="128" x="1453" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAADcklEQVR4Xu2c0W3iUBREqQjqSDXbRYpKJ/neMvYju08ECY3J4js2cGfeHOkoH9G7RvIBG2M4HEIIIYQQQgghhJ95e3v7/e/PV3ytx+Px1+GZnE6nP4cbDyS+1meFsNhwbOfDwA3Fvu4ObiA29vswvRuLDUQJdwMHRx03gwOjlpvBgVHIPc4FFkOjnBzfFxZwWNSTIwHYyJEAbORIADZyJAAbORKAjRyzBDDeK1+L/zeQwzGA9/f3ryqfn5+XCyqLeSJyuAQwdh7uVJaPj4/FfAE5HAJ4FOOVBLfVWA7lAMb9irjTHgFut6kcqgEwx/kt4PYbyqEYwLOe+deMk0R8HM3kUAzgVeDjaCaHWgCvBh9PIzkSQA18PI3kUAqABedcHO/3GXBOEzmcA1h74lYF1zeRQyUA5kofzvjJ6isBrm8ih0oAj95JFZp+YZZDJYAquP6eFZp+VsCRAOrz155bPFkOlQDGs64irr9nhQRgaIWmnxJyJICzFZreOMKRAM5WwLVN5EgAtZ0/wPVN5Jg9gOoFpqbH/yHH7AFUwfWN5Jg5gCpNrwBe5Jg1AAac0UyOGQNgwBkN5ZgpAPZGUpzTVI5ZAmB3ftOLPrfkmCGA6lu9C81P+lCOGQJgEHrmX+RwD4B56ccZInK4B1AF1wvJ4RxA9dmP68XkcA6ggtgJ3y05EsAZXCsoRwKw2PlDDtcAKsd/XCsqh2sA48bNNTA3kDaVwzWAteA6YTkSwHKtqBwJYLlWVA7XACaUIwHYyJEAbORIADZyJAAbORKAjRwzBIAYXf27lsM5gHs0/poXI4drAGsxioBj9gAGuFZUDscAqpi8CnAkgDM4Q1COBHAGZwjKkQDa/upXVQ7HACq3gw1wvagcjgEMK+BaUTlcAxiuAdcIy+EcwPDWN4NNjvkoh3sAE8mRAGzkSAA2ciQAGzkSgI0cCcBGjgRg4yZwWNRzEzgs6rkJHBb15Ml5gIWbwYFRy13AoVHH7Rj8VNrM7goOj/3dF8EfS57dx5DDgoxBBNxxexmEwJ23h0EM3IFbDYLgTtxiUGPnS/BBkR0jCKrsFEFQZocIgjobIwgObIgguEBGEJwgIghuFD+IC44UIgiurIwgOLMiguDOnQjCDPwngjALP9yvGWbiRgRhNiCCMCNXEYRZ+Y4ghBBCCCGEEG7wF4/x8PpTsJefAAAAAElFTkSuQmCC" y="2998.82"/><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="0" x="1587" y="3121.4"/><text fill="#000000" font-family="sans-serif" font-size="20" font-weight="bold" lengthAdjust="spacing" textLength="0" x="1660" y="3017.4"/><text fill="#000000" font-family="sans-serif" font-size="20" font-weight="bold" lengthAdjust="spacing" textLength="0" x="1660" y="3041.4"/><text fill="#000000" font-family="sans-serif" font-size="20" font-weight="bold" lengthAdjust="spacing" textLength="107" x="1660" y="3065.3999">»frag.jetzt«</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="95" x="1459" y="3155.4">Produktion</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="0" x="1660" y="3155.4"/><a href="https://frag.jetzt" target="_top" title="https://frag.jetzt" xlink:actuate="onRequest" xlink:href="https://frag.jetzt" xlink:show="new" xlink:title="https://frag.jetzt" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="20" lengthAdjust="spacing" text-decoration="underline" textLength="140" x="1660" y="3155.4">https://frag.jetzt</text></a><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="0" x="1806" y="3155.4"/><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="95" x="1459" y="3189.4">Repository</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="0" x="1660" y="3189.4"/><a href="https://git.thm.de/arsnova/frag.jetzt" target="_top" title="https://git.thm.de/arsnova/frag.jetzt" xlink:actuate="onRequest" xlink:href="https://git.thm.de/arsnova/frag.jetzt" xlink:show="new" xlink:title="https://git.thm.de/arsnova/frag.jetzt" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="20" lengthAdjust="spacing" text-decoration="underline" textLength="312" x="1660" y="3189.4">https://git.thm.de/arsnova/frag.jetzt</text></a><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="0" x="1978" y="3189.4"/><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="132" x="1459" y="3223.3999">Staging Server</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="0" x="1660" y="3223.3999"/><a href="https://staging.frag.jetzt" target="_top" title="https://staging.frag.jetzt" xlink:actuate="onRequest" xlink:href="https://staging.frag.jetzt" xlink:show="new" xlink:title="https://staging.frag.jetzt" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="20" lengthAdjust="spacing" text-decoration="underline" textLength="210" x="1660" y="3223.3999">https://staging.frag.jetzt</text></a><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="0" x="1876" y="3223.3999"/><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="87" x="1459" y="3257.3999">UML-Tool</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="181" x="1660" y="3257.3999">PlantUML v1.2021.5</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="73" x="1459" y="3291.3999">Ersteller</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="201" x="1660" y="3291.3999">Klaus Quibeldey-Cirkel</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="36" x="1459" y="3325.3999">Mail</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="309" x="1660" y="3325.3999">klaus.quibeldey-cirkel@mni.thm.de</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="178" x="1459" y="3359.3998">Vorherige Änderung</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="100" x="1660" y="3359.3998">26.08.2019</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="147" x="1459" y="3393.3998">Letzte Änderung</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="100" x="1660" y="3393.3998">26.04.2021</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="185" x="1459" y="3427.3998">Letzte Änderung von</text><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="159" x="1660" y="3427.3998">Jens Plüddemann</text><a href=" mailto:jens.plueddemann@mni.thm.de" target="_top" title="" xlink:actuate="onRequest" xlink:href=" mailto:jens.plueddemann@mni.thm.de" xlink:show="new" xlink:title="" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="20" lengthAdjust="spacing" text-decoration="underline" textLength="282" x="1825" y="3427.3998">jens.plueddemann@mni.thm.de</text></a><text fill="#000000" font-family="sans-serif" font-size="20" lengthAdjust="spacing" textLength="121" x="1660" y="3451.3998">Julian Clamer</text><a href=" mailto:julian.clamer@mni.thm.de" target="_top" title="" xlink:actuate="onRequest" xlink:href=" mailto:julian.clamer@mni.thm.de" xlink:show="new" xlink:title="" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="20" lengthAdjust="spacing" text-decoration="underline" textLength="231" x="1787" y="3451.3998">julian.clamer@mni.thm.de</text></a><line style="stroke:#000000;stroke-width:1.0;" x1="1448" x2="2112" y1="2993.82" y2="2993.82"/><line style="stroke:#000000;stroke-width:1.0;" x1="1448" x2="2112" y1="3131.82" y2="3131.82"/><line style="stroke:#000000;stroke-width:1.0;" x1="1448" x2="2112" y1="3165.82" y2="3165.82"/><line style="stroke:#000000;stroke-width:1.0;" x1="1448" x2="2112" y1="3199.82" y2="3199.82"/><line style="stroke:#000000;stroke-width:1.0;" x1="1448" x2="2112" y1="3233.8199" y2="3233.8199"/><line style="stroke:#000000;stroke-width:1.0;" x1="1448" x2="2112" y1="3267.8199" y2="3267.8199"/><line style="stroke:#000000;stroke-width:1.0;" x1="1448" x2="2112" y1="3301.8199" y2="3301.8199"/><line style="stroke:#000000;stroke-width:1.0;" x1="1448" x2="2112" y1="3335.8199" y2="3335.8199"/><line style="stroke:#000000;stroke-width:1.0;" x1="1448" x2="2112" y1="3369.8198" y2="3369.8198"/><line style="stroke:#000000;stroke-width:1.0;" x1="1448" x2="2112" y1="3403.8198" y2="3403.8198"/><line style="stroke:#000000;stroke-width:1.0;" x1="1448" x2="2112" y1="3461.8198" y2="3461.8198"/><line style="stroke:#000000;stroke-width:1.0;" x1="1448" x2="1448" y1="2993.82" y2="3461.8198"/><line style="stroke:#000000;stroke-width:1.0;" x1="1649" x2="1649" y1="2993.82" y2="3461.8198"/><line style="stroke:#000000;stroke-width:1.0;" x1="2112" x2="2112" y1="2993.82" y2="3461.8198"/><!--MD5=[c33d80f162936129db86e6cd77407a5c]
+@startuml Business Use-Case Diagram
+
+scale 1.0
+
+left to right direction
+
+skinparam backgroundColor Linen
+skinparam LegendBackgroundColor Strategy
+skinparam LegendBorderThickness 0
+skinparam LegendFontSize 20
+skinparam Padding 5
+skinparam defaultFontSize 24
+skinparam Nodesep 100
+skinparam ArrowThickness 2
+skinparam shadowing true
+
+skinparam usecase {
+    BackgroundColor PaleGreen
+    BorderColor Green
+    BackgroundColor<<USP>> Pink
+    BorderColor<<USP>> HotPink
+    BorderThickness 2
+    ArrowThickness 2
+    ArrowColor Green
+    ActorBorderColor Green
+}
+
+actor Lecturer
+actor Student
+actor Moderator
+
+note "If a lecturer is registered and logs in with an account, \nthe sessions remain stored for 180 days after the last visit, \notherwise they are deleted when logged out." as NoteForCreateSession
+note "Students can receive a token \nfor particularly interesting questions. \nThe tokens can later be used as a bonus." as NoteForJoinSession
+
+rectangle "frag.jetzt | use-case diagram \n" << Business >> {
+
+    (Join session as student) - - - NoteForJoinSession
+    (Create session) - - - NoteForCreateSession
+
+    Lecturer - - (Create session)
+    (Create session) <.. (Export questions) : << extend >>
+    (Create session) <.. (Create question tag) : << extend >>
+    (Create session) <.. (Assign moderator to session) : << extend >>
+    (Create session) <.. (Ask question) : << extend >>
+    (Create session) <.. (Evaluate questions) : << extend >>
+    (Create session) <.. (Edit session) : << extend >>
+    (Create session) <.. (Question wall) : << extend >>
+    (Question wall) <.. (Filter) : << extend >>
+    (Evaluate questions) <.. (Delete) : << extend >>
+    (Evaluate questions) <.. (Republish) : << extend >>
+    (Evaluate questions) <.. (Tag) : << extend >>
+    (Evaluate questions) <.. (Mark as correct) : << extend >>
+    (Evaluate questions) <.. (Mark as wrong) : << extend >>
+    (Evaluate questions) <.. (Bookmark) : << extend >>
+    (Evaluate questions) <.. (Answer) : << extend >>
+    (Evaluate questions) <.. (Ban question) : << extend >>
+    (Evaluate questions) <.. (Star) : << extend >>
+
+    Student- - (Join session as student)
+    (Join session as student) <.. (Ask question) : << extend >>
+    (Join session as student) <.. (Rate questions) : << extend >>
+    (Join session as student) <.. (Redeem bonus token) : << extend >>
+        
+    Moderator - - - - (Join session as moderator)
+    (Join session as moderator) <.. (Moderate questions)
+    (Moderate questions) <.. (Ban question) : << extend >>
+    (Moderate questions) <.. (Mark as correct) : << extend >>
+    (Moderate questions) <.. (Mark as wrong) : << extend >>
+    (Moderate questions) <.. (Answer) : << extend >>
+    (Moderate questions) <.. (Star) : << extend >>
+    (Moderate questions) <.. (Bookmark) : << extend >>
+    (Moderate questions) <.. (Republish) : << extend >>
+    ' (Join session as moderator) <.. (Award bonus for token) out of scope or not?
+}
+
+legend right
+  |<img:https://git.thm.de/arsnova/arsnova-lite/raw/staging/src/assets/icons/Logo_frag_jetzt_128x128.png> |= \n\n »frag.jetzt« |
+  | Produktion | [[https://frag.jetzt]] |
+  | Repository | [[https://git.thm.de/arsnova/frag.jetzt]] |
+  | Staging Server | [[https://staging.frag.jetzt]] |
+  | UML-Tool| PlantUML v1.2021.5|
+  | Ersteller| Klaus Quibeldey-Cirkel|
+  | Mail| klaus.quibeldey-cirkel@mni.thm.de |
+  | Vorherige Änderung | 26.08.2019 |
+  | Letzte Änderung| 26.04.2021 |
+  | Letzte Änderung von| Jens Plüddemann [[ mailto:jens.plueddemann@mni.thm.de{} jens.plueddemann@mni.thm.de]]\n Julian Clamer [[ mailto:julian.clamer@mni.thm.de{} julian.clamer@mni.thm.de]]|
+end legend
+
+@enduml
+
+@startuml Business Use-Case Diagram
+
+scale 1.0
+
+left to right direction
+
+skinparam backgroundColor Linen
+skinparam LegendBackgroundColor Strategy
+skinparam LegendBorderThickness 0
+skinparam LegendFontSize 20
+skinparam Padding 5
+skinparam defaultFontSize 24
+skinparam Nodesep 100
+skinparam ArrowThickness 2
+skinparam shadowing true
+
+skinparam usecase {
+    BackgroundColor PaleGreen
+    BorderColor Green
+    BackgroundColor<<USP>> Pink
+    BorderColor<<USP>> HotPink
+    BorderThickness 2
+    ArrowThickness 2
+    ArrowColor Green
+    ActorBorderColor Green
+}
+
+actor Lecturer
+actor Student
+actor Moderator
+
+note "If a lecturer is registered and logs in with an account, \nthe sessions remain stored for 180 days after the last visit, \notherwise they are deleted when logged out." as NoteForCreateSession
+note "Students can receive a token \nfor particularly interesting questions. \nThe tokens can later be used as a bonus." as NoteForJoinSession
+
+rectangle "frag.jetzt | use-case diagram \n" << Business >> {
+
+    (Join session as student) - - - NoteForJoinSession
+    (Create session) - - - NoteForCreateSession
+
+    Lecturer - - (Create session)
+    (Create session) <.. (Export questions) : << extend >>
+    (Create session) <.. (Create question tag) : << extend >>
+    (Create session) <.. (Assign moderator to session) : << extend >>
+    (Create session) <.. (Ask question) : << extend >>
+    (Create session) <.. (Evaluate questions) : << extend >>
+    (Create session) <.. (Edit session) : << extend >>
+    (Create session) <.. (Question wall) : << extend >>
+    (Question wall) <.. (Filter) : << extend >>
+    (Evaluate questions) <.. (Delete) : << extend >>
+    (Evaluate questions) <.. (Republish) : << extend >>
+    (Evaluate questions) <.. (Tag) : << extend >>
+    (Evaluate questions) <.. (Mark as correct) : << extend >>
+    (Evaluate questions) <.. (Mark as wrong) : << extend >>
+    (Evaluate questions) <.. (Bookmark) : << extend >>
+    (Evaluate questions) <.. (Answer) : << extend >>
+    (Evaluate questions) <.. (Ban question) : << extend >>
+    (Evaluate questions) <.. (Star) : << extend >>
+
+    Student- - (Join session as student)
+    (Join session as student) <.. (Ask question) : << extend >>
+    (Join session as student) <.. (Rate questions) : << extend >>
+    (Join session as student) <.. (Redeem bonus token) : << extend >>
+        
+    Moderator - - - - (Join session as moderator)
+    (Join session as moderator) <.. (Moderate questions)
+    (Moderate questions) <.. (Ban question) : << extend >>
+    (Moderate questions) <.. (Mark as correct) : << extend >>
+    (Moderate questions) <.. (Mark as wrong) : << extend >>
+    (Moderate questions) <.. (Answer) : << extend >>
+    (Moderate questions) <.. (Star) : << extend >>
+    (Moderate questions) <.. (Bookmark) : << extend >>
+    (Moderate questions) <.. (Republish) : << extend >>
+}
+
+legend right
+  |<img:https://git.thm.de/arsnova/arsnova-lite/raw/staging/src/assets/icons/Logo_frag_jetzt_128x128.png> |= \n\n »frag.jetzt« |
+  | Produktion | [[https://frag.jetzt]] |
+  | Repository | [[https://git.thm.de/arsnova/frag.jetzt]] |
+  | Staging Server | [[https://staging.frag.jetzt]] |
+  | UML-Tool| PlantUML v1.2021.5|
+  | Ersteller| Klaus Quibeldey-Cirkel|
+  | Mail| klaus.quibeldey-cirkel@mni.thm.de |
+  | Vorherige Änderung | 26.08.2019 |
+  | Letzte Änderung| 26.04.2021 |
+  | Letzte Änderung von| Jens Plüddemann [[ mailto:jens.plueddemann@mni.thm.de{} jens.plueddemann@mni.thm.de]]\n Julian Clamer [[ mailto:julian.clamer@mni.thm.de{} julian.clamer@mni.thm.de]]|
+end legend
+
+@enduml
+
+PlantUML version 1.2021.00(Sun Jan 10 11:25:05 CET 2021)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg>
\ No newline at end of file
diff --git a/docs/diagrams/UX-Diagrams/.gitkeep b/docs/diagrams/UX-Diagrams/.gitkeep
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/docs/diagrams/UX-Diagrams/Activitydiagram_-_Question_to_keywords.puml b/docs/diagrams/UX-Diagrams/Activitydiagram_-_Question_to_keywords.puml
new file mode 100644
index 0000000000000000000000000000000000000000..111ac562f5acba1667e96093772e3ef700253926
--- /dev/null
+++ b/docs/diagrams/UX-Diagrams/Activitydiagram_-_Question_to_keywords.puml
@@ -0,0 +1,127 @@
+@startuml
+'https://plantuml.com/activity-diagram-beta
+
+start
+partition "Comment List"
+    :create\nquestion;
+    partition "Create question dialog"
+        :Input;
+        repeat
+            switch (options)
+                case ()
+                    :   select\nlanguage;
+                case ()
+                    :select\n  tag;
+                case ()
+                    switch (suggestions\n    active?)
+                        case( no)
+                            :spellcheck;
+                            switch ()
+                                case ()
+                                    :     use\nsuggestion;
+                                case ()
+                            endswitch
+                        case ( yes)
+                          :     use\nsuggestion;
+                    endswitch
+                case ()
+                    switch ()
+                        case ()
+                            :cancel;
+                        case ()
+                            :    click\noutside of\n  window;
+                    endswitch
+                    stop
+                case (\n\n\n\n\n\n if\n preview\n selected)
+                    :input;
+                case ( if text\n added\n and\n input view\n selected)
+                    :preview;
+                case ()
+                    switch (empty\ntext\nfield?)
+                        case ( yes)
+                            :add\ntext;
+
+                        case ( no)
+                            switch ()
+                                case ()
+                                    :add\ntext;
+                                case ()
+                                    :edit\ntext;
+                                case ()
+                            endswitch
+                    endswitch
+                case ()
+            endswitch
+        repeat while (continue\n editing)
+
+        :send;
+        note left
+        only if text is added
+        end note
+        partition "SpaCy dialog" {
+            if(    supported\n     language\ndetected or set) then (yes)
+                if (nouns included?) then (yes)
+                    repeat
+                        switch(options)
+                            case ()
+                                :select\deselect\na keyword;
+                            case ()
+                                :select\deselect\n all keywords;
+                            case ()
+                                :     edit\n a keyword;
+                                :save;
+                            case ()
+                        endswitch
+                    repeat while (continue\n setting)
+                else (no)
+                endif
+            else (no)
+                if(add keyword manually?)
+                    repeat
+                        :add keyword;
+                        switch (options)
+                            case ()
+                                :select\deselect\na keyword;
+                            case ()
+                                :select\deselect\n all keywords;
+                            case ()
+                                :      edit\n a keyword;
+                                :save;
+                            case()
+                        endswitch
+                    repeat while (continue\n setting)
+                else
+                endif
+            endif
+            if(options)
+                :   send\n(publish\nquestion);
+            else
+                :cancel;
+            endif
+            stop
+        }
+    }
+}
+
+legend right
+  |<img:https://git.thm.de/arsnova/arsnova-lite/raw/staging/src/assets/icons/Logo_frag_jetzt_128x128.png> |= \n\n »frag.jetzt« |
+  | Produktion | [[https://frag.jetzt]] |
+  | Repository | [[https://git.thm.de/arsnova/frag.jetzt]] |
+  | Staging Server | [[https://staging.frag.jetzt]] |
+  | UML-Tool| PlantUML v5.5.1|
+  | Ersteller| Lujain Abou Assali, Dario Gloc|
+  | Letzte Änderung| 20.06.2021 |
+end legend
+/'
+legend right
+ |= \n          <img:https://git.thm.de/arsnova/frag.jetzt/-/raw/staging/src/assets/icons/favicon-32x32.png> |= \n [[https://git.thm.de/arsnova/frag.jetzt frag.jetzt]] \n\n Technische Hochschule Mittelhessen |
+ | Repository | [[https://git.thm.de/arsnova/frag.jetzt]] |
+ | Staging Server | [[https://staging.frag.jetzt]] |
+ | UML-Tool| PlantUML v5.5.1|
+ | Modellversion| 1.0|
+ | Erstelldatum| 17.06.2021|
+ | Ersteller| Lujain Abou Assali, Dario Gloc|
+ | Letzte Änderung| 17.06.2021|
+end legend
+'/
+@enduml
diff --git a/docs/diagrams/UX-Diagrams/Activitydiagram_-_Question_to_keywords.svg b/docs/diagrams/UX-Diagrams/Activitydiagram_-_Question_to_keywords.svg
new file mode 100644
index 0000000000000000000000000000000000000000..18e62a448da2eb315301bbbbb97a4d3aef646b0c
--- /dev/null
+++ b/docs/diagrams/UX-Diagrams/Activitydiagram_-_Question_to_keywords.svg
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="2092px" preserveAspectRatio="none" style="width:1078px;height:2092px;background:#FFFFFF;" version="1.1" viewBox="0 0 1078 2092" width="1078px" zoomAndPan="magnify"><defs><filter height="300%" id="fuc3n4o2gfifh" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><ellipse cx="552" cy="20" fill="#000000" filter="url(#fuc3n4o2gfifh)" rx="10" ry="10" style="stroke:none;stroke-width:1.0;"/><rect fill="#FFFFFF" filter="url(#fuc3n4o2gfifh)" height="1779.1797" style="stroke:#000000;stroke-width:2.0;" width="1050" x="11" y="40"/><path d="M119,40 L119,49.2969 L109,59.2969 L11,59.2969 " fill="none" style="stroke:#000000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="98" x="14" y="53.9951">Comment List</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="72" x="516" y="76.2969"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="38" x="526" y="97.4355">create</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="52" x="526" y="111.4043">question</text><rect fill="#FFFFFF" filter="url(#fuc3n4o2gfifh)" height="1672.9453" style="stroke:#000000;stroke-width:2.0;" width="1030" x="21" y="134.2344"/><path d="M192,134.2344 L192,143.5313 L182,153.5313 L21,153.5313 " fill="none" style="stroke:#000000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="161" x="24" y="148.2295">Create question dialog</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="33.9688" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="53" x="525.5" y="170.5313"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="33" x="535.5" y="191.6699">Input</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="531.5,268.5,572.5,268.5,584.5,280.5,572.5,292.5,531.5,292.5,519.5,280.5,531.5,268.5" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="41" x="531.5" y="284.3081">options</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="76" x="31" y="417.7422"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="35" x="53" y="438.8809">select</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="56" x="41" y="452.8496">language</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="55" x="127" y="417.7422"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="35" x="137" y="438.8809">select</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="20" x="145" y="452.8496">tag</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="289.5,417.7422,356.5,417.7422,368.5,430.5469,356.5,443.3516,289.5,443.3516,277.5,430.5469,289.5,417.7422" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="67" x="289.5" y="427.9526">suggestions</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="40" x="305.5" y="440.7573">active?</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="33.9688" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="83" x="228.5" y="466.1563"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="63" x="238.5" y="487.2949">spellcheck</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="270,535.125,270,535.125,282,547.125,270,559.125,270,559.125,258,547.125,270,535.125" style="stroke:#A80036;stroke-width:1.5;"/><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="86" x="202" y="579.125"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="21" x="232" y="600.2637">use</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="66" x="212" y="614.2324">suggestion</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="270,722.9336,270,722.9336,282,734.9336,270,746.9336,270,746.9336,258,734.9336,270,722.9336" style="stroke:#A80036;stroke-width:1.5;"/><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="86" x="358" y="466.1563"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="21" x="388" y="487.2949">use</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="66" x="368" y="501.2637">suggestion</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="323,790.9336,323,790.9336,335,802.9336,323,814.9336,323,814.9336,311,802.9336,323,790.9336" style="stroke:#A80036;stroke-width:1.5;"/><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="543,417.7422,543,417.7422,555,429.7422,543,441.7422,543,441.7422,531,429.7422,543,417.7422" style="stroke:#A80036;stroke-width:1.5;"/><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="33.9688" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="59" x="464" y="461.7422"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="39" x="474" y="482.8809">cancel</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="61.9063" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="79" x="543" y="461.7422"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="27" x="569" y="482.8809">click</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="59" x="553" y="496.8496">outside of</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="46" x="561" y="510.8184">window</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="543,633.6484,543,633.6484,555,645.6484,543,657.6484,543,657.6484,531,645.6484,543,633.6484" style="stroke:#A80036;stroke-width:1.5;"/><ellipse cx="543" cy="701.9336" fill="#FFFFFF" filter="url(#fuc3n4o2gfifh)" rx="11" ry="11" style="stroke:#000000;stroke-width:1.0;"/><ellipse cx="543" cy="701.9336" fill="#000000" rx="6" ry="6" style="stroke:#7F7F7F;stroke-width:1.0;"/><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="33.9688" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="52" x="642" y="417.7422"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="32" x="652" y="438.8809">input</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="33.9688" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="67" x="714" y="417.7422"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="47" x="724" y="438.8809">preview</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="894,417.7422,930,417.7422,942,436.9492,930,456.1563,894,456.1563,882,436.9492,894,417.7422" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="36" x="894" y="427.9526">empty</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="22" x="894" y="440.7573">text</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="30" x="894" y="453.562">field?</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="44" x="801" y="478.9609"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="23" x="811" y="500.0996">add</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="24" x="811" y="514.0684">text</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="944,478.9609,944,478.9609,956,490.9609,944,502.9609,944,502.9609,932,490.9609,944,478.9609" style="stroke:#A80036;stroke-width:1.5;"/><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="44" x="865" y="522.9609"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="23" x="875" y="544.0996">add</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="24" x="875" y="558.0684">text</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="44" x="929" y="522.9609"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="23" x="939" y="544.0996">edit</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="24" x="939" y="558.0684">text</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="944,679.1836,944,679.1836,956,691.1836,944,703.1836,944,703.1836,932,691.1836,944,679.1836" style="stroke:#A80036;stroke-width:1.5;"/><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="912,756.9336,912,756.9336,924,768.9336,912,780.9336,912,780.9336,900,768.9336,912,756.9336" style="stroke:#A80036;stroke-width:1.5;"/><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="552,824.9336,552,824.9336,564,836.9336,552,848.9336,552,848.9336,540,836.9336,552,824.9336" style="stroke:#A80036;stroke-width:1.5;"/><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="552,224.5,564,236.5,552,248.5,540,236.5,552,224.5" style="stroke:#A80036;stroke-width:1.5;"/><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="528,868.9336,576,868.9336,588,881.7383,576,894.543,528,894.543,516,881.7383,528,868.9336" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="48" x="528" y="879.144">continue</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="38" x="532" y="891.9487">editing</text><path d="M356.5,918.9609 L356.5,944.0938 A0,0 0 0 0 356.5,944.0938 L507.5,944.0938 A0,0 0 0 0 507.5,944.0938 L507.5,936.9609 L527.5,931.5273 L507.5,928.9609 L507.5,928.9609 L497.5,918.9609 L356.5,918.9609 A0,0 0 0 0 356.5,918.9609 " fill="#FBFB77" filter="url(#fuc3n4o2gfifh)" style="stroke:#A80036;stroke-width:1.0;"/><path d="M497.5,918.9609 L497.5,928.9609 L507.5,928.9609 L497.5,918.9609 " fill="#FBFB77" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="130" x="362.5" y="936.0278">only if text is added</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="33.9688" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="49" x="527.5" y="914.543"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="29" x="537.5" y="935.6816">send</text><rect fill="#FFFFFF" filter="url(#fuc3n4o2gfifh)" height="836.668" style="stroke:#000000;stroke-width:2.0;" width="931" x="90" y="958.5117"/><path d="M193,958.5117 L193,967.8086 L183,977.8086 L90,977.8086 " fill="none" style="stroke:#000000;stroke-width:2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="93" x="93" y="972.5068">SpaCy dialog</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="509,994.8086,595,994.8086,607,1014.0156,595,1033.2227,509,1033.2227,497,1014.0156,509,994.8086" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="57" x="525" y="1005.019">supported</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="52" x="529" y="1017.8237">language</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="86" x="509" y="1030.6284">detected or set</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="20" x="477" y="1011.4214">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="14" x="607" y="1011.4214">no</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="296.5,1136.0273,337.5,1136.0273,349.5,1148.0273,337.5,1160.0273,296.5,1160.0273,284.5,1148.0273,296.5,1136.0273" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="41" x="296.5" y="1151.8354">options</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="109" x="120" y="1180.0273"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="89" x="130" y="1201.166">select\deselect</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="62" x="130" y="1215.1348">a keyword</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="109" x="249" y="1180.0273"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="89" x="259" y="1201.166">select\deselect</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="74" x="263" y="1215.1348">all keywords</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="86" x="378" y="1180.0273"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="23" x="408" y="1201.166">edit</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="62" x="392" y="1215.1348">a keyword</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="33.9688" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="47" x="397.5" y="1262.9648"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="27" x="407.5" y="1284.1035">save</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="317,1384.0664,317,1384.0664,329,1396.0664,317,1408.0664,317,1408.0664,305,1396.0664,317,1384.0664" style="stroke:#A80036;stroke-width:1.5;"/><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="317,1091.625,329,1103.625,317,1115.625,305,1103.625,317,1091.625" style="stroke:#A80036;stroke-width:1.5;"/><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="293,1431.5,341,1431.5,353,1444.3047,341,1457.1094,293,1457.1094,281,1444.3047,293,1431.5" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="48" x="293" y="1441.7104">continue</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="38" x="297" y="1454.5151">setting</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="271.5,1043.2227,362.5,1043.2227,374.5,1055.2227,362.5,1067.2227,271.5,1067.2227,259.5,1055.2227,271.5,1043.2227" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="20" x="321" y="1077.4331">yes</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="91" x="271.5" y="1059.0308">nouns included?</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="14" x="374.5" y="1052.6284">no</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="317,1477.1094,329,1489.1094,317,1501.1094,305,1489.1094,317,1477.1094" style="stroke:#A80036;stroke-width:1.5;"/><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="33.9688" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="98" x="738" y="1135.625"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="78" x="748" y="1156.7637">add keyword</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="766.5,1204.5938,807.5,1204.5938,819.5,1216.5938,807.5,1228.5938,766.5,1228.5938,754.5,1216.5938,766.5,1204.5938" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="41" x="766.5" y="1220.4019">options</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="109" x="590" y="1248.5938"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="89" x="600" y="1269.7324">select\deselect</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="62" x="600" y="1283.7012">a keyword</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="109" x="719" y="1248.5938"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="89" x="729" y="1269.7324">select\deselect</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="74" x="733" y="1283.7012">all keywords</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="47.9375" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="86" x="848" y="1248.5938"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="23" x="882" y="1269.7324">edit</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="62" x="862" y="1283.7012">a keyword</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="33.9688" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="47" x="867.5" y="1330.0977"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="27" x="877.5" y="1351.2363">save</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="787,1428.0664,787,1428.0664,799,1440.0664,787,1452.0664,787,1452.0664,775,1440.0664,787,1428.0664" style="stroke:#A80036;stroke-width:1.5;"/><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="787,1091.2227,799,1103.2227,787,1115.2227,775,1103.2227,787,1091.2227" style="stroke:#A80036;stroke-width:1.5;"/><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="763,1495.6641,811,1495.6641,823,1508.4688,811,1521.2734,763,1521.2734,751,1508.4688,763,1495.6641" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="48" x="763" y="1505.8745">continue</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="38" x="767" y="1518.6792">setting</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="719.5,1043.2227,854.5,1043.2227,866.5,1055.2227,854.5,1067.2227,719.5,1067.2227,707.5,1055.2227,719.5,1043.2227" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="135" x="719.5" y="1059.0308">add keyword manually?</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="787,1541.2734,799,1553.2734,787,1565.2734,775,1553.2734,787,1541.2734" style="stroke:#A80036;stroke-width:1.5;"/><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="552,1571.2734,564,1583.2734,552,1595.2734,540,1583.2734,552,1571.2734" style="stroke:#A80036;stroke-width:1.5;"/><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="531.5,1615.2734,572.5,1615.2734,584.5,1627.2734,572.5,1639.2734,531.5,1639.2734,519.5,1627.2734,531.5,1615.2734" style="stroke:#A80036;stroke-width:1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="41" x="531.5" y="1631.0815">options</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="61.9063" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="77" x="469.5" y="1649.2734"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="29" x="491.5" y="1670.4121">send</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="49" x="479.5" y="1684.3809">(publish</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="57" x="479.5" y="1698.3496">question)</text><rect fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" height="33.9688" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="59" x="566.5" y="1649.2734"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="39" x="576.5" y="1670.4121">cancel</text><polygon fill="#FEFECE" filter="url(#fuc3n4o2gfifh)" points="552,1717.1797,564,1729.1797,552,1741.1797,540,1729.1797,552,1717.1797" style="stroke:#A80036;stroke-width:1.5;"/><ellipse cx="552" cy="1772.1797" fill="#FFFFFF" filter="url(#fuc3n4o2gfifh)" rx="11" ry="11" style="stroke:#000000;stroke-width:1.0;"/><ellipse cx="552" cy="1772.1797" fill="#000000" rx="6" ry="6" style="stroke:#7F7F7F;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="258" x2="245" y1="547.125" y2="547.125"/><line style="stroke:#A80036;stroke-width:1.5;" x1="245" x2="245" y1="547.125" y2="579.125"/><polygon fill="#A80036" points="241,569.125,245,579.125,249,569.125,245,573.125" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="282" x2="323" y1="547.125" y2="547.125"/><line style="stroke:#A80036;stroke-width:1.5;" x1="323" x2="323" y1="547.125" y2="734.9336"/><line style="stroke:#A80036;stroke-width:1.5;" x1="323" x2="282" y1="734.9336" y2="734.9336"/><polygon fill="#A80036" points="292,730.9336,282,734.9336,292,738.9336,288,734.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="245" x2="245" y1="627.0625" y2="734.9336"/><line style="stroke:#A80036;stroke-width:1.5;" x1="245" x2="258" y1="734.9336" y2="734.9336"/><polygon fill="#A80036" points="248,730.9336,258,734.9336,248,738.9336,252,734.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="270" x2="270" y1="500.125" y2="535.125"/><polygon fill="#A80036" points="266,525.125,270,535.125,274,525.125,270,529.125" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="277.5" x2="270" y1="430.5469" y2="430.5469"/><line style="stroke:#A80036;stroke-width:1.5;" x1="270" x2="270" y1="430.5469" y2="466.1563"/><polygon fill="#A80036" points="266,456.1563,270,466.1563,274,456.1563,270,460.1563" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="14" x="274" y="452.1597">no</text><line style="stroke:#A80036;stroke-width:1.5;" x1="368.5" x2="401" y1="430.5469" y2="430.5469"/><line style="stroke:#A80036;stroke-width:1.5;" x1="401" x2="401" y1="430.5469" y2="466.1563"/><polygon fill="#A80036" points="397,456.1563,401,466.1563,405,456.1563,401,460.1563" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="20" x="405" y="452.1597">yes</text><line style="stroke:#A80036;stroke-width:1.5;" x1="270" x2="270" y1="746.9336" y2="802.9336"/><line style="stroke:#A80036;stroke-width:1.5;" x1="270" x2="311" y1="802.9336" y2="802.9336"/><polygon fill="#A80036" points="301,798.9336,311,802.9336,301,806.9336,305,802.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="401" x2="401" y1="514.0938" y2="802.9336"/><line style="stroke:#A80036;stroke-width:1.5;" x1="401" x2="335" y1="802.9336" y2="802.9336"/><polygon fill="#A80036" points="345,798.9336,335,802.9336,345,806.9336,341,802.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="531" x2="493.5" y1="429.7422" y2="429.7422"/><line style="stroke:#A80036;stroke-width:1.5;" x1="493.5" x2="493.5" y1="429.7422" y2="461.7422"/><polygon fill="#A80036" points="489.5,451.7422,493.5,461.7422,497.5,451.7422,493.5,455.7422" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="555" x2="582.5" y1="429.7422" y2="429.7422"/><line style="stroke:#A80036;stroke-width:1.5;" x1="582.5" x2="582.5" y1="429.7422" y2="461.7422"/><polygon fill="#A80036" points="578.5,451.7422,582.5,461.7422,586.5,451.7422,582.5,455.7422" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="493.5" x2="493.5" y1="495.7109" y2="645.6484"/><line style="stroke:#A80036;stroke-width:1.5;" x1="493.5" x2="531" y1="645.6484" y2="645.6484"/><polygon fill="#A80036" points="521,641.6484,531,645.6484,521,649.6484,525,645.6484" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="582.5" x2="582.5" y1="523.6484" y2="645.6484"/><line style="stroke:#A80036;stroke-width:1.5;" x1="582.5" x2="555" y1="645.6484" y2="645.6484"/><polygon fill="#A80036" points="565,641.6484,555,645.6484,565,649.6484,561,645.6484" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="543" x2="543" y1="657.6484" y2="690.9336"/><polygon fill="#A80036" points="539,680.9336,543,690.9336,547,680.9336,543,684.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="932" x2="887" y1="490.9609" y2="490.9609"/><line style="stroke:#A80036;stroke-width:1.5;" x1="887" x2="887" y1="490.9609" y2="522.9609"/><polygon fill="#A80036" points="883,512.9609,887,522.9609,891,512.9609,887,516.9609" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="956" x2="996" y1="490.9609" y2="490.9609"/><line style="stroke:#A80036;stroke-width:1.5;" x1="996" x2="996" y1="490.9609" y2="691.1836"/><line style="stroke:#A80036;stroke-width:1.5;" x1="996" x2="956" y1="691.1836" y2="691.1836"/><polygon fill="#A80036" points="966,687.1836,956,691.1836,966,695.1836,962,691.1836" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="887" x2="887" y1="570.8984" y2="691.1836"/><line style="stroke:#A80036;stroke-width:1.5;" x1="887" x2="932" y1="691.1836" y2="691.1836"/><polygon fill="#A80036" points="922,687.1836,932,691.1836,922,695.1836,926,691.1836" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="944" x2="944" y1="502.9609" y2="509.6276"/><line style="stroke:#A80036;stroke-width:1.5;" x1="944" x2="951" y1="509.6276" y2="509.6276"/><line style="stroke:#A80036;stroke-width:1.5;" x1="951" x2="951" y1="509.6276" y2="522.9609"/><polygon fill="#A80036" points="947,512.9609,951,522.9609,955,512.9609,951,516.9609" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="951" x2="951" y1="570.8984" y2="625.8984"/><line style="stroke:#A80036;stroke-width:1.5;" x1="951" x2="944" y1="625.8984" y2="625.8984"/><line style="stroke:#A80036;stroke-width:1.5;" x1="944" x2="944" y1="625.8984" y2="679.1836"/><polygon fill="#A80036" points="940,669.1836,944,679.1836,948,669.1836,944,673.1836" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="882" x2="823" y1="436.9492" y2="436.9492"/><line style="stroke:#A80036;stroke-width:1.5;" x1="823" x2="823" y1="436.9492" y2="478.9609"/><polygon fill="#A80036" points="819,468.9609,823,478.9609,827,468.9609,823,472.9609" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="20" x="827" y="461.7632">yes</text><line style="stroke:#A80036;stroke-width:1.5;" x1="942" x2="944" y1="436.9492" y2="436.9492"/><line style="stroke:#A80036;stroke-width:1.5;" x1="944" x2="944" y1="436.9492" y2="478.9609"/><polygon fill="#A80036" points="940,468.9609,944,478.9609,948,468.9609,944,472.9609" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="14" x="948" y="461.7632">no</text><line style="stroke:#A80036;stroke-width:1.5;" x1="823" x2="823" y1="526.8984" y2="768.9336"/><line style="stroke:#A80036;stroke-width:1.5;" x1="823" x2="900" y1="768.9336" y2="768.9336"/><polygon fill="#A80036" points="890,764.9336,900,768.9336,890,772.9336,894,768.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="944" x2="944" y1="703.1836" y2="768.9336"/><line style="stroke:#A80036;stroke-width:1.5;" x1="944" x2="924" y1="768.9336" y2="768.9336"/><polygon fill="#A80036" points="934,764.9336,924,768.9336,934,772.9336,930,768.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="519.5" x2="69" y1="280.5" y2="280.5"/><line style="stroke:#A80036;stroke-width:1.5;" x1="69" x2="69" y1="280.5" y2="417.7422"/><polygon fill="#A80036" points="65,407.7422,69,417.7422,73,407.7422,69,411.7422" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="584.5" x2="1026" y1="280.5" y2="280.5"/><line style="stroke:#A80036;stroke-width:1.5;" x1="1026" x2="1026" y1="280.5" y2="836.9336"/><line style="stroke:#A80036;stroke-width:1.5;" x1="1026" x2="564" y1="836.9336" y2="836.9336"/><polygon fill="#A80036" points="574,832.9336,564,836.9336,574,840.9336,570,836.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="69" x2="69" y1="465.6797" y2="836.9336"/><line style="stroke:#A80036;stroke-width:1.5;" x1="69" x2="540" y1="836.9336" y2="836.9336"/><polygon fill="#A80036" points="530,832.9336,540,836.9336,530,840.9336,534,836.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="154.5" x2="154.5" y1="280.5" y2="417.7422"/><polygon fill="#A80036" points="150.5,407.7422,154.5,417.7422,158.5,407.7422,154.5,411.7422" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="154.5" x2="154.5" y1="465.6797" y2="836.9336"/><polygon fill="#A80036" points="150.5,826.9336,154.5,836.9336,158.5,826.9336,154.5,830.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="323" x2="323" y1="280.5" y2="417.7422"/><polygon fill="#A80036" points="319,407.7422,323,417.7422,327,407.7422,323,411.7422" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="323" x2="323" y1="814.9336" y2="836.9336"/><polygon fill="#A80036" points="319,826.9336,323,836.9336,327,826.9336,323,830.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="552" x2="552" y1="292.5" y2="334.2474"/><line style="stroke:#A80036;stroke-width:1.5;" x1="552" x2="543" y1="334.2474" y2="334.2474"/><line style="stroke:#A80036;stroke-width:1.5;" x1="543" x2="543" y1="334.2474" y2="417.7422"/><polygon fill="#A80036" points="539,407.7422,543,417.7422,547,407.7422,543,411.7422" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="668" x2="668" y1="280.5" y2="417.7422"/><polygon fill="#A80036" points="664,407.7422,668,417.7422,672,407.7422,668,411.7422" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="0" x="672" y="301.7104"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="0" x="672" y="314.5151"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="0" x="672" y="327.3198"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="0" x="672" y="340.1245"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="0" x="672" y="352.9292"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="0" x="672" y="365.7339"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="7" x="672" y="378.5386">if</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="45" x="672" y="391.3433">preview</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="47" x="672" y="404.1479">selected</text><line style="stroke:#A80036;stroke-width:1.5;" x1="668" x2="668" y1="451.7109" y2="836.9336"/><polygon fill="#A80036" points="664,826.9336,668,836.9336,672,826.9336,668,830.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="747.5" x2="747.5" y1="280.5" y2="417.7422"/><polygon fill="#A80036" points="743.5,407.7422,747.5,417.7422,751.5,407.7422,747.5,411.7422" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="33" x="751.5" y="327.3198">if text</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="35" x="751.5" y="340.1245">added</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="21" x="751.5" y="352.9292">and</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="58" x="751.5" y="365.7339">input view</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacing" textLength="47" x="751.5" y="378.5386">selected</text><line style="stroke:#A80036;stroke-width:1.5;" x1="747.5" x2="747.5" y1="451.7109" y2="836.9336"/><polygon fill="#A80036" points="743.5,826.9336,747.5,836.9336,751.5,826.9336,747.5,830.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="912" x2="912" y1="280.5" y2="417.7422"/><polygon fill="#A80036" points="908,407.7422,912,417.7422,916,407.7422,912,411.7422" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="912" x2="912" y1="780.9336" y2="836.9336"/><polygon fill="#A80036" points="908,826.9336,912,836.9336,916,826.9336,912,830.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="552" x2="552" y1="248.5" y2="268.5"/><polygon fill="#A80036" points="548,258.5,552,268.5,556,258.5,552,262.5" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="588" x2="1035" y1="881.7383" y2="881.7383"/><polygon fill="#A80036" points="1031,659.1836,1035,649.1836,1039,659.1836,1035,655.1836" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="1035" x2="1035" y1="236.5" y2="881.7383"/><line style="stroke:#A80036;stroke-width:1.5;" x1="1035" x2="564" y1="236.5" y2="236.5"/><polygon fill="#A80036" points="574,232.5,564,236.5,574,240.5,570,236.5" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="552" x2="552" y1="848.9336" y2="868.9336"/><polygon fill="#A80036" points="548,858.9336,552,868.9336,556,858.9336,552,862.9336" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="552" x2="552" y1="204.5" y2="224.5"/><polygon fill="#A80036" points="548,214.5,552,224.5,556,214.5,552,218.5" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="552" x2="552" y1="894.543" y2="914.543"/><polygon fill="#A80036" points="548,904.543,552,914.543,556,904.543,552,908.543" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="421" x2="421" y1="1227.9648" y2="1262.9648"/><polygon fill="#A80036" points="417,1252.9648,421,1262.9648,425,1252.9648,421,1256.9648" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="284.5" x2="174.5" y1="1148.0273" y2="1148.0273"/><line style="stroke:#A80036;stroke-width:1.5;" x1="174.5" x2="174.5" y1="1148.0273" y2="1180.0273"/><polygon fill="#A80036" points="170.5,1170.0273,174.5,1180.0273,178.5,1170.0273,174.5,1174.0273" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="349.5" x2="499" y1="1148.0273" y2="1148.0273"/><line style="stroke:#A80036;stroke-width:1.5;" x1="499" x2="499" y1="1148.0273" y2="1396.0664"/><line style="stroke:#A80036;stroke-width:1.5;" x1="499" x2="329" y1="1396.0664" y2="1396.0664"/><polygon fill="#A80036" points="339,1392.0664,329,1396.0664,339,1400.0664,335,1396.0664" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="174.5" x2="174.5" y1="1227.9648" y2="1396.0664"/><line style="stroke:#A80036;stroke-width:1.5;" x1="174.5" x2="305" y1="1396.0664" y2="1396.0664"/><polygon fill="#A80036" points="295,1392.0664,305,1396.0664,295,1400.0664,299,1396.0664" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="317" x2="317" y1="1160.0273" y2="1166.694"/><line style="stroke:#A80036;stroke-width:1.5;" x1="317" x2="303.5" y1="1166.694" y2="1166.694"/><line style="stroke:#A80036;stroke-width:1.5;" x1="303.5" x2="303.5" y1="1166.694" y2="1180.0273"/><polygon fill="#A80036" points="299.5,1170.0273,303.5,1180.0273,307.5,1170.0273,303.5,1174.0273" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="303.5" x2="303.5" y1="1227.9648" y2="1316.0156"/><line style="stroke:#A80036;stroke-width:1.5;" x1="303.5" x2="317" y1="1316.0156" y2="1316.0156"/><line style="stroke:#A80036;stroke-width:1.5;" x1="317" x2="317" y1="1316.0156" y2="1384.0664"/><polygon fill="#A80036" points="313,1374.0664,317,1384.0664,321,1374.0664,317,1378.0664" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="421" x2="421" y1="1148.0273" y2="1180.0273"/><polygon fill="#A80036" points="417,1170.0273,421,1180.0273,425,1170.0273,421,1174.0273" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="421" x2="421" y1="1296.9336" y2="1396.0664"/><polygon fill="#A80036" points="417,1386.0664,421,1396.0664,425,1386.0664,421,1390.0664" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="317" x2="317" y1="1115.625" y2="1136.0273"/><polygon fill="#A80036" points="313,1126.0273,317,1136.0273,321,1126.0273,317,1130.0273" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="353" x2="526" y1="1444.3047" y2="1444.3047"/><polygon fill="#A80036" points="522,1293.8828,526,1283.8828,530,1293.8828,526,1289.8828" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="526" x2="526" y1="1103.625" y2="1444.3047"/><line style="stroke:#A80036;stroke-width:1.5;" x1="526" x2="329" y1="1103.625" y2="1103.625"/><polygon fill="#A80036" points="339,1099.625,329,1103.625,339,1107.625,335,1103.625" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="317" x2="317" y1="1408.0664" y2="1431.5"/><polygon fill="#A80036" points="313,1421.5,317,1431.5,321,1421.5,317,1425.5" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="317" x2="317" y1="1067.2227" y2="1091.625"/><polygon fill="#A80036" points="313,1081.625,317,1091.625,321,1081.625,317,1085.625" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="374.5" x2="548" y1="1055.2227" y2="1055.2227"/><polygon fill="#A80036" points="544,1274.2852,548,1284.2852,552,1274.2852,548,1278.2852" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="548" x2="548" y1="1055.2227" y2="1489.1094"/><line style="stroke:#A80036;stroke-width:1.5;" x1="548" x2="329" y1="1489.1094" y2="1489.1094"/><polygon fill="#A80036" points="339,1485.1094,329,1489.1094,339,1493.1094,335,1489.1094" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="317" x2="317" y1="1457.1094" y2="1477.1094"/><polygon fill="#A80036" points="313,1467.1094,317,1477.1094,321,1467.1094,317,1471.1094" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="891" x2="891" y1="1296.5313" y2="1330.0977"/><polygon fill="#A80036" points="887,1320.0977,891,1330.0977,895,1320.0977,891,1324.0977" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="754.5" x2="644.5" y1="1216.5938" y2="1216.5938"/><line style="stroke:#A80036;stroke-width:1.5;" x1="644.5" x2="644.5" y1="1216.5938" y2="1248.5938"/><polygon fill="#A80036" points="640.5,1238.5938,644.5,1248.5938,648.5,1238.5938,644.5,1242.5938" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="819.5" x2="969" y1="1216.5938" y2="1216.5938"/><line style="stroke:#A80036;stroke-width:1.5;" x1="969" x2="969" y1="1216.5938" y2="1440.0664"/><line style="stroke:#A80036;stroke-width:1.5;" x1="969" x2="799" y1="1440.0664" y2="1440.0664"/><polygon fill="#A80036" points="809,1436.0664,799,1440.0664,809,1444.0664,805,1440.0664" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="644.5" x2="644.5" y1="1296.5313" y2="1440.0664"/><line style="stroke:#A80036;stroke-width:1.5;" x1="644.5" x2="775" y1="1440.0664" y2="1440.0664"/><polygon fill="#A80036" points="765,1436.0664,775,1440.0664,765,1444.0664,769,1440.0664" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="787" x2="787" y1="1228.5938" y2="1235.2604"/><line style="stroke:#A80036;stroke-width:1.5;" x1="787" x2="773.5" y1="1235.2604" y2="1235.2604"/><line style="stroke:#A80036;stroke-width:1.5;" x1="773.5" x2="773.5" y1="1235.2604" y2="1248.5938"/><polygon fill="#A80036" points="769.5,1238.5938,773.5,1248.5938,777.5,1238.5938,773.5,1242.5938" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="773.5" x2="773.5" y1="1296.5313" y2="1369.0664"/><line style="stroke:#A80036;stroke-width:1.5;" x1="773.5" x2="787" y1="1369.0664" y2="1369.0664"/><line style="stroke:#A80036;stroke-width:1.5;" x1="787" x2="787" y1="1369.0664" y2="1428.0664"/><polygon fill="#A80036" points="783,1418.0664,787,1428.0664,791,1418.0664,787,1422.0664" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="891" x2="891" y1="1216.5938" y2="1248.5938"/><polygon fill="#A80036" points="887,1238.5938,891,1248.5938,895,1238.5938,891,1242.5938" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="891" x2="891" y1="1364.0664" y2="1440.0664"/><polygon fill="#A80036" points="887,1430.0664,891,1440.0664,895,1430.0664,891,1434.0664" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="787" x2="787" y1="1169.5938" y2="1204.5938"/><polygon fill="#A80036" points="783,1194.5938,787,1204.5938,791,1194.5938,787,1198.5938" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="787" x2="787" y1="1115.2227" y2="1135.625"/><polygon fill="#A80036" points="783,1125.625,787,1135.625,791,1125.625,787,1129.625" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="823" x2="987" y1="1508.4688" y2="1508.4688"/><polygon fill="#A80036" points="983,1326.5313,987,1316.5313,991,1326.5313,987,1322.5313" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="987" x2="987" y1="1103.2227" y2="1508.4688"/><line style="stroke:#A80036;stroke-width:1.5;" x1="987" x2="799" y1="1103.2227" y2="1103.2227"/><polygon fill="#A80036" points="809,1099.2227,799,1103.2227,809,1107.2227,805,1103.2227" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="787" x2="787" y1="1452.0664" y2="1495.6641"/><polygon fill="#A80036" points="783,1485.6641,787,1495.6641,791,1485.6641,787,1489.6641" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="787" x2="787" y1="1067.2227" y2="1091.2227"/><polygon fill="#A80036" points="783,1081.2227,787,1091.2227,791,1081.2227,787,1085.2227" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="866.5" x2="1005" y1="1055.2227" y2="1055.2227"/><polygon fill="#A80036" points="1001,1306.9336,1005,1316.9336,1009,1306.9336,1005,1310.9336" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="1005" x2="1005" y1="1055.2227" y2="1553.2734"/><line style="stroke:#A80036;stroke-width:1.5;" x1="1005" x2="799" y1="1553.2734" y2="1553.2734"/><polygon fill="#A80036" points="809,1549.2734,799,1553.2734,809,1557.2734,805,1553.2734" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="787" x2="787" y1="1521.2734" y2="1541.2734"/><polygon fill="#A80036" points="783,1531.2734,787,1541.2734,791,1531.2734,787,1535.2734" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="497" x2="317" y1="1014.0156" y2="1014.0156"/><line style="stroke:#A80036;stroke-width:1.5;" x1="317" x2="317" y1="1014.0156" y2="1043.2227"/><polygon fill="#A80036" points="313,1033.2227,317,1043.2227,321,1033.2227,317,1037.2227" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="607" x2="787" y1="1014.0156" y2="1014.0156"/><line style="stroke:#A80036;stroke-width:1.5;" x1="787" x2="787" y1="1014.0156" y2="1043.2227"/><polygon fill="#A80036" points="783,1033.2227,787,1043.2227,791,1033.2227,787,1037.2227" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="317" x2="317" y1="1501.1094" y2="1583.2734"/><line style="stroke:#A80036;stroke-width:1.5;" x1="317" x2="540" y1="1583.2734" y2="1583.2734"/><polygon fill="#A80036" points="530,1579.2734,540,1583.2734,530,1587.2734,534,1583.2734" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="787" x2="787" y1="1565.2734" y2="1583.2734"/><line style="stroke:#A80036;stroke-width:1.5;" x1="787" x2="564" y1="1583.2734" y2="1583.2734"/><polygon fill="#A80036" points="574,1579.2734,564,1583.2734,574,1587.2734,570,1583.2734" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="519.5" x2="508" y1="1627.2734" y2="1627.2734"/><line style="stroke:#A80036;stroke-width:1.5;" x1="508" x2="508" y1="1627.2734" y2="1649.2734"/><polygon fill="#A80036" points="504,1639.2734,508,1649.2734,512,1639.2734,508,1643.2734" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="584.5" x2="596" y1="1627.2734" y2="1627.2734"/><line style="stroke:#A80036;stroke-width:1.5;" x1="596" x2="596" y1="1627.2734" y2="1649.2734"/><polygon fill="#A80036" points="592,1639.2734,596,1649.2734,600,1639.2734,596,1643.2734" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="508" x2="508" y1="1711.1797" y2="1729.1797"/><line style="stroke:#A80036;stroke-width:1.5;" x1="508" x2="540" y1="1729.1797" y2="1729.1797"/><polygon fill="#A80036" points="530,1725.1797,540,1729.1797,530,1733.1797,534,1729.1797" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="596" x2="596" y1="1683.2422" y2="1729.1797"/><line style="stroke:#A80036;stroke-width:1.5;" x1="596" x2="564" y1="1729.1797" y2="1729.1797"/><polygon fill="#A80036" points="574,1725.1797,564,1729.1797,574,1733.1797,570,1729.1797" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="552" x2="552" y1="1595.2734" y2="1615.2734"/><polygon fill="#A80036" points="548,1605.2734,552,1615.2734,556,1605.2734,552,1609.2734" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="552" x2="552" y1="1741.1797" y2="1761.1797"/><polygon fill="#A80036" points="548,1751.1797,552,1761.1797,556,1751.1797,552,1755.1797" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="552" x2="552" y1="948.5117" y2="994.8086"/><polygon fill="#A80036" points="548,984.8086,552,994.8086,556,984.8086,552,988.8086" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="552" x2="552" y1="124.2344" y2="170.5313"/><polygon fill="#A80036" points="548,160.5313,552,170.5313,556,160.5313,552,164.5313" style="stroke:#A80036;stroke-width:1.0;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="552" x2="552" y1="30" y2="76.2969"/><polygon fill="#A80036" points="548,66.2969,552,76.2969,556,66.2969,552,70.2969" style="stroke:#A80036;stroke-width:1.0;"/><rect fill="#DDDDDD" height="239.7813" rx="5" ry="5" style="stroke:#000000;stroke-width:1.0;" width="404" x="653" y="1832.1797"/><image height="128" width="128" x="659" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAADcklEQVR4Xu2c0W3iUBREqQjqSDXbRYpKJ/neMvYju08ECY3J4js2cGfeHOkoH9G7RvIBG2M4HEIIIYQQQgghhJ95e3v7/e/PV3ytx+Px1+GZnE6nP4cbDyS+1meFsNhwbOfDwA3Fvu4ObiA29vswvRuLDUQJdwMHRx03gwOjlpvBgVHIPc4FFkOjnBzfFxZwWNSTIwHYyJEAbORIADZyJAAbORKAjRyzBDDeK1+L/zeQwzGA9/f3ryqfn5+XCyqLeSJyuAQwdh7uVJaPj4/FfAE5HAJ4FOOVBLfVWA7lAMb9irjTHgFut6kcqgEwx/kt4PYbyqEYwLOe+deMk0R8HM3kUAzgVeDjaCaHWgCvBh9PIzkSQA18PI3kUAqABedcHO/3GXBOEzmcA1h74lYF1zeRQyUA5kofzvjJ6isBrm8ih0oAj95JFZp+YZZDJYAquP6eFZp+VsCRAOrz155bPFkOlQDGs64irr9nhQRgaIWmnxJyJICzFZreOMKRAM5WwLVN5EgAtZ0/wPVN5Jg9gOoFpqbH/yHH7AFUwfWN5Jg5gCpNrwBe5Jg1AAac0UyOGQNgwBkN5ZgpAPZGUpzTVI5ZAmB3ftOLPrfkmCGA6lu9C81P+lCOGQJgEHrmX+RwD4B56ccZInK4B1AF1wvJ4RxA9dmP68XkcA6ggtgJ3y05EsAZXCsoRwKw2PlDDtcAKsd/XCsqh2sA48bNNTA3kDaVwzWAteA6YTkSwHKtqBwJYLlWVA7XACaUIwHYyJEAbORIADZyJAAbORKAjRwzBIAYXf27lsM5gHs0/poXI4drAGsxioBj9gAGuFZUDscAqpi8CnAkgDM4Q1COBHAGZwjKkQDa/upXVQ7HACq3gw1wvagcjgEMK+BaUTlcAxiuAdcIy+EcwPDWN4NNjvkoh3sAE8mRAGzkSAA2ciQAGzkSgI0cCcBGjgRg4yZwWNRzEzgs6rkJHBb15Ml5gIWbwYFRy13AoVHH7Rj8VNrM7goOj/3dF8EfS57dx5DDgoxBBNxxexmEwJ23h0EM3IFbDYLgTtxiUGPnS/BBkR0jCKrsFEFQZocIgjobIwgObIgguEBGEJwgIghuFD+IC44UIgiurIwgOLMiguDOnQjCDPwngjALP9yvGWbiRgRhNiCCMCNXEYRZ+Y4ghBBCCCGEEG7wF4/x8PpTsJefAAAAAElFTkSuQmCC" y="1839.1797"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="0" x="791" y="1963.8779"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="0" x="796" y="1852.1748"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="0" x="796" y="1868.4717"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="92" x="796" y="1884.7686">»frag.jetzt«</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="76" x="663" y="1980.1748">Produktion</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="0" x="795" y="1980.1748"/><a href="https://frag.jetzt" target="_top" title="https://frag.jetzt" xlink:actuate="onRequest" xlink:href="https://frag.jetzt" xlink:show="new" xlink:title="https://frag.jetzt" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" text-decoration="underline" textLength="113" x="795" y="1980.1748">https://frag.jetzt</text></a><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="0" x="912" y="1980.1748"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="76" x="663" y="1996.4717">Repository</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="0" x="795" y="1996.4717"/><a href="https://git.thm.de/arsnova/frag.jetzt" target="_top" title="https://git.thm.de/arsnova/frag.jetzt" xlink:actuate="onRequest" xlink:href="https://git.thm.de/arsnova/frag.jetzt" xlink:show="new" xlink:title="https://git.thm.de/arsnova/frag.jetzt" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" text-decoration="underline" textLength="252" x="795" y="1996.4717">https://git.thm.de/arsnova/frag.jetzt</text></a><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="0" x="1051" y="1996.4717"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="105" x="663" y="2012.7686">Staging Server</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="0" x="795" y="2012.7686"/><a href="https://staging.frag.jetzt" target="_top" title="https://staging.frag.jetzt" xlink:actuate="onRequest" xlink:href="https://staging.frag.jetzt" xlink:show="new" xlink:title="https://staging.frag.jetzt" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" text-decoration="underline" textLength="169" x="795" y="2012.7686">https://staging.frag.jetzt</text></a><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="0" x="968" y="2012.7686"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="66" x="663" y="2029.0654">UML-Tool</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="112" x="795" y="2029.0654">PlantUML v5.5.1</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="59" x="663" y="2045.3623">Ersteller</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="212" x="795" y="2045.3623">Lujain Abou Assali, Dario Gloc</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="117" x="663" y="2061.6592">Letzte Änderung</text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="80" x="795" y="2061.6592">20.06.2021</text><line style="stroke:#000000;stroke-width:1.0;" x1="659" x2="1051" y1="1839.1797" y2="1839.1797"/><line style="stroke:#000000;stroke-width:1.0;" x1="659" x2="1051" y1="1967.1797" y2="1967.1797"/><line style="stroke:#000000;stroke-width:1.0;" x1="659" x2="1051" y1="1983.4766" y2="1983.4766"/><line style="stroke:#000000;stroke-width:1.0;" x1="659" x2="1051" y1="1999.7734" y2="1999.7734"/><line style="stroke:#000000;stroke-width:1.0;" x1="659" x2="1051" y1="2016.0703" y2="2016.0703"/><line style="stroke:#000000;stroke-width:1.0;" x1="659" x2="1051" y1="2032.3672" y2="2032.3672"/><line style="stroke:#000000;stroke-width:1.0;" x1="659" x2="1051" y1="2048.6641" y2="2048.6641"/><line style="stroke:#000000;stroke-width:1.0;" x1="659" x2="1051" y1="2064.9609" y2="2064.9609"/><line style="stroke:#000000;stroke-width:1.0;" x1="659" x2="659" y1="1839.1797" y2="2064.9609"/><line style="stroke:#000000;stroke-width:1.0;" x1="791" x2="791" y1="1839.1797" y2="2064.9609"/><line style="stroke:#000000;stroke-width:1.0;" x1="1051" x2="1051" y1="1839.1797" y2="2064.9609"/><!--MD5=[853126bd8101f2c89f57173f581c6eba]
+@startuml
+'https://plantuml.com/activity-diagram-beta
+
+start
+partition "Comment List"
+    :create\nquestion;
+    partition "Create question dialog"
+        :Input;
+        repeat
+            switch (options)
+                case ()
+                    :   select\nlanguage;
+                case ()
+                    :select\n  tag;
+                case ()
+                    switch (suggestions\n    active?)
+                        case( no)
+                            :spellcheck;
+                            switch ()
+                                case ()
+                                    :     use\nsuggestion;
+                                case ()
+                            endswitch
+                        case ( yes)
+                          :     use\nsuggestion;
+                    endswitch
+                case ()
+                    switch ()
+                        case ()
+                            :cancel;
+                        case ()
+                            :    click\noutside of\n  window;
+                    endswitch
+                    stop
+                case (\n\n\n\n\n\n if\n preview\n selected)
+                    :input;
+                case ( if text\n added\n and\n input view\n selected)
+                    :preview;
+                case ()
+                    switch (empty\ntext\nfield?)
+                        case ( yes)
+                            :add\ntext;
+
+                        case ( no)
+                            switch ()
+                                case ()
+                                    :add\ntext;
+                                case ()
+                                    :edit\ntext;
+                                case ()
+                            endswitch
+                    endswitch
+                case ()
+            endswitch
+        repeat while (continue\n editing)
+
+        :send;
+        note left
+        only if text is added
+        end note
+        partition "SpaCy dialog" {
+            if(    supported\n     language\ndetected or set) then (yes)
+                if (nouns included?) then (yes)
+                    repeat
+                        switch(options)
+                            case ()
+                                :select\deselect\na keyword;
+                            case ()
+                                :select\deselect\n all keywords;
+                            case ()
+                                :     edit\n a keyword;
+                                :save;
+                            case ()
+                        endswitch
+                    repeat while (continue\n setting)
+                else (no)
+                endif
+            else (no)
+                if(add keyword manually?)
+                    repeat
+                        :add keyword;
+                        switch (options)
+                            case ()
+                                :select\deselect\na keyword;
+                            case ()
+                                :select\deselect\n all keywords;
+                            case ()
+                                :      edit\n a keyword;
+                                :save;
+                            case()
+                        endswitch
+                    repeat while (continue\n setting)
+                else
+                endif
+            endif
+            if(options)
+                :   send\n(publish\nquestion);
+            else
+                :cancel;
+            endif
+            stop
+        }
+    }
+}
+
+legend right
+  |<img:https://git.thm.de/arsnova/arsnova-lite/raw/staging/src/assets/icons/Logo_frag_jetzt_128x128.png> |= \n\n »frag.jetzt« |
+  | Produktion | [[https://frag.jetzt]] |
+  | Repository | [[https://git.thm.de/arsnova/frag.jetzt]] |
+  | Staging Server | [[https://staging.frag.jetzt]] |
+  | UML-Tool| PlantUML v5.5.1|
+  | Ersteller| Lujain Abou Assali, Dario Gloc|
+  | Letzte Änderung| 20.06.2021 |
+end legend
+/'
+legend right
+ |= \n          <img:https://git.thm.de/arsnova/frag.jetzt/-/raw/staging/src/assets/icons/favicon-32x32.png> |= \n [[https://git.thm.de/arsnova/frag.jetzt frag.jetzt]] \n\n Technische Hochschule Mittelhessen |
+ | Repository | [[https://git.thm.de/arsnova/frag.jetzt]] |
+ | Staging Server | [[https://staging.frag.jetzt]] |
+ | UML-Tool| PlantUML v5.5.1|
+ | Modellversion| 1.0|
+ | Erstelldatum| 17.06.2021|
+ | Ersteller| Lujain Abou Assali, Dario Gloc|
+ | Letzte Änderung| 17.06.2021|
+end legend
+'/
+@enduml
+
+@startuml
+
+start
+partition "Comment List"
+    :create\nquestion;
+    partition "Create question dialog"
+        :Input;
+        repeat
+            switch (options)
+                case ()
+                    :   select\nlanguage;
+                case ()
+                    :select\n  tag;
+                case ()
+                    switch (suggestions\n    active?)
+                        case( no)
+                            :spellcheck;
+                            switch ()
+                                case ()
+                                    :     use\nsuggestion;
+                                case ()
+                            endswitch
+                        case ( yes)
+                          :     use\nsuggestion;
+                    endswitch
+                case ()
+                    switch ()
+                        case ()
+                            :cancel;
+                        case ()
+                            :    click\noutside of\n  window;
+                    endswitch
+                    stop
+                case (\n\n\n\n\n\n if\n preview\n selected)
+                    :input;
+                case ( if text\n added\n and\n input view\n selected)
+                    :preview;
+                case ()
+                    switch (empty\ntext\nfield?)
+                        case ( yes)
+                            :add\ntext;
+
+                        case ( no)
+                            switch ()
+                                case ()
+                                    :add\ntext;
+                                case ()
+                                    :edit\ntext;
+                                case ()
+                            endswitch
+                    endswitch
+                case ()
+            endswitch
+        repeat while (continue\n editing)
+
+        :send;
+        note left
+        only if text is added
+        end note
+        partition "SpaCy dialog" {
+            if(    supported\n     language\ndetected or set) then (yes)
+                if (nouns included?) then (yes)
+                    repeat
+                        switch(options)
+                            case ()
+                                :select\deselect\na keyword;
+                            case ()
+                                :select\deselect\n all keywords;
+                            case ()
+                                :     edit\n a keyword;
+                                :save;
+                            case ()
+                        endswitch
+                    repeat while (continue\n setting)
+                else (no)
+                endif
+            else (no)
+                if(add keyword manually?)
+                    repeat
+                        :add keyword;
+                        switch (options)
+                            case ()
+                                :select\deselect\na keyword;
+                            case ()
+                                :select\deselect\n all keywords;
+                            case ()
+                                :      edit\n a keyword;
+                                :save;
+                            case()
+                        endswitch
+                    repeat while (continue\n setting)
+                else
+                endif
+            endif
+            if(options)
+                :   send\n(publish\nquestion);
+            else
+                :cancel;
+            endif
+            stop
+        }
+    }
+}
+
+legend right
+  |<img:https://git.thm.de/arsnova/arsnova-lite/raw/staging/src/assets/icons/Logo_frag_jetzt_128x128.png> |= \n\n »frag.jetzt« |
+  | Produktion | [[https://frag.jetzt]] |
+  | Repository | [[https://git.thm.de/arsnova/frag.jetzt]] |
+  | Staging Server | [[https://staging.frag.jetzt]] |
+  | UML-Tool| PlantUML v5.5.1|
+  | Ersteller| Lujain Abou Assali, Dario Gloc|
+  | Letzte Änderung| 20.06.2021 |
+end legend
+@enduml
+
+PlantUML version 1.2021.7(Sun May 23 14:40:07 CEST 2021)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: Dynamic Code Evolution 64-Bit Server VM
+Default Encoding: UTF-8
+Language: de
+Country: DE
+--></g></svg>
\ No newline at end of file
diff --git a/docs/diagrams/UX-Diagrams/topic-cloud.puml b/docs/diagrams/UX-Diagrams/topic-cloud.puml
new file mode 100644
index 0000000000000000000000000000000000000000..747256c382c1e57c49ca0d122a380baf6b14d304
--- /dev/null
+++ b/docs/diagrams/UX-Diagrams/topic-cloud.puml
@@ -0,0 +1,95 @@
+@startuml
+partition Topic-Cloud #skyblue {
+skinparam backgroundColor #skyblue
+
+skinparam class{
+BackgroundColor Application
+BorderColor black
+ArrowColor black
+}
+
+skinparam BorderColor black
+skinparam ArrowColor black
+skinparam backgroundColor #powderblue
+skinparam backgroundColor Linen
+skinparam LegendBackgroundColor Strategy
+skinparam LegendBorderThickness 0
+skinparam LegendFontSize 12
+
+start
+if (decision ?) then
+ :create room;
+else
+ :enter room-code/name;
+endif
+
+ :click options;
+ :select topic-cloud;
+
+partition #powderblue select-list {
+switch ()
+case()
+ :continue with\ncomplete list\nof questions;
+case()
+ :continue with\n current filters;
+case()
+  :continue with\nall questions\n    from now;
+endswitch
+ :select option;
+}
+
+if (choose ?) then (cancel)
+-[#black]->
+end
+else (confirm "continue-button")
+:modify cloud-view;
+
+ floating note right:edit your own topic-cloud\n         or demo-cloud
+switch ()
+case()
+ :    activate\ndemo-cloud;
+case()
+ :  deactivate\ndemo-cloud;
+endswitch
+
+partition #powderblue edit-cloud {
+fork
+:general options;
+
+fork again
+:font options;
+
+fork again
+: hover options;
+
+fork again
+:weight-class options;
+end fork
+floating note right:options for weight\n classes 1 to 10
+
+}
+switch ()
+case()
+ :reset;
+case()
+ :cancel;
+case()
+ :save;
+endswitch
+end
+
+legend right
+  | |= \n »frag.jetzt« \n|
+  | Produktion | [[https://frag.jetzt]] |
+  | Repository | [[https://git.thm.de/arsnova/frag.jetzt]] |
+  | Staging Server | [[https://staging.frag.jetzt]] |
+  | UML-Tool| PlantUML v1.2021.5|
+  | Ersteller| Lauryn Lorna Monthe Djomeni, Aliye Tanriseven|
+  | Vorherige Änderung | 18.06.2021 |
+  | Letzte Änderung| 20.06.2021 |
+  | Letzte Änderung von| Lauryn Lorna Monthe Djomeni\n Aliye Tanriseven |
+end legend
+
+
+@enduml
+}
diff --git a/docs/diagrams/UX-Diagrams/topic_cloud.svg b/docs/diagrams/UX-Diagrams/topic_cloud.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e734180834471dc7c56d6e5026ccfd57a399b2d9
--- /dev/null
+++ b/docs/diagrams/UX-Diagrams/topic_cloud.svg
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="1359px" preserveAspectRatio="none" style="width:786px;height:1359px;background:#FAF0E6;" version="1.1" viewBox="0 0 786 1359" width="786px" zoomAndPan="magnify"><defs><filter height="300%" id="f1py7g1wtp6ye9" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><rect fill="#87CEEB" filter="url(#f1py7g1wtp6ye9)" height="1135.7148" style="stroke: #000000; stroke-width: 2.0;" width="765" x="10" y="10.5762"/><path d="M97,11.5762 L97,21.1855 L87,31.1855 L10,31.1855 " fill="none" style="stroke: #000000; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="77" x="13" y="26.1094">Topic-Cloud</text><ellipse cx="200.75" cy="51.1855" fill="#000000" filter="url(#f1py7g1wtp6ye9)" rx="10" ry="10" style="stroke: none; stroke-width: 1.0;"/><polygon fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" points="176.25,81.1855,225.25,81.1855,237.25,93.1855,225.25,105.1855,176.25,105.1855,164.25,93.1855,176.25,81.1855" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="49" x="176.25" y="97.6865">decision ?</text><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="86" x="89.75" y="115.1855"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="66" x="99.75" y="137.6426">create room</text><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="146" x="195.75" y="115.1855"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="126" x="205.75" y="137.6426">enter room-code/name</text><polygon fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" points="200.75,156.2793,212.75,168.2793,200.75,180.2793,188.75,168.2793,200.75,156.2793" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="88" x="156.75" y="200.2793"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="68" x="166.75" y="222.7363">click options</text><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="116" x="142.75" y="255.373"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="96" x="152.75" y="277.8301">select topic-cloud</text><rect fill="#B0E0E6" filter="url(#f1py7g1wtp6ye9)" height="257.9844" style="stroke: #000000; stroke-width: 2.0;" width="338" x="31.75" y="301.043"/><path d="M100.75,302.043 L100.75,311.6523 L90.75,321.6523 L31.75,321.6523 " fill="none" style="stroke: #000000; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="59" x="34.75" y="316.5762">select-list</text><polygon fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" points="200.75,338.6523,200.75,338.6523,212.75,350.6523,200.75,362.6523,200.75,362.6523,188.75,350.6523,200.75,338.6523" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="65.2813" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="92" x="41.75" y="382.6523"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="72" x="51.75" y="405.1094">continue with</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="70" x="51.75" y="420.2031">complete list</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="68" x="51.75" y="435.2969">of questions</text><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="50.1875" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="94" x="153.75" y="382.6523"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="72" x="163.75" y="405.1094">continue with</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="71" x="166.75" y="420.2031">current filters</text><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="65.2813" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="92" x="267.75" y="382.6523"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="72" x="277.75" y="405.1094">continue with</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="71" x="277.75" y="420.2031">all questions</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="51" x="289.75" y="435.2969">from now</text><polygon fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" points="200.75,467.9336,200.75,467.9336,212.75,479.9336,200.75,491.9336,200.75,491.9336,188.75,479.9336,200.75,467.9336" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="90" x="155.75" y="511.9336"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="70" x="165.75" y="534.3906">select option</text><polygon fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" points="178.25,579.0273,223.25,579.0273,235.25,591.0273,223.25,603.0273,178.25,603.0273,166.25,591.0273,178.25,579.0273" style="stroke: #A80036; stroke-width: 1.5;"/><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="45" x="178.25" y="595.5283">choose ?</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="32" x="134.25" y="588.6104">cancel</text><text fill="#000000" font-family="sans-serif" font-size="11" lengthAdjust="spacingAndGlyphs" textLength="122" x="235.25" y="588.6104">confirm "continue-button"</text><ellipse cx="45" cy="623.0273" fill="#FFFFFF" filter="url(#f1py7g1wtp6ye9)" rx="10" ry="10" style="stroke: #000000; stroke-width: 1.5;"/><line style="stroke: #000000; stroke-width: 2.5;" x1="38.8128" x2="51.1872" y1="616.8402" y2="629.2145"/><line style="stroke: #000000; stroke-width: 2.5;" x1="51.1872" x2="38.8128" y1="616.8402" y2="629.2145"/><path d="M435,613.0273 L435,655.7305 L600,655.7305 L600,623.0273 L590,613.0273 L435,613.0273 " fill="#FBFB77" filter="url(#f1py7g1wtp6ye9)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M590,613.0273 L590,623.0273 L600,623.0273 L590,613.0273 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="144" x="441" y="631.5225">edit your own topic-cloud</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="82" x="477" y="647.874">or demo-cloud</text><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="117" x="298" y="616.832"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="97" x="308" y="639.2891">modify cloud-view</text><polygon fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" points="356.5,675.7305,356.5,675.7305,368.5,687.7305,356.5,699.7305,356.5,699.7305,344.5,687.7305,356.5,675.7305" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="50.1875" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="86" x="260.5" y="719.7305"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="41" x="282.5" y="742.1875">activate</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="66" x="270.5" y="757.2813">demo-cloud</text><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="50.1875" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="86" x="366.5" y="719.7305"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="55" x="382.5" y="742.1875">deactivate</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="66" x="376.5" y="757.2813">demo-cloud</text><polygon fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" points="356.5,779.918,356.5,779.918,368.5,791.918,356.5,803.918,356.5,803.918,344.5,791.918,356.5,779.918" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#B0E0E6" filter="url(#f1py7g1wtp6ye9)" height="136.7031" style="stroke: #000000; stroke-width: 2.0;" width="683" x="80" y="814.4941"/><path d="M152,815.4941 L152,825.1035 L142,835.1035 L80,835.1035 " fill="none" style="stroke: #000000; stroke-width: 2.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacingAndGlyphs" textLength="62" x="83" y="830.0273">edit-cloud</text><path d="M631,874.2988 L631,917.002 L753,917.002 L753,884.2988 L743,874.2988 L631,874.2988 " fill="#FBFB77" filter="url(#f1py7g1wtp6ye9)" style="stroke: #A80036; stroke-width: 1.0;"/><path d="M743,874.2988 L743,884.2988 L753,884.2988 L743,874.2988 " fill="#FBFB77" style="stroke: #A80036; stroke-width: 1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="101" x="637" y="892.7939">options for weight</text><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacingAndGlyphs" textLength="89" x="641" y="909.1455">classes 1 to 10</text><rect fill="#000000" filter="url(#f1py7g1wtp6ye9)" height="6" rx="2.5" ry="2.5" style="stroke: #000000; stroke-width: 1.0;" width="531" x="90" y="852.1035"/><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="106" x="104" y="878.1035"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="86" x="114" y="900.5605">general options</text><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="84" x="238" y="878.1035"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="64" x="248" y="900.5605">font options</text><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="97" x="350" y="878.1035"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="74" x="363" y="900.5605">hover options</text><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="134" x="475" y="878.1035"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="114" x="485" y="900.5605">weight-class options</text><rect fill="#000000" filter="url(#f1py7g1wtp6ye9)" height="6" rx="2.5" ry="2.5" style="stroke: #000000; stroke-width: 1.0;" width="531" x="90" y="933.1973"/><polygon fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" points="356.5,971.1973,356.5,971.1973,368.5,983.1973,356.5,995.1973,356.5,995.1973,344.5,983.1973,356.5,971.1973" style="stroke: #A80036; stroke-width: 1.5;"/><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="48" x="261.5" y="1015.1973"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="28" x="271.5" y="1037.6543">reset</text><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="56" x="329.5" y="1015.1973"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="36" x="339.5" y="1037.6543">cancel</text><rect fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" height="35.0938" rx="12.5" ry="12.5" style="stroke: #A80036; stroke-width: 1.5;" width="46" x="405.5" y="1015.1973"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="26" x="415.5" y="1037.6543">save</text><polygon fill="#FEFECE" filter="url(#f1py7g1wtp6ye9)" points="356.5,1070.291,356.5,1070.291,368.5,1082.291,356.5,1094.291,356.5,1094.291,344.5,1082.291,356.5,1070.291" style="stroke: #A80036; stroke-width: 1.5;"/><ellipse cx="356.5" cy="1124.291" fill="#FFFFFF" filter="url(#f1py7g1wtp6ye9)" rx="10" ry="10" style="stroke: #000000; stroke-width: 1.5;"/><line style="stroke: #000000; stroke-width: 2.5;" x1="350.3128" x2="362.6872" y1="1118.1038" y2="1130.4782"/><line style="stroke: #000000; stroke-width: 2.5;" x1="362.6872" x2="350.3128" y1="1118.1038" y2="1130.4782"/><line style="stroke: #000000; stroke-width: 1.5;" x1="164.25" x2="132.75" y1="93.1855" y2="93.1855"/><line style="stroke: #000000; stroke-width: 1.5;" x1="132.75" x2="132.75" y1="93.1855" y2="115.1855"/><polygon fill="#000000" points="128.75,105.1855,132.75,115.1855,136.75,105.1855,132.75,109.1855" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="237.25" x2="268.75" y1="93.1855" y2="93.1855"/><line style="stroke: #000000; stroke-width: 1.5;" x1="268.75" x2="268.75" y1="93.1855" y2="115.1855"/><polygon fill="#000000" points="264.75,105.1855,268.75,115.1855,272.75,105.1855,268.75,109.1855" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="132.75" x2="132.75" y1="150.2793" y2="168.2793"/><line style="stroke: #000000; stroke-width: 1.5;" x1="132.75" x2="188.75" y1="168.2793" y2="168.2793"/><polygon fill="#000000" points="178.75,164.2793,188.75,168.2793,178.75,172.2793,182.75,168.2793" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="268.75" x2="268.75" y1="150.2793" y2="168.2793"/><line style="stroke: #000000; stroke-width: 1.5;" x1="268.75" x2="212.75" y1="168.2793" y2="168.2793"/><polygon fill="#000000" points="222.75,164.2793,212.75,168.2793,222.75,172.2793,218.75,168.2793" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="200.75" x2="200.75" y1="61.1855" y2="81.1855"/><polygon fill="#000000" points="196.75,71.1855,200.75,81.1855,204.75,71.1855,200.75,75.1855" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="200.75" x2="200.75" y1="180.2793" y2="200.2793"/><polygon fill="#000000" points="196.75,190.2793,200.75,200.2793,204.75,190.2793,200.75,194.2793" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="200.75" x2="200.75" y1="235.373" y2="255.373"/><polygon fill="#000000" points="196.75,245.373,200.75,255.373,204.75,245.373,200.75,249.373" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="188.75" x2="87.75" y1="350.6523" y2="350.6523"/><line style="stroke: #000000; stroke-width: 1.5;" x1="87.75" x2="87.75" y1="350.6523" y2="382.6523"/><polygon fill="#000000" points="83.75,372.6523,87.75,382.6523,91.75,372.6523,87.75,376.6523" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="212.75" x2="313.75" y1="350.6523" y2="350.6523"/><line style="stroke: #000000; stroke-width: 1.5;" x1="313.75" x2="313.75" y1="350.6523" y2="382.6523"/><polygon fill="#000000" points="309.75,372.6523,313.75,382.6523,317.75,372.6523,313.75,376.6523" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="87.75" x2="87.75" y1="447.9336" y2="479.9336"/><line style="stroke: #000000; stroke-width: 1.5;" x1="87.75" x2="188.75" y1="479.9336" y2="479.9336"/><polygon fill="#000000" points="178.75,475.9336,188.75,479.9336,178.75,483.9336,182.75,479.9336" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="313.75" x2="313.75" y1="447.9336" y2="479.9336"/><line style="stroke: #000000; stroke-width: 1.5;" x1="313.75" x2="212.75" y1="479.9336" y2="479.9336"/><polygon fill="#000000" points="222.75,475.9336,212.75,479.9336,222.75,483.9336,218.75,479.9336" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="200.75" x2="200.75" y1="362.6523" y2="369.319"/><line style="stroke: #000000; stroke-width: 1.5;" x1="200.75" x2="200.75" y1="369.319" y2="382.6523"/><polygon fill="#000000" points="196.75,372.6523,200.75,382.6523,204.75,372.6523,200.75,376.6523" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="200.75" x2="200.75" y1="432.8398" y2="452.9336"/><line style="stroke: #000000; stroke-width: 1.5;" x1="200.75" x2="200.75" y1="452.9336" y2="467.9336"/><polygon fill="#000000" points="196.75,457.9336,200.75,467.9336,204.75,457.9336,200.75,461.9336" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="200.75" x2="200.75" y1="491.9336" y2="511.9336"/><polygon fill="#000000" points="196.75,501.9336,200.75,511.9336,204.75,501.9336,200.75,505.9336" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="200.75" x2="200.75" y1="290.4668" y2="338.6523"/><polygon fill="#000000" points="196.75,328.6523,200.75,338.6523,204.75,328.6523,200.75,332.6523" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="344.5" x2="303.5" y1="687.7305" y2="687.7305"/><line style="stroke: #000000; stroke-width: 1.5;" x1="303.5" x2="303.5" y1="687.7305" y2="719.7305"/><polygon fill="#000000" points="299.5,709.7305,303.5,719.7305,307.5,709.7305,303.5,713.7305" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="368.5" x2="409.5" y1="687.7305" y2="687.7305"/><line style="stroke: #000000; stroke-width: 1.5;" x1="409.5" x2="409.5" y1="687.7305" y2="719.7305"/><polygon fill="#000000" points="405.5,709.7305,409.5,719.7305,413.5,709.7305,409.5,713.7305" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="303.5" x2="303.5" y1="769.918" y2="791.918"/><line style="stroke: #000000; stroke-width: 1.5;" x1="303.5" x2="344.5" y1="791.918" y2="791.918"/><polygon fill="#000000" points="334.5,787.918,344.5,791.918,334.5,795.918,338.5,791.918" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="409.5" x2="409.5" y1="769.918" y2="791.918"/><line style="stroke: #000000; stroke-width: 1.5;" x1="409.5" x2="368.5" y1="791.918" y2="791.918"/><polygon fill="#000000" points="378.5,787.918,368.5,791.918,378.5,795.918,374.5,791.918" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="356.5" x2="356.5" y1="651.9258" y2="675.7305"/><polygon fill="#000000" points="352.5,665.7305,356.5,675.7305,360.5,665.7305,356.5,669.7305" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="157" x2="157" y1="858.1035" y2="878.1035"/><polygon fill="#000000" points="153,868.1035,157,878.1035,161,868.1035,157,872.1035" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="280" x2="280" y1="858.1035" y2="878.1035"/><polygon fill="#000000" points="276,868.1035,280,878.1035,284,868.1035,280,872.1035" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="398.5" x2="398.5" y1="858.1035" y2="878.1035"/><polygon fill="#000000" points="394.5,868.1035,398.5,878.1035,402.5,868.1035,398.5,872.1035" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="542" x2="542" y1="858.1035" y2="878.1035"/><polygon fill="#000000" points="538,868.1035,542,878.1035,546,868.1035,542,872.1035" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="157" x2="157" y1="913.1973" y2="933.1973"/><polygon fill="#000000" points="153,923.1973,157,933.1973,161,923.1973,157,927.1973" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="280" x2="280" y1="913.1973" y2="933.1973"/><polygon fill="#000000" points="276,923.1973,280,933.1973,284,923.1973,280,927.1973" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="398.5" x2="398.5" y1="913.1973" y2="933.1973"/><polygon fill="#000000" points="394.5,923.1973,398.5,933.1973,402.5,923.1973,398.5,927.1973" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="542" x2="542" y1="913.1973" y2="933.1973"/><polygon fill="#000000" points="538,923.1973,542,933.1973,546,923.1973,542,927.1973" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="356.5" x2="356.5" y1="803.918" y2="852.1035"/><polygon fill="#000000" points="352.5,842.1035,356.5,852.1035,360.5,842.1035,356.5,846.1035" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="344.5" x2="285.5" y1="983.1973" y2="983.1973"/><line style="stroke: #000000; stroke-width: 1.5;" x1="285.5" x2="285.5" y1="983.1973" y2="1015.1973"/><polygon fill="#000000" points="281.5,1005.1973,285.5,1015.1973,289.5,1005.1973,285.5,1009.1973" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="368.5" x2="428.5" y1="983.1973" y2="983.1973"/><line style="stroke: #000000; stroke-width: 1.5;" x1="428.5" x2="428.5" y1="983.1973" y2="1015.1973"/><polygon fill="#000000" points="424.5,1005.1973,428.5,1015.1973,432.5,1005.1973,428.5,1009.1973" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="285.5" x2="285.5" y1="1050.291" y2="1082.291"/><line style="stroke: #000000; stroke-width: 1.5;" x1="285.5" x2="344.5" y1="1082.291" y2="1082.291"/><polygon fill="#000000" points="334.5,1078.291,344.5,1082.291,334.5,1086.291,338.5,1082.291" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="428.5" x2="428.5" y1="1050.291" y2="1082.291"/><line style="stroke: #000000; stroke-width: 1.5;" x1="428.5" x2="368.5" y1="1082.291" y2="1082.291"/><polygon fill="#000000" points="378.5,1078.291,368.5,1082.291,378.5,1086.291,374.5,1082.291" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="356.5" x2="356.5" y1="995.1973" y2="1001.8639"/><line style="stroke: #000000; stroke-width: 1.5;" x1="356.5" x2="357.5" y1="1001.8639" y2="1001.8639"/><line style="stroke: #000000; stroke-width: 1.5;" x1="357.5" x2="357.5" y1="1001.8639" y2="1015.1973"/><polygon fill="#000000" points="353.5,1005.1973,357.5,1015.1973,361.5,1005.1973,357.5,1009.1973" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="357.5" x2="357.5" y1="1050.291" y2="1055.291"/><line style="stroke: #000000; stroke-width: 1.5;" x1="357.5" x2="356.5" y1="1055.291" y2="1055.291"/><line style="stroke: #000000; stroke-width: 1.5;" x1="356.5" x2="356.5" y1="1055.291" y2="1070.291"/><polygon fill="#000000" points="352.5,1060.291,356.5,1070.291,360.5,1060.291,356.5,1064.291" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="356.5" x2="356.5" y1="939.1973" y2="971.1973"/><polygon fill="#000000" points="352.5,961.1973,356.5,971.1973,360.5,961.1973,356.5,965.1973" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="356.5" x2="356.5" y1="1094.291" y2="1114.291"/><polygon fill="#000000" points="352.5,1104.291,356.5,1114.291,360.5,1104.291,356.5,1108.291" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="166.25" x2="45" y1="591.0273" y2="591.0273"/><line style="stroke: #000000; stroke-width: 1.5;" x1="45" x2="45" y1="591.0273" y2="613.0273"/><polygon fill="#000000" points="41,603.0273,45,613.0273,49,603.0273,45,607.0273" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="235.25" x2="356.5" y1="591.0273" y2="591.0273"/><line style="stroke: #000000; stroke-width: 1.5;" x1="356.5" x2="356.5" y1="591.0273" y2="616.832"/><polygon fill="#000000" points="352.5,606.832,356.5,616.832,360.5,606.832,356.5,610.832" style="stroke: #000000; stroke-width: 1.0;"/><line style="stroke: #000000; stroke-width: 1.5;" x1="200.75" x2="200.75" y1="547.0273" y2="579.0273"/><polygon fill="#000000" points="196.75,569.0273,200.75,579.0273,204.75,569.0273,200.75,573.0273" style="stroke: #000000; stroke-width: 1.0;"/><rect fill="#F6E4CC" height="195.125" rx="5" ry="5" style="stroke: #F6E4CC; stroke-width: 1.0;" width="390" x="375" y="1153.291"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="384" y="1172.748"/><text fill="#000000" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="0" x="499" y="1172.748"/><text fill="#000000" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="64" x="499" y="1187.8418">»frag.jetzt«</text><text fill="#000000" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacingAndGlyphs" textLength="0" x="499" y="1202.9355"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="59" x="384" y="1218.0293">Produktion</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="499" y="1218.0293"/><a href="https://frag.jetzt" target="_top" title="https://frag.jetzt" xlink:actuate="onRequest" xlink:href="https://frag.jetzt" xlink:show="new" xlink:title="https://frag.jetzt" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" text-decoration="underline" textLength="81" x="499" y="1218.0293">https://frag.jetzt</text></a><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="583" y="1218.0293"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="59" x="384" y="1233.123">Repository</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="499" y="1233.123"/><a href="https://git.thm.de/arsnova/frag.jetzt" target="_top" title="https://git.thm.de/arsnova/frag.jetzt" xlink:actuate="onRequest" xlink:href="https://git.thm.de/arsnova/frag.jetzt" xlink:show="new" xlink:title="https://git.thm.de/arsnova/frag.jetzt" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" text-decoration="underline" textLength="185" x="499" y="1233.123">https://git.thm.de/arsnova/frag.jetzt</text></a><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="687" y="1233.123"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="80" x="384" y="1248.2168">Staging Server</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="499" y="1248.2168"/><a href="https://staging.frag.jetzt" target="_top" title="https://staging.frag.jetzt" xlink:actuate="onRequest" xlink:href="https://staging.frag.jetzt" xlink:show="new" xlink:title="https://staging.frag.jetzt" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" text-decoration="underline" textLength="125" x="499" y="1248.2168">https://staging.frag.jetzt</text></a><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="0" x="627" y="1248.2168"/><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="53" x="384" y="1263.3105">UML-Tool</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="109" x="499" y="1263.3105">PlantUML v1.2021.5</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="46" x="384" y="1278.4043">Ersteller</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="260" x="499" y="1278.4043">Lauryn Lorna Monthe Djomeni, Aliye Tanriseven</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="109" x="384" y="1293.498">Vorherige Änderung</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="62" x="499" y="1293.498">18.06.2021</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="88" x="384" y="1308.5918">Letzte Änderung</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="62" x="499" y="1308.5918">20.06.2021</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="110" x="384" y="1323.6855">Letzte Änderung von</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="165" x="499" y="1323.6855">Lauryn Lorna Monthe Djomeni</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacingAndGlyphs" textLength="89" x="499" y="1338.7793">Aliye Tanriseven</text><line style="stroke: #000000; stroke-width: 1.0;" x1="381" x2="759" y1="1160.291" y2="1160.291"/><line style="stroke: #000000; stroke-width: 1.0;" x1="381" x2="759" y1="1205.5723" y2="1205.5723"/><line style="stroke: #000000; stroke-width: 1.0;" x1="381" x2="759" y1="1220.666" y2="1220.666"/><line style="stroke: #000000; stroke-width: 1.0;" x1="381" x2="759" y1="1235.7598" y2="1235.7598"/><line style="stroke: #000000; stroke-width: 1.0;" x1="381" x2="759" y1="1250.8535" y2="1250.8535"/><line style="stroke: #000000; stroke-width: 1.0;" x1="381" x2="759" y1="1265.9473" y2="1265.9473"/><line style="stroke: #000000; stroke-width: 1.0;" x1="381" x2="759" y1="1281.041" y2="1281.041"/><line style="stroke: #000000; stroke-width: 1.0;" x1="381" x2="759" y1="1296.1348" y2="1296.1348"/><line style="stroke: #000000; stroke-width: 1.0;" x1="381" x2="759" y1="1311.2285" y2="1311.2285"/><line style="stroke: #000000; stroke-width: 1.0;" x1="381" x2="759" y1="1341.416" y2="1341.416"/><line style="stroke: #000000; stroke-width: 1.0;" x1="381" x2="381" y1="1160.291" y2="1341.416"/><line style="stroke: #000000; stroke-width: 1.0;" x1="496" x2="496" y1="1160.291" y2="1341.416"/><line style="stroke: #000000; stroke-width: 1.0;" x1="759" x2="759" y1="1160.291" y2="1341.416"/><!--MD5=[1a5204f5a884029499e62fa05bc7ca92]
+@startuml
+partition Topic-Cloud #skyblue {
+skinparam backgroundColor #skyblue
+
+skinparam class{
+BackgroundColor Application
+BorderColor black
+ArrowColor black
+}
+
+skinparam BorderColor black
+skinparam ArrowColor black
+skinparam backgroundColor #powderblue
+skinparam backgroundColor Linen
+skinparam LegendBackgroundColor Strategy
+skinparam LegendBorderThickness 0
+skinparam LegendFontSize 12
+
+start
+if (decision ?) then
+ :create room;
+else
+ :enter room-code/name;
+endif
+
+ :click options;
+ :select topic-cloud;
+
+partition #powderblue select-list {
+switch ()
+case()
+ :continue with\ncomplete list\nof questions;
+case()
+ :continue with\n current filters;
+case()
+  :continue with\nall questions\n    from now;
+endswitch
+ :select option;
+}
+
+if (choose ?) then (cancel)
+-[#black]->
+end
+else (confirm "continue-button")
+:modify cloud-view;
+
+ floating note right:edit your own topic-cloud\n         or demo-cloud
+switch ()
+case()
+ :    activate\ndemo-cloud;
+case()
+ :  deactivate\ndemo-cloud;
+endswitch
+
+partition #powderblue edit-cloud {
+fork
+:general options;
+
+fork again
+:font options;
+
+fork again
+: hover options;
+
+fork again
+:weight-class options;
+end fork
+floating note right:options for weight\n classes 1 to 10
+
+}
+switch ()
+case()
+ :reset;
+case()
+ :cancel;
+case()
+ :save;
+endswitch
+end
+
+legend right
+  | |= \n »frag.jetzt« \n|
+  | Produktion | [[https://frag.jetzt]] |
+  | Repository | [[https://git.thm.de/arsnova/frag.jetzt]] |
+  | Staging Server | [[https://staging.frag.jetzt]] |
+  | UML-Tool| PlantUML v1.2021.5|
+  | Ersteller| Lauryn Lorna Monthe Djomeni, Aliye Tanriseven|
+  | Vorherige Änderung | 18.06.2021 |
+  | Letzte Änderung| 20.06.2021 |
+  | Letzte Änderung von| Lauryn Lorna Monthe Djomeni\n Aliye Tanriseven |
+end legend
+
+
+@enduml
+
+PlantUML version 1.2020.03beta6(Unknown compile time)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: OpenJDK 64-Bit Server VM
+Java Version: 11.0.4+10-b304.69
+Operating System: Windows 10
+Default Encoding: Cp1252
+Language: de
+Country: DE
+--></g></svg>
\ No newline at end of file
diff --git a/docs/diagrams/UX-Diagrams/use_case_Diagram.puml b/docs/diagrams/UX-Diagrams/use_case_Diagram.puml
new file mode 100644
index 0000000000000000000000000000000000000000..cdf7d93ec455b02c07e419280d9e354308c4e73f
--- /dev/null
+++ b/docs/diagrams/UX-Diagrams/use_case_Diagram.puml
@@ -0,0 +1,131 @@
+@startuml
+
+scale 1.0
+
+left to right direction
+
+skinparam backgroundColor Linen
+skinparam LegendBackgroundColor Strategy
+skinparam LegendBorderThickness 0
+skinparam LegendFontSize 20
+skinparam Padding 5
+skinparam defaultFontSize 24
+skinparam Nodesep 100
+skinparam ArrowThickness 2
+skinparam shadowing true
+
+skinparam usecase {
+    BackgroundColor PaleGreen
+    BorderColor Green
+    BackgroundColor<<USP>> Pink
+    BorderColor<<USP>> HotPink
+    BorderThickness 2
+    ArrowThickness 2
+    ArrowColor Green
+    ActorBorderColor Green
+}
+
+actor Lecturer
+actor Student
+actor Moderator
+
+note "If a lecturer is registered and logs in with her account, \nher sessions remain stored for 180 days after the last visit, \notherwise they are deleted when she logs out." as NoteForCreateSession
+note "Registered students can receive a bonus \nfor particularly interesting questions." as NoteForJoinSessionAsStudent
+note "as another option we have general, fond, hover and \nweight-classes that apply to the sight of the cloud " as NoteForDemoCloud
+note "it is possible to choose the language for the spelling." as NoteForSpellCheck
+
+rectangle "frag.jetzt | use-case diagram \n" << Business >> {
+
+    (Create session) --- NoteForCreateSession
+    (Join session as student) --- NoteForJoinSessionAsStudent
+    (Demo cloud) --- NoteForDemoCloud
+    (My cloud) - NoteForDemoCloud
+    (Spell check) -- NoteForSpellCheck
+
+    Lecturer -- (Create session)
+    (Evaluate questions) <.. (Delete question) : << extend >>
+    Student-- (Join session as student)
+    Moderator ---- (Join session as Moderator)
+    (Join session as Moderator)<..(Moderate questions): << extend >>
+    (Create session) <.. (Question wall) : << extend >>
+    (Create session) <.. (Question wall) : << extend >>
+    (Create session) <.. (Edit session) : << extend >>
+    (Create session) <.. (Evaluate questions) : << extend >>
+    (Create session) <.. (Assign moderator to session) : << extend >>
+    (Create session) <.. (Create question tag) : << extend >>
+    (Create session) <.. (Export questions) : << extend >>
+    (Create session) <.. (Ask question) : << extend >>
+    (Create session) <.. (Rate questions) : << extend >>
+    (Create session) <.. (Redeem bonus token) : << extend >>
+    (Create session) <.. (Evaluate questions) : << extend >>
+    (Create session) <.. (Block question) : << extend >>
+    (Create session) <.. (Add keyword) : << extend >>
+    (Create session) <.. (Topic cloud) : << extend >>
+    (Create session) <.. (Question focus) : << extend >>
+
+
+    (Moderate questions) <.. (Ban question) : << extend >>
+    (Evaluate questions) <.. (Ban question) : << extend >>
+    (Join session as student) <.. (Question wall) : << extend >>
+    (Join session as student) <.. (Ask question) : << extend >>
+    (Join session as student) <.. (Vote up question) : << extend >>
+    (Join session as student) <.. (Vote down question) : << extend >>
+    (Join session as student) <.. (Export questions) : << extend >>
+    (Join session as student) <.. (Add keyword) : << extend >>
+    (Join session as student) <.. (Topic cloud) : << extend >>
+    (Join session as student) <.. (Question focus) : << extend >>
+
+
+
+    (Join session as Moderator) <.. (Ask question) : << extend >>
+    (Join session as Moderator) <.. (Block question) : << extend >>
+    (Join session as Moderator) <.. (Rate questions) : << extend >>
+    (Join session as Moderator) <.. (Export questions) : << extend >>
+    (Join session as Moderator) <.. (Add keyword) : << extend >>
+    (Join session as Moderator) <.. (Question wall) : << extend >>
+    (Join session as Moderator) <.. (Topic cloud) : << extend >>
+    (Join session as Moderator) <.. (Question focus) : << extend >>
+    (Ask question) <.. (Spell check) : << extend >>
+    (Ask question) <.. (Add keyword) : << extend >>
+    (Ask question) <.. (Publish question) : << extend >>
+    (Create check) <.. (Correct Spelling) : << extend >>
+
+    (Question wall) <.. (Filter) : << extend >>
+    (Evaluate questions) <.. (Tag) : << extend >>
+    (Evaluate questions) <.. (Delete) : << extend >>
+    (Evaluate questions) <.. (Mark as wrong) : << extend >>
+    (Evaluate questions) <.. (Mark as true) : << extend >>
+    (Evaluate questions) <.. (Republish) : << extend >>
+    (Evaluate questions) <.. (Answer) : << extend >>
+    (Evaluate questions) <.. (Star) : << extend >>
+    (Evaluate questions) <.. (Ban question) : << extend >>
+    (Topic cloud) <.. (Edit topic cloud) : << extend >>
+    (Topic cloud) <.. (Edit cloud view) : << extend >>
+    (Edit cloud view) <.. (My cloud) : << extend >>
+    (Edit cloud view) <.. (Demo cloud) : << extend >>
+    (Topic cloud) <.. (Correct a key word) : << extend >>
+    (Moderate questions) <.. (Tag) : << extend >>
+    (Moderate questions) <.. (Bookmark) : << extend >>
+    (Moderate questions) <.. (Delete) : << extend >>
+    (Moderate questions) <.. (Mark as wrong) : << extend >>
+    (Moderate questions) <.. (Mark as true) : << extend >>
+    (Moderate questions) <.. (Republish) : << extend >>
+    (Moderate questions) <.. (Answer) : << extend >>
+    (Moderate questions) <.. (Star) : << extend >>
+    (Moderate questions) <.. (Ban question) : << extend >>
+    (Moderate questions) <.. (Bookmark) : << extend >>
+    (Question focus) <.. (Filter) : << extend >>
+
+}
+
+legend right
+  |<img:https://git.thm.de/arsnova/arsnova-lite/raw/staging/src/assets/icons/Logo_frag_jetzt_128x128.png> |= \n\n »frag.jetzt« |
+  | Produktion | [[https://frag.jetzt]] |
+  | Repository | [[https://git.thm.de/arsnova/frag.jetzt]] |
+  | Staging Server | [[https://staging.frag.jetzt]] |
+  | UML-Tool| PlantUML v5.5.1|
+  | Ersteller| Kevin Piam , Franck Mezatio |
+  | Letzte Änderung| 20.06.2021 |
+end legend
+
+@enduml
\ No newline at end of file
diff --git a/docs/diagrams/UX-Diagrams/use_case_Diagram.svg b/docs/diagrams/UX-Diagrams/use_case_Diagram.svg
new file mode 100644
index 0000000000000000000000000000000000000000..9493c858886eda922eef195d645788ec98425349
--- /dev/null
+++ b/docs/diagrams/UX-Diagrams/use_case_Diagram.svg
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="6499.2px" preserveAspectRatio="none" style="width:4380px;height:6499px;background:#FAF0E6;" version="1.1" viewBox="0 0 4380 6499" width="4380px" zoomAndPan="magnify"><defs><filter height="300%" id="f1n2jmhqch82o3" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.4"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.8" dy="4.8" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><!--MD5=[99d0713b2e5d7da82e17adab78c10e4b]
+cluster frag.jetzt | use-case diagram \n--><rect fill="#FAF0E6" filter="url(#f1n2jmhqch82o3)" height="5485.2" style="stroke:#000000;stroke-width:1.7999999999999998;" width="2841" x="464.4" y="8.4"/><text fill="#000000" font-family="sans-serif" font-size="28.8" font-style="italic" lengthAdjust="spacing" textLength="147.6" x="1811.1" y="46.6969">«Business»</text><text fill="#000000" font-family="sans-serif" font-size="28.8" font-weight="bold" lengthAdjust="spacing" textLength="386.4" x="1687.5" y="94.9219">frag.jetzt | use-case diagram</text><text fill="#000000" font-family="sans-serif" font-size="28.8" font-weight="bold" lengthAdjust="spacing" textLength="0" x="1889.1" y="131.1469"/><ellipse cx="704.3836" cy="1889.9002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="157.1836" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="190.8" x="608.9836" y="1899.2846">Create session</text><ellipse cx="704.2693" cy="4719.5739" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="207.4693" ry="44.3739" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="302.4" x="553.0693" y="4728.9582">Join session as student</text><ellipse cx="3153.9277" cy="4732.7002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="131.7277" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="154.8" x="3076.5277" y="4742.0846">Demo cloud</text><ellipse cx="3154.3748" cy="4510.7002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="104.5748" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="116.4" x="3096.1748" y="4520.0846">My cloud</text><ellipse cx="2195.3336" cy="4819.1002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="128.3336" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="150" x="2120.3336" y="4828.4846">Spell check</text><ellipse cx="1362.2461" cy="1812.2892" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="185.0461" ry="39.8892" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="244.8" x="1239.8461" y="1821.6736">Evaluate questions</text><ellipse cx="2195.2203" cy="566.3002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="164.8203" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="201.6" x="2094.4203" y="575.6846">Delete question</text><ellipse cx="704.3444" cy="3486.2289" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="220.7444" ry="47.0289" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="334.8" x="536.9444" y="3495.6132">Join session as Moderator</text><ellipse cx="1361.8059" cy="2772.9212" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="188.2059" ry="40.5212" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="253.2" x="1235.2059" y="2782.3056">Moderate questions</text><ellipse cx="1361.7527" cy="1095.5002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="146.1527" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="175.2" x="1274.1527" y="1104.8846">Question wall</text><ellipse cx="1361.9763" cy="825.5002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="132.5763" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="156" x="1283.9763" y="834.8846">Edit session</text><ellipse cx="1362.0604" cy="618.2521" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="232.8604" ry="49.4521" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="363.6" x="1180.2604" y="627.6364">Assign moderator to session</text><ellipse cx="1361.8059" cy="407.7212" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="188.2059" ry="40.5212" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="253.2" x="1235.2059" y="417.1056">Create question tag</text><ellipse cx="1361.9525" cy="4259.9905" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="174.5525" ry="37.7905" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="216" x="1253.9525" y="4269.3749">Export questions</text><ellipse cx="1362.1645" cy="4064.3002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="139.3645" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="165.6" x="1279.3645" y="4073.6846">Ask question</text><ellipse cx="1361.8806" cy="2416.7002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="158.8806" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="193.2" x="1265.2806" y="2426.0846">Rate questions</text><ellipse cx="1362.1824" cy="205.4765" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="196.9824" ry="42.2765" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="276" x="1224.1824" y="214.8609">Redeem bonus token</text><ellipse cx="1361.7351" cy="3745.1002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="156.3351" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="189.6" x="1266.9351" y="3754.4846">Block question</text><ellipse cx="2195.213" cy="5248.7002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="140.213" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="166.8" x="2111.813" y="5258.0846">Add keyword</text><ellipse cx="1362.2851" cy="3231.5002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="127.4851" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="148.8" x="1287.8851" y="3240.8846">Topic cloud</text><ellipse cx="1362.1292" cy="1613.9002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="159.7292" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="194.4" x="1264.9292" y="1623.2846">Question focus</text><ellipse cx="2195.3586" cy="1095.5002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="142.7586" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="170.4" x="2110.1586" y="1104.8846">Ban question</text><ellipse cx="1362.2053" cy="4747.3611" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="175.4053" ry="37.9611" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="218.4" x="1253.0053" y="4756.7454">Vote up question</text><ellipse cx="1362.2607" cy="4946.2121" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="188.6607" ry="40.6121" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="254.4" x="1235.0607" y="4955.5965">Vote down question</text><ellipse cx="2195.3525" cy="5014.7905" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="174.5525" ry="37.7905" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="216" x="2087.3525" y="5024.1749">Publish question</text><ellipse cx="704.1101" cy="5354.3002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="141.9101" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="169.2" x="619.5101" y="5363.6846">Create check</text><ellipse cx="1361.863" cy="5435.9002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="169.063" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="207.6" x="1258.063" y="5445.2846">Correct Spelling</text><ellipse cx="2195.6881" cy="292.7002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="68.0881" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="64.8" x="2163.2881" y="302.0846">Filter</text><ellipse cx="2195.4573" cy="2157.5002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="57.0573" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="49.2" x="2170.8573" y="2166.8846">Tag</text><ellipse cx="2195.2161" cy="3880.7002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="80.8161" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="82.8" x="2153.8161" y="3890.0846">Delete</text><ellipse cx="2195.4865" cy="3485.9002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="155.4865" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="188.4" x="2101.2865" y="3495.2846">Mark as wrong</text><ellipse cx="2195.5219" cy="2402.3002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="135.1219" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="159.6" x="2115.7219" y="2411.6846">Mark as true</text><ellipse cx="2195.5572" cy="1936.7002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="114.7572" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="130.8" x="2130.1572" y="1946.0846">Republish</text><ellipse cx="2195.3013" cy="1729.1002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="89.3013" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="94.8" x="2147.9013" y="1738.4846">Answer</text><ellipse cx="2195.6029" cy="3221.9002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="59.6029" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="52.8" x="2169.2029" y="3231.2846">Star</text><ellipse cx="2195.3233" cy="2859.5002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="163.1233" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="199.2" x="2095.7233" y="2868.8846">Edit topic cloud</text><ellipse cx="2195.2806" cy="4623.5002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="158.8806" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="193.2" x="2098.6806" y="4632.8846">Edit cloud view</text><ellipse cx="2195.5048" cy="4425.621" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="183.7048" ry="39.621" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="241.2" x="2074.9048" y="4435.0053">Correct a key word</text><ellipse cx="2195.6601" cy="4132.7002" fill="#98FB98" filter="url(#f1n2jmhqch82o3)" rx="113.0601" ry="37.7002" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="128.4" x="2131.4601" y="4142.0846">Bookmark</text><!--MD5=[9642be9e27d3356614e146876c7fe741]
+entity Lecturer--><ellipse cx="349.2" cy="1838.4" fill="#FEFECE" filter="url(#f1n2jmhqch82o3)" rx="9.6" ry="9.6" style="stroke:#A80036;stroke-width:1.7999999999999998;"/><path d="M349.2,1848 L349.2,1880.4 M333.6,1857.6 L364.8,1857.6 M349.2,1880.4 L333.6,1898.4 M349.2,1880.4 L364.8,1898.4 " fill="none" filter="url(#f1n2jmhqch82o3)" style="stroke:#A80036;stroke-width:1.7999999999999998;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="105.6" x="296.4" y="1940.8969">Lecturer</text><!--MD5=[494c489cc4328319247ec2e1625e02a3]
+entity Student--><ellipse cx="349.2" cy="3928.8" fill="#FEFECE" filter="url(#f1n2jmhqch82o3)" rx="9.6" ry="9.6" style="stroke:#A80036;stroke-width:1.7999999999999998;"/><path d="M349.2,3938.4 L349.2,3970.8 M333.6,3948 L364.8,3948 M349.2,3970.8 L333.6,3988.8 M349.2,3970.8 L364.8,3988.8 " fill="none" filter="url(#f1n2jmhqch82o3)" style="stroke:#A80036;stroke-width:1.7999999999999998;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="102" x="298.2" y="4031.2969">Student</text><!--MD5=[751c087365caa72459e8e7ad1438504b]
+entity Moderator--><ellipse cx="72" cy="4173.6" fill="#FEFECE" filter="url(#f1n2jmhqch82o3)" rx="9.6" ry="9.6" style="stroke:#A80036;stroke-width:1.7999999999999998;"/><path d="M72,4183.2 L72,4215.6 M56.4,4192.8 L87.6,4192.8 M72,4215.6 L56.4,4233.6 M72,4215.6 L87.6,4233.6 " fill="none" filter="url(#f1n2jmhqch82o3)" style="stroke:#A80036;stroke-width:1.7999999999999998;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="129.6" x="7.2" y="4276.0969">Moderator</text><path d="M1798.8,5589 L1798.8,5721.675 L2592,5721.675 L2592,5601 L2580,5589 L1798.8,5589 " fill="#FBFB77" filter="url(#f1n2jmhqch82o3)" style="stroke:#A80036;stroke-width:1.2;"/><path d="M2580,5589 L2580,5601 L2592,5601 L2580,5589 " fill="#FBFB77" style="stroke:#A80036;stroke-width:1.2;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="691.2" x="1812" y="5630.8969">If a lecturer is registered and logs in with her account,</text><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="747.6" x="1812" y="5667.1219">her sessions remain stored for 180 days after the last visit,</text><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="592.8" x="1812" y="5703.3469">otherwise they are deleted when she logs out.</text><path d="M1909.8,5850 L1909.8,5946.45 L2481,5946.45 L2481,5862 L2469,5850 L1909.8,5850 " fill="#FBFB77" filter="url(#f1n2jmhqch82o3)" style="stroke:#A80036;stroke-width:1.2;"/><path d="M2469,5850 L2469,5862 L2481,5862 L2469,5850 " fill="#FBFB77" style="stroke:#A80036;stroke-width:1.2;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="525.6" x="1923" y="5891.8969">Registered students can receive a bonus</text><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="468" x="1923" y="5928.1219">for particularly interesting questions.</text><path d="M3660,4567.2 L3660,4663.65 L4369.2,4663.65 L4369.2,4579.2 L4357.2,4567.2 L3660,4567.2 " fill="#FBFB77" filter="url(#f1n2jmhqch82o3)" style="stroke:#A80036;stroke-width:1.2;"/><path d="M4357.2,4567.2 L4357.2,4579.2 L4369.2,4579.2 L4357.2,4567.2 " fill="#FBFB77" style="stroke:#A80036;stroke-width:1.2;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="663.6" x="3673.2" y="4609.0969">as another option we have general, fond, hover and</text><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="639.6" x="3673.2" y="4645.3219">weight-classes that apply to the sight of the cloud</text><path d="M2796,5512.8 L2796,5573.025 L3512.4,5573.025 L3512.4,5524.8 L3500.4,5512.8 L2796,5512.8 " fill="#FBFB77" filter="url(#f1n2jmhqch82o3)" style="stroke:#A80036;stroke-width:1.2;"/><path d="M3500.4,5512.8 L3500.4,5524.8 L3512.4,5524.8 L3500.4,5512.8 " fill="#FBFB77" style="stroke:#A80036;stroke-width:1.2;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="679.2" x="2809.2" y="5554.6969">it is possible to choose the language for the spelling.</text><!--MD5=[f33f0083b43779a952bb31043b621586]
+link Create session to NoteForCreateSession--><path d="M713.004,1927.764 C745.68,2096.316 877.38,2797.068 925.2,3379.2 C934.548,3492.972 904.092,5334.768 961.2,5433.6 C1120.752,5709.732 1502.016,5742.384 1798.68,5719.872 " fill="none" id="Create session-NoteForCreateSession" style="stroke:#008000;stroke-width:2.4;"/><!--MD5=[86135eae7f0ef83d4a67a5c98d2267dc]
+link Join session as student to NoteForJoinSessionAsStudent--><path d="M729.42,4763.916 C776.388,4853.748 880.296,5064.984 925.2,5256 C937.716,5309.232 923.496,5707.2 961.2,5746.8 C1218.132,6016.596 1689.768,5991.12 1969.344,5946.024 " fill="none" id="Join session as student-NoteForJoinSessionAsStudent" style="stroke:#008000;stroke-width:2.4;"/><!--MD5=[ad0b8c35b57c581c1b35766c2e314aa1]
+link Demo cloud to NoteForDemoCloud--><path d="M3273.804,4716.576 C3374.472,4702.776 3524.34,4682.232 3662.904,4663.248 " fill="none" id="Demo cloud-NoteForDemoCloud" style="stroke:#008000;stroke-width:2.4;"/><!--MD5=[3ff120ab0755ed136b02c02ad4f66e97]
+link My cloud to NoteForDemoCloud--><path d="M3253.404,4522.728 C3352.776,4534.824 3512.496,4554.252 3659.928,4572.192 " fill="none" id="My cloud-NoteForDemoCloud" style="stroke:#008000;stroke-width:2.4;"/><!--MD5=[5a69e9bd5369e276eb7cfe45f53ab9ef]
+link Spell check to NoteForSpellCheck--><path d="M2323.872,4820.076 C2409.492,4827.276 2519.568,4850.28 2592,4916.4 C2797.404,5103.912 2577.648,5335.74 2796,5508 C2798.076,5509.644 2800.188,5511.24 2802.324,5512.788 " fill="none" id="Spell check-NoteForSpellCheck" style="stroke:#008000;stroke-width:2.4;"/><!--MD5=[869ec2c1f0f4b3f7f156fd9f5e4df075]
+link Lecturer to Create session--><path d="M408.264,1890 C446.184,1890 497.712,1890 547.092,1890 " fill="none" id="Lecturer-Create session" style="stroke:#008000;stroke-width:2.4;"/><!--MD5=[e87a5f6d19689700d165899c8f873056]
+reverse link Evaluate questions to Delete question--><path d="M1498.98,1781.676 C1535.988,1766.664 1572.096,1744.344 1594.8,1711.2 C1650,1630.62 1576.86,914.244 1630.8,832.8 C1727.664,686.556 1927.8,618.708 2061.564,588.6 " fill="none" id="Evaluate questions-backto-Delete question" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1493.028,1784.028,1504.837,1784.505,1498.6048,1781.8145,1501.2953,1775.5822,1493.028,1784.028" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="694.6969">«extend»</text><!--MD5=[5522a805a19e2ea4957daad1d6e2f58e]
+link Student to Join session as student--><path d="M380.484,4043.424 C450.3,4189.716 621.972,4549.416 682.032,4675.26 " fill="none" id="Student-Join session as student" style="stroke:#008000;stroke-width:2.4;"/><!--MD5=[a216af25aa7a477935349f5497f4b499]
+link Moderator to Join session as Moderator--><path d="M143.076,4215.516 C216.96,4201.992 332.988,4170.948 408,4102.8 C586.596,3940.56 667.68,3647.136 693.516,3533.112 " fill="none" id="Moderator-Join session as Moderator" style="stroke:#008000;stroke-width:2.4;"/><!--MD5=[c06fc347e8c6987d7f6419dcb86f1933]
+reverse link Join session as Moderator to Moderate questions--><path d="M707.604,3433.128 C715.704,3302.364 756.432,2963.208 961.2,2808 C1030.152,2755.74 1126.308,2746.008 1207.008,2749.836 " fill="none" id="Join session as Moderator-backto-Moderate questions" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="707.244,3439.2,712.6822,3428.7069,707.6034,3433.2108,703.0995,3428.1319,707.244,3439.2" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="2743.0969">«extend»</text><!--MD5=[7dfe2385d2633f8f8a3d5420420b59a9]
+reverse link Create session to Question wall--><path d="M711.96,1846.092 C736.032,1686.828 826.956,1143.684 961.2,1044 C1059.768,970.812 1210.992,1022.22 1296.348,1061.796 " fill="none" id="Create session-backto-Question wall" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="711.072,1852.044,717.4238,1842.0773,711.9637,1846.1106,707.9304,1840.6506,711.072,1852.044" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="994.6969">«extend»</text><!--MD5=[7dfe2385d2633f8f8a3d5420420b59a9]
+reverse link Create session to Question wall--><path d="M709.428,1845.684 C722.088,1726.656 773.256,1397.052 961.2,1220.4 C1032.168,1153.704 1138.32,1122.636 1223.388,1108.176 " fill="none" id="Create session-backto-Question wall-1" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="708.78,1851.876,714.6949,1841.644,709.4144,1845.9096,705.1487,1840.629,708.78,1851.876" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="1132.6969">«extend»</text><!--MD5=[125dbe06e7289af99acfb6915be233ef]
+reverse link Create session to Edit session--><path d="M711.432,1845.444 C734.7,1674.18 826.284,1061.22 961.2,927.6 C1031.4,858.072 1142.04,833.868 1229.112,826.32 " fill="none" id="Create session-backto-Edit session" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="710.568,1851.828,716.7742,1841.77,711.3733,1845.8823,707.261,1840.4815,710.568,1851.828" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="842.2969">«extend»</text><!--MD5=[a908750067da40d8d99027ad74c6bc3f]
+reverse link Create session to Evaluate questions--><path d="M851.892,1872.588 C955.224,1860.288 1093.704,1843.8 1200.12,1831.128 " fill="none" id="Create session-backto-Evaluate questions" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="845.76,1873.32,857.0585,1876.7875,851.7165,1872.599,855.905,1867.257,845.76,1873.32" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="1831.0969">«extend»</text><!--MD5=[a908750067da40d8d99027ad74c6bc3f]
+reverse link Create session to Evaluate questions--><path d="M806.16,1921.74 C884.94,1942.068 996.948,1960.908 1093.2,1939.2 C1169.22,1922.052 1248.984,1880.652 1301.436,1849.716 " fill="none" id="Create session-backto-Evaluate questions-1" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="800.064,1920.156,809.3062,1927.5223,805.8704,1921.6677,811.725,1918.232,800.064,1920.156" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="1925.8969">«extend»</text><!--MD5=[0b0e7a1c01aea1e1d139ec993a23d908]
+reverse link Create session to Assign moderator to session--><path d="M710.292,1845.372 C730.704,1658.664 817.344,942.336 961.2,775.2 C1017.252,710.088 1103.82,671.736 1182.072,649.248 " fill="none" id="Create session-backto-Assign moderator to session" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="709.584,1851.78,715.528,1841.5649,710.2353,1845.8155,705.9847,1840.5228,709.584,1851.78" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="669.4969">«extend»</text><!--MD5=[1124252c85a8ce6300d05156e60b9541]
+reverse link Create session to Create question tag--><path d="M709.44,1845.54 C727.632,1643.064 810.684,809.172 961.2,602.4 C1025.22,514.452 1139.94,464.412 1230.096,437.208 " fill="none" id="Create session-backto-Create question tag" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="708.864,1851.912,714.6301,1841.5954,709.4118,1845.9371,705.0702,1840.7188,708.864,1851.912" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="483.4969">«extend»</text><!--MD5=[4ad2529de28aae003702c093f8566999]
+reverse link Create session to Export questions--><path d="M713.628,1933.956 C746.004,2112.972 867.936,2804.808 925.2,3379.2 C932.784,3455.328 920.904,4001.772 961.2,4066.8 C1019.232,4160.472 1137.12,4209.78 1229.88,4235.052 " fill="none" id="Create session-backto-Export questions" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="712.512,1927.812,709.6979,1939.2907,713.5733,1933.7174,719.1466,1937.5927,712.512,1927.812" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="4053.4969">«extend»</text><!--MD5=[44237e1e472c9a5c0032c80bc2f30a4e]
+reverse link Create session to Ask question--><path d="M713.316,1933.992 C744.48,2113.128 862.392,2805.384 925.2,3379.2 C931.284,3434.748 929.376,3834.876 961.2,3880.8 C1026.096,3974.472 1151.136,4021.32 1244.148,4044.108 " fill="none" id="Create session-backto-Ask question" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="712.248,1927.836,709.3695,1939.2987,713.276,1933.7473,718.8275,1937.6538,712.248,1927.836" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="3867.4969">«extend»</text><!--MD5=[4399433989adc063c46f824f374c14fc]
+reverse link Create session to Rate questions--><path d="M755.664,1930.248 C879.18,2029.56 1197.036,2285.136 1315.452,2380.344 " fill="none" id="Create session-backto-Rate questions" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="750.636,1926.216,756.038,1936.7278,755.3095,1929.9788,762.0585,1929.2503,750.636,1926.216" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="2093.8969">«extend»</text><!--MD5=[8c78ac721df487ac7657fed4f724648b]
+reverse link Create session to Redeem bonus token--><path d="M708.552,1845.636 C723.792,1626.66 799.284,661.884 961.2,416.4 C1023.312,322.236 1141.668,267.24 1233.516,237.096 " fill="none" id="Create session-backto-Redeem bonus token" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="708.108,1851.888,713.6356,1841.4417,708.5185,1845.9021,704.0581,1840.7849,708.108,1851.888" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="290.2969">«extend»</text><!--MD5=[c3905e30a1ce7722937daa733770d691]
+reverse link Create session to Block question--><path d="M708.444,1933.896 C723.528,2156.964 799.752,3164.688 961.2,3426 C999.324,3487.716 1048.524,3464.856 1093.2,3522 C1119.432,3555.552 1101.276,3578.652 1129.2,3610.8 C1169.124,3656.784 1228.836,3690.9 1277.628,3713.256 " fill="none" id="Create session-backto-Block question" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="708.036,1927.836,703.9566,1938.9283,708.4306,1933.823,713.5358,1938.297,708.036,1927.836" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="3412.6969">«extend»</text><!--MD5=[2dbc4004fe298cc52ce876eaf0817492]
+reverse link Create session to Add keyword--><path d="M709.224,1934.196 C725.472,2120.532 798,2838.912 961.2,2980.8 C983.424,3000.132 1072.344,2972.004 1093.2,2992.8 C1154.244,3053.712 1082.592,3306.648 1129.2,3379.2 C1258.2,3580.008 1472.352,3441.924 1594.8,3646.8 C1631.1,3707.544 1582.584,4868.208 1630.8,4920 C1650.888,4941.576 1740.948,4913.412 1762.8,4933.2 C1822.884,4987.62 1745.46,5050.968 1798.8,5112 C1864.884,5187.624 1974.9,5221.464 2062.14,5236.596 " fill="none" id="Create session-backto-Add keyword" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="708.672,1927.8,704.8173,1938.9724,709.1873,1933.7778,714.3819,1938.1478,708.672,1927.8" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1303.2" y="3365.8969">«extend»</text><!--MD5=[06701f1b41ec9b72785ef3384361a8fe]
+reverse link Create session to Topic cloud--><path d="M706.56,1934.532 C711.78,2083.116 745.356,2570.4 961.2,2888.4 C1001.94,2948.424 1037.124,2938.38 1093.2,2984.4 C1179.492,3055.224 1273.992,3145.896 1324.368,3195.384 " fill="none" id="Create session-backto-Topic cloud" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="706.344,1928.136,701.8856,1939.0815,706.5325,1934.133,711.4809,1938.7799,706.344,1928.136" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="2875.0969">«extend»</text><!--MD5=[5589d91c572eb6b4fbe3f8e855f40439]
+reverse link Create session to Question focus--><path d="M776.436,1852.728 C827.256,1826.568 897.684,1791.504 961.2,1764 C1065.756,1718.736 1188.864,1673.736 1270.512,1645.008 " fill="none" id="Create session-backto-Question focus" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="770.964,1855.548,782.7635,1854.8755,776.2993,1852.8031,778.3717,1846.339,770.964,1855.548" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="1697.8969">«extend»</text><!--MD5=[596368ba3f9b5cfa7f2506d9fd6c1d65]
+reverse link Moderate questions to Ban question--><path d="M1419.516,2730.156 C1475.388,2683.704 1557.864,2604.168 1594.8,2514 C1657.356,2361.324 1560.036,1921.452 1630.8,1772.4 C1664.652,1701.096 1709.112,1711.452 1762.8,1653.6 C1932.504,1470.72 2105.352,1225.476 2168.832,1132.992 " fill="none" id="Moderate questions-backto-Ban question" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1414.86,2733.984,1426.2507,2730.8325,1419.4946,2730.1734,1420.1537,2723.4172,1414.86,2733.984" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="1640.2969">«extend»</text><!--MD5=[596368ba3f9b5cfa7f2506d9fd6c1d65]
+reverse link Moderate questions to Ban question--><path d="M1420.284,2729.832 C1476.36,2683.416 1558.608,2604.156 1594.8,2514 C1638.24,2405.796 1573.644,1566.84 1630.8,1465.2 C1734.444,1280.904 1972.596,1172.604 2103.648,1124.856 " fill="none" id="Moderate questions-backto-Ban question-1" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1415.616,2733.672,1427.0124,2730.5412,1420.2575,2729.8698,1420.9288,2723.1148,1415.616,2733.672" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="1301.8969">«extend»</text><!--MD5=[6e7365dc6184bc23c1299532b8869c27]
+reverse link Evaluate questions to Ban question--><path d="M1498.296,1781.52 C1535.388,1766.496 1571.712,1744.2 1594.8,1711.2 C1670.748,1602.624 1535.976,1208.556 1630.8,1116 C1755.648,994.14 1979.784,1032.084 2104.416,1066.38 " fill="none" id="Evaluate questions-backto-Ban question" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1492.332,1783.872,1504.141,1784.349,1497.9088,1781.6585,1500.5993,1775.4262,1492.332,1783.872" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="1034.2969">«extend»</text><!--MD5=[6e7365dc6184bc23c1299532b8869c27]
+reverse link Evaluate questions to Ban question--><path d="M1498.824,1781.58 C1535.832,1766.556 1571.976,1744.26 1594.8,1711.2 C1641.828,1643.1 1570.884,1024.296 1630.8,967.2 C1776.06,828.804 2038.224,985.02 2145.972,1059.984 " fill="none" id="Evaluate questions-backto-Ban question-1" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1492.884,1783.92,1504.6911,1784.4408,1498.4689,1781.7271,1501.1826,1775.5049,1492.884,1783.92" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="899.8969">«extend»</text><!--MD5=[6983eac9236702cca9e67c6a17c77c73]
+reverse link Join session as student to Question wall--><path d="M718.74,4669.032 C759.012,4511.256 880.692,4013.52 925.2,3592.8 C936.672,3484.392 922.38,1732.668 961.2,1630.8 C993.252,1546.692 1037.964,1548.264 1093.2,1477.2 C1188.048,1355.184 1290.324,1202.82 1336.152,1133.316 " fill="none" id="Join session as student-backto-Question wall" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="717.228,4674.948,724.562,4665.6802,718.7195,4669.1363,715.2633,4663.2938,717.228,4674.948" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="1463.8969">«extend»</text><!--MD5=[7a8249f42ba6261bb0a479119a0bcc7b]
+reverse link Join session as student to Ask question--><path d="M906.36,4734.012 C974.988,4727.94 1046.196,4707.432 1093.2,4656 C1167.516,4574.688 1064.916,4251.06 1129.2,4161.6 C1156.872,4123.092 1202.832,4099.764 1246.536,4085.664 " fill="none" id="Join session as student-backto-Ask question" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="900.156,4734.528,911.3173,4738.4145,906.1353,4734.0297,910.5201,4728.8477,900.156,4734.528" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="4642.6969">«extend»</text><!--MD5=[285bb0fe55dcc5bc472019e1e5f96d3d]
+reverse link Join session as student to Vote up question--><path d="M730.464,4769.4 C768.852,4839.948 849.912,4966.08 961.2,5017.2 C1014.516,5041.692 1047.66,5054.184 1093.2,5017.2 C1153.692,4968.084 1079.724,4905.804 1129.2,4845.6 C1157.148,4811.592 1198.968,4789.116 1239.408,4774.356 " fill="none" id="Join session as student-backto-Vote up question" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="727.56,4764,728.4882,4775.7821,730.4199,4769.2746,736.9275,4771.2063,727.56,4764" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="5003.8969">«extend»</text><!--MD5=[a60b1979f222d1c8f6b64f05ea1f4dfd]
+reverse link Join session as student to Vote down question--><path d="M719.976,4769.748 C748.752,4859.58 822.876,5045.64 961.2,5121.6 C1012.62,5149.848 1040.244,5146.848 1093.2,5121.6 C1116.132,5110.668 1109.796,5093.604 1129.2,5077.2 C1174.344,5039.04 1232.244,5006.34 1278.852,4983.18 " fill="none" id="Join session as student-backto-Vote down question" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="718.14,4763.976,716.7999,4775.7184,719.9394,4769.6998,725.958,4772.8394,718.14,4763.976" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="5108.2969">«extend»</text><!--MD5=[1273d0c19a7e6b0ee95e10391cd1cd66]
+reverse link Join session as student to Export questions--><path d="M763.392,4766.22 C846.66,4827.504 1000.512,4917.888 1093.2,4832.4 C1165.968,4765.296 1075.548,4471.596 1129.2,4388.4 C1159.224,4341.84 1212.3,4310.664 1260.072,4290.708 " fill="none" id="Join session as student-backto-Export questions" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="758.508,4762.596,764.3092,4772.8929,763.3224,4766.1768,770.0385,4765.1899,758.508,4762.596" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="4819.0969">«extend»</text><!--MD5=[6e1ab3310e3a90219731f12a9d62a853]
+reverse link Join session as student to Add keyword--><path d="M718.704,4770.384 C746.16,4865.856 819.276,5071.524 961.2,5172 C1311.516,5420.016 1867.62,5327.196 2093.688,5274.864 " fill="none" id="Join session as student-backto-Add keyword" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="716.964,4764.252,715.3065,4775.9538,718.6078,4770.0224,724.5392,4773.3237,716.964,4764.252" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1303.2" y="5252.2969">«extend»</text><!--MD5=[a1381cf6416e1613492930a41d2d5dd5]
+reverse link Join session as student to Topic cloud--><path d="M706.752,4668.84 C712.608,4511.412 747.924,4022.544 961.2,3698.4 C1001.772,3636.732 1055.16,3660.864 1093.2,3597.6 C1143.624,3513.744 1075.416,3462.144 1129.2,3380.4 C1165.848,3324.708 1231.332,3285.528 1283.328,3261.396 " fill="none" id="Join session as student-backto-Topic cloud" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="706.536,4675.2,711.7043,4664.5713,706.7422,4669.2035,702.11,4664.2414,706.536,4675.2" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="3584.2969">«extend»</text><!--MD5=[ef7ef244dbc911735635a8e95dc08b18]
+reverse link Join session as student to Question focus--><path d="M717.312,4668.852 C753.432,4510.56 864.36,4011.468 925.2,3592.8 C949.164,3427.896 896.136,3373.008 961.2,3219.6 C996.504,3136.356 1060.812,3149.22 1093.2,3064.8 C1147.044,2924.46 1044.588,1836.648 1129.2,1712.4 C1154.34,1675.476 1196.352,1652.352 1237.74,1637.892 " fill="none" id="Join session as student-backto-Question focus" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="715.956,4674.78,723.0373,4665.3177,717.2902,4668.9302,713.6777,4663.1831,715.956,4674.78" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="3051.4969">«extend»</text><!--MD5=[4fad91c8fcab18b71e3ec530ab3bdebb]
+reverse link Join session as Moderator to Ask question--><path d="M714.012,3539.46 C741.396,3705.924 833.628,4209.432 961.2,4303.2 C1008.468,4337.952 1046.892,4339.212 1093.2,4303.2 C1144.464,4263.348 1086.816,4210.8 1129.2,4161.6 C1160.652,4125.096 1208.1,4101.996 1251.876,4087.536 " fill="none" id="Join session as Moderator-backto-Ask question" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="712.992,3533.208,710.0167,3544.646,713.97,3539.1277,719.4883,3543.0811,712.992,3533.208" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="4289.8969">«extend»</text><!--MD5=[9f10a2814e271a1e25d303ae6c7d6644]
+reverse link Join session as Moderator to Block question--><path d="M733.164,3538.188 C772.944,3607.188 853.644,3725.652 961.2,3774 C1059.528,3818.208 1185.276,3798.324 1269.192,3775.752 " fill="none" id="Join session as Moderator-backto-Block question" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="730.14,3532.896,731.3266,3544.6549,733.115,3538.1065,739.6634,3539.8949,730.14,3532.896" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="3760.6969">«extend»</text><!--MD5=[8b17e19d9c3567b7e6a2a50e7c41018b]
+reverse link Join session as Moderator to Rate questions--><path d="M710.004,3432.912 C723.864,3294.696 777.288,2917.656 961.2,2676 C1044.708,2566.272 1188.972,2489.52 1279.404,2449.344 " fill="none" id="Join session as Moderator-backto-Rate questions" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="709.404,3438.924,715.2286,3428.6403,709.9858,3432.9523,705.6738,3427.7095,709.404,3438.924" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="2547.4969">«extend»</text><!--MD5=[70f19510ddec9da693eed735309598e3]
+reverse link Join session as Moderator to Export questions--><path d="M711.984,3539.496 C734.724,3720.132 818.196,4302.348 961.2,4411.2 C1007.88,4446.732 1036.86,4427.544 1093.2,4411.2 C1111.392,4405.932 1112.916,4398.06 1129.2,4388.4 C1184.556,4355.568 1248.636,4320.24 1295.34,4294.968 " fill="none" id="Join session as Moderator-backto-Export questions" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="711.192,3533.244,707.7566,3544.5523,711.9299,3539.1985,717.2837,3543.3717,711.192,3533.244" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="4397.8969">«extend»</text><!--MD5=[1b35fe9ab1e6b9fdcace78ca6d7fb637]
+reverse link Join session as Moderator to Add keyword--><path d="M717.24,3539.196 C752.244,3700.488 858.288,4198.584 925.2,4615.2 C935.256,4677.84 913.596,4856.472 961.2,4898.4 C1005.216,4937.184 1048.86,4936.812 1093.2,4898.4 C1177.92,4825.02 1044.48,4722.18 1129.2,4648.8 C1285.62,4513.32 1444.128,4506.96 1594.8,4648.8 C1691.28,4739.628 1534.704,5152.764 1630.8,5244 C1691.712,5301.84 1924.488,5284.236 2071.092,5266.38 " fill="none" id="Join session as Moderator-backto-Add keyword" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="715.92,3533.136,713.5126,3544.7068,717.1889,3539.0003,722.8954,3542.6766,715.92,3533.136" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1303.2" y="4532.2969">«extend»</text><!--MD5=[5c3eb4baa600a65e20aa4a49e74f17e6]
+reverse link Join session as Moderator to Question wall--><path d="M715.056,3432.816 C749.088,3239.52 866.304,2555.868 925.2,1987.2 C931.968,1921.824 929.604,1454.436 961.2,1396.8 C996.072,1333.188 1035.084,1344.204 1093.2,1300.8 C1171.536,1242.3 1261.548,1172.796 1314.66,1131.552 " fill="none" id="Join session as Moderator-backto-Question wall" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="713.976,3438.936,720.5831,3429.1367,715.0207,3433.0276,711.1297,3427.4652,713.976,3438.936" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="1287.4969">«extend»</text><!--MD5=[75a8324fde0f0fc1aa28777be2627f56]
+reverse link Join session as Moderator to Topic cloud--><path d="M781.548,3438.384 C831.252,3408.72 898.404,3371.424 961.2,3345.6 C1059.444,3305.208 1176.876,3273.564 1258.92,3253.968 " fill="none" id="Join session as Moderator-backto-Topic cloud" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="776.184,3441.6,787.9145,3440.1594,781.329,3438.513,782.9753,3431.9275,776.184,3441.6" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="3286.6969">«extend»</text><!--MD5=[a4c8c696a9a306660ba54a3fcecef9ca]
+reverse link Join session as Moderator to Question focus--><path d="M712.68,3432.876 C734.424,3279.624 808.26,2825.592 961.2,2480.4 C1004.22,2383.296 1059.372,2381.88 1093.2,2281.2 C1133.544,2161.152 1056.012,1815.768 1129.2,1712.4 C1155.144,1675.764 1197.564,1652.688 1239.072,1638.192 " fill="none" id="Join session as Moderator-backto-Question focus" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="711.804,3439.08,718.0669,3429.0572,712.6429,3433.1389,708.5612,3427.7149,711.804,3439.08" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="2267.8969">«extend»</text><!--MD5=[2c5671eb0dd8697184a0bed8f5641e72]
+reverse link Ask question to Spell check--><path d="M1483.98,4087.452 C1525.848,4101.696 1568.76,4124.652 1594.8,4161.6 C1637.256,4221.852 1577.28,4773.312 1630.8,4824 C1761.648,4947.936 1995.996,4890.984 2117.076,4849.332 " fill="none" id="Ask question-backto-Spell check" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1477.812,4085.412,1486.5543,4093.3651,1483.5075,4087.2991,1489.5736,4084.2523,1477.812,4085.412" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="4810.6969">«extend»</text><!--MD5=[851af3305945c2ec3219bb63ddb66d44]
+reverse link Ask question to Add keyword--><path d="M1484.604,4087.308 C1526.412,4101.54 1569.132,4124.52 1594.8,4161.6 C1655.772,4249.704 1562.1,5042.988 1630.8,5125.2 C1734.504,5249.304 1931.58,5266.008 2062.956,5261.436 " fill="none" id="Ask question-backto-Add keyword" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1478.448,4085.28,1487.1974,4093.2253,1484.1452,4087.162,1490.2086,4084.1098,1478.448,4085.28" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="5111.8969">«extend»</text><!--MD5=[d319e51263f6a23b1252939bcf6cec7a]
+reverse link Ask question to Publish question--><path d="M1484.46,4087.416 C1526.256,4101.648 1569,4124.616 1594.8,4161.6 C1646.256,4235.388 1568.292,4905.72 1630.8,4970.4 C1746.372,5089.992 1955.892,5070.684 2084.28,5043.984 " fill="none" id="Ask question-backto-Publish question" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1478.304,4085.376,1487.0463,4093.3291,1483.9995,4087.2631,1490.0656,4084.2163,1478.304,4085.376" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="4957.0969">«extend»</text><!--MD5=[d1266514447d0e404ac883d8301131f9]
+reverse link Create check to Correct Spelling--><path d="M839.604,5371.092 C948.408,5384.64 1101.636,5403.72 1213.8,5417.688 " fill="none" id="Create check-backto-Correct Spelling" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="833.484,5370.324,843.6117,5376.4157,839.4385,5371.0619,844.7923,5366.8886,833.484,5370.324" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="968.4" y="5374.6969">«extend»</text><!--MD5=[833c4a05a00a3ffa447e96f152d14591]
+reverse link Question wall to Filter--><path d="M1441.428,1059.78 C1494.636,1030.908 1561.236,984.876 1594.8,922.8 C1625.736,865.572 1585.248,384.84 1630.8,338.4 C1764.12,202.5 2018.928,246.384 2134.524,275.616 " fill="none" id="Question wall-backto-Filter" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1435.992,1062.696,1447.7764,1061.7974,1441.2737,1059.8494,1443.2218,1053.3467,1435.992,1062.696" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="251.8969">«extend»</text><!--MD5=[29343977b60ea2dd034f269ff448c5bc]
+reverse link Evaluate questions to Tag--><path d="M1542.72,1826.196 C1619.064,1840.788 1703.88,1869.612 1762.8,1926 C1799.352,1960.992 1762.692,1998.564 1798.8,2034 C1892.484,2125.944 2053.536,2149.608 2138.304,2155.62 " fill="none" id="Evaluate questions-backto-Tag" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1536.768,1825.08,1546.5078,1831.7744,1542.6668,1826.1774,1548.2638,1822.3364,1536.768,1825.08" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="1839.4969">«extend»</text><!--MD5=[35ad29ab624e48f4c731265a9cca1897]
+reverse link Evaluate questions to Delete--><path d="M1391.208,1856.868 C1443.012,1942.632 1552.344,2137.428 1594.8,2318.4 C1623.444,2440.488 1575.168,3334.02 1630.8,3446.4 C1738.2,3663.36 2011.392,3802.74 2133.564,3856.152 " fill="none" id="Evaluate questions-backto-Delete" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1387.884,1851.384,1389.3706,1863.1088,1390.9911,1856.5168,1397.5831,1858.1373,1387.884,1851.384" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="3433.0969">«extend»</text><!--MD5=[97eaf76393834e8e320a1a760897c65d]
+reverse link Evaluate questions to Mark as wrong--><path d="M1390.944,1856.94 C1442.28,1942.812 1550.868,2137.776 1594.8,2318.4 C1634.04,2479.764 1551.9,2918.688 1630.8,3064.8 C1665.264,3128.628 1722.876,3100.236 1762.8,3160.8 C1802.532,3221.088 1752.432,3263.868 1798.8,3319.2 C1866.516,3399.996 1980.18,3442.44 2068.296,3464.244 " fill="none" id="Evaluate questions-backto-Mark as wrong" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1387.644,1851.444,1389.0846,1863.1745,1390.731,1856.589,1397.3165,1858.2353,1387.644,1851.444" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="3051.4969">«extend»</text><!--MD5=[a7c473b0ee706a13acc3e5489b5215d6]
+reverse link Evaluate questions to Mark as true--><path d="M1386.42,1857.6 C1426.872,1933.152 1516.944,2085.156 1630.8,2178 C1766.856,2288.952 1964.712,2350.572 2086.128,2380.056 " fill="none" id="Evaluate questions-backto-Mark as true" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1383.36,1851.852,1384.213,1863.6398,1386.1862,1857.1447,1392.6813,1859.1179,1383.36,1851.852" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="2164.6969">«extend»</text><!--MD5=[452a0555efe51dfd24c382d6bee38e01]
+reverse link Evaluate questions to Republish--><path d="M1490.568,1780.14 C1528.776,1764.936 1567.692,1742.88 1594.8,1711.2 C1636.008,1663.044 1580.64,1611.96 1630.8,1573.2 C1677.228,1537.332 1718.496,1534.752 1762.8,1573.2 C1848.648,1647.708 1723.86,1740.936 1798.8,1826.4 C1868.58,1905.984 1990.452,1930.38 2080.5,1936.848 " fill="none" id="Evaluate questions-backto-Republish" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1484.928,1782.336,1496.7337,1782.8882,1490.5187,1780.158,1493.2489,1773.943,1484.928,1782.336" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="1532.2969">«extend»</text><!--MD5=[1d5b344beb6824be3b9b014107f12236]
+reverse link Evaluate questions to Answer--><path d="M1497.744,1781.46 C1534.932,1766.424 1571.448,1744.14 1594.8,1711.2 C1658.052,1621.992 1550.688,1294.848 1630.8,1220.4 C1673.772,1180.464 1709.568,1195.74 1762.8,1220.4 C1980.588,1321.284 2128.488,1592.292 2176.92,1691.856 " fill="none" id="Evaluate questions-backto-Answer" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1491.768,1783.812,1503.5757,1784.3204,1497.3506,1781.6133,1500.0578,1775.3882,1491.768,1783.812" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="1183.0969">«extend»</text><!--MD5=[4ab1b68341f3be81a9e6e4ac9ad3a330]
+reverse link Evaluate questions to Star--><path d="M1388.82,1857.132 C1436.832,1943.724 1540.404,2140.404 1594.8,2318.4 C1623.396,2411.976 1579.392,2452.344 1630.8,2535.6 C1668.912,2597.328 1726.368,2568.876 1762.8,2631.6 C1835.832,2757.348 1723.404,2832.468 1798.8,2956.8 C1879.488,3089.856 2055.312,3170.628 2142.732,3204.072 " fill="none" id="Evaluate questions-backto-Star" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1385.736,1851.588,1386.785,1863.36,1388.6499,1856.8329,1395.1769,1858.6978,1385.736,1851.588" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="2522.2969">«extend»</text><!--MD5=[2515d2ea12e7d95f69f94fdf3962fdcd]
+reverse link Topic cloud to Edit topic cloud--><path d="M1396.224,3189.552 C1442.484,3133.692 1532.064,3036.048 1630.8,2984.4 C1759.416,2917.14 1922.892,2886.036 2040.588,2871.708 " fill="none" id="Topic cloud-backto-Edit topic cloud" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1392.156,3194.496,1402.7228,3189.2023,1395.9666,3189.8614,1395.3075,3183.1053,1392.156,3194.496" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="2918.2969">«extend»</text><!--MD5=[877d44bc31b9ffd7527cacc118f30bf3]
+reverse link Topic cloud to Edit cloud view--><path d="M1449.804,3262.992 C1501.632,3286.716 1563.348,3324.816 1594.8,3380.4 C1627.68,3438.516 1584.648,4533.36 1630.8,4581.6 C1747.752,4703.868 1962.9,4680.432 2090.808,4652.136 " fill="none" id="Topic cloud-backto-Edit cloud view" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1444.188,3260.46,1452.0796,3269.2578,1449.6631,3262.9143,1456.0066,3260.4978,1444.188,3260.46" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="4568.2969">«extend»</text><!--MD5=[1b1ae719670ea21dd1c8e6e7ff1a8896]
+reverse link Edit cloud view to My cloud--><path d="M2344.608,4606.14 C2542.02,4582.86 2886.12,4542.276 3054.504,4522.416 " fill="none" id="Edit cloud view-backto-My cloud" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="2338.236,4606.896,2349.5246,4610.3956,2344.1946,4606.192,2348.3982,4600.8619,2338.236,4606.896" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="2635.2" y="4547.8969">«extend»</text><!--MD5=[6574b4f8ee1b6919a2bb6c8200568a17]
+reverse link Edit cloud view to Demo cloud--><path d="M2305.524,4653.996 C2392.14,4676.664 2516.808,4705.968 2628,4719.6 C2761.704,4736.004 2915.952,4737.864 3022.5,4736.52 " fill="none" id="Edit cloud view-backto-Demo cloud" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="2299.356,4652.376,2308.5831,4659.7611,2305.1593,4653.8996,2311.0209,4650.4758,2299.356,4652.376" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="2635.2" y="4706.2969">«extend»</text><!--MD5=[ae23622c7ae1d42a52e9fdaea1273b54]
+reverse link Topic cloud to Correct a key word--><path d="M1449.756,3263.028 C1501.548,3286.764 1563.264,3324.864 1594.8,3380.4 C1654.668,3485.856 1543.644,4386.876 1630.8,4471.2 C1691.844,4530.264 1927.992,4488.588 2074.488,4455.42 " fill="none" id="Topic cloud-backto-Correct a key word" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1444.128,3260.484,1451.9967,3269.3024,1449.5966,3262.9526,1455.9464,3260.5526,1444.128,3260.484" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="4457.8969">«extend»</text><!--MD5=[65256f0e26b007da989708aa3f3c4f3f]
+reverse link Moderate questions to Tag--><path d="M1541.28,2789.22 C1620.096,2786.136 1707.324,2766.984 1762.8,2707.2 C1823.988,2641.26 1744.176,2375.472 1798.8,2304 C1880.928,2196.552 2050.452,2167.944 2138.448,2160.348 " fill="none" id="Moderate questions-backto-Tag" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1535.136,2789.424,1546.0941,2793.8511,1541.1325,2789.2184,1545.7652,2784.2568,1535.136,2789.424" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="2693.8969">«extend»</text><!--MD5=[e5b3ae8615b23ce7d58853667e9a823a]
+reverse link Moderate questions to Bookmark--><path d="M1404.24,2818.596 C1459.584,2883.048 1555.68,3007.32 1594.8,3133.2 C1613.964,3194.856 1584.444,4249.86 1630.8,4294.8 C1703.328,4365.108 2002.116,4228.992 2132.676,4164.288 " fill="none" id="Moderate questions-backto-Bookmark" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1400.004,2813.676,1403.4337,2824.9861,1403.9271,2818.2158,1410.6973,2818.7092,1400.004,2813.676" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="4281.4969">«extend»</text><!--MD5=[e5b3ae8615b23ce7d58853667e9a823a]
+reverse link Moderate questions to Bookmark--><path d="M1403.616,2818.116 C1458.684,2882.484 1554.96,3007.164 1594.8,3133.2 C1624.44,3226.98 1567.08,3942.696 1630.8,4017.6 C1742.388,4148.772 1959.408,4155.48 2089.104,4145.892 " fill="none" id="Moderate questions-backto-Bookmark-1" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1399.404,2813.208,1402.8092,2824.5255,1403.3172,2817.7563,1410.0864,2818.2643,1399.404,2813.208" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="4004.2969">«extend»</text><!--MD5=[a045ee0aeabb80e46e97b69db30ab7f2]
+reverse link Moderate questions to Delete--><path d="M1403.472,2818.164 C1458.36,2882.58 1554.444,3007.332 1594.8,3133.2 C1619.784,3211.128 1572.144,3811.74 1630.8,3868.8 C1765.092,3999.444 2013.732,3941.352 2130.504,3903.78 " fill="none" id="Moderate questions-backto-Delete" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1399.272,2813.244,1402.6315,2824.5751,1403.1668,2817.808,1409.9339,2818.3433,1399.272,2813.244" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="3855.4969">«extend»</text><!--MD5=[f300e0b511c5aabb8568aefce0a13f04]
+reverse link Moderate questions to Mark as wrong--><path d="M1403.34,2818.212 C1458.06,2882.688 1553.94,3007.488 1594.8,3133.2 C1616.556,3200.136 1579.644,3717.276 1630.8,3765.6 C1673.448,3805.884 1706.544,3782.244 1762.8,3765.6 C1925.412,3717.516 2084.28,3586.788 2155.392,3522.588 " fill="none" id="Moderate questions-backto-Mark as wrong" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1399.14,2813.292,1402.4995,2824.6231,1403.0348,2817.856,1409.8019,2818.3913,1399.14,2813.292" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="3752.2969">«extend»</text><!--MD5=[dda53ebe170a6a2f5fff422fc4917c9b]
+reverse link Moderate questions to Mark as true--><path d="M1397.364,2818.5 C1446.168,2884.8 1536.396,3013.416 1594.8,3133.2 C1616.088,3176.868 1591.2,3208.272 1630.8,3236.4 C1678.632,3270.372 1719.78,3276.288 1762.8,3236.4 C1840.464,3164.4 1752.288,2856.336 1798.8,2761.2 C1873.308,2608.812 2043.348,2490.948 2134.26,2436.12 " fill="none" id="Moderate questions-backto-Mark as true" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1393.632,2813.448,1396.1799,2824.9887,1397.1935,2818.2766,1403.9056,2819.2903,1393.632,2813.448" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="3223.0969">«extend»</text><!--MD5=[4d8cfbab1f8b0019c7892bc1ed6236a3]
+reverse link Moderate questions to Republish--><path d="M1407.648,2728.536 C1456.332,2678.508 1535.388,2593.92 1594.8,2514 C1613.088,2489.412 1611.024,2478.612 1630.8,2455.2 C1681.044,2395.716 1726.128,2408.688 1762.8,2340 C1822.056,2229.012 1717.836,2155.512 1798.8,2059.2 C1867.704,1977.24 1990.344,1949.232 2080.824,1940.124 " fill="none" id="Moderate questions-backto-Republish" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1403.328,2732.976,1414.3065,2728.5997,1407.5188,2728.6821,1407.4364,2721.8944,1403.328,2732.976" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="2326.6969">«extend»</text><!--MD5=[679d69c509a4b70cc0eea01a520dd089]
+reverse link Moderate questions to Answer--><path d="M1418.796,2729.856 C1474.104,2683.164 1556.124,2603.436 1594.8,2514 C1667.7,2345.46 1540.416,2262.252 1630.8,2102.4 C1666.5,2039.256 1723.26,2067.216 1762.8,2006.4 C1804.428,1942.38 1746.408,1893.948 1798.8,1838.4 C1878.084,1754.352 2015.7,1732.98 2105.856,1728.588 " fill="none" id="Moderate questions-backto-Answer" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1414.2,2733.708,1425.5578,2730.4399,1418.7952,2729.8501,1419.3851,2723.0875,1414.2,2733.708" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="1993.0969">«extend»</text><!--MD5=[23e52ed03cc32ef66e605affcd82554c]
+reverse link Moderate questions to Star--><path d="M1400.976,2818.356 C1453.332,2883.492 1546.896,3009.612 1594.8,3133.2 C1629.408,3222.48 1557.66,3283.812 1630.8,3345.6 C1709.208,3411.84 2023.32,3292.74 2145.36,3242.652 " fill="none" id="Moderate questions-backto-Star" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1396.968,2813.388,1400.0023,2824.8105,1400.7308,2818.0615,1407.4798,2818.79,1396.968,2813.388" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="3332.2969">«extend»</text><!--MD5=[553b96aa498067b762d70a578a8be1f8]
+reverse link Question focus to Filter--><path d="M1395.096,1571.364 C1447.704,1498.344 1551.192,1342.644 1594.8,1192.8 C1629.96,1071.96 1577.496,741.612 1630.8,627.6 C1725.252,425.58 2005.332,336.648 2131.428,306.06 " fill="none" id="Question focus-backto-Filter" style="stroke:#008000;stroke-width:2.4;stroke-dasharray:7.0,7.0;"/><polygon fill="#008000" points="1391.4,1576.488,1401.623,1570.5575,1394.9198,1571.6289,1393.8484,1564.9258,1391.4,1576.488" style="stroke:#008000;stroke-width:2.4;"/><text fill="#000000" font-family="sans-serif" font-size="28.8" lengthAdjust="spacing" textLength="117.6" x="1638" y="467.8969">«extend»</text><rect fill="#F8E7C0" height="447.525" rx="6" ry="6" style="stroke:#F8E7C0;stroke-width:0.0;" width="610.8" x="3740.4" y="6033.396"/><image height="153.6" width="153.6" x="3759.6" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAADcklEQVR4Xu2c0W3iUBREqQjqSDXbRYpKJ/neMvYju08ECY3J4js2cGfeHOkoH9G7RvIBG2M4HEIIIYQQQgghhJ95e3v7/e/PV3ytx+Px1+GZnE6nP4cbDyS+1meFsNhwbOfDwA3Fvu4ObiA29vswvRuLDUQJdwMHRx03gwOjlpvBgVHIPc4FFkOjnBzfFxZwWNSTIwHYyJEAbORIADZyJAAbORKAjRyzBDDeK1+L/zeQwzGA9/f3ryqfn5+XCyqLeSJyuAQwdh7uVJaPj4/FfAE5HAJ4FOOVBLfVWA7lAMb9irjTHgFut6kcqgEwx/kt4PYbyqEYwLOe+deMk0R8HM3kUAzgVeDjaCaHWgCvBh9PIzkSQA18PI3kUAqABedcHO/3GXBOEzmcA1h74lYF1zeRQyUA5kofzvjJ6isBrm8ih0oAj95JFZp+YZZDJYAquP6eFZp+VsCRAOrz155bPFkOlQDGs64irr9nhQRgaIWmnxJyJICzFZreOMKRAM5WwLVN5EgAtZ0/wPVN5Jg9gOoFpqbH/yHH7AFUwfWN5Jg5gCpNrwBe5Jg1AAac0UyOGQNgwBkN5ZgpAPZGUpzTVI5ZAmB3ftOLPrfkmCGA6lu9C81P+lCOGQJgEHrmX+RwD4B56ccZInK4B1AF1wvJ4RxA9dmP68XkcA6ggtgJ3y05EsAZXCsoRwKw2PlDDtcAKsd/XCsqh2sA48bNNTA3kDaVwzWAteA6YTkSwHKtqBwJYLlWVA7XACaUIwHYyJEAbORIADZyJAAbORKAjRwzBIAYXf27lsM5gHs0/poXI4drAGsxioBj9gAGuFZUDscAqpi8CnAkgDM4Q1COBHAGZwjKkQDa/upXVQ7HACq3gw1wvagcjgEMK+BaUTlcAxiuAdcIy+EcwPDWN4NNjvkoh3sAE8mRAGzkSAA2ciQAGzkSgI0cCcBGjgRg4yZwWNRzEzgs6rkJHBb15Ml5gIWbwYFRy13AoVHH7Rj8VNrM7goOj/3dF8EfS57dx5DDgoxBBNxxexmEwJ23h0EM3IFbDYLgTtxiUGPnS/BBkR0jCKrsFEFQZocIgjobIwgObIgguEBGEJwgIghuFD+IC44UIgiurIwgOLMiguDOnQjCDPwngjALP9yvGWbiRgRhNiCCMCNXEYRZ+Y4ghBBCCCGEEG7wF4/x8PpTsJefAAAAAElFTkSuQmCC" y="6053.796"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="0" x="3920.4" y="6202.1226"/><text fill="#000000" font-family="sans-serif" font-size="24" font-weight="bold" lengthAdjust="spacing" textLength="0" x="3957.6" y="6078.7101"/><text fill="#000000" font-family="sans-serif" font-size="24" font-weight="bold" lengthAdjust="spacing" textLength="0" x="3957.6" y="6108.8976"/><text fill="#000000" font-family="sans-serif" font-size="24" font-weight="bold" lengthAdjust="spacing" textLength="127.2" x="3957.6" y="6139.0851">»frag.jetzt«</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="111.6" x="3766.8" y="6244.3101">Produktion</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="0" x="3957.6" y="6244.3101"/><a href="https://frag.jetzt" target="_top" title="https://frag.jetzt" xlink:actuate="onRequest" xlink:href="https://frag.jetzt" xlink:show="new" xlink:title="https://frag.jetzt" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="24" lengthAdjust="spacing" text-decoration="underline" textLength="165.6" x="3957.6" y="6244.3101">https://frag.jetzt</text></a><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="0" x="4130.4" y="6244.3101"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="114" x="3766.8" y="6286.4976">Repository</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="0" x="3957.6" y="6286.4976"/><a href="https://git.thm.de/arsnova/frag.jetzt" target="_top" title="https://git.thm.de/arsnova/frag.jetzt" xlink:actuate="onRequest" xlink:href="https://git.thm.de/arsnova/frag.jetzt" xlink:show="new" xlink:title="https://git.thm.de/arsnova/frag.jetzt" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="24" lengthAdjust="spacing" text-decoration="underline" textLength="367.2" x="3957.6" y="6286.4976">https://git.thm.de/arsnova/frag.jetzt</text></a><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="0" x="4332" y="6286.4976"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="156" x="3766.8" y="6328.6851">Staging Server</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="0" x="3957.6" y="6328.6851"/><a href="https://staging.frag.jetzt" target="_top" title="https://staging.frag.jetzt" xlink:actuate="onRequest" xlink:href="https://staging.frag.jetzt" xlink:show="new" xlink:title="https://staging.frag.jetzt" xlink:type="simple"><text fill="#0000FF" font-family="sans-serif" font-size="24" lengthAdjust="spacing" text-decoration="underline" textLength="248.4" x="3957.6" y="6328.6851">https://staging.frag.jetzt</text></a><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="0" x="4213.2" y="6328.6851"/><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="103.2" x="3766.8" y="6370.8726">UML-Tool</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="174" x="3957.6" y="6370.8726">PlantUML v5.5.1</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="87.6" x="3766.8" y="6413.0601">Ersteller</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="300" x="3957.6" y="6413.0601">Kevin Piam , Franck Mezatio</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="171.6" x="3766.8" y="6455.2476">Letzte Änderung</text><text fill="#000000" font-family="sans-serif" font-size="24" lengthAdjust="spacing" textLength="120" x="3957.6" y="6455.2476">20.06.2021</text><line style="stroke:#000000;stroke-width:1.2;" x1="3753.6" x2="4338" y1="6047.796" y2="6047.796"/><line style="stroke:#000000;stroke-width:1.2;" x1="3753.6" x2="4338" y1="6213.396" y2="6213.396"/><line style="stroke:#000000;stroke-width:1.2;" x1="3753.6" x2="4338" y1="6255.5835" y2="6255.5835"/><line style="stroke:#000000;stroke-width:1.2;" x1="3753.6" x2="4338" y1="6297.771" y2="6297.771"/><line style="stroke:#000000;stroke-width:1.2;" x1="3753.6" x2="4338" y1="6339.9585" y2="6339.9585"/><line style="stroke:#000000;stroke-width:1.2;" x1="3753.6" x2="4338" y1="6382.146" y2="6382.146"/><line style="stroke:#000000;stroke-width:1.2;" x1="3753.6" x2="4338" y1="6424.3335" y2="6424.3335"/><line style="stroke:#000000;stroke-width:1.2;" x1="3753.6" x2="4338" y1="6466.521" y2="6466.521"/><line style="stroke:#000000;stroke-width:1.2;" x1="3753.6" x2="3753.6" y1="6047.796" y2="6466.521"/><line style="stroke:#000000;stroke-width:1.2;" x1="3944.4" x2="3944.4" y1="6047.796" y2="6466.521"/><line style="stroke:#000000;stroke-width:1.2;" x1="4338" x2="4338" y1="6047.796" y2="6466.521"/><!--MD5=[06fa9b4f4bc99f86171e97f1c04b0579]
+@startuml
+
+scale 1.0
+
+left to right direction
+
+skinparam backgroundColor Linen
+skinparam LegendBackgroundColor Strategy
+skinparam LegendBorderThickness 0
+skinparam LegendFontSize 20
+skinparam Padding 5
+skinparam defaultFontSize 24
+skinparam Nodesep 100
+skinparam ArrowThickness 2
+skinparam shadowing true
+
+skinparam usecase {
+    BackgroundColor PaleGreen
+    BorderColor Green
+    BackgroundColor<<USP>> Pink
+    BorderColor<<USP>> HotPink
+    BorderThickness 2
+    ArrowThickness 2
+    ArrowColor Green
+    ActorBorderColor Green
+}
+
+actor Lecturer
+actor Student
+actor Moderator
+
+note "If a lecturer is registered and logs in with her account, \nher sessions remain stored for 180 days after the last visit, \notherwise they are deleted when she logs out." as NoteForCreateSession
+note "Registered students can receive a bonus \nfor particularly interesting questions." as NoteForJoinSessionAsStudent
+note "as another option we have general, fond, hover and \nweight-classes that apply to the sight of the cloud " as NoteForDemoCloud
+note "it is possible to choose the language for the spelling." as NoteForSpellCheck
+
+rectangle "frag.jetzt | use-case diagram \n" << Business >> {
+
+    (Create session) - - - NoteForCreateSession
+    (Join session as student) - - - NoteForJoinSessionAsStudent
+    (Demo cloud) - - - NoteForDemoCloud
+    (My cloud) - NoteForDemoCloud
+    (Spell check) - - NoteForSpellCheck
+
+    Lecturer - - (Create session)
+    (Evaluate questions) <.. (Delete question) : << extend >>
+    Student- - (Join session as student)
+    Moderator - - - - (Join session as Moderator)
+    (Join session as Moderator)<..(Moderate questions): << extend >>
+    (Create session) <.. (Question wall) : << extend >>
+    (Create session) <.. (Question wall) : << extend >>
+    (Create session) <.. (Edit session) : << extend >>
+    (Create session) <.. (Evaluate questions) : << extend >>
+    (Create session) <.. (Assign moderator to session) : << extend >>
+    (Create session) <.. (Create question tag) : << extend >>
+    (Create session) <.. (Export questions) : << extend >>
+    (Create session) <.. (Ask question) : << extend >>
+    (Create session) <.. (Rate questions) : << extend >>
+    (Create session) <.. (Redeem bonus token) : << extend >>
+    (Create session) <.. (Evaluate questions) : << extend >>
+    (Create session) <.. (Block question) : << extend >>
+    (Create session) <.. (Add keyword) : << extend >>
+    (Create session) <.. (Topic cloud) : << extend >>
+    (Create session) <.. (Question focus) : << extend >>
+
+
+    (Moderate questions) <.. (Ban question) : << extend >>
+    (Evaluate questions) <.. (Ban question) : << extend >>
+    (Join session as student) <.. (Question wall) : << extend >>
+    (Join session as student) <.. (Ask question) : << extend >>
+    (Join session as student) <.. (Vote up question) : << extend >>
+    (Join session as student) <.. (Vote down question) : << extend >>
+    (Join session as student) <.. (Export questions) : << extend >>
+    (Join session as student) <.. (Add keyword) : << extend >>
+    (Join session as student) <.. (Topic cloud) : << extend >>
+    (Join session as student) <.. (Question focus) : << extend >>
+
+
+
+    (Join session as Moderator) <.. (Ask question) : << extend >>
+    (Join session as Moderator) <.. (Block question) : << extend >>
+    (Join session as Moderator) <.. (Rate questions) : << extend >>
+    (Join session as Moderator) <.. (Export questions) : << extend >>
+    (Join session as Moderator) <.. (Add keyword) : << extend >>
+    (Join session as Moderator) <.. (Question wall) : << extend >>
+    (Join session as Moderator) <.. (Topic cloud) : << extend >>
+    (Join session as Moderator) <.. (Question focus) : << extend >>
+    (Ask question) <.. (Spell check) : << extend >>
+    (Ask question) <.. (Add keyword) : << extend >>
+    (Ask question) <.. (Publish question) : << extend >>
+    (Create check) <.. (Correct Spelling) : << extend >>
+
+    (Question wall) <.. (Filter) : << extend >>
+    (Evaluate questions) <.. (Tag) : << extend >>
+    (Evaluate questions) <.. (Delete) : << extend >>
+    (Evaluate questions) <.. (Mark as wrong) : << extend >>
+    (Evaluate questions) <.. (Mark as true) : << extend >>
+    (Evaluate questions) <.. (Republish) : << extend >>
+    (Evaluate questions) <.. (Answer) : << extend >>
+    (Evaluate questions) <.. (Star) : << extend >>
+    (Evaluate questions) <.. (Ban question) : << extend >>
+    (Topic cloud) <.. (Edit topic cloud) : << extend >>
+    (Topic cloud) <.. (Edit cloud view) : << extend >>
+    (Edit cloud view) <.. (My cloud) : << extend >>
+    (Edit cloud view) <.. (Demo cloud) : << extend >>
+    (Topic cloud) <.. (Correct a key word) : << extend >>
+    (Moderate questions) <.. (Tag) : << extend >>
+    (Moderate questions) <.. (Bookmark) : << extend >>
+    (Moderate questions) <.. (Delete) : << extend >>
+    (Moderate questions) <.. (Mark as wrong) : << extend >>
+    (Moderate questions) <.. (Mark as true) : << extend >>
+    (Moderate questions) <.. (Republish) : << extend >>
+    (Moderate questions) <.. (Answer) : << extend >>
+    (Moderate questions) <.. (Star) : << extend >>
+    (Moderate questions) <.. (Ban question) : << extend >>
+    (Moderate questions) <.. (Bookmark) : << extend >>
+    (Question focus) <.. (Filter) : << extend >>
+
+}
+
+legend right
+  |<img:https://git.thm.de/arsnova/arsnova-lite/raw/staging/src/assets/icons/Logo_frag_jetzt_128x128.png> |= \n\n »frag.jetzt« |
+  | Produktion | [[https://frag.jetzt]] |
+  | Repository | [[https://git.thm.de/arsnova/frag.jetzt]] |
+  | Staging Server | [[https://staging.frag.jetzt]] |
+  | UML-Tool| PlantUML v5.5.1|
+  | Ersteller| Kevin Piam , Franck Mezatio |
+  | Letzte Änderung| 20.06.2021 |
+end legend
+
+@enduml
+
+PlantUML version 1.2021.7(Sun May 23 14:40:07 CEST 2021)
+(GPL source distribution)
+Java Runtime: OpenJDK Runtime Environment
+JVM: Dynamic Code Evolution 64-Bit Server VM
+Default Encoding: Cp1252
+Language: de
+Country: DE
+--></g></svg>
\ No newline at end of file
diff --git a/docs/diagrams/activity_diagram_bonus_option_frag_jetzt.puml b/docs/diagrams/activity_diagram_bonus_option_frag_jetzt.puml
index 6fd69615c06d200ce5eefba085c72440eb4a2ab9..378405e63adb0d4d116a484fe48ebc974db3066a 100644
--- a/docs/diagrams/activity_diagram_bonus_option_frag_jetzt.puml
+++ b/docs/diagrams/activity_diagram_bonus_option_frag_jetzt.puml
@@ -94,7 +94,7 @@ PlantUML doesn't support pins.
 The black arrow only transmits the information
 that a question has been awarded a star.
 end note
-:select "Your stars";
+:select "Your bonus stars";
 :choose a session;
 :redeem token;
 :send email with token to lecturer;
diff --git a/package-lock.json b/package-lock.json
index 24b83da600a1c4e91406825e3e257b2893212a8c..39c96e9701c6914e7f559fa315dc65d9ca8b5e6e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5,25 +5,25 @@
   "requires": true,
   "dependencies": {
     "@angular-devkit/architect": {
-      "version": "0.1102.12",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1102.12.tgz",
-      "integrity": "sha512-6qnI3NXpHzSlNG6jSLNdQazx7SILSpE3YD9l9n0tjHF3yeFnzPuVVWbQSjI9Us5EQi86lVGT3mTJbivRRRUYUQ==",
+      "version": "0.1102.14",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1102.14.tgz",
+      "integrity": "sha512-965TVXuBtRb8RySgxRxUEO+YTd7mT0xiqVHSe+MHvMtUCmEE9vwRofFZl6axkK5ri4fiomiMnOVE19aw4spgNQ==",
       "dev": true,
       "requires": {
-        "@angular-devkit/core": "11.2.12",
+        "@angular-devkit/core": "11.2.14",
         "rxjs": "6.6.3"
       }
     },
     "@angular-devkit/build-angular": {
-      "version": "0.1102.12",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.1102.12.tgz",
-      "integrity": "sha512-mX8UqIR+Ev6p37zXLtZghdCNta3Pi5bG6o0PCXUGcDRY63kp2jiWH0RgvoBjJBlAt358tIO9GEkR8kuqZt8x4w==",
+      "version": "0.1102.14",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.1102.14.tgz",
+      "integrity": "sha512-SyX9SK3qfpk6xNIrxpxYi8zxP/cN2kny4I+XYbkKvgGiE3qhkrC/PRJE9OWj0sloekLD0CDfFWOvIiw3GMc4Tg==",
       "dev": true,
       "requires": {
-        "@angular-devkit/architect": "0.1102.12",
-        "@angular-devkit/build-optimizer": "0.1102.12",
-        "@angular-devkit/build-webpack": "0.1102.12",
-        "@angular-devkit/core": "11.2.12",
+        "@angular-devkit/architect": "0.1102.14",
+        "@angular-devkit/build-optimizer": "0.1102.14",
+        "@angular-devkit/build-webpack": "0.1102.14",
+        "@angular-devkit/core": "11.2.14",
         "@babel/core": "7.12.10",
         "@babel/generator": "7.12.11",
         "@babel/plugin-transform-async-to-generator": "7.12.1",
@@ -33,7 +33,7 @@
         "@babel/template": "7.12.7",
         "@discoveryjs/json-ext": "0.5.2",
         "@jsdevtools/coverage-istanbul-loader": "3.0.5",
-        "@ngtools/webpack": "11.2.12",
+        "@ngtools/webpack": "11.2.14",
         "ansi-colors": "4.1.1",
         "autoprefixer": "10.2.4",
         "babel-loader": "8.2.2",
@@ -45,7 +45,7 @@
         "core-js": "3.8.3",
         "critters": "0.0.7",
         "css-loader": "5.0.1",
-        "cssnano": "5.0.1",
+        "cssnano": "5.0.2",
         "file-loader": "6.2.0",
         "find-cache-dir": "3.3.1",
         "glob": "7.1.6",
@@ -63,12 +63,12 @@
         "ora": "5.3.0",
         "parse5-html-rewriting-stream": "6.0.1",
         "pnp-webpack-plugin": "1.6.4",
-        "postcss": "8.2.13",
+        "postcss": "8.2.15",
         "postcss-import": "14.0.0",
         "postcss-loader": "4.2.0",
         "raw-loader": "4.0.2",
         "regenerator-runtime": "0.13.7",
-        "resolve-url-loader": "3.1.2",
+        "resolve-url-loader": "4.0.0",
         "rimraf": "3.0.2",
         "rollup": "2.38.4",
         "rxjs": "6.6.3",
@@ -122,9 +122,9 @@
       }
     },
     "@angular-devkit/build-optimizer": {
-      "version": "0.1102.12",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1102.12.tgz",
-      "integrity": "sha512-4aQ4t7iDagrsNrF5JDS3bZw+uIn4z0llyau7GQQwZm1OmpRcl33hXOIHSFUJoRPP6pI5liNVuffF3lrAoC6sZA==",
+      "version": "0.1102.14",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1102.14.tgz",
+      "integrity": "sha512-1j69rFqE6tPMO0lQvOH8ogF7vE+p+Ws1/OtdZKUkZPOerIbQ8A3n5wzCx6/ZzMVhBQ3sXNhaShb4b9/1YuwU/g==",
       "dev": true,
       "requires": {
         "loader-utils": "2.0.0",
@@ -143,20 +143,20 @@
       }
     },
     "@angular-devkit/build-webpack": {
-      "version": "0.1102.12",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1102.12.tgz",
-      "integrity": "sha512-AoqnveSLhkQznI3SBX7/uoOEs93EOi8/u1sdOU8QBicM53n/IcUPIjilwHL+CY8J0YKcxg4ESsN3LAFQCzYT6g==",
+      "version": "0.1102.14",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1102.14.tgz",
+      "integrity": "sha512-+dJvzrwjbHY0bNr8fUDVbn4D4pAT/h1YVpGVyaoX7q66LN0x61zRC3e10gJ/Mr54l3yfc26M0OPD9KG8iZRbCA==",
       "dev": true,
       "requires": {
-        "@angular-devkit/architect": "0.1102.12",
-        "@angular-devkit/core": "11.2.12",
+        "@angular-devkit/architect": "0.1102.14",
+        "@angular-devkit/core": "11.2.14",
         "rxjs": "6.6.3"
       }
     },
     "@angular-devkit/core": {
-      "version": "11.2.12",
-      "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.2.12.tgz",
-      "integrity": "sha512-VMRMmRj6ZX32cWpuA6vD4KSmji17yC4EtbXsiqrHZ8zAho4ifu8xImCC5PugTQnHa+RlIadOXwXX89aujUEwRw==",
+      "version": "11.2.14",
+      "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.2.14.tgz",
+      "integrity": "sha512-Ad1fHqLxDwhkQgLPqq9i+G65NSOoIHXQx7ILcSPACKurV3XLS1RO9BgP/BDaqHAG+WslUAPbMStaTzzPm+9dNw==",
       "dev": true,
       "requires": {
         "ajv": "6.12.6",
@@ -216,24 +216,6 @@
         "@typescript-eslint/experimental-utils": "4.16.1",
         "aria-query": "^4.2.2",
         "axobject-query": "^2.2.0"
-      },
-      "dependencies": {
-        "aria-query": {
-          "version": "4.2.2",
-          "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz",
-          "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==",
-          "dev": true,
-          "requires": {
-            "@babel/runtime": "^7.10.2",
-            "@babel/runtime-corejs3": "^7.10.2"
-          }
-        },
-        "axobject-query": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
-          "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==",
-          "dev": true
-        }
       }
     },
     "@angular-eslint/schematics": {
@@ -1856,12 +1838,12 @@
       }
     },
     "@ngtools/webpack": {
-      "version": "11.2.12",
-      "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-11.2.12.tgz",
-      "integrity": "sha512-YgzgJ72oGLvYVQH1c+pqJQRO5OE8axPt8HwPdueL/1g3rEwJgbeUrnIqw/eri7iTgFZflQRcePAA7dIz2uHwcw==",
+      "version": "11.2.14",
+      "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-11.2.14.tgz",
+      "integrity": "sha512-6q57tEWtUJRsxfTKE19L20iXvNesfVy8hrVdyzVk64DZQh0lIl4/xZT4d5bJCWOuQQDaAeZK4YbEFcYJn7k1yw==",
       "dev": true,
       "requires": {
-        "@angular-devkit/core": "11.2.12",
+        "@angular-devkit/core": "11.2.14",
         "enhanced-resolve": "5.7.0",
         "webpack-sources": "2.2.0"
       }
@@ -2274,9 +2256,9 @@
       "dev": true
     },
     "@types/marked": {
-      "version": "0.7.2",
-      "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.7.2.tgz",
-      "integrity": "sha512-A3EDyNaq6OCcpaOia2HQ/tu2QYt8DKuj4ExP21VU3cU3HTo2FLslvbqa2T1vux910RHvuSVqpwKnnykSFcRWOA=="
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@types/marked/-/marked-2.0.2.tgz",
+      "integrity": "sha512-P4zanhCQKs4tiWPPBGpB7lHflgFCP9DFGNI5YtpW9MALKoy2qs9rHNWJ+z55cegD9uCfnmsKuaosq9FNvbxrOw=="
     },
     "@types/minimatch": {
       "version": "3.0.4",
@@ -2755,9 +2737,9 @@
       "dev": true
     },
     "adjust-sourcemap-loader": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-3.0.0.tgz",
-      "integrity": "sha512-YBrGyT2/uVQ/c6Rr+t6ZJXniY03YtHGMJQYal368burRGYKqhx9qGTWqcBU5s1CwYY9E/ri63RYyG1IacMZtqw==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz",
+      "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==",
       "dev": true,
       "requires": {
         "loader-utils": "^2.0.0",
@@ -3053,12 +3035,6 @@
         "@babel/runtime-corejs3": "^7.10.2"
       }
     },
-    "arity-n": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz",
-      "integrity": "sha1-2edrEXM+CFacCEeuezmyhgswt0U=",
-      "dev": true
-    },
     "arr-diff": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
@@ -3328,6 +3304,11 @@
         "object.assign": "^4.1.0"
       }
     },
+    "badwords-list": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/badwords-list/-/badwords-list-1.0.0.tgz",
+      "integrity": "sha1-XphW2/E0gqKVw7CzBK+51M/FxXk="
+    },
     "balanced-match": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -3964,6 +3945,15 @@
         "is-glob": "~4.0.1",
         "normalize-path": "~3.0.0",
         "readdirp": "~3.5.0"
+      },
+      "dependencies": {
+        "fsevents": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+          "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+          "dev": true,
+          "optional": true
+        }
       }
     },
     "chownr": {
@@ -4107,17 +4097,6 @@
       "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
       "dev": true
     },
-    "clipboard": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz",
-      "integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==",
-      "optional": true,
-      "requires": {
-        "good-listener": "^1.2.2",
-        "select": "^1.1.2",
-        "tiny-emitter": "^2.0.0"
-      }
-    },
     "cliui": {
       "version": "7.0.4",
       "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
@@ -4176,16 +4155,6 @@
         "object-visit": "^1.0.0"
       }
     },
-    "color": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz",
-      "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==",
-      "dev": true,
-      "requires": {
-        "color-convert": "^1.9.1",
-        "color-string": "^1.5.4"
-      }
-    },
     "color-convert": {
       "version": "1.9.3",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -4199,15 +4168,11 @@
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
       "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
     },
-    "color-string": {
-      "version": "1.5.5",
-      "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz",
-      "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==",
-      "dev": true,
-      "requires": {
-        "color-name": "^1.0.0",
-        "simple-swizzle": "^0.2.2"
-      }
+    "colord": {
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/colord/-/colord-2.6.0.tgz",
+      "integrity": "sha512-8yMrtE20ZxH1YWvvSoeJFtvqY+GIAOfU+mZ3jx7ZSiEMasnAmNqD1BKUP3CuCWcy/XHgcXkLW6YU8C35nhOYVg==",
+      "dev": true
     },
     "colorette": {
       "version": "1.2.2",
@@ -4233,7 +4198,8 @@
     "commander": {
       "version": "2.20.0",
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
-      "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ=="
+      "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
+      "dev": true
     },
     "comment-parser": {
       "version": "1.1.5",
@@ -4253,15 +4219,6 @@
       "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
       "dev": true
     },
-    "compose-function": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/compose-function/-/compose-function-3.0.3.tgz",
-      "integrity": "sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8=",
-      "dev": true,
-      "requires": {
-        "arity-n": "^1.0.4"
-      }
-    },
     "compressible": {
       "version": "2.0.18",
       "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
@@ -4737,9 +4694,9 @@
       "dev": true
     },
     "css-declaration-sorter": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.0.0.tgz",
-      "integrity": "sha512-S0TE4E0ha5+tBHdLWPc5n+S8E4dFBS5xScPvgHkLNZwWvX4ISoFGhGeerLC9uS1cKA/sC+K2wHq6qEbcagT/fg==",
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.1.tgz",
+      "integrity": "sha512-BZ1aOuif2Sb7tQYY1GeCjG7F++8ggnwUkH5Ictw0mrdpqpEd+zWmcPdstnH2TItlb74FqR0DrVEieon221T/1Q==",
       "dev": true,
       "requires": {
         "timsort": "^0.3.0"
@@ -4842,15 +4799,15 @@
       }
     },
     "css-select": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/css-select/-/css-select-3.1.2.tgz",
-      "integrity": "sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA==",
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
+      "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==",
       "dev": true,
       "requires": {
         "boolbase": "^1.0.0",
-        "css-what": "^4.0.0",
-        "domhandler": "^4.0.0",
-        "domutils": "^2.4.3",
+        "css-what": "^5.0.0",
+        "domhandler": "^4.2.0",
+        "domutils": "^2.6.0",
         "nth-check": "^2.0.0"
       }
     },
@@ -4873,63 +4830,63 @@
       }
     },
     "css-what": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/css-what/-/css-what-4.0.0.tgz",
-      "integrity": "sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz",
+      "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==",
       "dev": true
     },
     "cssnano": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.1.tgz",
-      "integrity": "sha512-5WubEmKcK2cqw43DUAayRBiIlTdX7iX3ZowrWDVxSVcW3hyohVnbJ4K4mbnWtJp5rfJnUwHg5H4mDAGzmuCM3g==",
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.2.tgz",
+      "integrity": "sha512-8JK3EnPsjQsULme9/e5M2hF564f/480hwsdcHvQ7ZtAIMfQ1O3SCfs+b8Mjf5KJxhYApyRshR2QSovEJi2K72Q==",
       "dev": true,
       "requires": {
         "cosmiconfig": "^7.0.0",
-        "cssnano-preset-default": "^5.0.0",
+        "cssnano-preset-default": "^5.0.1",
         "is-resolvable": "^1.1.0"
       }
     },
     "cssnano-preset-default": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.0.1.tgz",
-      "integrity": "sha512-cfmfThYODGqhpQKDq9H0MTAqkMvZ3dGbOUTBKw0xWZiIycMqHid22LsJXJl4r1qX4qzDeKxcSyQ/Xb5Mu3Z//Q==",
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.3.tgz",
+      "integrity": "sha512-qo9tX+t4yAAZ/yagVV3b+QBKeLklQbmgR3wI7mccrDcR+bEk9iHgZN1E7doX68y9ThznLya3RDmR+nc7l6/2WQ==",
       "dev": true,
       "requires": {
-        "css-declaration-sorter": "6.0.0",
-        "cssnano-utils": "^2.0.0",
+        "css-declaration-sorter": "^6.0.3",
+        "cssnano-utils": "^2.0.1",
         "postcss-calc": "^8.0.0",
-        "postcss-colormin": "^5.0.0",
-        "postcss-convert-values": "^5.0.0",
-        "postcss-discard-comments": "^5.0.0",
-        "postcss-discard-duplicates": "^5.0.0",
-        "postcss-discard-empty": "^5.0.0",
-        "postcss-discard-overridden": "^5.0.0",
-        "postcss-merge-longhand": "^5.0.1",
-        "postcss-merge-rules": "^5.0.0",
-        "postcss-minify-font-values": "^5.0.0",
-        "postcss-minify-gradients": "^5.0.0",
-        "postcss-minify-params": "^5.0.0",
-        "postcss-minify-selectors": "^5.0.0",
-        "postcss-normalize-charset": "^5.0.0",
-        "postcss-normalize-display-values": "^5.0.0",
-        "postcss-normalize-positions": "^5.0.0",
-        "postcss-normalize-repeat-style": "^5.0.0",
-        "postcss-normalize-string": "^5.0.0",
-        "postcss-normalize-timing-functions": "^5.0.0",
-        "postcss-normalize-unicode": "^5.0.0",
-        "postcss-normalize-url": "^5.0.0",
-        "postcss-normalize-whitespace": "^5.0.0",
-        "postcss-ordered-values": "^5.0.0",
-        "postcss-reduce-initial": "^5.0.0",
-        "postcss-reduce-transforms": "^5.0.0",
-        "postcss-svgo": "^5.0.0",
-        "postcss-unique-selectors": "^5.0.0"
+        "postcss-colormin": "^5.2.0",
+        "postcss-convert-values": "^5.0.1",
+        "postcss-discard-comments": "^5.0.1",
+        "postcss-discard-duplicates": "^5.0.1",
+        "postcss-discard-empty": "^5.0.1",
+        "postcss-discard-overridden": "^5.0.1",
+        "postcss-merge-longhand": "^5.0.2",
+        "postcss-merge-rules": "^5.0.2",
+        "postcss-minify-font-values": "^5.0.1",
+        "postcss-minify-gradients": "^5.0.1",
+        "postcss-minify-params": "^5.0.1",
+        "postcss-minify-selectors": "^5.1.0",
+        "postcss-normalize-charset": "^5.0.1",
+        "postcss-normalize-display-values": "^5.0.1",
+        "postcss-normalize-positions": "^5.0.1",
+        "postcss-normalize-repeat-style": "^5.0.1",
+        "postcss-normalize-string": "^5.0.1",
+        "postcss-normalize-timing-functions": "^5.0.1",
+        "postcss-normalize-unicode": "^5.0.1",
+        "postcss-normalize-url": "^5.0.2",
+        "postcss-normalize-whitespace": "^5.0.1",
+        "postcss-ordered-values": "^5.0.2",
+        "postcss-reduce-initial": "^5.0.1",
+        "postcss-reduce-transforms": "^5.0.1",
+        "postcss-svgo": "^5.0.2",
+        "postcss-unique-selectors": "^5.0.1"
       }
     },
     "cssnano-utils": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-2.0.0.tgz",
-      "integrity": "sha512-xvxmTszdrvSyTACdPe8VU5J6p4sm3egpgw54dILvNqt5eBUv6TFjACLhSxtRuEsxYrgy8uDy269YjScO5aKbGA==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-2.0.1.tgz",
+      "integrity": "sha512-i8vLRZTnEH9ubIyfdZCAdIdgnHAUeQeByEeQ2I7oTilvP9oHO6RScpeq3GsFUVqeB8uZgOQ9pw8utofNn32hhQ==",
       "dev": true
     },
     "csso": {
@@ -4953,16 +4910,6 @@
       "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
       "dev": true
     },
-    "d": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
-      "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
-      "dev": true,
-      "requires": {
-        "es5-ext": "^0.10.50",
-        "type": "^1.0.1"
-      }
-    },
     "dashdash": {
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -5108,12 +5055,6 @@
       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
       "dev": true
     },
-    "delegate": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
-      "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
-      "optional": true
-    },
     "delegates": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@@ -5206,9 +5147,9 @@
       "dev": true
     },
     "dns-packet": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
-      "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
+      "version": "1.3.4",
+      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz",
+      "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==",
       "dev": true,
       "requires": {
         "ip": "^1.1.0",
@@ -5237,13 +5178,13 @@
       }
     },
     "dom-serializer": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.1.tgz",
-      "integrity": "sha512-Pv2ZluG5ife96udGgEDovOOOA5UELkltfJpnIExPrAk1LTvecolUGn6lIaoLh86d83GiB86CjzciMd9BuRB71Q==",
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
+      "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
       "dev": true,
       "requires": {
         "domelementtype": "^2.0.1",
-        "domhandler": "^4.0.0",
+        "domhandler": "^4.2.0",
         "entities": "^2.0.0"
       }
     },
@@ -5269,9 +5210,9 @@
       }
     },
     "domutils": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.6.0.tgz",
-      "integrity": "sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA==",
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
+      "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==",
       "dev": true,
       "requires": {
         "dom-serializer": "^1.0.1",
@@ -5279,15 +5220,6 @@
         "domhandler": "^4.2.0"
       }
     },
-    "dot-prop": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
-      "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
-      "dev": true,
-      "requires": {
-        "is-obj": "^2.0.0"
-      }
-    },
     "duplexify": {
       "version": "3.7.1",
       "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
@@ -5382,6 +5314,11 @@
       "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
       "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
     },
+    "emoji-toolkit": {
+      "version": "6.5.1",
+      "resolved": "https://registry.npmjs.org/emoji-toolkit/-/emoji-toolkit-6.5.1.tgz",
+      "integrity": "sha512-oY5E81cXvRUxXkbVgOI8NxYHKF5FeWfJhFCIYUKhbVfSmdCH8+bmJzgDdhufExa7t1+WEzpUFdHwYxJTXS90vQ=="
+    },
     "emojis-list": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
@@ -5560,28 +5497,6 @@
         "is-symbol": "^1.0.2"
       }
     },
-    "es5-ext": {
-      "version": "0.10.53",
-      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
-      "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
-      "dev": true,
-      "requires": {
-        "es6-iterator": "~2.0.3",
-        "es6-symbol": "~3.1.3",
-        "next-tick": "~1.0.0"
-      }
-    },
-    "es6-iterator": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
-      "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
-      "dev": true,
-      "requires": {
-        "d": "1",
-        "es5-ext": "^0.10.35",
-        "es6-symbol": "^3.1.1"
-      }
-    },
     "es6-promise": {
       "version": "4.2.8",
       "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
@@ -5597,16 +5512,6 @@
         "es6-promise": "^4.0.3"
       }
     },
-    "es6-symbol": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
-      "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
-      "dev": true,
-      "requires": {
-        "d": "^1.0.1",
-        "ext": "^1.1.2"
-      }
-    },
     "escalade": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -6268,23 +6173,6 @@
         }
       }
     },
-    "ext": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
-      "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
-      "dev": true,
-      "requires": {
-        "type": "^2.0.0"
-      },
-      "dependencies": {
-        "type": {
-          "version": "2.5.0",
-          "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz",
-          "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==",
-          "dev": true
-        }
-      }
-    },
     "extend": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -6831,11 +6719,15 @@
       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
     },
     "fsevents": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
-      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+      "version": "1.2.13",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+      "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
       "dev": true,
-      "optional": true
+      "optional": true,
+      "requires": {
+        "bindings": "^1.5.0",
+        "nan": "^2.12.1"
+      }
     },
     "function-bind": {
       "version": "1.1.1",
@@ -6989,15 +6881,6 @@
         "slash": "^3.0.0"
       }
     },
-    "good-listener": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
-      "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
-      "optional": true,
-      "requires": {
-        "delegate": "^3.1.2"
-      }
-    },
     "graceful-fs": {
       "version": "4.2.6",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
@@ -7639,12 +7522,6 @@
       "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
       "dev": true
     },
-    "indexes-of": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
-      "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=",
-      "dev": true
-    },
     "infer-owner": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
@@ -7987,12 +7864,6 @@
       "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==",
       "dev": true
     },
-    "is-obj": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
-      "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
-      "dev": true
-    },
     "is-path-cwd": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
@@ -8109,6 +7980,13 @@
         }
       }
     },
+    "isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+      "dev": true,
+      "optional": true
+    },
     "isbinaryfile": {
       "version": "4.0.8",
       "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz",
@@ -8571,11 +8449,18 @@
       }
     },
     "katex": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/katex/-/katex-0.11.1.tgz",
-      "integrity": "sha512-5oANDICCTX0NqYIyAiFCCwjQ7ERu3DQG2JFHLbYOf+fXaMoH8eg/zOq5WSYJsKMi/QebW+Eh3gSM+oss1H/bww==",
+      "version": "0.13.11",
+      "resolved": "https://registry.npmjs.org/katex/-/katex-0.13.11.tgz",
+      "integrity": "sha512-yJBHVIgwlAaapzlbvTpVF/ZOs8UkTj/sd46Fl8+qAf2/UiituPYVeapVD8ADZtqyRg/qNWUKt7gJoyYVWLrcXw==",
       "requires": {
-        "commander": "^2.19.0"
+        "commander": "^6.0.0"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "6.2.1",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+          "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="
+        }
       }
     },
     "killable": {
@@ -8998,9 +8883,9 @@
       }
     },
     "marked": {
-      "version": "0.8.0",
-      "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.0.tgz",
-      "integrity": "sha512-MyUe+T/Pw4TZufHkzAfDj6HarCBWia2y27/bhuYkTaiUnfDYFnCP3KUN+9oM7Wi6JA2rymtVYbQu3spE0GCmxQ=="
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-2.0.3.tgz",
+      "integrity": "sha512-5otztIIcJfPc2qGTN8cVtOJEjNJZ0jwa46INMagrYfk0EvqtRuEHLsEe0LrFS0/q+ZRKT0+kXK7P2T1AN5lWRA=="
     },
     "mat-color-picker": {
       "version": "1.4.3",
@@ -9518,9 +9403,9 @@
       "optional": true
     },
     "nanoid": {
-      "version": "3.1.22",
-      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz",
-      "integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==",
+      "version": "3.1.23",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
+      "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==",
       "dev": true
     },
     "nanomatch": {
@@ -9548,6 +9433,11 @@
       "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
       "dev": true
     },
+    "naughty-words": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/naughty-words/-/naughty-words-1.2.0.tgz",
+      "integrity": "sha512-0iadX6fN+3NsfvIRtWmmpEX9VsoIQ6n9FwyIxmew9w5yzFNqMgs/Ky0eAC/z5xXSHtqlVoByiovdROikwH9SXQ=="
+    },
     "needle": {
       "version": "2.6.0",
       "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz",
@@ -9591,12 +9481,6 @@
       "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
       "dev": true
     },
-    "next-tick": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
-      "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
-      "dev": true
-    },
     "ngx-color-picker": {
       "version": "11.0.0",
       "resolved": "https://registry.npmjs.org/ngx-color-picker/-/ngx-color-picker-11.0.0.tgz",
@@ -9605,15 +9489,25 @@
         "tslib": "^2.0.0"
       }
     },
-    "ngx-markdown": {
-      "version": "9.0.0",
-      "resolved": "https://registry.npmjs.org/ngx-markdown/-/ngx-markdown-9.0.0.tgz",
-      "integrity": "sha512-wcXMxA4Skgk9SzhfDRjihap/Kjq17jmMQiE/Ccp0bNibGaDgS5DbZiPBlMNLkp669UvjY9wVuxE4NuDtmQHS9w==",
+    "ngx-joyride": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/ngx-joyride/-/ngx-joyride-2.4.0.tgz",
+      "integrity": "sha512-r6Zp4FPwTqIceCWPoeSgxo+wLuT/teMcixyjKxuGRBZwsqwau+eYiWcf1Khw1U6Gie448gtOr7SJG30/EnRd1Q==",
       "requires": {
-        "@types/marked": "^0.7.2",
-        "katex": "^0.11.0",
-        "marked": "^0.8.0",
-        "prismjs": "^1.16.0"
+        "tslib": "^2.0.0"
+      }
+    },
+    "ngx-markdown": {
+      "version": "11.1.3",
+      "resolved": "https://registry.npmjs.org/ngx-markdown/-/ngx-markdown-11.1.3.tgz",
+      "integrity": "sha512-z32q8l76ubrcP62L03mdvrizwueLBHV10LkT8MEDnFcjmY+8J1PytxFJ9EBTJpvc+CaPolgAoi7felN2XJZTSg==",
+      "requires": {
+        "@types/marked": "^2.0.0",
+        "emoji-toolkit": "^6.0.1",
+        "katex": "^0.13.0",
+        "marked": "^2.0.0",
+        "prismjs": "^1.23.0",
+        "tslib": "^2.0.0"
       }
     },
     "ngx-matomo": {
@@ -9816,9 +9710,9 @@
       "dev": true
     },
     "normalize-url": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
-      "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==",
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
+      "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
       "dev": true
     },
     "npm-bundled": {
@@ -10769,13 +10663,13 @@
       "dev": true
     },
     "postcss": {
-      "version": "8.2.13",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.13.tgz",
-      "integrity": "sha512-FCE5xLH+hjbzRdpbRb1IMCvPv9yZx2QnDarBEYSN0N0HYk+TcXsEhwdFcFb+SRWOKzKGErhIEbBK2ogyLdTtfQ==",
+      "version": "8.2.15",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz",
+      "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==",
       "dev": true,
       "requires": {
         "colorette": "^1.2.2",
-        "nanoid": "^3.1.22",
+        "nanoid": "^3.1.23",
         "source-map": "^0.6.1"
       },
       "dependencies": {
@@ -10798,47 +10692,48 @@
       }
     },
     "postcss-colormin": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.0.0.tgz",
-      "integrity": "sha512-Yt84+5V6CgS/AhK7d7MA58vG8dSZ7+ytlRtWLaQhag3HXOncTfmYpuUOX4cDoXjvLfw1sHRCHMiBjYhc35CymQ==",
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.0.tgz",
+      "integrity": "sha512-+HC6GfWU3upe5/mqmxuqYZ9B2Wl4lcoUUNkoaX59nEWV4EtADCMiBqui111Bu8R8IvaZTmqmxrqOAqjbHIwXPw==",
       "dev": true,
       "requires": {
-        "browserslist": "^4.16.0",
-        "color": "^3.1.1",
+        "browserslist": "^4.16.6",
+        "caniuse-api": "^3.0.0",
+        "colord": "^2.0.1",
         "postcss-value-parser": "^4.1.0"
       }
     },
     "postcss-convert-values": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.0.tgz",
-      "integrity": "sha512-V5kmYm4xoBAjNs+eHY/6XzXJkkGeg4kwNf2ocfqhLb1WBPEa4oaSmoi1fnVO7Dkblqvus9h+AenDvhCKUCK7uQ==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.1.tgz",
+      "integrity": "sha512-C3zR1Do2BkKkCgC0g3sF8TS0koF2G+mN8xxayZx3f10cIRmTaAnpgpRQZjNekTZxM2ciSPoh2IWJm0VZx8NoQg==",
       "dev": true,
       "requires": {
         "postcss-value-parser": "^4.1.0"
       }
     },
     "postcss-discard-comments": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.0.tgz",
-      "integrity": "sha512-Umig6Gxs8m20RihiXY6QkePd6mp4FxkA1Dg+f/Kd6uw0gEMfKRjDeQOyFkLibexbJJGHpE3lrN/Q0R9SMrUMbQ==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.1.tgz",
+      "integrity": "sha512-lgZBPTDvWrbAYY1v5GYEv8fEO/WhKOu/hmZqmCYfrpD6eyDWWzAOsl2rF29lpvziKO02Gc5GJQtlpkTmakwOWg==",
       "dev": true
     },
     "postcss-discard-duplicates": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.0.tgz",
-      "integrity": "sha512-vEJJ+Y3pFUnO1FyCBA6PSisGjHtnphL3V6GsNvkASq/VkP3OX5/No5RYXXLxHa2QegStNzg6HYrYdo71uR4caQ==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.1.tgz",
+      "integrity": "sha512-svx747PWHKOGpAXXQkCc4k/DsWo+6bc5LsVrAsw+OU+Ibi7klFZCyX54gjYzX4TH+f2uzXjRviLARxkMurA2bA==",
       "dev": true
     },
     "postcss-discard-empty": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.0.tgz",
-      "integrity": "sha512-+wigy099Y1xZxG36WG5L1f2zeH1oicntkJEW4TDIqKKDO2g9XVB3OhoiHTu08rDEjLnbcab4rw0BAccwi2VjiQ==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.1.tgz",
+      "integrity": "sha512-vfU8CxAQ6YpMxV2SvMcMIyF2LX1ZzWpy0lqHDsOdaKKLQVQGVP1pzhrI9JlsO65s66uQTfkQBKBD/A5gp9STFw==",
       "dev": true
     },
     "postcss-discard-overridden": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.0.tgz",
-      "integrity": "sha512-hybnScTaZM2iEA6kzVQ6Spozy7kVdLw+lGw8hftLlBEzt93uzXoltkYp9u0tI8xbfhxDLTOOzHsHQCkYdmzRUg==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.1.tgz",
+      "integrity": "sha512-Y28H7y93L2BpJhrdUR2SR2fnSsT+3TVx1NmVQLbcnZWwIUpJ7mfcTC6Za9M2PG6w8j7UQRfzxqn8jU2VwFxo3Q==",
       "dev": true
     },
     "postcss-import": {
@@ -10888,83 +10783,70 @@
       }
     },
     "postcss-merge-longhand": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.1.tgz",
-      "integrity": "sha512-H1RO8le5deFGumQzuhJjuL0bIXPRysa+w7xtk5KrHe38oiaSS9ksPXDo24+IOS3SETPhip0J5+1uCOW+ALs3Yw==",
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.2.tgz",
+      "integrity": "sha512-BMlg9AXSI5G9TBT0Lo/H3PfUy63P84rVz3BjCFE9e9Y9RXQZD3+h3YO1kgTNsNJy7bBc1YQp8DmSnwLIW5VPcw==",
       "dev": true,
       "requires": {
         "css-color-names": "^1.0.1",
         "postcss-value-parser": "^4.1.0",
-        "stylehacks": "^5.0.0"
+        "stylehacks": "^5.0.1"
       }
     },
     "postcss-merge-rules": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.0.tgz",
-      "integrity": "sha512-TfsXbKjNYCGfUPEXGIGPySnMiJbdS+3gcVeV8gwmJP4RajyKZHW8E0FYDL1WmggTj3hi+m+WUCAvqRpX2ut4Kg==",
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.2.tgz",
+      "integrity": "sha512-5K+Md7S3GwBewfB4rjDeol6V/RZ8S+v4B66Zk2gChRqLTCC8yjnHQ601omj9TKftS19OPGqZ/XzoqpzNQQLwbg==",
       "dev": true,
       "requires": {
-        "browserslist": "^4.16.0",
+        "browserslist": "^4.16.6",
         "caniuse-api": "^3.0.0",
-        "cssnano-utils": "^2.0.0",
-        "postcss-selector-parser": "^6.0.4",
+        "cssnano-utils": "^2.0.1",
+        "postcss-selector-parser": "^6.0.5",
         "vendors": "^1.0.3"
       }
     },
     "postcss-minify-font-values": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.0.tgz",
-      "integrity": "sha512-zi2JhFaMOcIaNxhndX5uhsqSY1rexKDp23wV8EOmC9XERqzLbHsoRye3aYF716Zm+hkcR4loqKDt8LZlmihwAg==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.1.tgz",
+      "integrity": "sha512-7JS4qIsnqaxk+FXY1E8dHBDmraYFWmuL6cgt0T1SWGRO5bzJf8sUoelwa4P88LEWJZweHevAiDKxHlofuvtIoA==",
       "dev": true,
       "requires": {
         "postcss-value-parser": "^4.1.0"
       }
     },
     "postcss-minify-gradients": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.0.tgz",
-      "integrity": "sha512-/jPtNgs6JySMwgsE5dPOq8a2xEopWTW3RyqoB9fLqxgR+mDUNLSi7joKd+N1z7FXWgVkc4l/dEBMXHgNAaUbvg==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.1.tgz",
+      "integrity": "sha512-odOwBFAIn2wIv+XYRpoN2hUV3pPQlgbJ10XeXPq8UY2N+9ZG42xu45lTn/g9zZ+d70NKSQD6EOi6UiCMu3FN7g==",
       "dev": true,
       "requires": {
-        "cssnano-utils": "^2.0.0",
+        "cssnano-utils": "^2.0.1",
         "is-color-stop": "^1.1.0",
         "postcss-value-parser": "^4.1.0"
       }
     },
     "postcss-minify-params": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.0.tgz",
-      "integrity": "sha512-KvZYIxTPBVKjdd+XgObq9A+Sfv8lMkXTpbZTsjhr42XbfWIeLaTItMlygsDWfjArEc3muUfDaUFgNSeDiJ5jug==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.1.tgz",
+      "integrity": "sha512-4RUC4k2A/Q9mGco1Z8ODc7h+A0z7L7X2ypO1B6V8057eVK6mZ6xwz6QN64nHuHLbqbclkX1wyzRnIrdZehTEHw==",
       "dev": true,
       "requires": {
         "alphanum-sort": "^1.0.2",
         "browserslist": "^4.16.0",
-        "cssnano-utils": "^2.0.0",
+        "cssnano-utils": "^2.0.1",
         "postcss-value-parser": "^4.1.0",
         "uniqs": "^2.0.0"
       }
     },
     "postcss-minify-selectors": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.0.0.tgz",
-      "integrity": "sha512-cEM0O0eWwFIvmo6nfB0lH0vO/XFwgqIvymODbfPXZ1gTA3i76FKnb7TGUrEpiTxaXH6tgYQ6DcTHwRiRS+YQLQ==",
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.0.tgz",
+      "integrity": "sha512-NzGBXDa7aPsAcijXZeagnJBKBPMYLaJJzB8CQh6ncvyl2sIndLVWfbcDi0SBjRWk5VqEjXvf8tYwzoKf4Z07og==",
       "dev": true,
       "requires": {
         "alphanum-sort": "^1.0.2",
-        "postcss-selector-parser": "^3.1.2"
-      },
-      "dependencies": {
-        "postcss-selector-parser": {
-          "version": "3.1.2",
-          "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz",
-          "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==",
-          "dev": true,
-          "requires": {
-            "dot-prop": "^5.2.0",
-            "indexes-of": "^1.0.1",
-            "uniq": "^1.0.1"
-          }
-        }
+        "postcss-selector-parser": "^6.0.5"
       }
     },
     "postcss-modules-extract-imports": {
@@ -11003,63 +10885,63 @@
       }
     },
     "postcss-normalize-charset": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.0.tgz",
-      "integrity": "sha512-pqsCkgo9KmQP0ew6DqSA+uP9YN6EfsW20pQ3JU5JoQge09Z6Too4qU0TNDsTNWuEaP8SWsMp+19l15210MsDZQ==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.1.tgz",
+      "integrity": "sha512-6J40l6LNYnBdPSk+BHZ8SF+HAkS4q2twe5jnocgd+xWpz/mx/5Sa32m3W1AA8uE8XaXN+eg8trIlfu8V9x61eg==",
       "dev": true
     },
     "postcss-normalize-display-values": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.0.tgz",
-      "integrity": "sha512-t4f2d//gH1f7Ns0Jq3eNdnWuPT7TeLuISZ6RQx4j8gpl5XrhkdshdNcOnlrEK48YU6Tcb6jqK7dorME3N4oOGA==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.1.tgz",
+      "integrity": "sha512-uupdvWk88kLDXi5HEyI9IaAJTE3/Djbcrqq8YgjvAVuzgVuqIk3SuJWUisT2gaJbZm1H9g5k2w1xXilM3x8DjQ==",
       "dev": true,
       "requires": {
-        "cssnano-utils": "^2.0.0",
+        "cssnano-utils": "^2.0.1",
         "postcss-value-parser": "^4.1.0"
       }
     },
     "postcss-normalize-positions": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.0.tgz",
-      "integrity": "sha512-0o6/qU5ky74X/eWYj/tv4iiKCm3YqJnrhmVADpIMNXxzFZywsSQxl8F7cKs8jQEtF3VrJBgcDHTexZy1zgDoYg==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.1.tgz",
+      "integrity": "sha512-rvzWAJai5xej9yWqlCb1OWLd9JjW2Ex2BCPzUJrbaXmtKtgfL8dBMOOMTX6TnvQMtjk3ei1Lswcs78qKO1Skrg==",
       "dev": true,
       "requires": {
         "postcss-value-parser": "^4.1.0"
       }
     },
     "postcss-normalize-repeat-style": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.0.tgz",
-      "integrity": "sha512-KRT14JbrXKcFMYuc4q7lh8lvv8u22wLyMrq+UpHKLtbx2H/LOjvWXYdoDxmNrrrJzomAWL+ViEXr48/IhSUJnQ==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.1.tgz",
+      "integrity": "sha512-syZ2itq0HTQjj4QtXZOeefomckiV5TaUO6ReIEabCh3wgDs4Mr01pkif0MeVwKyU/LHEkPJnpwFKRxqWA/7O3w==",
       "dev": true,
       "requires": {
-        "cssnano-utils": "^2.0.0",
+        "cssnano-utils": "^2.0.1",
         "postcss-value-parser": "^4.1.0"
       }
     },
     "postcss-normalize-string": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.0.tgz",
-      "integrity": "sha512-wSO4pf7GNcDZpmelREWYADF1+XZWrAcbFLQCOqoE92ZwYgaP/RLumkUTaamEzdT2YKRZAH8eLLKGWotU/7FNPw==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.1.tgz",
+      "integrity": "sha512-Ic8GaQ3jPMVl1OEn2U//2pm93AXUcF3wz+OriskdZ1AOuYV25OdgS7w9Xu2LO5cGyhHCgn8dMXh9bO7vi3i9pA==",
       "dev": true,
       "requires": {
         "postcss-value-parser": "^4.1.0"
       }
     },
     "postcss-normalize-timing-functions": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.0.tgz",
-      "integrity": "sha512-TwPaDX+wl9wO3MUm23lzGmOzGCGKnpk+rSDgzB2INpakD5dgWR3L6bJq1P1LQYzBAvz8fRIj2NWdnZdV4EV98Q==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.1.tgz",
+      "integrity": "sha512-cPcBdVN5OsWCNEo5hiXfLUnXfTGtSFiBU9SK8k7ii8UD7OLuznzgNRYkLZow11BkQiiqMcgPyh4ZqXEEUrtQ1Q==",
       "dev": true,
       "requires": {
-        "cssnano-utils": "^2.0.0",
+        "cssnano-utils": "^2.0.1",
         "postcss-value-parser": "^4.1.0"
       }
     },
     "postcss-normalize-unicode": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.0.tgz",
-      "integrity": "sha512-2CpVoz/67rXU5s9tsPZDxG1YGS9OFHwoY9gsLAzrURrCxTAb0H7Vp87/62LvVPgRWTa5ZmvgmqTp2rL8tlm72A==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.1.tgz",
+      "integrity": "sha512-kAtYD6V3pK0beqrU90gpCQB7g6AOfP/2KIPCVBKJM2EheVsBQmx/Iof+9zR9NFKLAx4Pr9mDhogB27pmn354nA==",
       "dev": true,
       "requires": {
         "browserslist": "^4.16.0",
@@ -11067,39 +10949,39 @@
       }
     },
     "postcss-normalize-url": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.0.tgz",
-      "integrity": "sha512-ICDaGFBqLgA3dlrCIRuhblLl80D13YtgEV9NJPTYJtgR72vu61KgxAHv+z/lKMs1EbwfSQa3ALjOFLSmXiE34A==",
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.2.tgz",
+      "integrity": "sha512-k4jLTPUxREQ5bpajFQZpx8bCF2UrlqOTzP9kEqcEnOfwsRshWs2+oAFIHfDQB8GO2PaUaSE0NlTAYtbluZTlHQ==",
       "dev": true,
       "requires": {
         "is-absolute-url": "^3.0.3",
-        "normalize-url": "^4.5.0",
+        "normalize-url": "^6.0.1",
         "postcss-value-parser": "^4.1.0"
       }
     },
     "postcss-normalize-whitespace": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.0.tgz",
-      "integrity": "sha512-KRnxQvQAVkJfaeXSz7JlnD9nBN9sFZF9lrk9452Q2uRoqrRSkinqifF8Iex7wZGei2DZVG/qpmDFDmRvbNAOGA==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.1.tgz",
+      "integrity": "sha512-iPklmI5SBnRvwceb/XH568yyzK0qRVuAG+a1HFUsFRf11lEJTiQQa03a4RSCQvLKdcpX7XsI1Gen9LuLoqwiqA==",
       "dev": true,
       "requires": {
         "postcss-value-parser": "^4.1.0"
       }
     },
     "postcss-ordered-values": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.0.tgz",
-      "integrity": "sha512-dPr+SRObiHueCIc4IUaG0aOGQmYkuNu50wQvdXTGKy+rzi2mjmPsbeDsheLk5WPb9Zyf2tp8E+I+h40cnivm6g==",
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.2.tgz",
+      "integrity": "sha512-8AFYDSOYWebJYLyJi3fyjl6CqMEG/UVworjiyK1r573I56kb3e879sCJLGvR3merj+fAdPpVplXKQZv+ey6CgQ==",
       "dev": true,
       "requires": {
-        "cssnano-utils": "^2.0.0",
+        "cssnano-utils": "^2.0.1",
         "postcss-value-parser": "^4.1.0"
       }
     },
     "postcss-reduce-initial": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.0.tgz",
-      "integrity": "sha512-wR6pXUaFbSMG1oCKx8pKVA+rnSXCHlca5jMrlmkmif+uig0HNUTV9oGN5kjKsM3mATQAldv2PF9Tbl2vqLFjnA==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.1.tgz",
+      "integrity": "sha512-zlCZPKLLTMAqA3ZWH57HlbCjkD55LX9dsRyxlls+wfuRfqCi5mSlZVan0heX5cHr154Dq9AfbH70LyhrSAezJw==",
       "dev": true,
       "requires": {
         "browserslist": "^4.16.0",
@@ -11107,12 +10989,12 @@
       }
     },
     "postcss-reduce-transforms": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.0.tgz",
-      "integrity": "sha512-iHdGODW4YzM3WjVecBhPQt6fpJC4lGQZxJKjkBNHpp2b8dzmvj0ogKThqya+IRodQEFzjfXgYeESkf172FH5Lw==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.1.tgz",
+      "integrity": "sha512-a//FjoPeFkRuAguPscTVmRQUODP+f3ke2HqFNgGPwdYnpeC29RZdCBvGRGTsKpMURb/I3p6jdKoBQ2zI+9Q7kA==",
       "dev": true,
       "requires": {
-        "cssnano-utils": "^2.0.0",
+        "cssnano-utils": "^2.0.1",
         "postcss-value-parser": "^4.1.0"
       }
     },
@@ -11135,9 +11017,9 @@
       }
     },
     "postcss-svgo": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.0.tgz",
-      "integrity": "sha512-M3/VS4sFI1Yp9g0bPL+xzzCNz5iLdRUztoFaugMit5a8sMfkVzzhwqbsOlD8IFFymCdJDmXmh31waYHWw1K4BA==",
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.2.tgz",
+      "integrity": "sha512-YzQuFLZu3U3aheizD+B1joQ94vzPfE6BNUcSYuceNxlVnKKsOtdo6hL9/zyC168Q8EwfLSgaDSalsUGa9f2C0A==",
       "dev": true,
       "requires": {
         "postcss-value-parser": "^4.1.0",
@@ -11145,13 +11027,13 @@
       }
     },
     "postcss-unique-selectors": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.0.tgz",
-      "integrity": "sha512-o9l4pF8SRn7aCMTmzb/kNv/kjV7wPZpZ8Nlb1Gq8v/Qvw969K1wanz1RVA0ehHzWe9+wHXaC2DvZlak/gdMJ5w==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.1.tgz",
+      "integrity": "sha512-gwi1NhHV4FMmPn+qwBNuot1sG1t2OmacLQ/AX29lzyggnjd+MnVD5uqQmpXO3J17KGL2WAxQruj1qTd3H0gG/w==",
       "dev": true,
       "requires": {
         "alphanum-sort": "^1.0.2",
-        "postcss-selector-parser": "^6.0.2",
+        "postcss-selector-parser": "^6.0.5",
         "uniqs": "^2.0.0"
       }
     },
@@ -11174,12 +11056,9 @@
       "dev": true
     },
     "prismjs": {
-      "version": "1.23.0",
-      "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz",
-      "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==",
-      "requires": {
-        "clipboard": "^2.0.0"
-      }
+      "version": "1.24.1",
+      "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.24.1.tgz",
+      "integrity": "sha512-mNPsedLuk90RVJioIky8ANZEwYm5w9LcvCXrxHlwf4fNVSn8jEipMybMkWUyyF0JhnC+C4VcOVSBuHRKs1L5Ow=="
     },
     "process": {
       "version": "0.11.10",
@@ -11634,13 +11513,6 @@
             "which-module": "^2.0.0",
             "y18n": "^4.0.0",
             "yargs-parser": "^13.1.1"
-          },
-          "dependencies": {
-            "y18n": {
-              "version": "4.0.3",
-              "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
-              "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
-            }
           }
         },
         "yargs-parser": {
@@ -12026,53 +11898,22 @@
       "dev": true
     },
     "resolve-url-loader": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.2.tgz",
-      "integrity": "sha512-QEb4A76c8Mi7I3xNKXlRKQSlLBwjUV/ULFMP+G7n3/7tJZ8MG5wsZ3ucxP1Jz8Vevn6fnJsxDx9cIls+utGzPQ==",
-      "dev": true,
-      "requires": {
-        "adjust-sourcemap-loader": "3.0.0",
-        "camelcase": "5.3.1",
-        "compose-function": "3.0.3",
-        "convert-source-map": "1.7.0",
-        "es6-iterator": "2.0.3",
-        "loader-utils": "1.2.3",
-        "postcss": "7.0.21",
-        "rework": "1.0.1",
-        "rework-visit": "1.0.0",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz",
+      "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==",
+      "dev": true,
+      "requires": {
+        "adjust-sourcemap-loader": "^4.0.0",
+        "convert-source-map": "^1.7.0",
+        "loader-utils": "^2.0.0",
+        "postcss": "^7.0.35",
         "source-map": "0.6.1"
       },
       "dependencies": {
-        "emojis-list": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
-          "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
-          "dev": true
-        },
-        "json5": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
-          "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
-          "dev": true,
-          "requires": {
-            "minimist": "^1.2.0"
-          }
-        },
-        "loader-utils": {
-          "version": "1.2.3",
-          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz",
-          "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==",
-          "dev": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^2.0.0",
-            "json5": "^1.0.1"
-          }
-        },
         "postcss": {
-          "version": "7.0.21",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz",
-          "integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==",
+          "version": "7.0.36",
+          "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
+          "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
           "dev": true,
           "requires": {
             "chalk": "^2.4.2",
@@ -12125,61 +11966,6 @@
       "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
       "dev": true
     },
-    "rework": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz",
-      "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=",
-      "dev": true,
-      "requires": {
-        "convert-source-map": "^0.3.3",
-        "css": "^2.0.0"
-      },
-      "dependencies": {
-        "convert-source-map": {
-          "version": "0.3.5",
-          "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz",
-          "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=",
-          "dev": true
-        },
-        "css": {
-          "version": "2.2.4",
-          "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz",
-          "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==",
-          "dev": true,
-          "requires": {
-            "inherits": "^2.0.3",
-            "source-map": "^0.6.1",
-            "source-map-resolve": "^0.5.2",
-            "urix": "^0.1.0"
-          }
-        },
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        },
-        "source-map-resolve": {
-          "version": "0.5.3",
-          "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
-          "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
-          "dev": true,
-          "requires": {
-            "atob": "^2.1.2",
-            "decode-uri-component": "^0.2.0",
-            "resolve-url": "^0.2.1",
-            "source-map-url": "^0.4.0",
-            "urix": "^0.1.0"
-          }
-        }
-      }
-    },
-    "rework-visit": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz",
-      "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=",
-      "dev": true
-    },
     "rfdc": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
@@ -12224,6 +12010,15 @@
       "dev": true,
       "requires": {
         "fsevents": "~2.3.1"
+      },
+      "dependencies": {
+        "fsevents": {
+          "version": "2.3.2",
+          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+          "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+          "dev": true,
+          "optional": true
+        }
       }
     },
     "run-async": {
@@ -12391,12 +12186,6 @@
         "ajv-keywords": "^3.5.2"
       }
     },
-    "select": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
-      "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=",
-      "optional": true
-    },
     "select-hose": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -12638,23 +12427,6 @@
       "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
       "dev": true
     },
-    "simple-swizzle": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
-      "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
-      "dev": true,
-      "requires": {
-        "is-arrayish": "^0.3.1"
-      },
-      "dependencies": {
-        "is-arrayish": {
-          "version": "0.3.2",
-          "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
-          "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
-          "dev": true
-        }
-      }
-    },
     "slash": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
@@ -13659,9 +13431,9 @@
       }
     },
     "stylehacks": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.0.tgz",
-      "integrity": "sha512-QOWm6XivDLb+fqffTZP8jrmPmPITVChl2KCY2R05nsCWwLi3VGhCdVc3IVGNwd1zzTt1jPd67zIKjpQfxzQZeA==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.1.tgz",
+      "integrity": "sha512-Es0rVnHIqbWzveU1b24kbw92HsebBepxfcqe5iix7t9j0PQqhs0IxXVXv0pY2Bxa08CgMkzD6OWql7kbGOuEdA==",
       "dev": true,
       "requires": {
         "browserslist": "^4.16.0",
@@ -13767,15 +13539,15 @@
       }
     },
     "svgo": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.3.0.tgz",
-      "integrity": "sha512-fz4IKjNO6HDPgIQxu4IxwtubtbSfGEAJUq/IXyTPIkGhWck/faiiwfkvsB8LnBkKLvSoyNNIY6d13lZprJMc9Q==",
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.3.1.tgz",
+      "integrity": "sha512-riDDIQgXpEnn0BEl9Gvhh1LNLIyiusSpt64IR8upJu7MwxnzetmF/Y57pXQD2NMX2lVyMRzXt5f2M5rO4wG7Dw==",
       "dev": true,
       "requires": {
         "@trysound/sax": "0.1.1",
         "chalk": "^4.1.0",
         "commander": "^7.1.0",
-        "css-select": "^3.1.2",
+        "css-select": "^4.1.3",
         "css-tree": "^1.1.2",
         "csso": "^4.2.0",
         "stable": "^0.1.8"
@@ -13791,9 +13563,9 @@
           }
         },
         "chalk": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
-          "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
+          "version": "4.1.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
           "dev": true,
           "requires": {
             "ansi-styles": "^4.1.0",
@@ -13900,9 +13672,9 @@
       "dev": true
     },
     "tar": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
-      "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
+      "version": "6.1.6",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.6.tgz",
+      "integrity": "sha512-oaWyu5dQbHaYcyZCTfyPpC+VmI62/OM2RTUYavTk1MDr1cwW5Boi3baeYQKiZbY2uSQJGr+iMOzb/JFxLrft+g==",
       "dev": true,
       "requires": {
         "chownr": "^2.0.0",
@@ -14063,12 +13835,6 @@
       "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
       "dev": true
     },
-    "tiny-emitter": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
-      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
-      "optional": true
-    },
     "tmp": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
@@ -14248,12 +14014,6 @@
       "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
       "dev": true
     },
-    "type": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
-      "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
-      "dev": true
-    },
     "type-check": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -14362,12 +14122,6 @@
         }
       }
     },
-    "uniq": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
-      "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=",
-      "dev": true
-    },
     "uniqs": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz",
@@ -14772,17 +14526,6 @@
             }
           }
         },
-        "fsevents": {
-          "version": "1.2.13",
-          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
-          "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "bindings": "^1.5.0",
-            "nan": "^2.12.1"
-          }
-        },
         "glob-parent": {
           "version": "3.1.0",
           "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
@@ -14845,13 +14588,6 @@
             }
           }
         },
-        "isarray": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-          "dev": true,
-          "optional": true
-        },
         "micromatch": {
           "version": "3.1.10",
           "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@@ -15648,17 +15384,6 @@
             "locate-path": "^3.0.0"
           }
         },
-        "fsevents": {
-          "version": "1.2.13",
-          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
-          "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "bindings": "^1.5.0",
-            "nan": "^2.12.1"
-          }
-        },
         "glob-parent": {
           "version": "3.1.0",
           "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
@@ -15949,9 +15674,9 @@
           }
         },
         "ws": {
-          "version": "6.2.1",
-          "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
-          "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
+          "version": "6.2.2",
+          "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
+          "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
           "dev": true,
           "requires": {
             "async-limiter": "~1.0.0"
@@ -16271,9 +15996,9 @@
       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
     },
     "ws": {
-      "version": "7.4.5",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz",
-      "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==",
+      "version": "7.4.6",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
+      "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
       "dev": true
     },
     "xml2js": {
@@ -16301,8 +16026,7 @@
     "y18n": {
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
-      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
-      "dev": true
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
     },
     "yallist": {
       "version": "4.0.0",
diff --git a/package.json b/package.json
index b4859819ff5162d1408de08e5b619cf3682a2198..1ed0a97bf0f8f4c87f8d3adc2aff26c0ea5ee26e 100644
--- a/package.json
+++ b/package.json
@@ -31,17 +31,23 @@
     "@stomp/ng2-stompjs": "^7.2.0",
     "angular-tag-cloud-module": "^5.3.0",
     "angularx-qrcode": "^11.0.0",
+    "badwords-list": "^1.0.0",
     "chart.js": "^2.9.4",
     "core-js": "^2.5.7",
+    "emoji-toolkit": "^6.5.1",
     "get-stream": "^6.0.1",
     "is-docker": "^1.1.0",
     "is-promise": "^4.0.0",
+    "katex": "^0.13.0",
     "mat-color-picker": "^1.4.3",
     "material-design-icons": "^3.0.1",
+    "naughty-words": "^1.2.0",
     "ngx-color-picker": "^11.0.0",
-    "ngx-markdown": "^9.0.0",
+    "ngx-joyride": "^2.4.0",
+    "ngx-markdown": "^11.1.3",
     "ngx-matomo": "^0.1.4",
     "ngx-matomo-v9": "^0.3.0",
+    "prismjs": "^1.23.0",
     "rxjs": "^6.5.4",
     "tslib": "^2.0.0",
     "typescript-map": "0.0.7",
diff --git a/proxy.conf.json b/proxy.conf.json
index d9c429863b7cd7022076d74148411dac622414e8..6aa7e2adcba2940d5444320a585b4fbedcb387ba 100644
--- a/proxy.conf.json
+++ b/proxy.conf.json
@@ -1,6 +1,15 @@
 {
+  "/languagetool": {
+    "target": "https://lt.frag.jetzt/v2/check",
+    "secure": true,
+    "changeOrigin": true,
+    "pathRewrite": {
+      "^/languagetool": ""
+    },
+    "logLevel": "debug"
+  },
   "/spacy": {
-    "target": "https://spacy.frag.jetzt/dep",
+    "target": "https://spacy.frag.jetzt/spacy",
     "secure": true,
     "changeOrigin": true,
     "pathRewrite": {
@@ -17,6 +26,14 @@
     "ws": true,
     "logLevel": "debug"
   },
+  "/api/roomsubscription": {
+    "target": "http://localhost:8080",
+    "secure": false,
+    "pathRewrite": {
+      "^/api": ""
+    },
+    "logLevel": "debug"
+  },
   "/api": {
     "target": "http://localhost:8888",
     "secure": false,
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 919267c9535d0cd2d0f37768fa617d7cb0460712..bdb860dbda82ad5eedd69c052dfa4b1a3c4fa28f 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -5,6 +5,7 @@ import { HomePageComponent } from './components/home/home-page/home-page.compone
 import { UserHomeComponent } from './components/home/user-home/user-home.component';
 import { ImprintComponent } from './components/home/_dialogs/imprint/imprint.component';
 import { DataProtectionComponent } from './components/home/_dialogs/data-protection/data-protection.component';
+import { QuizNowComponent } from './components/shared/quiz-now/quiz-now.component';
 
 const routes: Routes = [
   {
@@ -28,6 +29,10 @@ const routes: Routes = [
     path: 'data-protection',
     component: DataProtectionComponent
   },
+  {
+    path: 'quiz',
+    component: QuizNowComponent
+  },
   {
     path: 'creator',
     loadChildren: () => import('./components/creator/creator.module').then(m => m.CreatorModule)
diff --git a/src/app/app.component.scss b/src/app/app.component.scss
index 3ba532c16a02a2932f198c41e5fbfdbb82ca6887..5064f84737b2d6c8dbc2edc772f9be0d9f606952 100644
--- a/src/app/app.component.scss
+++ b/src/app/app.component.scss
@@ -1,10 +1,12 @@
 .app-component {
-  padding: 4% 4% 0 4%;
+  padding: 0 5% 0;
   z-index: 1;
 }
 
 main {
   height: 100%;
+  margin-left: auto;
+  margin-right: auto;
 }
 
 #rescale_screen {
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 0de7b9567e4d934cc07a7f101747004f09ced28b..c85438c51dc2e69b75aacd6cbecd52c3bfbc1917 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -3,7 +3,7 @@ import { AppComponent } from './app.component';
 import { RegisterComponent } from './components/home/_dialogs/register/register.component';
 import { PasswordResetComponent } from './components/home/_dialogs/password-reset/password-reset.component';
 import { AppRoutingModule } from './app-routing.module';
-import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
+import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog';
 import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from '@angular/common/http';
 import { UserService } from './services/http/user.service';
 import { NotificationService } from './services/util/notification.service';
@@ -59,12 +59,16 @@ import { QrCodeDialogComponent } from './components/shared/_dialogs/qr-code-dial
 import { MatIconModule } from '@angular/material/icon';
 import { RemoveFromHistoryComponent } from './components/shared/_dialogs/remove-from-history/remove-from-history.component';
 import { MatomoModule } from 'ngx-matomo-v9';
-import { TagCloudComponent } from './components/shared/tag-cloud/tag-cloud.component';
-import { MatDialogModule } from '@angular/material/dialog';
-import {TagCloudModule} from 'angular-tag-cloud-module';
-import {SpacyService} from './services/http/spacy.service';
-
+import { TagCloudModule } from 'angular-tag-cloud-module';
+import { SpacyService } from './services/http/spacy.service';
+import { QuizNowComponent } from './components/shared/quiz-now/quiz-now.component';
+import { JoyrideModule } from 'ngx-joyride';
 
+import 'prismjs';
+import 'prismjs/plugins/line-numbers/prism-line-numbers.js';
+import 'prismjs/plugins/line-highlight/prism-line-highlight.js';
+import 'katex/dist/katex.min.js';
+import 'emoji-toolkit/lib/js/joypixels.min.js';
 export function dialogClose(dialogResult: any) {
 }
 
@@ -100,7 +104,7 @@ export function initializeApp(appConfig: AppConfig) {
     DemoEnComponent,
     HelpEnComponent,
     OverlayComponent,
-    TagCloudComponent
+    QuizNowComponent
   ],
   imports: [
     MatomoModule,
@@ -120,7 +124,13 @@ export function initializeApp(appConfig: AppConfig) {
       markedOptions: {
         provide: MarkedOptions,
         useValue: {
-          sanitize: true
+          pedantic: false,
+          gfm: true,
+          breaks: true,
+          sanitize: false,
+          smartLists: true,
+          smartypants: true,
+          xhtml: false
         }
       }
     }),
@@ -134,7 +144,8 @@ export function initializeApp(appConfig: AppConfig) {
       isolate: true
     }),
     ArsModule,
-    TagCloudModule
+    TagCloudModule,
+    JoyrideModule.forRoot()
   ],
   providers: [
     /*AppConfig,
diff --git a/src/app/components/creator/_dialogs/bonus-delete/bonus-delete.component.html b/src/app/components/creator/_dialogs/bonus-delete/bonus-delete.component.html
index 3cf979abb1c3105dfe3a0eaeaa55057519440b6c..ab20226fa6b3dd84cb0f5e4ab705d3bc549159f9 100644
--- a/src/app/components/creator/_dialogs/bonus-delete/bonus-delete.component.html
+++ b/src/app/components/creator/_dialogs/bonus-delete/bonus-delete.component.html
@@ -1,5 +1,4 @@
 <h2 class="oldtypo-h2">{{ 'room-page.sure' | translate }}</h2>
-<mat-divider></mat-divider>
 <p class="oldtypo-p">{{reallyDeleteText}}</p>
 <app-dialog-action-buttons
   buttonsLabelSection="content"
diff --git a/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.html b/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.html
index fce88c9ec58f120e55d8dc82433c68f91944da40..8aaa38b574869ea5514a918197709af4ce0a6e82 100644
--- a/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.html
+++ b/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.html
@@ -2,24 +2,51 @@
   <h2 class="oldtypo-h2">{{'room-page.bonus-token-header' | translate }}</h2>
   <h3 class="oldtypo-h3">&raquo;{{room.name}}&laquo;</h3>
   <h3 class="oldtypo-h3">{{ 'room-page.session-id' | translate}}: {{ room.shortId }}</h3>
-  <mat-divider></mat-divider>
   <div *ngIf="bonusTokens.length >= 1">
-    <div fxLayout="row" *ngFor="let bonusToken of bonusTokens; index as i" class="tokens">
-      <p tabindex="0">
-        {{bonusToken.token}}
-      </p>
-      <span class="fill-remaining-space"></span>
-      <p>
-        {{bonusToken.timestamp | date: lang === 'de' ? 'dd.MM.yy' : ' M/d/yy'}}
-      </p>
-      <span class="fill-remaining-space"></span>
-      <button mat-icon-button (click)="navToComment(bonusToken.commentId)">
-        <mat-icon matTooltip="{{ 'room-page.nav-to-comment' | translate }}">comment</mat-icon>
+    <div class="validator">
+      <mat-form-field>
+        <input (focus)="eventService.makeFocusOnInputTrue()"
+               (blur)="eventService.makeFocusOnInputFalse()"
+               (keyup)="inputChanged($event)"
+               (input)="inputChanged($event)"
+               matInput
+               class="input-block"
+               type="text"
+               maxlength="14"
+               name="roomName"
+               aria-labelledby="room-name-input"/>
+        <mat-placeholder class="placeholder">{{ 'room-page.hint' | translate }}</mat-placeholder>
+        <mat-hint align="end"
+                  class="count"><span aria-hidden="true">{{ value.length }} / 8</span></mat-hint>
+      </mat-form-field>
+      <button *ngIf="!valid" (click)="navToCommentByValue()"
+              matTooltip="{{ 'room-page.nav-to-comment' | translate }}"
+              mat-stroked-button disabled>
+        Go to Question
       </button>
-      <button mat-icon-button (click)="openDeleteSingleBonusDialog(bonusToken.userId, bonusToken.commentId, i)">
-        <mat-icon matTooltip="{{ 'room-page.delete-token' | translate }}" class="delete-icon">close</mat-icon>
+      <button *ngIf="valid" (click)="navToCommentByValue()"
+              matTooltip="{{ 'room-page.nav-to-comment' | translate }}"
+              mat-stroked-button class="enabled">
+        Go to Question
       </button>
     </div>
+    <mat-list>
+      <mat-list-item *ngFor="let bonusToken of bonusTokens; let index = index"
+                     [appScrollIntoView]="valueEqual(bonusToken.token)">
+        <p [ngClass]="{'selected': valueEqual(bonusToken.token)}" tabindex="0">
+          {{ bonusToken.token }}
+        </p>
+        <p>
+          {{ bonusToken.timestamp | date: lang === 'de' ? 'dd.MM.yy' : ' M/d/yy'}}
+        </p>
+        <button mat-icon-button (click)="navToComment(bonusToken.commentId)">
+          <mat-icon matTooltip="{{ 'room-page.nav-to-comment' | translate }}">comment</mat-icon>
+        </button>
+        <button mat-icon-button (click)="openDeleteSingleBonusDialog(bonusToken.userId, bonusToken.commentId, index)">
+          <mat-icon matTooltip="{{ 'room-page.delete-token' | translate }}" class="delete-icon">close</mat-icon>
+        </button>
+      </mat-list-item>
+    </mat-list>
   </div>
   <div *ngIf="bonusTokens.length === 0">
     <p>{{'room-page.no-bonus' | translate }}
@@ -27,13 +54,13 @@
   </div>
   <div fxLayoutAlign="center center" *ngIf="bonusTokens.length > 1">
     <button mat-button class="delete" (click)="openDeleteAllBonusDialog()">
-      <mat-icon>delete</mat-icon>
+      <mat-icon>delete_forever</mat-icon>
       {{'room-page.delete-all-tokens' | translate}}
     </button>
   </div>
 </div>
 
-  <app-dialog-action-buttons
-    buttonsLabelSection="content"
-    [cancelButtonClickAction]="buildDeclineActionCallback()">
-  </app-dialog-action-buttons>
+<app-dialog-action-buttons
+  buttonsLabelSection="content"
+  [cancelButtonClickAction]="buildDeclineActionCallback()">
+</app-dialog-action-buttons>
diff --git a/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.scss b/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.scss
index a5af15bbbd23e4df5a8eee8b813cb6d8b46fdaeb..d1e8b0aa62fbfd83e3345a00f7d2d77e89e4fed6 100644
--- a/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.scss
+++ b/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.scss
@@ -1,6 +1,6 @@
 p {
   color: var(--on-surface);
-  margin: 10px 0 10px 0;
+  margin-right: 30px;
 }
 
 .delete-icon {
@@ -20,3 +20,34 @@ p {
     background-color: var(--alt-dialog);
   }
 }
+
+.mat-stroked-button {
+  margin-left: 30px;
+  width: 130px;
+  height: 40px;
+  margin: auto;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding-top: 8px;
+  padding-bottom: 8px;
+  cursor: pointer;
+}
+
+.selected {
+  color: var(--red);
+}
+
+.enabled {
+  color: var(--primary);
+  border-color: var(--primary);
+}
+
+.validator {
+  overflow: hidden;
+}
+
+.validator .mat-stroked-button {
+  float: right;
+  margin-left: -40%;
+}
\ No newline at end of file
diff --git a/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.ts b/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.ts
index 7d92e32a37db8560b0d0fcb02678196f6ad6a3c3..ce5f9ed8ee4d5725f8fa2fb353e1133e8310b6fb 100644
--- a/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.ts
+++ b/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnDestroy, OnInit } from '@angular/core';
 import { BonusTokenService } from '../../../../services/http/bonus-token.service';
 import { BonusToken } from '../../../../models/bonus-token';
 import { Room } from '../../../../models/room';
@@ -8,19 +8,29 @@ import { BonusDeleteComponent } from '../bonus-delete/bonus-delete.component';
 import { NotificationService } from '../../../../services/util/notification.service';
 import { TranslateService } from '@ngx-translate/core';
 import { Router } from '@angular/router';
+import { Subject, Subscription } from 'rxjs';
+import { debounceTime } from 'rxjs/operators';
+import { isNumeric } from 'rxjs/internal-compatibility';
+import { EventService } from '../../../../services/util/event.service';
 
 @Component({
   selector: 'app-bonus-token',
   templateUrl: './bonus-token.component.html',
   styleUrls: ['./bonus-token.component.scss']
 })
-export class BonusTokenComponent implements OnInit {
+export class BonusTokenComponent implements OnInit, OnDestroy {
+  value: any = '';
+  valid = false;
   room: Room;
   bonusTokens: BonusToken[] = [];
   lang: string;
+  private modelChanged: Subject<string> = new Subject<string>();
+  private subscription: Subscription;
+  private debounceTime = 500;
 
   constructor(private bonusTokenService: BonusTokenService,
               public dialog: MatDialog,
+              public eventService: EventService,
               protected router: Router,
               private dialogRef: MatDialogRef<RoomCreatorPageComponent>,
               private translationService: TranslateService,
@@ -29,11 +39,16 @@ export class BonusTokenComponent implements OnInit {
 
   ngOnInit() {
     this.bonusTokenService.getTokensByRoomId(this.room.id).subscribe(list => {
-      this.bonusTokens = list.sort((a, b) => {
-        return (a.token > b.token) ? 1 : -1;
-      });
+      this.bonusTokens = list.sort((a, b) => (a.token > b.token) ? 1 : -1);
     });
     this.lang = localStorage.getItem('currentLang');
+    this.subscription = this.modelChanged
+      .pipe(
+        debounceTime(this.debounceTime),
+      )
+      .subscribe(_ => {
+        this.inputToken();
+      });
   }
 
   openDeleteSingleBonusDialog(userId: string, commentId: string, index: number): void {
@@ -89,10 +104,63 @@ export class BonusTokenComponent implements OnInit {
     this.router.navigate([commentURL]);
   }
 
+  navToCommentByValue() {
+    if(this.valid) {
+      this.bonusTokens.map(b => {
+        if(b.token === this.value) {
+          this.navToComment(b.commentId);
+        }
+      });
+    } else {
+      this.translationService.get('token-validator.cant-find-comment').subscribe(msg => {
+        this.notificationService.show(msg);
+      });
+    }
+  }
+
   /**
    * Returns a lambda which closes the dialog on call.
    */
   buildDeclineActionCallback(): () => void {
     return () => this.dialogRef.close();
   }
+
+  inputChanged(event: any) {
+    event.cancelBubble = true;
+    this.value = event.target.value;
+    this.modelChanged.next(event);
+  }
+
+  inputToken() {
+    const index = this.validateTokenInput(this.value);
+    if(index) {
+      this.translationService.get('token-validator.valid').subscribe(msg => {
+        this.notificationService.show(msg);
+      });
+      this.valid = true;
+    } else {
+      this.translationService.get('token-validator.invalid').subscribe(msg => {
+        this.notificationService.show(msg);
+      });
+      this.valid = false;
+    }
+  }
+
+  validateTokenInput(input: any) {
+    if(input.length === 8 && isNumeric(input)) {
+      return this.bonusTokens.map((c, index) => {
+        if (c.token === input) {
+          return index;
+        }
+      });
+    }
+  }
+
+  valueEqual(token: string) {
+    return token.trim() === this.value;
+  }
+
+  ngOnDestroy(): void {
+    this.subscription.unsubscribe();
+  }
 }
diff --git a/src/app/components/creator/_dialogs/comment-settings/comment-settings.component.html b/src/app/components/creator/_dialogs/comment-settings/comment-settings.component.html
index 677dad19771578dbec799c4b93df56ec4d33654f..0aba3e1d94ffb46ac95c59bc31ca7e4dcc698510 100644
--- a/src/app/components/creator/_dialogs/comment-settings/comment-settings.component.html
+++ b/src/app/components/creator/_dialogs/comment-settings/comment-settings.component.html
@@ -1,7 +1,7 @@
 <div mat-dialog-content>
   <!--questions-->
-  <h2 class="oldtypo-h2">{{'room-page.comments' | translate }}</h2>
-  <mat-divider></mat-divider>
+  <h2 class="oldtypo-h2">{{'room-page.moderation-mode' | translate }}</h2>
+
 
   <div fxLayout="column">
 
@@ -50,24 +50,6 @@
     </div>
   </div>
 
-  <mat-divider></mat-divider>
-
-  <div fxLayoutAlign="center center">
-    <button mat-raised-button
-            class="export"
-            (click)="exportCSV()"
-            aria-labelledby="export-comments">
-      <mat-icon>save</mat-icon>
-      {{ 'room-page.export-comments' | translate }}</button>
-  </div>
-  <div fxLayoutAlign="center center">
-    <button mat-raised-button
-            class="delete"
-            (click)="openDeleteCommentDialog()"
-            aria-labelledby="delete-all-comments">
-      <mat-icon>delete</mat-icon>
-      {{ 'room-page.delete-all-comments' | translate }}</button>
-  </div>
 </div>
 
 <app-dialog-action-buttons
diff --git a/src/app/components/creator/_dialogs/comment-settings/comment-settings.component.scss b/src/app/components/creator/_dialogs/comment-settings/comment-settings.component.scss
index d30fd4a86e04c31f955e35b91189f755bc732961..f20f3195572509cdc4d64de9253b879f69f9315a 100644
--- a/src/app/components/creator/_dialogs/comment-settings/comment-settings.component.scss
+++ b/src/app/components/creator/_dialogs/comment-settings/comment-settings.component.scss
@@ -24,12 +24,6 @@ mat-icon {
   margin-right: 10px;
 }
 
-
-mat-divider {
-  margin-bottom: 10px;
-  color: var(--on-surface) !important;
-}
-
 .abort {
   background-color: var(--cancel);
   color: var(--on-cancel);
diff --git a/src/app/components/creator/_dialogs/delete-answer/delete-answer.component.html b/src/app/components/creator/_dialogs/delete-answer/delete-answer.component.html
index efb99a94313dedc72250ce710100b6f2b77be485..773d4e2925a8ebea612012c4a79777ba48dcd7c4 100644
--- a/src/app/components/creator/_dialogs/delete-answer/delete-answer.component.html
+++ b/src/app/components/creator/_dialogs/delete-answer/delete-answer.component.html
@@ -1,5 +1,4 @@
 <h3>{{ 'room-page.sure' | translate }}</h3>
-<mat-divider></mat-divider>
 <p>{{ 'comment-page.really-delete-answer' | translate }}</p>
 <app-dialog-action-buttons
   buttonsLabelSection="content"
diff --git a/src/app/components/creator/_dialogs/delete-comment/delete-comment.component.html b/src/app/components/creator/_dialogs/delete-comment/delete-comment.component.html
index 481c7295862f174425fbec53d461ce923e73ca32..69e831011b567ee47e3cc08fddbec9e83a0a41fc 100644
--- a/src/app/components/creator/_dialogs/delete-comment/delete-comment.component.html
+++ b/src/app/components/creator/_dialogs/delete-comment/delete-comment.component.html
@@ -1,5 +1,4 @@
 <h3>{{ 'room-page.sure' | translate }}</h3>
-<mat-divider></mat-divider>
 <p>{{ 'comment-list.really-delete' | translate }}</p>
 <app-dialog-action-buttons
   buttonsLabelSection="content"
diff --git a/src/app/components/creator/_dialogs/delete-comments/delete-comments.component.html b/src/app/components/creator/_dialogs/delete-comments/delete-comments.component.html
index cbf60a00c514122132b96e2ea078277102dfc0a3..daeb3ea25f9f02f5ea9cf231c055d7b9804b0b10 100644
--- a/src/app/components/creator/_dialogs/delete-comments/delete-comments.component.html
+++ b/src/app/components/creator/_dialogs/delete-comments/delete-comments.component.html
@@ -1,6 +1,5 @@
 <h2 *ngIf="!bonusQuestions">{{ 'room-page.sure' | translate }}</h2>
 <h2 *ngIf="bonusQuestions">{{ 'room-page.delete-comments-alt-header' | translate }}</h2>
-<mat-divider></mat-divider>
 <p *ngIf="!bonusQuestions">{{ 'room-page.really-delete-comments' | translate }}</p>
 <p *ngIf="bonusQuestions">{{ 'room-page.really-delete-comments-hint' | translate }}</p>
 <app-dialog-action-buttons *ngIf="!bonusQuestions"
diff --git a/src/app/components/creator/_dialogs/moderator-delete/moderator-delete.component.html b/src/app/components/creator/_dialogs/moderator-delete/moderator-delete.component.html
index 12c21a192a5691a5fed435e583ff8b9856bbc920..9032a9fffb4b842f0b058cfd8041fe46102d45d9 100644
--- a/src/app/components/creator/_dialogs/moderator-delete/moderator-delete.component.html
+++ b/src/app/components/creator/_dialogs/moderator-delete/moderator-delete.component.html
@@ -1,6 +1,5 @@
 <!--Are you sure-->
 <h2 class="oldtypo-h2">{{ 'room-page.sure' | translate }}</h2>
-<mat-divider></mat-divider>
 <!--remove moderator-->
 <p class="oldtypo-p">{{ 'room-page.really-remove-moderator' | translate }}</p>
 <!--list of moderators-->
diff --git a/src/app/components/creator/_dialogs/moderators/moderators.component.html b/src/app/components/creator/_dialogs/moderators/moderators.component.html
index be10d42c4669d5797c4c8e2706c8ea6a0758f3a6..6340dfb4f540a1fa431cc6e45b4e57f65f73c1db 100644
--- a/src/app/components/creator/_dialogs/moderators/moderators.component.html
+++ b/src/app/components/creator/_dialogs/moderators/moderators.component.html
@@ -1,6 +1,6 @@
 <div mat-dialog-content>
   <h2 class="oldtypo-h2">{{'room-page.moderators' | translate }}</h2>
-  <mat-divider></mat-divider>
+
   <div fxLayout="row">
     <mat-form-field class="input-block">
       <input (focus)="eventService.makeFocusOnInputTrue()"
diff --git a/src/app/components/creator/_dialogs/moderators/moderators.component.scss b/src/app/components/creator/_dialogs/moderators/moderators.component.scss
index 07d6c29e8f5e0accb83a5fb1e2cf513656d722b8..a2bc1bcc451a78903da5ac77a98044de49f1f768 100644
--- a/src/app/components/creator/_dialogs/moderators/moderators.component.scss
+++ b/src/app/components/creator/_dialogs/moderators/moderators.component.scss
@@ -6,10 +6,6 @@ p {
   font-size: medium;
 }
 
-mat-divider {
-  margin-bottom: 10px;
-}
-
 mat-form-field {
   width: 90%;
   color: var(--on-surface);
diff --git a/src/app/components/creator/_dialogs/profanity-settings/profanity-settings.component.html b/src/app/components/creator/_dialogs/profanity-settings/profanity-settings.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..87bf944cb7706a4e7b7ee1911686f35256a6214f
--- /dev/null
+++ b/src/app/components/creator/_dialogs/profanity-settings/profanity-settings.component.html
@@ -0,0 +1,45 @@
+<div mat-dialog-content
+     *ngIf="editRoom">
+  <h2 class="oldtypo-h2">{{'room-page.profanity-heading' | translate }}</h2>
+
+  <div fxLayout="column">
+
+    <div fxLayout="row">
+      <p class="oldtypo-p">
+        <mat-slide-toggle (change)="showMessage('words-will-be-overwritten', $event.checked)"
+                          [(ngModel)]="profanityCheck">
+          {{ 'room-page.profanity-filter' | translate }}
+        </mat-slide-toggle>
+      </p>
+    </div>
+
+    <div fxLayout="row">
+      <p class="oldtypo-p">
+        <mat-slide-toggle *ngIf="profanityCheck"
+                          (change)="showMessage('only-specific-language-will-be-filtered', $event.checked)"
+                          [(ngModel)]="censorLanguageSpecificCheck">
+          {{ 'room-page.language-specific-filter' | translate }}
+        </mat-slide-toggle>
+      </p>
+    </div>
+
+    <div fxLayout="row">
+      <p class="oldtypo-p">
+        <mat-slide-toggle *ngIf="profanityCheck"
+                          (change)="showMessage('partial-words-will-be-filtered', $event.checked)"
+                          [(ngModel)]="censorPartialWordsCheck">
+          {{ 'room-page.partial-words-filter' | translate }}
+        </mat-slide-toggle>
+      </p>
+    </div>
+
+  </div>
+</div>
+
+<app-dialog-action-buttons
+  buttonsLabelSection="room-page"
+  confirmButtonLabel="update"
+
+  [cancelButtonClickAction]="buildCloseDialogActionCallback()"
+  [confirmButtonClickAction]="buildSaveActionCallback()"
+></app-dialog-action-buttons>
diff --git a/src/app/components/creator/_dialogs/profanity-settings/profanity-settings.component.scss b/src/app/components/creator/_dialogs/profanity-settings/profanity-settings.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/app/components/creator/_dialogs/profanity-settings/profanity-settings.component.spec.ts b/src/app/components/creator/_dialogs/profanity-settings/profanity-settings.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..89f7b20011d98808e17822e7cf742950e30f2022
--- /dev/null
+++ b/src/app/components/creator/_dialogs/profanity-settings/profanity-settings.component.spec.ts
@@ -0,0 +1,25 @@
+// import { ComponentFixture, TestBed } from '@angular/core/testing';
+//
+// import { ProfanitySettingsComponent } from './profanity-settings.component';
+//
+// describe('ProfanitySettingsComponent', () => {
+//   let component: ProfanitySettingsComponent;
+//   let fixture: ComponentFixture<ProfanitySettingsComponent>;
+//
+//   beforeEach(async () => {
+//     await TestBed.configureTestingModule({
+//       declarations: [ ProfanitySettingsComponent ]
+//     })
+//     .compileComponents();
+//   });
+//
+//   beforeEach(() => {
+//     fixture = TestBed.createComponent(ProfanitySettingsComponent);
+//     component = fixture.componentInstance;
+//     fixture.detectChanges();
+//   });
+//
+//   it('should create', () => {
+//     expect(component).toBeTruthy();
+//   });
+// });
diff --git a/src/app/components/creator/_dialogs/profanity-settings/profanity-settings.component.ts b/src/app/components/creator/_dialogs/profanity-settings/profanity-settings.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ad81ba4ead5ed15fbf9034f0fddbaf3c604ee956
--- /dev/null
+++ b/src/app/components/creator/_dialogs/profanity-settings/profanity-settings.component.ts
@@ -0,0 +1,85 @@
+import {Component,Inject,OnInit} from '@angular/core';
+import {MAT_DIALOG_DATA,MatDialog,MatDialogRef} from '@angular/material/dialog';
+import {RoomCreatorPageComponent} from '../../room-creator-page/room-creator-page.component';
+import {NotificationService} from '../../../../services/util/notification.service';
+import {TranslateService} from '@ngx-translate/core';
+import {RoomService} from '../../../../services/http/room.service';
+import {Router} from '@angular/router';
+import {EventService} from '../../../../services/util/event.service';
+import {ProfanityFilter,Room} from '../../../../models/room';
+
+@Component({
+  selector:'app-profanity-settings',
+  templateUrl:'./profanity-settings.component.html',
+  styleUrls:['./profanity-settings.component.scss']
+})
+export class ProfanitySettingsComponent implements OnInit{
+
+  editRoom: Room;
+  check=false;
+  profanityCheck: boolean;
+  censorPartialWordsCheck: boolean;
+  censorLanguageSpecificCheck: boolean;
+
+  constructor(public dialogRef: MatDialogRef<RoomCreatorPageComponent>,
+              public dialog: MatDialog,
+              public notificationService: NotificationService,
+              public translationService: TranslateService,
+              protected roomService: RoomService,
+              public router: Router,
+              public eventService: EventService,
+              @Inject(MAT_DIALOG_DATA) public data: any){
+  }
+
+  ngOnInit(){
+    this.profanityCheck=this.editRoom.profanityFilter!==ProfanityFilter.deactivated;
+    if(this.editRoom.profanityFilter===ProfanityFilter.all){
+      this.censorLanguageSpecificCheck=this.censorPartialWordsCheck=true;
+    }else if(this.profanityCheck){
+      this.censorLanguageSpecificCheck=this.editRoom.profanityFilter===ProfanityFilter.languageSpecific;
+      this.censorPartialWordsCheck=this.editRoom.profanityFilter===ProfanityFilter.partialWords;
+    }
+  }
+
+  showMessage(label: string,event: boolean){
+    if(event){
+      this.translationService.get('room-page.'+label).subscribe(msg=>{
+        this.notificationService.show(msg);
+      });
+    }
+  }
+
+
+  /**
+   * Returns a lambda which closes the dialog on call.
+   */
+  buildCloseDialogActionCallback(): () => void{
+    return ()=>this.closeDialog('abort');
+  }
+
+  /**
+   * Returns a lambda which executes the dialog dedicated action on call.
+   */
+  buildSaveActionCallback(): () => void{
+    return ()=>this.save();
+  }
+
+  closeDialog(type: string): void{
+    this.dialogRef.close(type);
+  }
+
+  save(): void{
+    this.editRoom.questionsBlocked=this.check;
+    this.editRoom.profanityFilter=this.profanityCheck?ProfanityFilter.none:ProfanityFilter.deactivated;
+    if(this.profanityCheck){
+      if(this.censorLanguageSpecificCheck&&this.censorPartialWordsCheck){
+        this.editRoom.profanityFilter=ProfanityFilter.all;
+      }else{
+        this.editRoom.profanityFilter=this.censorLanguageSpecificCheck?ProfanityFilter.languageSpecific:ProfanityFilter.none;
+        this.editRoom.profanityFilter=this.censorPartialWordsCheck?ProfanityFilter.partialWords:this.editRoom.profanityFilter;
+      }
+    }
+    this.closeDialog('update');
+  }
+
+}
diff --git a/src/app/components/creator/_dialogs/room-delete/room-delete.component.html b/src/app/components/creator/_dialogs/room-delete/room-delete.component.html
index 9c7adb3fed8055d678cd632fc530e01f79c6a801..4b8ec3bda1ecaf864fd69363ac3a9c1d5fe905ce 100644
--- a/src/app/components/creator/_dialogs/room-delete/room-delete.component.html
+++ b/src/app/components/creator/_dialogs/room-delete/room-delete.component.html
@@ -1,5 +1,4 @@
 <h2>{{ 'room-page.sure' | translate }}</h2>
-<mat-divider></mat-divider>
 <p>{{ 'room-page.reallySession' | translate}}<strong>&raquo;{{room.name}}&laquo;</strong>{{ 'room-page.really2' | translate}}</p>
 <app-dialog-action-buttons
   buttonsLabelSection="room-page"
diff --git a/src/app/components/creator/_dialogs/room-description-settings/room-description-settings.component.html b/src/app/components/creator/_dialogs/room-description-settings/room-description-settings.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..3655622d27e70385c88198fdb8a8951fc44fd9d2
--- /dev/null
+++ b/src/app/components/creator/_dialogs/room-description-settings/room-description-settings.component.html
@@ -0,0 +1,43 @@
+<div mat-dialog-content
+     *ngIf="editRoom">
+  <h2 class="oldtypo-h2">{{ 'room-page.description' | translate }}</h2>
+  <mat-tab-group>
+    <mat-tab label="{{'room-page.tab1' | translate}}">
+      <mat-form-field class="input-block" style="width:100%;min-width:100%;">
+      <textarea
+        (focus)="eventService.makeFocusOnInputTrue()"
+        (blur)="eventService.makeFocusOnInputFalse()"
+        [(ngModel)]="editRoom.description"
+        matInput
+        matTextareaAutosize
+        matAutosizeMinRows="2"
+        matAutosizeMaxRows="5"
+        maxlength="500"
+        name="description"
+        aria-labelledby="description"
+      ></textarea>
+        <mat-hint align="start">
+              <span aria-hidden="true">
+                {{ 'room-page.Markdown-hint' | translate }}
+              </span>
+        </mat-hint>
+        <mat-hint align="end">
+            <span aria-hidden="true">
+              {{ editRoom.description?editRoom.description.length:0 }} / 500
+            </span>
+        </mat-hint>
+      </mat-form-field>
+    </mat-tab>
+    <mat-tab label="{{'session.preview' | translate}}"
+             [disabled]="!editRoom.description">
+      <app-custom-markdown class="images" [data]="editRoom.description"></app-custom-markdown>
+    </mat-tab>
+  </mat-tab-group>
+</div>
+<app-dialog-action-buttons
+  buttonsLabelSection="room-page"
+  confirmButtonLabel="update"
+
+  [cancelButtonClickAction]="buildCloseDialogActionCallback()"
+  [confirmButtonClickAction]="buildSaveActionCallback()"
+></app-dialog-action-buttons>
diff --git a/src/app/components/creator/_dialogs/room-description-settings/room-description-settings.component.scss b/src/app/components/creator/_dialogs/room-description-settings/room-description-settings.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/app/components/creator/_dialogs/room-description-settings/room-description-settings.component.spec.ts b/src/app/components/creator/_dialogs/room-description-settings/room-description-settings.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..32a8c08c6970557863d0d91cb3d0e5be6476bf64
--- /dev/null
+++ b/src/app/components/creator/_dialogs/room-description-settings/room-description-settings.component.spec.ts
@@ -0,0 +1,25 @@
+// import { ComponentFixture, TestBed } from '@angular/core/testing';
+//
+// import { RoomDescriptionSettingsComponent } from './room-description-settings.component';
+//
+// describe('RoomDescriptionSettingsComponent', () => {
+//   let component: RoomDescriptionSettingsComponent;
+//   let fixture: ComponentFixture<RoomDescriptionSettingsComponent>;
+//
+//   beforeEach(async () => {
+//     await TestBed.configureTestingModule({
+//       declarations: [ RoomDescriptionSettingsComponent ]
+//     })
+//     .compileComponents();
+//   });
+//
+//   beforeEach(() => {
+//     fixture = TestBed.createComponent(RoomDescriptionSettingsComponent);
+//     component = fixture.componentInstance;
+//     fixture.detectChanges();
+//   });
+//
+//   it('should create', () => {
+//     expect(component).toBeTruthy();
+//   });
+// });
diff --git a/src/app/components/creator/_dialogs/room-description-settings/room-description-settings.component.ts b/src/app/components/creator/_dialogs/room-description-settings/room-description-settings.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cd5f3ac74bf44d7f926629a15046dadc5bebdfc1
--- /dev/null
+++ b/src/app/components/creator/_dialogs/room-description-settings/room-description-settings.component.ts
@@ -0,0 +1,57 @@
+import {Component,Inject,OnInit} from '@angular/core';
+import {MAT_DIALOG_DATA,MatDialog,MatDialogRef} from '@angular/material/dialog';
+import {RoomCreatorPageComponent} from '../../room-creator-page/room-creator-page.component';
+import {NotificationService} from '../../../../services/util/notification.service';
+import {TranslateService} from '@ngx-translate/core';
+import {RoomService} from '../../../../services/http/room.service';
+import {Router} from '@angular/router';
+import {EventService} from '../../../../services/util/event.service';
+import {ProfanityFilter,Room} from '../../../../models/room';
+import {FormControl,Validators} from '@angular/forms';
+
+@Component({
+  selector:'app-room-description-settings',
+  templateUrl:'./room-description-settings.component.html',
+  styleUrls:['./room-description-settings.component.scss']
+})
+export class RoomDescriptionSettingsComponent implements OnInit{
+  editRoom: Room;
+  roomNameFormControl=new FormControl('',[Validators.required,Validators.minLength(3),Validators.maxLength(30)]);
+
+  constructor(public dialogRef: MatDialogRef<RoomCreatorPageComponent>,
+              public dialog: MatDialog,
+              public notificationService: NotificationService,
+              public translationService: TranslateService,
+              protected roomService: RoomService,
+              public router: Router,
+              public eventService: EventService,
+              @Inject(MAT_DIALOG_DATA) public data: any){
+  }
+
+
+  ngOnInit(){
+  }
+
+  buildCloseDialogActionCallback(): () => void{
+    return ()=>this.closeDialog('abort');
+  }
+
+  buildSaveActionCallback(): () => void{
+    return ()=>this.save();
+  }
+
+  closeDialog(type: string): void{
+    this.dialogRef.close(type);
+  }
+
+  save(): void{
+    this.roomService.updateRoom(this.editRoom).subscribe(r=>this.editRoom=r);
+    if(!this.roomNameFormControl.hasError('required')
+      && !this.roomNameFormControl.hasError('minlength')
+      && !this.roomNameFormControl.hasError('maxlength')){
+      this.closeDialog('update');
+    }
+    this.closeDialog('update');
+  }
+
+}
diff --git a/src/app/components/creator/_dialogs/room-edit/room-edit.component.html b/src/app/components/creator/_dialogs/room-edit/room-edit.component.html
index cbcd9da2b489fd76e74b7071f7180d3bf1535717..f05eb018dd58f7fc88fc8b3eb081890b180259ba 100644
--- a/src/app/components/creator/_dialogs/room-edit/room-edit.component.html
+++ b/src/app/components/creator/_dialogs/room-edit/room-edit.component.html
@@ -2,7 +2,7 @@
      *ngIf="editRoom">
   <!--Sitzung-->
   <h2 class="oldtypo-h2">{{ 'room-page.general' | translate }}</h2>
-  <mat-divider></mat-divider>
+
   <div fxLayout="column">
     <mat-form-field class="input-block">
       <input (focus)="eventService.makeFocusOnInputTrue()"
@@ -51,16 +51,34 @@
       </mat-tab>
       <mat-tab label="{{'session.preview' | translate}}"
                [disabled]="!editRoom.description">
-        <markdown [data]="editRoom.description"></markdown>
+        <app-custom-markdown class="images" [data]="editRoom.description"></app-custom-markdown>
       </mat-tab>
     </mat-tab-group>
+    <div fxLayout="column">
+      <mat-slide-toggle [(ngModel)]= "check">{{ 'room-page.block' | translate }}</mat-slide-toggle>
+    </div>
+    <div fxLayout="column">
+      <mat-slide-toggle (change)="showMessage('words-will-be-overwritten', $event.checked)" [(ngModel)]= "profanityCheck">
+        {{ 'room-page.profanity-filter' | translate }}
+      </mat-slide-toggle>
+      <mat-slide-toggle *ngIf="profanityCheck" (change)="showMessage('only-specific-language-will-be-filtered', $event.checked)" [(ngModel)]= "censorLanguageSpecificCheck">
+        {{ 'room-page.language-specific-filter' | translate }}
+      </mat-slide-toggle>
+      <mat-slide-toggle *ngIf="profanityCheck" (change)="showMessage('partial-words-will-be-filtered', $event.checked)" [(ngModel)]= "censorPartialWordsCheck">
+        {{ 'room-page.partial-words-filter' | translate }}
+      </mat-slide-toggle>
+    </div>
     <div fxLayoutAlign="center center">
+      <!-- <input type="checkbox" id= "myCheck" [(ngModel)]= "check" > -->
+   <!-- <mat-label for="myCheck" ><mat-icon>block</mat-icon>{{ 'room-page.block' | translate }} </mat-label> -->
+
       <button mat-raised-button
               class="delete"
               (click)="openDeleteRoomDialog()"
               aria-labelledby="delete-room">
-        <mat-icon>delete</mat-icon>
+        <mat-icon>delete_forever</mat-icon>
         {{ 'room-page.delete-room' | translate }}</button>
+
     </div>
   </div>
 </div>
@@ -68,6 +86,7 @@
 <app-dialog-action-buttons
   buttonsLabelSection="room-page"
   confirmButtonLabel="update"
+
   [cancelButtonClickAction]="buildCloseDialogActionCallback()"
   [confirmButtonClickAction]="buildSaveActionCallback()"
 ></app-dialog-action-buttons>
diff --git a/src/app/components/creator/_dialogs/room-edit/room-edit.component.scss b/src/app/components/creator/_dialogs/room-edit/room-edit.component.scss
index 55edafc7f35014143fef054a1140837b8a7dbfad..35318234e616b7b8a0feebba5fcf7a78c58ddb43 100644
--- a/src/app/components/creator/_dialogs/room-edit/room-edit.component.scss
+++ b/src/app/components/creator/_dialogs/room-edit/room-edit.component.scss
@@ -24,11 +24,6 @@ mat-icon {
   margin-right: 10px;
 }
 
-mat-divider {
-  margin-bottom: 10px;
-  color: var(--on-surface) !important;
-}
-
 .abort {
   background-color: var(--cancel);
   color: var(--on-cancel);
@@ -51,3 +46,11 @@ mat-hint {
   color: var(--on-surface) !important;
   margin-right: 1%;
 }
+
+mat-slide-toggle {
+  margin-top: 20px;
+}
+
+
+
+
diff --git a/src/app/components/creator/_dialogs/room-edit/room-edit.component.ts b/src/app/components/creator/_dialogs/room-edit/room-edit.component.ts
index cd26cf219d0ac1c5e78777beafa4d27d574f6215..aa6468be4985a8de87814b3c65591b1ff7ce7d7b 100644
--- a/src/app/components/creator/_dialogs/room-edit/room-edit.component.ts
+++ b/src/app/components/creator/_dialogs/room-edit/room-edit.component.ts
@@ -1,6 +1,6 @@
 import { Component, Inject, OnInit } from '@angular/core';
 import { FormControl, Validators } from '@angular/forms';
-import { Room } from '../../../../models/room';
+import { ProfanityFilter, Room } from '../../../../models/room';
 import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
 import { RoomDeleteComponent } from '../room-delete/room-delete.component';
 import { NotificationService } from '../../../../services/util/notification.service';
@@ -11,6 +11,7 @@ import { RoomCreatorPageComponent } from '../../room-creator-page/room-creator-p
 import { EventService } from '../../../../services/util/event.service';
 import { RoomDeleted } from '../../../../models/events/room-deleted';
 
+
 @Component({
   selector: 'app-room-edit',
   templateUrl: './room-edit.component.html',
@@ -18,6 +19,10 @@ import { RoomDeleted } from '../../../../models/events/room-deleted';
 })
 export class RoomEditComponent implements OnInit {
   editRoom: Room;
+  check = false;
+  profanityCheck: boolean;
+  censorPartialWordsCheck: boolean;
+  censorLanguageSpecificCheck: boolean;
 
   roomNameFormControl = new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(30)]);
 
@@ -32,6 +37,14 @@ export class RoomEditComponent implements OnInit {
   }
 
   ngOnInit() {
+    this.check = this.editRoom.questionsBlocked;
+    this.profanityCheck = this.editRoom.profanityFilter !== ProfanityFilter.deactivated;
+    if (this.editRoom.profanityFilter === ProfanityFilter.all){
+      this.censorLanguageSpecificCheck = this.censorPartialWordsCheck = true;
+    } else if (this.profanityCheck){
+      this.censorLanguageSpecificCheck = this.editRoom.profanityFilter === ProfanityFilter.languageSpecific;
+      this.censorPartialWordsCheck = this.editRoom.profanityFilter === ProfanityFilter.partialWords;
+    }
   }
 
   openDeleteRoomDialog(): void {
@@ -59,7 +72,6 @@ export class RoomEditComponent implements OnInit {
     });
   }
 
-
   /**
    * Closes the dialog on call.
    */
@@ -68,6 +80,17 @@ export class RoomEditComponent implements OnInit {
   }
 
   save(): void {
+    this.editRoom.questionsBlocked = this.check;
+    this.editRoom.profanityFilter = this.profanityCheck ? ProfanityFilter.none : ProfanityFilter.deactivated;
+    if (this.profanityCheck) {
+      if (this.censorLanguageSpecificCheck && this.censorPartialWordsCheck) {
+        this.editRoom.profanityFilter = ProfanityFilter.all;
+      } else {
+        this.editRoom.profanityFilter = this.censorLanguageSpecificCheck ? ProfanityFilter.languageSpecific : ProfanityFilter.none;
+        this.editRoom.profanityFilter = this.censorPartialWordsCheck ? ProfanityFilter.partialWords : this.editRoom.profanityFilter;
+      }
+    }
+    this.roomService.updateRoom(this.editRoom).subscribe(r => this.editRoom = r);
     if (!this.roomNameFormControl.hasError('required')
         && !this.roomNameFormControl.hasError('minlength')
         && !this.roomNameFormControl.hasError('maxlength')) {
@@ -83,11 +106,18 @@ export class RoomEditComponent implements OnInit {
     return () => this.closeDialog('abort');
   }
 
-
   /**
    * Returns a lambda which executes the dialog dedicated action on call.
    */
   buildSaveActionCallback(): () => void {
     return () => this.save();
   }
+
+  showMessage(label: string, event: boolean) {
+    if (event) {
+      this.translationService.get('room-page.'+label).subscribe(msg => {
+        this.notificationService.show(msg);
+      });
+    }
+  }
 }
diff --git a/src/app/components/creator/_dialogs/tags/tags.component.html b/src/app/components/creator/_dialogs/tags/tags.component.html
index 9cdac0911227374b3a00328f107decbe13a988d7..e29b5abd02d1c852d966feeb2c20369822180b31 100644
--- a/src/app/components/creator/_dialogs/tags/tags.component.html
+++ b/src/app/components/creator/_dialogs/tags/tags.component.html
@@ -1,7 +1,7 @@
 <div mat-dialog-content>
   <!--Tags-->
   <h2 class="oldtypo-h2">{{'room-page.tags' | translate }}</h2>
-  <mat-divider></mat-divider>
+
   <div fxLayout="column">
     <div fxLayout="row">
       <mat-form-field class="input-block">
diff --git a/src/app/components/creator/_dialogs/tags/tags.component.scss b/src/app/components/creator/_dialogs/tags/tags.component.scss
index 7b5cf7d48136c128c2968dacf2b421e3616a8cbd..e8c0a94b694be5fbfb7575409f21c1288b847e43 100644
--- a/src/app/components/creator/_dialogs/tags/tags.component.scss
+++ b/src/app/components/creator/_dialogs/tags/tags.component.scss
@@ -1,8 +1,3 @@
-mat-divider {
-  margin-bottom: 10px;
-  color: var(--on-surface) !important;
-}
-
 h2 {
   margin-bottom: 10px;
 }
diff --git a/src/app/components/creator/creator.module.ts b/src/app/components/creator/creator.module.ts
index 10b0706bd73293cd45e16b584f072917b30750d4..6d5670cf1401e205997d36e95f3c918beb64e785 100644
--- a/src/app/components/creator/creator.module.ts
+++ b/src/app/components/creator/creator.module.ts
@@ -23,6 +23,9 @@ import { DeleteAnswerComponent } from './_dialogs/delete-answer/delete-answer.co
 import { QuestionWallComponent } from '../shared/questionwall/question-wall/question-wall.component';
 import { ArsModule } from '../../../../projects/ars/src/lib/ars.module';
 import { MatRippleModule } from '@angular/material/core';
+import { ProfanitySettingsComponent } from './_dialogs/profanity-settings/profanity-settings.component';
+import { RoomDescriptionSettingsComponent } from './_dialogs/room-description-settings/room-description-settings.component';
+import { ScrollIntoViewDirective } from '../../directives/scroll-into-view.directive';
 
 @NgModule({
   imports: [
@@ -56,7 +59,10 @@ import { MatRippleModule } from '@angular/material/core';
     DeleteCommentComponent,
     BonusDeleteComponent,
     DeleteAnswerComponent,
-    QuestionWallComponent
+    QuestionWallComponent,
+    ProfanitySettingsComponent,
+    RoomDescriptionSettingsComponent,
+    ScrollIntoViewDirective
   ],
   exports: []
 })
diff --git a/src/app/components/creator/room-creator-page/room-creator-page.component.html b/src/app/components/creator/room-creator-page/room-creator-page.component.html
index eaf734408eedda04f6bed6c3183f3e7ef30b34f3..b4d745512dc7295038fc4f211966c104a1fe46da 100644
--- a/src/app/components/creator/room-creator-page/room-creator-page.component.html
+++ b/src/app/components/creator/room-creator-page/room-creator-page.component.html
@@ -4,12 +4,9 @@
      fxFill>
   <div fxLayout="row"
        fxLayoutAlign="center">
-    <mat-progress-spinner *ngIf="isLoading"
-                          color="primary"
-                          mode="indeterminate"></mat-progress-spinner>
+    <app-mat-spinner-overlay *ngIf="isLoading" overlay="true"></app-mat-spinner-overlay>
     <mat-card *ngIf="room">
       <div fxLayout="row">
-        <span class="corner-icons"></span>
         <span class="fill-remaining-space"></span>
         <mat-card-header fxLayoutAlign="center"
                          fxLayout="row">
@@ -25,7 +22,7 @@
                     (click)="copyShortId()"
                     aria-labelledby="cloud_download">
               <mat-icon class="copy"
-                        matTooltip="{{ 'room-page.copy-session-id' | translate}}">content_paste
+                        matTooltip="{{ 'room-page.copy-session-id' | translate}}">share
               </mat-icon>
             </button>
           </mat-card-subtitle>
@@ -65,19 +62,10 @@
             {{ 'room-page.tags' | translate}}
           </button>
         </mat-menu>
-        <button id="settings-menu"
-                mat-icon-button
-                class="corner-icons"
-                [matMenuTriggerFor]="settingsMenu"
-                aria-labelledby="settings">
-          <mat-icon class="corner-icon"
-                    matTooltip="{{ 'room-page.session-settings' | translate}}">settings
-          </mat-icon>
-        </button>
       </div>
       <mat-card-content *ngIf="room.description"
                         fxLayoutAlign="center">
-        <markdown [data]="room.description.trim()"></markdown>
+        <app-custom-markdown class="images" [data]="room.description.trim()"></app-custom-markdown>
       </mat-card-content>
       <div fxLayout="column"
            fxLayoutAlign="center"
@@ -109,7 +97,7 @@
                         class="main-icon"
                         [ngClass]="{'smallerIcon' : deviceType === 'mobile'}"
                         matTooltip="{{ 'room-page.session-moderation-board' | translate}}">visibility_off
-                        </mat-icon>
+              </mat-icon>
               <h3>{{ 'room-page.moderating-stream' | translate}}</h3>
             </button>
           </mat-grid-tile>
@@ -139,6 +127,9 @@
           class="visually-hidden">{{ 'room-page.live-announcer' | translate }}</button>
 </div>
 
+<app-active-user *ngIf="room"
+                 [room]="room"></app-active-user>
+
 <div class="visually-hidden">
   <div id="cloud_download">{{'room-page.a11y-cloud_download' | translate}}</div>
   <div id="question_answer">{{'room-page.a11y-question_answer' | translate}}</div>
diff --git a/src/app/components/creator/room-creator-page/room-creator-page.component.scss b/src/app/components/creator/room-creator-page/room-creator-page.component.scss
index ea240d770244f84396af3a5289a9ba3ee8b6fb7c..e555b3b8887d040ae1d8706dccb2c5dee245e9ec 100644
--- a/src/app/components/creator/room-creator-page/room-creator-page.component.scss
+++ b/src/app/components/creator/room-creator-page/room-creator-page.component.scss
@@ -28,10 +28,6 @@ mat-card-content > :first-child {
   }
 }
 
-.corner-icons {
-  width: 40px;
-}
-
 .corner-icon {
   font-size: 40px;
   height: 40px;
diff --git a/src/app/components/creator/room-creator-page/room-creator-page.component.ts b/src/app/components/creator/room-creator-page/room-creator-page.component.ts
index e1ffc26c791a651bb8b1a9414adc322743f271df..6f4b6d344027f77a976eb6fec79a2dc081090a5c 100644
--- a/src/app/components/creator/room-creator-page/room-creator-page.component.ts
+++ b/src/app/components/creator/room-creator-page/room-creator-page.component.ts
@@ -1,8 +1,8 @@
 import { Component, OnInit, Renderer2, OnDestroy, AfterContentInit } from '@angular/core';
 import { RoomService } from '../../../services/http/room.service';
-import { ActivatedRoute } from '@angular/router';
+import {ActivatedRoute,Router} from '@angular/router';
 import { RoomPageComponent } from '../../shared/room-page/room-page.component';
-import { Room } from '../../../models/room';
+import {ProfanityFilter,Room} from '../../../models/room';
 import { CommentSettingsDialog } from '../../../models/comment-settings-dialog';
 import { Location } from '@angular/common';
 import { NotificationService } from '../../../services/util/notification.service';
@@ -11,7 +11,7 @@ import { RoomEditComponent } from '../_dialogs/room-edit/room-edit.component';
 import { TranslateService } from '@ngx-translate/core';
 import { LanguageService } from '../../../services/util/language.service';
 import { TSMap } from 'typescript-map';
-import { WsCommentServiceService } from '../../../services/websockets/ws-comment-service.service';
+import { WsCommentService } from '../../../services/websockets/ws-comment.service';
 import { CommentService } from '../../../services/http/comment.service';
 import { ModeratorsComponent } from '../_dialogs/moderators/moderators.component';
 import { BonusTokenComponent } from '../_dialogs/bonus-token/bonus-token.component';
@@ -26,6 +26,14 @@ import { DeleteCommentsComponent } from '../_dialogs/delete-comments/delete-comm
 import { Export } from '../../../models/export';
 import { BonusTokenService } from '../../../services/http/bonus-token.service';
 import { TopicCloudFilterComponent } from '../../shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component';
+import {HeaderService} from '../../../services/util/header.service';
+import {RoomDeleteComponent} from '../_dialogs/room-delete/room-delete.component';
+import {RoomDeleted} from '../../../models/events/room-deleted';
+import {ProfanitySettingsComponent} from '../_dialogs/profanity-settings/profanity-settings.component';
+import {RoomDescriptionSettingsComponent} from '../_dialogs/room-description-settings/room-description-settings.component';
+import {ModeratorDeleteComponent} from '../_dialogs/moderator-delete/moderator-delete.component';
+import {ModeratorCommentPageComponent} from '../../moderator/moderator-comment-page/moderator-comment-page.component';
+import {ModeratorCommentListComponent} from '../../moderator/moderator-comment-list/moderator-comment-list.component';
 
 @Component({
   selector: 'app-room-creator-page',
@@ -52,14 +60,16 @@ export class RoomCreatorPageComponent extends RoomPageComponent implements OnIni
               public dialog: MatDialog,
               private translateService: TranslateService,
               protected langService: LanguageService,
-              protected wsCommentService: WsCommentServiceService,
+              protected wsCommentService: WsCommentService,
               protected commentService: CommentService,
               private liveAnnouncer: LiveAnnouncer,
               private _r: Renderer2,
               public eventService: EventService,
               public titleService: TitleService,
               private notificationService: NotificationService,
-              private bonusTokenService: BonusTokenService) {
+              private bonusTokenService: BonusTokenService,
+              public router: Router,
+              public translationService: TranslateService) {
     super(roomService, route, location, wsCommentService, commentService, eventService);
     this.commentCounterEmitSubscription = this.commentCounterEmit.subscribe(e => {
       this.titleService.attachTitle('(' + e + ')');
@@ -70,35 +80,16 @@ export class RoomCreatorPageComponent extends RoomPageComponent implements OnIni
   initNavigation() {
     const navigation = {};
     const nav = (b, c) => navigation[b] = c;
+    nav('deleteRoom',()=>this.openDeleteRoomDialog());
+    nav('profanityFilter',()=>this.toggleProfanityFilter());
+    nav('editSessionDescription',()=>this.editSessionDescription());
     nav('roomBonusToken', () => this.showBonusTokenDialog());
     nav('moderator', () => this.showModeratorsDialog());
     nav('tags', () => this.showTagsDialog());
     nav('topicCloud', () => this.showTagCloud());
-    nav('exportQuestions', () => {
-      const exp: Export = new Export(
-        this.room,
-        this.commentService,
-        this.bonusTokenService,
-        this.translateService,
-        'comment-list',
-        this.notificationService);
-      exp.exportAsCsv();
-    });
-    nav('deleteQuestions', () => {
-      const dialogRef = this.dialog.open(DeleteCommentsComponent, {
-        width: '400px'
-      });
-      dialogRef.componentInstance.roomId = this.room.id;
-      dialogRef.afterClosed()
-      .subscribe(result => {
-        if (result === 'delete') {
-          this.translateService.get('room-page.comments-deleted').subscribe(msg => {
-            this.notificationService.show(msg);
-          });
-          this.commentService.deleteCommentsByRoomId(this.room.id).subscribe();
-        }
-      });
-    });
+    nav('exportQuestions', () => this.exportQuestions());
+    nav('deleteQuestions', () => this.deleteQuestions());
+    nav('moderatorSettings', () => this.navigateModeratorSettings());
     this.headerInterface = this.eventService.on<string>('navigate').subscribe(e => {
       if (navigation.hasOwnProperty(e)) {
         navigation[e]();
@@ -106,6 +97,51 @@ export class RoomCreatorPageComponent extends RoomPageComponent implements OnIni
     });
   }
 
+  navigateModeratorSettings(){
+    this.showCommentsDialog();
+  }
+
+  toggleProfanityFilter(){
+    const dialogRef = this.dialog.open(ProfanitySettingsComponent, {
+      width: '400px'
+    });
+    dialogRef.componentInstance.editRoom=this.room;
+  }
+
+  editSessionDescription(){
+    const dialogRef = this.dialog.open(RoomDescriptionSettingsComponent, {
+      width: '400px'
+    });
+    dialogRef.componentInstance.editRoom=this.room;
+  }
+
+  exportQuestions(){
+    const exp: Export = new Export(
+      this.room,
+      this.commentService,
+      this.bonusTokenService,
+      this.translateService,
+      'comment-list',
+      this.notificationService);
+    exp.exportAsCsv();
+  }
+
+  deleteQuestions(){
+    const dialogRef = this.dialog.open(DeleteCommentsComponent, {
+      width: '400px'
+    });
+    dialogRef.componentInstance.roomId = this.room.id;
+    dialogRef.afterClosed()
+    .subscribe(result => {
+      if (result === 'delete') {
+        this.translateService.get('room-page.comments-deleted').subscribe(msg => {
+          this.notificationService.show(msg);
+        });
+        this.commentService.deleteCommentsByRoomId(this.room.id).subscribe();
+      }
+    });
+  }
+
   ngOnDestroy() {
     super.ngOnDestroy();
     this.commentCounterEmitSubscription.unsubscribe();
@@ -142,8 +178,10 @@ export class RoomCreatorPageComponent extends RoomPageComponent implements OnIni
         if (lang === 'de') {
         this.liveAnnouncer.announce('Aktueller Sitzungs-Name: ' + this.room.name + '. ' +
                                     'Aktueller Raum-Code: ' + this.room.shortId);
-        } else { this.liveAnnouncer.announce('Current Session-Name: ' + this.room.name + '. ' +
-          'Current Session Code: ' + this.room.shortId); }
+        } else {
+ this.liveAnnouncer.announce('Current Session-Name: ' + this.room.name + '. ' +
+          'Current Session Code: ' + this.room.shortId);
+}
       } else if (
         KeyboardUtils.isKeyEvent(event, KeyboardKey.Digit9, KeyboardKey.Escape) === true &&
         this.eventService.focusOnInput === false
@@ -278,14 +316,12 @@ export class RoomCreatorPageComponent extends RoomPageComponent implements OnIni
   }
 
   showTagCloud(): void {
-    console.log("Showtagcloud called");
     const dialogRef = this.dialog.open(TopicCloudFilterComponent, {
       width: '400px'
     });
   }
 
   showTagsDialog(): void {
-    console.log("Showtag called");
     this.updRoom = JSON.parse(JSON.stringify(this.room));
     const dialogRef = this.dialog.open(TagsComponent, {
       width: '400px'
@@ -306,6 +342,30 @@ export class RoomCreatorPageComponent extends RoomPageComponent implements OnIni
       });
   }
 
+  openDeleteRoomDialog(): void {
+    const dialogRef = this.dialog.open(RoomDeleteComponent, {
+      width: '400px'
+    });
+    dialogRef.componentInstance.room = this.room;
+    dialogRef.afterClosed()
+    .subscribe(result => {
+      if (result === 'delete') {
+        this.deleteRoom();
+      }
+    });
+  }
+
+  deleteRoom(): void {
+    this.translationService.get('room-page.deleted').subscribe(msg => {
+      this.notificationService.show(this.room.name + msg);
+    });
+    this.roomService.deleteRoom(this.room.id).subscribe(result => {
+      const event = new RoomDeleted(this.room.id);
+      this.eventService.broadcast(event.type, event.payload);
+      this.location.back();
+    });
+  }
+
   copyShortId(): void {
     const selBox = document.createElement('textarea');
     selBox.style.position = 'fixed';
diff --git a/src/app/components/home/_dialogs/cookies/cookies.component.html b/src/app/components/home/_dialogs/cookies/cookies.component.html
index 828f262d86f172376d47bf85d8e3d0c4c540b6b8..b8315dac4de90a127bbdf933fbb1266e4e470e3e 100644
--- a/src/app/components/home/_dialogs/cookies/cookies.component.html
+++ b/src/app/components/home/_dialogs/cookies/cookies.component.html
@@ -13,7 +13,7 @@
     </button>
   </div>
 
-  <mat-divider></mat-divider>
+
 
   <mat-dialog-content tabindex="-1">
 
diff --git a/src/app/components/home/_dialogs/cookies/cookies.component.ts b/src/app/components/home/_dialogs/cookies/cookies.component.ts
index 5d69d51863d809bd0808c1b4def2115690ef5775..0f769405fa141921c40372e8baf4547e4c9692d8 100644
--- a/src/app/components/home/_dialogs/cookies/cookies.component.ts
+++ b/src/app/components/home/_dialogs/cookies/cookies.component.ts
@@ -2,6 +2,7 @@ import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angula
 import { DataProtectionComponent } from '../data-protection/data-protection.component';
 import { MatDialog, MatDialogRef } from '@angular/material/dialog';
 import { DialogConfirmActionButtonType } from '../../../shared/dialog/dialog-action-buttons/dialog-action-buttons.component';
+import { EventService } from '../../../../services/util/event.service';
 
 @Component({
   selector: 'app-cookies',
@@ -18,7 +19,10 @@ export class CookiesComponent implements OnInit, AfterViewInit {
 
   confirmButtonType: DialogConfirmActionButtonType = DialogConfirmActionButtonType.Primary;
 
-  constructor(private dialog: MatDialog, private dialogRef: MatDialogRef<CookiesComponent>, private ref: ElementRef) {
+  constructor(private dialog: MatDialog,
+              private dialogRef: MatDialogRef<CookiesComponent>,
+              private ref: ElementRef<HTMLElement>,
+              private eventService: EventService) {
   }
 
   ngOnInit() {
@@ -31,13 +35,14 @@ export class CookiesComponent implements OnInit, AfterViewInit {
 
   ngAfterViewInit() {
     setTimeout(() => {
-      (<HTMLElement>(<HTMLElement>this.ref.nativeElement).getElementsByClassName('mat-dialog-title')[0]).focus();
+      (this.ref.nativeElement.getElementsByClassName('mat-dialog-title')[0] as HTMLElement).focus();
     }, 500);
   }
 
   acceptCookies() {
     localStorage.setItem('cookieAccepted', 'true');
     localStorage.setItem('dataProtectionConsent', 'true');
+    this.eventService.broadcast('dataProtectionConsentUpdate', true);
     this.dialogRef.close(true);
     setTimeout(() => {
       document.getElementById('live_announcer-button').focus();
diff --git a/src/app/components/home/_dialogs/data-protection/data-protection.component.html b/src/app/components/home/_dialogs/data-protection/data-protection.component.html
index 747b8f3613d878e59104fad551a25e9f3535aa33..022ce18707dca781988bf2cd92fb676aacd231bc 100644
--- a/src/app/components/home/_dialogs/data-protection/data-protection.component.html
+++ b/src/app/components/home/_dialogs/data-protection/data-protection.component.html
@@ -4,7 +4,7 @@
       mat-dialog-title
       class="modal oldtypo-h2">{{ 'data-protection.title' | translate }}</h2>
 
-  <mat-divider></mat-divider>
+
 
   <mat-dialog-content tabindex="0">
     <app-data-protection-en *ngIf="currentLang=='en'"></app-data-protection-en>
diff --git a/src/app/components/home/_dialogs/demo-video/demo-video.component.html b/src/app/components/home/_dialogs/demo-video/demo-video.component.html
index 1ff33d7e72d5c87c66b10027ce367dbf1d0bcd15..ed8c9a2d89d51b9709494287d5063cae5e8d9ed4 100644
--- a/src/app/components/home/_dialogs/demo-video/demo-video.component.html
+++ b/src/app/components/home/_dialogs/demo-video/demo-video.component.html
@@ -10,7 +10,7 @@
 </div>
 <!--frag.jetzt-->
 <h1 tabindex="0" class="modal oldtypo-h2" mat-dialog-title>{{ 'introduction.title' | translate }}</h1>
-<mat-divider></mat-divider>
+
 <mat-dialog-content>
   <div id="setFocus" class="intro-text" tabindex="-1">
     <app-demo-en *ngIf="currentLang=='en'"></app-demo-en>
diff --git a/src/app/components/home/_dialogs/imprint/imprint.component.html b/src/app/components/home/_dialogs/imprint/imprint.component.html
index 2094257b41af9dd7bebca1653969fa68246f5379..238866fee112d15404449513cfbdd9b51c1fb3ce 100644
--- a/src/app/components/home/_dialogs/imprint/imprint.component.html
+++ b/src/app/components/home/_dialogs/imprint/imprint.component.html
@@ -2,7 +2,7 @@
 <h1 tabindex="0"
     mat-dialog-title>{{ 'imprint.title' | translate }} </h1>
 
-<mat-divider></mat-divider>
+
 
 <mat-dialog-content tabindex="0">
   <app-imprint-en *ngIf="currentLang=='en'"></app-imprint-en>
diff --git a/src/app/components/home/_dialogs/password-reset/password-reset.component.html b/src/app/components/home/_dialogs/password-reset/password-reset.component.html
index 5e07cdfb5f9cd449c75a566e7455329288df4b6b..55ead6df79f27f1e9c3a8ad07af099bc5af9ea56 100644
--- a/src/app/components/home/_dialogs/password-reset/password-reset.component.html
+++ b/src/app/components/home/_dialogs/password-reset/password-reset.component.html
@@ -21,7 +21,7 @@
   </button>
 </form>
 
-<mat-divider></mat-divider>
+
 
 <div fxLayout="column" class="textfields">
   <!--set new password-->
diff --git a/src/app/components/home/home-page/home-page.component.html b/src/app/components/home/home-page/home-page.component.html
index 9a8371ba260f91330770baf791745be70b57efb3..fa008117e4817c6b01bf947210a67f5dc1a19946 100644
--- a/src/app/components/home/home-page/home-page.component.html
+++ b/src/app/components/home/home-page/home-page.component.html
@@ -1,3 +1,9 @@
+<h1 style="display: none;"
+    [joyrideStep]="'greeting'"
+    appJoyrideTemplate
+    [stepPosition]="'center'">
+</h1>
+
 <div fxLayout="column"
      fxLayoutAlign="center"
      fxLayoutGap="20px"
@@ -31,11 +37,13 @@
       </mat-card-content>
     </mat-card>
   </div>
-  
-  <!--
+
   <h2>
     <span class="feedback">
-      <a class="info"
+      <a [joyrideStep]="'feedbackLink'"
+         appJoyrideTemplate
+         [stepPosition]="'top'"
+         class="info"
          href="https://frag.jetzt/participant/room/Feedback/comments"
          target="_blank"
          aria-labelledby="feedback-aria">{{ 'login.welcome-feedback' | translate }}
@@ -43,9 +51,9 @@
       </a>
     </span>
   </h2>
-  -->
 
   <button id="live_announcer-button"
+          autofocus
           tabIndex="-1"
           (click)="announce()"
           class="visually-hidden">{{ 'home-page.live-announcer' | translate }}</button>
diff --git a/src/app/components/home/home-page/home-page.component.scss b/src/app/components/home/home-page/home-page.component.scss
index a8c1e2067414cd8056b95130ba1719fb1d8d06f1..57268df5858112858ab237b212b972ef84b4387c 100644
--- a/src/app/components/home/home-page/home-page.component.scss
+++ b/src/app/components/home/home-page/home-page.component.scss
@@ -17,6 +17,7 @@
 
 .main-heading-secondary {
   display: block;
+  margin-top: 4vh;
   font-weight: bold;
   font-size: 80%;
   text-align: center;
@@ -31,6 +32,11 @@
   font-size: 60%;
   text-align: center;
   color: var(--on-background);
+
+  > a {
+    padding: 5px;
+    display: inline;
+  }
 }
 
 @keyframes moveInLeft {
@@ -71,7 +77,7 @@ mat-card-header {
 
 .screenshot {
   display: block;
-  margin-top: -30px;
+  margin-top: -20px;
   margin-left: auto;
   margin-right: auto;
   max-width: 100%;
diff --git a/src/app/components/home/home-page/home-page.component.ts b/src/app/components/home/home-page/home-page.component.ts
index c5380a171c7995c33008b68d3d8ea387b2d52554..2f2f9adda75d223286c1fc3770c14fa2ba451457 100644
--- a/src/app/components/home/home-page/home-page.component.ts
+++ b/src/app/components/home/home-page/home-page.component.ts
@@ -1,34 +1,32 @@
-import { Component, OnInit, OnDestroy, Renderer2, AfterContentInit } from '@angular/core';
+import { Component, OnInit, OnDestroy, Renderer2, AfterViewInit } from '@angular/core';
 import { EventService } from '../../../services/util/event.service';
 import { LiveAnnouncer } from '@angular/cdk/a11y';
 import { KeyboardUtils } from '../../../utils/keyboard';
 import { KeyboardKey } from '../../../utils/keyboard/keys';
 import { TranslateService } from '@ngx-translate/core';
+import { OnboardingService } from '../../../services/util/onboarding.service';
+import { Subscription } from 'rxjs';
 
 @Component({
   selector: 'app-home-page',
   templateUrl: './home-page.component.html',
   styleUrls: ['./home-page.component.scss']
 })
-export class HomePageComponent implements OnInit, OnDestroy, AfterContentInit {
+export class HomePageComponent implements OnInit, OnDestroy, AfterViewInit {
 
   deviceType: string;
   listenerFn: () => void;
+  private _eventServiceSubscription: Subscription;
 
   constructor(
     private translateService: TranslateService,
     private eventService: EventService,
     private liveAnnouncer: LiveAnnouncer,
-    private _r: Renderer2
+    private _r: Renderer2,
+    private onboardingService: OnboardingService
   ) {
   }
 
-  ngAfterContentInit(): void {
-    setTimeout( () => {
-      document.getElementById('live_announcer-button').focus();
-    }, 500);
-  }
-
   ngOnInit() {
     this.deviceType = localStorage.getItem('deviceType');
     if (localStorage.getItem('cookieAccepted')) {
@@ -43,7 +41,22 @@ export class HomePageComponent implements OnInit, OnDestroy, AfterContentInit {
     }
   }
 
-  loadListener () {
+  ngAfterViewInit() {
+    if (localStorage.getItem('dataProtectionConsent') === 'true') {
+      this.onboardingService.startDefaultTour();
+    } else {
+      this._eventServiceSubscription = this.eventService.on<boolean>('dataProtectionConsentUpdate')
+        .subscribe(b => {
+          if (b) {
+            this._eventServiceSubscription.unsubscribe();
+            this._eventServiceSubscription = null;
+            this.onboardingService.startDefaultTour();
+          }
+        });
+    }
+  }
+
+  loadListener() {
     this.listenerFn = this._r.listen(document, 'keyup', (event) => {
       if (KeyboardUtils.isKeyEvent(event, KeyboardKey.Digit1) === true && this.eventService.focusOnInput === false) {
         document.getElementById('session_id-input').focus();
@@ -65,6 +78,9 @@ export class HomePageComponent implements OnInit, OnDestroy, AfterContentInit {
   ngOnDestroy() {
     this.listenerFn();
     this.eventService.makeFocusOnInputFalse();
+    if (this._eventServiceSubscription) {
+      this._eventServiceSubscription.unsubscribe();
+    }
   }
 
   public announce() {
diff --git a/src/app/components/home/new-landing/new-landing.component.html b/src/app/components/home/new-landing/new-landing.component.html
index 20a83fea6022a11d5814b96666b84bea20c0f889..584ffcf62d32e74cf835cb05ff5c89efc98c8af4 100644
--- a/src/app/components/home/new-landing/new-landing.component.html
+++ b/src/app/components/home/new-landing/new-landing.component.html
@@ -3,7 +3,10 @@
      fxlayoutgap="20px"
      fxFill>
   <app-room-join></app-room-join>
-  <button [disabled]="cookiesDisabled()"
+  <button [joyrideStep]="'createRoom'"
+          appJoyrideTemplate
+          [stepPosition]="'top'"
+          [disabled]="cookiesDisabled()"
           id="new_session-button"
           mat-flat-button
           class="new-session"
diff --git a/src/app/components/home/new-landing/new-landing.component.scss b/src/app/components/home/new-landing/new-landing.component.scss
index ba491d4e6f0f7ec9369485257ff1fc85ec05fd62..80f3b9231884d3823e7e536e4dd420e1666bf7bb 100644
--- a/src/app/components/home/new-landing/new-landing.component.scss
+++ b/src/app/components/home/new-landing/new-landing.component.scss
@@ -2,14 +2,14 @@
   width: 100%;
   height: 60px;
   border-radius: 5px;
-  margin: 10% 0 2% 0;
+  margin: 10% 0 17% 0;
   font-size: large;
   background-color: var(--background);
   color: var(--on-background);
 }
 
 .add {
-  padding-right: 10px;
+  padding-right: 12px;
   padding-left: 10px;
   transform: scale(2);
   color: var(--primary);
diff --git a/src/app/components/home/user-home/user-home.component.html b/src/app/components/home/user-home/user-home.component.html
index d93a18db1c5f33741bdfb9c63ad37c784079775e..8b3c64f578d75cc765d094a1a42aa82049e99e42 100644
--- a/src/app/components/home/user-home/user-home.component.html
+++ b/src/app/components/home/user-home/user-home.component.html
@@ -1,16 +1,31 @@
-<div class="userHomeContainer" fxLayout="column" fxLayoutAlign="start" fxLayoutGap="20px">
-  <div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="15px">
+<div class="userHomeContainer"
+     fxLayout="column"
+     fxLayoutAlign="start"
+     fxLayoutGap="20px">
+  <div fxLayout="row"
+       fxLayoutAlign="center"
+       fxLayoutGap="15px">
     <app-room-join></app-room-join>
   </div>
-  <div fxLayout="row" fxLayoutAlign="center" class="button-container">
-    <button class="focus_button" mat-raised-button (click)="openCreateRoomDialog()" id="create_session-button">
-      <mat-icon>add_circle</mat-icon>
+  <div fxLayout="row"
+       fxLayoutAlign="center"
+       class="button-container">
+    <button class="new-session"
+            mat-flat-button
+            (click)="openCreateRoomDialog()"
+            id="create_session-button">
+      <mat-icon class="add">add_circle</mat-icon>
       {{ 'home-page.create-session' | translate }}
     </button>
   </div>
-  <div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="15px">
+  <div fxLayout="row"
+       fxLayoutAlign="center"
+       fxLayoutGap="15px">
     <app-room-list [user]="user"></app-room-list>
   </div>
-  <button id="live_announcer-button" tabIndex="-1" (click)="announce()" class="visually-hidden">{{ 'home-page.live-announcer-user' | translate }}</button>
+  <button id="live_announcer-button"
+          tabIndex="-1"
+          (click)="announce()"
+          class="visually-hidden">{{ 'home-page.live-announcer-user' | translate }}</button>
 </div>
 
diff --git a/src/app/components/home/user-home/user-home.component.scss b/src/app/components/home/user-home/user-home.component.scss
index 5c3daabea6a6a3881d0cdd1645464a91f8dd7cde..d605ba095fe7a3f06307a91507aaf98a5a933c48 100644
--- a/src/app/components/home/user-home/user-home.component.scss
+++ b/src/app/components/home/user-home/user-home.component.scss
@@ -3,16 +3,22 @@ app-room-list {
   max-width: 800px;
 }
 
-.mat-raised-button {
-  background-color: var(--primary);
-  color: var(--on-primary);
+.button-container {
+  margin-bottom: 3% !important;
 }
 
-.focus_button:focus {
-  background: var(--on-surface);
-  color: var(--background);
+.new-session {
+  width: 200px;
+  height: 60px;
+  border-radius: 5px;
+  font-size: large;
+  background-color: var(--background);
+  color: var(--on-background);
 }
 
-.button-container {
-  margin-bottom: 3% !important;
+.add {
+  padding-right: 12px;
+  padding-left: 10px;
+  transform: scale(2);
+  color: var(--primary);
 }
diff --git a/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts b/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts
index 0efa82d0e494e4b10cb496908cf12facd35904b0..854f7595a5f0ec417b4cb034b2964583ac93b828 100644
--- a/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts
+++ b/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts
@@ -5,7 +5,7 @@ import { TranslateService } from '@ngx-translate/core';
 import { LanguageService } from '../../../services/util/language.service';
 import { Message } from '@stomp/stompjs';
 import { MatDialog } from '@angular/material/dialog';
-import { WsCommentServiceService } from '../../../services/websockets/ws-comment-service.service';
+import { WsCommentService } from '../../../services/websockets/ws-comment.service';
 import { User } from '../../../models/user';
 import { Vote } from '../../../models/vote';
 import { UserRole } from '../../../models/user-roles.enum';
@@ -15,7 +15,6 @@ import { CorrectWrong } from '../../../models/correct-wrong.enum';
 import { EventService } from '../../../services/util/event.service';
 import { Router } from '@angular/router';
 import { AppComponent } from '../../../app.component';
-import { Period } from '../../shared/comment-list/comment-list.component';
 import { ModeratorsComponent } from '../../creator/_dialogs/moderators/moderators.component';
 import { TagsComponent } from '../../creator/_dialogs/tags/tags.component';
 import { DeleteCommentsComponent } from '../../creator/_dialogs/delete-comments/delete-comments.component';
@@ -23,6 +22,8 @@ import { Export } from '../../../models/export';
 import { CreateCommentComponent } from '../../shared/_dialogs/create-comment/create-comment.component';
 import { NotificationService } from '../../../services/util/notification.service';
 import { BonusTokenService } from '../../../services/http/bonus-token.service';
+import { CommentFilter, Period } from '../../../utils/filter-options';
+
 
 @Component({
   selector: 'app-moderator-comment-list',
@@ -63,7 +64,7 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy {
   search = false;
   searchPlaceholder = '';
   periodsList = Object.values(Period);
-  period: Period = Period.TWOWEEKS;
+  period: Period = Period.twoWeeks;
   fromNow: number;
   headerInterface = null;
 
@@ -72,7 +73,7 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy {
     private translateService: TranslateService,
     public dialog: MatDialog,
     protected langService: LanguageService,
-    private wsCommentService: WsCommentServiceService,
+    private wsCommentService: WsCommentService,
     protected roomService: RoomService,
     public eventService: EventService,
     private router: Router,
@@ -187,10 +188,18 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy {
     this.translateService.get('comment-list.search').subscribe(msg => {
       this.searchPlaceholder = msg;
     });
+  }
 
-    localStorage.setItem('currentFilters', JSON.stringify(this.currentFilter));
-    localStorage.setItem('currentPeriod', JSON.stringify(this.period));
-    localStorage.setItem('currentFromNowTimestamp', JSON.stringify(this.fromNow)); // can be null
+  private getCurrentFilter() {
+    const filter = new CommentFilter();
+    filter.filterSelected = this.currentFilter;
+    filter.periodSet = this.period;
+
+    if (filter.periodSet === Period.fromNow) {
+      filter.timeStampNow = new Date().getTime();
+    }
+
+    CommentFilter.currentFilter = filter;
   }
 
   checkScroll(): void {
@@ -317,6 +326,8 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy {
         c.id = payload.id;
         c.timestamp = payload.timestamp;
         c.creatorId = payload.creatorId;
+        c.keywordsFromQuestioner = payload.keywordsFromQuestioner ?
+                                   JSON.parse(payload.keywordsFromQuestioner as unknown as string) : null;
         c.userNumber = this.commentService.hashCode(c.creatorId);
         this.comments = this.comments.concat(c);
         break;
@@ -353,9 +364,6 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy {
     });
     this.hideCommentsList = true;
     this.sortComments(this.currentSort);
-
-    // set current filters to local storage for later use
-    localStorage.setItem('currentFilters', JSON.stringify(this.currentFilter));
   }
 
   clickedUserNumber(usrNumber: number): void {
@@ -402,39 +410,36 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy {
     const currentTime = new Date();
     const hourInSeconds = 3600000;
     let periodInSeconds;
-    if (this.period !== Period.ALL) {
+    if (this.period !== Period.all) {
       switch (this.period) {
-        case Period.FROMNOW:
+        case Period.fromNow:
           if (!this.fromNow) {
             this.fromNow = new Date().getTime();
           }
           break;
-        case Period.ONEHOUR:
+        case Period.oneHour:
           periodInSeconds = hourInSeconds;
           break;
-        case Period.THREEHOURS:
+        case Period.threeHours:
           periodInSeconds = hourInSeconds * 2;
           break;
-        case Period.ONEDAY:
+        case Period.oneDay:
           periodInSeconds = hourInSeconds * 24;
           break;
-        case Period.ONEWEEK:
+        case Period.oneWeek:
           periodInSeconds = hourInSeconds * 168;
           break;
-        case Period.TWOWEEKS:
+        case Period.twoWeeks:
           periodInSeconds = hourInSeconds * 336;
           break;
       }
       this.commentsFilteredByTime = this.comments
         .filter(c => new Date(c.timestamp).getTime() >=
-          (this.period === Period.FROMNOW ? this.fromNow : (currentTime.getTime() - periodInSeconds)));
+          (this.period === Period.fromNow ? this.fromNow : (currentTime.getTime() - periodInSeconds)));
     } else {
       this.commentsFilteredByTime = this.comments;
     }
 
-    localStorage.setItem('currentPeriod', JSON.stringify(this.period));
-    localStorage.setItem('currentFromNowTimestamp', JSON.stringify(this.fromNow)); // can be null
-
     this.filterComments(this.currentFilter);
   }
 }
diff --git a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.html b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.html
index d03cf13b0f4c93b402da3d05acb9fd0d134df896..61a847b46dc6ed9dac012768edb59457c3e5256f 100644
--- a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.html
+++ b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.html
@@ -4,8 +4,7 @@
      fxFill>
   <div fxLayout="row"
        fxLayoutAlign="center">
-    <mat-progress-spinner *ngIf="isLoading"
-                          mode="indeterminate"></mat-progress-spinner>
+    <app-mat-spinner-overlay *ngIf="isLoading" overlay="true"></app-mat-spinner-overlay>
     <mat-card *ngIf="room">
       <div fxLayout="row">
         <span class="fill-remaining-space"></span>
@@ -25,17 +24,17 @@
                     mat-icon-button
                     (click)="copyShortId()">
               <mat-icon class="copy"
-                        matTooltip="{{ 'room-page.copy-session-id' | translate}}">content_paste
+                        matTooltip="{{ 'room-page.copy-session-id' | translate}}">share
               </mat-icon>
             </button>
           </mat-card-subtitle>
         </mat-card-header>
         <span class="fill-remaining-space"></span>
       </div>
-      <mat-divider></mat-divider>
+
       <mat-card-content *ngIf="room.description"
                         fxLayoutAlign="center">
-        <markdown [data]="room.description.trim()"></markdown>
+        <app-custom-markdown class="images" [data]="room.description.trim()"></app-custom-markdown>
       </mat-card-content>
       <div fxLayout="column"
            fxLayoutAlign="center"
diff --git a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.scss b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.scss
index a6ed51d24b38c06010c775f436d1c015ff11b6d3..7d5ca669e29422bcd1504837eb371de897a11551 100644
--- a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.scss
+++ b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.scss
@@ -5,7 +5,7 @@ mat-card {
   max-width: 800px;
   min-height: 350px;
   max-height: 700px;
-  background-color: var(--surface)!important;
+  background-color: var(--surface) !important;
 }
 
 mat-card-content > :first-child {
@@ -19,8 +19,9 @@ mat-card-content > :first-child {
 .mat-icon-button {
   width: 60%; // 100%
   height: 75%;
-  color: var(--primary)!important;
+  color: var(--primary) !important;
   transition: all 0.3s;
+
   &:hover {
     transform: scale(1.2)
   }
@@ -33,10 +34,6 @@ mat-card-content > :first-child {
   margin-bottom: 5%;
 }
 
-.corner-icons {
-  width: 40px;
-}
-
 .corner-icon {
   font-size: 40px;
   height: 40px;
@@ -51,24 +48,24 @@ mat-card-content > :first-child {
   line-height: 100%!important;
 }*/
 
-.main-icon{
+.main-icon {
   font-size: 80px;
   height: 80px;
   width: 80px;
-  line-height: 100%!important;
+  line-height: 100% !important;
 }
 
 .smallerIcon {
   font-size: 55px;
   height: 55px;
   width: 55px;
-  line-height: 100%!important;
+  line-height: 100% !important;
 }
 
 .room-short-id {
   font-size: larger;
   font-weight: bold;
-  color: var(--on-surface)!important;
+  color: var(--on-surface) !important;
   margin: 5% 5% 0 0;
 }
 
@@ -81,33 +78,33 @@ mat-grid-list {
 }
 
 h1 {
-   font-size: large;
-   color: var(--on-surface)!important;
- }
+  font-size: large;
+  color: var(--on-surface) !important;
+}
 
 p {
-  color: var(--on-surface)!important;
+  color: var(--on-surface) !important;
 }
 
 h2 {
   font-size: larger;
-  color: var(--on-surface)!important;
+  color: var(--on-surface) !important;
 }
 
 mat-card-header {
   min-height: 80px;
-  height: 10%!important;
+  height: 10% !important;
 }
 
 mat-card-title {
   height: 40%;
   min-width: 200px;
-  color: var(--on-surface)!important;
+  color: var(--on-surface) !important;
 }
 
 mat-card-subtitle {
   height: 30%;
-  color: var(--on-surface)!important;
+  color: var(--on-surface) !important;
 }
 
 mat-grid-tile {
@@ -116,7 +113,7 @@ mat-grid-tile {
 }
 
 mat-expansion-panel {
-  background-color: var(--surface)!important;
+  background-color: var(--surface) !important;
   min-width: 200px;
   hyphens: auto;
 }
diff --git a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.ts b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.ts
index 07ed7ef4a5994f448cdd35c9977d71f4aa638b26..466dc34e6c8ac31f174be4617257fa90e2fed111 100644
--- a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.ts
+++ b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.ts
@@ -6,7 +6,7 @@ import { RoomService } from '../../../services/http/room.service';
 import { ActivatedRoute } from '@angular/router';
 import { TranslateService } from '@ngx-translate/core';
 import { LanguageService } from '../../../services/util/language.service';
-import { WsCommentServiceService } from '../../../services/websockets/ws-comment-service.service';
+import { WsCommentService } from '../../../services/websockets/ws-comment.service';
 import { CommentService } from '../../../services/http/comment.service';
 import { Message } from '@stomp/stompjs';
 import { NotificationService } from '../../../services/util/notification.service';
@@ -33,7 +33,7 @@ export class RoomModeratorPageComponent extends RoomPageComponent implements OnI
               protected route: ActivatedRoute,
               private translateService: TranslateService,
               protected langService: LanguageService,
-              protected wsCommentService: WsCommentServiceService,
+              protected wsCommentService: WsCommentService,
               protected commentService: CommentService,
               protected notification: NotificationService,
               public eventService: EventService,
diff --git a/src/app/components/participant/_dialogs/remind-of-tokens/remind-of-tokens.component.html b/src/app/components/participant/_dialogs/remind-of-tokens/remind-of-tokens.component.html
index 258f3cb44635ee018ccf92fa9905e1b025813ec2..d460d8fe51f3416b1558cfb9d15355cdd67ad5e9 100644
--- a/src/app/components/participant/_dialogs/remind-of-tokens/remind-of-tokens.component.html
+++ b/src/app/components/participant/_dialogs/remind-of-tokens/remind-of-tokens.component.html
@@ -1,7 +1,6 @@
 <div mat-dialog-content>
   <div>
     <h2 tabindex="0">{{ 'header.sure' | translate }}</h2>
-    <mat-divider></mat-divider>
     <p tabindex="0">{{ 'header.user-got-tokens' | translate }}</p>
   </div>
 </div>
diff --git a/src/app/components/participant/_dialogs/user-bonus-token/user-bonus-token.component.html b/src/app/components/participant/_dialogs/user-bonus-token/user-bonus-token.component.html
index d6c9c72f6067cfe05a7f6109db6a0473bc2d9d9e..69fb893e51e3eb0a9065a1704f87baef0c31ac62 100644
--- a/src/app/components/participant/_dialogs/user-bonus-token/user-bonus-token.component.html
+++ b/src/app/components/participant/_dialogs/user-bonus-token/user-bonus-token.component.html
@@ -1,7 +1,6 @@
 <div mat-dialog-content>
   <h2 class="oldtypo-h2"
       tabindex="0">{{'user-bonus-token.header' | translate }}</h2>
-  <mat-divider></mat-divider>
   <div *ngIf="bonusTokensMixin.length >= 1">
     <div fxLayout="column"
          class="tokens"
@@ -11,7 +10,7 @@
           tabindex="1">{{bonusToken.token}}</h2>
       <h2 class="roomName">&raquo;{{bonusToken.roomName}}&laquo;</h2>
     </div>
-    <mat-divider></mat-divider>
+
     <div fxLayout="column">
       <form class="example-form">
         <mat-form-field class="example-full-width">
diff --git a/src/app/components/participant/_dialogs/user-bonus-token/user-bonus-token.component.scss b/src/app/components/participant/_dialogs/user-bonus-token/user-bonus-token.component.scss
index 96aa7a07811a4cbb3df4c6e8130ac05115b2b9c5..fe3b4e59a6241b7ce247a169ea8a0e39a129ba0b 100644
--- a/src/app/components/participant/_dialogs/user-bonus-token/user-bonus-token.component.scss
+++ b/src/app/components/participant/_dialogs/user-bonus-token/user-bonus-token.component.scss
@@ -21,3 +21,7 @@ form {
   margin: 10px 0;
   text-align: center;
 }
+
+::ng-deep .mat-form-field .mat-form-field-infix {
+  max-width: 400px;
+}
diff --git a/src/app/components/participant/room-participant-page/room-participant-page.component.html b/src/app/components/participant/room-participant-page/room-participant-page.component.html
index ee603de0bd35c49bba5823dd808d170899af145d..5da0230922f98d2fa9238d034ffd97aea4cbaa39 100644
--- a/src/app/components/participant/room-participant-page/room-participant-page.component.html
+++ b/src/app/components/participant/room-participant-page/room-participant-page.component.html
@@ -1,6 +1,6 @@
 <div fxLayout="column" fxLayoutAlign="center" fxLayoutGap="20px" fxFill>
   <div fxLayout="row" fxLayoutAlign="center">
-    <mat-progress-spinner *ngIf="isLoading" mode="indeterminate"></mat-progress-spinner>
+    <app-mat-spinner-overlay *ngIf="isLoading" overlay="true"></app-mat-spinner-overlay>
     <mat-card *ngIf="room">
       <div fxLayout="row">
         <span class="fill-remaining-space"></span>
@@ -19,9 +19,9 @@
         </mat-card-header>
         <span class="fill-remaining-space"></span>
       </div>
-      <mat-divider></mat-divider>
+
       <mat-card-content *ngIf="room.description" fxLayoutAlign="center">
-        <markdown [data]="room.description.trim()"></markdown>
+        <app-custom-markdown class="images" [data]="room.description.trim()"></app-custom-markdown>
       </mat-card-content>
       <mat-grid-list cols="1" rowHeight="2:1">
         <mat-grid-tile>
diff --git a/src/app/components/participant/room-participant-page/room-participant-page.component.scss b/src/app/components/participant/room-participant-page/room-participant-page.component.scss
index 7e01c67a31b97b8b080a781255ad5f7f3c358705..4245f09a284b6dedbf446784aa4fb8e810471ce8 100644
--- a/src/app/components/participant/room-participant-page/room-participant-page.component.scss
+++ b/src/app/components/participant/room-participant-page/room-participant-page.component.scss
@@ -4,10 +4,10 @@ mat-card {
   width: 100%;
   max-width: 800px;
   min-height: 350px;
-  background-color: var(--surface)!important;
+  background-color: var(--surface) !important;
 }
 
-mat-card-content>:first-child {
+mat-card-content > :first-child {
   margin-top: 5%;
 }
 
@@ -16,14 +16,14 @@ mat-card-content>:first-child {
   height: 75%;
   margin-bottom: 3%;
   border-radius: 0;
-  color: var(--primary)!important;
+  color: var(--primary) !important;
 }
 
 .main-icon {
   font-size: 80px;
   height: 80px;
   width: 80px;
-  line-height: 100%!important;
+  line-height: 100% !important;
 }
 
 .desktop {
@@ -42,30 +42,29 @@ button {
 }
 
 
-
 h3 {
   margin: 5% 0 5% 0;
-  color: var(--on-surface)!important;
+  color: var(--on-surface) !important;
 }
 
 mat-card-header {
-  min-height: 80px!important;
-  height: 12%!important;
+  min-height: 80px !important;
+  height: 12% !important;
 }
 
 mat-card-title {
   height: 40%;
   min-width: 200px;
-  color: var(--on-surface)!important;
+  color: var(--on-surface) !important;
 }
 
 mat-card-subtitle {
   height: 20%;
-  color: var(-on--surface)!important;
+  color: var(-on--surface) !important;
 }
 
 mat-expansion-panel {
-  background-color: var(--surface)!important;
+  background-color: var(--surface) !important;
   min-width: 200px;
   hyphens: auto;
 }
diff --git a/src/app/components/participant/room-participant-page/room-participant-page.component.ts b/src/app/components/participant/room-participant-page/room-participant-page.component.ts
index 72b93139a0eeb8057c283ade7dd7b463c1e0734e..2d98c36882c0ee0423214693e4e97cb5426466f7 100644
--- a/src/app/components/participant/room-participant-page/room-participant-page.component.ts
+++ b/src/app/components/participant/room-participant-page/room-participant-page.component.ts
@@ -8,7 +8,7 @@ import { RoomService } from '../../../services/http/room.service';
 import { ActivatedRoute } from '@angular/router';
 import { TranslateService } from '@ngx-translate/core';
 import { LanguageService } from '../../../services/util/language.service';
-import { WsCommentServiceService } from '../../../services/websockets/ws-comment-service.service';
+import { WsCommentService } from '../../../services/websockets/ws-comment.service';
 import { CommentService } from '../../../services/http/comment.service';
 import { AuthenticationService } from '../../../services/http/authentication.service';
 import { LiveAnnouncer } from '@angular/cdk/a11y';
@@ -35,7 +35,7 @@ export class RoomParticipantPageComponent extends RoomPageComponent implements O
               protected route: ActivatedRoute,
               private translateService: TranslateService,
               protected langService: LanguageService,
-              protected wsCommentService: WsCommentServiceService,
+              protected wsCommentService: WsCommentService,
               protected commentService: CommentService,
               protected authenticationService: AuthenticationService,
               private liveAnnouncer: LiveAnnouncer,
diff --git a/src/app/components/shared/_dialogs/cloud-configuration/cloud-configuration.component.html b/src/app/components/shared/_dialogs/cloud-configuration/cloud-configuration.component.html
index 0c699b126ee2fb8c432f122912a1b69699b70af9..cea9b96d335667290ef45f34c4fd87bc3ecd4a57 100644
--- a/src/app/components/shared/_dialogs/cloud-configuration/cloud-configuration.component.html
+++ b/src/app/components/shared/_dialogs/cloud-configuration/cloud-configuration.component.html
@@ -1,88 +1,266 @@
 <div id="wholeDialog" class="drawer-container" fxLayout="column" fxLayoutGap="5px">
-  <div class="cloud-configuration-form" fxLayout="column">
-    <h2>{{'tag-cloud-config.title' | translate}}</h2>
-    <h3>{{'tag-cloud-config.general' | translate}}</h3>
-    <div class="input-row" fxLayout="row" fxLayoutGap="5px" fxLayout.xs="column">
-    </div>
-    <div class="input-row" fxLayout="row" fxLayoutGap="5px" fxLayout.xs="column">
-      <mat-slide-toggle (change)="valueChanged()" fxFlex [(ngModel)]="cloudParameters.randomAngles"
-        [ngModelOptions]="{standalone: true}">{{'tag-cloud-config.random-angle' | translate}}</mat-slide-toggle>
+  <div class="cloud-configuration-form" fxLayout="column" *ngIf="!extendedView && !cleanUpView">
+    <div class="input-row special-settings demo-cloud-settings" fxLayout="row" fxLayoutGap="5px" fxLayout.xs="column">
+      <div class="input-row" fxLayout="row" fxLayoutGap="5px" fxLayout.xs="column">
+        <mat-slide-toggle fxFlex (change)="parent.dataManager.demoActive = !parent.dataManager.demoActive"
+                          [checked]="parent.dataManager.demoActive"
+                          [ngModelOptions]="{standalone: true}">Demo Cloud
+        </mat-slide-toggle>
+      </div>
     </div>
-    <div style="margin: 10px;"></div>
-    <div class="input-row" fxLayout="column" fxLayoutGap="5px">
-      <div class="input-row" fxLayout="column" fxLayoutGap="5px">
-        <div fxLayout="row" fxLayoutGap="5px">
-          <mat-form-field fxFlex="100%">
-            <mat-label>{{'tag-cloud-config.background' | translate}}</mat-label>
-            <input matInput [value]="cloudParameters.backgroundColor" [colorPicker]="cloudParameters.backgroundColor"
-              (colorPickerChange)="backgroundColorChanged($event)" class="custom-color-picker" />
-            <p matTooltip="{{'tag-cloud-config.background-tooltip' | translate}}" class="custom-color-picker-text">
-              {{'tag-cloud-config.select-color' | translate}}</p>
+    <br>
+    <mat-accordion id="accordion">
+      <mat-expansion-panel [expanded]="step == 0" (opened)="setStep(0)" class="matExpansionPanel">
+        <mat-expansion-panel-header>
+          <mat-panel-title>
+            <label class=" expansion-title settings-heading">{{'tag-cloud-config.general' | translate}}</label>
+          </mat-panel-title>
+        </mat-expansion-panel-header>
+        <div class="input-row firstElementOfExpansionPanel" fxLayout="row" fxLayoutGap="5px" fxLayout.xs="column">
+          <mat-slide-toggle matTooltip="{{'tag-cloud-config.random-angle-tooltip' | translate}}"
+                            (change)="valueChanged()" fxFlex [(ngModel)]="cloudParameters.randomAngles"
+                            [ngModelOptions]="{standalone: true}">{{'tag-cloud-config.random-angle' | translate}}</mat-slide-toggle>
+          <mat-icon matTooltip="{{'tag-cloud-config.random-angle-note' | translate}}">help</mat-icon>
+        </div>
+        <div class="input-row special-settings automatic-spelling" fxLayout="row" fxLayoutGap="5px"
+             fxLayout.xs="column">
+          <mat-radio-group matTooltip="{{'tag-cloud-config.notation-tooltip' | translate}}"
+                           aria-label="Notation:"> {{'tag-cloud-config.notation' | translate}}
+            <div>
+              <mat-radio-button value="1" (change)="textStyleChanged(1)"
+                                [checked]="cloudParameters.textTransform == 1">{{'tag-cloud-config.lowerCase' | translate}}</mat-radio-button>
+            </div>
+            <div>
+              <mat-radio-button value="2" (change)="textStyleChanged(3)"
+                                [checked]="cloudParameters.textTransform == 3">{{'tag-cloud-config.upperCase' | translate}}</mat-radio-button>
+            </div>
+            <div>
+              <mat-radio-button value="2" (change)="textStyleChanged(2)"
+                                [checked]="cloudParameters.textTransform == 2">{{'tag-cloud-config.capitalization' | translate}}</mat-radio-button>
+            </div>
+            <div>
+              <mat-radio-button value="0" (change)="textStyleChanged(0)"
+                                [checked]="cloudParameters.textTransform == 0">{{'tag-cloud-config.standard' | translate}}</mat-radio-button>
+            </div>
+          </mat-radio-group>
+        </div>
+        <div class="input-row special-settings alphabetical-sorting" fxLayout="row" fxLayoutGap="5px"
+             fxLayout.xs="column">
+          <div class="input-row" fxLayout="row" fxLayoutGap="5px" fxLayout.xs="column">
+            <mat-slide-toggle matTooltip="{{'tag-cloud-config.alphabetical-sorting-tooltip' | translate}}"
+                              [(ngModel)]="cloudParameters.sortAlphabetically"
+                              [checked]="cloudParameters.sortAlphabetically" [ngModelOptions]="{standalone: true}"
+                              (change)="valueChanged()">{{'tag-cloud-config.alphabetical-sorting' | translate}}</mat-slide-toggle>
+          </div>
+        </div>
+        <div style="margin: 10px;"></div>
+        <div class="input-row" fxLayout="column" fxLayoutGap="5px">
+          <div class="input-row" fxLayout="column" fxLayoutGap="5px">
+            <div fxLayout="column" fxLayoutGap="5px">
+              <mat-label>{{'tag-cloud-config.background' | translate}}</mat-label>
+              <input [value]="cloudParameters.backgroundColor"
+                     [colorPicker]="cloudParameters.backgroundColor"
+                     (colorPickerChange)="backgroundColorChanged($event)"
+                     class="custom-color-picker"
+                     [cpToggle]="true"
+                     [cpDialogDisplay]="'inline'"/>
+            </div>
+          </div>
+        </div>
+        <div class="input-row" fxLayout="column" fxLayoutGap="5px">
+          <mat-label class="label-text">{{'tag-cloud-config.word-delay' | translate}}</mat-label>
+          <mat-slider #delaySlider min="0" max="1000" step="50" [(ngModel)]="cloudParameters.delayWord"
+                      [ngModelOptions]="{standalone: true}" (change)="valueChanged()" [thumbLabel]="true"
+                      [value]="cloudParameters.delayWord"
+                      matTooltip="{{'tag-cloud-config.word-delay-tooltip' | translate}}">
+          </mat-slider>
+        </div>
+        <mat-action-row>
+          <button mat-icon-button (click)="nextStep()">
+            <mat-icon>expand_more</mat-icon>
+          </button>
+        </mat-action-row>
+      </mat-expansion-panel>
+      <mat-expansion-panel [expanded]="step == 1" (opened)="setStep(1)" class="matExpansionPanel">
+        <mat-expansion-panel-header>
+          <mat-panel-title>
+            <label class=" expansion-title settings-heading">{{'tag-cloud-config.font' | translate}}</label>
+          </mat-panel-title>
+        </mat-expansion-panel-header>
+        <div class="input-row" fxLayout="column" fxLayoutGap="5px">
+          <mat-form-field appearance="fill">
+            <mat-label>{{'tag-cloud-config.font-family' | translate}}</mat-label>
+            <mat-select (selectionChange)="valueChanged()"
+                        matTooltip="{{'tag-cloud-config.font-family-tooltip' | translate}}"
+                        [(ngModel)]="cloudParameters.fontFamily">
+              <mat-option value="sans-serif">Normal</mat-option>
+              <mat-option value="Abril Fatface">Abril Fatface</mat-option>
+              <mat-option value="Dancing Script">Dancing Script</mat-option>
+              <mat-option value="Indie Flower">Indie Flower</mat-option>
+              <mat-option value="Permanent Marker">Permanent Marker</mat-option>
+            </mat-select>
           </mat-form-field>
-          <div fxFlex="35px" class="color-box" [style.background]="cloudParameters.backgroundColor"></div>
         </div>
-      </div>
-    </div>
-    <div class="input-row" fxLayout="column" fxLayoutGap="5px">
-      <mat-label class="label-text">{{'tag-cloud-config.word-delay' | translate}}</mat-label>
-      <mat-slider #delaySlider min="0" max="1000" step="50" [(ngModel)]="cloudParameters.delayWord"
-        [ngModelOptions]="{standalone: true}" (change)="valueChanged()" [thumbLabel]="true"
-        [value]="cloudParameters.delayWord" matTooltip="{{'tag-cloud-config.word-delay-tooltip' | translate}}">
-      </mat-slider>
-    </div>
-    <div class="input-row" fxLayout="column" fxLayoutGap="5px">
-      <mat-form-field fxFlex fxLayout.xs="column">
-        <mat-label>{{'tag-cloud-config.font-size-min' | translate}}</mat-label>
-        <input #minFont [value]="cloudParameters.fontSizeMin" matInput type="number"
-          [(ngModel)]="cloudParameters.fontSizeMin" [ngModelOptions]="{standalone: true}" (change)="valueChanged()"
-          min="10" max="300" step="10" matTooltip="{{'tag-cloud-config.font-size-min-tooltip' | translate}}" />
-      </mat-form-field>
-    </div>
-    <div class="input-row" fxLayout="column" fxLayoutGap="5px">
-      <mat-form-field fxFlex fxLayout.xs="column">
-        <mat-label>{{'tag-cloud-config.font-size-max' | translate}}</mat-label>
-        <input #maxFont matInput type="number" [(ngModel)]="cloudParameters.fontSizeMax"
-          [ngModelOptions]="{standalone: true}" (change)="valueChanged()" min="10" max="1000" step="10"
-          matTooltip="{{'tag-cloud-config.font-size-max-tooltip' | translate}}" />
-      </mat-form-field>
-    </div>
-    <h3>{{'tag-cloud-config.hover-title' | translate}}</h3>
-    <div>
-      <div class="input-row" fxLayout="column" fxLayoutGap="5px">
-        <div fxLayout="row" fxLayoutGap="5px">
-          <mat-form-field fxFlex="100%">
-            <mat-label>{{'tag-cloud-config.hover-color' | translate}}</mat-label>
-            <input matInput [value]="cloudParameters.fontColor" [colorPicker]="cloudParameters.fontColor"
-              (colorPickerChange)="fontColorChanged($event)" class="custom-color-picker" />
-            <p class="custom-color-picker-text" matTooltip="{{'tag-cloud-config.select-color-tooltip' | translate}}">
-              {{'tag-cloud-config.select-color' | translate}}</p>
+        <div class="input-row special-settings automatic-spelling" fxLayout="row" fxLayoutGap="5px"
+             fxLayout.xs="column">
+          <mat-radio-group matTooltip="{{'tag-cloud-config.bold-notation-tooltip' | translate}}" aria-label="Notation:">
+            <div>
+              <mat-slide-toggle [checked]="checkBold()" (change)="boldChecked($event)"
+                                [ngModelOptions]="{standalone: true}">{{'tag-cloud-config.font-style-bold' | translate}}</mat-slide-toggle>
+            </div>
+          </mat-radio-group>
+        </div>
+        <div class="input-row" fxLayout="column" fxLayoutGap="5px">
+          <mat-form-field fxFlex fxLayout.xs="column">
+            <mat-label>{{'tag-cloud-config.font-size-min' | translate}}</mat-label>
+            <input #minFont [value]="cloudParameters.fontSizeMin.toString()" matInput type="number"
+                   [(ngModel)]="cloudParameters.fontSizeMin" [ngModelOptions]="{standalone: true}"
+                   (change)="calcMaxFont($event,true)"
+                   min="50" max="300" step="10" matTooltip="{{'tag-cloud-config.font-size-min-tooltip' | translate}}"/>
           </mat-form-field>
-          <div fxFlex="35px" class="color-box" [style.background]="cloudParameters.fontColor"></div>
         </div>
-      </div>
-      <div class="input-row" fxLayout="column" fxLayoutGap="5px">
-        <mat-label class="label-text">{{'tag-cloud-config.hover-scale' | translate}}</mat-label>
-        <mat-slider #hoverScaleSlider [value]="cloudParameters.hoverScale" min="1" max="10" step="0.2"
-          [(ngModel)]="cloudParameters.hoverScale" [ngModelOptions]="{standalone: true}" (change)="valueChanged()"
-          [thumbLabel]="true" matTooltip="{{'tag-cloud-config.hover-scale-tooltip' | translate}}"></mat-slider>
-      </div>
-      <div class="input-row" fxLayout="column" fxLayoutGap="5px">
-        <mat-label class="label-text">{{'tag-cloud-config.hover-time' | translate}}</mat-label>
-        <mat-slider #transitonSlider [value]="cloudParameters.hoverTime" min="0" max="2" step="0.2"
-          [(ngModel)]="cloudParameters.hoverTime" [ngModelOptions]="{standalone: true}" (change)="valueChanged()"
-          [thumbLabel]="true" matTooltip="{{'tag-cloud-config.hover-time-tooltip' | translate}}"></mat-slider>
-      </div>
-      <div class="input-row" fxLayout="column" fxLayoutGap="5px">
-        <mat-label class="label-text">{{'tag-cloud-config.hover-delay' | translate}}</mat-label>
-        <mat-slider #hoverDelaySlider [value]="cloudParameters.hoverDelay" min="0" max="2" step="0.1"
-          [(ngModel)]="cloudParameters.hoverDelay" [ngModelOptions]="{standalone: true}" (change)="valueChanged()"
-          [thumbLabel]="true" matTooltip="{{'tag-cloud-config.hover-delay-tooltip' | translate}}"></mat-slider>
-      </div>
-    </div>
+        <div class="input-row" fxLayout="column" fxLayoutGap="5px">
+          <mat-form-field fxFlex fxLayout.xs="column">
+            <mat-label>{{'tag-cloud-config.font-size-max' | translate}}</mat-label>
+            <input #maxFont matInput type="number" [(ngModel)]="MaxFont" [value]="MaxFont.toString()"
+                   [ngModelOptions]="{standalone: true}" (change)="calcMaxFont($event,false)" min="1" max="10" step="1"
+                   matTooltip="{{'tag-cloud-config.font-size-max-tooltip' | translate}}"/>
+          </mat-form-field>
+        </div>
+        <mat-action-row>
+          <button mat-icon-button (click)="prevStep()">
+            <mat-icon>expand_less</mat-icon>
+          </button>
+          <button mat-icon-button (click)="nextStep()">
+            <mat-icon>expand_more</mat-icon>
+          </button>
+        </mat-action-row>
+      </mat-expansion-panel>
+      <mat-expansion-panel [expanded]="step == 2" (opened)="setStep(2)" class="matExpansionPanel">
+        <mat-expansion-panel-header>
+          <mat-panel-title>
+            <label class=" expansion-title settings-heading">{{'tag-cloud-config.hover-title' | translate}}</label>
+          </mat-panel-title>
+        </mat-expansion-panel-header>
+        <div>
+          <div class="input-row firstElementOfExpansionPanel" fxLayout="column" fxLayoutGap="5px">
+            <div fxLayout="column" fxLayoutGap="5px">
+              <mat-label>{{'tag-cloud-config.hover-color' | translate}}</mat-label>
+              <input [value]="cloudParameters.fontColor"
+                     [colorPicker]="cloudParameters.fontColor"
+                     (colorPickerChange)="fontColorChanged($event)"
+                     [cpToggle]="true"
+                     class="custom-color-picker"
+                     [cpDialogDisplay]="'inline'"/>
+            </div>
+          </div>
+          <div class="input-row" fxLayout="column" fxLayoutGap="5px">
+            <mat-label class="label-text">{{'tag-cloud-config.hover-scale' | translate}}</mat-label>
+            <mat-slider #hoverScaleSlider [value]="cloudParameters.hoverScale" min="1" max="10" step="0.2"
+                        [(ngModel)]="cloudParameters.hoverScale" [ngModelOptions]="{standalone: true}"
+                        (change)="valueChanged()"
+                        [thumbLabel]="true"
+                        matTooltip="{{'tag-cloud-config.hover-scale-tooltip' | translate}}"></mat-slider>
+          </div>
+          <div class="input-row" fxLayout="column" fxLayoutGap="5px">
+            <mat-label class="label-text">{{'tag-cloud-config.hover-time' | translate}}</mat-label>
+            <mat-slider #transitonSlider [value]="cloudParameters.hoverTime" min="0" max="2" step="0.2"
+                        [(ngModel)]="cloudParameters.hoverTime" [ngModelOptions]="{standalone: true}"
+                        (change)="valueChanged()"
+                        [thumbLabel]="true"
+                        matTooltip="{{'tag-cloud-config.hover-time-tooltip' | translate}}"></mat-slider>
+          </div>
+          <div class="input-row" fxLayout="column" fxLayoutGap="5px">
+            <mat-label class="label-text">{{'tag-cloud-config.hover-delay' | translate}}</mat-label>
+            <mat-slider #hoverDelaySlider [value]="cloudParameters.hoverDelay" min="0" max="2" step="0.1"
+                        [(ngModel)]="cloudParameters.hoverDelay" [ngModelOptions]="{standalone: true}"
+                        (change)="valueChanged()"
+                        [thumbLabel]="true"
+                        matTooltip="{{'tag-cloud-config.hover-delay-tooltip' | translate}}"></mat-slider>
+          </div>
+        </div>
+        <mat-action-row>
+          <button mat-icon-button (click)="prevStep()">
+            <mat-icon>expand_less</mat-icon>
+          </button>
+          <button mat-icon-button (click)="nextStep()">
+            <mat-icon>expand_more</mat-icon>
+          </button>
+        </mat-action-row>
+      </mat-expansion-panel>
+      <mat-expansion-panel [expanded]="step == 3" (opened)="setStep(3)" class="matExpansionPanel">
+        <mat-expansion-panel-header>
+          <mat-panel-title>
+            <label
+              class=" expansion-title settings-heading">{{'tag-cloud-config.weight-class-settings' | translate}}</label>
+          </mat-panel-title>
+        </mat-expansion-panel-header>
+        <div class="input-row" fxLayout="row" fxLayoutGap="5px" fxLayout.xs="column">
+          <div class="cloud-configuration-form" fxLayout="column">
+            <div *ngFor="let weightClass of weightClasses" class="weight-class-setting">
+              <div class="weight-class-setting-content">
+                <label
+                  class=" expansion-title weight-class-heading">{{'tag-cloud-config.weight-class' | translate}} {{weightClasses.indexOf(weightClass) + 1}}</label>
+                <div class="input-row" fxLayout="column" fxLayoutGap="5px">
+                  <div fxLayout="column" fxLayoutGap="5px">
+                    <mat-label>{{'tag-cloud-config.weight-color' | translate}}</mat-label>
+                    <input [value]="weightClass.tagColor" [colorPicker]="weightClass.tagColor"
+                           (colorPickerChange)="weightColorChanged(weightClasses.indexOf(weightClass), $event)"
+                           class="custom-color-picker"
+                           [cpToggle]="true"
+                           [cpDialogDisplay]="'inline'"/>
+                  </div>
+                </div>
+                <div class="input-row firstElementOfWeightClass" fxLayout="row" fxLayoutGap="5px" fxLayout.xs="column"
+                     *ngIf="weightClass.actualTagNumber > 0 && !parent.dataManager.demoActive">
+                  <mat-slide-toggle matTooltip="{{'tag-cloud-config.manual-weight-number-tooltip' | translate}}"
+                                    (change)="valueChanged()" fxFlex [(ngModel)]=" weightClass.allowManualTagNumber"
+                                    [ngModelOptions]="{standalone: true}">{{'tag-cloud-config.manual-weight-number' | translate}}</mat-slide-toggle>
+                  <mat-icon matTooltip="{{'tag-cloud-config.manual-weight-number-note' | translate}}">help</mat-icon>
+                </div>
+                <div class="input-row" fxLayout="column" fxLayoutGap="5px"
+                     *ngIf="weightClass.actualTagNumber > 0 && !parent.dataManager.demoActive && weightClass.allowManualTagNumber">
+                  <div class="input-row" fxLayout="column" fxLayoutGap="5px">
+                    <mat-label class="label-text">{{'tag-cloud-config.weight-number' | translate}}</mat-label>
+                    <mat-slider [value]="weightClass.maxTagNumber" min="1" [max]="weightClass.actualTagNumber" step="1"
+                                [(ngModel)]="weightClass.maxTagNumber" [ngModelOptions]="{standalone: true}"
+                                (change)="valueChanged()"
+                                [thumbLabel]="true"
+                                matTooltip="{{'tag-cloud-config.weight-number-tooltip' | translate}}"></mat-slider>
+                  </div>
+                </div>
+                <div class="input-row" fxLayout="column" fxLayoutGap="5px" *ngIf="!cloudParameters.randomAngles">
+                  <mat-label class="label-text">{{'tag-cloud-config.rotate-weight' | translate}}</mat-label>
+                  <mat-slider [value]="weightClass.rotationAngle" min="-180" max="180" step="1"
+                              [(ngModel)]="weightClass.rotationAngle" [ngModelOptions]="{standalone: true}"
+                              (change)="valueChanged()"
+                              [thumbLabel]="true"
+                              matTooltip="{{'tag-cloud-config.rotate-weight-tooltip' | translate}}"></mat-slider>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <mat-action-row>
+          <button mat-icon-button (click)="prevStep()">
+            <mat-icon>expand_less</mat-icon>
+          </button>
+          <button class="close-btn" mat-icon-button (click)="nextStep()">
+            <mat-icon>close</mat-icon>
+          </button>
+        </mat-action-row>
+      </mat-expansion-panel>
+    </mat-accordion>
     <br>
     <div class="button-row">
-      <button (click)="cancel()" mat-button class="secondary">{{'tag-cloud-config.cancel-btn' | translate}}</button>
-      <button (click)="save()" mat-button class="primary">{{'tag-cloud-config.save-btn' | translate}}</button>
+      <button (click)="reset()" mat-button
+              class="reset tag-config-button">{{'tag-cloud-config.reset-btn' | translate}}</button>
+    </div>
+    <div class="button-row save-or-cancel">
+      <button (click)="cancel()" mat-button
+              class="secondary tag-config-button">{{'tag-cloud-config.cancel-btn' | translate}}</button>
+      <button (click)="save()" mat-button
+              class="primary tag-config-button">{{'tag-cloud-config.save-btn' | translate}}</button>
     </div>
   </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/src/app/components/shared/_dialogs/cloud-configuration/cloud-configuration.component.scss b/src/app/components/shared/_dialogs/cloud-configuration/cloud-configuration.component.scss
index d38b2c54433cebd9dfddcf1158a71d172c4c88e2..20162aa28dbc89407cb9d659662c08ca9100ecc0 100644
--- a/src/app/components/shared/_dialogs/cloud-configuration/cloud-configuration.component.scss
+++ b/src/app/components/shared/_dialogs/cloud-configuration/cloud-configuration.component.scss
@@ -1,16 +1,12 @@
-* {
-  color: var(--on-dialog);
-}
-
-h2{
+h2 {
   color: var(--on-dialog);
   font-size: 1.7rem;
 }
 
-h3 {
-  border-bottom: 1px solid var(--primary);
+.expansion-title {
   color: var(--primary);
   padding-bottom: 6px;
+  font-size: 1.2rem;
 }
 
 #commentSlider {
@@ -35,18 +31,17 @@ div {
   color: var(--on-secondary);
 }
 
-button {
-  min-width: 105px;
+.tag-config-button {
+  min-width: 135px;
 }
 
-mat-icon {
-  margin-right: 10px;
+.close-btn mat-icon {
+  font-size: 20px;
+  margin-top: 2px;
 }
 
-
-mat-divider {
-  margin-bottom: 10px;
-  color: var(--on-surface) !important;
+mat-icon {
+  margin-right: 10px;
 }
 
 .abort {
@@ -63,43 +58,46 @@ mat-divider {
   margin-top: 20px;
 }
 
-.color-box{
+.color-box {
   flex: 1 1 100%;
   box-sizing: border-box;
   border: 2px solid var(--on-dialog);
   height: 30px;
   width: 20px;
+  bottom: 8px;
   border-radius: 50%;
   margin-top: 13px;
+  margin-bottom: 10px;
   transform: translateY(-4px);
   display: block;
   position: relative;
   right: 40px;
+  pointer-events: none;
 }
 
-::ng-deep .mat-slide-toggle-thumb{
-  background-color:  var(--secondary);
+::ng-deep .mat-slide-toggle-thumb {
+  background-color: var(--secondary);
 }
 
-::ng-deep .mat-slide-toggle.mat-checked .mat-slide-toggle-bar{
-  background-color:  var(--primary);
+::ng-deep .mat-slide-toggle.mat-checked .mat-slide-toggle-bar {
+  background-color: var(--primary);
 }
 
-::ng-deep .mat-slide-toggle.mat-checked .mat-slide-toggle-thumb{
-  background-color:  var(--primary);
+::ng-deep .mat-slide-toggle.mat-checked .mat-slide-toggle-thumb {
+  background-color: var(--primary);
 
 }
 
 ::ng-deep .mat-form-field-label {
-  color: var(--on-surface)!important;
+  color: var(--on-surface) !important;
 }
 
 ::ng-deep .mat-form-field-underline {
-  background-color: var(--on-surface)!important;
+  background-color: var(--on-surface) !important;
 }
 
 ::ng-deep .mat-form-field-ripple {
-  background-color: var(--on-surface)!important;
+  background-color: var(--on-surface) !important;
 }
 
 ::ng-deep .mat-select-arrow-wrapper .mat-select-arrow {
@@ -116,54 +114,134 @@ mat-divider {
 
 ::ng-deep .mat-accent .mat-slider-track-fill,
 ::ng-deep .mat-accent .mat-slider-thumb,
-::ng-deep .mat-accent .mat-slider-thumb-label{
-  color: var(--on-primary);;
+::ng-deep .mat-accent .mat-slider-thumb-label {
+  color: var(--on-primary);
   background-color: var(--primary);
 }
 
-::ng-deep .mat-accent .mat-slider-thumb-label-text{
-  color:  var(--on-primary);
+::ng-deep .mat-accent .mat-slider-thumb-label-text {
+  color: var(--on-primary);
 }
 
-::ng-deep .primary{
-  color: var(--on-primary);;
+::ng-deep .primary {
+  color: var(--on-primary);
   background-color: var(--primary);
 }
 
-::ng-deep .secondary{
-  color: var(--on-cancel);;
+::ng-deep .secondary {
+  color: var(--on-cancel);
   background-color: var(--cancel);
   margin-right: 20px;
 
 }
 
-.button-row{
-  margin: auto auto 50px auto ;
+.button-row {
+  width: 100%;
+  margin: auto auto 20px auto;
+}
+
+.reset {
+  margin: 25px auto auto auto;
+  background-color: var(--secondary);
+  color: var(--alt-surface);
+  width: 100%;
 }
 
-.cloud-configuration-form{
-  width: 265px;
-  margin-top: 60px;
+.cloud-configuration-form {
+  width: min-content;
 }
 
-.drawer-container{
+.drawer-container {
+  color: var(--on-dialog) !important;
   margin: 20px;
+  align-items: center;
+  justify-content: center;
 }
 
-::ng-deep.custom-color-picker{
-  opacity: 0;
-  z-index: -1;
+.custom-color-picker {
+  display: none;
 }
-.custom-color-picker-text{
+
+.custom-color-picker-text {
   position: absolute;
+  top: 25px;
   transform: translateY(-35px);
 }
 
-::ng-deep.mat-drawer-backdrop.mat-drawer-shown{
-  display: none;
+.settings-heading {
+  margin-left: 0;
+  margin-right: auto;
+}
+
+::ng-deep .mat-drawer-backdrop {
+  opacity: 0;
 }
 
-::ng-deep.mat-slider-track-background{
+::ng-deep.mat-slider-track-background {
   background-color: var(--primary);
   opacity: 0.2;
-}
\ No newline at end of file
+}
+
+.weight-class-setting-content {
+  border-top: 3px solid var(--primary);
+  padding-top: 20px;
+  padding-bottom: 15px;
+}
+
+.weight-class-heading {
+  border: none;
+  color: var(--on-dialog);
+}
+
+#extendedViewButton {
+  margin-right: 10px;
+}
+
+.demo-cloud-settings {
+  border-bottom: none;
+}
+
+#accordion {
+  margin-bottom: 10px;
+  margin-top: 10px;
+}
+
+.weight-class-buttons {
+  margin-bottom: 0;
+}
+
+.special-settings {
+  border-top: none;
+  border-bottom: 2px solid var(--primary);
+  padding: 10px 0;
+  margin-bottom: 20px;
+}
+
+#rotation {
+  margin-top: 10px;
+}
+
+.matExpansionPanel {
+  background-color: var(--dialog);
+  color: var(--on-dialog) !important;
+  margin: 2px;
+  padding: 5px;
+}
+
+.firstElementOfExpansionPanel {
+  border-top: 2px solid var(--primary);
+  padding-top: 10px;
+}
+
+.firstElementOfWeightClass {
+  margin-top: 10px;
+  padding-bottom: 10px;
+}
+
+.automatic-spelling {
+  padding-bottom: 30px;
+}
+
+.save-or-cancel {
+  width: max-content;
+}
diff --git a/src/app/components/shared/_dialogs/cloud-configuration/cloud-configuration.component.ts b/src/app/components/shared/_dialogs/cloud-configuration/cloud-configuration.component.ts
index f52da628444f4c1f5cf4848dece62dbf9eb46a02..209c571529cc6c1174af4512d16639806d591f86 100644
--- a/src/app/components/shared/_dialogs/cloud-configuration/cloud-configuration.component.ts
+++ b/src/app/components/shared/_dialogs/cloud-configuration/cloud-configuration.component.ts
@@ -1,52 +1,274 @@
-
-
-
-import { Component, Input, OnInit, SimpleChanges } from '@angular/core';
+import { Component, Input, OnInit } from '@angular/core';
 import { TranslateService } from '@ngx-translate/core';
 import { TagCloudComponent } from '../../tag-cloud/tag-cloud.component';
-import { CloudParameters } from '../../tag-cloud/tag-cloud.interface';
+import { WeightClass } from './weight-class.interface';
+import { TagCloudMetaDataCount } from '../../../../services/util/tag-cloud-data.service';
+import { CloudParameters, CloudTextStyle } from '../../../../utils/cloud-parameters';
+import { AppComponent } from '../../../../app.component';
 
 @Component({
   selector: 'app-cloud-configuration',
   templateUrl: './cloud-configuration.component.html',
   styleUrls: ['./cloud-configuration.component.scss'],
 })
-export class CloudConfigurationComponent implements OnInit{
+export class CloudConfigurationComponent implements OnInit {
   @Input() parent: TagCloudComponent;
+  CloudTextStyle: CloudTextStyle;
   cloudParameters: CloudParameters;
   defaultCloudParameters: CloudParameters;
-  oldCloudParameters: CloudParameters
- 
-  constructor(private translateService: TranslateService) {}
+  oldCloudParameters: CloudParameters;
+  countPerWeight: TagCloudMetaDataCount;
+  extendedView: boolean;
+  cleanUpView: boolean;
+  automaticSpelling: boolean;
+  lowerCase: boolean;
+  capitalization: boolean;
+  standard: boolean;
+  alphabeticalSorting: boolean;
+  rotation: number;
+  highestWeight: number;
+  step: number = 10;
+  weightClasses: WeightClass[] = [
+    {
+      maxTagNumber: 20,
+      tagColor: '#8800ff',
+      actualTagNumber: 5,
+      rotationAngle: 0,
+      allowManualTagNumber: false
+    },
+    {
+      maxTagNumber: 20,
+      tagColor: '#ff00ff',
+      actualTagNumber: 5,
+      rotationAngle: 0,
+      allowManualTagNumber: false
+    },
+    {
+      maxTagNumber: 17,
+      tagColor: '#ffea00',
+      actualTagNumber: 5,
+      rotationAngle: 0,
+      allowManualTagNumber: false
+    },
+    {
+      maxTagNumber: 15,
+      tagColor: '#00CC99',
+      actualTagNumber: 5,
+      rotationAngle: 0,
+      allowManualTagNumber: false
+    },
+    {
+      maxTagNumber: 12,
+      tagColor: '#00CC66',
+      actualTagNumber: 5,
+      rotationAngle: 0,
+      allowManualTagNumber: false
+    },
+    {
+      maxTagNumber: 10,
+      tagColor: '#0033FF',
+      actualTagNumber: 5,
+      rotationAngle: 0,
+      allowManualTagNumber: false
+    },
+    {
+      maxTagNumber: 8,
+      tagColor: '#CC0099',
+      actualTagNumber: 5,
+      rotationAngle: 0,
+      allowManualTagNumber: false
+    },
+    {
+      maxTagNumber: 7,
+      tagColor: '#FF3399',
+      actualTagNumber: 5,
+      rotationAngle: 0,
+      allowManualTagNumber: false
+    },
+    {
+      maxTagNumber: 6,
+      tagColor: '#FFFF00',
+      actualTagNumber: 5,
+      rotationAngle: 0,
+      allowManualTagNumber: false
+    },
+    {
+      maxTagNumber: 5,
+      tagColor: '#FF0000',
+      actualTagNumber: 5,
+      rotationAngle: 0,
+      allowManualTagNumber: false
+    },
+  ];
+  MinFont: number;
+  MaxFont: number;
+
+  isTestCloud = false;
+
+  constructor(private translateService: TranslateService) {
+  }
 
   ngOnInit() {
     this.translateService.use(localStorage.getItem('currentLang'));
-    this.cloudParameters = this.parent.getCurrentCloudParameters();
-    this.defaultCloudParameters = this.parent.getCurrentCloudParameters();
+    this.cloudParameters = new CloudParameters(this.parent.currentCloudParameters);
+    this.defaultCloudParameters = new CloudParameters(this.parent.currentCloudParameters);
+    this.parent.dataManager.getMetaData().subscribe((value) => {
+      if (!value) {
+        return;
+      }
+      this.countPerWeight = value.countPerWeight;
+      this.parseArrayToJsonWeightClasses();
+    });
+    this.extendedView = false;
+    this.cleanUpView = false;
+    this.automaticSpelling = true;
+    this.lowerCase = true;
+    this.capitalization = false;
+    this.standard = false;
+    this.alphabeticalSorting = true;
+    this.rotation = 360;
+    this.highestWeight = 100;
+    this.readMaxFont();
   }
 
-  fontColorChanged(value: string){
+  fontColorChanged(value: string) {
     this.cloudParameters.fontColor = value;
-    this.parent.setCloudParameters(this.cloudParameters, false);
+    this.valueChanged();
   }
 
-  backgroundColorChanged(value: string){
+  backgroundColorChanged(value: string) {
     this.cloudParameters.backgroundColor = value;
-    this.valueChanged()
+    this.valueChanged();
+  }
+
+  parseArrayToJsonWeightClasses() {
+    this.cloudParameters.cloudWeightSettings.forEach((element, i) => {
+      this.weightClasses[i].tagColor = element.color;
+      this.weightClasses[i].actualTagNumber = this.countPerWeight[i];
+      this.weightClasses[i].rotationAngle = element.rotation;
+      this.weightClasses[i].maxTagNumber = (element.maxVisibleElements == -1 || element.maxVisibleElements == 0) ? this.weightClasses[i].actualTagNumber : element.maxVisibleElements;
+      this.weightClasses[i].allowManualTagNumber = element.allowManualTagNumber;
+    });
+  }
+
+  parseJsonToArrayWeightClasses() {
+    this.weightClasses.forEach((element, i) => {
+      this.cloudParameters.cloudWeightSettings[i].allowManualTagNumber = element.allowManualTagNumber;
+      if (element.allowManualTagNumber == true) {
+        this.cloudParameters.cloudWeightSettings[i].maxVisibleElements = element.maxTagNumber == 0 ? -1 : element.maxTagNumber;
+      } else {
+        this.cloudParameters.cloudWeightSettings[i].maxVisibleElements = -1;
+      }
+      this.cloudParameters.cloudWeightSettings[i].color = element.tagColor;
+      this.cloudParameters.cloudWeightSettings[i].rotation = element.rotationAngle;
+    });
   }
 
-  valueChanged(){
+  valueChanged() {
+    this.parseJsonToArrayWeightClasses();
     this.parent.setCloudParameters(this.cloudParameters, false);
   }
 
-  cancel(){
+  closePanel() {
+    this.parent.tagCloudDataManager.demoActive = false;
+    this.parent.drawer.close();
+    this.readMaxFont();
+    const defaultScale = AppComponent.rescale.getInitialScale();
+    if (defaultScale !== 1) {
+      AppComponent.rescale.setDefaultScale(defaultScale);
+      this.parent.updateTagCloud();
+    }
+  }
+
+  openPanel() {
+    if (AppComponent.rescale.getInitialScale() !== 1) {
+      AppComponent.rescale.setDefaultScale(1);
+    }
+  }
+
+  cancel() {
     this.parent.setCloudParameters(this.defaultCloudParameters);
-    this.parent.configurationOpen = false;
+    this.cloudParameters = new CloudParameters(this.defaultCloudParameters);
+    this.setStep(0);
+    this.closePanel();
   }
 
-  save(){
+  save() {
     this.parent.setCloudParameters(this.cloudParameters);
-    this.parent.configurationOpen = false;
+    this.defaultCloudParameters = new CloudParameters(this.cloudParameters);
+    this.setStep(0);
+    this.closePanel();
+  }
+
+  toggleExtendedView() {
+    this.cleanUpView = false;
+    this.extendedView = !this.extendedView;
+  }
+
+  toggleCleanupView() {
+    this.cleanUpView = !this.cleanUpView;
+    this.extendedView = false;
+  }
+
+  weightColorChanged(index: number, event: string): void {
+    this.weightClasses[index].tagColor = event;
+    this.valueChanged();
+  }
+
+  textStyleChanged(val: CloudTextStyle) {
+    this.cloudParameters.textTransform = val;
+    this.valueChanged();
+  }
+
+  setStep(index: number) {
+    this.step = index;
+  }
+
+  nextStep() {
+    this.step++;
+  }
+
+  prevStep() {
+    this.step--;
+  }
+
+  reset() {
+    this.parent.resetColorsToTheme();
+    this.cloudParameters = new CloudParameters(this.parent.currentCloudParameters);
+    this.defaultCloudParameters = new CloudParameters(this.parent.currentCloudParameters);
+    this.closePanel();
+  }
+
+  italicChecked(event) {
+    this.cloudParameters.fontStyle = event.checked === true ? 'italic' : 'normal';
+    this.valueChanged();
+  }
+
+  boldChecked(event) {
+    this.cloudParameters.fontWeight = event.checked === true ? 'bold' : 'normal';
+    this.valueChanged();
   }
 
+  checkBold() {
+    return this.cloudParameters.fontWeight === 'bold';
+  }
+
+  readMaxFont() {
+    let valMax: number = this.cloudParameters.fontSizeMax;
+    let valMin: number = this.cloudParameters.fontSizeMin;
+    this.MaxFont = Math.floor(valMax / valMin);
+  }
+
+  calcMaxFont(event, setMin: Boolean) {
+    let val: number = Number(event.target.value);
+    if (val > 0 && val <= 10 && !setMin) {
+      this.cloudParameters.fontSizeMax = this.cloudParameters.fontSizeMin * val;
+      this.MaxFont = val;
+      this.valueChanged();
+    }
+    if (setMin) {
+      this.cloudParameters.fontSizeMax = this.cloudParameters.fontSizeMin * this.MaxFont;
+      this.valueChanged();
+    }
+  }
 }
diff --git a/src/app/components/shared/_dialogs/cloud-configuration/weight-class.interface.ts b/src/app/components/shared/_dialogs/cloud-configuration/weight-class.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6cf05143bfd5c2253e2325bc56c0fc6ca830f92f
--- /dev/null
+++ b/src/app/components/shared/_dialogs/cloud-configuration/weight-class.interface.ts
@@ -0,0 +1,7 @@
+export interface WeightClass {
+    maxTagNumber: number;
+    tagColor: string;
+    actualTagNumber: number;
+    rotationAngle: number;
+    allowManualTagNumber: boolean;
+}
diff --git a/src/app/components/shared/_dialogs/create-comment/create-comment.component.html b/src/app/components/shared/_dialogs/create-comment/create-comment.component.html
index 3f4d32f786d5afea87405bfd5edcfd6f6ff2009b..744beea27e2131ebac46c0fa000c3a5f410b0f75 100644
--- a/src/app/components/shared/_dialogs/create-comment/create-comment.component.html
+++ b/src/app/components/shared/_dialogs/create-comment/create-comment.component.html
@@ -1,93 +1,9 @@
 <ars-row ars-flex-box>
-  <ars-row>
-    <div class="anchor-wrp">
-      <div class="anchor-right">
-        <mat-form-field *ngIf="tags"
-                        class="tag-form-field">
-          <mat-label>
-            <mat-icon class="icon-svg"
-                      svgIcon="comment_tag"></mat-icon>
-            {{'comment-page.tag' | translate}}</mat-label>
-          <mat-select [(ngModel)]="selectedTag"
-                      class="tag-select">
-            <mat-option>{{'comment-page.tag-reset' | translate}}</mat-option>
-            <mat-option *ngFor="let tag of tags"
-                        value="{{tag}}">
-              {{tag}}
-            </mat-option>
-          </mat-select>
-        </mat-form-field>
-      </div>
-    </div>
-    <mat-tab-group>
-      <mat-tab label="{{ 'comment-page.write-comment' | translate }}">
-        <ars-row [height]="12"></ars-row>
-        <ars-row>
-          <mat-divider></mat-divider>
-        </ars-row>
-        <ars-row [height]="12"></ars-row>
-        <ars-row [overflow]="'auto'"
-                 style="max-height:calc( 100vh - 250px )">
-          <mat-form-field style="width:100%;">
-            <textarea (focus)="eventService.makeFocusOnInputTrue()"
-                      style="margin-top:15px;width:100%;"
-                      (blur)="eventService.makeFocusOnInputFalse()"
-                      matInput
-                      #commentBody
-                      matTextareaAutosize
-                      matAutosizeMinRows="5"
-                      matAutosizeMaxRows="10"
-                      maxlength="{{user.role === 3 ? 1000 : 500}}"
-                      [formControl]="bodyForm"
-                      aria-labelledby="ask-question-description"
-                      autofocus
-                      id="answer-input">
-            </textarea>
-            <mat-placeholder class="placeholder">
-              {{ 'comment-page.enter-comment' | translate }}
-            </mat-placeholder>
-            <mat-hint align="start">
-              <span aria-hidden="true">
-                {{ 'comment-page.Markdown-hint' | translate }}
-              </span>
-            </mat-hint>
-            <mat-hint align="end">
-              <span aria-hidden="true">
-                {{commentBody.value.length}} / {{user.role === 3 ? 1000 : 500}}
-              </span>
-            </mat-hint>
-          </mat-form-field>
-        </ars-row>
-      </mat-tab>
-      <mat-tab label="{{ 'comment-page.preview-comment' | translate }}"
-               [disabled]="!commentBody.value">
-        <ars-row [height]="12"></ars-row>
-        <ars-row>
-          <mat-divider></mat-divider>
-        </ars-row>
-        <ars-row [height]="12"></ars-row>
-        <ars-row [overflow]="'auto'"
-                 style="max-height:calc( 100vh - 250px )">
-          <markdown [data]="commentBody.value"></markdown>
-        </ars-row>
-      </mat-tab>
-    </mat-tab-group>
-  </ars-row>
-  <ars-row style="margin-top:8px">
-    <mat-divider></mat-divider>
-  </ars-row>
-  <ars-row ars-flex-box>
-    <ars-fill>
-    </ars-fill>
-    <ars-col>
-      <app-dialog-action-buttons
-        buttonsLabelSection="comment-page"
-        confirmButtonLabel="send"
-        [showDivider]="false"
-        [spacing]="false"
-        [cancelButtonClickAction]="buildCloseDialogActionCallback()"
-        [confirmButtonClickAction]="buildCreateCommentActionCallback(commentBody)"
-      ></app-dialog-action-buttons>
-    </ars-col>
-  </ars-row>
+  <app-write-comment [confirmLabel]="'send'"
+                     [onSubmit]="buildCreateCommentActionCallback()"
+                     [onClose]="buildCloseDialogActionCallback()"
+                     [isSpinning]="isSendingToSpacy"
+                     [tags]="tags"
+                     [user]="user">
+  </app-write-comment>
 </ars-row>
diff --git a/src/app/components/shared/_dialogs/create-comment/create-comment.component.scss b/src/app/components/shared/_dialogs/create-comment/create-comment.component.scss
index d795fb287789cde71d15807311ee8d34c1c79a17..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/src/app/components/shared/_dialogs/create-comment/create-comment.component.scss
+++ b/src/app/components/shared/_dialogs/create-comment/create-comment.component.scss
@@ -1,93 +0,0 @@
-button {
-  min-width: 80px;
-}
-
-form {
-  display: block;
-  width: 100%;
-  max-width: 800px;
-  margin-bottom: 50px;
-}
-
-app-comment-list {
-  width: 100%;
-  max-width: 800px;
-}
-
-textarea {
-  line-height: 120%;
-  color: var(--on-surface);
-  caret-color: var(--on-surface);
-}
-
-.send {
-  color: var(--on-primary);
-  background-color: var(--primary);
-}
-
-mat-hint {
-  color: var(--on-surface) !important;
-}
-
-.mat-select-value-text {
-  color: var(--on-surface);
-  caret-color: var(--on-surface);
-}
-
-.placeholder {
-  color: var(--on-surface);
-}
-
-.tag-form-field{
-  @media screen and (max-width:500px) {
-    width:70px;
-  }
-  z-index:10000;
-}
-
-.tag-select{
-}
-
-.anchor-right{
-  @media screen and (max-width:500px) {
-    width:70px;
-    left:calc( 100% - 70px );
-  }
-  width:200px;
-  height:50px;
-  position:relative;
-  left:calc( 100% - 200px );
-  top:0;
-}
-
-.anchor-wrp{
-  width:100%;
-  height:0;
-  position:relative;
-  left:0;
-  top:0;
-}
-
-::ng-deep .mat-form-field-label {
-  color: var(--on-surface)!important;
-}
-
-::ng-deep .mat-form-field-underline {
-  background-color: var(--on-surface)!important;
-}
-
-::ng-deep .mat-form-field-ripple {
-  background-color: var(--on-surface)!important;
-}
-
-::ng-deep .mat-select-arrow-wrapper .mat-select-arrow {
-  color: var(--on-surface);
-}
-
-::ng-deep .mat-select-value-text {
-  color: var(--on-surface);
-}
-
-::ng-deep .mat-primary .mat-option.mat-selected:not(.mat-option-disabled) {
-  color: var(--primary);
-}
diff --git a/src/app/components/shared/_dialogs/create-comment/create-comment.component.ts b/src/app/components/shared/_dialogs/create-comment/create-comment.component.ts
index 87f620569ee0cdab4e0570f2d5ee594d9f5c5d21..654bb7aa9d5c097f383da2811c3a1d81c71db76c 100644
--- a/src/app/components/shared/_dialogs/create-comment/create-comment.component.ts
+++ b/src/app/components/shared/_dialogs/create-comment/create-comment.component.ts
@@ -1,13 +1,15 @@
-import { Component, Inject, OnInit, ViewChild } from '@angular/core';
-import { Comment } from '../../../../models/comment';
+import { Component, Inject, OnInit } from '@angular/core';
+import { Comment, Language as CommentLanguage } from '../../../../models/comment';
 import { NotificationService } from '../../../../services/util/notification.service';
-import { MAT_DIALOG_DATA, MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog';
+import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
 import { TranslateService } from '@ngx-translate/core';
-import { FormControl, Validators } from '@angular/forms';
 import { User } from '../../../../models/user';
 import { CommentListComponent } from '../../comment-list/comment-list.component';
 import { EventService } from '../../../../services/util/event.service';
 import { SpacyDialogComponent } from '../spacy-dialog/spacy-dialog.component';
+import { LanguagetoolService, Language } from '../../../../services/http/languagetool.service';
+import { CreateCommentKeywords } from '../../../../utils/create-comment-keywords';
+import { GrammarChecker } from '../../../../utils/grammar-checker';
 
 @Component({
   selector: 'app-submit-comment',
@@ -17,31 +19,27 @@ import { SpacyDialogComponent } from '../spacy-dialog/spacy-dialog.component';
 export class CreateCommentComponent implements OnInit {
 
   comment: Comment;
-
   user: User;
   roomId: string;
   tags: string[];
   selectedTag: string;
-
-  bodyForm = new FormControl('', [Validators.required]);
-
-  @ViewChild('commentBody', { static: true })commentBody: HTMLTextAreaElement;
+  isSendingToSpacy = false;
+  grammarChecker: GrammarChecker;
+  tempEditView: string;
 
   constructor(
-              private notification: NotificationService,
-              public dialogRef: MatDialogRef<CommentListComponent>,
-              private translateService: TranslateService,
-              public dialog: MatDialog,
-              private translationService: TranslateService,
-              public eventService: EventService,
-              @Inject(MAT_DIALOG_DATA) public data: any) {
+    private notification: NotificationService,
+    public dialogRef: MatDialogRef<CommentListComponent>,
+    private translateService: TranslateService,
+    public dialog: MatDialog,
+    public languagetoolService: LanguagetoolService,
+    public eventService: EventService,
+    @Inject(MAT_DIALOG_DATA) public data: any) {
+    this.grammarChecker = new GrammarChecker(this.languagetoolService);
   }
 
   ngOnInit() {
     this.translateService.use(localStorage.getItem('currentLang'));
-    setTimeout(() => {
-      document.getElementById('answer-input').focus();
-    }, 0);
   }
 
   onNoClick(): void {
@@ -51,7 +49,7 @@ export class CreateCommentComponent implements OnInit {
   checkInputData(body: string): boolean {
     body = body.trim();
     if (!body) {
-      this.translationService.get('comment-page.error-comment').subscribe(message => {
+      this.translateService.get('comment-page.error-comment').subscribe(message => {
         this.notification.show(message);
       });
       return false;
@@ -67,39 +65,53 @@ export class CreateCommentComponent implements OnInit {
       comment.creatorId = this.user.id;
       comment.createdFromLecturer = this.user.role === 1;
       comment.tag = this.selectedTag;
+      this.isSendingToSpacy = true;
       this.openSpacyDialog(comment);
     }
   }
 
   openSpacyDialog(comment: Comment): void {
-    const dialogRef = this.dialog.open(SpacyDialogComponent, {
-      data: {
-        comment
-      }
-    });
-
-    dialogRef.afterClosed()
-      .subscribe(result => {
-        if (result) {
-          this.dialogRef.close(result);
+    CreateCommentKeywords.isSpellingAcceptable(this.languagetoolService, comment.body, this.grammarChecker.selectedLang)
+      .subscribe((result) => {
+        if (result.isAcceptable) {
+          const commentLang = this.languagetoolService.mapLanguageToSpacyModel(result.result.language.code as Language);
+          const selectedLangExtend = this.grammarChecker.selectedLang[2] === '-' ?
+            this.grammarChecker.selectedLang.substr(0, 2) : this.grammarChecker.selectedLang;
+          // Store language if it was auto-detected
+          if (this.grammarChecker.selectedLang === 'auto') {
+            comment.language = Comment.mapModelToLanguage(commentLang);
+          } else if (CommentLanguage[selectedLangExtend]) {
+            comment.language = CommentLanguage[selectedLangExtend];
+          }
+          const dialogRef = this.dialog.open(SpacyDialogComponent, {
+            data: {
+              comment,
+              commentLang,
+              commentBodyChecked: result.text
+            }
+          });
+          dialogRef.afterClosed().subscribe(dialogResult => {
+            if (dialogResult) {
+              this.dialogRef.close(dialogResult);
+            }
+          });
+        } else {
+          comment.language = CommentLanguage.auto;
+          this.dialogRef.close(comment);
         }
+        this.isSendingToSpacy = false;
+      }, () => {
+        comment.language = CommentLanguage.auto;
+        this.dialogRef.close(comment);
+        this.isSendingToSpacy = false;
       });
-
   }
 
-
-  /**
-   * Returns a lambda which closes the dialog on call.
-   */
   buildCloseDialogActionCallback(): () => void {
     return () => this.onNoClick();
   }
 
-
-  /**
-   * Returns a lambda which executes the dialog dedicated action on call.
-   */
-  buildCreateCommentActionCallback(text: HTMLInputElement|HTMLTextAreaElement): () => void {
-    return () => this.closeDialog(text.value);
+  buildCreateCommentActionCallback(): (string) => void {
+    return (text: string) => this.closeDialog(text);
   }
 }
diff --git a/src/app/components/shared/_dialogs/delete-account/delete-account.component.html b/src/app/components/shared/_dialogs/delete-account/delete-account.component.html
index 30280d5cd3c8e286f12027bf568c0fc0be50cc1d..b9392eba794324974dde2b00d09673114ae85a68 100644
--- a/src/app/components/shared/_dialogs/delete-account/delete-account.component.html
+++ b/src/app/components/shared/_dialogs/delete-account/delete-account.component.html
@@ -2,7 +2,6 @@
   <div>
     <h2 class="oldtypo-h2"
         tabindex="0">{{ 'header.sure' | translate }}</h2>
-    <mat-divider></mat-divider>
     <p class="oldtypo-p"
        tabindex="0">{{ 'header.really-delete-account' | translate }}</p>
     <ul *ngFor="let room of rooms"
diff --git a/src/app/components/shared/_dialogs/joyride-template/joyride-template.component.html b/src/app/components/shared/_dialogs/joyride-template/joyride-template.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..7e7d9966bcf10f4a9dd31162c7671f531477fcc2
--- /dev/null
+++ b/src/app/components/shared/_dialogs/joyride-template/joyride-template.component.html
@@ -0,0 +1,24 @@
+<ng-template #translateText class="textContainer">
+  <div id="joyrideScrollContainer">
+    <h3 *ngIf="title">{{title}}</h3>
+    {{text}}
+  </div>
+</ng-template>
+<ng-template #nextButton>
+  <button mat-button class="joy-primary" (click)="handle($event, 1)">
+    {{'joyride.next' | translate}}
+  </button>
+</ng-template>
+<ng-template #prevButton>
+  <button mat-button class="joy-secondary" (click)="handle($event, -1)">
+    {{'joyride.prev' | translate}}
+  </button>
+</ng-template>
+<ng-template #doneButton>
+  <button mat-button class="joy-primary" (click)="finish()">
+    {{'joyride.done' | translate}}
+  </button>
+</ng-template>
+<ng-template #counter let-step="step" let-total="total">
+  {{'joyride.step' | translate: {step: step, total: total} }}
+</ng-template>
diff --git a/src/app/components/shared/_dialogs/joyride-template/joyride-template.component.scss b/src/app/components/shared/_dialogs/joyride-template/joyride-template.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..dd7dfff21796f706bae835ed19f6d536734bc7a9
--- /dev/null
+++ b/src/app/components/shared/_dialogs/joyride-template/joyride-template.component.scss
@@ -0,0 +1,92 @@
+::ng-deep {
+  .joyride-step__holder {
+    z-index: 1000 !important;
+
+    &.center {
+      top: 22.5vh !important;
+      left: 0 !important;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      width: 100%;
+      height: 55vh;
+      transform: none !important;
+    }
+  }
+
+  .joyride-step__header {
+    padding: 0 !important;
+  }
+
+  .joyride-step__container {
+    box-shadow: unset !important;
+    border-radius: 10px;
+    box-sizing: border-box !important;
+    padding: 24px !important;
+    display: block !important;
+    background-color: var(--dialog) !important;
+    color: var(--on-dialog) !important;
+    width: 350px;
+    max-width: 75vw !important;
+    max-height: 55vh;
+  }
+
+  .joyride-arrow__top {
+    border-bottom-color: var(--dialog) !important;
+  }
+
+  .joyride-arrow__bottom {
+    border-top-color: var(--dialog) !important;
+  }
+
+  .joyride-arrow__right {
+    border-left-color: var(--dialog) !important;
+  }
+
+  .joyride-arrow__left {
+    border-right-color: var(--dialog) !important;
+  }
+
+  .joyride-backdrop {
+    background-color: var(--primary) !important;
+    opacity: 0.7;
+  }
+
+  .backdrop-container {
+    z-index: 999 !important;
+  }
+
+  .joyride-step__close {
+    width: 1em !important;
+    height: 1em !important;
+    top: 0.75em !important;
+    right: 0.75em !important;
+
+    line {
+      stroke: var(--on-dialog);
+    }
+  }
+
+  .joyride-step__body {
+    hyphens: auto;
+  }
+}
+
+#joyrideScrollContainer {
+  overflow: auto;
+  max-height: 32vh;
+}
+
+.joy-primary {
+  color: var(--on-primary);
+  background-color: var(--primary);
+}
+
+.joy-secondary {
+  color: var(--on-secondary);
+  background-color: var(--secondary);
+}
+
+h3 {
+  margin-top: 0;
+}
diff --git a/src/app/components/shared/_dialogs/joyride-template/joyride-template.component.spec.ts b/src/app/components/shared/_dialogs/joyride-template/joyride-template.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d95f1e5f985c24facef0d5a28ef8d2dc2de0380e
--- /dev/null
+++ b/src/app/components/shared/_dialogs/joyride-template/joyride-template.component.spec.ts
@@ -0,0 +1,26 @@
+/*import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { JoyrideTemplateComponent } from './joyride-template.component';
+
+describe('JoyrideTemplateComponent', () => {
+  let component: JoyrideTemplateComponent;
+  let fixture: ComponentFixture<JoyrideTemplateComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ JoyrideTemplateComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(JoyrideTemplateComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
+ */
diff --git a/src/app/components/shared/_dialogs/joyride-template/joyride-template.component.ts b/src/app/components/shared/_dialogs/joyride-template/joyride-template.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d9657421aac6498d9321ae36e13aed917213ed22
--- /dev/null
+++ b/src/app/components/shared/_dialogs/joyride-template/joyride-template.component.ts
@@ -0,0 +1,54 @@
+import { Component, Input, OnInit, TemplateRef, ViewChild } from '@angular/core';
+import { LanguageService } from '../../../../services/util/language.service';
+import { TranslateService } from '@ngx-translate/core';
+import { EventService } from '../../../../services/util/event.service';
+import { OnboardingService } from '../../../../services/util/onboarding.service';
+import { Router } from '@angular/router';
+
+@Component({
+  selector: 'app-joyride-template',
+  templateUrl: './joyride-template.component.html',
+  styleUrls: ['./joyride-template.component.scss']
+})
+export class JoyrideTemplateComponent implements OnInit {
+
+  @ViewChild('translateText', { static: true }) translateText: TemplateRef<any>;
+  @ViewChild('nextButton', { static: true }) nextButton: TemplateRef<any>;
+  @ViewChild('prevButton', { static: true }) prevButton: TemplateRef<any>;
+  @ViewChild('doneButton', { static: true }) doneButton: TemplateRef<any>;
+  @ViewChild('counter', { static: true }) counter: TemplateRef<any>;
+
+  @Input() name: string;
+
+  title: string;
+  text: string;
+
+  constructor(private langService: LanguageService,
+              private eventService: EventService,
+              private router: Router,
+              private translateService: TranslateService,
+              private onboardingService: OnboardingService) {
+    this.langService.langEmitter.subscribe(lang => {
+      this.translateService.use(lang);
+    });
+  }
+
+  ngOnInit(): void {
+    this.translateService.use(localStorage.getItem('currentLang'));
+    this.translateService.get(`joyride.${this.name}Title`).subscribe(translation => this.title = translation);
+    this.translateService.get(`joyride.${this.name}`).subscribe(translation => this.text = translation);
+  }
+
+  finish() {
+    this.eventService.broadcast('onboarding', 'finished');
+  }
+
+  handle(e: MouseEvent, dir: number) {
+    if (this.onboardingService.doStep(dir)) {
+      e.preventDefault();
+      e.stopPropagation();
+    }
+    return false;
+  }
+
+}
diff --git a/src/app/components/shared/_dialogs/motd-dialog/motd-dialog.component.html b/src/app/components/shared/_dialogs/motd-dialog/motd-dialog.component.html
index 55b77aa3cb8ad45f3c56a1a5d1616014f41f2790..425b92d722bf1d0e908819a27ce532d3b04202f8 100644
--- a/src/app/components/shared/_dialogs/motd-dialog/motd-dialog.component.html
+++ b/src/app/components/shared/_dialogs/motd-dialog/motd-dialog.component.html
@@ -3,7 +3,7 @@
   <h2 tabindex="0" style="padding:0;margin:0 0 20px 0;">
     {{ 'footer.motd-title-main' | translate }}
   </h2>
-  <mat-divider></mat-divider>
+
 </ars-row>
 <mat-dialog-content class="container" ars-flex-box>
   <ars-row ars-flex-box>
@@ -12,7 +12,7 @@
     </ars-col>
     <ars-fill></ars-fill>
     <ars-col class="align-center-y">
-      <button mat-stroked-button (click)="markAllAsRead()">
+      <button mat-flat-button (click)="markAllAsRead()">
         <mat-icon style="margin-right:8px;">checkmark</mat-icon>
         <span>{{ 'footer.motd-mark-all-read' | translate }}</span>
       </button>
diff --git a/src/app/components/shared/_dialogs/motd-dialog/motd-dialog.component.scss b/src/app/components/shared/_dialogs/motd-dialog/motd-dialog.component.scss
index 381cbfbaf598f38c6bcb5581925af11cd4aefb99..1e1e2e547d6798357cf07d224eedbe8c1c507597 100644
--- a/src/app/components/shared/_dialogs/motd-dialog/motd-dialog.component.scss
+++ b/src/app/components/shared/_dialogs/motd-dialog/motd-dialog.component.scss
@@ -34,3 +34,8 @@
     padding: 0 !important;
   }
 }
+
+.mat-flat-button {
+  color: var(--on-dialog);
+  background-color: var(--dialog);
+}
diff --git a/src/app/components/shared/_dialogs/motd-dialog/motd-message/motd-message.component.html b/src/app/components/shared/_dialogs/motd-dialog/motd-message/motd-message.component.html
index ce2cca0095942e574f84e25adeda7733ea24086d..be7e211bf926e7f86d5e095f36c56cf0440da210 100644
--- a/src/app/components/shared/_dialogs/motd-dialog/motd-message/motd-message.component.html
+++ b/src/app/components/shared/_dialogs/motd-dialog/motd-message/motd-message.component.html
@@ -13,6 +13,6 @@
     </ars-col>
   </ars-row>
   <ars-row>
-    <markdown class="images" #markdown [data]="translatedMessage"></markdown>
+    <app-custom-markdown class="images" #markdown [data]="translatedMessage"></app-custom-markdown>
   </ars-row>
 </ars-row>
diff --git a/src/app/components/shared/_dialogs/motd-dialog/motd-message/motd-message.component.scss b/src/app/components/shared/_dialogs/motd-dialog/motd-message/motd-message.component.scss
index 1b45fcc6611a96e9ba63ec3b5925629f4b10edcd..39fe401b06d089a0185ee96df6eeb1028bc10c04 100644
--- a/src/app/components/shared/_dialogs/motd-dialog/motd-message/motd-message.component.scss
+++ b/src/app/components/shared/_dialogs/motd-dialog/motd-message/motd-message.component.scss
@@ -6,11 +6,10 @@
   }
 
   .container {
-    border-radius: 4px;
+    border-radius: 20px;
     background-color: var(--surface);
-    box-shadow: inset 0px 0px 0px 1px rgba(0, 0, 0, 0.2);
     box-sizing: border-box;
-    padding: 5px 10px;
+    padding: 5px 20px;
   }
 
   .timestamp {
diff --git a/src/app/components/shared/_dialogs/motd-temp-dialog/motd-temp-dialog.component.html b/src/app/components/shared/_dialogs/motd-temp-dialog/motd-temp-dialog.component.html
index d8186fd8951735d03dff44ba551c933aca2c9a98..47c5bdba7353245f940677ec2d91f282f881e789 100644
--- a/src/app/components/shared/_dialogs/motd-temp-dialog/motd-temp-dialog.component.html
+++ b/src/app/components/shared/_dialogs/motd-temp-dialog/motd-temp-dialog.component.html
@@ -3,11 +3,11 @@
   <h2 tabindex="0" style="padding:0;margin:0 0 20px 0;">
     Message of the Day
   </h2>
-  <mat-divider></mat-divider>
+
 </ars-row>
 <mat-dialog-content class="container" ars-flex-box>
   <ars-row ars-flex-box>
-    <markdown class="images" [data]="content"></markdown>
+    <app-custom-markdown class="images" [data]="content"></app-custom-markdown>
   </ars-row>
   <ars-row [height]="32"></ars-row>
   <ars-fill></ars-fill>
diff --git a/src/app/components/shared/_dialogs/present-comment/present-comment.component.html b/src/app/components/shared/_dialogs/present-comment/present-comment.component.html
index fceed936fc7842843239ba6c76b467093db82514..cf4217111f40b7f7b6b7345310dccb992d4be044 100644
--- a/src/app/components/shared/_dialogs/present-comment/present-comment.component.html
+++ b/src/app/components/shared/_dialogs/present-comment/present-comment.component.html
@@ -12,7 +12,7 @@
   <mat-icon >close</mat-icon>
 </button>
 <div id="comment">
-  <markdown [data]="body"></markdown>
+  <app-custom-markdown [data]="body"></app-custom-markdown>
 </div>
 
 <div class="visually-hidden">
diff --git a/src/app/components/shared/_dialogs/qr-code-dialog/qr-code-dialog.component.html b/src/app/components/shared/_dialogs/qr-code-dialog/qr-code-dialog.component.html
index 1c20c59c8a7f1d408b94b65306833a1ee0190f4c..74424cc34089558ff13d0e247120923607d51152 100644
--- a/src/app/components/shared/_dialogs/qr-code-dialog/qr-code-dialog.component.html
+++ b/src/app/components/shared/_dialogs/qr-code-dialog/qr-code-dialog.component.html
@@ -4,7 +4,7 @@
       <mat-icon>close</mat-icon>
     </button>
     <div>
-      <h2>frag.jetzt</h2>
+      <h2>URL: frag.jetzt</h2>
       <h2>{{'qr-dialog.session' | translate}}: {{key}}</h2>
     </div>
     <qrcode [qrdata]="data" [width]="qrWidth" [errorCorrectionLevel]="'M'"></qrcode>
diff --git a/src/app/components/shared/_dialogs/remove-from-history/remove-from-history.component.html b/src/app/components/shared/_dialogs/remove-from-history/remove-from-history.component.html
index 1a40aa482ea52815ef54cce1a72afa506e0ba9f8..dea1a2f44dd7b9f8060f5f3905d25053880c1b77 100644
--- a/src/app/components/shared/_dialogs/remove-from-history/remove-from-history.component.html
+++ b/src/app/components/shared/_dialogs/remove-from-history/remove-from-history.component.html
@@ -1,6 +1,5 @@
 <div mat-dialog-content>
   <h2 class="oldtypo-h2" tabindex="0">{{ 'header.sure' | translate }}</h2>
-  <mat-divider></mat-divider>
   <p class="oldtypo-p" tabindex="0">{{ (role < 3 ? 'room-list.really-remove' : 'room-list.really-delete') | translate }}
     <strong>{{roomName}}</strong>{{ (role < 3 ? 'room-list.really-remove-2' : 'room-list.really-delete-2') | translate }}</p>
   <app-dialog-action-buttons
diff --git a/src/app/components/shared/_dialogs/room-create/room-create.component.html b/src/app/components/shared/_dialogs/room-create/room-create.component.html
index 7bad2dbc4f8b4ca1df987045377ec561484e7af3..6ebf25d9056eec6a7ae48b5e24d75dc17583919d 100644
--- a/src/app/components/shared/_dialogs/room-create/room-create.component.html
+++ b/src/app/components/shared/_dialogs/room-create/room-create.component.html
@@ -23,11 +23,12 @@
                 class="error"
                 *ngIf="emptyInputs"><strong>{{ 'home-page.no-empty-name' | translate }}</strong></mat-hint>
     </mat-form-field>
-    <mat-checkbox (change)="hasCustomShortId=$event.checked">{{ 'home-page.custom-shortid' | translate }}</mat-checkbox>
+    <mat-slide-toggle (change)="hasCustomShortId=$event.checked">{{ 'home-page.custom-shortid' | translate }}</mat-slide-toggle>
     <mat-form-field *ngIf="hasCustomShortId">
       <input (focus)="eventService.makeFocusOnInputTrue()"
              (blur)="eventService.makeFocusOnInputFalse()"
              (keyup)="resetInvalidCharacters()"
+             autofocus
              matInput
              #customShortId
              class="input-block"
diff --git a/src/app/components/shared/_dialogs/room-create/room-create.component.scss b/src/app/components/shared/_dialogs/room-create/room-create.component.scss
index 1aa550dc36fe0212ab94e24622639d1e3b6a1291..9380e9ba82864cb420c7583468277e316e69b2e5 100644
--- a/src/app/components/shared/_dialogs/room-create/room-create.component.scss
+++ b/src/app/components/shared/_dialogs/room-create/room-create.component.scss
@@ -37,3 +37,8 @@ mat-form-field {
   overflow: hidden;
   left: -10000px;
 }
+
+::ng-deep .mat-form-field .mat-form-field-infix {
+  max-width: 500px;
+}
+
diff --git a/src/app/components/shared/_dialogs/room-create/room-create.component.ts b/src/app/components/shared/_dialogs/room-create/room-create.component.ts
index 5c83def0486ec96696029d41e50134b895e0378e..f0f7a36d8a0d221f8464e6df56b9b59bbbaefc1f 100644
--- a/src/app/components/shared/_dialogs/room-create/room-create.component.ts
+++ b/src/app/components/shared/_dialogs/room-create/room-create.component.ts
@@ -1,13 +1,12 @@
 import { Component, Inject, OnInit } from '@angular/core';
 import { RoomService } from '../../../../services/http/room.service';
-import { Room } from '../../../../models/room';
+import { ProfanityFilter, Room } from '../../../../models/room';
 import { UserRole } from '../../../../models/user-roles.enum';
 import { Router } from '@angular/router';
 import { NotificationService } from '../../../../services/util/notification.service';
 import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
 import { AuthenticationService } from '../../../../services/http/authentication.service';
 import { TranslateService } from '@ngx-translate/core';
-import { TSMap } from 'typescript-map';
 import { EventService } from '../../../../services/util/event.service';
 import { User } from '../../../../models/user';
 
@@ -74,6 +73,9 @@ export class RoomCreateComponent implements OnInit {
     newRoom.name = longRoomName;
     newRoom.abbreviation = '00000000';
     newRoom.description = '';
+    newRoom.blacklist = '[]';
+    newRoom.questionsBlocked = false;
+    newRoom.profanityFilter = ProfanityFilter.none;
     if (this.hasCustomShortId && this.customShortIdName && this.customShortIdName.length > 0) {
       if (!new RegExp('[1-9a-z,A-Z,\s,\-,\.,\_,\~]+').test(this.customShortIdName)
         || this.customShortIdName.startsWith(' ') || this.customShortIdName.endsWith(' ')) {
@@ -97,8 +99,8 @@ export class RoomCreateComponent implements OnInit {
       this.room = room;
       let msg1: string;
       let msg2: string;
-      this.translateService.get('home-page.created-1').subscribe(msg => { msg1 = msg; });
-      this.translateService.get('home-page.created-2').subscribe(msg => { msg2 = msg; });
+      this.translateService.get('home-page.created-1').subscribe(msg => msg1 = msg);
+      this.translateService.get('home-page.created-2').subscribe(msg => msg2 = msg);
       this.notification.show(msg1 + longRoomName + msg2);
       this.authenticationService.setAccess(encoded, UserRole.CREATOR);
       this.authenticationService.assignRole(UserRole.CREATOR);
diff --git a/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.html b/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.html
index b23229d31d9fa7384a8f2e934455a09e9d2c43cb..290fdaffbb54c2ace7939b1195e61c785becf998 100644
--- a/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.html
+++ b/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.html
@@ -1,69 +1,83 @@
 <ars-row>
   <div class="anchor-wrp">
-    <ars-row class="content-container">
-      <ars-row class="dialog-header">
-      <div class="lang-selection">
-        <mat-icon>more_vert</mat-icon>
-        <mat-select class="select-list" [(ngModel)]="selectedLang" (selectionChange)="evalInput($event.value)">
-          <mat-option *ngFor="let lang of commentLang" [value]="lang.lang">
-            <span *ngIf="lang.lang == 'de'">{{ 'spacy-dialog.german' | translate}}</span>
-            <span *ngIf="lang.lang == 'en'">{{ 'spacy-dialog.english' | translate}}</span>
-            <span *ngIf="lang.lang == 'fr'">{{ 'spacy-dialog.french' | translate}}</span>
-          </mat-option>
-        </mat-select>
-      </div>
-      <span *ngIf="keywords.length > 0">
-        <ars-row class="select-all-section">
-          <mat-icon>playlist_add_check</mat-icon>
-          <mat-label class="select-all-label" for="checkAll">{{ 'spacy-dialog.select-all' | translate }}</mat-label>
-          <mat-checkbox class="select-all-checkbox" id="checkAll" (change)="selectAll($event.checked)"></mat-checkbox>
-        </ars-row>
-      </span>
-      <span *ngIf="keywords.length > 0"></span>
-      </ars-row>
-      <ars-row ars-flex-box class="list-container">
-        <mat-list dense class="keywords-list">
-          <mat-list-item  *ngFor="let keyword of keywords; let odd = odd; let even = even"
-                          [class.keywords-alternate]="odd"
-                          [class.keywords-even]="even"
-                          [ngClass]="{'keyword-selected': keyword.selected}">
-            <span class="keyword-span" *ngIf="!keyword.editing">{{keyword.word}}</span>
-            <input  class="keyword-span, isEditing" *ngIf="keyword.editing" [(ngModel)]="keyword.word"/>
-            <div class="keywords-actions">
-              <mat-checkbox [checked]="keyword.completed"
-                            (change)="keyword.selected = $event.checked">
-              </mat-checkbox>
-              <button *ngIf="!keyword.editing"
-                      (click)="onEdit(keyword)" mat-icon-button
-                      [ngClass]="{'keywords-actions-selected': keyword.selected}">
-                <mat-icon>edit</mat-icon>
-              </button>
-              <button *ngIf="keyword.editing"
-                      (click)="onEndEditing(keyword)" mat-icon-button
-                      class = "edit-accept">
-                <mat-icon>check</mat-icon>
-              </button>
-            </div>
-          </mat-list-item>
-        </mat-list>
+    <span *ngIf="keywords.length > 0">
+        <span>{{ 'spacy-dialog.select-keywords' | translate }}</span>
+      <ars-row class="select-all-section">
+        <mat-checkbox class="select-all-checkbox"
+                      id="checkAll"
+                      (change)="selectAll(checkall.checked)"
+                      #checkall
+                      [checked]="allKeywordsSelected()"
+                      matTooltip="{{ 'spacy-dialog.select-all-hint' | translate }}"
+                      matTooltipShowDelay="750">
+        </mat-checkbox>
+        <mat-label class="select-all-label"
+                   for="checkAll"
+                   (click)="checkall.checked = !checkall.checked;
+                   selectAll(checkall.checked)"
+                   matTooltip="{{ 'spacy-dialog.select-all-hint' | translate }}"
+                   matTooltipShowDelay="750">
+          <mat-icon class="select-all-icon">playlist_add_check</mat-icon>
+          {{ 'spacy-dialog.select-all' | translate }}
+        </mat-label>
       </ars-row>
-      <span *ngIf="keywords.length<=0">
-        <p>{{ 'spacy-dialog.empty-nouns' | translate}}</p>
+    </span>
+    <ars-row class="list-container">
+      <div fxLayout="row" fxLayoutAlign="center center" fxFill>
+        <app-mat-spinner-overlay *ngIf="isLoading"></app-mat-spinner-overlay>
+      </div>
+      <mat-list dense class="keywords-list">
+        <mat-list-item  *ngFor="let keyword of keywords; let odd = odd; let even = even; let i = index"
+                        [class.keywords-alternate]="odd"
+                        [class.keywords-even]="even"
+                        [ngClass]="{'keyword-selected': keyword.selected, 'first-keyword': i === 0}">
+          <span class="keyword-span" *ngIf="!keyword.editing">{{keyword.word}}</span>
+          <input  class="keyword-span, isEditing" *ngIf="keyword.editing" [(ngModel)]="keyword.word"/>
+          <div class="keywords-actions">
+            <mat-checkbox [checked]="keyword.completed"
+                          (change)="keyword.selected = $event.checked"
+                          [(ngModel)]="keyword.completed"
+                          matTooltip="{{ 'spacy-dialog.select-keyword-hint' | translate }}"
+                          matTooltipShowDelay="750">
+            </mat-checkbox>
+            <button *ngIf="!keyword.editing"
+                    (click)="onEdit(keyword); onEditChange(1)" mat-icon-button
+                    [ngClass]="{'keywords-actions-selected': keyword.selected}"
+                    matTooltip="{{ 'spacy-dialog.edit-keyword-hint' | translate }}"
+                    matTooltipShowDelay="750">
+              <mat-icon>edit</mat-icon>
+            </button>
+            <button *ngIf="keyword.editing"
+                    (click)="onEndEditing(keyword); onEditChange(-1)" mat-icon-button
+                    class = "edit-accept"
+                    matTooltip="{{ 'spacy-dialog.editing-done-hint' | translate }}"
+                    matTooltipShowDelay="750">
+              <mat-icon>check</mat-icon>
+            </button>
+          </div>
+        </mat-list-item>
+      </mat-list>
+    </ars-row>
+    <ars-row>
+      <span *ngIf="!isLoading && (!langSupported || !hasKeywordsFromSpacy)">
+        <p class="manual-input-title">{{ 'spacy-dialog.add-manually' | translate }}</p>
+        <textarea class="manual-input" [(ngModel)]="manualKeywords" (input)="manualKeywordsToKeywords()"></textarea>
       </span>
     </ars-row>
   </div>
 </ars-row>
+
 <ars-row ars-flex-box>
-  <ars-fill>
-  </ars-fill>
+  <ars-fill></ars-fill>
   <ars-col>
     <app-dialog-action-buttons
+      #appDialogActionButtons
       buttonsLabelSection="comment-page"
       confirmButtonLabel="send"
       [showDivider]="false"
       [spacing]="false"
       [cancelButtonClickAction]="buildCloseDialogActionCallback()"
-      [confirmButtonClickAction]="buildCreateCommentActionCallback()">
+      [confirmButtonClickAction]="!isLoading ? buildCreateCommentActionCallback() : undefined">
     </app-dialog-action-buttons>
   </ars-col>
 </ars-row>
diff --git a/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.scss b/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.scss
index 34602fb836e85b5d22ef37bea3813562827a6331..29d07cae3203aad421599e3cf54125088ef00b0e 100644
--- a/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.scss
+++ b/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.scss
@@ -1,71 +1,140 @@
 .mat-list-base[dense] .mat-list-item, .list-item {
-  font-size: 14px;
-  height: 35px !important;
+  font-size: 13px;
+  height: 40px !important;
 }
+
 .keywords-list {
-  height: 343px;
+  max-height: 340px;
   flex-grow: 1;
   flex-shrink: 1;
   overflow: auto;
   padding-top: 0 !important;
 }
-.keywords-even {
-background-color: var(--alt-dialog);
+
+.first-keyword {
+  border-top: 1px solid var(--surface);
+  box-sizing: border-box;
+}
+
+.keywords-even, .keywords-alternate {
+  background-color: var(--dialog);
+  border-bottom: 1px solid var(--surface);
+  border-top-left-radius: 5px;
+  border-bottom-left-radius: 5px;
+  border-left: 3px solid var(--primary);
+  border-right: 1px solid var(--primary);
+  box-sizing: border-box;
+}
+
+.keyword-selected {
+  background: var(--surface);
+  box-shadow: inset -2px 0 0 1px var(--primary);
 }
+
 .keyword-span {
   color: var(--on-surface) !important;
   opacity: 1 !important;
 }
-.keyword-selected {
-  background: var(--primary-variant);
-  border-bottom: 1px solid var(--alt-surface);
-}
+
 ::ng-deep .mat-checkbox-checked .mat-checkbox-background {
-  background: var(--cancel) !important;
+  background: var(--primary) !important;
 }
+
 .mat-checkbox-frame {
   color: var(--secondary);
 }
-:focus{
+
+:focus {
   outline: none;
   outline-offset: 8px;
 }
+
 .lang-selection {
-  display: inline-flex;
   vertical-align: middle;
-  width:100%;
+  margin-right: 0;
+}
+
+.select-all-label {
+  padding-left: 15px;
+  cursor: pointer;
+}
+
+.manual-input {
+  background-color: transparent;
+  border: 1px solid var(--on-dialog);
+  padding: 5px;
+  border-radius: 5px;
+  color: var(--on-dialog);
+  width: 100%
+}
+
+.manual-input-title {
+  margin-top: 15px;
+}
+
+.select-list {
+  width: calc(100% - 24px);
 }
+
 .keywords-actions {
+  white-space: nowrap;
+  padding-left: 5px;
   margin-left: auto;
   color: var(--on-surface);
 }
+
+.lang-btn {
+  width: 100%;
+}
+
 .keywords-actions-selected {
   color: var(--on-surface);
 }
-.isEditing{
+
+.isEditing {
   background: var(--primary);
   height: 22px;
   border-radius: 5px;
   color: var(--on-primary);
-  border: 1px solid var( --on-primary);
+  border: 1px solid var(--on-primary);
 }
+
 .edit-accept {
   color: var(--on-surface);
 }
+
 .select-all-section {
-  display: inline-flex;
   vertical-align: middle;
   padding-top: 20px;
-  padding-bottom: 30px;
-  padding-left: 4px;
+  padding-bottom: 20px;
 }
+
 .select-all-label {
-  padding-left: 10px;
+  padding-left: 15px;
+}
+
+.select-all-icon {
+  float: left;
+  padding-left: 16px;
 }
+
 .select-all-checkbox {
-  margin-left: auto;
-  padding-right: 5px;
+  float: right;
+  padding-right: 3px;
 }
+
 .mat-select {
   padding-left: 14px;
 }
+
+::ng-deep .mat-select-panel {
+  background: var(--dialog);
+}
+
+.mat-option.mat-active {
+  color: var(--primary);
+}
+
+.mat-option {
+  color: var(--on-surface);
+}
diff --git a/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.ts b/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.ts
index 5fccb64f59bfde9c9300666b5208a32e9ab2e071..dd6c33c9308826aa764fcdae8a24ba0b1ebf5dd1 100644
--- a/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.ts
+++ b/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.ts
@@ -1,16 +1,21 @@
-import { AfterContentInit, Component, Inject, OnInit } from '@angular/core';
+import { AfterContentInit, Component, Inject, OnInit, ViewChild } from '@angular/core';
 import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+
 import { CreateCommentComponent } from '../create-comment/create-comment.component';
-import { SpacyService } from '../../../../services/http/spacy.service';
-import { LanguageService } from '../../../../services/util/language.service';
+import { SpacyService, SpacyKeyword } from '../../../../services/http/spacy.service';
+import { LanguagetoolService } from '../../../../services/http/languagetool.service';
 import { Comment } from '../../../../models/comment';
+import { DialogActionButtonsComponent } from '../../dialog/dialog-action-buttons/dialog-action-buttons.component';
+import { Model } from '../../../../services/http/spacy.interface';
 
 export interface Keyword {
   word: string;
+  dep: string[];
   completed: boolean;
   editing: boolean;
   selected: boolean;
 }
+
 @Component({
   selector: 'app-spacy-dialog',
   templateUrl: './spacy-dialog.component.html',
@@ -18,17 +23,21 @@ export interface Keyword {
 })
 export class SpacyDialogComponent implements OnInit, AfterContentInit {
 
-  commentLang = [
-    { lang: 'de' },
-    { lang: 'en' },
-    { lang: 'fr' },
-  ];
-  selectedLang = localStorage.getItem('currentLang');
+  @ViewChild('appDialogActionButtons') appDialogActionButtons: DialogActionButtonsComponent;
+
   comment: Comment;
+  commentLang: Model;
+  commentBodyChecked: string;
   keywords: Keyword[] = [];
+  keywordsOriginal: SpacyKeyword[] = [];
+  hasKeywordsFromSpacy = false;
+  isLoading = false;
+  langSupported: boolean;
+  manualKeywords = '';
+  _concurrentEdits = 0;
 
   constructor(
-    protected langService: LanguageService,
+    protected langService: LanguagetoolService,
     private spacyService: SpacyService,
     public dialogRef: MatDialogRef<CreateCommentComponent>,
     @Inject(MAT_DIALOG_DATA) public data) {
@@ -36,53 +45,68 @@ export class SpacyDialogComponent implements OnInit, AfterContentInit {
 
   ngOnInit(): void {
     this.comment = this.data.comment;
+    this.commentLang = this.data.commentLang;
+    this.commentBodyChecked = this.data.commentBodyChecked;
+    this.langSupported = this.langService.isSupportedLanguage(this.data.commentLang);
   }
 
   ngAfterContentInit(): void {
-    this.evalInput(this.selectedLang);
+    if (this.langSupported) {
+      this.evalInput(this.commentLang);
+    }
   }
 
   /**
    * Returns a lambda which closes the dialog on call.
    */
-   buildCloseDialogActionCallback(): () => void {
+  buildCloseDialogActionCallback(): () => void {
     return () => this.dialogRef.close();
   }
 
   buildCreateCommentActionCallback() {
     return () => {
-      this.comment.keywords = this.keywords.filter(kw => kw.selected).map(kw => kw.word);
+      this.comment.keywordsFromQuestioner = this.keywords.filter(kw => kw.selected && kw.word.length).map(kw => ({
+        lemma: kw.word,
+        dep: kw.dep
+      } as SpacyKeyword));
+      this.comment.keywordsFromSpacy = this.keywordsOriginal;
       this.dialogRef.close(this.comment);
     };
   }
 
-  evalInput(model: string) {
-    const words: Keyword[] = [];
+  evalInput(model: Model) {
+    this.isLoading = true;
 
     // N at first pos = all Nouns(NN de/en) including singular(NN, NNP en), plural (NNPS, NNS en), proper Noun(NNE, NE de)
-    this.spacyService.analyse(this.comment.body, model)
-      .subscribe(res => {
-        for(const word of res.words) {
-          if (word.tag.charAt(0) === 'N') {
-            words.push({
-              word: word.text,
-              completed: false,
-              editing: false,
-              selected: false
-            });
-          }
-        }
-        this.keywords = words;
+    this.spacyService.getKeywords(this.commentBodyChecked, model)
+      .subscribe(words => {
+        this.keywordsOriginal = words;
+        this.keywords = words.map(keyword => ({
+          word: keyword.lemma,
+          dep: [...keyword.dep],
+          completed: false,
+          editing: false,
+          selected: false
+        } as Keyword));
+        this.keywords.sort((a, b) => a.word.localeCompare(b.word));
+        this.hasKeywordsFromSpacy = this.keywords.length > 0;
+      }, () => {
+        this.keywords = [];
+        this.keywordsOriginal = [];
+        this.hasKeywordsFromSpacy = false;
+        this.isLoading = false;
       }, () => {
-        this.keywords = []
+        this.isLoading = false;
       });
   }
 
-  onEdit(keyword){
+  onEdit(keyword) {
     keyword.editing = true;
+    keyword.completed = false;
+    keyword.selected = false;
   }
 
-  onEndEditing(keyword){
+  onEndEditing(keyword) {
     keyword.editing = false;
     keyword.completed = true;
     keyword.selected = true;
@@ -101,4 +125,35 @@ export class SpacyDialogComponent implements OnInit, AfterContentInit {
       });
     }
   }
+
+  allKeywordsSelected(): boolean {
+    for (const kw of this.keywords) {
+      if (!kw.selected) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  manualKeywordsToKeywords() {
+    const tempKeywords = this.manualKeywords.replace(/\s/g, '');
+    if (tempKeywords.length) {
+      this.keywords = tempKeywords.split(',').map((keyword) => (
+        {
+          word: keyword,
+          dep: ['ROOT'],
+          completed: true,
+          editing: false,
+          selected: true
+        }
+      ));
+    } else {
+      this.keywords = [];
+    }
+  }
+
+  onEditChange(change: number) {
+    this._concurrentEdits += change;
+    this.appDialogActionButtons.confirmButtonDisabled = (this._concurrentEdits > 0);
+  }
 }
diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData.ts b/src/app/components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1337a08d1e37606c118c08f6ee6244e999e15e97
--- /dev/null
+++ b/src/app/components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData.ts
@@ -0,0 +1,72 @@
+import { ProfanityFilter } from '../../../../models/room';
+
+export interface TopicCloudAdminData {
+  blacklist: string[];
+  wantedLabels: {
+    de: string[];
+    en: string[];
+  };
+  considerVotes: boolean;
+  profanityFilter: ProfanityFilter;
+  blacklistIsActive: boolean;
+  keywordORfulltext: KeywordOrFulltext;
+  minQuestions: number;
+  minQuestioners: number;
+  minUpvotes: number;
+  startDate: string;
+  endDate: string;
+}
+
+export enum KeywordOrFulltext {
+  keyword,
+  fulltext,
+  both
+}
+
+export interface Label {
+  readonly tag: string;
+  readonly label: string;
+  readonly enabledByDefault: boolean;
+}
+
+export class Labels {
+  readonly de: Label[];
+  readonly en: Label[];
+
+  constructor(_de: Label[], _en: Label[]) {
+    this.de = _de;
+    this.en = _en;
+  }
+}
+
+const deLabels: Label[] = [
+  {tag: 'sb', label: 'Subjekt', enabledByDefault: true},
+  {tag: 'op', label: 'Präpositionalobjekt', enabledByDefault: true},
+  {tag: 'og', label: 'Genitivobjekt', enabledByDefault: true},
+  {tag: 'da', label: 'Dativobjekt', enabledByDefault: true},
+  {tag: 'oa', label: 'Akkusativobjekt', enabledByDefault: true},
+  {tag: 'pd', label: 'Prädikat', enabledByDefault: false},
+  {tag: 'ag', label: 'Genitivattribut', enabledByDefault: false},
+  {tag: 'app', label: 'Apposition', enabledByDefault: false},
+  {tag: 'nk', label: 'Nomen Kernelement', enabledByDefault: false},
+  {tag: 'mo', label: 'Modifikator', enabledByDefault: false},
+  {tag: 'cj', label: 'Konjunktor', enabledByDefault: false},
+  {tag: 'ROOT', label: 'Satzkernelement', enabledByDefault: false},
+  {tag: 'par', label: 'Klammerzusatz', enabledByDefault: false}
+];
+
+const enLabels: Label[] = [
+  {tag: 'nsubj', label: 'Nominal subject', enabledByDefault: true},
+  {tag: 'pobj', label: 'Object of preposition', enabledByDefault: true},
+  {tag: 'dobj', label: 'Direct object', enabledByDefault: true},
+  {tag: 'compound', label: 'Compound', enabledByDefault: true},
+  {tag: 'nsubjpass', label: 'Passive nominal subject', enabledByDefault: true},
+  {tag: 'nummod', label: 'Numeric modifier', enabledByDefault: false},
+  {tag: 'amod', label: 'Adjectival modifier', enabledByDefault: false},
+  {tag: 'npadvmod', label: 'Noun phrase as adverbial modifier', enabledByDefault: false},
+  {tag: 'conj', label: 'Conjunct', enabledByDefault: false},
+  {tag: 'ROOT', label: 'Sentence kernel element', enabledByDefault: false},
+  {tag: 'intj', label: 'Interjection', enabledByDefault: false}
+];
+
+export const spacyLabels = new Labels(deLabels, enLabels);
diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html
index 9f6b4c7cdf25f7555f1556ae3c0cd62fc64004b9..222f911ca6e74c857377ccd66b5be3d498e777a8 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html
+++ b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.html
@@ -1,101 +1,520 @@
 <mat-dialog-content>
-  <mat-card>
-    <mat-slide-toggle [(ngModel)]="considerVotes">{{'topic-cloud-dialog.consider-votes' | translate}}</mat-slide-toggle>
-    <mat-slide-toggle [(ngModel)]="tagsLowerCase">{{'topic-cloud-dialog.tags-lowercase' | translate}}</mat-slide-toggle>
-  </mat-card>
-
-  <div fxLayout="row" style="margin-top: 10px;">
-    <mat-label fxLayoutAlign="center center">
-      <mat-icon>search</mat-icon>
-    </mat-label>
-    <div style="margin-left: 10px;">
-      <mat-form-field class="example-form-field">
-        <input #searchBox id="searchBox" (input)="searchKeyword()"
-               [(ngModel)]="searchedKeyword" matInput type="text"
-               placeholder="{{'topic-cloud-dialog.keyword-search' | translate}}">
-        <button *ngIf="searchedKeyword"
-                (click)="searchedKeyword = ''; searchMode = false;"
-                mat-button matSuffix mat-icon-button aria-label="topic-cloud-dialog.keyword-search">
-          <mat-icon>close</mat-icon>
-        </button>
-      </mat-form-field>
-    </div>
-    <div fxLayoutAlign="end" style="margin-left: 52%;">
-      <button  mat-button [matMenuTriggerFor]="sortMenu" mat-ripple>
-        <mat-icon>sort</mat-icon>
-      </button>
-    </div>
+  <div fxLayout="row" fxLayoutAlign="center center" fxFill>
+    <app-mat-spinner-overlay *ngIf="isLoading"></app-mat-spinner-overlay>
   </div>
-
-  <mat-menu #sortMenu>
-    <button mat-menu-item (click)="sortQuestions('alphabetic')">
-      <mat-icon>sort_by_alpha</mat-icon>
-      {{'topic-cloud-dialog.sort-alpha' | translate}} </button>
-    <button mat-menu-item (click)="sortQuestions('questionsCount')">
-      <mat-icon>swap_vert</mat-icon>
-      {{'topic-cloud-dialog.sort-count' | translate}} </button>
-    <button mat-menu-item (click)="sortQuestions('voteCount')">
-      <mat-icon>swap_vert</mat-icon>
-      {{'topic-cloud-dialog.sort-vote' | translate}} </button>
-  </mat-menu>
-
-  <mat-accordion>
-    <mat-expansion-panel hideToggle *ngIf="searchMode && filteredKeywords.length === 0">
-        <mat-expansion-panel-header>
-            <mat-panel-title fxLayoutAlign="center">
-              {{'topic-cloud-dialog.no-keywords-note' | translate}}
-            </mat-panel-title>
+  <div *ngIf="!isLoading">
+    <mat-accordion hideToggle>
+      <mat-expansion-panel class="color-surface">
+        <mat-expansion-panel-header class="color-surface">
+          <mat-icon class="color-on-surface">settings</mat-icon>
+          <mat-panel-title>
+            {{'topic-cloud-dialog.settings' | translate}}
+          </mat-panel-title>
         </mat-expansion-panel-header>
+        <mat-card style="background: none; margin-bottom: 10px;">
+          <mat-label class="color-on-surface">
+            {{"topic-cloud-dialog.select-choice" | translate}}
+          </mat-label>
+          <mat-radio-group class="radio-button-group" (change)=(refreshKeywords()) [(ngModel)]="keywordORfulltext">
+            <mat-radio-button checked="true" [value]="keywordOrFulltextENUM[0]" class="radio-button-item">
+              {{"topic-cloud-dialog.keyword" | translate}}
+            </mat-radio-button>
+            <mat-radio-button [value]="keywordOrFulltextENUM[1]" class="radio-button-item">
+              {{"topic-cloud-dialog.full-text" | translate}}
+            </mat-radio-button>
+            <mat-radio-button [value]="keywordOrFulltextENUM[2]" class="color-on-surface">
+              {{"topic-cloud-dialog.both" | translate}}
+            </mat-radio-button>
+          </mat-radio-group>
+        </mat-card>
+
+        <mat-card style="background: none; margin-bottom: 10px;">
+          <mat-slide-toggle [(ngModel)]="considerVotes">
+            {{'topic-cloud-dialog.consider-votes' | translate}}
+          </mat-slide-toggle>
+        </mat-card>
+        <div *ngIf="isCreatorOrMod">
+          <mat-card style="background: none; margin-bottom: 10px;">
+            <mat-slide-toggle (change)="showMessage('words-will-be-overwritten', $event.checked)"
+                              [(ngModel)]="profanityFilter">
+              {{'topic-cloud-dialog.profanity' | translate}}
+            </mat-slide-toggle>
+            <mat-slide-toggle *ngIf="profanityFilter"
+                              (change)="showMessage('only-specific-language-will-be-filtered', $event.checked)"
+                              [(ngModel)]="censorLanguageSpecificCheck">
+              {{'topic-cloud-dialog.language-specific-filter' | translate}}
+            </mat-slide-toggle>
+            <mat-slide-toggle *ngIf="profanityFilter"
+                              (change)="showMessage('partial-words-will-be-filtered', $event.checked)"
+                              [(ngModel)]="censorPartialWordsCheck">
+              {{'topic-cloud-dialog.partial-words-filter' | translate}}
+            </mat-slide-toggle>
+
+            <mat-accordion>
+              <mat-expansion-panel class="color-background" (opened)="focusInput('test-profanity-input')">
+                <mat-expansion-panel-header class="color-background">
+                  <mat-panel-title>
+                    {{'topic-cloud-dialog.test-profanity' | translate}}
+                  </mat-panel-title>
+                </mat-expansion-panel-header>
+                <p>
+                  <mat-form-field *ngIf="censorLanguageSpecificCheck">
+                    <mat-label>{{'topic-cloud-dialog.language' | translate}}</mat-label>
+                    <mat-select [(value)]="testProfanityLanguage">
+                      <mat-option value="en">English</mat-option>
+                      <mat-option value="de">German</mat-option>
+                      <mat-option value="fr">French</mat-option>
+                      <mat-option value="ar">Arabic</mat-option>
+                      <mat-option value="ru">Russian</mat-option>
+                      <mat-option value="es">Spanish</mat-option>
+                      <mat-option value="it">Italian</mat-option>
+                      <mat-option value="nl">Netherlandish</mat-option>
+                      <mat-option value="tr">Turkish</mat-option>
+                      <mat-option value="pt">Portuguese</mat-option>
+                    </mat-select>
+                  </mat-form-field>
+                </p>
+                <p>
+                  <mat-form-field>
+                    <mat-label>{{'topic-cloud-dialog.word' | translate}}</mat-label>
+                    <input id="test-profanity-input" matInput [(ngModel)]="testProfanityWord">
+                  </mat-form-field>
+                </p>
+                <p>{{'topic-cloud-dialog.preview' | translate}}:</p>
+                <p>{{getFilteredProfanity()}}</p>
+
+
+                <mat-accordion>
+                  <mat-expansion-panel class="color-surface">
+                    <mat-expansion-panel-header class="color-surface">
+                      <mat-panel-title>
+                        {{"topic-cloud-dialog.words-in-profanity" | translate}}
+                      </mat-panel-title>
+                    </mat-expansion-panel-header>
+                    <a
+                      href="https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/en"
+                      target="_blank">English</a>
+                    <br>
+                    <a
+                      href="https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/de"
+                      target="_blank">German</a>
+                    <br>
+                    <a
+                      href="https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/fr"
+                      target="_blank">French</a>
+                    <br>
+                    <a
+                      href="https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/ar"
+                      target="_blank">Arabic</a>
+                    <br>
+                    <a
+                      href="https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/ru"
+                      target="_blank">Russian</a>
+                    <br>
+                    <a
+                      href="https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/es"
+                      target="_blank">Spanish</a>
+                    <br>
+                    <a
+                      href="https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/it"
+                      target="_blank">Italian</a>
+                    <br>
+                    <a
+                      href="https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/nl"
+                      target="_blank">Netherlandish</a>
+                    <br>
+                    <a
+                      href="https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/tr"
+                      target="_blank">Turkish</a>
+                    <br>
+                    <a
+                      href="https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/pt"
+                      target="_blank">Portuguese</a>
+                  </mat-expansion-panel>
+                </mat-accordion>
+
+              </mat-expansion-panel>
+            </mat-accordion>
+
+          </mat-card>
+          <mat-card style="background: none; margin-bottom: 10px;">
+            <mat-slide-toggle [(ngModel)]="blacklistIsActive">
+              {{'topic-cloud-dialog.hide-blacklist-words' | translate}}
+            </mat-slide-toggle>
+          </mat-card>
+        </div>
+
+        <mat-accordion class="new-profanity-word" multi>
+          <div *ngIf="isCreatorOrMod">
+            <mat-expansion-panel class="color-background"
+                                 (opened)="enterProfanityWord=true; focusInput('bad-word-input')"
+                                 (closed)="enterProfanityWord = false">
+              <mat-expansion-panel-header class="color-background">
+                <mat-panel-title>
+                  {{'topic-cloud-dialog.edit-profanity-list' | translate}}
+                </mat-panel-title>
+              </mat-expansion-panel-header>
+
+              <mat-form-field>
+                <mat-label>{{'topic-cloud-dialog.enter-word' | translate}}</mat-label>
+                <input matInput id="bad-word-input" [(ngModel)]="newProfanityWord">
+              </mat-form-field>
+
+              <button mat-stroked-button class="margin-left color-on-background" (click)="addProfanityWord()">
+                {{'topic-cloud-dialog.add-word' | translate}}
+              </button>
+
+              <mat-list role="list" *ngIf="showProfanityList" class="margin-bottom">
+                <mat-list-item class="color-on-surface" *ngFor="let word of profanitywordlist" role="listitem">{{word}}
+                  <button style="margin-left: auto" mat-icon-button class="red"
+                          (click)="removeWordFromProfanityList(word)">
+                    <mat-icon mat-list-icon style="margin-bottom: 6px;">delete_sweep</mat-icon>
+                  </button>
+                </mat-list-item>
+              </mat-list>
+
+              <div>
+                <button mat-raised-button *ngIf="profanitywordlist.length > 0" class="primaryBackground"
+                        (click)="showProfanityList=!showProfanityList">
+                  {{showProfanityList ? ('topic-cloud-dialog.hide-profanity-list' | translate) :
+                  ('topic-cloud-dialog.show-profanity-list' | translate)}}
+                </button>
+              </div>
+            </mat-expansion-panel>
+
+            <mat-expansion-panel class="color-background margin-bottom"
+                                 (opened)="enterBlacklistWord = true; focusInput('blacklist-word-input')"
+                                 (closed)="enterBlacklistWord = false">
+              <mat-expansion-panel-header class="color-background">
+                <mat-panel-title>
+                  {{'topic-cloud-dialog.edit-blacklist-list' | translate}}
+                </mat-panel-title>
+              </mat-expansion-panel-header>
+
+              <mat-form-field>
+                <mat-label>{{'topic-cloud-dialog.enter-word' | translate}}</mat-label>
+                <input matInput id="blacklist-word-input" [(ngModel)]="newBlacklistWord">
+              </mat-form-field>
+
+              <button mat-stroked-button class="margin-left color-on-background" (click)="addBlacklistWord()">
+                {{'topic-cloud-dialog.add-word' | translate}}
+              </button>
+              <mat-list role="list" *ngIf="showBlacklistWordList && blacklist.length > 0" class="margin-bottom">
+                <mat-list-item class="color-on-surface" *ngFor="let word of blacklist" role="listitem">{{word}}
+                  <button style="margin-left: auto" mat-icon-button class="red" (click)="removeWordFromBlacklist(word)">
+                    <mat-icon mat-list-icon style="margin-bottom: 6px;">delete_sweep</mat-icon>
+                  </button>
+                </mat-list-item>
+              </mat-list>
+
+              <div>
+                <button mat-raised-button class="primaryBackground" *ngIf="blacklist.length > 0"
+                        (click)="showBlacklistWordList=!showBlacklistWordList">
+                  {{showBlacklistWordList ? ('topic-cloud-dialog.hide-blacklist' | translate) :
+                  ('topic-cloud-dialog.show-blacklist' | translate)}}
+                </button>
+              </div>
+            </mat-expansion-panel>
+          </div>
+          <mat-expansion-panel class="color-background margin-bottom">
+            <mat-expansion-panel-header class="color-background">
+              <mat-panel-title>
+                {{'topic-cloud-dialog.spacy-labels' | translate}}
+              </mat-panel-title>
+            </mat-expansion-panel-header>
+
+            <mat-tab-group animationDuration="0ms" mat-stretch-tabs mat-align-tabs="center">
+              <mat-tab label="{{'topic-cloud-dialog.german' | translate}}">
+                <mat-selection-list *ngIf="wantedLabels" [(ngModel)]="wantedLabels.de">
+
+                  <mat-option class="color-on-surface" (click)="selectAllDE()">
+                    <mat-label class="color-on-surface">
+                      <mat-icon>playlist_add_check</mat-icon>
+                      {{'topic-cloud-dialog.select-all' | translate}}
+                    </mat-label>
+                    <mat-checkbox style="vertical-align: middle;float: right;"
+                                  [checked]="this.wantedLabels.de.length===this.spacyLabels.de.length"></mat-checkbox>
+                  </mat-option>
+
+                  <mat-list-option [value]="label.tag" class="color-on-surface" *ngFor="let label of spacyLabels.de">
+                    {{label.label + " (" + label.tag + ")"}}
+                  </mat-list-option>
+                </mat-selection-list>
+              </mat-tab>
+              <mat-tab label="{{'topic-cloud-dialog.english' | translate}}">
+                <mat-selection-list *ngIf="wantedLabels" [(ngModel)]="wantedLabels.en">
+
+                  <mat-option class="color-on-surface" (click)="selectAllEN()">
+                    <mat-label class="color-on-surface">
+                      <mat-icon>playlist_add_check</mat-icon>
+                      {{'topic-cloud-dialog.select-all' | translate}}
+                    </mat-label>
+                    <mat-checkbox style="vertical-align: middle;float: right;"
+                                  [checked]="this.wantedLabels.en.length===this.spacyLabels.en.length"></mat-checkbox>
+                  </mat-option>
+
+                  <mat-list-option [value]="label.tag" class="color-on-surface" *ngFor="let label of spacyLabels.en">
+                    {{label.label + " (" + label.tag + ")"}}
+                  </mat-list-option>
+                </mat-selection-list>
+              </mat-tab>
+            </mat-tab-group>
+          </mat-expansion-panel>
+        </mat-accordion>
+
+        <mat-accordion>
+          <mat-expansion-panel class="color-background margin-top">
+            <mat-expansion-panel-header class="color-background">
+              <mat-panel-title [ngClass]="{'animation-blink': isTopicRequirementActive()}">
+                {{'topic-cloud-dialog.topic-requirement-title' | translate}}
+              </mat-panel-title>
+            </mat-expansion-panel-header>
+            <mat-form-field class="themeRequirementInput" appearance="fill">
+              <mat-label>{{'topic-cloud-dialog.topic-requirement-questions' | translate}}</mat-label>
+              <input matInput type="number" min="1" [(ngModel)]="minQuestions">
+              <button *ngIf="minQuestions !== '1'" matSuffix mat-icon-button aria-label="Clear"
+                      (click)="minQuestions='1'">
+                <mat-icon>close</mat-icon>
+              </button>
+            </mat-form-field>
+            <mat-form-field class="themeRequirementInput" appearance="fill">
+              <mat-label>{{'topic-cloud-dialog.topic-requirement-questioners' | translate}}</mat-label>
+              <input matInput type="number" min="1" [(ngModel)]="minQuestioners">
+              <button *ngIf="minQuestioners !== '1'" matSuffix mat-icon-button aria-label="Clear"
+                      (click)="minQuestioners='1'">
+                <mat-icon>close</mat-icon>
+              </button>
+            </mat-form-field>
+            <mat-form-field class="themeRequirementInput" appearance="fill">
+              <mat-label>{{'topic-cloud-dialog.topic-requirement-upvotes' | translate}}</mat-label>
+              <input matInput type="number" min="0" [(ngModel)]="minUpvotes">
+              <button *ngIf="minUpvotes !== '0'" matSuffix mat-icon-button aria-label="Clear"
+                      (click)="minUpvotes='0'">
+                <mat-icon>close</mat-icon>
+              </button>
+            </mat-form-field>
+            <mat-form-field class="themeRequirementInput" appearance="fill">
+              <mat-label>{{'topic-cloud-dialog.topic-requirement-begin-datetime' | translate}}</mat-label>
+              <input matInput type="datetime-local" [(ngModel)]="startDate">
+              <button *ngIf="startDate" matSuffix mat-icon-button aria-label="Clear" (click)="startDate=''">
+                <mat-icon>close</mat-icon>
+              </button>
+            </mat-form-field>
+            <mat-form-field class="themeRequirementInput" appearance="fill">
+              <mat-label>{{'topic-cloud-dialog.topic-requirement-end-datetime' | translate}}</mat-label>
+              <input matInput type="datetime-local" [(ngModel)]="endDate">
+              <button *ngIf="endDate" matSuffix mat-icon-button aria-label="Clear" (click)="endDate=''">
+                <mat-icon>close</mat-icon>
+              </button>
+            </mat-form-field>
+            <button mat-button class="themeRequirementInput reset"
+                    [disabled]="!isTopicRequirementActive()"
+                    (click)="minQuestioners='1'; minQuestions='1'; minUpvotes='0'; startDate=''; endDate=''">
+              {{'topic-cloud-dialog.topic-requirement-reset' | translate}}
+            </button>
+          </mat-expansion-panel>
+        </mat-accordion>
+
       </mat-expansion-panel>
-    <mat-expansion-panel (opened)="panelOpenState = true"
-                         (closed)="panelOpenState = edit = false"
-                         *ngFor="let keyword of (searchMode ? filteredKeywords : keywords); let i = index" [attr.data-index]="i">
-      <mat-expansion-panel-header class="color">
-        <mat-panel-title [ngClass]="{'edit-keyword': editedKeyword}">
-          {{keyword.keyword}}
-        </mat-panel-title>
-        <mat-panel-description>
-          {{keyword.questions.length}}
-          {{'topic-cloud-dialog.question-count-'+(keyword.questions.length > 1 ? 'plural' : 'singular') | translate}}
-        </mat-panel-description>
-      </mat-expansion-panel-header>
-      <div *ngFor="let question of keyword.questions">
-        <mat-divider></mat-divider>
-        <app-topic-dialog-comment
-        [question]="question"
-        [keyword]="keyword.keyword"
-        [maxShowedCharachters]="140"
-        [isCollapsed]="!panelOpenState"
-        ></app-topic-dialog-comment>
-      </div>
+    </mat-accordion>
 
-      <!-- Only visible when not editing -->
-      <div *ngIf="!edit" align="end">
-        <mat-divider></mat-divider>
+    <div fxLayout="row">
+      <mat-label fxLayoutAlign="center center">
+        <mat-icon>search</mat-icon>
+      </mat-label>
+      <div style="margin-left: 10px; margin-top: 6px;">
+        <mat-form-field [ngClass]="{'search': searchMode, 'smallerInput': deviceType === 'mobile'}">
+          <input #searchBox class="searchBox" (input)="searchKeyword()" [(ngModel)]="searchedKeyword" matInput
+                 type="text" placeholder="{{'topic-cloud-dialog.keyword-search' | translate}}">
+          <button *ngIf="searchedKeyword" (click)="searchedKeyword = ''; searchMode = false;" mat-button matSuffix
+                  mat-icon-button aria-label="topic-cloud-dialog.keyword-search">
+            <mat-icon>close</mat-icon>
+          </button>
+        </mat-form-field>
+      </div>
 
-        <button class="margin-right" mat-icon-button style="align-self:flex-end;" (click)="editKeyword(i)">
-          <mat-icon class="primary">edit</mat-icon>
-        </button>
-        <button class="margin-right" mat-icon-button style="align-self:flex-end;"
-          (click)="openConfirmDialog(keyword)">
-          <mat-icon class="red">delete</mat-icon>
+      <div fxLayoutAlign="center center" style="margin-left: auto; font-weight: bold;">
+        <mat-icon [ngClass]="{'animation-blink': searchMode}" svgIcon="hashtag" class="oldtypo-h2 comment_tag-icon"
+                  matTooltip="{{'topic-cloud-dialog.keyword-counter' | translate}}"></mat-icon>
+        <p [ngClass]="{'animation-blink': searchMode}"
+           matTooltip="{{'topic-cloud-dialog.keyword-counter' | translate}}">
+          {{searchMode ? filteredKeywords.length :
+            selectedTabIndex === 0 ? keywords.size : blacklistKeywords.length}}</p>
+      </div>
+      <div class="margin-left vertical-center">
+        <button [ngClass]="{'animation-blink': sortMode!=='alphabetic'}" mat-icon-button [matMenuTriggerFor]="sortMenu">
+          <mat-icon matTooltip="{{'topic-cloud-dialog.sort' | translate}}">filter_list</mat-icon>
         </button>
       </div>
+    </div>
 
-      <!-- Only visible when editing -->
-      <div *ngIf="edit">
-        <mat-divider></mat-divider>
+    <mat-menu #sortMenu>
+      <button [ngClass]="{'animation-blink': sortMode==='alphabetic'}" mat-menu-item
+              (click)="sortQuestions('alphabetic')">
+        <mat-icon>sort_by_alpha</mat-icon>
+        {{'topic-cloud-dialog.sort-alpha' | translate}}
+      </button>
+      <button [ngClass]="{'animation-blink': sortMode==='questionsCount'}" mat-menu-item
+              (click)="sortQuestions('questionsCount')">
+        <mat-icon>swap_vert</mat-icon>
+        {{'topic-cloud-dialog.sort-count' | translate}}
+      </button>
+      <button [ngClass]="{'animation-blink': sortMode==='voteCount'}" mat-menu-item
+              (click)="sortQuestions('voteCount')">
+        <mat-icon>swap_vert</mat-icon>
+        {{'topic-cloud-dialog.sort-vote' | translate}}
+      </button>
+    </mat-menu>
 
-        <mat-form-field>
-          <mat-label>{{'topic-cloud-dialog.edit-keyword-tip' | translate}}</mat-label>
-          <input matInput id="{{'edit-input'+i}}" [(ngModel)]="newKeyword">
-        </mat-form-field>
-        <!-- TODO: textinput and buttons in one row -->
-        <div align="end">
-          <button mat-raised-button class="redBackground margin-right" (click)="cancelEdit()">{{'topic-cloud-dialog.cancel' | translate}}</button>
-          <button mat-raised-button class="primaryBackground" (click)="confirmEdit(keyword.keywordID)">{{'topic-cloud-dialog.save' | translate}}</button>
-        </div>
-      </div>
-    </mat-expansion-panel>
-  </mat-accordion>
+
+    <mat-tab-group [selectedIndex]="selectedTabIndex" (selectedIndexChange)="changeTabIndex()" animationDuration="0ms"
+                   mat-stretch-tabs mat-align-tabs="center">
+      <mat-tab label="{{'topic-cloud-dialog.keywords' | translate}}">
+        <mat-card class="color-surface"
+                  *ngIf="(keywords.size === 0 || (searchMode && filteredKeywords.length === 0))&&!isLoading">
+          <p class="color-on-surface" fxLayoutAlign="center">
+            {{'topic-cloud-dialog.no-keywords-note' | translate}}
+          </p>
+        </mat-card>
+        <mat-accordion>
+          <div *ngFor="let keyword of (searchMode ? filteredKeywords : getValues()); let i = index">
+            <mat-expansion-panel class="color-surface" (opened)="panelOpenState = true"
+                                 (closed)="panelOpenState = edit = false" [attr.data-index]="i"
+                                 *ngIf="(blacklistIncludesKeyword(keyword.keyword) && isCreatorOrMod) || !blacklistIncludesKeyword(keyword.keyword)"
+                                 matTooltip="{{'topic-cloud-dialog.'+(keyword.keywordType === 2?'Keyword-from-both':(keyword.keywordType === 0?'keyword-from-spacy':'keyword-from-questioner')) | translate}}">
+              <mat-expansion-panel-header class="color-surface">
+                <mat-panel-title>
+                  {{profanityFilter ? keyword.keywordWithoutProfanity : keyword.keyword}}
+                </mat-panel-title>
+                <mat-panel-description>
+                  {{keyword.comments.length}}
+                  {{'topic-cloud-dialog.question-count-' + (keyword.comments.length > 1 ? 'plural' : 'singular') | translate}}
+                </mat-panel-description>
+              </mat-expansion-panel-header>
+              <div *ngFor="let question of keyword.comments">
+
+                <app-topic-dialog-comment [question]="question.body" [keyword]="keyword.keyword"
+                                          [maxShowedCharachters]="140"
+                                          [profanityFilter]="profanityFilter"
+                                          [languageSpecific]="censorLanguageSpecificCheck"
+                                          [partialWords]="censorPartialWordsCheck"
+                                          [language]="question.language"></app-topic-dialog-comment>
+              </div>
+
+              <div *ngIf="isCreatorOrMod">
+                <!-- Only visible when not editing -->
+                <div *ngIf="!edit" align="end">
+
+                  <button class="margin-right" mat-icon-button style="align-self:flex-end;" (click)="editKeyword(i)">
+                    <mat-icon class="primary" matTooltip="{{'topic-cloud-dialog.edit' | translate}}">edit</mat-icon>
+                  </button>
+                  <button class="margin-right" mat-icon-button style="align-self:flex-end;"
+                          (click)="openConfirmDialog('delete-message','delete',keyword)">
+                    <mat-icon class="red" matTooltip="{{'topic-cloud-dialog.delete' | translate}}">delete_sweep
+                    </mat-icon>
+                  </button>
+                </div>
+
+                <!-- Only visible when editing -->
+                <div *ngIf="edit">
+
+                  <mat-form-field>
+                    <mat-label>{{'topic-cloud-dialog.edit-keyword-tip' | translate}}</mat-label>
+                    <input matInput id="{{'edit-input'+i}}" [(ngModel)]="newKeyword">
+                  </mat-form-field>
+                  <!-- TODO: textinput and buttons in one row -->
+                  <div align="end">
+                    <button mat-raised-button class="redBackground margin-right"
+                            (click)="cancelEdit()">{{'topic-cloud-dialog.cancel' | translate}}</button>
+                    <button mat-raised-button class="primaryBackground"
+                            [disabled]="!newKeyword || newKeyword.toLowerCase() === keyword.keyword.toLowerCase()"
+                            (click)="confirmEdit(keyword)">
+                      {{'topic-cloud-dialog.save' | translate}}
+                    </button>
+                  </div>
+                </div>
+              </div>
+            </mat-expansion-panel>
+          </div>
+        </mat-accordion>
+      </mat-tab>
+
+      <mat-tab *ngIf="isCreatorOrMod">
+        <ng-template mat-tab-label>
+          <label [ngClass]="{'animation-blink': blacklistIsActive}"
+                 matTooltip="{{'topic-cloud-dialog.blacklist-is'+(blacklistIsActive?'':'-not')+'-active' | translate}}">Blacklist</label>
+        </ng-template>
+        <mat-card class="color-surface"
+                  *ngIf="(blacklistKeywords.length === 0 || (searchMode && filteredKeywords.length === 0))&&!isLoading">
+          <p class="color-on-surface" fxLayoutAlign="center">
+            {{'topic-cloud-dialog.no-keywords-note' | translate}}
+          </p>
+        </mat-card>
+        <mat-accordion>
+          <div *ngFor="let keyword of (searchMode ? filteredKeywords : blacklistKeywords); let i = index">
+            <mat-expansion-panel class="color-surface" (opened)="panelOpenState = true"
+                                 (closed)="panelOpenState = edit = false" [attr.data-index]="i"
+                                 matTooltip="{{'topic-cloud-dialog.'+(keyword.keywordType === 2?'Keyword-from-both':(keyword.keywordType === 0?'keyword-from-spacy':'keyword-from-questioner')) | translate}}">
+              <mat-expansion-panel-header class="color-surface">
+                <mat-panel-title>
+                  {{keyword.keyword}}
+                </mat-panel-title>
+                <mat-panel-description>
+                  {{keyword.comments.length}}
+                  {{'topic-cloud-dialog.question-count-' + (keyword.comments.length > 1 ? 'plural' : 'singular') | translate}}
+                </mat-panel-description>
+              </mat-expansion-panel-header>
+              <div *ngFor="let question of keyword.comments">
+
+                <app-topic-dialog-comment [question]="question.body" [keyword]="keyword.keyword"
+                                          [maxShowedCharachters]="140"
+                                          [profanityFilter]="profanityFilter"
+                                          [languageSpecific]="censorLanguageSpecificCheck"
+                                          [partialWords]="censorPartialWordsCheck"
+                                          [language]="question.language"></app-topic-dialog-comment>
+              </div>
+              <div>
+                <!-- Only visible when not editing -->
+                <div *ngIf="!edit" align="end">
+
+                  <button class="margin-right" mat-icon-button style="align-self:flex-end;" (click)="editKeyword(i)">
+                    <mat-icon class="primary" matTooltip="{{'topic-cloud-dialog.edit' | translate}}">edit</mat-icon>
+                  </button>
+                  <button class="margin-right" mat-icon-button style="align-self:flex-end;"
+                          (click)="openConfirmDialog('delete-message','delete',keyword)">
+                    <mat-icon class="red" matTooltip="{{'topic-cloud-dialog.delete' | translate}}">delete_sweep
+                    </mat-icon>
+                  </button>
+                </div>
+
+                <!-- Only visible when editing -->
+                <div *ngIf="edit">
+
+                  <mat-form-field>
+                    <mat-label>{{'topic-cloud-dialog.edit-keyword-tip' | translate}}</mat-label>
+                    <input matInput id="{{'edit-input'+i}}" [(ngModel)]="newKeyword">
+                  </mat-form-field>
+
+                  <div align="end">
+                    <button mat-raised-button class="redBackground margin-right"
+                            (click)="cancelEdit()">{{'topic-cloud-dialog.cancel' | translate}}</button>
+                    <button mat-raised-button class="primaryBackground"
+                            (click)="confirmEdit(keyword)">{{'topic-cloud-dialog.save'
+                      | translate}}</button>
+                  </div>
+                </div>
+              </div>
+            </mat-expansion-panel>
+          </div>
+        </mat-accordion>
+      </mat-tab>
+    </mat-tab-group>
+  </div>
 </mat-dialog-content>
+<app-dialog-action-buttons
+  buttonsLabelSection="topic-cloud-dialog"
+  confirmButtonLabel="save"
+
+  [cancelButtonClickAction]="buildCloseDialogActionCallback()"
+  [confirmButtonClickAction]="buildSaveActionCallback()"
+></app-dialog-action-buttons>
diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.scss b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.scss
index a947d843613ebf92e8d6d0405f1dd087937ca49d..86c644ce629cd8a7704e986c99957c3071e622fb 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.scss
+++ b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.scss
@@ -1,21 +1,39 @@
 // hide scrollbar
 ::-webkit-scrollbar {
-    display: none;  /* Chrome Safari */
+  display: none; /* Chrome Safari */
 }
+
 //TODO: hide scrollbar for IE and Firefox
 
 .margin-right {
   margin-right: 16px;
 }
 
+.margin-left {
+  margin-left: 8px;
+}
+
+.margin-bottom {
+  margin-bottom: 16px;
+}
+
+.margin-top {
+  margin-top: 16px;
+}
+
 .primary {
   color: var(--primary);
+  background: none;
 }
 
 .red {
   color: var(--red);
 }
 
+.green {
+  color: var(--green);
+}
+
 .primaryBackground {
   background-color: var(--primary);
 }
@@ -32,10 +50,42 @@ mat-icon {
   fill: currentColor;
 }
 
-mat-expansion-panel-header, mat-expansion-panel, mat-card {
+mat-list-item:hover {
+  background-color: rgba(128, 128, 128, 0.2);
+
+}
+
+.color-surface {
   background-color: var(--surface);
 }
 
+.color-background {
+  background-color: var(--dialog);
+}
+
+.color-on-surface {
+  color: var(--on-surface);
+}
+
+.color-on-background {
+  color: var(--on-background);
+}
+
+.search {
+  box-sizing: border-box;
+  padding: 0 10px 0 5px;
+  border: none;
+  outline: none;
+  min-height: 60px;
+  font-size: large;
+  border-radius: 5px;
+  color: var(--on-surface);
+  transition: width 300ms linear;
+}
+
+.smallerInput {
+  max-width: 100px;
+}
 
 label {
   color: var(--on-surface)
@@ -57,7 +107,7 @@ mat-panel-title, mat-panel-description {
   }
 }
 
-.edit-keyword .mat-panel-title {
+.animation-blink {
   color: var(--red) !important;
   animation-name: animation_blink_5s;
   animation-timing-function: ease-in;
@@ -65,4 +115,69 @@ mat-panel-title, mat-panel-description {
   animation-iteration-count: 2;
   opacity: 1.0 !important;
 }
- 
\ No newline at end of file
+
+.new-profanity-word .mat-expansion-panel-header-title,
+.new-profanity-word .mat-expansion-panel-header-description {
+  flex-basis: 0;
+}
+
+.new-profanity-word .mat-expansion-panel-header-description,
+.new-profanity-word .button {
+  justify-content: space-between;
+  align-items: center;
+}
+
+.new-profanity-word .mat-form-field + .mat-form-field {
+  margin-left: 8px;
+}
+
+.themeRequirementInput {
+  width: 100%;
+  margin-left: 0 !important;
+}
+
+.vertical-center {
+  margin-top: auto;
+  margin-bottom: auto;
+}
+
+.radio-button-item {
+  margin-bottom: 7px;
+  color: var(--on-surface);
+}
+
+.radio-button-group {
+  display: flex;
+  flex-direction: column;
+  margin: 15px 0;
+}
+
+mat-dialog-content {
+  max-height: 80vh !important;
+  margin: unset;
+  padding: unset;
+}
+
+.comment_tag-icon {
+  height: 18px !important;
+}
+
+.testProfanity {
+  margin-top: 0px;
+}
+
+::ng-deep .ng-animating div mat-accordion mat-expansion-panel mat-expansion-panel-header {
+  height: 48px;
+}
+
+::ng-deep .ng-animating div mat-accordion mat-expansion-panel div.mat-expansion-panel-content {
+  height: 0px;
+  visibility: hidden;
+}
+
+.reset {
+  margin: 25px auto auto auto;
+  background-color: var(--secondary);
+  color: black;
+  width: 100%;
+}
diff --git a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts
index c18be92350c9ad7f1ea277be0a42a265a7af72a4..db3d258cf2c1e2f6f26e8e0e8c1fb2efbf9bec66 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts
+++ b/src/app/components/shared/_dialogs/topic-cloud-administration/topic-cloud-administration.component.ts
@@ -1,201 +1,618 @@
-import { Component, OnInit } from '@angular/core';
-import { MatDialog, MatDialogRef } from '@angular/material/dialog';
-import { TagCloudComponent } from '../../tag-cloud/tag-cloud.component';
+import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
 import { NotificationService } from '../../../../services/util/notification.service';
 import { TopicCloudConfirmDialogComponent } from '../topic-cloud-confirm-dialog/topic-cloud-confirm-dialog.component';
-import { AuthenticationService } from '../../../../services/http/authentication.service';
 import { UserRole } from '../../../../models/user-roles.enum';
 import { TranslateService } from '@ngx-translate/core';
 import { LanguageService } from '../../../../services/util/language.service';
+import { TopicCloudAdminService } from '../../../../services/util/topic-cloud-admin.service';
+import { ProfanityFilterService } from '../../../../services/util/profanity-filter.service';
+import { TopicCloudAdminData, Labels, spacyLabels, KeywordOrFulltext } from './TopicCloudAdminData';
+import { User } from '../../../../models/user';
+import { Comment } from '../../../../models/comment';
+import { CommentService } from '../../../../services/http/comment.service';
+import { TSMap } from 'typescript-map';
+import { RoomDataService } from '../../../../services/util/room-data.service';
+import { ProfanityFilter } from '../../../../models/room';
 
 @Component({
   selector: 'app-topic-cloud-administration',
   templateUrl: './topic-cloud-administration.component.html',
   styleUrls: ['./topic-cloud-administration.component.scss']
 })
-export class TopicCloudAdministrationComponent implements OnInit {
+export class TopicCloudAdministrationComponent implements OnInit, OnDestroy {
   public panelOpenState = false;
-  public considerVotes: boolean; // should be sent back to tagCloud component
-  public tagsLowerCase: boolean; // should be sent back to tagCloud component
+  public considerVotes: boolean;
+  public blacklistIsActive: boolean;
+  blacklist: string[] = [];
+  profanitywordlist: string[] = [];
+  blacklistSubscription = undefined;
+  profanitylistSubscription = undefined;
+  commentServiceSubscription = undefined;
+  keywordOrFulltextENUM = KeywordOrFulltext;
   newKeyword = undefined;
   edit = false;
   isCreatorOrMod: boolean;
-
+  enterProfanityWord = false;
+  enterBlacklistWord = false;
+  newProfanityWord: string = undefined;
+  newBlacklistWord: string = undefined;
   sortMode = 'alphabetic';
-  editedKeyword = false;
   searchedKeyword = undefined;
   searchMode = false;
+  deviceType: string;
   filteredKeywords: Keyword[] = [];
+  showProfanityList = false;
+  showBlacklistWordList = false;
+  showSettingsPanel = false;
+  keywordORfulltext: string = undefined;
+  userRole: UserRole;
+  spacyLabels: Labels;
+  wantedLabels: {
+    de: string[];
+    en: string[];
+  };
+  spacyLabelsAllSelectedDE = true;
+  isLoading: boolean;
+  minQuestions: string;
+  minQuestioners: string;
+  minUpvotes: string;
+  startDate: string;
+  endDate: string;
+  selectedTabIndex = 0;
 
-  keywords: Keyword[] = [
-    {
-      keywordID: 1,
-      keyword: 'Cloud',
-      questions: [
-        'Wieviel speicherplatz steht mir in der Cloud zur verfuegung? Ich habe eine Frage, sind Fragen zum thema \'Frage\' auch erlaubt?',
-        'Sollen wir die Tag Cloud implementieren?',
-        // eslint-disable-next-line max-len
-        'Wie genau ist die Cloud aufgebaut? Wieviel speicherplatz steht mir in der Cloud zur verfuegungWie genau ist die Cloud aufgebaut? Wieviel speicherplatz steht mir in der Cloud zur verfuegungWie genau ist die Cloud aufgebaut? Wieviel speicherplatz steht mir in der Cloud zur verfuegungWie genau ist die Cloud aufgebaut? Wieviel speicherplatz steht mir in der Cloud zur verfuegungWie genau ist die Cloud aufgebaut? Wieviel speicherplatz steht mir in der Cloud zur verfuegungWie genau ist die Cloud aufgebaut? Wieviel speicherplatz steht mir in der Cloud zur verfuegung',
-      ]
-    },
-    {
-      keywordID: 2,
-      keyword: 'SWT',
-      questions: [
-        'Muss man fuer das Modul SWT bestanden haben?'
-      ]
-    },
-    {
-      keywordID: 3,
-      keyword: 'Frage',
-      questions: [
-        'Das ist eine Lange Frage mit dem Thema \'frage\'',
-        'Ich habe eine Frage, sind Fragen zum thema \'Frage\' auch erlaubt?',
-        'Ich wollte Fragen ob sie gerne Sachen gefragt werden',
-        'Langsam geht mir die Fragerei mit den ganzen Fragen auf den Geist Frage'
-      ]
-    },
-    {
-      keywordID: 4,
-      keyword: 'Klausur',
-      questions: [
-        'Darf man in der Klausur hilfmittel verwenden?',
-        'An welchem Termin findet die Klausur statt?'
-      ]
-    },
-    {
-      keywordID: 5,
-      keyword: 'Diskrete Math',
-      questions: [
-        'wann wird die nächste veranstaltung stattfinden?',
-        'gibt es heute übung?'
-      ]
-    },
-
-  ];
-
-  constructor(public cloudDialogRef: MatDialogRef<TagCloudComponent>,
-              public confirmDialog: MatDialog,
-              private notificationService: NotificationService,
-              private authenticationService: AuthenticationService,
-              private translateService: TranslateService,
-              private langService: LanguageService) {
-
-                this.langService.langEmitter.subscribe(lang => {
-                  this.translateService.use(lang);
-                });
-              }
+  keywords: Map<string, Keyword> = new Map<string, Keyword>();
+  private topicCloudAdminData: TopicCloudAdminData;
+  private profanityFilter: boolean;
+  private censorPartialWordsCheck: boolean;
+  private censorLanguageSpecificCheck: boolean;
+  private testProfanityWord: string = undefined;
+  private testProfanityLanguage = 'de';
+  private blacklistKeywords = [];
+
+  constructor(
+    @Inject(MAT_DIALOG_DATA) public data: Data,
+    public cloudDialogRef: MatDialogRef<TopicCloudAdministrationComponent>,
+    public confirmDialog: MatDialog,
+    private notificationService: NotificationService,
+    private translateService: TranslateService,
+    private langService: LanguageService,
+    private topicCloudAdminService: TopicCloudAdminService,
+    private commentService: CommentService,
+    private roomDataService: RoomDataService,
+    private profanityFilterService: ProfanityFilterService) {
+    this.langService.langEmitter.subscribe(lang => {
+      this.translateService.use(lang);
+    });
+  }
 
   ngOnInit(): void {
+    this.topicCloudAdminService.getBlacklistIsActive().subscribe(isActive => {
+      this.blacklistIsActive = isActive;
+      this.refreshKeywords();
+    });
+    this.deviceType = localStorage.getItem('deviceType');
+    this.blacklistSubscription = this.topicCloudAdminService.getBlacklist().subscribe(list => {
+      this.blacklist = list;
+      this.refreshKeywords();
+    });
+    this.profanitywordlist = this.profanityFilterService.getProfanityListFromStorage();
+    this.profanitylistSubscription = this.profanityFilterService.getCustomProfanityList().subscribe(list => {
+      this.profanitywordlist = list;
+      this.refreshKeywords();
+    });
+    this.isCreatorOrMod = this.data.user.role !== UserRole.PARTICIPANT;
     this.translateService.use(localStorage.getItem('currentLang'));
-    this.checkIfUserIsModOrCreator();
-    this.checkIfThereAreQuestions();
-    this.sortQuestions();
+    this.spacyLabels = spacyLabels;
+    this.wantedLabels = undefined;
+    this.setDefaultAdminData();
+    this.initializeKeywords();
+  }
+
+  changeTabIndex() {
+    this.selectedTabIndex = this.selectedTabIndex === 0 ? 1 : 0;
+    if (this.searchMode) {
+      this.searchKeyword();
+    }
+  }
+
+  getValues(): Keyword[] {
+    return [...this.keywords.values()];
+  }
+
+  removeFromKeywords(comment: Comment) {
+    for (const [_, keyword] of this.keywords.entries()) {
+      const index = keyword.comments.findIndex(c => c.id === comment.id);
+      if (index >= 0) {
+        keyword.comments.splice(index, 1);
+      }
+    }
+    this.refreshKeywords();
+  }
+
+  refreshKeywords() {
+    this.blacklistKeywords = [];
+    this.keywords = new Map<string, Keyword>();
+    this.roomDataService.currentRoomData.forEach(comment => {
+      this.pushInKeywords(comment);
+    });
+    if (this.searchMode) {
+      this.searchKeyword();
+    }
+  }
+
+  pushInKeywords(comment: Comment) {
+    let _keywordType = KeywordType.fromQuestioner;
+    let keywords = comment.keywordsFromQuestioner;
+    if (this.keywordORfulltext === KeywordOrFulltext[KeywordOrFulltext.both]) {
+      if (!keywords || !keywords.length) {
+        keywords = comment.keywordsFromSpacy;
+        _keywordType = KeywordType.fromSpacy;
+      }
+    } else if (this.keywordORfulltext === KeywordOrFulltext[KeywordOrFulltext.fulltext]) {
+      keywords = comment.keywordsFromSpacy;
+      _keywordType = KeywordType.fromSpacy;
+    }
+    if (!keywords) {
+      keywords = [];
+    }
+    keywords.forEach(_keyword => {
+      const existingKey = this.checkIfKeywordExists(_keyword.lemma);
+      if (existingKey) {
+        existingKey.vote += comment.score;
+        _keyword.dep.forEach(dep => existingKey.keywordDeps.add(dep));
+        if (this.checkIfCommentExists(existingKey.comments, comment.id)) {
+          existingKey.comments.push(comment);
+        }
+      } else {
+        if (this.keywordORfulltext === KeywordOrFulltext[KeywordOrFulltext.both]) {
+          const includedFromQuestioner = comment.keywordsFromQuestioner.findIndex(e => e.lemma === _keyword.lemma) >= 0;
+          if (includedFromQuestioner && comment.keywordsFromSpacy.findIndex(e => e.lemma === _keyword.lemma) >= 0) {
+            _keywordType = KeywordType.fromBoth;
+          } else {
+            _keywordType = includedFromQuestioner ? KeywordType.fromQuestioner : KeywordType.fromSpacy;
+          }
+        }
+        const entry = {
+          keyword: _keyword.lemma,
+          keywordDeps: new Set<string>(_keyword.dep),
+          keywordType: _keywordType,
+          keywordWithoutProfanity: this.getKeywordWithoutProfanity(_keyword.lemma, comment.language),
+          comments: [comment],
+          vote: comment.score
+        };
+
+        if (this.blacklistIncludesKeyword(_keyword.lemma) && this.blacklistIsActive) {
+          this.blacklistKeywords.push(entry);
+        } else {
+          this.keywords.set(_keyword.lemma, entry as Keyword);
+        }
+      }
+    });
+  }
+
+  /**
+   * Returns a lambda which closes the dialog on call.
+   */
+   buildCloseDialogActionCallback(): () => void {
+    return () => this.ngOnDestroy();
+  }
+
+  /**
+   * Returns a lambda which executes the dialog dedicated action on call.
+   */
+   buildSaveActionCallback(): () => void {
+    return () => this.save();
+  }
+
+  ngOnDestroy() {
+    if (this.blacklistSubscription !== undefined) {
+      this.blacklistSubscription.unsubscribe();
+    }
+    if (this.profanitylistSubscription !== undefined) {
+      this.profanitylistSubscription.unsubscribe();
+    }
+    this.cloudDialogRef.close();
+  }
+
+  save() {
+    this.setAdminData();
+    this.ngOnDestroy();
+  }
+
+  initializeKeywords() {
+    const roomId = localStorage.getItem('roomId');
+    this.roomDataService.getRoomData(roomId).subscribe(comments => {
+      if (comments === null) {
+        return;
+      }
+      this.keywords = new Map<string, Keyword>();
+      comments.forEach(comment => {
+        this.pushInKeywords(comment);
+      });
+      this.sortQuestions();
+      this.isLoading = false;
+    });
+    this.commentServiceSubscription = this.roomDataService.receiveUpdates([
+      { type: 'CommentCreated', finished: true },
+      { type: 'CommentDeleted' },
+      { type: 'CommentPatched', finished: true, updates: ['score'] },
+      { type: 'CommentPatched', finished: true, updates: ['upvotes'] },
+      { type: 'CommentPatched', finished: true, updates: ['downvotes'] },
+      { type: 'CommentPatched', finished: true, updates: ['keywordsFromSpacy'] },
+      { type: 'CommentPatched', finished: true, updates: ['keywordsFromQuestioner'] },
+      { type: 'CommentPatched', finished: true, updates: ['ack'] },
+      { type: 'CommentPatched', finished: true, updates: ['tag'] },
+      { type: 'CommentPatched', subtype: 'ack' },
+      { finished: true }
+    ]).subscribe(update => {
+      if (update.type === 'CommentCreated') {
+        this.pushInKeywords(update.comment);
+      } else if (update.type === 'CommentDeleted') {
+        this.removeFromKeywords(update.comment);
+      } else if (update.type === 'CommentPatched' && update.subtype === 'ack') {
+        if (!update.comment.ack) {
+          this.removeFromKeywords(update.comment);
+        }
+      }
+      if (update.finished) {
+        if (this.searchMode) {
+          this.searchKeyword();
+        }
+        this.refreshKeywords();
+      }
+    });
+  }
+
+  blacklistIncludesKeyword(keyword: string) {
+    return this.blacklistIsActive && this.blacklist.includes(keyword.toLowerCase());
+  }
+
+  checkIfCommentExists(comments: Comment[], id: string): boolean {
+    return comments.filter(comment => comment.id === id).length === 0;
+  }
+
+  isTopicRequirementActive(): boolean {
+    return (this.minQuestioners !== '1') || (this.minQuestions !== '1') || (this.minUpvotes !== '0') ||
+      (!!this.startDate) || (!!this.endDate);
+  }
+
+  setAdminData() {
+    let profFilter = this.profanityFilter ? ProfanityFilter.none : ProfanityFilter.deactivated;
+    if (this.profanityFilter) {
+      if (this.censorLanguageSpecificCheck && this.censorPartialWordsCheck) {
+        profFilter = ProfanityFilter.all;
+      } else {
+        profFilter = this.censorLanguageSpecificCheck ? ProfanityFilter.languageSpecific : ProfanityFilter.none;
+        profFilter = this.censorPartialWordsCheck ? ProfanityFilter.partialWords : profFilter;
+      }
+    }
+    let minQuestionersVerified = +this.minQuestioners;
+    if (Number.isNaN(minQuestionersVerified) || minQuestionersVerified < 1) {
+      minQuestionersVerified = 1;
+    }
+    let minQuestionsVerified = +this.minQuestions;
+    if (Number.isNaN(minQuestionsVerified) || minQuestionsVerified < 1) {
+      minQuestionsVerified = 1;
+    }
+    let minUpvotesVerified = +this.minUpvotes;
+    if (Number.isNaN(minUpvotesVerified) || minUpvotesVerified < 0) {
+      minUpvotesVerified = 0;
+    }
+    this.topicCloudAdminData = {
+      blacklist: [],
+      wantedLabels: {
+        de: this.wantedLabels.de,
+        en: this.wantedLabels.en
+      },
+      considerVotes: this.considerVotes,
+      profanityFilter: profFilter,
+      blacklistIsActive: this.blacklistIsActive,
+      keywordORfulltext: KeywordOrFulltext[this.keywordORfulltext],
+      minQuestioners: minQuestionersVerified,
+      minQuestions: minQuestionsVerified,
+      minUpvotes: minUpvotesVerified,
+      startDate: this.startDate.length ? this.startDate : null,
+      endDate: this.endDate.length ? this.endDate : null
+    };
+    this.topicCloudAdminService.setAdminData(this.topicCloudAdminData, true, this.data.user.role);
+  }
+
+  setDefaultAdminData() {
+    this.topicCloudAdminData = TopicCloudAdminService.getDefaultAdminData;
+    if (this.topicCloudAdminData) {
+      this.considerVotes = this.topicCloudAdminData.considerVotes;
+      this.profanityFilter = this.topicCloudAdminData.profanityFilter !== ProfanityFilter.deactivated;
+      if (this.topicCloudAdminData.profanityFilter === ProfanityFilter.all) {
+        this.censorLanguageSpecificCheck = this.censorPartialWordsCheck = true;
+      } else if (this.profanityFilter) {
+        this.censorLanguageSpecificCheck = this.topicCloudAdminData.profanityFilter === ProfanityFilter.languageSpecific;
+        this.censorPartialWordsCheck = this.topicCloudAdminData.profanityFilter === ProfanityFilter.partialWords;
+      }
+      this.blacklistIsActive = this.topicCloudAdminData.blacklistIsActive;
+      this.keywordORfulltext = KeywordOrFulltext[this.topicCloudAdminData.keywordORfulltext];
+      this.wantedLabels = {
+        de: this.topicCloudAdminData.wantedLabels.de,
+        en: this.topicCloudAdminData.wantedLabels.en
+      };
+      this.minQuestioners = String(this.topicCloudAdminData.minQuestioners);
+      this.minQuestions = String(this.topicCloudAdminData.minQuestions);
+      this.minUpvotes = String(this.topicCloudAdminData.minUpvotes);
+      this.startDate = this.topicCloudAdminData.startDate || '';
+      this.endDate = this.topicCloudAdminData.endDate || '';
+    }
+  }
+
+  getKeywordWithoutProfanity(keyword: string, lang: string): string {
+    return this.profanityFilterService.filterProfanityWords(keyword, this.censorPartialWordsCheck, this.censorLanguageSpecificCheck, lang);
   }
 
   sortQuestions(sortMode?: string) {
     if (sortMode !== undefined) {
       this.sortMode = sortMode;
     }
-
+    const entries = [...this.keywords.entries()];
     switch (this.sortMode) {
       case 'alphabetic':
-        this.keywords.sort((a, b) => a.keyword.localeCompare(b.keyword));
+        entries.sort(([a], [b]) => a.localeCompare(b));
         break;
       case 'questionsCount':
-        this.keywords.sort((a, b) => b.questions.length - a.questions.length);
+        entries.sort(([_, a], [__, b]) => b.comments.length - a.comments.length);
         break;
       case 'voteCount':
-        console.log('not implemented!, sorting with question count');
-        this.keywords.sort((a, b) => b.questions.length - a.questions.length);
+        entries.sort(([_, a], [__, b]) => b.vote - a.vote);
         break;
     }
-  }
-
-  checkIfUserIsModOrCreator() {
-    this.isCreatorOrMod = this.authenticationService.getRole() === UserRole.CREATOR ||
-                          this.authenticationService.getRole() === UserRole.EDITING_MODERATOR ||
-                          this.authenticationService.getRole() === UserRole.EXECUTIVE_MODERATOR;
+    this.keywords = new Map(entries);
   }
 
   checkIfThereAreQuestions() {
-    if (this.keywords.length === 0){
-      this.translateService.get('topic-cloud-dialog.nokeyword-note').subscribe(msg => {
+    if (this.keywords.size === 0) {
+      this.translateService.get('topic-cloud-dialog.no-keywords-note').subscribe(msg => {
         this.notificationService.show(msg);
       });
-      this.cloudDialogRef.close();
+      setTimeout(() => {
+        this.cloudDialogRef.close();
+      }, 0);
     }
   }
 
   editKeyword(index: number): void {
     this.edit = true;
-
     setTimeout(() => {
-      document.getElementById('edit-input'+ index).focus();
+      document.getElementById('edit-input' + index).focus();
     }, 0);
   }
 
-  deleteKeyword(id: number): void{
-    this.keywords.map(keyword => {
-      if (keyword.keywordID === id) {
-          this.keywords.splice(this.keywords.indexOf(keyword, 0), 1);
-      }
+  deleteKeyword(key: Keyword, message?: string): void {
+    key.comments.forEach(comment => {
+      const changes = new TSMap<string, any>();
+      let keywords = comment.keywordsFromQuestioner;
+      keywords.splice(keywords.findIndex(e => e.lemma === key.keyword), 1);
+      changes.set('keywordsFromQuestioner', JSON.stringify(keywords));
+      keywords = comment.keywordsFromSpacy;
+      keywords.splice(keywords.findIndex(e => e.lemma === key.keyword), 1);
+      changes.set('keywordsFromSpacy', JSON.stringify(keywords));
+      this.updateComment(comment, changes, message);
     });
-    if (this.keywords.length === 0) {
-      this.cloudDialogRef.close();
-    }
-    if (this.searchMode === true){
-      /* update filtered array if it is searchmode */
+
+    if (this.searchMode === true) {
       this.searchKeyword();
     }
   }
 
+  updateComment(updatedComment: Comment, changes: TSMap<string, any>, messageTranslate?: string) {
+    this.commentService.patchComment(updatedComment, changes).subscribe(_ => {
+        if (messageTranslate) {
+          this.translateService.get('topic-cloud-dialog.' + messageTranslate).subscribe(msg => {
+            this.notificationService.show(msg);
+          });
+        }
+      },
+      error => {
+        this.translateService.get('topic-cloud-dialog.changes-gone-wrong').subscribe(msg => {
+          this.notificationService.show(msg);
+        });
+      });
+  }
+
   cancelEdit(): void {
     this.edit = false;
     this.newKeyword = undefined;
   }
 
-  confirmEdit(id: number): void {
-    this.keywords.map(keyword => {
-      if (keyword.keywordID === id) {
-          keyword.keyword = this.newKeyword.trim();
+  confirmEdit(key: Keyword): void {
+    const key2 = this.checkIfKeywordExists(this.newKeyword);
+    if (key2) {
+      if (key === key2) {
+        return;
       }
-    });
+      this.openConfirmDialog('merge-message', 'merge', key, key2);
+    } else {
+      key.comments.forEach(comment => {
+        const changes = new TSMap<string, any>();
+        let keywords = comment.keywordsFromQuestioner;
+        const lowerCaseKeyword = key.keyword.toLowerCase();
+        for (const keyword of keywords) {
+          if (keyword.lemma.toLowerCase() === lowerCaseKeyword) {
+            keyword.lemma = this.newKeyword.trim();
+          }
+        }
+        changes.set('keywordsFromQuestioner', JSON.stringify(keywords));
+        keywords = comment.keywordsFromSpacy;
+        for (const keyword of keywords) {
+          if (keyword.lemma.toLowerCase() === lowerCaseKeyword) {
+            keyword.lemma = this.newKeyword.trim();
+          }
+        }
+        changes.set('keywordsFromSpacy', JSON.stringify(keywords));
+        this.updateComment(comment, changes, 'keyword-edit');
+      });
+    }
+
     this.edit = false;
-    this.editedKeyword = true;
     this.newKeyword = undefined;
     this.sortQuestions();
-    if (this.searchMode){
+    if (this.searchMode) {
       this.searchKeyword();
     }
   }
 
-  openConfirmDialog(keyword: Keyword): void {
+  openConfirmDialog(msg: string, _confirmLabel: string, keyword: Keyword, mergeTarget?: Keyword) {
+    const translationPart = 'topic-cloud-confirm-dialog.' + msg;
     const confirmDialogRef = this.confirmDialog.open(TopicCloudConfirmDialogComponent, {
-      data: {topic: keyword.keyword}
+      data: { topic: keyword.keyword, message: translationPart, confirmLabel: _confirmLabel }
     });
 
     confirmDialogRef.afterClosed().subscribe(result => {
       if (result === 'delete') {
-        this.deleteKeyword(keyword.keywordID);
+        this.deleteKeyword(keyword, 'keyword-delete');
+      } else if (result === 'merge') {
+        this.mergeKeywords(keyword, mergeTarget);
       }
     });
   }
 
   searchKeyword(): void {
-    if (!this.searchedKeyword){
-        this.searchMode = false;
+    if (!this.searchedKeyword) {
+      this.searchMode = false;
     } else {
-      this.filteredKeywords = this.keywords.filter(keyword =>
+      if (this.selectedTabIndex === 0) {
+        const entries = [...this.keywords.entries()];
+        this.filteredKeywords = entries.filter(([_, keyword]) =>
         keyword.keyword.toLowerCase().includes(this.searchedKeyword.toLowerCase())
-      );
+        ).map(e => e[1]);
+      } else {
+        this.filteredKeywords = this.blacklistKeywords.filter(keyword =>
+          keyword.keyword.toLowerCase().includes(this.searchedKeyword.toLowerCase())
+        );
+      }
       this.searchMode = true;
     }
   }
+
+  mergeKeywords(key1: Keyword, key2: Keyword) {
+    if (key1 !== undefined && key2 !== undefined) {
+      key1.comments = key1.comments.filter(comment => {
+        if (this.checkIfCommentExists(key2.comments, comment.id)) {
+          const changes = new TSMap<string, any>();
+          const lowerKey1 = key1.keyword.toLowerCase();
+
+          let keywords = comment.keywordsFromQuestioner;
+          let index = keywords.findIndex(k => k.lemma.toLowerCase() === lowerKey1);
+          keywords[index].lemma = key2.keyword;
+          changes.set('keywordsFromQuestioner', JSON.stringify(keywords));
+
+          keywords = comment.keywordsFromSpacy;
+          index = keywords.findIndex(k => k.lemma.toLowerCase() === lowerKey1);
+          keywords[index].lemma = key2.keyword;
+          changes.set('keywordsFromSpacy', JSON.stringify(keywords));
+
+          this.updateComment(comment, changes);
+          return false;
+        }
+        return true;
+      });
+      this.deleteKeyword(key1);
+    }
+  }
+
+  checkIfKeywordExists(key: string): Keyword {
+    const currentKeyword = key.toLowerCase();
+    for (const keyword of this.keywords.keys()) {
+      if (keyword.toLowerCase() === currentKeyword) {
+        return this.keywords.get(keyword);
+      }
+    }
+    return undefined;
+  }
+
+  focusInput(id: string) {
+    setTimeout(() => {
+      document.getElementById(id).focus();
+    }, 100);
+  }
+
+  addProfanityWord() {
+    this.profanityFilterService.addToProfanityList(this.newProfanityWord);
+    this.newProfanityWord = undefined;
+  }
+
+  addBlacklistWord() {
+    this.topicCloudAdminService.addWordToBlacklist(this.newBlacklistWord);
+    this.newBlacklistWord = undefined;
+  }
+
+  removeWordFromProfanityList(word: string) {
+    this.profanityFilterService.removeFromProfanityList(word);
+  }
+
+  removeWordFromBlacklist(word: string) {
+    this.topicCloudAdminService.removeWordFromBlacklist(word);
+  }
+
+  showMessage(label: string, event: boolean) {
+    if (event) {
+      this.translateService.get('topic-cloud-dialog.' + label).subscribe(msg => {
+        this.notificationService.show(msg);
+      });
+      if (this.searchMode) {
+        this.searchKeyword();
+      }
+    }
+    this.refreshKeywords();
+  }
+
+  selectAllDE() {
+    if (this.wantedLabels.de.length < this.spacyLabels.de.length) {
+      this.wantedLabels.de = [];
+      this.spacyLabels.de.forEach(label => {
+        this.wantedLabels.de.push(label.tag);
+      });
+      this.spacyLabelsAllSelectedDE = true;
+    } else {
+      this.wantedLabels.de = [];
+      this.spacyLabelsAllSelectedDE = false;
+    }
+  }
+
+  selectAllEN() {
+    if (this.wantedLabels.en.length < this.spacyLabels.en.length) {
+      this.wantedLabels.en = [];
+      this.spacyLabels.en.forEach(label => {
+        this.wantedLabels.en.push(label.tag);
+      });
+    } else {
+      this.wantedLabels.en = [];
+    }
+  }
+
+  getFilteredProfanity(): string {
+    if (this.testProfanityWord) {
+      // eslint-disable-next-line max-len
+      return this.profanityFilterService.filterProfanityWords(this.testProfanityWord, this.censorPartialWordsCheck, this.censorLanguageSpecificCheck, this.testProfanityLanguage);
+    } else {
+      return '';
+    }
+  }
 }
 
 interface Keyword {
-  keywordID: number;
   keyword: string;
-  questions: string[];
+  keywordDeps: Set<string>;
+  keywordType: KeywordType;
+  keywordWithoutProfanity: string;
+  comments: Comment[];
+  vote: number;
+}
+
+export interface Data {
+  user: User;
+}
+
+enum KeywordType {
+  fromSpacy = 0,
+  fromQuestioner = 1,
+  fromBoth = 2
 }
+
diff --git a/src/app/components/shared/_dialogs/topic-cloud-confirm-dialog/topic-cloud-confirm-dialog.component.html b/src/app/components/shared/_dialogs/topic-cloud-confirm-dialog/topic-cloud-confirm-dialog.component.html
index a6ec0ecf8685871eac234e9b4739bad642ae53eb..8fd6099f08a587b10642a236a87a3a6275f4a9f9 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-confirm-dialog/topic-cloud-confirm-dialog.component.html
+++ b/src/app/components/shared/_dialogs/topic-cloud-confirm-dialog/topic-cloud-confirm-dialog.component.html
@@ -1,18 +1,9 @@
 <h2 mat-dialog-title>{{'topic-cloud-confirm-dialog.confirm' | translate}}</h2>
-<mat-divider></mat-divider>
-<p>{{'topic-cloud-confirm-dialog.will-be-deleted' | translate }} '{{data.topic}}'.</p>
-
-<!-- <div mat-dialog-actions align="end">
-  <button class="primary" mat-raised-button [mat-dialog-close]="false">
-    {{'topic-cloud-confirm-dialog.cancel' | translate}}</button>
-  <button class="warn" mat-raised-button [mat-dialog-close]="true">
-    {{'topic-cloud-confirm-dialog.delete' | translate}}
-  </button>
-</div> -->
+<p>{{ data.message | translate}} '{{data.topic}}'.</p>
 
 <app-dialog-action-buttons
   buttonsLabelSection="topic-cloud-confirm-dialog"
-  confirmButtonLabel="delete"
+  [confirmButtonLabel]= data.confirmLabel
   [confirmButtonType]=confirmButtonType
   [cancelButtonClickAction]="buildCloseDialogActionCallback()"
   [confirmButtonClickAction]="buildDeleteAccountActionCallback()"
diff --git a/src/app/components/shared/_dialogs/topic-cloud-confirm-dialog/topic-cloud-confirm-dialog.component.ts b/src/app/components/shared/_dialogs/topic-cloud-confirm-dialog/topic-cloud-confirm-dialog.component.ts
index 6e76bd59c5372940dba3585d3d52e558cae2d159..54b69f1c9b18a8dfd2fa4c38d27d10dee3120067 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-confirm-dialog/topic-cloud-confirm-dialog.component.ts
+++ b/src/app/components/shared/_dialogs/topic-cloud-confirm-dialog/topic-cloud-confirm-dialog.component.ts
@@ -1,7 +1,6 @@
-import { Component, Inject, OnInit } from '@angular/core';
+import { Component, Inject, Input, OnInit } from '@angular/core';
 import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
 import { DialogConfirmActionButtonType } from '../../dialog/dialog-action-buttons/dialog-action-buttons.component';
-import { TranslateService } from '@ngx-translate/core';
 
 @Component({
   selector: 'app-topic-cloud-confirm-dialog',
@@ -11,10 +10,9 @@ import { TranslateService } from '@ngx-translate/core';
 export class TopicCloudConfirmDialogComponent implements OnInit {
 
   confirmButtonType: DialogConfirmActionButtonType = DialogConfirmActionButtonType.Alert;
-
+  confirmLabel = this.data.confirmLabel;
   constructor(
     public confirmDialogRef: MatDialogRef<TopicCloudConfirmDialogComponent>,
-    private translationService: TranslateService,
     @Inject(MAT_DIALOG_DATA) public data: DialogData) { }
 
   ngOnInit(): void {
@@ -39,10 +37,12 @@ export class TopicCloudConfirmDialogComponent implements OnInit {
    * Returns a lambda which executes the dialog dedicated action on call.
    */
   buildDeleteAccountActionCallback(): () => void {
-    return () => this.close('delete');
+    return () => this.close(this.data.confirmLabel);
   }
 }
 
 export interface DialogData {
   topic: string;
+  message: string;
+  confirmLabel: string;
 }
diff --git a/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.html b/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.html
index fdf95e7f172a29c2b8cefd8726b737e60b8d8500..f5e3f893c2d878a85eafe33baf9ad06610279ed7 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.html
+++ b/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.html
@@ -1,21 +1,105 @@
-<div mat-dialog-content>
-  <p>{{'content.topic-cloud-content' | translate}}</p>
-</div>
-
-<mat-divider></mat-divider>
-  <mat-radio-group [(ngModel)]="continueFilter" aria-label="Select an option">
-    <mat-radio-button value="continueWithAll">{{'content.continue-with-all-questions' | translate}}</mat-radio-button>
-    <mat-radio-button checked="true" value="continueWithCurr">{{'content.continue-with-current-questions' | translate}}</mat-radio-button>
-    <mat-radio-button value="continueWithAllFromNow">{{'content.continue-with-all-questions-from-now' | translate}}</mat-radio-button>
+<mat-dialog-content>
+
+  <h3>{{'content.tag-cloud-questions-title' | translate}}</h3>
+
+  <span *ngIf="isTopicRequirementActive">
+    <mat-icon [inline]="true"
+              style="color: var(--red) !important;">warning</mat-icon>
+    {{'header.overview-admin-config-enabled' | translate}}
+  </span>
+
+  <mat-radio-group [(ngModel)]="continueFilter"
+                   aria-label="Select an option">
+    <mat-radio-button checked="true"
+                      value="continueWithAll">
+      <div class="elementRow">
+        <div class="elementText"
+             *ngIf="isMobile()">{{'content.tag-cloud-questions-all-short' | translate}}</div>
+        <div class="elementText"
+             *ngIf="!isMobile()">{{'content.tag-cloud-questions-all' | translate}}</div>
+        <div class="elementIcons"
+             *ngIf="allComments">
+          <mat-icon [inline]="true"
+                    matTooltip="{{'header.overview-question-tooltip' | translate}}">comment
+          </mat-icon>
+          {{allComments.comments}}
+          <mat-icon [inline]="true"
+                    matTooltip="{{'header.overview-questioners-tooltip' | translate}}">person
+          </mat-icon>
+          {{allComments.users}}
+          <mat-icon svgIcon="hashtag"
+                    class="comment_tag-icon"
+                    matTooltip="{{'header.overview-keywords-tooltip' | translate}}"></mat-icon>
+          {{allComments.keywords}}
+        </div>
+      </div>
+    </mat-radio-button>
+    <mat-radio-button value="continueWithCurr"
+                      *ngIf="!disableCurrentFiltersOptions">
+      <div class="elementRow">
+        <div class="elementText">{{'content.tag-cloud-questions-current-filtered' | translate}}</div>
+        <div class="elementIcons"
+             *ngIf="filteredComments">
+          <mat-icon [inline]="true"
+                    matTooltip="{{'header.overview-question-tooltip' | translate}}">comment
+          </mat-icon>
+          {{filteredComments.comments}}
+          <mat-icon [inline]="true"
+                    matTooltip="{{'header.overview-questioners-tooltip' | translate}}">person
+          </mat-icon>
+          {{filteredComments.users}}
+          <mat-icon svgIcon="hashtag"
+                    class="comment_tag-icon"
+                    matTooltip="{{'header.overview-keywords-tooltip' | translate}}"></mat-icon>
+          {{filteredComments.keywords}}
+        </div>
+      </div>
+    </mat-radio-button>
+    <mat-radio-button #radioButton
+                      value="continueWithAllFromNow">
+      <span *ngIf="isMobile()">{{'content.tag-cloud-questions-brainstorming-short' | translate}}</span>
+      <span *ngIf="!isMobile()">{{'content.tag-cloud-questions-brainstorming' | translate}}</span>
+    </mat-radio-button>
+    <mat-form-field *ngIf="user && user.role > 0 && radioButton.checked"
+                    appearance="fill">
+      <mat-label>{{'content.brainstorming-question' | translate}}</mat-label>
+      <input matInput
+             autofocus
+             autocomplete="off"
+             type="text"
+             (keyup)="checkForEnter($event)"
+             [(ngModel)]="question">
+      <button *ngIf="question"
+              matSuffix
+              mat-icon-button
+              aria-label="Clear"
+              (click)="question=''">
+        <mat-icon>close</mat-icon>
+      </button>
+    </mat-form-field>
   </mat-radio-group>
 
+  <mat-card *ngIf="user && user.role > 0 && hasNoKeywords"
+            class="noKeywords">
+    <p>{{'topic-cloud-filter.info-no-keywords' | translate}}</p>
+    <button mat-flat-button
+            type="button"
+            class="mat-flat-button secondary-confirm-button"
+            (click)="onKeywordRefreshClick()">
+      {{'topic-cloud-filter.label-refresh-keywords-start' | translate}}
+    </button>
+  </mat-card>
+
+  <app-worker-dialog [inlined]="true"
+                     *ngIf="user && user.role > 0"></app-worker-dialog>
 
-<app-dialog-action-buttons
-  buttonsLabelSection="content"
-  confirmButtonLabel="continue"
-  buttonIcon="cloud"
+  <app-dialog-action-buttons
+    buttonsLabelSection="content"
+    confirmButtonLabel="tag-cloud-create"
+    buttonIcon="cloud"
 
-  [cancelButtonClickAction]="cancelButtonActionCallback()"
-  [confirmButtonClickAction]="confirmButtonActionCallback()">
-</app-dialog-action-buttons>
+    [cancelButtonClickAction]="cancelButtonActionCallback()"
+    [confirmButtonClickAction]="confirmButtonActionCallback()">
+  </app-dialog-action-buttons>
 
+</mat-dialog-content>
diff --git a/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.scss b/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.scss
index d0f639b53f2a3aaebcca5c9dd5c1ae7f22d83027..35e221f156f660e8d1ddc7cf4d6ef276e7bc4746 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.scss
+++ b/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.scss
@@ -1,12 +1,51 @@
-mat-radio-button{
+mat-radio-button {
     margin: 5px;
+}
+
+mat-radio-group {
+  display: flex;
+  flex-direction: column;
+}
 
+::ng-deep .mat-radio-label-content {
+  width: 100%;
 }
 
+::ng-deep mat-form-field > .mat-form-field-wrapper {
+  margin-bottom: -1.34375em;
+}
 
+.elementRow {
+  display: flex;
+  flex-direction: row;
+  width: 100% !important;
+}
 
-mat-radio-group {
-    display: flex;
-  flex-direction: column;
-  margin: 15px 0;
-}
\ No newline at end of file
+.elementText {
+  align-content: flex-start;
+  margin-right: 10px;
+}
+
+.elementIcons {
+  margin-left: auto;
+}
+
+.comment_tag-icon {
+  height: 18px !important;
+}
+
+.mat-dialog-content {
+  padding: 0px 15px;
+  margin: 0;
+}
+
+.noKeywords {
+  background: var(--surface);
+  color: var(--on-surface);
+  margin-top: 20px;
+}
+
+.secondary-confirm-button {
+  background-color: var(--secondary);
+  color: var(--on-secondary);
+}
diff --git a/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.ts b/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.ts
index 12f4ba73bb0dd23a573125fc061ca13bab06090e..769f5d25a10dbe4577d94428659968d12477551c 100644
--- a/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.ts
+++ b/src/app/components/shared/_dialogs/topic-cloud-filter/topic-cloud-filter.component.ts
@@ -1,73 +1,178 @@
-import { Component, Inject, OnInit, ViewChild, ElementRef, Input } from '@angular/core';
+import { Component, Inject, Input, OnInit } from '@angular/core';
 import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
 import { NotificationService } from '../../../../services/util/notification.service';
 import { TranslateService } from '@ngx-translate/core';
 import { RoomCreatorPageComponent } from '../../../creator/room-creator-page/room-creator-page.component';
 import { LanguageService } from '../../../../services/util/language.service';
 import { EventService } from '../../../../services/util/event.service';
-import {Router} from '@angular/router';
+import { Router } from '@angular/router';
+import { CommentFilter, Period } from '../../../../utils/filter-options';
+import { RoomService } from '../../../../services/http/room.service';
+import { Comment } from '../../../../models/comment';
+import { CommentListData } from '../../comment-list/comment-list.component';
+import { TopicCloudAdminService } from '../../../../services/util/topic-cloud-admin.service';
+import { KeywordOrFulltext, TopicCloudAdminData } from '../topic-cloud-administration/TopicCloudAdminData';
+import { TagCloudDataService } from '../../../../services/util/tag-cloud-data.service';
+import { User } from '../../../../models/user';
+import { WorkerDialogComponent } from '../worker-dialog/worker-dialog.component';
+import { Room } from '../../../../models/room';
+import { CloudParameters } from '../../../../utils/cloud-parameters';
+import { ThemeService } from '../../../../../theme/theme.service';
+import { Theme } from '../../../../../theme/Theme';
+
+class CommentsCount {
+  comments: number;
+  users: number;
+  keywords: number;
+}
+
+enum KeywordsSource {
+  fromUser = 'fromUser',
+  fromSpacy = 'fromSpacy',
+  all = 'all'
+}
 
 @Component({
   selector: 'app-topic-cloud-filter',
   templateUrl: './topic-cloud-filter.component.html',
   styleUrls: ['./topic-cloud-filter.component.scss']
 })
-export class TopicCloudFilterComponent implements OnInit{
-  @Input()filteredComments: any;
-  @Input()commentsFilteredByTime: any;
+export class TopicCloudFilterComponent implements OnInit {
+  @Input() target: string;
+  @Input() user: User;
 
-  continueFilter: string = 'continueWithCurr';
-  tmpCurFilters: string;
-  tmpPeriod : string;
+  question = '';
+  continueFilter = 'continueWithAll';
+  comments: Comment[];
+  tmpFilter: CommentFilter;
+  allComments: CommentsCount;
+  filteredComments: CommentsCount;
+  disableCurrentFiltersOptions = false;
+  isTopicRequirementActive = false;
+  hasNoKeywords = false;
+  private readonly _adminData: TopicCloudAdminData;
+  private _room: Room;
+  private currentTheme: Theme;
 
   constructor(public dialogRef: MatDialogRef<RoomCreatorPageComponent>,
-    public dialog: MatDialog,
-    public notificationService: NotificationService,
-    public translationService: TranslateService,
-    protected langService: LanguageService,
-    private router: Router,
-    @Inject(MAT_DIALOG_DATA) public data: any,
-    public eventService: EventService) {
-      langService.langEmitter.subscribe(lang => translationService.use(lang));
+              public dialog: MatDialog,
+              public notificationService: NotificationService,
+              public translationService: TranslateService,
+              protected langService: LanguageService,
+              private router: Router,
+              protected roomService: RoomService,
+              @Inject(MAT_DIALOG_DATA) public data: any,
+              public eventService: EventService,
+              private topicCloudAdminService: TopicCloudAdminService,
+              private themeService: ThemeService) {
+    langService.langEmitter.subscribe(lang => translationService.use(lang));
+    this._adminData = TopicCloudAdminService.getDefaultAdminData;
+    this.isTopicRequirementActive = !TopicCloudAdminService.isTopicRequirementDisabled(this._adminData);
   }
 
   ngOnInit() {
+    this.themeService.getTheme().subscribe((themeName) => {
+      this.currentTheme = this.themeService.getThemeByKey(themeName);
+    });
     this.translationService.use(localStorage.getItem('currentLang'));
-    this.tmpPeriod = localStorage.getItem('currentPeriod');
-    this.tmpCurFilters = localStorage.getItem('currentFilters');
+    const subscriptionEventService = this.eventService.on<CommentListData>('currentRoomData').subscribe(data => {
+      subscriptionEventService.unsubscribe();
+      this.comments = data.comments;
+      this.tmpFilter = data.currentFilter;
+      this._room = data.room;
+      this.allComments = this.getCommentCounts(this.comments);
+      this.filteredComments = this.getCommentCounts(this.comments.filter(comment => this.tmpFilter.checkComment(comment)));
+      this.commentsLoadedCallback();
+      this.hasNoKeywords = this.isUpdatable();
+    });
+    this.eventService.broadcast('pushCurrentRoomData');
+  }
+
+  commentsLoadedCallback() {
+    this.disableCurrentFiltersOptions = ((this.allComments.comments === this.filteredComments.comments) &&
+      (this.allComments.users === this.filteredComments.users) &&
+      (this.allComments.keywords === this.filteredComments.keywords));
+
+    if (this.disableCurrentFiltersOptions) {
+      this.continueFilter = 'continueWithAll';
+    }
+  }
+
+  isMobile(): boolean {
+    return window.matchMedia('(max-width:500px)').matches;
+  }
+
+  onKeywordRefreshClick() {
+    this.hasNoKeywords = false;
+    WorkerDialogComponent.addWorkTask(this.dialog, this._room);
   }
 
-  closeDialog(): void {
+  getCommentCounts(comments: Comment[]): CommentsCount {
+    const [data, users] = TagCloudDataService.buildDataFromComments(this._adminData, comments);
+    const counts = new CommentsCount();
+    counts.comments = comments.length;
+    counts.users = users.size;
+    counts.keywords = data.size;
+    return counts;
   }
 
-  
   cancelButtonActionCallback(): () => void {
     return () => this.dialogRef.close('abort');
   }
 
-  confirmButtonActionCallback(): () => void {
-    localStorage.setItem('currentFilters', this.tmpCurFilters);
-    localStorage.setItem('currentPeriod', this.tmpPeriod);
-    localStorage.setItem('currentFromNowTimestamp', JSON.stringify(null)); 
-    switch (this.continueFilter) {
-      case 'continueWithAll':
-        localStorage.setItem('currentFilters', JSON.stringify(""));
-        break;
-
-      case 'continueWithCurr':
-        // filter set already
-        break;
-
-      case 'continueWithAllFromNow':
-        localStorage.setItem('currentFilters', JSON.stringify(""));
-        localStorage.setItem('currentPeriod', JSON.stringify('from-now'));
-        localStorage.setItem('currentFromNowTimestamp', JSON.stringify(new Date().getTime())); 
-        break;
-
-      default:
-        break;
+  confirmButtonActionCallback() {
+    return () => {
+      let filter: CommentFilter;
+
+      switch (this.continueFilter) {
+        case 'continueWithAll':
+          // all questions allowed
+          filter = new CommentFilter();
+          filter.periodSet = Period.all;
+          break;
+
+        case 'continueWithAllFromNow':
+          filter = CommentFilter.generateFilterNow(this.tmpFilter.filterSelected);
+          break;
+
+        case 'continueWithCurr':
+          filter = this.tmpFilter;
+          break;
+
+        default:
+          return;
+      }
+
+      localStorage.setItem('tag-cloud-question', this.question);
+
+      CommentFilter.currentFilter = filter;
+
+      this.dialogRef.close(this.router.navigateByUrl(this.target));
+    };
+  }
+
+  checkForEnter(e: KeyboardEvent) {
+    if (e.key === 'Enter') {
+      this.confirmButtonActionCallback()();
     }
+  }
 
-    return () => this.dialogRef.close(this.router.navigateByUrl('/participant/room/' + localStorage.getItem('roomId') + '/comments/tagcloud'));
+  private isUpdatable(): boolean {
+    if (this.comments.length < 3) {
+      return false;
+    }
+    let count = 0;
+    let newCount = 0;
+    this.comments.forEach(comment => {
+      if (comment.keywordsFromSpacy && comment.keywordsFromSpacy.length) {
+        newCount++;
+      } else {
+        count++;
+      }
+    });
+    if (count * 2 / 3 < newCount) {
+      return false;
+    }
+    return !WorkerDialogComponent.isWorkingOnRoom(this._room.id);
   }
 }
diff --git a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog-task.ts b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog-task.ts
new file mode 100644
index 0000000000000000000000000000000000000000..62091d33b420a05ab2019fe8f60496aa458abd53
--- /dev/null
+++ b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog-task.ts
@@ -0,0 +1,111 @@
+import { Room } from '../../../../models/room';
+import { SpacyKeyword, SpacyService } from '../../../../services/http/spacy.service';
+import { CommentService } from '../../../../services/http/comment.service';
+import { Comment, Language } from '../../../../models/comment';
+import { Language as Lang, LanguagetoolService } from '../../../../services/http/languagetool.service';
+import { CreateCommentKeywords } from '../../../../utils/create-comment-keywords';
+import { TSMap } from 'typescript-map';
+import { HttpErrorResponse } from '@angular/common/http';
+import { CURRENT_SUPPORTED_LANGUAGES, Model } from '../../../../services/http/spacy.interface';
+
+const concurrentCallsPerTask = 4;
+
+enum FinishType {
+  completed,
+  badSpelled,
+  failed
+}
+
+export class WorkerDialogTask {
+
+  error: string = null;
+  readonly statistics = {
+    succeeded: 0,
+    badSpelled: 0,
+    failed: 0,
+    length: 0
+  };
+  private readonly _comments: Comment[] = null;
+  private readonly _running: boolean[] = null;
+
+  constructor(public readonly room: Room,
+              private comments: Comment[],
+              private spacyService: SpacyService,
+              private commentService: CommentService,
+              private languagetoolService: LanguagetoolService,
+              private finished: () => void) {
+    this._comments = comments;
+    this.statistics.length = comments.length;
+    this._running = new Array(concurrentCallsPerTask);
+    for (let i = 0; i < concurrentCallsPerTask; i++) {
+      this._running[i] = true;
+      this.callSpacy(i);
+    }
+  }
+
+  isRunning(): boolean {
+    return this._running.some(e => e === true);
+  }
+
+  private callSpacy(currentIndex: number) {
+    if (this.error || currentIndex >= this._comments.length) {
+      this._running[currentIndex % concurrentCallsPerTask] = false;
+      if (this._running.every(e => e === false)) {
+        if (this.finished) {
+          this.finished();
+          this.finished = null;
+        }
+      }
+      return;
+    }
+    const currentComment = this._comments[currentIndex];
+    CreateCommentKeywords.isSpellingAcceptable(this.languagetoolService, currentComment.body)
+      .subscribe(result => {
+        if (!result.isAcceptable) {
+          this.finishSpacyCall(FinishType.badSpelled, currentIndex);
+          return;
+        }
+        const commentModel = currentComment.language.toLowerCase();
+        const model = commentModel !== 'auto' ? commentModel.toLowerCase() as Model :
+          this.languagetoolService.mapLanguageToSpacyModel(result.result.language.detectedLanguage.code as Lang);
+        if (model === 'auto' || !CURRENT_SUPPORTED_LANGUAGES.includes(model)) {
+          this.finishSpacyCall(FinishType.badSpelled, currentIndex);
+          return;
+        }
+        this.spacyService.getKeywords(result.text, model)
+          .subscribe(newKeywords =>
+              this.finishSpacyCall(FinishType.completed, currentIndex, newKeywords, model.toUpperCase() as Language),
+            __ => this.finishSpacyCall(FinishType.failed, currentIndex));
+      }, _ => this.finishSpacyCall(FinishType.failed, currentIndex));
+  }
+
+  private finishSpacyCall(finishType: FinishType, index: number, tags?: SpacyKeyword[], lang?: Language): void {
+    if (finishType === FinishType.completed) {
+      this.patchToServer(tags, index, lang);
+    } else if (finishType === FinishType.badSpelled) {
+      this.statistics.badSpelled++;
+      this.patchToServer([], index, Language.auto);
+    } else {
+      this.statistics.failed++;
+      this.callSpacy(index + concurrentCallsPerTask);
+    }
+  }
+
+  private patchToServer(tags: SpacyKeyword[], index: number, language: Language) {
+    const changes = new TSMap<string, string>();
+    changes.set('keywordsFromSpacy', JSON.stringify(tags));
+    changes.set('language', language);
+    this.commentService.patchComment(this._comments[index], changes).subscribe(_ => {
+        this.statistics.succeeded++;
+        this.callSpacy(index + concurrentCallsPerTask);
+      },
+      patchError => {
+        this.statistics.failed++;
+        if (patchError instanceof HttpErrorResponse && patchError.status === 403) {
+          this.error = 'forbidden';
+        }
+        this.callSpacy(index + concurrentCallsPerTask);
+      });
+  }
+
+}
diff --git a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.html b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..903b48527d99e397f0ff4af13334ada42f319bd1
--- /dev/null
+++ b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.html
@@ -0,0 +1,65 @@
+<div id="worker-content">
+  <div id="header" (window:beforeunload)="checkTasks($event)">
+    <details *ngIf="!inlined">
+      <summary>
+        <span>{{'worker-dialog.running' | translate}} # {{getActiveRoomCount()}}</span>
+        <span><button id="btn_hide" (click)="close()">x</button></span>
+      </summary>
+      <div mat-dialog-content>
+        <div class="entry" *ngFor="let task of getRooms().values()">
+          <div class="entryRow">
+            <mat-icon svgIcon="meeting_room" matTooltip="{{'worker-dialog.room-name' | translate}}"></mat-icon>
+            <span>{{ task.room.name }}</span>
+            <span *ngIf="task.error" style="color: var(--red)">{{task.error}}</span>
+          </div>
+          <div *ngIf="!task.error" class="entryRow">
+            <mat-icon matTooltip="{{'worker-dialog.comments' | translate}}">comment</mat-icon>
+            <span>{{task.statistics.succeeded}}/{{ task.statistics.length}}</span>
+            <mat-icon *ngIf="task.statistics.badSpelled" style="color: darkorange"
+                      matTooltip="{{'worker-dialog.bad-spelled' | translate}}">warning
+            </mat-icon>
+            <span *ngIf="task.statistics.badSpelled">
+              {{task.statistics.badSpelled}}
+            </span>
+          </div>
+          <div *ngIf="!task.error && task.statistics.failed" class="entryRow">
+            <mat-icon style="color: var(--red)"
+                      matTooltip="{{'worker-dialog.failed' | translate}}">error
+            </mat-icon>
+            <span>
+              {{task.statistics.failed}}
+            </span>
+          </div>
+        </div>
+      </div>
+    </details>
+    <div mat-dialog-content style="padding-top: 0.75em;" *ngIf="inlined">
+      <h4 *ngIf="getRooms().length">{{'worker-dialog.inline-header' | translate}} ({{getActiveRoomCount()}}):</h4>
+      <div class="entry" *ngFor="let task of getRooms().values()">
+        <div class="entryRow">
+          <mat-icon svgIcon="meeting_room" matTooltip="{{'worker-dialog.room-name' | translate}}"></mat-icon>
+          <span>{{ task.room.name }}</span>
+          <span *ngIf="task.error" style="color: var(--red)">{{task.error}}</span>
+        </div>
+        <div *ngIf="!task.error" class="entryRow">
+          <mat-icon matTooltip="{{'worker-dialog.comments' | translate}}">comment</mat-icon>
+          <span>{{task.statistics.succeeded}}/{{ task.statistics.length}}</span>
+          <mat-icon *ngIf="task.statistics.badSpelled" style="color: darkorange"
+                    matTooltip="{{'worker-dialog.bad-spelled' | translate}}">warning
+          </mat-icon>
+          <span *ngIf="task.statistics.badSpelled">
+              {{task.statistics.badSpelled}}
+            </span>
+        </div>
+        <div *ngIf="!task.error && task.statistics.failed" class="entryRow">
+          <mat-icon style="color: var(--red)"
+                    matTooltip="{{'worker-dialog.failed' | translate}}">error
+          </mat-icon>
+          <span>
+              {{task.statistics.failed}}
+            </span>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.scss b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..fdffcf6b3acca7c2570e4e0ea73b7f249d882390
--- /dev/null
+++ b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.scss
@@ -0,0 +1,71 @@
+button {
+  position: absolute;
+  top: 3px;
+  right: 3px;
+  font-weight: bold;
+  background: none;
+  outline: none;
+  border: none;
+  font-size: large;
+  vertical-align: middle;
+  cursor: pointer;
+}
+
+::ng-deep .workerContainer > .mat-dialog-container {
+  padding: 5px !important;
+  box-shadow: 0 2px 1px -1px rgba(0, 0, 0, .2), 0 1px 1px 0 rgba(0, 0, 0, .14), 0 1px 3px 0 rgba(0, 0, 0, .12), -4px 0 0 0 var(--primary);
+  overflow: hidden !important;
+  position: relative !important;
+}
+
+#worker-content {
+  padding-left: 5px;
+
+  .mat-dialog-content {
+    margin: 0;
+    padding: 0;
+  }
+}
+
+.entry {
+  display: flex;
+  flex-direction: column;
+  justify-content: left;
+  border-bottom: var(--primary) dashed 2px;
+  margin-bottom: 3px;
+  padding-bottom: 3px;
+}
+
+.entryRow {
+  display: flex;
+  flex-direction: row;
+  justify-content: left;
+  align-items: center;
+}
+
+span, mat-icon {
+  margin-right: 7px;
+}
+
+details > summary {
+  border: none;
+  outline: none;
+  cursor: pointer;
+}
+
+details[open] > summary {
+  box-shadow: 0 4px 4px -2px #232323;
+  margin-bottom: 7px;
+}
+
+::ng-deep .noKeywords {
+  color: var(--on-surface);
+  background: var(--surface);
+  margin: 0.75em;
+
+  > button {
+    color: var(--on-primary);
+    background: var(--primary);
+    margin-left: 1em;
+  }
+}
diff --git a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.spec.ts b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..650d036a9c0941d90bc163f29cb475c4c543bd63
--- /dev/null
+++ b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.spec.ts
@@ -0,0 +1,25 @@
+/*import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { WorkerDialogComponent } from './worker-dialog.component';
+
+describe('WorkerDialogComponent', () => {
+  let component: WorkerDialogComponent;
+  let fixture: ComponentFixture<WorkerDialogComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ WorkerDialogComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(WorkerDialogComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});*/
diff --git a/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.ts b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f17042906d79db9bed8a98479a4a59b52fe8bd2c
--- /dev/null
+++ b/src/app/components/shared/_dialogs/worker-dialog/worker-dialog.component.ts
@@ -0,0 +1,114 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { Room } from '../../../../models/room';
+import { CommentService } from '../../../../services/http/comment.service';
+import { SpacyService } from '../../../../services/http/spacy.service';
+import { TSMap } from 'typescript-map';
+import { MatDialog, MatDialogRef } from '@angular/material/dialog';
+import { WorkerDialogTask } from './worker-dialog-task';
+import { LanguagetoolService } from '../../../../services/http/languagetool.service';
+import { TranslateService } from '@ngx-translate/core';
+import { LanguageService } from '../../../../services/util/language.service';
+import { Comment } from '../../../../models/comment';
+import { RoomDataService } from '../../../../services/util/room-data.service';
+
+@Component({
+  selector: 'app-worker-dialog',
+  templateUrl: './worker-dialog.component.html',
+  styleUrls: ['./worker-dialog.component.scss']
+})
+export class WorkerDialogComponent implements OnInit {
+
+  private static dialogRef: MatDialogRef<WorkerDialogComponent> = null;
+  private static queuedRooms = new TSMap<string, WorkerDialogTask>();
+
+  @Input() inlined = false;
+
+  constructor(private commentService: CommentService,
+              private languagetoolService: LanguagetoolService,
+              private spacyService: SpacyService,
+              protected langService: LanguageService,
+              private translateService: TranslateService,
+              private roomDataService: RoomDataService) {
+    langService.langEmitter.subscribe(lang => translateService.use(lang));
+  }
+
+  static isWorkingOnRoom(roomId: string) {
+    if (!this.dialogRef) {
+      return false;
+    }
+    return this.queuedRooms.has(roomId);
+  }
+
+  static addWorkTask(dialog: MatDialog, room: Room): boolean {
+    if (!this.dialogRef) {
+      this.dialogRef = dialog.open(WorkerDialogComponent, {
+        width: '200px',
+        disableClose: true,
+        autoFocus: false,
+        position: { left: '50px', bottom: '50px' },
+        role: 'dialog',
+        hasBackdrop: false,
+        closeOnNavigation: false,
+        panelClass: 'workerContainer'
+      });
+      this.dialogRef.beforeClosed().subscribe(_ => {
+        for (const value of WorkerDialogComponent.queuedRooms.values()) {
+          value.error = 'interrupt';
+        }
+        WorkerDialogComponent.queuedRooms.clear();
+      });
+    }
+    if (this.queuedRooms.has(room.id)) {
+      return false;
+    }
+    this.dialogRef.componentInstance.appendRoom(room, this.dialogRef.componentInstance.roomDataService.currentRoomData);
+    return true;
+  }
+
+  ngOnInit(): void {
+    this.translateService.use(localStorage.getItem('currentLang'));
+  }
+
+  checkTasks(event: BeforeUnloadEvent) {
+    if (WorkerDialogComponent.queuedRooms.length > 0) {
+      event.preventDefault();
+      event.returnValue = '';
+    }
+  }
+
+  getRooms() {
+    return WorkerDialogComponent.queuedRooms;
+  }
+
+  getActiveRoomCount(): number {
+    let count = 0;
+    WorkerDialogComponent.queuedRooms.values().forEach(e => {
+      if (e.isRunning()) {
+        ++count;
+      }
+    });
+    return count;
+  }
+
+  appendRoom(room: Room, comments: Comment[]) {
+    WorkerDialogComponent.queuedRooms.set(room.id,
+      new WorkerDialogTask(room, comments, this.spacyService, this.commentService, this.languagetoolService, () => {
+        setTimeout(() => {
+          WorkerDialogComponent.queuedRooms.delete(room.id);
+          if (WorkerDialogComponent.queuedRooms.length === 0) {
+            this.close();
+          }
+        }, 10_000);
+      })
+    );
+  }
+
+  close(): void {
+    if (WorkerDialogComponent.dialogRef) {
+      WorkerDialogComponent.dialogRef.close();
+      WorkerDialogComponent.dialogRef = null;
+    }
+  }
+
+}
+
diff --git a/src/app/components/shared/comment-answer/comment-answer.component.html b/src/app/components/shared/comment-answer/comment-answer.component.html
index fdd4f031a9a4786508e2311f34e51e3ff401bfb8..8d133d0083abd17604e4bf9a2321dae7c941ea58 100644
--- a/src/app/components/shared/comment-answer/comment-answer.component.html
+++ b/src/app/components/shared/comment-answer/comment-answer.component.html
@@ -10,64 +10,31 @@
        fxLayoutAlign="center">
     <mat-card class="answer border-answer"
               *ngIf="!isStudent || answer">
-      <div *ngIf="(isStudent || !edit) && answer">
-        <markdown [data]="answer"></markdown>
-        <div fxLayout="row"
-             fxLayoutAlign="end">
-          <button mat-raised-button
-                  *ngIf="!isStudent && !edit"
-                  class="save"
-                  (click)="edit = true">
-            <mat-icon>edit</mat-icon>
-            {{'comment-page.edit-answer' | translate}}
-          </button>
-        </div>
-      </div>
-      <mat-tab-group *ngIf="!isStudent && (edit || !answer)"
-                     [dynamicHeight]="false">
-        <mat-tab label="{{'comment-page.your-answer' | translate}}">
-          <mat-form-field class="input-block">
-            <textarea [(ngModel)]="answer"
-                      (input)="edit = true"
-                      (keyup)="$event.cancelBubble=true"
-                      matInput
-                      matTextareaAutosize
-                      matAutosizeMinRows="3"
-                      matAutosizeMaxRows="10"
-                      maxlength="2000"
-                      name="answer"
-                      autofocus>
-            </textarea>
-            <mat-hint align="start">
-              <span aria-hidden="true">
-                {{ 'comment-page.Markdown-hint' | translate }}
-              </span>
-            </mat-hint>
-            <mat-hint align="end">
-            <span aria-hidden="true">
-              {{ answer ? answer.length : 0 }} / 2000
-            </span>
-            </mat-hint>
-          </mat-form-field>
-        </mat-tab>
-        <mat-tab label="{{'session.preview' | translate}}"
-                 [disabled]="!answer">
-          <markdown [data]="answer"></markdown>
-        </mat-tab>
-      </mat-tab-group>
-      <div fxLayout="row"
-           fxLayoutAlign="end">
-        <button mat-raised-button
-                *ngIf="!isStudent && answer && edit"
-                class="delete"
-                (click)="openDeleteAnswerDialog()">
-          {{'comment-page.delete-answer' | translate}}</button>
-        <button mat-raised-button
-                *ngIf="!isStudent && (edit || !answer)"
-                class="save"
-                (click)="saveAnswer()">
-          {{'comment-page.save-answer' | translate}}</button>
-      </div>
+      <app-write-comment [user]="user"
+                         [onClose]="openDeleteAnswerDialog()"
+                         [onSubmit]="saveAnswer()"
+                         [disableCancelButton]="!answer && commentComponent && commentComponent.commentBody && !commentComponent.commentBody.nativeElement.innerText"
+                         [confirmLabel]="'save-answer'"
+                         [cancelLabel]="'delete-answer'"
+                         [additionalTemplate]="editAnswer"
+                         [enabled]="!isStudent && (edit || !answer)">
+      </app-write-comment>
     </mat-card>
   </div>
 </div>
+
+<ng-template #editAnswer>
+  <div *ngIf="(isStudent || !edit) && answer">
+    <app-custom-markdown class="imborder-answerages" [data]="answer"></app-custom-markdown>
+    <div fxLayout="row"
+         fxLayoutAlign="end">
+      <button mat-raised-button
+              *ngIf="!isStudent && !edit"
+              class="save"
+              (click)="onEditClick()">
+        <mat-icon>edit</mat-icon>
+        {{'comment-page.edit-answer' | translate}}
+      </button>
+    </div>
+  </div>
+</ng-template>
diff --git a/src/app/components/shared/comment-answer/comment-answer.component.scss b/src/app/components/shared/comment-answer/comment-answer.component.scss
index b87b500b6b06a4fe23dc4d3fdb661110396419cb..17448b00544cb65fb8212e99b507b783ed8596e4 100644
--- a/src/app/components/shared/comment-answer/comment-answer.component.scss
+++ b/src/app/components/shared/comment-answer/comment-answer.component.scss
@@ -29,12 +29,6 @@ button {
   margin-right: 1%;
 }
 
-.delete {
-  background-color: var(--red);
-  color: var(--white);
-  margin-right: 20px;
-}
-
 mat-icon {
   font-size: 18px;
   height: 18px;
diff --git a/src/app/components/shared/comment-answer/comment-answer.component.ts b/src/app/components/shared/comment-answer/comment-answer.component.ts
index 536bfb9d238f0dacf6a2bb7bd9ac9dea554b5e8b..d1a60c5a615a446c9e357e2e5e58b4ffc6623752 100644
--- a/src/app/components/shared/comment-answer/comment-answer.component.ts
+++ b/src/app/components/shared/comment-answer/comment-answer.component.ts
@@ -1,8 +1,8 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, ViewChild } from '@angular/core';
 import { ActivatedRoute } from '@angular/router';
 import { TranslateService } from '@ngx-translate/core';
 import { LanguageService } from '../../../services/util/language.service';
-import { WsCommentServiceService } from '../../../services/websockets/ws-comment-service.service';
+import { WsCommentService } from '../../../services/websockets/ws-comment.service';
 import { CommentService } from '../../../services/http/comment.service';
 import { Comment } from '../../../models/comment';
 import { User } from '../../../models/user';
@@ -11,6 +11,9 @@ import { UserRole } from '../../../models/user-roles.enum';
 import { NotificationService } from '../../../services/util/notification.service';
 import { MatDialog } from '@angular/material/dialog';
 import { DeleteAnswerComponent } from '../../creator/_dialogs/delete-answer/delete-answer.component';
+import { LanguagetoolService } from '../../../services/http/languagetool.service';
+import { EventService } from '../../../services/util/event.service';
+import { WriteCommentComponent } from '../write-comment/write-comment.component';
 
 @Component({
   selector: 'app-comment-answer',
@@ -19,6 +22,8 @@ import { DeleteAnswerComponent } from '../../creator/_dialogs/delete-answer/dele
 })
 export class CommentAnswerComponent implements OnInit {
 
+  @ViewChild(WriteCommentComponent) commentComponent: WriteCommentComponent;
+
   comment: Comment;
   answer: string;
   isLoading = true;
@@ -30,10 +35,13 @@ export class CommentAnswerComponent implements OnInit {
               private notificationService: NotificationService,
               private translateService: TranslateService,
               protected langService: LanguageService,
-              protected wsCommentService: WsCommentServiceService,
+              protected wsCommentService: WsCommentService,
               protected commentService: CommentService,
               private authenticationService: AuthenticationService,
-              public dialog: MatDialog) { }
+              public languagetoolService: LanguagetoolService,
+              public dialog: MatDialog,
+              public eventService: EventService) {
+  }
 
   ngOnInit() {
     this.user = this.authenticationService.getUser();
@@ -44,36 +52,52 @@ export class CommentAnswerComponent implements OnInit {
       this.commentService.getComment(params['commentId']).subscribe(comment => {
         this.comment = comment;
         this.answer = this.comment.answer;
+        this.edit = !this.answer;
         this.isLoading = false;
       });
     });
   }
 
-  saveAnswer() {
-    this.edit = false;
-    this.commentService.answer(this.comment, this.answer).subscribe();
-    this.translateService.get('comment-page.comment-answered').subscribe(msg => {
-      this.notificationService.show(msg);
-    });
+  saveAnswer(): (string) => void {
+    return (text: string) => {
+      this.answer = text;
+      this.edit = !this.answer;
+      this.commentService.answer(this.comment, this.answer).subscribe();
+      this.translateService.get('comment-page.comment-answered').subscribe(msg => {
+        this.notificationService.show(msg);
+      });
+    };
   }
 
-  openDeleteAnswerDialog(): void {
-    const dialogRef = this.dialog.open(DeleteAnswerComponent, {
-      width: '400px'
-    });
-    dialogRef.afterClosed()
-      .subscribe(result => {
-        if (result === 'delete') {
-          this.deleteAnswer();
-        }
+  openDeleteAnswerDialog(): () => void {
+    return () => {
+      const dialogRef = this.dialog.open(DeleteAnswerComponent, {
+        width: '400px'
       });
+      dialogRef.afterClosed()
+        .subscribe(result => {
+          if (result === 'delete') {
+            this.deleteAnswer();
+          }
+        });
+    }
   }
 
   deleteAnswer() {
+    if (this.commentComponent.commentBody) {
+      this.commentComponent.commentBody.nativeElement.innerText = '';
+    }
     this.answer = null;
     this.commentService.answer(this.comment, this.answer).subscribe();
     this.translateService.get('comment-page.answer-deleted').subscribe(msg => {
       this.notificationService.show(msg);
     });
   }
+
+  onEditClick() {
+    this.edit = true;
+    setTimeout(() => {
+      this.commentComponent.commentBody.nativeElement.innerText = this.answer;
+    });
+  }
 }
diff --git a/src/app/components/shared/comment-list/comment-list.component.html b/src/app/components/shared/comment-list/comment-list.component.html
index 8bbfa8ae3c4911cc042a7b2c945b1d81c0f79fc4..0b41ad4d82e2674ab4c4d266e588d64433f87f85 100644
--- a/src/app/components/shared/comment-list/comment-list.component.html
+++ b/src/app/components/shared/comment-list/comment-list.component.html
@@ -3,6 +3,7 @@
      [ngClass]="{'search-container' : !scroll, 'search-container-fixed' : scroll}"
      (window:scroll)="checkScroll()"
      fxLayoutAlign="center">
+
   <button id="filter-close-button"
           mat-icon-button
           class="searchBarButton"
@@ -29,12 +30,16 @@
           mat-icon-button
           class="searchBarButton close red"
           *ngIf="searchInput !== '' || search"
-          (click)="hideCommentsList=false; searchInput = ''; search = false; searchPlaceholder = '';"
+          (click)="hideCommentsList=false; searchInput = ''; search = false;"
           aria-labelledby="close_search">
     <mat-icon>close</mat-icon>
   </button>
 
   <div class="button-bar"
+       [ngClass]="{'joyrideActive': isJoyrideActive}"
+       [joyrideStep]="'commentFilter'"
+       [stepPosition]="'bottom'"
+       appJoyrideTemplate
        fxLayoutAlign="center center">
     <div *ngIf="comments && commentsFilteredByTime.length > 0">
       <h3 class="counter"
@@ -153,7 +158,8 @@
         <mat-icon class="star"
                   [ngClass]="{favorite: 'favorite-icon'}[currentFilter]">grade
         </mat-icon>
-        <span [ngClass]="{favorite: 'favorite-icon'}[currentFilter]">{{ 'comment-list.filter-favorite' | translate }}</span>
+        <span
+          [ngClass]="{favorite: 'favorite-icon'}[currentFilter]">{{ 'comment-list.filter-favorite' | translate }}</span>
       </button>
 
       <button mat-menu-item
@@ -162,7 +168,8 @@
         <mat-icon class="bookmark"
                   [ngClass]="{bookmark: 'bookmark-icon'}[currentFilter]">bookmark
         </mat-icon>
-        <span [ngClass]="{bookmark: 'bookmark-icon'}[currentFilter]">{{ 'comment-list.filter-bookmark' | translate }}</span>
+        <span
+          [ngClass]="{bookmark: 'bookmark-icon'}[currentFilter]">{{ 'comment-list.filter-bookmark' | translate }}</span>
       </button>
 
       <button mat-menu-item
@@ -172,7 +179,8 @@
         <mat-icon class="answer"
                   [ngClass]="{answer: 'answered-icon'}[currentFilter]">comment
         </mat-icon>
-        <span [ngClass]="{answer: 'answered-icon'}[currentFilter]">{{ 'comment-list.filter-answered' | translate }}</span>
+        <span
+          [ngClass]="{answer: 'answered-icon'}[currentFilter]">{{ 'comment-list.filter-answered' | translate }}</span>
       </button>
 
       <button mat-menu-item
@@ -182,7 +190,8 @@
         <mat-icon class="unanswered"
                   [ngClass]="{unanswered: 'unanswered-icon'}[currentFilter]">comment
         </mat-icon>
-        <span [ngClass]="{unanswered: 'unanswered-icon'}[currentFilter]">{{ 'comment-list.filter-unanswered' | translate }}</span>
+        <span
+          [ngClass]="{unanswered: 'unanswered-icon'}[currentFilter]">{{ 'comment-list.filter-unanswered' | translate }}</span>
       </button>
 
       <button mat-menu-item
@@ -200,7 +209,8 @@
         <mat-icon class="lecturer"
                   [ngClass]="{lecturer: 'lecturer-icon'}[currentFilter]">school
         </mat-icon>
-        <span [ngClass]="{lecturer: 'lecturer-icon'}[currentFilter]">{{ 'comment-list.filter-lecturer' | translate }}</span>
+        <span
+          [ngClass]="{lecturer: 'lecturer-icon'}[currentFilter]">{{ 'comment-list.filter-lecturer' | translate }}</span>
       </button>
 
       <button mat-menu-item
@@ -209,7 +219,8 @@
         <mat-icon class="moderator"
                   [ngClass]="{moderator: 'moderator-icon'}[currentFilter]">gavel
         </mat-icon>
-        <span [ngClass]="{moderator: 'moderator-icon'}[currentFilter]">{{ 'comment-list.filter-moderator' | translate }}</span>
+        <span
+          [ngClass]="{moderator: 'moderator-icon'}[currentFilter]">{{ 'comment-list.filter-moderator' | translate }}</span>
       </button>
 
 
@@ -233,32 +244,48 @@
   <mat-icon>arrow_upward</mat-icon>
 </button>
 
-<button mat-fab
+<div id="createCommentJoyrideWrapper"
+     [joyrideStep]="'createQuestion'"
+     [stepPosition]="'center'"
+     appJoyrideTemplate>
+</div>
+
+<button *ngIf="commentsEnabled"
+        mat-fab
         mat-icon-button
         aria-labelledby="add"
         class="fab_add_comment"
-        (click)="openCreateDialog()"
+        (click)="this.createCommentWrapper.openCreateDialog(this.user)"
         matTooltip="{{ 'comment-list.add-comment' | translate }}">
   <mat-icon>add</mat-icon>
 </button>
 
+<app-mat-spinner-overlay *ngIf="isLoading" overlay="true"></app-mat-spinner-overlay>
+
 <div *ngIf="!isLoading">
-  <app-comment *ngFor="let current of hideCommentsList ? filteredComments : commentsFilteredByTime"
+  <app-comment *ngFor="let current of hideCommentsList ? filteredComments : commentsFilteredByTime; let i = index"
+               [usesJoyride]="i === 0"
                [comment]="current"
                [parseVote]="getVote(current)"
                [userRole]="userRole"
                [moderator]="false"
                [user]="user"
+               [disabled]="!commentsEnabled"
                (clickedOnTag)="clickedOnTag($event)"
-               (clickedUserNumber)="clickedUserNumber($event)">
+               (clickedUserNumber)="clickedUserNumber($event)"
+               (clickedOnKeyword)="clickedOnKeyword($event)">
   </app-comment>
 
 </div>
+<!-- Active User Overlay -->
+<app-active-user *ngIf="room" [room]="this.room"></app-active-user>
+
 <!-- No Questions Present -->
-<div *ngIf="comments && (commentsFilteredByTime.length < 1 && period === 'time-all' || comments.length === 0) && !isLoading"
-     fxLayout="row"
-     fxLayoutAlign="center center"
-     class="no-comments">
+<div
+  *ngIf="comments && (commentsFilteredByTime.length < 1 && period === 'time-all' || comments.length === 0) && !isLoading"
+  fxLayout="row"
+  fxLayoutAlign="center center"
+  class="no-comments">
   <p class="oldtypo-p">{{ 'comment-page.no-comments' | translate }}</p>
 </div>
 
@@ -267,7 +294,8 @@
      fxLayout="row"
      fxLayoutAlign="center center"
      class="no-comments">
-  <p class="oldtypo-p">{{ (search ? 'comment-page.no-comments-with-search' : 'comment-page.no-comments-with-filter') | translate }}</p>
+  <p
+    class="oldtypo-p">{{ (search ? 'comment-page.no-comments-with-search' : 'comment-page.no-comments-with-filter') | translate }}</p>
 </div>
 
 <!--Hidden Div's for a11y-Descriptions-->
@@ -299,4 +327,5 @@
   <div id="select-time-1d">{{ 'comment-list.a11y-select-time-1d' | translate }}</div>
   <div id="select-time-1w">{{ 'comment-list.a11y-select-time-1w' | translate }}</div>
   <div id="select-time-all">{{ 'comment-list.a11y-select-time-all' | translate }}</div>
+  <div id="activity">{{ 'comment-list.a11y-activity' | translate }} {{activeUsers}}</div>
 </div>
diff --git a/src/app/components/shared/comment-list/comment-list.component.scss b/src/app/components/shared/comment-list/comment-list.component.scss
index 2872f0c8457c26b4a5e215363ab0b541a8512ac8..9dc447656b6f0344c40a348a1f39c4d9fb888670 100644
--- a/src/app/components/shared/comment-list/comment-list.component.scss
+++ b/src/app/components/shared/comment-list/comment-list.component.scss
@@ -1,3 +1,5 @@
+$joyrideElementPadding: 5px;
+
 app-comment {
   overflow: auto;
   overflow-wrap: break-word;
@@ -115,6 +117,11 @@ app-comment {
   margin-right: 2%;
 }
 
+.button-bar.joyrideActive {
+  padding: 15px;
+  margin: unset;
+}
+
 .correct-icon {
   color: var(--green);
 }
@@ -226,6 +233,15 @@ h3 {
   transition: all 0.1s ease-in-out;
 }
 
+#createCommentJoyrideWrapper {
+  position: fixed;
+  width: 56px + 2 * $joyrideElementPadding;
+  height: 56px + 2 * $joyrideElementPadding;
+  right: 17px - $joyrideElementPadding;
+  bottom: 57px - $joyrideElementPadding;
+  visibility: hidden;
+}
+
 .visible {
   transform: scale(1.4);
 }
@@ -254,3 +270,7 @@ h3 {
   animation-iteration-count: 2;
   opacity: 1.0 !important;
 }
+
+h1 {
+  color: red;
+}
diff --git a/src/app/components/shared/comment-list/comment-list.component.ts b/src/app/components/shared/comment-list/comment-list.component.ts
index 5bc9ba945dfee91d590f4dc957f4ee202bd0df40..71d15e4a007dcf6cb8cf655e965160cf73150ce1 100644
--- a/src/app/components/shared/comment-list/comment-list.component.ts
+++ b/src/app/components/shared/comment-list/comment-list.component.ts
@@ -3,10 +3,7 @@ import { Comment } from '../../../models/comment';
 import { CommentService } from '../../../services/http/comment.service';
 import { TranslateService } from '@ngx-translate/core';
 import { LanguageService } from '../../../services/util/language.service';
-import { Message } from '@stomp/stompjs';
-import { CreateCommentComponent } from '../_dialogs/create-comment/create-comment.component';
 import { MatDialog } from '@angular/material/dialog';
-import { WsCommentServiceService } from '../../../services/websockets/ws-comment-service.service';
 import { User } from '../../../models/user';
 import { Vote } from '../../../models/vote';
 import { UserRole } from '../../../models/user-roles.enum';
@@ -17,11 +14,10 @@ import { NotificationService } from '../../../services/util/notification.service
 import { CorrectWrong } from '../../../models/correct-wrong.enum';
 import { LiveAnnouncer } from '@angular/cdk/a11y';
 import { EventService } from '../../../services/util/event.service';
-import { Observable, Subscription } from 'rxjs';
+import { Subscription } from 'rxjs';
 import { AppComponent } from '../../../app.component';
 import { Router, ActivatedRoute } from '@angular/router';
 import { AuthenticationService } from '../../../services/http/authentication.service';
-import { Title } from '@angular/platform-browser';
 import { TitleService } from '../../../services/util/title.service';
 import { ModeratorsComponent } from '../../creator/_dialogs/moderators/moderators.component';
 import { TagsComponent } from '../../creator/_dialogs/tags/tags.component';
@@ -29,16 +25,18 @@ import { DeleteCommentsComponent } from '../../creator/_dialogs/delete-comments/
 import { Export } from '../../../models/export';
 import { BonusTokenService } from '../../../services/http/bonus-token.service';
 import { ModeratorService } from '../../../services/http/moderator.service';
-import { TopicCloudFilterComponent } from '../_dialogs/topic-cloud-filter/topic-cloud-filter.component';
-
-export enum Period {
-  FROMNOW    = 'from-now',
-  ONEHOUR    = 'time-1h',
-  THREEHOURS = 'time-3h',
-  ONEDAY     = 'time-1d',
-  ONEWEEK    = 'time-1w',
-  TWOWEEKS   = 'time-2w',
-  ALL        = 'time-all'
+import { CommentFilter, Period } from '../../../utils/filter-options';
+import { CreateCommentWrapper } from '../../../utils/create-comment-wrapper';
+import { TopicCloudAdminService } from '../../../services/util/topic-cloud-admin.service';
+import { RoomDataService } from '../../../services/util/room-data.service';
+import { WsRoomService } from '../../../services/websockets/ws-room.service';
+import { ActiveUserService } from '../../../services/http/active-user.service';
+import { OnboardingService } from '../../../services/util/onboarding.service';
+
+export interface CommentListData {
+  comments: Comment[];
+  currentFilter: CommentFilter;
+  room: Room;
 }
 
 @Component({
@@ -46,7 +44,6 @@ export enum Period {
   templateUrl: './comment-list.component.html',
   styleUrls: ['./comment-list.component.scss'],
 })
-
 export class CommentListComponent implements OnInit, OnDestroy {
   @ViewChild('searchBox') searchField: ElementRef;
   @Input() user: User;
@@ -76,11 +73,15 @@ export class CommentListComponent implements OnInit, OnDestroy {
   moderator = 'moderator';
   lecturer = 'lecturer';
   tag = 'tag';
+  selectedTag = '';
   userNumber = 'userNumber';
+  keyword = 'keyword';
+  selectedKeyword = '';
   answer = 'answer';
   unanswered = 'unanswered';
   owner = 'owner';
   currentFilter = '';
+  currentFilterCompare: any = null;
   commentVoteMap = new Map<string, Vote>();
   scroll = false;
   scrollExtended = false;
@@ -95,16 +96,23 @@ export class CommentListComponent implements OnInit, OnDestroy {
   commentStream: Subscription;
   periodsList = Object.values(Period);
   headerInterface = null;
-  period: Period = Period.TWOWEEKS;
+  period: Period = Period.twoWeeks;
   fromNow: number;
   moderatorIds: string[];
+  commentsEnabled: boolean;
+  userNumberSelection = 0;
+  createCommentWrapper: CreateCommentWrapper = null;
+  isJoyrideActive = false;
+  private _subscriptionEventServiceTagConfig = null;
+  private _subscriptionEventServiceRoomData = null;
+  private _subscriptionRoomService = null;
+  activeUsers = 0;
 
   constructor(
     private commentService: CommentService,
     private translateService: TranslateService,
     public dialog: MatDialog,
     protected langService: LanguageService,
-    private wsCommentService: WsCommentServiceService,
     protected roomService: RoomService,
     protected voteService: VoteService,
     private authenticationService: AuthenticationService,
@@ -117,14 +125,35 @@ export class CommentListComponent implements OnInit, OnDestroy {
     private translationService: TranslateService,
     private bonusTokenService: BonusTokenService,
     private moderatorService: ModeratorService,
+    private topicCloudAdminService: TopicCloudAdminService,
+    private roomDataService: RoomDataService,
+    private wsRoomService: WsRoomService,
+    private activeUserService: ActiveUserService,
+    private onboardingService: OnboardingService
   ) {
-    langService.langEmitter.subscribe(lang => translateService.use(lang));
+    langService.langEmitter.subscribe(lang => {
+      translateService.use(lang);
+      this.translateService.get('comment-list.search').subscribe(msg => {
+        this.searchPlaceholder = msg;
+      });
+    });
   }
 
   initNavigation() {
+    this._subscriptionEventServiceTagConfig = this.eventService.on<string>('setTagConfig').subscribe(tag => {
+      this.setTimePeriod(Period.all);
+      this.clickedOnKeyword(tag);
+    });
+    this._subscriptionEventServiceRoomData = this.eventService.on<string>('pushCurrentRoomData').subscribe(_ => {
+      this.eventService.broadcast('currentRoomData', {
+        currentFilter: this.getCurrentFilter(),
+        comments: this.comments,
+        room: this.room
+      } as CommentListData);
+    });
     const navigation = {};
     const nav = (b, c) => navigation[b] = c;
-    nav('createQuestion', () => this.openCreateDialog());
+    nav('createQuestion', () => this.createCommentWrapper.openCreateDialog(this.user));
     nav('moderator', () => {
       const dialogRef = this.dialog.open(ModeratorsComponent, {
         width: '400px',
@@ -211,24 +240,46 @@ export class CommentListComponent implements OnInit, OnDestroy {
     this.userRole = this.route.snapshot.data.roles[0];
     this.route.params.subscribe(params => {
       this.shortId = params['shortId'];
+      this.authenticationService.checkAccess(this.shortId);
       this.authenticationService.guestLogin(UserRole.PARTICIPANT).subscribe(r => {
         this.roomService.getRoomByShortId(this.shortId).subscribe(room => {
           this.room = room;
           this.roomId = room.id;
+          this._subscriptionRoomService = this.wsRoomService.getRoomStream(this.roomId).subscribe(msg => {
+            const message = JSON.parse(msg.body);
+            if (message.type === 'RoomPatched') {
+              this.room = message.payload.changes;
+              this.roomId = this.room.id;
+              this.moderationEnabled = this.room.moderated;
+              this.directSend = this.room.directSend;
+              this.commentsEnabled = (this.userRole > 0) || !this.room.questionsBlocked;
+            }
+          });
           this.moderationEnabled = this.room.moderated;
           this.directSend = this.room.directSend;
+          this.commentsEnabled = (this.userRole > 0) || !this.room.questionsBlocked;
+          this.createCommentWrapper = new CreateCommentWrapper(this.translateService,
+            this.notificationService, this.commentService, this.dialog, this.room);
           localStorage.setItem('moderationEnabled', JSON.stringify(this.moderationEnabled));
           if (!this.authenticationService.hasAccess(this.shortId, UserRole.PARTICIPANT)) {
             this.roomService.addToHistory(this.room.id);
             this.authenticationService.setAccess(this.shortId, UserRole.PARTICIPANT);
           }
-          this.getModeratorIds();
-          this.subscribeCommentStream();
-          this.commentService.getAckComments(this.room.id)
-            .subscribe(comments => {
+          this.moderatorService.get(this.roomId).subscribe(list => {
+            this.moderatorIds = list.map(m => m.accountId);
+            this.moderatorIds.push(this.room.ownerId);
+
+            this.roomDataService.getRoomData(this.room.id).subscribe(comments => {
+              if (comments === null) {
+                return;
+              }
               this.comments = comments;
               this.getComments();
+              this.eventService.broadcast('commentListCreated', null);
+              this.isJoyrideActive = this.onboardingService.startDefaultTour();
             });
+            this.subscribeCommentStream();
+          });
           /**
            if (this.userRole === UserRole.PARTICIPANT) {
             this.openCreateDialog();
@@ -245,27 +296,25 @@ export class CommentListComponent implements OnInit, OnDestroy {
     this.translateService.get('comment-list.search').subscribe(msg => {
       this.searchPlaceholder = msg;
     });
-
-    localStorage.setItem('currentFilters', JSON.stringify(this.currentFilter));
-    localStorage.setItem('currentPeriod', JSON.stringify(this.period));
-    localStorage.setItem('currentFromNowTimestamp', JSON.stringify(this.fromNow)); // can be null
-  }
-
-  getModeratorIds() {
-    this.moderatorService.get(this.roomId).subscribe(list => {
-      this.moderatorIds = list.map(m => m.accountId);
-      this.moderatorIds.push(this.room.ownerId);
-    });
   }
 
   ngOnDestroy() {
     if (!this.freeze && this.commentStream) {
       this.commentStream.unsubscribe();
     }
+    if (this._subscriptionRoomService) {
+      this._subscriptionRoomService.unsubscribe();
+    }
     this.titleService.resetTitle();
     if (this.headerInterface) {
       this.headerInterface.unsubscribe();
     }
+    if (this._subscriptionEventServiceRoomData) {
+      this._subscriptionEventServiceRoomData.unsubscribe();
+    }
+    if (this._subscriptionEventServiceTagConfig) {
+      this._subscriptionEventServiceTagConfig.unsubscribe();
+    }
   }
 
   checkScroll(): void {
@@ -285,7 +334,7 @@ export class CommentListComponent implements OnInit, OnDestroy {
         this.hideCommentsList = true;
         this.filteredComments = this.comments
           .filter(c => this.checkIfIncludesKeyWord(c.body, this.searchInput)
-                       || (!!c.answer ? this.checkIfIncludesKeyWord(c.answer, this.searchInput) : false));
+            || (!!c.answer ? this.checkIfIncludesKeyWord(c.answer, this.searchInput) : false));
       }
     } else if (this.searchInput.length === 0 && this.currentFilter === '') {
       this.hideCommentsList = false;
@@ -297,9 +346,6 @@ export class CommentListComponent implements OnInit, OnDestroy {
   }
 
   activateSearch() {
-    this.translateService.get('comment-list.search').subscribe(msg => {
-      this.searchPlaceholder = msg;
-    });
     this.search = true;
     this.searchField.nativeElement.focus();
   }
@@ -329,154 +375,20 @@ export class CommentListComponent implements OnInit, OnDestroy {
     }
   }
 
-  parseIncomingMessage(message: Message) {
-    const msg = JSON.parse(message.body);
-    const payload = msg.payload;
-    switch (msg.type) {
-      case 'CommentCreated':
-        const c = new Comment();
-        c.roomId = this.roomId;
-        c.body = payload.body;
-        c.id = payload.id;
-        c.timestamp = payload.timestamp;
-        c.tag = payload.tag;
-        c.creatorId = payload.creatorId;
-        c.userNumber = this.commentService.hashCode(c.creatorId);
-        this.commentService.getComment(c.id).subscribe(e => {
-          c.number = e.number;
-        });
-
-        this.announceNewComment(c.body);
-        this.comments = this.comments.concat(c);
-        this.setComments(this.comments);
-        break;
-      case 'CommentPatched':
-        // ToDo: Use a map for comments w/ key = commentId
-        for (let i = 0; i < this.comments.length; i++) {
-          if (payload.id === this.comments[i].id) {
-            for (const [key, value] of Object.entries(payload.changes)) {
-              switch (key) {
-                case this.read:
-                  this.comments[i].read = <boolean>value;
-                  break;
-                case this.correct:
-                  this.comments[i].correct = <CorrectWrong>value;
-                  break;
-                case this.favorite:
-                  this.comments[i].favorite = <boolean>value;
-                  if (this.user.id === this.comments[i].creatorId && <boolean>value) {
-                    this.translateService.get('comment-list.comment-got-favorited').subscribe(ret => {
-                      this.notificationService.show(ret);
-                    });
-                  }
-                  break;
-                case this.bookmark:
-                  this.comments[i].bookmark = <boolean>value;
-                  break;
-                case 'score':
-                  this.comments[i].score = <number>value;
-                  this.getComments();
-                  break;
-                case this.ack:
-                  const isNowAck = <boolean>value;
-                  if (!isNowAck) {
-                    this.comments = this.comments.filter(function (el) {
-                      return el.id !== payload.id;
-                    });
-                    this.setTimePeriod();
-                  }
-                  break;
-                case this.tag:
-                  this.comments[i].tag = <string>value;
-                  break;
-                case this.answer:
-                  this.comments[i].answer = <string>value;
-                  break;
-              }
-            }
-          }
-        }
-        break;
-      case 'CommentHighlighted':
-        // ToDo: Use a map for comments w/ key = commentId
-        for (let i = 0; i < this.comments.length; i++) {
-          if (payload.id === this.comments[i].id) {
-            this.comments[i].highlighted = <boolean>payload.lights;
-          }
-        }
-        break;
-      case 'CommentDeleted':
-        for (let i = 0; i < this.comments.length; i++) {
-          this.comments = this.comments.filter(function (el) {
-            return el.id !== payload.id;
-          });
-        }
-        break;
-    }
-    this.setTimePeriod();
-    if (this.hideCommentsList) {
-      this.searchComments();
-    }
-  }
   closeDialog() {
     this.dialog.closeAll();
   }
-  openCreateDialog(): void {
-    const dialogRef = this.dialog.open(CreateCommentComponent, {
-      width: '900px',
-      maxWidth: 'calc( 100% - 50px )',
-      maxHeight: 'calc( 100vh - 50px )',
-      autoFocus: false,
-    });
-    dialogRef.componentInstance.user = this.user;
-    dialogRef.componentInstance.roomId = this.roomId;
-    let tags;
-    tags = [];
-    if (this.room.tags) {
-      tags = this.room.tags;
-    }
-    dialogRef.componentInstance.tags = tags;
-    dialogRef.afterClosed()
-      .subscribe(result => {
-        if (result) {
-          this.send(result);
-        } else {
-          return;
-        }
-      });
-  }
-
-
-  send(comment: Comment): void {
-    let message;
-    if (this.directSend) {
-      this.translateService.get('comment-list.comment-sent').subscribe(msg => {
-        message = msg;
-      });
-      comment.ack = true;
-    } else {
-      if (this.userRole === 1 || this.userRole === 2 || this.userRole === 3) {
-        this.translateService.get('comment-list.comment-sent').subscribe(msg => {
-          message = msg;
-        });
-        comment.ack = true;
-      }
-      if (this.userRole === 0) {
-        this.translateService.get('comment-list.comment-sent-to-moderator').subscribe(msg => {
-          message = msg;
-        });
-      }
-    }
-    this.commentService.addComment(comment).subscribe();
-    this.notificationService.show(message);
-  }
 
   filterComments(type: string, compare?: any): void {
     this.currentFilter = type;
+    this.currentFilterCompare = compare;
     if (type === '') {
       this.filteredComments = this.commentsFilteredByTime;
       this.hideCommentsList = false;
       this.currentFilter = '';
+      this.selectedTag = '';
+      this.selectedKeyword = '';
+      this.userNumberSelection = 0;
       this.sortComments(this.currentSort);
       return;
     }
@@ -495,9 +407,15 @@ export class CommentListComponent implements OnInit, OnDestroy {
         case this.unread:
           return !c.read;
         case this.tag:
+          this.selectedTag = compare;
           return c.tag === compare;
         case this.userNumber:
           return c.userNumber === compare;
+        case this.keyword:
+          this.selectedKeyword = compare;
+          const isInQuestioner = c.keywordsFromQuestioner ? c.keywordsFromQuestioner.findIndex(k => k.lemma === compare) >= 0 : false;
+          const isInSpacy = c.keywordsFromSpacy ? c.keywordsFromSpacy.findIndex(k => k.lemma === compare) >= 0 : false;
+          return isInQuestioner || isInSpacy;
         case this.answer:
           return c.answer;
         case this.unanswered:
@@ -505,16 +423,29 @@ export class CommentListComponent implements OnInit, OnDestroy {
         case this.owner:
           return c.creatorId === this.user.id;
         case this.moderator:
-          return c.creatorId === this.user.id && (this.user.role === 2 || this.user.role === 1);
+          return this.moderatorIds.includes(c.creatorId);
         case this.lecturer:
-          return c.creatorId === this.user.id && this.user.role === 3;
+          return c.createdFromLecturer;
       }
     });
+    const testForModerator=()=>{
+      this.comments.forEach(e=>{
+        this.commentService.role(e).subscribe(i=>{
+          console.log(e,i);
+        });
+      });
+    };
+    if(type==='moderator'){
+      console.log(
+        'TEST moderator',
+        this.moderatorIds,
+        this.user,
+        this.room
+      );
+      testForModerator();
+    }
     this.hideCommentsList = true;
     this.sortComments(this.currentSort);
-
-    // set current filters to local storage for later use
-    localStorage.setItem('currentFilters', JSON.stringify(this.currentFilter));
   }
 
   sort(array: any[], type: string): any[] {
@@ -524,13 +455,12 @@ export class CommentListComponent implements OnInit, OnDestroy {
       } else if (type === this.votedesc) {
         return (b.score > a.score) ? 1 : (a.score > b.score) ? -1 : 0;
       } else if (type === this.time) {
-        const dateA = new Date(a.timestamp), dateB = new Date(b.timestamp);
+        const dateA = new Date(a.timestamp);
+        const dateB = new Date(b.timestamp);
         return (+dateB > +dateA) ? 1 : (+dateA > +dateB) ? -1 : 0;
       }
     });
-    return sortedArray.sort((a, b) => {
-      return this.isCreatedByModeratorOrCreator(a) ? -1 : this.isCreatedByModeratorOrCreator(b) ? 1 : 0;
-    });
+    return sortedArray.sort((a, b) => this.isCreatedByModeratorOrCreator(a) ? -1 : this.isCreatedByModeratorOrCreator(b) ? 1 : 0);
   }
 
   isCreatedByModeratorOrCreator(comment: Comment): boolean {
@@ -550,12 +480,25 @@ export class CommentListComponent implements OnInit, OnDestroy {
     this.filterComments(this.tag, tag);
   }
 
+  clickedOnKeyword(keyword: string): void {
+    this.filterComments(this.keyword, keyword);
+  }
+
   clickedUserNumber(usrNumber: number): void {
+    this.userNumberSelection = usrNumber;
     this.filterComments(this.userNumber, usrNumber);
   }
 
   pauseCommentStream() {
     this.freeze = true;
+    this.roomDataService.getRoomData(this.roomId, true).subscribe(comments => {
+      if (comments === null) {
+        return;
+      }
+      this.comments = comments;
+      this.setComments(comments);
+      this.getComments();
+    });
     this.commentStream.unsubscribe();
     this.translateService.get('comment-list.comment-stream-stopped').subscribe(msg => {
       this.notificationService.show(msg);
@@ -564,12 +507,14 @@ export class CommentListComponent implements OnInit, OnDestroy {
 
   playCommentStream() {
     this.freeze = false;
-    this.commentService.getAckComments(this.roomId)
-      .subscribe(comments => {
-        this.comments = comments;
-        this.setComments(comments);
-        this.getComments();
-      });
+    this.roomDataService.getRoomData(this.roomId).subscribe(comments => {
+      if (comments === null) {
+        return;
+      }
+      this.comments = comments;
+      this.setComments(comments);
+      this.getComments();
+    });
     this.subscribeCommentStream();
     this.translateService.get('comment-list.comment-stream-started').subscribe(msg => {
       this.notificationService.show(msg);
@@ -577,8 +522,32 @@ export class CommentListComponent implements OnInit, OnDestroy {
   }
 
   subscribeCommentStream() {
-    this.commentStream = this.wsCommentService.getCommentStream(this.room.id).subscribe((message: Message) => {
-      this.parseIncomingMessage(message);
+    this.commentStream = this.roomDataService.receiveUpdates([
+      { type: 'CommentCreated', finished: true },
+      { type: 'CommentPatched', subtype: this.favorite },
+      { type: 'CommentPatched', subtype: 'score' },
+      { finished: true }
+    ]).subscribe(update => {
+      if (update.type === 'CommentCreated') {
+        this.announceNewComment(update.comment.body);
+        this.setComments(this.comments);
+      } else if (update.type === 'CommentPatched') {
+        if (update.subtype === 'score') {
+          this.getComments();
+        } else if (update.subtype === this.favorite) {
+          if (this.user.id === update.comment.creatorId && update.comment.favorite) {
+            this.translateService.get('comment-list.comment-got-favorited').subscribe(ret => {
+              this.notificationService.show(ret);
+            });
+          }
+        }
+      }
+      if (update.finished) {
+        this.setTimePeriod();
+        if (this.hideCommentsList) {
+          this.searchComments();
+        }
+      }
     });
   }
 
@@ -606,7 +575,8 @@ export class CommentListComponent implements OnInit, OnDestroy {
       // current live announcer content must be cleared before next read
       this.liveAnnouncer.clear();
 
-      this.liveAnnouncer.announce(newCommentText).catch(err => { /* TODO error handling */ });
+      this.liveAnnouncer.announce(newCommentText).catch(err => { /* TODO error handling */
+      });
     }, 450);
   }
 
@@ -618,40 +588,53 @@ export class CommentListComponent implements OnInit, OnDestroy {
     const currentTime = new Date();
     const hourInSeconds = 3600000;
     let periodInSeconds;
-    if (this.period !== Period.ALL) {
+    if (this.period !== Period.all) {
       switch (this.period) {
-        case Period.FROMNOW:
+        case Period.fromNow:
           if (!this.fromNow) {
             this.fromNow = new Date().getTime();
           }
           break;
-        case Period.ONEHOUR:
+        case Period.oneHour:
           periodInSeconds = hourInSeconds;
           break;
-        case Period.THREEHOURS:
+        case Period.threeHours:
           periodInSeconds = hourInSeconds * 2;
           break;
-        case Period.ONEDAY:
+        case Period.oneDay:
           periodInSeconds = hourInSeconds * 24;
           break;
-        case Period.ONEWEEK:
+        case Period.oneWeek:
           periodInSeconds = hourInSeconds * 168;
           break;
-        case Period.TWOWEEKS:
+        case Period.twoWeeks:
           periodInSeconds = hourInSeconds * 336;
           break;
       }
       this.commentsFilteredByTime = this.comments
         .filter(c => new Date(c.timestamp).getTime() >=
-                     (this.period === Period.FROMNOW ? this.fromNow : (currentTime.getTime() - periodInSeconds)));
+          (this.period === Period.fromNow ? this.fromNow : (currentTime.getTime() - periodInSeconds)));
     } else {
       this.commentsFilteredByTime = this.comments;
     }
 
-    localStorage.setItem('currentPeriod', JSON.stringify(this.period));
-    localStorage.setItem('currentFromNowTimestamp', JSON.stringify(this.fromNow)); // can be null
-    
-    this.filterComments(this.currentFilter);
+    this.filterComments(this.currentFilter, this.currentFilterCompare);
     this.titleService.attachTitle('(' + this.commentsFilteredByTime.length + ')');
   }
+
+  private getCurrentFilter(): CommentFilter {
+    const filter = new CommentFilter();
+    filter.filterSelected = this.currentFilter;
+    filter.paused = this.freeze;
+    filter.periodSet = this.period;
+    filter.keywordSelected = this.selectedKeyword;
+    filter.tagSelected = this.selectedTag;
+    filter.userNumberSelected = this.userNumberSelection;
+
+    if (filter.periodSet === Period.fromNow) {
+      filter.timeStampNow = new Date().getTime();
+    }
+
+    return filter;
+  }
 }
diff --git a/src/app/components/shared/comment/comment.component.html b/src/app/components/shared/comment/comment.component.html
index 826f46505b0f959ebc058aca5f5c5c535a535fe9..bd009b1e970a3438c0d77feb16a6287ee4112155 100644
--- a/src/app/components/shared/comment/comment.component.html
+++ b/src/app/components/shared/comment/comment.component.html
@@ -39,6 +39,15 @@
       </button>
       <span class="fill-remaining-space"></span>
       <ng-container>
+        <button mat-icon-button
+                *ngIf="(isCreator || isModerator)"
+                (click)="changeProfanityShowForModerators(comment)">
+          <mat-icon class="not-marked"
+                    [matTooltip]="filterProfanityForModerators ? ('comment-page.show-comment-with-filter' | translate) :
+            ('comment-page.show-comment-without-filter' | translate)">
+            {{filterProfanityForModerators ? 'visibility' : 'visibility_off'}}
+          </mat-icon>
+        </button>
         <button mat-icon-button
                 *ngIf="(isCreator || isModerator || comment.answer) && !inAnswerView"
                 (click)="answerComment()"
@@ -76,7 +85,7 @@
           </mat-icon>
         </button>
         <button mat-icon-button
-                *ngIf="(!isStudent || comment.favorite) && !moderator"
+                *ngIf="!isStudent && !moderator"
                 [disabled]="isStudent"
                 (click)="setFavorite(comment)"
                 tabindex="0"
@@ -86,6 +95,25 @@
                                                  : ('comment-page.mark-not-favorite' | translate)">grade
           </mat-icon>
         </button>
+        <button mat-icon-button
+                *ngIf="(comment.favorite && isStudent && !(comment.creatorId && user && comment.creatorId === user.id))"
+                tabindex="0"
+                attr.aria-labelledby="comment_grade{{ comment.id }}">
+          <mat-icon [ngClass]="{'favorite-icon' : comment.favorite, 'not-marked' : !comment.favorite}"
+                    [matTooltip]="!comment.favorite ? ('comment-page.mark-favorite' | translate)
+                                                 : ('comment-page.mark-not-favorite' | translate)">grade
+          </mat-icon>
+        </button>
+        <button mat-icon-button
+                *ngIf="(comment.favorite && isStudent && (comment.creatorId && user && comment.creatorId === user.id))"
+                (click)="openBonusStarDialog()"
+                tabindex="0"
+                attr.aria-labelledby="comment_grade{{ comment.id }}">
+          <mat-icon [ngClass]="{'favorite-icon' : comment.favorite, 'not-marked' : !comment.favorite}"
+                    [matTooltip]="!comment.favorite ? ('comment-page.mark-favorite' | translate)
+                                                 : ('comment-page.mark-not-favorite' | translate)">grade
+          </mat-icon>
+        </button>
         <button mat-icon-button
                 *ngIf="(!isStudent || comment.bookmark) && !moderator"
                 [disabled]="isStudent"
@@ -107,7 +135,7 @@
               attr.aria-labelledby="comment_delete{{ comment.id }}"
       >
         <mat-icon>
-          delete
+          delete_sweep
         </mat-icon>
       </button>
 
@@ -217,7 +245,7 @@
                   attr.aria-labelledby="comment_delete{{ comment.id }}"
           >
             <mat-icon class="not-marked">
-              delete
+              delete_sweep
             </mat-icon>
             <span>
               {{
@@ -236,8 +264,7 @@
            tabindex="0">
         <ars-row #commentBody>
           <ars-row #commentBodyInner>
-            <markdown class="images"
-                      [data]="comment.body"></markdown>
+            <app-custom-markdown class="images" [data]="comment.body"></app-custom-markdown>
           </ars-row>
         </ars-row>
         <span id="comment-{{ comment.id }}"
@@ -254,29 +281,21 @@
           }}</span>
       </div>
       <div
+        [joyrideStep]="'voting'"
+        [stepPosition]="'left'"
+        appJoyrideTemplate
         fxLayout="column"
         fxLayoutAlign="center"
-        *ngIf="isStudent"
+        *ngIf="isStudent && usesJoyride"
         [ngClass]="{ '1': 'voteUp', '-1': 'voteDown', '0': 'reset'}[currentVote]">
-        <button mat-icon-button
-                (click)="voteUp(comment)"
-                matTooltip="{{ 'comment-page.vote-up' | translate }}"
-                tabindex="0"
-                attr.aria-labelledby="comment_vote_up{{ comment.id }}">
-          <mat-icon class="voting-icon"
-                    [ngClass]="{'upVoted' : hasVoted === 1}">keyboard_arrow_up
-          </mat-icon>
-        </button>
-        <span class="score">{{comment.score}}</span>
-        <button mat-icon-button
-                (click)="voteDown(comment)"
-                matTooltip="{{ 'comment-page.vote-down' | translate }}"
-                tabindex="0"
-                attr.aria-labelledby="comment_vote_down{{ comment.id }}">
-          <mat-icon class="voting-icon"
-                    [ngClass]="{'downVoted' : hasVoted === -1}">keyboard_arrow_down
-          </mat-icon>
-        </button>
+        <ng-container [ngTemplateOutlet]="voting"></ng-container>
+      </div>
+      <div
+        fxLayout="column"
+        fxLayoutAlign="center"
+        *ngIf="isStudent && !usesJoyride"
+        [ngClass]="{ '1': 'voteUp', '-1': 'voteDown', '0': 'reset'}[currentVote]">
+        <ng-container [ngTemplateOutlet]="voting"></ng-container>
       </div>
       <div *ngIf="!isStudent"
            fxLayout="column"
@@ -308,7 +327,21 @@
           &nbsp;{{comment.tag}}
         </span>
       </div>
+      <div class="user-number joyrideActive"
+           *ngIf="usesJoyride"
+           [joyrideStep]="'commentUserNumber'"
+           [stepPosition]="'right'"
+           appJoyrideTemplate
+           fxLayoutAlign="center center"
+           matTooltip="{{ 'comment-page.user-number' | translate }}"
+           (click)="this.clickedUserNumber.emit(comment.userNumber)">
+        <mat-icon class="user-icon">person_pin_circle</mat-icon>
+        <strong>
+          {{comment.userNumber}}
+        </strong>
+      </div>
       <div class="user-number"
+           *ngIf="!usesJoyride"
            fxLayoutAlign="center center"
            matTooltip="{{ 'comment-page.user-number' | translate }}"
            (click)="this.clickedUserNumber.emit(comment.userNumber)">
@@ -317,6 +350,28 @@
           {{comment.userNumber}}
         </strong>
       </div>
+      <div fxLayoutAlign="center center"
+           matTooltip="{{ 'comment-page.keywords-per-question' | translate }}"
+           [mat-menu-trigger-for]="keywordsMenu"
+           *ngIf="(comment.keywordsFromQuestioner != undefined && comment.keywordsFromQuestioner.length > 0)"
+           class="comment-keywords">
+        <mat-icon svgIcon="hashtag" class="keyword-icon"></mat-icon>
+        <span matBadge="{{comment.keywordsFromQuestioner.length}}" matBadgeSize="small" matBadgeOverlap="false">
+          {{ this.selectedKeyword === '' ? ('comment-page.keywords' | translate) : this.selectedKeyword}}
+        </span>
+        <mat-menu #keywordsMenu>
+
+          <mat-list dense class="keywords-list">
+            <mat-list-item
+              *ngFor="let keyword of sortKeywords(comment.keywordsFromQuestioner); let odd = odd; let even = even"
+              [class.keywords-alternate]="odd"
+              [class.keywords-even]="even">
+              <span (click)="this.clickedOnKeyword.emit(keyword.lemma)" class="keyword-span">{{keyword.lemma}}</span>
+            </mat-list-item>
+          </mat-list>
+        </mat-menu>
+      </div>
+
       <span class="fill-remaining-space"></span>
       <button mat-icon-button
               class="moderate-button"
@@ -338,10 +393,12 @@
   <div id="comment_answer{{ comment.id }}">{{comment.answer ? ('comment-page.a11y-comment-answer' | translate) :
     ('comment-page.a11y-comment-answer-not' | translate)}}
   </div>
-  <div id="comment_correct{{ comment.id }}">{{comment.correct != 1 ? ('comment-page.a11y-comment_not_marked_correct' | translate)
+  <div
+    id="comment_correct{{ comment.id }}">{{comment.correct != 1 ? ('comment-page.a11y-comment_not_marked_correct' | translate)
     : ('comment-page.a11y-comment_marked_correct' | translate) }}
   </div>
-  <div id="comment_not_correct{{ comment.id }}">{{comment.correct != 2 ? ('comment-page.a11y-comment_not_marked_wrong' | translate)
+  <div
+    id="comment_not_correct{{ comment.id }}">{{comment.correct != 2 ? ('comment-page.a11y-comment_not_marked_wrong' | translate)
     : ('comment-page.a11y-comment_marked_wrong' | translate) }}
   </div>
   <div id="comment_grade{{ comment.id }}">{{ !comment.favorite ? ('comment-page.a11y-comment_grade' | translate)
@@ -354,3 +411,27 @@
   <div *ngIf="isStudent"
        id="comment_vote_down{{ comment.id }}">{{'comment-page.a11y-comment_vote_down' | translate}}</div>
 </div>
+
+<ng-template #voting>
+  <button mat-icon-button
+          (click)="voteUp(comment)"
+          *ngIf="!disabled"
+          matTooltip="{{ 'comment-page.vote-up' | translate }}"
+          tabindex="0"
+          attr.aria-labelledby="comment_vote_up{{ comment.id }}">
+    <mat-icon class="voting-icon"
+              [ngClass]="{'upVoted' : hasVoted === 1}">keyboard_arrow_up
+    </mat-icon>
+  </button>
+  <span class="score">{{comment.score}}</span>
+  <button mat-icon-button
+          (click)="voteDown(comment)"
+          *ngIf="!disabled"
+          matTooltip="{{ 'comment-page.vote-down' | translate }}"
+          tabindex="0"
+          attr.aria-labelledby="comment_vote_down{{ comment.id }}">
+    <mat-icon class="voting-icon"
+              [ngClass]="{'downVoted' : hasVoted === -1}">keyboard_arrow_down
+    </mat-icon>
+  </button>
+</ng-template>
diff --git a/src/app/components/shared/comment/comment.component.scss b/src/app/components/shared/comment/comment.component.scss
index 41cbf510532a3b7b4bef04193e07cba958f68c50..d4016d05999df61fb84d7b36bfdc227bc7dcfa1b 100644
--- a/src/app/components/shared/comment/comment.component.scss
+++ b/src/app/components/shared/comment/comment.component.scss
@@ -1,9 +1,8 @@
-@mixin card-box-shadow($color: transparent, $x: -4px){
-  box-shadow:
-    0px 2px 1px -1px rgba(0, 0, 0, 0.2),
-    0px 1px 1px 0px rgba(0, 0, 0, 0.14),
-    0px 1px 3px 0px rgba(0, 0, 0, 0.12),
-    $x 0px 0px 0px $color;
+@mixin card-box-shadow($color: transparent, $x: -4px) {
+  box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2),
+  0px 1px 1px 0px rgba(0, 0, 0, 0.14),
+  0px 1px 3px 0px rgba(0, 0, 0, 0.12),
+  $x 0px 0px 0px $color;
 }
 
 #comment-card {
@@ -11,7 +10,7 @@
   background-color: var(--surface);
   padding: 1.5% 1.5% 3% 3%;
   transition: background-color 0.5s linear,
-              box-shadow 0.15s ease-in-out;
+  box-shadow 0.15s ease-in-out;
   touch-action: auto !important;
 }
 
@@ -72,7 +71,7 @@ mat-card-content > :first-child {
 .score {
   text-align: center;
   margin: 0;
-  color: var(--primary);
+  color: var(--on-surface);
   font-size: 24px;
   font-weight: bold;
 }
@@ -136,39 +135,50 @@ mat-card-content > :first-child {
   background-color: var(--moderator) !important;
 }
 
-.border{
-  @include card-box-shadow(transparent,0);
-  &-correct{
+.border {
+  @include card-box-shadow(transparent, 0);
+
+  &-correct {
     @include card-box-shadow(var(--green));
   }
-  &-wrong{
+
+  &-wrong {
     @include card-box-shadow(var(--red));
   }
-  &-bookmark{
+
+  &-bookmark {
     @include card-box-shadow(var(--magenta));
   }
-  &-favorite{
+
+  &-favorite {
     @include card-box-shadow(var(--yellow));
   }
-  &-notMarked{
+
+  &-notMarked {
     @include card-box-shadow(var(--grey));
   }
-  &-answer{
+
+  &-answer {
     @include card-box-shadow(var(--primary));
   }
-  &-ownQuestion{
+
+  &-ownQuestion {
     @include card-box-shadow(var(--purple));
   }
-  &-bonus{
+
+  &-bonus {
     @include card-box-shadow(var(--yellow));
   }
-  &-merged{
+
+  &-merged {
     @include card-box-shadow(var(--magenta));
   }
-  &-discussed{
+
+  &-discussed {
     @include card-box-shadow(var(--gray));
   }
-  &-mergeSelect{
+
+  &-mergeSelect {
     @include card-box-shadow(var(--cyan));
   }
 }
@@ -179,11 +189,53 @@ mat-card-content > :first-child {
   margin-right: 10px;
 }
 
+.comment-keywords {
+  cursor: pointer;
+  color: var(--on-surface);
+  margin-left: 10px;
+}
+
+
+::ng-deep .mat-menu-panel {
+  min-height: 56px !important;
+}
+
+.keywords-list {
+  flex-grow: 1;
+  flex-shrink: 1;
+  overflow: auto;
+  padding-top: 0 !important;
+  background-color: var(--alt-dialog);
+}
+
+.keywords-even {
+  background-color: var(--alt-surface);
+}
+
+.keyword-span {
+  color: var(--on-surface) !important;
+  opacity: 1 !important;
+  cursor: pointer;
+  width: 100%;
+}
+
+.keyword-icon {
+  height: 18px !important;
+}
+
+.mat-badge-content {
+  background: #fb9a1c;
+}
+
 .user-number {
   cursor: pointer;
   color: var(--on-surface);
 }
 
+.user-number.joyrideActive {
+  padding: 5px;
+}
+
 .commentExpanderButton {
   color: var(--on-surface);
 }
@@ -290,26 +342,27 @@ button:focus {
   border: 1px solid var(--on-surface);
 }
 
-:host{
-  .runningnum-outer{
-    width:100%;
-    height:0px;
-    background-color:red;
-    position:absolute;
-    >p{
-      font-size:200px;
-      padding:0;
-      margin:0;
-      font-weight:normal;
-      font-style:normal;
-      font-family:Roboto, 'sans-serif';
-      margin-top:-50px;
-      margin-right:32px;
-      color:var(--on-surface);
-      opacity:0.1;
-      float:right;
-      position:relative;
-      z-index:0;
+:host {
+  .runningnum-outer {
+    width: 100%;
+    height: 0px;
+    background-color: red;
+    position: absolute;
+
+    > p {
+      font-family: 'Roboto', sans-serif;
+      font-size: 150px;
+      padding: 0;
+      margin: 0;
+      font-weight: bold;
+      font-style: normal;
+      margin-top: -3px;
+      margin-right: 70px;
+      color: var(--on-surface);
+      opacity: 0.1;
+      float: right;
+      position: relative;
+      z-index: 0;
     }
   }
 }
diff --git a/src/app/components/shared/comment/comment.component.ts b/src/app/components/shared/comment/comment.component.ts
index acb0137a08a3993db91ce1d531533a3f536a2d52..76f7e91fabbe963999dcf967fdebed8b270e1494 100644
--- a/src/app/components/shared/comment/comment.component.ts
+++ b/src/app/components/shared/comment/comment.component.ts
@@ -1,4 +1,4 @@
-import { Component, Input, Output, OnInit, EventEmitter, ViewChild, AfterViewInit, Renderer2 } from '@angular/core';
+import { Component, Input, Output, OnInit, EventEmitter, ViewChild, AfterViewInit } from '@angular/core';
 import { Comment } from '../../../models/comment';
 import { Vote } from '../../../models/vote';
 import { AuthenticationService } from '../../../services/http/authentication.service';
@@ -8,7 +8,6 @@ import { CommentService } from '../../../services/http/comment.service';
 import { NotificationService } from '../../../services/util/notification.service';
 import { TranslateService } from '@ngx-translate/core';
 import { LanguageService } from '../../../services/util/language.service';
-import { WsCommentServiceService } from '../../../services/websockets/ws-comment-service.service';
 import { PresentCommentComponent } from '../_dialogs/present-comment/present-comment.component';
 import { MatDialog } from '@angular/material/dialog';
 import { animate, state, style, transition, trigger } from '@angular/animations';
@@ -18,6 +17,9 @@ import { UserRole } from '../../../models/user-roles.enum';
 import { Rescale } from '../../../models/rescale';
 import { RowComponent } from '../../../../../projects/ars/src/lib/components/layout/frame/row/row.component';
 import { User } from '../../../models/user';
+import { RoomDataService } from '../../../services/util/room-data.service';
+import { SpacyKeyword } from '../../../services/http/spacy.service';
+import { UserBonusTokenComponent } from '../../participant/_dialogs/user-bonus-token/user-bonus-token.component';
 
 @Component({
   selector: 'app-comment',
@@ -40,8 +42,14 @@ export class CommentComponent implements OnInit, AfterViewInit {
   @Input() moderator: boolean;
   @Input() userRole: UserRole;
   @Input() user: User;
+  @Input() disabled = false;
+  @Input() usesJoyride = false;
   @Output() clickedOnTag = new EventEmitter<string>();
+  @Output() clickedOnKeyword = new EventEmitter<string>();
   @Output() clickedUserNumber = new EventEmitter<number>();
+  @ViewChild('commentBody', { static: true })commentBody: RowComponent;
+  @ViewChild('commentBodyInner', { static: true })commentBodyInner: RowComponent;
+  @ViewChild('commentExpander', { static: true })commentExpander: RowComponent;
   isStudent = false;
   isCreator = false;
   isModerator = false;
@@ -52,11 +60,11 @@ export class CommentComponent implements OnInit, AfterViewInit {
   currentVote: string;
   slideAnimationState = 'hidden';
   roleString: string;
-  @ViewChild('commentBody', { static: true })commentBody: RowComponent;
-  @ViewChild('commentBodyInner', { static: true })commentBodyInner: RowComponent;
-  @ViewChild('commentExpander', { static: true })commentExpander: RowComponent;
   isExpanded = false;
   isExpandable = false;
+  selectedKeyword = '';
+  filterProfanityForModerators = false;
+  createdBy;
 
   constructor(protected authenticationService: AuthenticationService,
     private route: ActivatedRoute,
@@ -65,9 +73,9 @@ export class CommentComponent implements OnInit, AfterViewInit {
     private commentService: CommentService,
     private notification: NotificationService,
     private translateService: TranslateService,
+    private roomDataService: RoomDataService,
     public dialog: MatDialog,
-    protected langService: LanguageService,
-    private wsCommentService: WsCommentServiceService) {
+    protected langService: LanguageService) {
     langService.langEmitter.subscribe(lang => {
       translateService.use(lang);
       this.language = lang;
@@ -75,6 +83,7 @@ export class CommentComponent implements OnInit, AfterViewInit {
   }
 
   ngOnInit() {
+    this.checkProfanity();
     switch (this.userRole) {
       case UserRole.PARTICIPANT.valueOf():
         this.isStudent = true;
@@ -94,6 +103,25 @@ export class CommentComponent implements OnInit, AfterViewInit {
     this.inAnswerView = !this.router.url.includes('comments');
   }
 
+  checkProfanity(){
+    if (!this.router.url.includes('moderator/comments')) {
+      this.roomDataService.checkProfanity(this.comment);
+    }
+  }
+
+  changeProfanityShowForModerators(comment: Comment) {
+    let newBody: string;
+    if (this.filterProfanityForModerators) {
+      newBody = this.roomDataService.getFilteredBody(comment.id);
+    } else {
+      newBody = this.roomDataService.getUnFilteredBody(comment.id);
+    }
+    if (newBody) {
+      comment.body = newBody;
+    }
+    this.filterProfanityForModerators = !this.filterProfanityForModerators;
+  }
+
   ngAfterViewInit(): void {
     this.isExpandable = this.commentBody.getRenderedHeight() > CommentComponent.COMMENT_MAX_HEIGHT;
     if (!this.isExpandable) {
@@ -104,6 +132,10 @@ export class CommentComponent implements OnInit, AfterViewInit {
     }
   }
 
+  sortKeywords(keywords: SpacyKeyword[]){
+    return keywords.sort((a,b) => a.lemma.localeCompare(b.lemma));
+  }
+
   toggleExpand(evt: MouseEvent) {
     this.isExpanded = !this.isExpanded;
     if (this.isExpanded) {
@@ -127,7 +159,10 @@ export class CommentComponent implements OnInit, AfterViewInit {
   }
 
   setRead(comment: Comment): void {
-    this.commentService.toggleRead(comment).subscribe();
+    this.commentService.toggleRead(comment).subscribe(c => {
+      this.comment = c;
+      this.checkProfanity();
+    });
   }
 
   markCorrect(comment: Comment, type: CorrectWrong): void {
@@ -136,11 +171,18 @@ export class CommentComponent implements OnInit, AfterViewInit {
       } else {
         comment.correct = type;
       }
-    this.commentService.markCorrect(comment).subscribe();
+    this.commentService.markCorrect(comment).subscribe(c => {
+      this.comment = c;
+      this.checkProfanity();
+    });
   }
 
+
   setFavorite(comment: Comment): void {
-    this.commentService.toggleFavorite(comment).subscribe();
+    this.commentService.toggleFavorite(comment).subscribe(c => {
+      this.comment = c;
+      this.checkProfanity();
+    });
   }
 
   voteUp(comment: Comment): void {
@@ -207,11 +249,17 @@ export class CommentComponent implements OnInit, AfterViewInit {
   }
 
   setAck(comment: Comment): void {
-    this.commentService.toggleAck(comment).subscribe();
+    this.commentService.toggleAck(comment).subscribe(c => {
+      this.comment = c;
+      this.checkProfanity();
+    });
   }
 
   setBookmark(comment: Comment): void {
-    this.commentService.toggleBookmark(comment).subscribe();
+    this.commentService.toggleBookmark(comment).subscribe(c => {
+      this.comment = c;
+      this.checkProfanity();
+    });
   }
 
   goToFullScreen(element: Element): void {
@@ -247,4 +295,11 @@ export class CommentComponent implements OnInit, AfterViewInit {
 
       });
   }
+
+  openBonusStarDialog() {
+      const dialogRef = this.dialog.open(UserBonusTokenComponent, {
+        width: '600px'
+      });
+      dialogRef.componentInstance.userId = this.user.id;
+  }
 }
diff --git a/src/app/components/shared/custom-markdown/custom-markdown.component.scss b/src/app/components/shared/custom-markdown/custom-markdown.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/app/components/shared/custom-markdown/custom-markdown.component.spec.ts b/src/app/components/shared/custom-markdown/custom-markdown.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..be6dc6386da6215d8964594f9bb561d2c028e3de
--- /dev/null
+++ b/src/app/components/shared/custom-markdown/custom-markdown.component.spec.ts
@@ -0,0 +1,26 @@
+/*import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CustomMarkdownComponent } from './custom-markdown.component';
+
+describe('CustomMarkdownComponent', () => {
+  let component: CustomMarkdownComponent;
+  let fixture: ComponentFixture<CustomMarkdownComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ CustomMarkdownComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(CustomMarkdownComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
+ */
diff --git a/src/app/components/shared/custom-markdown/custom-markdown.component.ts b/src/app/components/shared/custom-markdown/custom-markdown.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9b00e52d5a73d8c688ad723a29a30399cd68032e
--- /dev/null
+++ b/src/app/components/shared/custom-markdown/custom-markdown.component.ts
@@ -0,0 +1,131 @@
+import { Component, ElementRef, Input, OnChanges, SimpleChanges } from '@angular/core';
+import { KatexOptions, MarkdownService, PrismPlugin } from 'ngx-markdown';
+
+@Component({
+  selector: 'app-custom-markdown',
+  template: '<ng-content></ng-content>',
+  styleUrls: ['./custom-markdown.component.scss']
+})
+export class CustomMarkdownComponent implements OnChanges {
+  @Input() katex = true;
+  @Input() emoji = true;
+  @Input() lineNumbers = true;
+  @Input() lineHighlight = true;
+  @Input() start: number | undefined;
+  @Input() line: string | string[] | undefined;
+  @Input() lineOffset: number | undefined;
+  @Input() katexOptions: KatexOptions = {
+    throwOnError: true
+  };
+  @Input() data: string;
+
+  constructor(public element: ElementRef<HTMLElement>,
+              public markdownService: MarkdownService) {
+  }
+
+  private static setPluginClass(element: HTMLElement, plugin: string | string[]): void {
+    const preElements = element.querySelectorAll('pre');
+    for (let i = 0; i < preElements.length; i++) {
+      const classes = plugin instanceof Array ? plugin : [plugin];
+      preElements.item(i).classList.add(...classes);
+    }
+  }
+
+  private static setPluginOptions(element: HTMLElement, options: { [key: string]: number | string | string[] | undefined }): void {
+    const preElements = element.querySelectorAll('pre');
+    for (let i = 0; i < preElements.length; i++) {
+      Object.keys(options).forEach(option => {
+        const attributeValue = options[option];
+        if (attributeValue) {
+          const attributeName = this.toLispCase(option);
+          preElements.item(i).setAttribute(attributeName, attributeValue.toString());
+        }
+      });
+    }
+  }
+
+  private static toLispCase(value: string): string {
+    const upperChars = value.match(/([A-Z])/g);
+    if (!upperChars) {
+      return value;
+    }
+    let str = value.toString();
+    for (let i = 0, n = upperChars.length; i < n; i++) {
+      str = str.replace(new RegExp(upperChars[i]), '-' + upperChars[i].toLowerCase());
+    }
+    if (str.slice(0, 1) === '-') {
+      str = str.slice(1);
+    }
+    return str;
+  }
+
+  private static fixKatex(markdown: string): string {
+    const regexp = /\${1,2}[^$]+\${1,2}/g;
+    let newStr = '';
+    let lastIndex = 0;
+    let match: RegExpExecArray;
+    while ((match = regexp.exec(markdown)) !== null) {
+      if (match.index === regexp.lastIndex) {
+        regexp.lastIndex++;
+      }
+      newStr += markdown.substring(lastIndex, match.index) + match[0].replace('\\\\', '\\\\\\\\');
+      lastIndex = match.index + match[0].length;
+    }
+    newStr += markdown.substring(lastIndex);
+    return newStr;
+  }
+
+  private static decodeHTML(encodedHTML: string) {
+    const elem = document.createElement('textarea');
+    elem.innerHTML = encodedHTML;
+    return elem.value;
+  }
+
+  ngOnChanges(changes: SimpleChanges) {
+    if (this.data != null) {
+      this.render(this.data);
+    }
+  }
+
+  private render(markdown: string, decodeHtml = false): void {
+    if (this.katex) {
+      markdown = CustomMarkdownComponent.fixKatex(markdown);
+    }
+    const compiled = this.markdownService.compile(markdown, decodeHtml, this.emoji);
+    this.element.nativeElement.innerHTML = this.katex ? this.renderKatex(compiled) : compiled;
+    if (this.lineHighlight) {
+      CustomMarkdownComponent.setPluginOptions(this.element.nativeElement, {
+        dataLine: this.line,
+        dataLineOffset: this.lineOffset
+      });
+    }
+    if (this.lineNumbers) {
+      CustomMarkdownComponent.setPluginClass(this.element.nativeElement, PrismPlugin.LineNumbers);
+      CustomMarkdownComponent.setPluginOptions(this.element.nativeElement, { dataStart: this.start });
+    }
+    this.markdownService.highlight(this.element.nativeElement);
+  }
+
+  private renderKatex(compiledMarkdown: string): string {
+    const regexp = /\${1,2}[^$]+\${1,2}/g;
+    let newStr = '';
+    let lastIndex = 0;
+    let match: RegExpExecArray;
+    while ((match = regexp.exec(compiledMarkdown)) !== null) {
+      if (match.index === regexp.lastIndex) {
+        regexp.lastIndex++;
+      }
+      newStr += compiledMarkdown.substring(lastIndex, match.index);
+      const katex = match[0];
+      lastIndex = match.index + katex.length;
+      this.katexOptions.displayMode = katex.startsWith('$$') && katex.endsWith('$$');
+      const offset = this.katexOptions.displayMode ? 2 : 1;
+      const innerKatex = CustomMarkdownComponent.decodeHTML(katex.substring(offset, katex.length - offset))
+        .replace(/(^\s*)|(\s+$)/g, '');
+      newStr += this.markdownService.renderKatex('$' + innerKatex + '$', this.katexOptions);
+    }
+    newStr += compiledMarkdown.substring(lastIndex);
+    return newStr;
+  }
+
+}
diff --git a/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.html b/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.html
index fe6843e70a778497898e8deb431813613841fa7e..1f6ed32cfd5f2b5a741d60484e4933e9628835ac 100644
--- a/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.html
+++ b/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.html
@@ -2,25 +2,36 @@
   'dialog-action-buttons': true,
   'no-spacing': (spacing === false)
 }">
-  <mat-divider *ngIf="showDivider"></mat-divider>
   <div fxLayoutAlign="end">
-    <div fxLayout="row-reverse" fxLayoutGap="10px" class="buttons">
+    <div fxLayout="row-reverse"
+         fxLayoutGap="10px"
+         class="buttons">
       <button
+        [disabled]="confirmButtonDisabled"
         *ngIf="confirmButtonClickAction !== undefined"
         type="button"
         mat-flat-button
         class="mat-flat-button {{ confirmButtonType }}-confirm-button"
         attr.aria-labelledby="{{ ariaPrefix + 'confirm' | translate }}"
         (click)="performConfirmButtonClickAction()"
-      ><mat-icon *ngIf="buttonIcon" style="margin-right: 5px;">{{buttonIcon}}</mat-icon>{{ buttonsLabelSection + '.' + confirmButtonLabel | translate}}</button>
+      >
+        <mat-icon *ngIf="buttonIcon"
+                  style="margin-right: 5px;">{{buttonIcon}}</mat-icon>
+        {{ buttonsLabelSection + '.' + confirmButtonLabel | translate}}
+        <mat-icon *ngIf="showLoadingCycle" class="spinner-container">
+          <app-mat-spinner-overlay diameter="20" strokeWidth="2" [color]="'on-primary'"></app-mat-spinner-overlay>
+        </mat-icon>
+      </button>
       <button
+        [disabled]="cancelButtonDisabled"
         *ngIf="cancelButtonClickAction !== undefined"
         type="button"
         mat-flat-button
         class="cancel-button"
         attr.aria-labelledby="{{ ariaPrefix + 'cancel' | translate }}"
         (click)="performCancelButtonClickAction()"
-      >{{ buttonsLabelSection + '.cancel' | translate}}</button>
+      >{{ buttonsLabelSection + '.' + cancelButtonLabel | translate}}</button>
+
     </div>
   </div>
   <!--Hidden Div's for a11y-Descriptions-->
diff --git a/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.scss b/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.scss
index f05bfaa7fd20dec32f0eab59e64d0a322861c6b0..2a364a363221960de5e78c1cd26134fcda75bdfd 100644
--- a/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.scss
+++ b/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.scss
@@ -26,3 +26,8 @@
   background: var(--secondary);
   color: var(--on-secondary);
 }
+
+.spinner-container {
+  font-size: 14px;
+  margin-top: -2px;
+}
diff --git a/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.ts b/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.ts
index 4fa8c7d7d921f621413b051418a9510a16be5c15..9c52a26c86fd1a7c0cc143b9ce2a80e0a1f2779d 100644
--- a/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.ts
+++ b/src/app/components/shared/dialog/dialog-action-buttons/dialog-action-buttons.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, Input, Output } from '@angular/core';
+import { Component, OnInit, Input } from '@angular/core';
 
 /**
  * Available confirm button types.
@@ -16,6 +16,16 @@ export enum DialogConfirmActionButtonType {
 })
 export class DialogActionButtonsComponent implements OnInit {
 
+  /**
+   * gray out confirm button
+   */
+  @Input() confirmButtonDisabled: boolean = false
+
+  /**
+   * gray out cancel button
+   */
+  @Input() cancelButtonDisabled: boolean = false
+
   @Input() showDivider = true;
 
   /**
@@ -34,6 +44,11 @@ export class DialogActionButtonsComponent implements OnInit {
    */
   @Input() confirmButtonLabel: string;
 
+  /**
+   * The i18n label identifier of the confirm button.
+   */
+  @Input() cancelButtonLabel = 'cancel';
+
 
   /**
    * The confirm button type.
@@ -52,13 +67,14 @@ export class DialogActionButtonsComponent implements OnInit {
    */
   @Input() cancelButtonClickAction: (Function | undefined);
 
-  @Input() resetButtonClickAction: (Function | undefined);
 
   /**
    * TRUE if some spacing will be rendered above the action buttons.
    */
   @Input() spacing = true;
 
+  @Input() showLoadingCycle = false;
+
 
   /**
    * The ARIA identifier prefix.
@@ -83,7 +99,6 @@ export class DialogActionButtonsComponent implements OnInit {
     }
   }
 
-
   /**
    * Performs the cancel button click action.
    */
@@ -92,10 +107,4 @@ export class DialogActionButtonsComponent implements OnInit {
       this.cancelButtonClickAction();
     }
   }
-  public filterzu(): void{
-    if (this.resetButtonClickAction !== undefined) {
-      this.resetButtonClickAction();
-      
-    }
-  }
 }
diff --git a/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.html b/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.html
index 9284e8b2e8ed4a124697947a2890df604257abd5..6a744fbc7c74b8fc0392fc6961b117fb9faded10 100644
--- a/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.html
+++ b/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.html
@@ -1,11 +1,11 @@
 <div>
   <p>
-    <!--{{(isCollapsed) ? question : question | slice:0:maxShowedCharachters}}{{question.length > maxShowedCharachters && !isCollapsed? "..." : ""}} -->
-    <span *ngFor="let part Of partsOfQuestion; let i = index">{{part}}<mark *ngIf="i < partsOfQuestion.length -1">{{keyword}}</mark></span>
+    <span *ngFor="let part Of (isCollapsed?partsOfQuestion:partsOfShortQuestion); let i = index">{{part}}<mark
+      *ngIf="i < (isCollapsed?partsOfQuestion:partsOfShortQuestion).length-1">{{keyword}}</mark></span><span *ngIf="!isCollapsed && question.length > maxShowedCharachters">..</span>
     <button
           *ngIf = "question.length > maxShowedCharachters"
-          (click)="isCollapsed = !isCollapsed">
-          {{"dialog-comment.read-" + (!isCollapsed ? 'more': 'less') | translate}}
-    </button>
+          (click)="isCollapsed = !isCollapsed">{{"dialog-comment.read-"+(!isCollapsed?'more':'less') | translate}}</button>
   </p>
 </div>
+
+
diff --git a/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.scss b/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.scss
index 84e15614647e5b8ec2680f1c834fbfdcfc18b140..686326146d10cab32c45b67595c306f0190ae16b 100644
--- a/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.scss
+++ b/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.scss
@@ -15,6 +15,7 @@ button{
   background: none;
   font-weight: bold;
   border: 0px solid;
+  padding: 0%;
 }
 
 button:focus{
diff --git a/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.ts b/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.ts
index 3102627513ef19d75be15672b932553d54b74da2..77b32abda5c7f29d5fa3b4d559e558e36d3ad61a 100644
--- a/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.ts
+++ b/src/app/components/shared/dialog/topic-dialog-comment/topic-dialog-comment.component.ts
@@ -1,4 +1,6 @@
 import { Component, Input, OnInit } from '@angular/core';
+import { Language } from '../../../../models/comment';
+import { ProfanityFilterService } from '../../../../services/util/profanity-filter.service';
 
 @Component({
   selector: 'app-topic-dialog-comment',
@@ -8,17 +10,50 @@ import { Component, Input, OnInit } from '@angular/core';
 export class TopicDialogCommentComponent implements OnInit {
 
   @Input() question: string;
+  @Input() language: Language;
   @Input() keyword: string ;
   @Input() maxShowedCharachters: number;
-  @Input() isCollapsed = false;
-  constructor() { }
+  @Input() profanityFilter: boolean;
+  @Input() languageSpecific;
+  @Input() partialWords;
 
-  get partsOfQuestion(){
+  isCollapsed = false;
 
-    return this.question.slice(0,this.isCollapsed? this.question.length: this.maxShowedCharachters).split(new RegExp(this.keyword,'i')) ;
+  public badWords = [];
+  questionWithoutProfanity: string = undefined;
 
+  public parts: string[];
+  public partsWithoutProfanity: string[];
+  public partsShort: string[];
+  public partsWithoutProfanityShort: string[];
+
+  constructor(private profanityFilterService: ProfanityFilterService) {}
+
+  get partsOfQuestion() {
+    return this.profanityFilter ? this.partsWithoutProfanity : this.parts;
+  }
+
+  get partsOfShortQuestion(){
+    return this.profanityFilter ? this.partsWithoutProfanityShort : this.partsShort;
+  }
+
+  splitShortQuestion(question: string){
+    return question.slice(0, this.maxShowedCharachters).split(this.keyword);
+  }
+
+  splitQuestion(question: string){
+    return question.split(this.keyword);
   }
 
   ngOnInit(): void {
+    if (!this.language) {
+      return;
+    }
+    this.questionWithoutProfanity = this.profanityFilterService.
+                                    filterProfanityWords(this.question, this.partialWords, this.languageSpecific, this.language);
+    this.partsWithoutProfanity = this.splitQuestion(this.questionWithoutProfanity);
+    this.parts = this.splitQuestion(this.question);
+    this.partsWithoutProfanityShort = this.splitShortQuestion(this.questionWithoutProfanity);
+    this.partsShort = this.splitShortQuestion(this.question);
   }
 }
diff --git a/src/app/components/shared/footer/footer.component.html b/src/app/components/shared/footer/footer.component.html
index dd8f018bdbd26b6e04430044ba0739cc74a0eac5..5085b2af4fc667b259ae48732fbf6b85e0b45e13 100644
--- a/src/app/components/shared/footer/footer.component.html
+++ b/src/app/components/shared/footer/footer.component.html
@@ -1,9 +1,13 @@
 <div>
 
   <mat-toolbar class="mat-elevation-z24"
-               id="footer-toolbar">
+               id="footer-toolbar"
+               *ngIf="!router.url.endsWith('/quiz')">
 
     <button (click)="showDemo()"
+            [joyrideStep]="'introduction'"
+            [stepPosition]="'center'"
+            appJoyrideTemplate
             aria-labelledby="demo-label"
             class="focus_button"
             mat-button>
@@ -27,6 +31,7 @@
 
     <span class="fill-remaining-space"></span>
     <button [matMenuTriggerFor]="langMenu"
+            (menuOpened)="openMenu()"
             aria-labelledby="language-label"
             class="focus_button"
             id="language-menu"
@@ -87,9 +92,6 @@
             <div class="title">
               <p class="title_bold">{{theme.getName(getLanguage())}}</p>
             </div>
-            <div class="title">
-              <p>{{theme.getDescription(getLanguage())}}</p>
-            </div>
           </div>
         </div>
       </button>
diff --git a/src/app/components/shared/footer/footer.component.scss b/src/app/components/shared/footer/footer.component.scss
index 57723619c9ee34f3bbdd97e10cc4193196bfe863..d573680c25e8947d59d04c987ca227bae496ab94 100644
--- a/src/app/components/shared/footer/footer.component.scss
+++ b/src/app/components/shared/footer/footer.component.scss
@@ -66,6 +66,7 @@ mat-icon {
   width: 100%!important;
   background-color: var(--dialog);
   color: var(--on-dialog);
+  min-width: unset !important;
 }
 
 ::ng-deep .mat-menu-item {
@@ -86,9 +87,7 @@ mat-icon {
 }
 
 ::ng-deep .color-menu{
-  min-width:280px!important;
-  max-width:280px!important;
-  width:280px!important;
+  width:170px!important;
 }
 
 @media (max-width: 500px){
@@ -106,14 +105,13 @@ mat-icon {
   outline:none;
   background-color:transparent;
   float:left;
-  border:none;
   margin:0px;
   padding:0px;
   cursor:pointer;
 }
 
 ::ng-deep .color-menu button:last-child{
-  margin-bottom:5px;
+  margin-bottom:10px;
 }
 
 .btnContent{
@@ -121,7 +119,6 @@ mat-icon {
   height:50px;
   float:left;
   margin-bottom:5px;
-  border-radius:2px;
 }
 
 .btnContent>.btnColorIcon{
@@ -130,6 +127,7 @@ mat-icon {
   float:left;
   margin:5px;
   padding:0px;
+  border-radius: 20px;
 }
 
 .checked{
@@ -139,6 +137,8 @@ mat-icon {
   float:left;
   border-radius:100%;
   transition:all 0.1s;
+  border-color: var(--red) !important;
+  border-width: thick !important;
 }
 
 .checked.checked_true{
@@ -193,13 +193,10 @@ mat-icon {
   white-space: nowrap;
   float:left;
   padding:0px;
-  margin:0px;
   margin-left:15px;
-  color:var(--on-dialog);
 }
 
 .title_bold{
-  color:rgba(0,0,0,0.9);
   font-weight:500;
 }
 
diff --git a/src/app/components/shared/footer/footer.component.ts b/src/app/components/shared/footer/footer.component.ts
index 2af9c97542e300c39ccd7da357725bd7790811b2..ce858113a5af58684f945f48a91034c12ab2a8fb 100644
--- a/src/app/components/shared/footer/footer.component.ts
+++ b/src/app/components/shared/footer/footer.component.ts
@@ -1,5 +1,5 @@
-import { LanguageService } from './../../../services/util/language.service';
-import { Component, OnInit } from '@angular/core';
+import { LanguageService } from '../../../services/util/language.service';
+import { Component, OnInit, ViewChild } from '@angular/core';
 import { NotificationService } from '../../../services/util/notification.service';
 import { Router } from '@angular/router';
 import { MatDialog } from '@angular/material/dialog';
@@ -18,6 +18,7 @@ import { AppComponent } from '../../../app.component';
 import { StyleService } from '../../../../../projects/ars/src/lib/style/style.service';
 import { MotdService } from '../../../services/http/motd.service';
 import { MotdDialogComponent } from '../_dialogs/motd-dialog/motd-dialog.component';
+import { MatMenu } from '@angular/material/menu';
 
 @Component({
   selector: 'app-footer',
@@ -26,6 +27,8 @@ import { MotdDialogComponent } from '../_dialogs/motd-dialog/motd-dialog.compone
 })
 export class FooterComponent implements OnInit {
 
+  @ViewChild('langMenu') langaugeMenu: MatMenu;
+
   public demoId = 'Feedback';
 
   public room: Room;
@@ -68,17 +71,6 @@ export class FooterComponent implements OnInit {
       });
     });
     this.deviceType = localStorage.getItem('deviceType');
-    if (!this.themeService.getThemeByKey(this.themeClass) || !this.themeService.getTheme()['source']['_value']) {
-      if (this.deviceType === 'mobile') {
-        this.themeService.activate('dark');
-        this.themeClass = 'dark';
-      } else {
-        // this.themeService.activate('arsnova');
-        // this.themeClass = 'arsnova';
-        this.themeService.activate('dark');
-        this.themeClass = 'dark';
-      }
-    }
     this.styleService.setColor(this.themeService.getThemeByKey(this.themeClass).isDark);
     this.translateService.use(localStorage.getItem('currentLang'));
     this.translateService.get('footer.open').subscribe(message => {
@@ -177,4 +169,12 @@ export class FooterComponent implements OnInit {
   getLanguage(): string {
     return localStorage.getItem('currentLang');
   }
+
+  openMenu() {
+    if (this.getLanguage() === 'de') {
+      this.langaugeMenu._allItems.get(0).focus();
+    } else if (this.getLanguage() === 'en') {
+      this.langaugeMenu._allItems.get(1).focus();
+    }
+  }
 }
diff --git a/src/app/components/shared/header/header.component.html b/src/app/components/shared/header/header.component.html
index 757110d6f6fa5342988a9933d2821b58f6f01a88..0e259e40f1b844231781329f63615d9bde829c42 100644
--- a/src/app/components/shared/header/header.component.html
+++ b/src/app/components/shared/header/header.component.html
@@ -1,5 +1,7 @@
 <mat-toolbar class="mat-elevation-z2">
-  <mat-toolbar-row>
+  <mat-toolbar-row
+    [ngClass]="{'mat-toolbar-moderation': router.url.endsWith('/moderator/comments')}">
+
     <button id="back-button"
             mat-icon-button
             aria-labelledby="back-label"
@@ -8,40 +10,102 @@
       <mat-icon class="header-icons">arrow_back</mat-icon>
     </button>
 
+    <button id="tour-button"
+            mat-button
+            aria-labelledby="tour-label"
+            class="focus_button"
+            *ngIf="router.url.endsWith('/home')"
+            (click)="startTour()">
+      <mat-icon class="header-icons">flag</mat-icon>
+      <span *ngIf="deviceType === 'desktop'">
+        {{ 'header.tour' | translate }}
+      </span>
+    </button>
+
+    <ng-container *ngIf="toggleUserActivity">
+      <div class="userActivityIcon"
+           matTooltip="{{'header.users-online' | translate}}"></div>
+      <p class="userActivityTxt">{{userActivity}}</p>
+    </ng-container>
+
+    <span class="fill-remaining-space"
+          *ngIf="router.url.endsWith('/moderator/comments')"></span>
+
+    <h2 class="oldtypo-h2"
+        *ngIf="router.url.endsWith('/moderator/comments') && deviceType === 'desktop'">
+      {{'header.moderation-warning'|translate}}
+    </h2>
+
     <span class="fill-remaining-space"></span>
 
     <h2 class="oldtypo-h2"
-        *ngIf="router.url.includes('comments')  && deviceType === 'desktop'"
-        fxLayoutAlign="center center">
+        *ngIf="deviceType === 'desktop' && router.url !== '/home'">
       {{cTime}}
     </h2>
 
-    <!--
-    <span *ngIf="router.url.includes('comments')  && !router.url.includes('moderator/comments') && deviceType === 'desktop'"
-          class="fill-remaining-space"></span>
     <span class="fill-remaining-space"
-          *ngIf="router.url.includes('comments') && deviceType === 'desktop'"></span>
-    <span
-      *ngIf="router.url.includes('comments') && moderationEnabled"
-      class="moderation-enabled"
-      fxLayoutAlign="center center">
-    <mat-icon matTooltip="{{ 'header.moderation-enabled' | translate }}">
-      gavel
-    </mat-icon>
-  </span>
+          *ngIf="room && room.questionsBlocked"></span>
+
+    <h1
+      *ngIf="room && room.questionsBlocked">
+      {{'header.questions-blocked'|translate}}
+    </h1>
+
+    <!--Topic Cloud-->
+    <div class="topic-cloud-btns"
+         [ngClass]="{'noOfQuestions': deviceType === 'desktop'}"
+         *ngIf="router.url.includes('tagcloud')"
+         ars-flex-box>
+      <ars-col
+        [xp]="16"
+        [extra]="true">
+        <button mat-icon-button
+                *ngIf="isAdminConfigEnabled"
+                class="pseudo-button"
+                matRipple
+                matTooltip="{{'header.overview-admin-config-enabled' | translate}}">
+          <mat-icon class="oldtypo-h2 comment_tag-icon"
+                    style="color: red !important;">warning
+          </mat-icon>
+        </button>
+        <button mat-icon-button
+                class="pseudo-button"
+                matRipple
+                matTooltip="{{'header.overview-question-tooltip' | translate}}">
+          <mat-icon class="oldtypo-h2 comment_tag-icon">comment</mat-icon>
+          <span style="margin-left: 0.25em;">{{commentsCountQuestions}}</span>
+        </button>
+        <button mat-icon-button
+                class="pseudo-button"
+                matRipple
+                matTooltip="{{'header.overview-questioners-tooltip' | translate}}">
+          <mat-icon class="oldtypo-h2 comment_tag-icon">person</mat-icon>
+          <span style="margin-left: 0.25em;">{{commentsCountUsers}}</span>
+        </button>
+        <button mat-icon-button
+                class="pseudo-button"
+                matRipple
+                matTooltip="{{'header.overview-keywords-tooltip' | translate}}">
+          <mat-icon svgIcon="hashtag"
+                    class="oldtypo-h2 comment_tag-icon"></mat-icon>
+          <span style="margin-left: 0.25em;">{{commentsCountKeywords}}</span>
+        </button>
+      </ars-col>
+    </div>
 
-    <h2 class="oldtypo-h2"
-        id="shortId-header"
-        *ngIf="router.url.includes('comments')"
-        fxLayoutAlign="center center">
-      {{ shortId.slice(0, 4) }} {{  shortId.slice(4, 8) }}
-    </h2>-->
     <!--Feedback im Hörsaal-->
-    <h2 class="oldtypo-h2"
-        *ngIf="router.url.includes('home')"
+    <h2 class="header-slogan-mobile"
+        *ngIf="router.url.includes('home') && deviceType === 'mobile'"
+        fxLayoutAlign="center center">
+      {{ 'header.home-header-mobile' | translate }}
+    </h2>
+
+    <h2 class="header-slogan-desktop"
+        *ngIf="router.url.includes('home') && deviceType === 'desktop'"
         fxLayoutAlign="center center">
       {{ 'header.home-header' | translate }}
     </h2>
+
     <span class="fill-remaining-space"></span>
 
     <mat-menu #userMenu="matMenu"
@@ -106,18 +170,18 @@
           <!-- Question board -->
           <ng-container *ngIf="router.url.endsWith('/comments')">
 
-            <button mat-menu-item
-                    *ngIf="user && !router.url.endsWith('moderator/comments')"
-                    tabindex="0"
-                    (click)="navigateCreateQuestion();">
-              <mat-icon>
-                add
-              </mat-icon>
-              <span>{{'header.create-question' | translate}}</span>
-            </button>
-
             <ng-container>
 
+              <button mat-menu-item
+                      *ngIf="user && user.role > 0 && !router.url.includes('/comment/') && !router.url.endsWith('/tagcloud') && !router.url.endsWith('moderator/comments')"
+                      tabindex="0"
+                      (click)="showQRDialog();">
+                <mat-icon svgIcon="qrcode"
+                          class="header-icons qrcode">
+                </mat-icon>
+                <span>{{'header.room-qr' | translate}}</span>
+              </button>
+
               <button mat-menu-item
                       tabindex="0"
                       *ngIf="user && user.role > 0 && !router.url.includes('/participant/') && !router.url.endsWith('moderator/comments')"
@@ -130,22 +194,32 @@
 
               <button mat-menu-item
                       tabindex="0"
-                      *ngIf="deviceType !== 'mobile'"
+                      *ngIf="user && user.role >0 && deviceType !== 'mobile' && !router.url.endsWith('moderator/comments')"
                       routerLink="participant/room/{{shortId}}/comments/questionwall">
-                <mat-icon
-                  svgIcon="beamer">
+                <mat-icon class="beamer-icon"
+                          svgIcon="beamer">
                 </mat-icon>
                 <span>{{'header.questionwall' | translate}}</span>
               </button>
 
               <button mat-menu-item
                       tabindex="0"
+                      *ngIf="!router.url.endsWith('moderator/comments')"
                       (click)="navigateTopicCloud()">
                 <mat-icon>cloud
                 </mat-icon>
                 <span>{{'header.tag-cloud' | translate}}</span>
               </button>
 
+              <button mat-menu-item
+                      tabindex="0"
+                      *ngIf="!router.url.endsWith('moderator/comments')"
+                      routerLink="quiz">
+                <mat-icon>school
+                </mat-icon>
+                <span>{{'header.quiz-now' | translate}}</span>
+              </button>
+
             </ng-container>
             <ng-container *ngIf="router.url.includes('/participant/room/')">
             </ng-container>
@@ -154,26 +228,10 @@
             <ng-container *ngIf="router.url.includes('/creator/room/')">
             </ng-container>
 
-            <button mat-menu-item
-                    *ngIf="user"
-                    (click)="navigateExportQuestions()"
-                    tabindex="0">
-              <mat-icon>save</mat-icon>
-              <span>{{'header.export-questions' | translate}}</span>
-            </button>
-
-            <button mat-menu-item
-                    *ngIf="user && user.role > 0 && !router.url.includes('/participant/')"
-                    (click)="navigateDeleteQuestions()"
-                    tabindex="0">
-              <mat-icon class="color-warn">delete</mat-icon>
-              <span>{{'header.delete-questions' | translate}}</span>
-            </button>
-
           </ng-container>
 
           <!-- Session -->
-          <ng-container *ngIf="!router.url.endsWith('/comments') && !router.url.includes('/comment/')">
+          <ng-container *ngIf="!router.url.endsWith('/comments') && !router.url.includes('/comment/') && !router.url.endsWith('tagcloud')">
 
             <!-- app-room-participant-page -->
             <ng-container *ngIf="router.url.includes('/participant/room/')">
@@ -181,31 +239,24 @@
             <!-- app-room-creator-page -->
             <ng-container *ngIf="router.url.includes('/moderator/room/')">
             </ng-container>
+
             <!-- app-room-creator-page -->
-            <ng-container *ngIf="router.url.includes('/creator/room/')">
 
-              <button mat-menu-item
-                      *ngIf="user"
-                      (click)="navigateRoomBonusToken()"
-                      tabindex="0">
-                <mat-icon class="star">grade</mat-icon>
-                <span>{{'header.bonustoken' | translate}}</span>
-              </button>
+            <ng-container *ngIf="router.url.includes('/creator/room/')">
 
               <button mat-menu-item
-                      *ngIf="user"
-                      (click)="navigateExportQuestions()"
+                      (click)="navigateEditSessionDescription()"
                       tabindex="0">
-                <mat-icon>save</mat-icon>
-                <span>{{'header.export-questions' | translate}}</span>
+                <mat-icon>flag</mat-icon>
+                <span>{{'header.edit-session-description' | translate}}</span>
               </button>
 
               <button mat-menu-item
+                      (click)="navigateModeratorSettings()"
                       *ngIf="user"
-                      (click)="navigateDeleteQuestions()"
                       tabindex="0">
-                <mat-icon class="color-warn">delete</mat-icon>
-                <span>{{'header.delete-questions' | translate}}</span>
+                <mat-icon class="gavel">visibility_off</mat-icon>
+                <span>{{'header.moderation-mode' | translate}}</span>
               </button>
 
             </ng-container>
@@ -215,10 +266,9 @@
           <!-- Room General Options - bot -->
 
           <ng-container
-            *ngIf="user && user.role == 3 && !router.url.includes('/participant') && !router.url.includes('/comment/')">
+            *ngIf="user && user.role == 3 && !router.url.includes('/participant') && !router.url.endsWith('/comments') && !router.url.includes('/comment/') && !router.url.endsWith('tagcloud')">
 
             <button mat-menu-item
-                    *ngIf="user"
                     (click)="navigateModerator()"
                     tabindex="0">
               <mat-icon>gavel</mat-icon>
@@ -226,27 +276,48 @@
             </button>
 
             <button mat-menu-item
-                    *ngIf="user"
                     (click)="navigateTags()"
                     tabindex="0">
               <mat-icon svgIcon="comment_tag"></mat-icon>
               <span>{{'header.edit-tags' | translate}}</span>
             </button>
 
+            <button mat-menu-item
+                    *ngIf="user"
+                    (click)="navigateRoomBonusToken()"
+                    tabindex="0">
+              <mat-icon class="star">grade</mat-icon>
+              <span>{{'header.bonustoken' | translate}}</span>
+            </button>
+
+            <button mat-menu-item
+                    (click)="navigateExportQuestions()"
+                    tabindex="0">
+              <mat-icon>file_download</mat-icon>
+              <span>{{'header.export-questions' | translate}}</span>
+            </button>
+
+            <button mat-menu-item
+                    (click)="navigateProfanityFilter()"
+                    tabindex="0">
+              <mat-icon>clear</mat-icon>
+              <span>{{'header.profanity-filter' | translate}}</span>
+            </button>
+
           </ng-container>
 
           <button mat-menu-item
-                  *ngIf="user && user.role > 0 && !router.url.includes('/comment/') && !router.url.endsWith('/tagcloud')"
                   tabindex="0"
-                  (click)="showQRDialog();">
-            <mat-icon svgIcon="qrcode"
-                      class="header-icons qrcode">
+                  *ngIf="router.url.endsWith('/tagcloud')"
+                  (click)="navigateQuestionBoard()">
+            <mat-icon>
+              forum
             </mat-icon>
-            <span>{{'header.room-qr' | translate}}</span>
+            <span>{{'header.back-to-questionboard' | translate}}</span>
           </button>
 
           <button mat-menu-item
-                  *ngIf="router.url.endsWith('/tagcloud')"
+                  *ngIf="user && user.role >0 && router.url.endsWith('/tagcloud')"
                   tabindex="0"
                   (click)="navigateTopicCloudConfig()">
             <mat-icon aria-label="Configuration Icon">cloud</mat-icon>
@@ -254,31 +325,58 @@
           </button>
 
           <button mat-menu-item
-                  *ngIf="router.url.endsWith('/tagcloud')"
+                  *ngIf="user && user.role >0 && router.url.endsWith('/tagcloud')"
                   tabindex="0"
                   (click)="navigateTopicCloudAdministration()">
-            <mat-icon aria-hidden="false" aria-label="Control Icon">edit</mat-icon>
+            <mat-icon aria-hidden="false"
+                      aria-label="Control Icon">cloud
+            </mat-icon>
             <span>{{'header.tag-cloud-administration' | translate}}</span>
           </button>
 
+
           <button mat-menu-item
-                  *ngIf="router.url.endsWith('/tagcloud')"
                   tabindex="0"
-                  (click)="navigateCreateQuestion();">
-            <mat-icon>
-              add
+                  *ngIf="user && user.role > 0 && router.url.endsWith('/tagcloud')"
+                  (click)="startWorkerDialog()">
+            <mat-icon>update
             </mat-icon>
-            <span>{{'header.create-question' | translate}}</span>
+            <span>{{'header.update-spacy-keywords' | translate}}</span>
+          </button>
+
+          <button mat-menu-item
+                  *ngIf="router.url.endsWith('/comments') && !router.url.includes('/comment/') && !router.url.endsWith('tagcloud')"
+                  (click)="navigateExportQuestions()"
+                  tabindex="0">
+            <mat-icon>file_download</mat-icon>
+            <span>{{'header.export-questions' | translate}}</span>
           </button>
 
           <button mat-menu-item
                   tabindex="0"
-                  *ngIf="router.url.endsWith('/tagcloud')"
-                  routerLink="participant/room/{{shortId}}/comments">
-            <mat-icon>
-              forum
-            </mat-icon>
-            <span>{{'header.back-to-questionboard' | translate}}</span>
+                  *ngIf="user && user.role == 3 && !router.url.includes('/participant') && !router.url.endsWith('/comments') && !router.url.includes('/comment/') && !router.url.endsWith('tagcloud')"
+                  (click)="blockQuestions()"
+                  [ngClass]="{'color-warn': room && room.questionsBlocked}"
+          >
+            <mat-icon class="color-warn">block</mat-icon>
+            <span *ngIf="room && !room.questionsBlocked">{{'header.block' | translate}}</span>
+            <span *ngIf="room && room.questionsBlocked">{{'header.unlock' | translate}}</span>
+          </button>
+
+          <button mat-menu-item
+                  *ngIf="user && user.role == 3 && !router.url.includes('/participant') && !router.url.endsWith('/comments') && !router.url.includes('/comment/') && !router.url.endsWith('tagcloud')"
+                  (click)="navigateDeleteQuestions()"
+                  tabindex="0">
+            <mat-icon class="color-warn">delete_sweep</mat-icon>
+            <span>{{'header.delete-questions' | translate}}</span>
+          </button>
+
+          <button mat-menu-item
+                  *ngIf="user && user.role == 3 && !router.url.includes('/participant') && !router.url.endsWith('/comments') && !router.url.includes('/comment/') && !router.url.endsWith('tagcloud')"
+                  (click)="navigateDeleteRoom()"
+                  tabindex="0">
+            <mat-icon class="color-warn">delete</mat-icon>
+            <span>{{'header.delete-room' | translate}}</span>
           </button>
 
         </ng-container>
@@ -287,49 +385,93 @@
 
       <!-- General Options -->
 
+      <button mat-menu-item
+              *ngIf="user && user.role == 0 && !router.url.endsWith('/tagcloud') && !router.url.endsWith('/quiz')"
+              (click)="openUserBonusTokenDialog()"
+              tabindex="0">
+        <mat-icon class="star">grade</mat-icon>
+        <span>{{'header.user-bonus-token' | translate}}</span>
+      </button>
+
+
+      <ng-container *ngIf="router.url.endsWith('/comments') || router.url.endsWith('/tagcloud')">
+
+        <button mat-menu-item
+                *ngIf="user && user.role == 0"
+                tabindex="0"
+                routerLink="participant/room/{{shortId}}">
+          <mat-icon>
+            flag
+          </mat-icon>
+          <span>{{'header.back-to-room' | translate}}</span>
+        </button>
+
+        <button mat-menu-item
+                *ngIf="user && user.role == 3"
+                tabindex="0"
+                routerLink="creator/room/{{shortId}}">
+          <mat-icon>
+            settings
+          </mat-icon>
+          <span>{{'header.back-to-room-creator' | translate}}</span>
+        </button>
+
+        <button mat-menu-item
+                *ngIf="user && user.role == 2"
+                tabindex="0"
+                routerLink="moderator/room/{{shortId}}">
+          <mat-icon>
+            flag
+          </mat-icon>
+          <span>{{'header.back-to-room-moderator' | translate}}</span>
+        </button>
+
+      </ng-container>
+
+      <button mat-menu-item
+              *ngIf="user && router.url.endsWith('/quiz')"
+              tabindex="0"
+              (click)="navigateQuestionBoard()">
+        <mat-icon class="header-icons">forum</mat-icon>
+        <span>{{'header.back-to-questionboard' | translate}}</span>
+      </button>
+
       <button mat-menu-item
               *ngIf="user && !router.url.endsWith('/user')"
               routerLink="/user"
               tabindex="0">
-        <mat-icon class="sessions">view_list</mat-icon>
+        <mat-icon svgIcon="meeting_room"
+                  class="sessions"></mat-icon>
         <span *ngIf="!user.isGuest">{{'header.my-sessions' | translate}}</span>
         <span *ngIf="user.isGuest"
               svgIcon="meeting_room">{{'header.visited-sessions' | translate}}</span>
       </button>
 
       <button mat-menu-item
-              *ngIf="user"
-              (click)="openUserBonusTokenDialog()"
-              tabindex="0">
-        <mat-icon class="star">grade</mat-icon>
-        <span>{{'header.user-bonus-token' | translate}}</span>
+              aria-hidden="true"
+              *ngIf="isSafari === 'false'  && !router.url.includes('home')  && !router.url.endsWith('/quiz')"
+              (click)="getRescale().toggleState();">
+        <mat-icon class="fullscreen"
+                  (click)="getRescale().toggleState();">format_size
+        </mat-icon>
+        <span>{{'header.fullscreen' | translate}}</span>
       </button>
 
       <button mat-menu-item
               *ngIf="user"
               (click)="showMotdDialog()">
-        <mat-icon>
-          {{ motdState ? 'notifications_active' : 'notifications_none' }}
+        <mat-icon class="faq">
+          {{ motdState ? 'notifications_active' : 'help' }}
         </mat-icon>
         <span>{{'header.motd' | translate}}</span>
       </button>
 
-      <button mat-menu-item
-              aria-hidden="true"
-              *ngIf="isSafari === 'false'  && !router.url.includes('home')"
-              (click)="getRescale().toggleState();">
-        <mat-icon (click)="getRescale().toggleState();">format_size
-        </mat-icon>
-        <span>{{'header.fullscreen' | translate}}</span>
-      </button>
-
-      <mat-divider></mat-divider>
 
       <button mat-menu-item
-              *ngIf="user && !user.isGuest && user.loginId"
+              *ngIf="user && !user.isGuest && user.loginId && router.url.endsWith('/user')"
               (click)="openDeleteUserDialog()"
               tabindex="0">
-        <mat-icon class="color-warn">delete</mat-icon>
+        <mat-icon class="color-warn">delete_forever</mat-icon>
         <span>{{'header.delete-account' | translate}}</span>
       </button>
 
@@ -344,6 +486,9 @@
 
     <button [disabled]="cookiesDisabled()"
             mat-button
+            [joyrideStep]="'optionHeader'"
+            [stepPosition]="'center'"
+            appJoyrideTemplate
             *ngIf="user && deviceType === 'desktop'"
             [matMenuTriggerFor]="userMenu"
             aria-labelledby="session-label"
@@ -365,6 +510,9 @@
 
     <button [disabled]="cookiesDisabled()"
             mat-icon-button
+            [joyrideStep]="'optionHeader'"
+            [stepPosition]="'center'"
+            appJoyrideTemplate
             *ngIf="user && deviceType === 'mobile'"
             [matMenuTriggerFor]="userMenu"
             aria-labelledby="session-label">
@@ -379,6 +527,9 @@
     <button id="login-button"
             [disabled]="cookiesDisabled()"
             mat-button
+            [joyrideStep]="'loginButtonHeader'"
+            [stepPosition]="'center'"
+            appJoyrideTemplate
             *ngIf="!user && deviceType === 'desktop'"
             (click)=login(false)
             aria-labelledby="login-label">
@@ -391,6 +542,9 @@
 
     <button [disabled]="cookiesDisabled()"
             mat-icon-button
+            [joyrideStep]="'loginButtonHeader'"
+            [stepPosition]="'center'"
+            appJoyrideTemplate
             *ngIf="!user && deviceType === 'mobile'"
             (click)=login(false)
             aria-labelledby="login-label">
@@ -402,5 +556,6 @@
 <div class="visually-hidden">
   <div id="login-label">{{'header.accessibility-login' | translate}}</div>
   <div id="back-label">{{'header.accessibility-back' | translate}}</div>
+  <div id="tour-label">{{'header.accessibility-tour' | translate}}</div>
   <div id="session-label">{{'header.accessibility-session' | translate}}</div>
 </div>
diff --git a/src/app/components/shared/header/header.component.scss b/src/app/components/shared/header/header.component.scss
index 2cbe46f2d37731df916225704471332a85e17dec..e005bab75feb864636077c88a7f9586608f4448b 100644
--- a/src/app/components/shared/header/header.component.scss
+++ b/src/app/components/shared/header/header.component.scss
@@ -5,7 +5,13 @@
 }
 
 mat-toolbar {
-  background-color: var(--surface);
+  background-color: transparent;
+  box-shadow: none;
+  position: relative;
+}
+
+.mat-toolbar-moderation {
+  background-color: var(--moderator);
   position: relative;
 }
 
@@ -29,8 +35,35 @@ mat-toolbar-row {
   font-weight: bold;
 }
 
+.noOfQuestions {
+  position: absolute !important;
+  right: 130px !important;
+  padding: 10px !important;
+  margin: 0 !important;
+}
+
+.topic-cloud-btns {
+  > ars-col button {
+    margin-right: 0.75em;
+
+    &:hover, &:focus {
+      border: none;
+    }
+  }
+
+  > * {
+    overflow: hidden !important;
+    color: var(--on-surface);
+  }
+}
+
+.comment_tag-icon {
+  height: 18px !important;
+}
+
 .sessions {
-  color: var(--primary);
+  color: var(--primary) !important;
+  transform: scale(1.5);
 }
 
 h2 {
@@ -38,6 +71,19 @@ h2 {
   font-size: medium !important;
 }
 
+.header-slogan-desktop {
+  margin-right: 10px;
+  margin-left: 130px;
+  font-size: medium !important;
+  color: var(--on-background);
+}
+
+.header-slogan-mobile {
+  margin-left: 30px;
+  font-size: medium !important;
+  color: var(--on-background);
+}
+
 .label-icon {
   display: flex;
   align-items: center;
@@ -77,7 +123,7 @@ svg {
 }
 
 .beamer-icon {
-  transform: scale(1.5);
+  transform: scale(1.4);
 }
 
 .mat-menu-inner-title {
@@ -96,4 +142,65 @@ svg {
   * {
     background-color: transparent !important;
   }
+
+  *:hover {
+    color: var(--on-secondary) !important;
+    background-color: var(--secondary) !important;
+
+    mat-icon {
+      color: var(--on-secondary) !important;
+      background-color: var(--secondary) !important;
+    }
+  }
+
+}
+
+h1 {
+  color: red;
+}
+
+::ng-deep .mat-menu-item:hover .qrcode svg > path {
+  fill: var(--dialog) !important;
+  color: var(--dialog) !important;
+  background-color: var(--on-dialog) !important;
+}
+
+::ng-deep #cdk-overlay-0 .mat-menu-content > button:hover mat-icon {
+  color: white !important;
+  background-color: gray !important;
+}
+
+.userActivityIcon {
+  width: 25px;
+  height: 25px;
+  margin-left: 25px;
+  margin-bottom: 5px;
+  background-color: var(--primary);
+  -webkit-mask-image: url("../../../../assets/icons/activity.svg");
+  mask-image: url("../../../../assets/icons/activity.svg");
+  mask-repeat: no-repeat;
+  mask-position: center;
+  mask-size: 100% 100%;
+}
+
+.userActivityTxt {
+  color: var(--primary);
+  margin-left: 5px;
+  font-size: 14px;
+}
+
+.focus_button {
+  min-height: 28px;
+  font-size: 16px;
+  padding: unset;
+  color: var(--on-surface);
+
+  &:focus {
+    background: var(--on-surface);
+    color: var(--background);
+
+    mat-icon {
+      color: var(--background);
+    }
+  }
 }
diff --git a/src/app/components/shared/header/header.component.ts b/src/app/components/shared/header/header.component.ts
index 2378610f89b6628c30f7823ca4f10c8f55bc5340..8bf64ce5745a23bb16723a140fbd32a84c50a12b 100644
--- a/src/app/components/shared/header/header.component.ts
+++ b/src/app/components/shared/header/header.component.ts
@@ -6,7 +6,7 @@ import { User } from '../../../models/user';
 import { UserRole } from '../../../models/user-roles.enum';
 import { Location } from '@angular/common';
 import { TranslateService } from '@ngx-translate/core';
-import {MatDialog, MatDialogRef} from '@angular/material/dialog';
+import { MatDialog } from '@angular/material/dialog';
 import { LoginComponent } from '../login/login.component';
 import { DeleteAccountComponent } from '../_dialogs/delete-account/delete-account.component';
 import { UserService } from '../../../services/http/user.service';
@@ -20,9 +20,15 @@ import { RemindOfTokensComponent } from '../../participant/_dialogs/remind-of-to
 import { QrCodeDialogComponent } from '../_dialogs/qr-code-dialog/qr-code-dialog.component';
 import { BonusTokenService } from '../../../services/http/bonus-token.service';
 import { MotdService } from '../../../services/http/motd.service';
-import { RoomService } from '../../../services/http/room.service';
-//import {CloudConfigurationComponent} from "../_dialogs/cloud-configuration/cloud-configuration.component";
 import { TopicCloudFilterComponent } from '../_dialogs/topic-cloud-filter/topic-cloud-filter.component';
+import { RoomService } from '../../../services/http/room.service';
+import { Room } from '../../../models/room';
+import { TagCloudMetaData } from '../../../services/util/tag-cloud-data.service';
+import { WorkerDialogComponent } from '../_dialogs/worker-dialog/worker-dialog.component';
+import { WsRoomService } from '../../../services/websockets/ws-room.service';
+import { TopicCloudAdminService } from '../../../services/util/topic-cloud-admin.service';
+import { HeaderService } from '../../../services/util/header.service';
+import { OnboardingService } from '../../../services/util/onboarding.service';
 
 @Component({
   selector: 'app-header',
@@ -33,10 +39,18 @@ export class HeaderComponent implements OnInit {
   user: User;
   cTime: string;
   shortId: string;
-  deviceType: string;
   isSafari = 'false';
   moderationEnabled: boolean;
   motdState = false;
+  room: Room;
+  commentsCountQuestions = 0;
+  commentsCountUsers = 0;
+  commentsCountKeywords = 0;
+  isAdminConfigEnabled = false;
+  private _subscriptionRoomService = null;
+  toggleUserActivity = false;
+  userActivity = 0;
+  deviceType = localStorage.getItem('deviceType');
 
   constructor(public location: Location,
               private authenticationService: AuthenticationService,
@@ -49,21 +63,33 @@ export class HeaderComponent implements OnInit {
               private bonusTokenService: BonusTokenService,
               private _r: Renderer2,
               private motdService: MotdService,
-              private confirmDialog: MatDialog
+              private confirmDialog: MatDialog,
+              private roomService: RoomService,
+              private wsRoomService: WsRoomService,
+              private topicCloudAdminService: TopicCloudAdminService,
+              private headerService: HeaderService,
+              private onboardingService: OnboardingService
   ) {
   }
 
   ngOnInit() {
+    this.topicCloudAdminService.getAdminData.subscribe(data => {
+      this.isAdminConfigEnabled = !TopicCloudAdminService.isTopicRequirementDisabled(data);
+    });
     this.eventService.on('userLogin').subscribe(e => {
       this.motdService.checkNewMessage(() => {
         this.motdService.requestDialog();
       });
     });
+    this.eventService.on<TagCloudMetaData>('tagCloudHeaderDataOverview').subscribe(data => {
+      this.commentsCountQuestions = data.commentCount;
+      this.commentsCountUsers = data.userCount;
+      this.commentsCountKeywords = data.tagCount;
+    });
     if (localStorage.getItem('loggedin') !== null && localStorage.getItem('loggedin') === 'true') {
       this.authenticationService.refreshLogin();
     }
     const userAgent = navigator.userAgent;
-    console.log(userAgent);
     // Check if mobile device
     if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)) {
       // Check if IOS device
@@ -105,16 +131,34 @@ export class HeaderComponent implements OnInit {
       if (val instanceof NavigationEnd) {
         /* segments gets all parts of the url */
         const segments = this.router.parseUrl(this.router.url).root.children.primary.segments;
+        this.shortId = '';
+        this.room = null;
+        if (this._subscriptionRoomService) {
+          this._subscriptionRoomService.unsubscribe();
+          this._subscriptionRoomService = null;
+        }
+
         if (segments && segments.length > 2) {
           if (!segments[2].path.includes('%')) {
             this.shortId = segments[2].path;
             localStorage.setItem('shortId', this.shortId);
+            this.roomService.getRoomByShortId(this.shortId).subscribe(room => {
+              this.room = room;
+              this._subscriptionRoomService = this.wsRoomService.getRoomStream(this.room.id).subscribe(msg => {
+                const message = JSON.parse(msg.body);
+                if (message.type === 'RoomPatched') {
+                  this.room.questionsBlocked = message.payload.changes.questionsBlocked;
+                  this.moderationEnabled = message.payload.changes.moderated;
+                }
+              });
+            });
           }
         }
       }
     });
     this.moderationEnabled = (localStorage.getItem('moderationEnabled') === 'true') ? true : false;
 
+
     this._r.listen(document, 'keyup', (event) => {
       if (
         document.getElementById('back-button') &&
@@ -133,6 +177,13 @@ export class HeaderComponent implements OnInit {
     this.motdService.onNewMessage().subscribe(state => {
       this.motdState = state;
     });
+
+    this.headerService.onActivityChange(e => {
+      this.toggleUserActivity = e;
+    });
+    this.headerService.onUserChange(e => {
+      this.userActivity = e;
+    });
   }
 
   showMotdDialog() {
@@ -148,7 +199,7 @@ export class HeaderComponent implements OnInit {
   logout() {
     // ToDo: Fix this madness.
     if (this.user.authProvider === 'ARSNOVA_GUEST') {
-      this.bonusTokenService.getTokensByUserId(this.user.id).subscribe( list => {
+      this.bonusTokenService.getTokensByUserId(this.user.id).subscribe(list => {
         if (list && list.length > 0) {
           const dialogRef = this.dialog.open(RemindOfTokensComponent, {
             width: '600px'
@@ -182,6 +233,9 @@ export class HeaderComponent implements OnInit {
     this.location.back();
   }
 
+  startTour() {
+    this.onboardingService.startDefaultTour(true);
+  }
 
   login(isLecturer: boolean) {
     const dialogRef = this.dialog.open(LoginComponent, {
@@ -286,10 +340,28 @@ export class HeaderComponent implements OnInit {
     this.eventService.broadcast('navigate', 'createQuestion');
   }
 
+  public navigateDeleteRoom() {
+    this.eventService.broadcast('navigate', 'deleteRoom');
+  }
+
+  public navigateProfanityFilter() {
+    this.eventService.broadcast('navigate', 'profanityFilter');
+  }
+
+  public navigateEditSessionDescription() {
+    this.eventService.broadcast('navigate', 'editSessionDescription');
+  }
+
+  public navigateModeratorSettings() {
+    this.eventService.broadcast('navigate', 'moderatorSettings');
+  }
+
   public navigateTopicCloud() {
     const confirmDialogRef = this.confirmDialog.open(TopicCloudFilterComponent, {
       autoFocus: false
     });
+    confirmDialogRef.componentInstance.target = this.router.url + '/tagcloud';
+    confirmDialogRef.componentInstance.user = this.user;
   }
 
   public navigateTopicCloudConfig() {
@@ -300,4 +372,13 @@ export class HeaderComponent implements OnInit {
     this.eventService.broadcast('navigate', 'topicCloudAdministration');
   }
 
+  public blockQuestions() {
+    // flip state if clicked
+    this.room.questionsBlocked = !this.room.questionsBlocked;
+    this.roomService.updateRoom(this.room).subscribe();
+  }
+
+  public startWorkerDialog() {
+    WorkerDialogComponent.addWorkTask(this.dialog, this.room);
+  }
 }
diff --git a/src/app/components/shared/login/login.component.html b/src/app/components/shared/login/login.component.html
index 6084f3e5764271dc946f45be2052848991ef95b3..1f38df86f084878400297c7b0495a531509a43cb 100644
--- a/src/app/components/shared/login/login.component.html
+++ b/src/app/components/shared/login/login.component.html
@@ -74,7 +74,7 @@
     </a>
   </div>
 </form>
-<mat-divider></mat-divider>
+
 <div fxLayout="row"
      class="register">
   <p>{{ 'login.not-registered' | translate }}</p>
diff --git a/src/app/components/shared/login/login.component.scss b/src/app/components/shared/login/login.component.scss
index a60d2ef3697d4ba2132bb7fd18facb53a42cd28e..0ba3c185fa9df09414b17851be6e96945b5b02b9 100644
--- a/src/app/components/shared/login/login.component.scss
+++ b/src/app/components/shared/login/login.component.scss
@@ -101,3 +101,7 @@ h3 {
 .or {
   height: 30px;
 }
+
+::ng-deep .mat-form-field .mat-form-field-infix {
+  max-width: 500px;
+}
diff --git a/src/app/components/shared/mat-spinner-overlay/mat-spinner-overlay.component.html b/src/app/components/shared/mat-spinner-overlay/mat-spinner-overlay.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..d4b215643c4db78d04806c46d7053601c38df23d
--- /dev/null
+++ b/src/app/components/shared/mat-spinner-overlay/mat-spinner-overlay.component.html
@@ -0,0 +1,18 @@
+<ng-container *ngIf="overlay;else progressSpinner">
+  <div class="overlay {{color}}">
+    <div class="center">
+      <ng-template [ngTemplateOutlet]="progressSpinner"></ng-template>
+    </div>
+  </div>
+</ng-container>
+<ng-template #progressSpinner>
+  <mat-progress-spinner
+    #containerRef
+    [ngClass]="{'inline-spinner': !overlay}"
+    class="{{color}}-spinner"
+    [diameter]="diameter"
+    [mode]="mode"
+    [strokeWidth]="strokeWidth"
+    [value]="value">
+  </mat-progress-spinner>
+</ng-template>
diff --git a/src/app/components/shared/mat-spinner-overlay/mat-spinner-overlay.component.scss b/src/app/components/shared/mat-spinner-overlay/mat-spinner-overlay.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..8027de8ea767f0370e64c9b1418fa00bceceba87
--- /dev/null
+++ b/src/app/components/shared/mat-spinner-overlay/mat-spinner-overlay.component.scss
@@ -0,0 +1,48 @@
+.center {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+}
+
+mat-progress-spinner {
+  -moz-transform: translateX(-50%) translateY(-50%);
+  -webkit-transform: translateX(-50%) translateY(-50%);
+  transform: translateX(-50%) translateY(-50%);
+}
+
+.overlay {
+  height: 100vh;
+  width: 100%;
+  background-color: var(--background);
+  opacity: 0.5;
+  z-index: 10;
+  top: 0;
+  left: 0;
+  position: fixed;
+}
+
+mat-progress-spinner.inline-spinner {
+  display: inline;
+  margin-left: 0.25em;
+  top: 0.115em;
+}
+
+mat-progress-spinner.primary-spinner, mat-progress-spinner.secondary-spinner {
+  color: var(--on-background);
+}
+
+mat-progress-spinner.on-primary-spinner {
+  color: var(--on-primary);
+}
+
+mat-progress-spinner.primary-spinner.inline-spinner {
+  color: var(--primary);
+}
+
+mat-progress-spinner.on-secondary-spinner {
+  color: var(--on-secondary);
+}
+
+mat-progress-spinner.secondary-spinner.inline-spinner {
+  color: var(--secondary);
+}
diff --git a/src/app/components/shared/mat-spinner-overlay/mat-spinner-overlay.component.spec.ts b/src/app/components/shared/mat-spinner-overlay/mat-spinner-overlay.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e984205b8f4ded729d07b6a92c8a305a125111e9
--- /dev/null
+++ b/src/app/components/shared/mat-spinner-overlay/mat-spinner-overlay.component.spec.ts
@@ -0,0 +1,26 @@
+/*import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MatSpinnerOverlayComponent } from './mat-spinner-overlay.component';
+
+describe('MatSpinnerOverlayComponent', () => {
+  let component: MatSpinnerOverlayComponent;
+  let fixture: ComponentFixture<MatSpinnerOverlayComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ MatSpinnerOverlayComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(MatSpinnerOverlayComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
+ */
diff --git a/src/app/components/shared/mat-spinner-overlay/mat-spinner-overlay.component.ts b/src/app/components/shared/mat-spinner-overlay/mat-spinner-overlay.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e04fcd09496f6749345fcb3ee28f6dee66f53a37
--- /dev/null
+++ b/src/app/components/shared/mat-spinner-overlay/mat-spinner-overlay.component.ts
@@ -0,0 +1,61 @@
+import {
+  AfterViewInit,
+  Component,
+  ElementRef,
+  Input,
+  OnInit,
+  Renderer2,
+  RendererStyleFlags2,
+  ViewChild
+} from '@angular/core';
+import { ProgressSpinnerMode } from '@angular/material/progress-spinner';
+
+export type SpinnerTheme = 'primary' | 'on-primary' | 'secondary' | 'on-secondary';
+
+@Component({
+  selector: 'app-mat-spinner-overlay',
+  templateUrl: './mat-spinner-overlay.component.html',
+  styleUrls: ['./mat-spinner-overlay.component.scss']
+})
+export class MatSpinnerOverlayComponent implements OnInit, AfterViewInit {
+
+  @ViewChild('containerRef') containerRef: ElementRef;
+  @Input() value = 100;
+  @Input() diameter = 100;
+  @Input() mode: ProgressSpinnerMode = 'indeterminate';
+  @Input() strokeWidth = 10;
+  @Input() overlay = false;
+  /**
+   * Overrides diameter and strokeWidth settings, only possible if overlay is false
+   */
+  @Input() parentFontContainer: HTMLElement = null;
+  @Input() color: SpinnerTheme = 'primary';
+
+  constructor(private element: ElementRef<HTMLElement>,
+              private renderer2: Renderer2) {
+  }
+
+  ngOnInit(): void {
+    if (this.parentFontContainer && !this.overlay) {
+      const elem = this.renderer2.createElement('canvas');
+      const ctx = elem.getContext('2d');
+      const style = window.getComputedStyle(this.parentFontContainer);
+      ctx.font = style.font;
+      const metric = ctx.measureText(this.parentFontContainer.innerText);
+      this.diameter = Math.abs(metric.fontBoundingBoxAscent) + Math.abs(metric.actualBoundingBoxDescent);
+      this.strokeWidth = this.diameter / 10;
+    }
+  }
+
+  ngAfterViewInit() {
+    const svg = this.element.nativeElement.getElementsByTagName('svg');
+    if (svg.length < 1) {
+      return;
+    }
+    this.renderer2.setStyle(svg[0], 'position', 'static');
+    if (svg[0].firstElementChild) {
+      this.renderer2.setStyle(svg[0].firstElementChild, 'stroke', 'currentColor', RendererStyleFlags2.Important);
+    }
+  }
+
+}
diff --git a/src/app/components/shared/overlay/active-user/active-user.component.html b/src/app/components/shared/overlay/active-user/active-user.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..53cd8d3a98b3d51438d7763c7b5261bebf0aae8e
--- /dev/null
+++ b/src/app/components/shared/overlay/active-user/active-user.component.html
@@ -0,0 +1,16 @@
+<div class="activityIcon" *ngIf="showByComponent" [ngStyle]="{
+    'left':left+'px',
+    'top':top+'px'
+  }" #divElement>
+  <div class="activityIconBackground" [ngStyle]="{
+    'background-color':iconColor
+    }"></div>
+  <div class="activityIconForeground" aria-hidden="true">
+    <p class="activityIconForegroundText" [ngStyle]="{
+      'background-color':backgroundColor,
+      'color':foregroundColor
+      }">
+      {{activeUser}}
+    </p>
+  </div>
+</div>
diff --git a/src/app/components/shared/overlay/active-user/active-user.component.scss b/src/app/components/shared/overlay/active-user/active-user.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..0cae9ce21377aea41b3b2853d9fcf1e041077148
--- /dev/null
+++ b/src/app/components/shared/overlay/active-user/active-user.component.scss
@@ -0,0 +1,61 @@
+
+.activityIcon {
+  width: 64px;
+  height: 64px;
+  position: fixed;
+  top: 80px;
+  left: 20px;
+
+  .activityIconForeground {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+
+    .activityIconForegroundText {
+      position: relative;
+      font-family: 'Roboto', sans-serif;
+      font-size: 24px;
+      font-weight: bold;
+      box-shadow: none !important;
+      right: -75px;
+      background-color: transparent !important;
+      color: var(--primary) !important;
+      animation:popin-shadow 0.4s cubic-bezier(0.680, -0.550, 0.265, 1.550) both;
+    }
+  }
+  .activityIconBackground {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    background-color:var(--primary) !important;
+    -webkit-mask-image: url("../../../../../assets/icons/activity.svg");
+    mask-image: url("../../../../../assets/icons/activity.svg");
+    mask-repeat: no-repeat;
+    mask-position: center;
+    mask-size: 100% 100%;
+    animation:shake 0.4s cubic-bezier(0.680, -0.550, 0.265, 1.550) both;
+  }
+}
+
+@keyframes shake {
+  0% {
+    transform: translateY(-10px);
+  }
+  100% {
+    transform: translateY(0px);
+  }
+}
+
+@keyframes popin-shadow {
+  0% {
+    transform: scale(0);
+    box-shadow: 0 0 0 0 transparent;
+    opacity:0;
+  }
+  50%{
+    opacity:1;
+  }
+  100% {
+    transform: scale(1);
+  }
+}
diff --git a/src/app/components/shared/overlay/active-user/active-user.component.spec.ts b/src/app/components/shared/overlay/active-user/active-user.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1fdf99ae52be744a5e157d447310ed837cbe6511
--- /dev/null
+++ b/src/app/components/shared/overlay/active-user/active-user.component.spec.ts
@@ -0,0 +1,25 @@
+// import { ComponentFixture, TestBed } from '@angular/core/testing';
+//
+// import { ActiveUserComponent } from './active-user.component';
+//
+// describe('ActiveUserComponent', () => {
+//   let component: ActiveUserComponent;
+//   let fixture: ComponentFixture<ActiveUserComponent>;
+//
+//   beforeEach(async () => {
+//     await TestBed.configureTestingModule({
+//       declarations: [ ActiveUserComponent ]
+//     })
+//     .compileComponents();
+//   });
+//
+//   beforeEach(() => {
+//     fixture = TestBed.createComponent(ActiveUserComponent);
+//     component = fixture.componentInstance;
+//     fixture.detectChanges();
+//   });
+//
+//   it('should create', () => {
+//     expect(component).toBeTruthy();
+//   });
+// });
diff --git a/src/app/components/shared/overlay/active-user/active-user.component.ts b/src/app/components/shared/overlay/active-user/active-user.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..72482cf46d2479b48cdf4a5bf14af6260338fe34
--- /dev/null
+++ b/src/app/components/shared/overlay/active-user/active-user.component.ts
@@ -0,0 +1,57 @@
+import {AfterViewInit,Component,Input,OnDestroy,OnInit,ViewChild} from '@angular/core';
+import {Room} from '../../../../models/room';
+import {ActiveUserService} from '../../../../services/http/active-user.service';
+import {HeaderService} from '../../../../services/util/header.service';
+
+@Component({
+  selector:'app-active-user',
+  templateUrl:'./active-user.component.html',
+  styleUrls:['./active-user.component.scss']
+})
+export class ActiveUserComponent implements OnInit,OnDestroy{
+
+  @Input() room: Room;
+  @Input() iconColor: string;
+  @Input() foregroundColor: string;
+  @Input() backgroundColor: string;
+  @Input() left: number;
+  @Input() top: number;
+  @Input() alwaysShowInHeader: boolean;
+  @ViewChild('divElement') elem: HTMLElement;
+  activeUser=0;
+  onDestroyListener: (() => void)[]=[];
+  onValueChangeListener: ((user: number) => void)[]=[];
+  deviceType;
+  showByComponent: boolean;
+
+  constructor(
+    private activeUserService: ActiveUserService,
+    private headerService: HeaderService
+  ){
+    this.deviceType=localStorage.getItem('deviceType');
+  }
+
+  ngOnInit(): void{
+    if(this.deviceType&&(this.deviceType==='mobile'||this.alwaysShowInHeader)){
+      this.showByComponent=false;
+      this.headerService.toggleCurrentUserActivity(true);
+      this.onDestroyListener.push(()=>this.headerService.toggleCurrentUserActivity(false));
+      this.onValueChangeListener.push(num=>this.headerService.setCurrentUserActivity(num));
+    } else{
+      this.showByComponent=true;
+    }
+    this.onDestroyListener.push(
+      this.activeUserService.observeUserActivity(this.room,user=>{
+        if(user!==null){
+          this.activeUser=user;
+          this.onValueChangeListener.forEach(e=>e(user));
+        }
+      })
+    );
+  }
+
+  ngOnDestroy(){
+    this.onDestroyListener.forEach(e=>e());
+  }
+
+}
diff --git a/src/app/components/shared/questionwall/QuestionWallComment.ts b/src/app/components/shared/questionwall/QuestionWallComment.ts
index 2ba8c70b625a55cf5157443b6fd62beb0d77718c..b33b8b483adaae07aba4a6e39d7eb51ce04d99a7 100644
--- a/src/app/components/shared/questionwall/QuestionWallComment.ts
+++ b/src/app/components/shared/questionwall/QuestionWallComment.ts
@@ -1,23 +1,22 @@
 import { Comment } from '../../../models/comment';
 
 export class QuestionWallComment {
-
   public static readonly TIME_FORMAT_DE: string[][] =
-    [
-      ['vor % Jahr', 'vor % Jahren'],
-      ['vor % Monat', 'vor % Monaten'],
-      ['vor % Tag', 'vor % Tagen'],
-      ['vor % Stunde', 'vor % Stunden'],
-      ['vor % Minute', 'vor % Minuten'],
-      ['vor % Sekunde', 'vor % Sekunden']
-    ];
+  [
+    ['vor % Jahr', 'vor % Jahren'],
+    ['vor % Monat', 'vor % Monaten'],
+    ['vor % Tag', 'vor % Tagen'],
+    ['vor % Stunde', 'vor % Stunden'],
+    ['vor % Minute', 'vor % Minuten'],
+    ['vor % Sekunde', 'vor % Sekunden']
+  ];
   public static readonly TIME_FORMAT_EN: string[][] = [
-      ['% year ago', '% years ago'],
-      ['% month ago', '% months ago'],
-      ['% day ago', '% days ago'],
-      ['% hour ago', '% hours ago'],
-      ['% minute ago', '% minutes ago'],
-      ['% second ago', '% seconds ago'],
+    ['% year ago', '% years ago'],
+    ['% month ago', '% months ago'],
+    ['% day ago', '% days ago'],
+    ['% hour ago', '% hours ago'],
+    ['% minute ago', '% minutes ago'],
+    ['% second ago', '% seconds ago'],
   ];
 
   public static currentTimeFormat: string[][] = QuestionWallComment.TIME_FORMAT_EN;
@@ -25,18 +24,18 @@ export class QuestionWallComment {
   public date: Date;
   public timeAgo: string;
 
-  public static updateTimeFormat(lang: string) {
-    this.currentTimeFormat = this['TIME_FORMAT_' + lang.toUpperCase()];
-  }
-
   constructor(
     public comment: Comment,
     public old: boolean
-  ) {
+    ) {
     this.date = new Date(comment.timestamp);
     this.updateTimeAgo();
   }
 
+  public static updateTimeFormat(lang: string) {
+    this.currentTimeFormat = this['TIME_FORMAT_' + lang.toUpperCase()];
+  }
+
   public update() {
   }
 
diff --git a/src/app/components/shared/questionwall/question-wall/question-wall.component.html b/src/app/components/shared/questionwall/question-wall/question-wall.component.html
index 09fd459a85d550dbb81b1b5b8a038b5b202c9b7f..b5c65f32b432ea53cd8a028ddbf6eef46a96fe10 100644
--- a/src/app/components/shared/questionwall/question-wall/question-wall.component.html
+++ b/src/app/components/shared/questionwall/question-wall/question-wall.component.html
@@ -1,3 +1,4 @@
+<app-mat-spinner-overlay *ngIf="isLoading" [overlay]="true"></app-mat-spinner-overlay>
 <ars-screen ars-flex-box class="questionwall-screen">
   <ars-row [height]="50" class="questionwall-header">
     <ars-style-btn-material *ngIf="room" style="width:100%;height:100%;" ars-flex-box>
@@ -6,6 +7,10 @@
           <button ars-btn (click)="leave()" matRipple aria-labelledby="back-lbl"><i>arrow_back</i></button>
         </ars-col>
       </ars-fill>
+      <ng-container *ngIf="room && room.questionsBlocked && !router.url.includes('/room-list/')">
+        <mat-icon>block</mat-icon>
+        <h2>{{'question-wall.questions-blocked'|translate}}</h2>
+      </ng-container>
       <ars-col>
         <!-- centered col -->
       </ars-col>
@@ -13,29 +18,32 @@
         <ars-fill></ars-fill>
         <ars-col ars-btn-wrp [xp]="16" [extra]="true">
           <mat-menu #sortMenu>
-            <button mat-menu-item (click)="sortTime(true)" aria-labelledby="sort-lbl-new">{{'question-wall.sort-new' | translate}}</button>
-            <button mat-menu-item (click)="sortTime()" aria-labelledby="sort-lbl-old">{{'question-wall.sort-old' | translate}}</button>
-            <button mat-menu-item (click)="sortScore(true)" aria-labelledby="sort-lbl-rating">{{'question-wall.sort-score' | translate}}</button>
+            <button mat-menu-item (click)="sortTime(true)"
+                    aria-labelledby="sort-lbl-new">{{'question-wall.sort-new' | translate}}</button>
+            <button mat-menu-item (click)="sortTime()"
+                    aria-labelledby="sort-lbl-old">{{'question-wall.sort-old' | translate}}</button>
+            <button mat-menu-item (click)="sortScore(true)"
+                    aria-labelledby="sort-lbl-rating">{{'question-wall.sort-score' | translate}}</button>
           </mat-menu>
           <mat-menu #filterMenu>
-            <button mat-menu-item (click)="filterFavorites()" aria-labelledby="filter-lbl-favorites">
+            <button mat-menu-item (click)="filterFavorites()" aria-labelledby="filter-lbl-favorites" class="selection">
               <mat-icon class="star">grade</mat-icon>
               <span>{{'question-wall.filter-favorite' | translate}}</span>
             </button>
 
-            <button mat-menu-item (click)="filterBookmark()" aria-labelledby="filter-lbl-bookmark">
+            <button mat-menu-item (click)="filterBookmark()" aria-labelledby="filter-lbl-bookmark" class="selection">
               <mat-icon>bookmark</mat-icon>
               <span>{{'question-wall.filter-bookmark' | translate}}</span>
             </button>
           </mat-menu>
           <mat-menu #filterTagMenu>
-            <button mat-menu-item *ngFor="let tag of tags" (click)="filterTag(tag)">
+            <button mat-menu-item *ngFor="let tag of tags" (click)="filterTag(tag)" class="selection">
               <span>{{tag}}</span>
             </button>
           </mat-menu>
           <mat-menu #timeMenu="matMenu" xPosition="before">
             <div *ngFor="let periodItem of periodsList">
-              <button mat-menu-item (click)="setTimePeriod(periodItem)" class="period"
+              <button mat-menu-item (click)="setTimePeriod(periodItem)" class="period selection"
                       [ngClass]="{'selected': periodItem === period}"
                       aria-labelledby="{{periodItem}}">
                 <span>{{ ('comment-list.select-' + periodItem) | translate }}</span>
@@ -81,6 +89,7 @@
             <p>Filter</p>
           </button>
           <button ars-btn
+                  [disabled]="tags.length==0"
                   [mat-menu-trigger-for]="filterTagMenu"
                   [ngClass]="{'selected': hasFilter && filterTitle === '' && filterDesc !== ''}"
                   matRipple
@@ -114,7 +123,9 @@
             </ars-row>
             <ars-row>
               <ars-row class="bound" style="padding:16px 32px 16px 32px;box-sizing:border-box;max-width:100%;">
-                <markdown [ngStyle]="{'font-size':fontSize+'%'}" class="questionwall-present-markdown" [data]="commentFocus.comment.body"></markdown>
+                <app-custom-markdown [ngStyle]="{'font-size':fontSize+'%'}"
+                                     class="questionwall-present-markdown images"
+                                     [data]="commentFocus.comment.body"></app-custom-markdown>
               </ars-row>
             </ars-row>
             <ars-row [height]="50">
@@ -208,18 +219,19 @@
                          style="box-sizing:border-box;padding:16px;cursor:pointer">
                   <ars-col class="questionwall-comment-meta">
                     <i class="questionwall-icon">person_pin_circle</i>
-                    <p (click)="filterUser(comment);" class="questionwall-comment-user" matRipple>{{comment.comment.userNumber}}</p>
+                    <p (click)="filterUser(comment);" class="questionwall-comment-user"
+                       matRipple>{{comment.comment.userNumber}}</p>
                     <p class="questionwall-comment-timestamp">{{comment.timeAgo}}</p>
                   </ars-col>
                   <ars-col>
-                    <p class="questionwall-comment-notification">{{comment.old?'':'NEW'}}</p>
+                    <p class="questionwall-comment-notification">{{comment.old ? '' : 'NEW'}}</p>
                   </ars-col>
                 </ars-row>
                 <ars-row
                   (click)="focusComment(comment)"
                   style="box-sizing:border-box;padding:0 16px;cursor:pointer">
                   <p class="questionwall-comment-body">
-                    <markdown [data]="comment.comment.body"></markdown>
+                    <app-custom-markdown class="images" [data]="comment.comment.body"></app-custom-markdown>
                   </p>
                 </ars-row>
                 <ars-row [height]="50">
@@ -234,7 +246,7 @@
                       </button>
                     </ars-col>
                     <ars-fill (click)="focusComment(comment)" style="cursor:pointer"></ars-fill>
-                    <ars-col ars-btn-wrp [xp]="16" [extra]="true"*ngIf="comment.comment.tag">
+                    <ars-col ars-btn-wrp [xp]="16" [extra]="true" *ngIf="comment.comment.tag">
                       <button ars-btn (click)="filterTag(comment.comment.tag);" matRipple>
                         <mat-icon class="icon-svg" svgIcon="comment_tag"></mat-icon>
                         <p>{{comment.comment.tag}}</p>
@@ -267,7 +279,8 @@
                 <p>{{'question-wall.filter-user-count' | translate}}</p>
               </button>
               <button ars-btn mat-ripple *ngFor="let user of userList" (click)="applyUserMap(user[1])">
-                <p>{{user[1]}}</p><p>{{user[0]}}</p>
+                <p>{{user[1]}}</p>
+                <p>{{user[0]}}</p>
               </button>
             </ars-row>
           </ars-style-btn-material>
@@ -307,8 +320,13 @@
       </ars-col>
     </ars-style-btn-material>
   </ars-row>
+  <app-active-user *ngIf="room" [room]="room"
+                   [iconColor]="'#FFFFFF'"
+                   [backgroundColor]="'#FFFFFF'"
+                   [foregroundColor]="'#000000'"></app-active-user>
 </ars-screen>
 
+
 <div class="visually-hidden">
   <div id="back-lbl">{{'question-wall.back-lbl' | translate}}</div>
   <div id="sort-lbl">{{'question-wall.sort-lbl' | translate}}</div>
diff --git a/src/app/components/shared/questionwall/question-wall/question-wall.component.scss b/src/app/components/shared/questionwall/question-wall/question-wall.component.scss
index 56653aab8fe296193c1f39a79d40efd93e428938..58dac5ddeb9628f3b4711f21fac53c92e5686cc1 100644
--- a/src/app/components/shared/questionwall/question-wall/question-wall.component.scss
+++ b/src/app/components/shared/questionwall/question-wall/question-wall.component.scss
@@ -181,6 +181,7 @@
           justify-content: center;
           hyphens: auto;
           word-break: break-word;
+          color: yellow;
         }
 
         &-inner {
@@ -298,3 +299,13 @@
 .selected {
   font-weight: bold;
 }
+
+.selection:focus {
+  background-color: black !important;
+}
+
+h2 {
+  color: red;
+  font-weight: normal !important;
+  padding-top: 10px !important;
+}
diff --git a/src/app/components/shared/questionwall/question-wall/question-wall.component.ts b/src/app/components/shared/questionwall/question-wall/question-wall.component.ts
index 8148af8a71b5aeea0174ddd555730624f52af07c..4506a8b84e2c671140ac26802d87e7fe1e5dea56 100644
--- a/src/app/components/shared/questionwall/question-wall/question-wall.component.ts
+++ b/src/app/components/shared/questionwall/question-wall/question-wall.component.ts
@@ -3,7 +3,7 @@ import { CommentService } from '../../../../services/http/comment.service';
 import { Comment } from '../../../../models/comment';
 import { RoomService } from '../../../../services/http/room.service';
 import { Room } from '../../../../models/room';
-import { WsCommentServiceService } from '../../../../services/websockets/ws-comment-service.service';
+import { WsCommentService } from '../../../../services/websockets/ws-comment.service';
 import { QuestionWallComment } from '../QuestionWallComment';
 import { ColComponent } from '../../../../../../projects/ars/src/lib/components/layout/frame/col/col.component';
 import { Router } from '@angular/router';
@@ -12,9 +12,9 @@ import { LanguageService } from '../../../../services/util/language.service';
 import { TranslateService } from '@ngx-translate/core';
 import { Rescale } from '../../../../models/rescale';
 import { QuestionWallKeyEventSupport } from '../QuestionWallKeyEventSupport';
-import { CorrectWrong } from '../../../../models/correct-wrong.enum';
 import { MatSliderChange } from '@angular/material/slider';
-import { Period } from '../../comment-list/comment-list.component';
+import { Period } from '../../../../utils/filter-options';
+import { RoomDataService } from '../../../../services/util/room-data.service';
 
 @Component({
   selector: 'app-question-wall',
@@ -47,31 +47,21 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy {
   userList = [];
   userSelection = false;
   tags;
-  fontSize = 250;
+  fontSize = 180;
   periodsList = Object.values(Period);
-  period: Period = Period.ALL;
-
-  public wrap<E>(e: E, action: (e: E) => void) {
-    action(e);
-  }
-
-  public notUndefined<E>(e: E, action: (e: E) => void, elsePart?: () => void) {
-    if (e) {
-      action(e);
-    } else if (elsePart) {
-      elsePart();
-    }
-  }
+  period: Period = Period.all;
+  isLoading = true;
 
   constructor(
     private authenticationService: AuthenticationService,
     private router: Router,
     private commentService: CommentService,
     private roomService: RoomService,
-    private wsCommentService: WsCommentServiceService,
+    private wsCommentService: WsCommentService,
     private langService: LanguageService,
-    private translateService: TranslateService
-  ) {
+    private translateService: TranslateService,
+    private roomDataService: RoomDataService
+    ) {
     this.keySupport = new QuestionWallKeyEventSupport();
     this.roomId = localStorage.getItem('roomId');
     this.timeUpdateInterval = setInterval(() => {
@@ -83,12 +73,29 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy {
     });
   }
 
+  public wrap<E>(e: E, action: (e: E) => void) {
+    action(e);
+  }
+
+  public notUndefined<E>(e: E, action: (e: E) => void, elsePart?: () => void) {
+    if (e) {
+      action(e);
+    } else if (elsePart) {
+      elsePart();
+    }
+  }
+
   ngOnInit(): void {
     QuestionWallComment.updateTimeFormat(localStorage.getItem('currentLang'));
     this.translateService.use(localStorage.getItem('currentLang'));
-    this.commentService.getAckComments(this.roomId).subscribe(e => {
+    this.roomDataService.getRoomData(this.roomId).subscribe(e => {
+      if (e === null) {
+        return;
+      }
       e.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
+      this.isLoading = false;
       e.forEach(c => {
+        this.roomDataService.checkProfanity(c);
         const comment = new QuestionWallComment(c, true);
         this.comments.push(comment);
         this.setTimePeriod(this.period);
@@ -99,20 +106,28 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy {
       this.room = e;
       this.tags = e.tags;
     });
-    this.wsCommentService.getCommentStream(this.roomId).subscribe(e => {
-      this.commentService.getComment(JSON.parse(e.body).payload.id).subscribe(comment => {
-        this.notUndefined(this.comments.find(f => f.comment.id === comment.id), qwComment => {
-          qwComment.comment = comment;
-        }, () => {
-          this.wrap(this.pushIncommingComment(comment), qwComment => {
-            if (this.focusIncommingComments) {
-              setTimeout(() => this.focusComment(qwComment), 5);
-            }
-          });
+    this.subscribeCommentStream();
+    this.initKeySupport();
+  }
+
+  subscribeCommentStream() {
+    this.roomDataService.receiveUpdates([
+      { type: 'CommentCreated', finished: true},
+      { type: 'CommentPatched', finished: true, updates: ['upvotes'] },
+      { type: 'CommentPatched', finished: true, updates: ['downvotes'] },
+      {finished: true}
+    ]).subscribe(update => {
+      if (update.type === 'CommentCreated') {
+        this.wrap(this.pushIncommingComment(update.comment), qwComment => {
+          if (this.focusIncommingComments) {
+            setTimeout(() => this.focusComment(qwComment), 5);
+          }
         });
-      });
+      } else if (update.type === 'CommentPatched') {
+        const qwComment = this.comments.find(f => f.comment.id === update.comment.id);
+        qwComment.comment = update.comment;
+      }
     });
-    this.initKeySupport();
   }
 
   updateCommentsCountOverview(): void {
@@ -183,6 +198,8 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy {
   }
 
   pushIncommingComment(comment: Comment): QuestionWallComment {
+    this.roomDataService.checkProfanity(comment);
+    console.log(comment);
     const qwComment = new QuestionWallComment(comment, false);
     this.comments = [qwComment, ...this.comments];
     this.setTimePeriod(this.period);
@@ -355,21 +372,21 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy {
     const currentTime = new Date();
     const hourInSeconds = 3600000;
     let periodInSeconds;
-    if (period !== Period.ALL) {
+    if (period !== Period.all) {
       switch (period) {
-        case Period.ONEHOUR:
+        case Period.oneHour:
           periodInSeconds = hourInSeconds;
           break;
-        case Period.THREEHOURS:
+        case Period.threeHours:
           periodInSeconds = hourInSeconds * 2;
           break;
-        case Period.ONEDAY:
+        case Period.oneDay:
           periodInSeconds = hourInSeconds * 24;
           break;
-        case Period.ONEWEEK:
+        case Period.oneWeek:
           periodInSeconds = hourInSeconds * 168;
           break;
-        case Period.TWOWEEKS:
+        case Period.twoWeeks:
           periodInSeconds = hourInSeconds * 336;
           break;
       }
diff --git a/src/app/components/shared/quiz-now/quiz-now.component.html b/src/app/components/shared/quiz-now/quiz-now.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..ecbb031e7aa4e1dc0c2924af2380dac708ea7872
--- /dev/null
+++ b/src/app/components/shared/quiz-now/quiz-now.component.html
@@ -0,0 +1,7 @@
+<app-mat-spinner-overlay *ngIf="isLoading" overlay="true"></app-mat-spinner-overlay>
+<div class="container">
+  <iframe class="responsive-iframe" [src]="urlSafe"
+          (load)="isLoading = false"
+          (error)="isLoading = false">
+  </iframe>
+</div>
diff --git a/src/app/components/shared/quiz-now/quiz-now.component.scss b/src/app/components/shared/quiz-now/quiz-now.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..c4785b36853df6e11b794b3f6b9a944a4163e941
--- /dev/null
+++ b/src/app/components/shared/quiz-now/quiz-now.component.scss
@@ -0,0 +1,18 @@
+iframe {
+  border-width: 0px;
+}
+
+.container {
+  width: auto;
+  height: auto;
+}
+
+.responsive-iframe {
+  position: absolute;
+  top: 56px;
+  left: 0;
+  bottom: 0;
+  right: 0;
+  width: 100%;
+  height: 100%;
+}
diff --git a/src/app/components/shared/quiz-now/quiz-now.component.spec.ts b/src/app/components/shared/quiz-now/quiz-now.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eb2e840793c039433251a26cf0633edbb570c159
--- /dev/null
+++ b/src/app/components/shared/quiz-now/quiz-now.component.spec.ts
@@ -0,0 +1,25 @@
+/*import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { QuizNowComponent } from './quiz-now.component';
+
+describe('QuizNowComponent', () => {
+  let component: QuizNowComponent;
+  let fixture: ComponentFixture<QuizNowComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ QuizNowComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(QuizNowComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});*/
diff --git a/src/app/components/shared/quiz-now/quiz-now.component.ts b/src/app/components/shared/quiz-now/quiz-now.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5993dc3dad3fe8f7c48bdc7f0df9a3dcb71fcfa3
--- /dev/null
+++ b/src/app/components/shared/quiz-now/quiz-now.component.ts
@@ -0,0 +1,46 @@
+import { Component, OnDestroy, OnInit } from '@angular/core';
+import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
+import { EventService } from '../../../services/util/event.service';
+import { Router } from '@angular/router';
+
+@Component({
+  selector: 'app-quiz-now',
+  templateUrl: './quiz-now.component.html',
+  styleUrls: ['./quiz-now.component.scss']
+})
+export class QuizNowComponent implements OnInit, OnDestroy {
+  urlSafe: SafeResourceUrl;
+  isLoading = true;
+  shortId: string;
+  roleString: string;
+  private _headerSubscription;
+
+  constructor(public sanitizer: DomSanitizer,
+              private router: Router,
+              private eventService: EventService) {
+    this.shortId = localStorage.getItem('shortId');
+    const access = (JSON.parse(localStorage.getItem('ROOM_ACCESS')) || []) as string[];
+    const roomAccess = access.find(e => e.endsWith('_' + this.shortId)) || '0_' + this.shortId;
+    const role = parseInt(roomAccess.substr(0, 1), 10);
+    if (role === 3) {
+      this.roleString = 'creator';
+    } else if (role > 0) {
+      this.roleString = 'moderator';
+    } else {
+      this.roleString = 'participant';
+    }
+  }
+
+  ngOnInit() {
+    this.urlSafe = this.sanitizer.bypassSecurityTrustResourceUrl('https://staging.antworte.jetzt/');
+    this._headerSubscription = this.eventService.on<string>('navigate').subscribe(action => {
+      if (action === 'questionBoard') {
+        this.router.navigate(['/' + this.roleString + '/room/' + this.shortId + '/comments']);
+      }
+    });
+  }
+
+  ngOnDestroy() {
+    this._headerSubscription.unsubscribe();
+  }
+}
diff --git a/src/app/components/shared/room-join/room-join.component.html b/src/app/components/shared/room-join/room-join.component.html
index 9385a9cb62e8c7f0379a9dfcf175451e4e4b5fe2..7162f3412ca36ad111d80c3e962bbe58a3965eb2 100644
--- a/src/app/components/shared/room-join/room-join.component.html
+++ b/src/app/components/shared/room-join/room-join.component.html
@@ -5,7 +5,11 @@
   <form (ngSubmit)="joinRoom(sessionCode.value)">
     <div fxLayout="row"
          fxLayoutAlign="center"
-         fxLayoutGap="10px">
+         fxLayoutGap="10px"
+         class="layoutWrapper"
+         [joyrideStep]="'roomJoin'"
+         [stepPosition]="'top'"
+         appJoyrideTemplate>
       <mat-form-field (keyup.enter)="onEnter()">
         <input
           id="session_id-input"
@@ -25,10 +29,11 @@
       </mat-form-field>
       <button [disabled]="cookiesDisabled()"
               id="session_enter-button"
-              mat-fab
+              mat-flat-button
               type="submit"
               aria-labelledby="join-button-label">
         <mat-icon svgIcon="meeting_room" class="join-room"></mat-icon>
+        {{'home-page.join-room' | translate}}
       </button>
     </div>
   </form>
diff --git a/src/app/components/shared/room-join/room-join.component.scss b/src/app/components/shared/room-join/room-join.component.scss
index 602a813b4384966d20956d9a653992ec8805be29..78b98bb606c6e686fb3eaab684e51ee526d4da88 100644
--- a/src/app/components/shared/room-join/room-join.component.scss
+++ b/src/app/components/shared/room-join/room-join.component.scss
@@ -1,21 +1,18 @@
 mat-form-field {
-  font-size: larger;
   color: var(--on-surface);
 }
 
+.layoutWrapper {
+  padding-left: 15px;
+}
+
 form {
   padding-top: 5%;
 }
 
 mat-error {
   font-size: small;
-}
-
-.mat-fab {
-  width: 65px;
-  height: 65px;
-  background-color: var(--primary);
-  color: var(--on-primary);
+  color: var(--red) !important;
 }
 
 input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button {
@@ -31,31 +28,40 @@ mat-hint {
 }
 
 ::ng-deep .mat-form-field-label {
-  color: var(--on-surface)!important;
+  color: var(--on-surface) !important;
 }
 
 ::ng-deep .mat-form-field-underline {
-  background-color: var(--on-surface)!important;
+  background-color: var(--on-surface) !important;
 }
 
 ::ng-deep .mat-form-field-ripple {
-  background-color: var(--on-surface)!important;
+  background-color: var(--on-surface) !important;
 }
 
 input:-webkit-autofill {
-  -webkit-box-shadow:0 0 0 50px var(--surface) inset;
+  -webkit-box-shadow: 0 0 0 50px var(--surface) inset;
   -webkit-text-fill-color: var(--on-surface);
 }
 
-mat-error{
-  color:var(--on-surface);
+mat-error {
+  color: var(--on-surface);
 }
 
-#session_enter-button:focus {
-  background: var(--on-surface);
-  color: var(--background);
+#session_enter-button {
+  width: 100%;
+  height: 60px;
+  font-size: large;
+  background-color: var(--background);
+  color: var(--on-background);
 }
 
 .join-room {
-  transform: scale(1.5);
+  padding-right: 5px;
+  transform: scale(2.0);
+  color: var(--primary);
+}
+
+::ng-deep .mat-form-field .mat-form-field-infix {
+  max-width: 130px;
 }
diff --git a/src/app/components/shared/room-join/room-join.component.ts b/src/app/components/shared/room-join/room-join.component.ts
index 66cf2e77a76724c2c9ee0f052e788432d13c520d..cc6a6ea8e23488cf3626cbab9095f34f5a2d9916 100644
--- a/src/app/components/shared/room-join/room-join.component.ts
+++ b/src/app/components/shared/room-join/room-join.component.ts
@@ -74,7 +74,7 @@ export class RoomJoinComponent implements OnInit {
   joinRoom(id: string): void {
     if (!this.sessionCodeFormControl.hasError('required') && !this.sessionCodeFormControl.hasError('minlength')) {
       if (!this.user) {
-        this.authenticationService.guestLogin(UserRole.CREATOR).subscribe(() => {
+        this.authenticationService.guestLogin(UserRole.PARTICIPANT).subscribe(() => {
           this.getRoom(id);
         });
       } else {
@@ -93,6 +93,7 @@ export class RoomJoinComponent implements OnInit {
 
   addAndNavigate() {
     if (this.user.id === this.room.ownerId) {
+      this.authenticationService.setAccess(this.room.shortId, UserRole.CREATOR);
       this.router.navigate([`/creator/room/${this.room.shortId}/comments`]);
     } else {
       this.roomService.addToHistory(this.room.id);
diff --git a/src/app/components/shared/room-list/room-list.component.html b/src/app/components/shared/room-list/room-list.component.html
index ba91b8547d2f22346f88c798f45b5d45bf214be0..28467a4acdbab66a8db8057ac19f289d183b97cf 100644
--- a/src/app/components/shared/room-list/room-list.component.html
+++ b/src/app/components/shared/room-list/room-list.component.html
@@ -1,11 +1,11 @@
 <div *ngIf="isLoading" fxLayout="column" fxLayoutAlign="center" fxFill>
   <div fxLayout="row" fxLayoutAlign="center">
-    <mat-progress-spinner color="primary" mode="indeterminate" diameter="80"></mat-progress-spinner>
+    <app-mat-spinner-overlay diameter="80" strokeWidth="8"></app-mat-spinner-overlay>
   </div>
 </div>
 
 <div *ngIf="roomsWithRole">
-  <mat-divider></mat-divider>
+
   <div *ngIf="tableDataSource.data.length === 0" aria-labelledby="emptySessionHistoryLabel">
     <h3 class="noRoomHistory">{{ 'room-list.no-room-history' | translate }}</h3>
   </div>
@@ -27,12 +27,13 @@
 
         <!-- Room / Session name column -->
         <ng-container matColumnDef="name" aria-hidden="true">
-          <th mat-header-cell *matHeaderCellDef style="width: 35%">
+          <th mat-header-cell *matHeaderCellDef style="width: 45%; padding-right: 40px">
             {{ 'room-list.panel-session-name' | translate }}
           </th>
           <td mat-cell class="clickable" *matCellDef="let room" (click)="setCurrentRoom(room.shortId)"
               routerLink="/{{ roleToString((room.role)) }}/room/{{ room.shortId }}">
-            <span matBadge="{{room.commentCount > 0 ? room.commentCount : null}}" matBadgePosition="before" matBadgeSize="small" matBadgeOverlap="false">
+            <span matBadge="{{room.commentCount > 0 ? room.commentCount : null}}" matBadgePosition="before"
+                  matBadgeSize="small" matBadgeOverlap="false">
               &raquo;{{room.name}}&laquo;
             </span>
           </td>
@@ -40,18 +41,19 @@
 
         <!-- Session ID column -->
         <ng-container matColumnDef="shortId" aria-hidden="true">
-          <th mat-header-cell *matHeaderCellDef style="width: 30%">
+          <th mat-header-cell *matHeaderCellDef style="width: 45%">
             {{ 'room-list.panel-session-id' | translate }}
           </th>
           <td mat-cell class="clickable" *matCellDef="let room" (click)="setCurrentRoom(room.shortId)"
               routerLink="/{{ roleToString((room.role)) }}/room/{{ room.shortId }}">
             {{ room.shortId }}
+            <mat-icon *ngIf="room.questionsBlocked" class="warn" [inline]="true">block</mat-icon>
           </td>
         </ng-container>
 
         <!-- Role column -->
         <ng-container matColumnDef="role" aria-hidden="true">
-          <th mat-header-cell *matHeaderCellDef style="width: 15%">
+          <th mat-header-cell *matHeaderCellDef style="width: 10%">
             {{ 'room-list.panel-user-role' | translate }}
           </th>
           <td mat-cell class="clickable" *matCellDef="let room" [ngSwitch]="room.role"
@@ -74,10 +76,10 @@
 
         <!-- Join button column -->
         <ng-container matColumnDef="button">
-          <th mat-header-cell *matHeaderCellDef style="width: 20%; text-align: end">
+          <th mat-header-cell *matHeaderCellDef style="width: 5%; text-align: end">
             {{ 'room-list.panel-join-button' | translate }}
           </th>
-          <td mat-cell *matCellDef="let room" style="text-align: end"
+          <td mat-cell *matCellDef="let room" style="text-align: end; padding-right: 0"
               attr.aria-labelledby="empty">
             <button mat-icon-button [matMenuTriggerFor]="moreActions">
               <mat-icon>more_vert</mat-icon>
@@ -89,16 +91,16 @@
                   'room-list.delete-room') | translate}}</span>
               </button>
               <button mat-menu-item (click)="exportCsv(room)">
-                <mat-icon class="export">save</mat-icon>
+                <mat-icon class="export">file_download</mat-icon>
                 <span class="delete-text">{{ 'room-list.export-comments' | translate }}</span>
               </button>
             </mat-menu>
             <div class="visually-hidden">
               <div id="{{ 'joinButtonLabel' + room.shortId | translate }}">
                 {{ 'room-list.join-message-template' | translate:{
-                  session: room.name,
-                  id: room.shortId,
-                  role: ( 'room-list.' + roleToString((room.role)) + '-role' | translate )
+                session: room.name,
+                id: room.shortId,
+                role: ('room-list.' + roleToString((room.role)) + '-role' | translate)
               } }}
               </div>
             </div>
diff --git a/src/app/components/shared/room-list/room-list.component.scss b/src/app/components/shared/room-list/room-list.component.scss
index cd8996e28f42f64346f2feaac8dbe21e04ab21ef..0d62c327c961c820d92575a23ee46c2a83998e73 100644
--- a/src/app/components/shared/room-list/room-list.component.scss
+++ b/src/app/components/shared/room-list/room-list.component.scss
@@ -84,10 +84,6 @@ th, tr {
   margin-right: 10px;
 }
 
-.delete-text {
-  color: var(--on-dialog);
-}
-
 .export {
   color: var(--green);
   margin-right: 10px;
@@ -100,3 +96,10 @@ th, tr {
 .list-entries {
   width: 100%;
 }
+
+.warn {
+  color: var(--red) !important;
+  font-size: large ;
+  font-weight: bold;
+  padding-left: 3px;
+}
diff --git a/src/app/components/shared/room-page/room-page.component.ts b/src/app/components/shared/room-page/room-page.component.ts
index d61ddc13fac550eec84f973646e881f61724d842..b9bb29d8b0b168f22db6f859113ce9acbe10d480 100644
--- a/src/app/components/shared/room-page/room-page.component.ts
+++ b/src/app/components/shared/room-page/room-page.component.ts
@@ -4,7 +4,7 @@ import { User } from '../../../models/user';
 import { RoomService } from '../../../services/http/room.service';
 import { ActivatedRoute } from '@angular/router';
 import { Location } from '@angular/common';
-import { WsCommentServiceService } from '../../../services/websockets/ws-comment-service.service';
+import { WsCommentService } from '../../../services/websockets/ws-comment.service';
 import { CommentService } from '../../../services/http/comment.service';
 import { EventService } from '../../../services/util/event.service';
 import { Message, IMessage } from '@stomp/stompjs';
@@ -28,7 +28,7 @@ export class RoomPageComponent implements OnInit, OnDestroy {
   constructor(protected roomService: RoomService,
               protected route: ActivatedRoute,
               protected location: Location,
-              protected wsCommentService: WsCommentServiceService,
+              protected wsCommentService: WsCommentService,
               protected commentService: CommentService,
               protected eventService: EventService
   ) {
@@ -61,7 +61,7 @@ export class RoomPageComponent implements OnInit, OnDestroy {
       this.roomService.getRoomByShortId(id).subscribe(room => {
         this.room = room;
         this.isLoading = false;
-        this.moderationEnabled = this.room.moderated;
+        this.moderationEnabled = !this.room.directSend;
         localStorage.setItem('moderationEnabled', String(this.moderationEnabled));
         this.commentService.countByRoomId(this.room.id, true)
           .subscribe(commentCounter => {
diff --git a/src/app/components/shared/shared.module.ts b/src/app/components/shared/shared.module.ts
index 0fe7715ac88a1eada7caf515b44614ca0fbeed45..40b9193a271a0f44d648ba93272e06a8a1b24f19 100644
--- a/src/app/components/shared/shared.module.ts
+++ b/src/app/components/shared/shared.module.ts
@@ -29,13 +29,25 @@ import { QRCodeModule } from 'angularx-qrcode';
 import { MotdDialogComponent } from './_dialogs/motd-dialog/motd-dialog.component';
 import { MotdMessageComponent } from './_dialogs/motd-dialog/motd-message/motd-message.component';
 import { TagCloudModule } from 'angular-tag-cloud-module';
-import { CloudConfigurationComponent } from "./_dialogs/cloud-configuration/cloud-configuration.component";
+import { CloudConfigurationComponent } from './_dialogs/cloud-configuration/cloud-configuration.component';
 import { ColorPickerModule } from 'ngx-color-picker';
 import { TopicCloudConfirmDialogComponent } from './_dialogs/topic-cloud-confirm-dialog/topic-cloud-confirm-dialog.component';
 import { TopicCloudAdministrationComponent } from './_dialogs/topic-cloud-administration/topic-cloud-administration.component';
 import { TopicDialogCommentComponent } from './dialog/topic-dialog-comment/topic-dialog-comment.component';
 import { TopicCloudFilterComponent } from './_dialogs/topic-cloud-filter/topic-cloud-filter.component';
 import { SpacyDialogComponent } from './_dialogs/spacy-dialog/spacy-dialog.component';
+import { TagCloudPopUpComponent } from './tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component';
+import { WorkerDialogComponent } from './_dialogs/worker-dialog/worker-dialog.component';
+import { DragDropModule } from '@angular/cdk/drag-drop';
+import { ActiveUserComponent } from './overlay/active-user/active-user.component';
+import { AutofocusDirective } from '../../directives/autofocus.directive';
+import { JoyrideModule } from 'ngx-joyride';
+import { TagCloudComponent } from './tag-cloud/tag-cloud.component';
+import { JoyrideTemplateComponent } from './_dialogs/joyride-template/joyride-template.component';
+import { JoyrideTemplateDirective } from '../../directives/joyride-template.directive';
+import { MatSpinnerOverlayComponent } from './mat-spinner-overlay/mat-spinner-overlay.component';
+import { WriteCommentComponent } from './write-comment/write-comment.component';
+import { CustomMarkdownComponent } from './custom-markdown/custom-markdown.component';
 
 @NgModule({
   imports: [
@@ -47,7 +59,9 @@ import { SpacyDialogComponent } from './_dialogs/spacy-dialog/spacy-dialog.compo
     MarkdownModule,
     QRCodeModule,
     TagCloudModule,
-    ColorPickerModule
+    ColorPickerModule,
+    DragDropModule,
+    JoyrideModule.forChild()
   ],
   declarations: [
     RoomJoinComponent,
@@ -77,24 +91,40 @@ import { SpacyDialogComponent } from './_dialogs/spacy-dialog/spacy-dialog.compo
     TopicCloudAdministrationComponent,
     TopicDialogCommentComponent,
     TopicCloudFilterComponent,
-    SpacyDialogComponent
+    SpacyDialogComponent,
+    TagCloudComponent,
+    TagCloudPopUpComponent,
+    ActiveUserComponent,
+    WorkerDialogComponent,
+    AutofocusDirective,
+    JoyrideTemplateComponent,
+    JoyrideTemplateDirective,
+    MatSpinnerOverlayComponent,
+    WriteCommentComponent,
+    CustomMarkdownComponent
   ],
-    exports: [
-        RoomJoinComponent,
-        PageNotFoundComponent,
-        RoomPageComponent,
-        RoomListComponent,
-        HeaderComponent,
-        FooterComponent,
-        CommentPageComponent,
-        CommentListComponent,
-        CreateCommentComponent,
-        PresentCommentComponent,
-        CommentComponent,
-        DialogActionButtonsComponent,
-        UserBonusTokenComponent,
-        CloudConfigurationComponent
-    ]
+  exports: [
+    RoomJoinComponent,
+    PageNotFoundComponent,
+    RoomPageComponent,
+    RoomListComponent,
+    HeaderComponent,
+    FooterComponent,
+    CommentPageComponent,
+    CommentListComponent,
+    CreateCommentComponent,
+    PresentCommentComponent,
+    CommentComponent,
+    DialogActionButtonsComponent,
+    UserBonusTokenComponent,
+    CloudConfigurationComponent,
+    TagCloudPopUpComponent,
+    ActiveUserComponent,
+    MatSpinnerOverlayComponent,
+    JoyrideTemplateDirective,
+    AutofocusDirective,
+    CustomMarkdownComponent
+  ]
 })
 export class SharedModule {
 }
diff --git a/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.html b/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..3c4d2d344bb7675515900fceaaeb5e91ecb36977
--- /dev/null
+++ b/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.html
@@ -0,0 +1,71 @@
+<div #popupContainer
+     class="popupContainer"
+     (focusout)="onFocusOut()"
+     tabindex="0">
+  <div>
+    <div>
+      <span>
+        <mat-icon matTooltip="{{'tag-cloud.overview-question-topic-tooltip' | translate}}">comment</mat-icon>
+        <p>
+          {{tagData && tagData.comments.length}}
+        </p>
+      </span>
+      <span>
+        <mat-icon matTooltip="{{'tag-cloud.overview-questioners-topic-tooltip' | translate}}">person</mat-icon>
+        <p>
+          {{tagData && tagData.distinctUsers.size}}
+        </p>
+      </span>
+      <button *ngIf="user && user.role >= 1 && isBlacklistActive" mat-button (click)="addBlacklistWord()">
+        <mat-icon matTooltip="{{'tag-cloud.blacklist-topic' | translate}}">gavel</mat-icon>
+      </button>
+    </div>
+    <div>
+      <span>
+        <mat-icon matTooltip="{{'tag-cloud.upvote-topic' | translate}}">thumb_up</mat-icon>
+        <p>
+          {{tagData && tagData.cachedUpVotes}}
+        </p>
+      </span>
+      <span>
+        <mat-icon matTooltip="{{'tag-cloud.downvote-topic' | translate}}">thumb_down</mat-icon>
+        <p>
+          {{tagData && tagData.cachedDownVotes}}
+        </p>
+      </span>
+    </div>
+    <div>
+      <span>
+        <mat-icon matTooltip="{{'tag-cloud.period-since-first-comment' | translate}}">date_range</mat-icon>
+        <p>
+          {{timePeriodText}}
+        </p>
+      </span>
+    </div>
+    <div class="replacementContainer" *ngIf="user && user.role >= 1">
+      <mat-form-field>
+        <mat-label>{{'tag-cloud-popup.tag-correction-placeholder' | translate}}</mat-label>
+        <input type="text"
+               aria-label="{{'tag-cloud-popup.tag-correction-placeholder' | translate}}"
+               matInput
+               (keyup)="checkEnter($event)"
+               [formControl]="replacementInput"
+               [matAutocomplete]="auto">
+        <mat-autocomplete #auto="matAutocomplete">
+          <mat-option *ngFor="let data of spellingData" [value]="data">
+            {{data}}
+          </mat-option>
+        </mat-autocomplete>
+      </mat-form-field>
+      <br>
+      <button mat-flat-button class="replace-button" [disabled]="!isNewTagReady()"
+              (click)="updateTag()">{{"comment-page.send" | translate}}</button>
+    </div>
+    <div *ngIf="categories && categories.length">
+      <p>Kategorien:</p>
+      <ul>
+        <li *ngFor="let category of categories">{{category}}</li>
+      </ul>
+    </div>
+  </div>
+</div>
diff --git a/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.scss b/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..b98c760cb7340435ebf9a902879cea2730c08a33
--- /dev/null
+++ b/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.scss
@@ -0,0 +1,179 @@
+$popup-arrow-size: 20px;
+$popup-arrow-border-size: 2px;
+$popup-arrow-half-size: $popup-arrow-size / 2;
+$popup-arrow-offset: $popup-arrow-half-size + $popup-arrow-border-size;
+$header-size: 67px;
+
+.popupContainer {
+  visibility: hidden;
+  border-radius: 25px;
+  border: 2px solid #000;
+  background-color: var(--dialog);
+  padding: $popup-arrow-half-size;
+  position: absolute;
+  box-shadow: 0 0 10px var(--dialog);
+  box-sizing: border-box;
+  z-index: 3;
+  color: var(--on-dialog);
+  transform: translateY(-$header-size);
+  min-width: 200px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+
+  & > div {
+    display: flex;
+    justify-content: center;
+    flex-direction: column;
+    align-items: flex-start;
+    overflow: hidden;
+  }
+
+  &:focus {
+    outline: none;
+  }
+
+  &::after {
+    position: absolute;
+    content: '';
+    width: $popup-arrow-size;
+    height: $popup-arrow-size;
+    background-color: var(--dialog);
+    border-top: 0 solid #000;
+    border-right: $popup-arrow-border-size solid #000;
+    border-left: 0 solid #000;
+    border-bottom: $popup-arrow-border-size solid #000;
+  }
+
+  &.down {
+    visibility: unset;
+    transform: translate(-50%, calc(-100% - #{$header-size + $popup-arrow-offset}));
+
+    &::after {
+      top: 100%;
+      left: 50%;
+      margin-top: -$popup-arrow-half-size;
+      margin-left: -$popup-arrow-half-size;
+      transform: rotate(45deg);
+    }
+  }
+
+  &.left {
+    visibility: unset;
+    transform: translate($popup-arrow-offset, calc(-50% - #{$header-size}));
+
+    &::after {
+      top: 50%;
+      right: 100%;
+      margin-top: -$popup-arrow-half-size;
+      margin-right: -$popup-arrow-half-size;
+      transform: rotate(135deg);
+    }
+  }
+
+  &.up {
+    visibility: unset;
+    transform: translate(-50%, $popup-arrow-offset - $header-size);
+
+    &::after {
+      bottom: 100%;
+      left: 50%;
+      margin-bottom: -$popup-arrow-half-size;
+      margin-left: -$popup-arrow-half-size;
+      transform: rotate(225deg);
+    }
+  }
+
+  &.right {
+    visibility: unset;
+    transform: translate(calc(-100% - #{$popup-arrow-offset}), calc(-50% - #{$header-size}));
+
+    &::after {
+      top: 50%;
+      left: 100%;
+      margin-top: -$popup-arrow-half-size;
+      margin-left: -$popup-arrow-half-size;
+      transform: rotate(315deg);
+    }
+  }
+}
+
+div > p {
+  margin-bottom: 1px;
+}
+
+span {
+  margin-right: 5px;
+
+  & > mat-icon {
+    margin: -1px 0px 0px 12px;
+    vertical-align: middle;
+  }
+
+  & > p {
+    display: inline;
+    font-weight: 600;
+    vertical-align: middle;
+  }
+}
+
+ul {
+  margin: 0;
+}
+
+button {
+  color: var(--red);
+  min-width: unset;
+  margin-left: 0;
+  padding-left: 10px;
+  padding-right: 10px;
+}
+
+.replace-button {
+  background-color: var(--primary);
+  color: var(--on-primary);
+  min-width: 30px !important;
+  min-height: 10px !important;
+  width: 100%;
+  z-index: 3;
+}
+
+::ng-deep .replacementContainer {
+  align-self: center;
+
+  .mat-form-field-infix {
+    min-width: 150px;
+    width: min-content;
+  }
+
+  .mat-form-field-wrapper {
+    margin-bottom: -0.8em;
+  }
+}
+
+mat-form-field {
+  border-radius: 5px;
+  line-height: 80%;
+  caret-color: var(--on-surface);
+  -webkit-appearance: textarea;
+  min-height: 30px;
+  min-width: 140px;
+  cursor: text;
+  color: var(--on-dialog);
+  background-color: var(--dialog);
+  margin-top: 0.2em;
+
+  &:focus {
+    outline: none;
+  }
+}
+
+#replacement {
+  color: var(--on-dialog);
+  background-color: var(--dialog);
+  border-radius: 5px;
+}
+
+.mat-flat-button.mat-primary.mat-button-disabled, .mat-flat-button.mat-accent.mat-button-disabled, .mat-flat-button.mat-warn.mat-button-disabled, .mat-flat-button.mat-button-disabled.mat-button-disabled, .mat-raised-button.mat-primary.mat-button-disabled, .mat-raised-button.mat-accent.mat-button-disabled, .mat-raised-button.mat-warn.mat-button-disabled, .mat-raised-button.mat-button-disabled.mat-button-disabled, .mat-fab.mat-primary.mat-button-disabled, .mat-fab.mat-accent.mat-button-disabled, .mat-fab.mat-warn.mat-button-disabled, .mat-fab.mat-button-disabled.mat-button-disabled, .mat-mini-fab.mat-primary.mat-button-disabled, .mat-mini-fab.mat-accent.mat-button-disabled, .mat-mini-fab.mat-warn.mat-button-disabled, .mat-mini-fab.mat-button-disabled.mat-button-disabled {
+  display: none;
+}
diff --git a/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.spec.ts b/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..be4c0a85dfd377daf9509432ffd793ae52fed9fe
--- /dev/null
+++ b/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.spec.ts
@@ -0,0 +1,26 @@
+/*import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { TagCloudPopUpComponent } from './tag-cloud-pop-up.component';
+
+describe('TagCloudPopUpComponent', () => {
+  let component: TagCloudPopUpComponent;
+  let fixture: ComponentFixture<TagCloudPopUpComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ TagCloudPopUpComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(TagCloudPopUpComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
+*/
diff --git a/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.ts b/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..41bebb11df4bd5f59c5b4d9dc073ecb010156b66
--- /dev/null
+++ b/src/app/components/shared/tag-cloud/tag-cloud-pop-up/tag-cloud-pop-up.component.ts
@@ -0,0 +1,333 @@
+import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
+import { TranslateService } from '@ngx-translate/core';
+import { LanguageService } from '../../../../services/util/language.service';
+import { AuthenticationService } from '../../../../services/http/authentication.service';
+import { User } from '../../../../models/user';
+import { TagCloudDataService, TagCloudDataTagEntry } from '../../../../services/util/tag-cloud-data.service';
+import { Language, LanguagetoolService } from '../../../../services/http/languagetool.service';
+import { FormControl } from '@angular/forms';
+import { TSMap } from 'typescript-map';
+import { CommentService } from '../../../../services/http/comment.service';
+import { NotificationService } from '../../../../services/util/notification.service';
+import { MatAutocompleteTrigger } from '@angular/material/autocomplete';
+import { UserRole } from '../../../../models/user-roles.enum';
+import { SpacyKeyword } from '../../../../services/http/spacy.service';
+
+const CLOSE_TIME = 1500;
+
+@Component({
+  selector: 'app-tag-cloud-pop-up',
+  templateUrl: './tag-cloud-pop-up.component.html',
+  styleUrls: ['./tag-cloud-pop-up.component.scss']
+})
+export class TagCloudPopUpComponent implements OnInit, AfterViewInit {
+
+  @ViewChild('popupContainer') popupContainer: ElementRef;
+  @ViewChild(MatAutocompleteTrigger) trigger: MatAutocompleteTrigger;
+  replacementInput = new FormControl();
+  tag: string;
+  tagData: TagCloudDataTagEntry;
+  categories: string[];
+  timePeriodText: string;
+  user: User;
+  selectedLang: Language = 'en-US';
+  spellingData: string[] = [];
+  isBlacklistActive = true;
+  private _popupHoverTimer;
+  private _popupCloseTimer;
+  private _hasLeft = true;
+
+  constructor(private langService: LanguageService,
+              private translateService: TranslateService,
+              private authenticationService: AuthenticationService,
+              private tagCloudDataService: TagCloudDataService,
+              private languagetoolService: LanguagetoolService,
+              private commentService: CommentService,
+              private notificationService: NotificationService) {
+    this.langService.langEmitter.subscribe(lang => {
+      this.translateService.use(lang);
+    });
+  }
+
+  ngOnInit(): void {
+    this.timePeriodText = '...';
+    this.authenticationService.watchUser.subscribe(newUser => {
+      if (newUser) {
+        this.user = newUser;
+      }
+    });
+  }
+
+  ngAfterViewInit() {
+    const html = this.popupContainer.nativeElement as HTMLDivElement;
+    html.addEventListener('mouseenter', () => {
+      clearTimeout(this._popupCloseTimer);
+      this._hasLeft = false;
+    });
+    html.addEventListener('mouseleave', () => {
+      this._hasLeft = true;
+      this.close();
+    });
+  }
+
+  onFocusOut() {
+    this.close();
+  }
+
+  leave(): void {
+    clearTimeout(this._popupHoverTimer);
+    this.close();
+  }
+
+  enter(elem: HTMLElement, tag: string, tagData: TagCloudDataTagEntry, hoverDelayInMs: number, isBlacklistActive: boolean): void {
+    if (!elem) {
+      return;
+    }
+    this.spellingData = [];
+    if (this.user && this.user.role > UserRole.PARTICIPANT) {
+      this.languagetoolService.checkSpellings(tag, 'auto').subscribe(correction => {
+        const langKey = correction.language.code.split('-')[0].toUpperCase();
+        if (['DE', 'FR', 'EN'].indexOf(langKey) < 0) {
+          return;
+        }
+        for (const match of correction.matches) {
+          if (match.replacements != null && match.replacements.length > 0) {
+            for (const replacement of match.replacements) {
+              this.spellingData.push(replacement.value);
+            }
+          }
+        }
+      });
+    }
+    clearTimeout(this._popupCloseTimer);
+    clearTimeout(this._popupHoverTimer);
+    this._hasLeft = true;
+    this._popupHoverTimer = setTimeout(() => {
+      this.tag = tag;
+      this.tagData = tagData;
+      this.categories = Array.from(tagData.categories.keys());
+      this.calculateDateText(() => {
+        this.position(elem);
+        this.isBlacklistActive = isBlacklistActive;
+      });
+    }, hoverDelayInMs);
+  }
+
+  addBlacklistWord(): void {
+    this.tagCloudDataService.blockWord(this.tag);
+    this.close(false);
+  }
+
+  close(addDelay = true): void {
+    const html = this.popupContainer.nativeElement as HTMLDivElement;
+    clearTimeout(this._popupCloseTimer);
+    if (addDelay) {
+      if (!this._hasLeft || (html.contains(document.activeElement) && html !== document.activeElement)) {
+        return;
+      }
+      this._popupCloseTimer = setTimeout(() => {
+        if (html.contains(document.activeElement) && html !== document.activeElement) {
+          return;
+        }
+        html.classList.remove('up', 'down', 'right', 'left');
+      }, CLOSE_TIME);
+    } else {
+      html.classList.remove('up', 'down', 'right', 'left');
+    }
+  }
+
+  isNewTagReady(): boolean {
+    if (!this.replacementInput.value) {
+      return false;
+    }
+    const tag = this.replacementInput.value.trim();
+    return !(tag.length < 1 || tag === this.tag);
+  }
+
+  updateTag(): void {
+    if (!this.isNewTagReady()) {
+      return;
+    }
+    const tagReplacementInput = this.replacementInput.value.trim();
+    const renameKeyword = (elem: SpacyKeyword) => {
+      if (elem.lemma === this.tag) {
+        elem.lemma = tagReplacementInput;
+      }
+    };
+    const tagReplacementInputLower = tagReplacementInput.toLowerCase();
+    this.tagData.comments.forEach(comment => {
+      const changes = new TSMap<string, any>();
+      if (comment.keywordsFromQuestioner.findIndex(e => e.lemma.toLowerCase() === tagReplacementInputLower) >= 0) {
+        comment.keywordsFromQuestioner = comment.keywordsFromQuestioner.filter(e => e.lemma !== this.tag);
+      } else {
+        comment.keywordsFromQuestioner.forEach(renameKeyword);
+      }
+      changes.set('keywordsFromQuestioner', JSON.stringify(comment.keywordsFromQuestioner));
+      if (comment.keywordsFromSpacy.findIndex(e => e.lemma.toLowerCase() === tagReplacementInputLower) >= 0) {
+        comment.keywordsFromSpacy = comment.keywordsFromSpacy.filter(e => e.lemma !== this.tag);
+      } else {
+        comment.keywordsFromSpacy.forEach(renameKeyword);
+      }
+      changes.set('keywordsFromSpacy', JSON.stringify(comment.keywordsFromSpacy));
+      this.commentService.patchComment(comment, changes).subscribe(_ => {
+        this.translateService.get('topic-cloud-dialog.keyword-edit').subscribe(msg => {
+          this.notificationService.show(msg);
+        });
+      }, _ => {
+        this.translateService.get('topic-cloud-dialog.changes-gone-wrong').subscribe(msg => {
+          this.notificationService.show(msg);
+        });
+      });
+    });
+    this.close(false);
+    this.replacementInput.reset();
+    this.trigger.closePanel();
+  }
+
+  checkEnter(e: KeyboardEvent) {
+    if (e.key === 'Enter') {
+      this.updateTag();
+    }
+  }
+
+  private position(elem: HTMLElement) {
+    const html = this.popupContainer.nativeElement as HTMLDivElement;
+    const popup = html.getBoundingClientRect();
+    const tag = elem.getBoundingClientRect();
+    const boundingBox = elem.parentElement.getBoundingClientRect();
+    // calculate the free space to the left, right, top and bottom from tag
+    const spaceLeft = tag.x + tag.width / 2;
+    const spaceRight = boundingBox.right - tag.right + tag.width / 2;
+    const spaceTop = tag.y - boundingBox.y;
+    const spaceBottom = boundingBox.bottom - tag.bottom;
+    // set flags if tag is near bounding box
+    const isLeft = spaceLeft <= popup.width / 2.0;
+    const isRight = spaceRight <= popup.width / 2.0;
+    const isTop = spaceTop <= popup.height;
+    const isBottom = spaceBottom <= popup.height;
+
+    // try to make a decision where to place the popup outgoing from tag with checks if we are at a border of the viewport
+    enum PopupPosition {
+      top,
+      bottom,
+      left,
+      right
+    }
+
+    let dockingPosition;
+    if (isLeft && isTop && !isBottom && !isRight) {
+      dockingPosition = PopupPosition.right;
+    } else if (isTop && !isLeft && !isRight && !isBottom) {
+      dockingPosition = PopupPosition.bottom;
+    } else if (isRight && isTop && !isLeft && !isBottom) {
+      dockingPosition = PopupPosition.left;
+    } else if (isLeft && !isTop && !isRight && !isBottom) {
+      dockingPosition = PopupPosition.right;
+    } else if (!isLeft && !isTop && !isRight && !isBottom) {
+      // default docking when all sides offer enough space
+      dockingPosition = PopupPosition.top;
+    } else if (isRight && !isTop && !isLeft && !isBottom) {
+      dockingPosition = PopupPosition.left;
+    } else if (isLeft && isBottom && !isTop && !isRight) {
+      dockingPosition = PopupPosition.right;
+    } else if (!isLeft && isBottom && !isTop && !isRight) {
+      dockingPosition = PopupPosition.top;
+    } else if (!isLeft && isBottom && isTop && !isRight) {
+      dockingPosition = PopupPosition.left;
+    } else {
+      /*
+       * Find solution for small screens when all sides produce unpleasant results
+       */
+      dockingPosition = PopupPosition.top;
+    }
+    html.classList.remove('left', 'right', 'up', 'down');
+    if (dockingPosition === PopupPosition.bottom) {
+      html.style.top = tag.bottom + 'px';
+      html.style.left = tag.x + tag.width / 2 + 'px';
+      html.classList.add('up');
+    } else if (dockingPosition === PopupPosition.top) {
+      html.style.top = tag.y + 'px';
+      html.style.left = tag.x + tag.width / 2 + 'px';
+      html.classList.add('down');
+    } else if (dockingPosition === PopupPosition.left) {
+      html.style.top = tag.top + tag.height / 2 + 'px';
+      html.style.left = tag.x + 'px';
+      html.classList.add('right');
+    } else if (dockingPosition === PopupPosition.right) {
+      html.style.top = tag.top + tag.height / 2 + 'px';
+      html.style.left = tag.right + 'px';
+      html.classList.add('left');
+    }
+    html.focus();
+  }
+
+  private calculateDateText(afterInit: () => void): void {
+    const subscriber = (e: string) => {
+      this.timePeriodText = e;
+      if (afterInit) {
+        setTimeout(afterInit);
+      }
+    };
+    // @ts-ignore
+    const diffMs = Date.now() - Date.parse(this.tagData.firstTimeStamp);
+    const seconds = Math.floor(diffMs / 1_000);
+    if (seconds < 60) {
+      // few seconds
+      this.translateService.get('tag-cloud-popup.few-seconds').subscribe(subscriber);
+      return;
+    }
+    const minutes = Math.floor(seconds / 60);
+    if (minutes < 5) {
+      // few minutes
+      this.translateService.get('tag-cloud-popup.few-minutes').subscribe(subscriber);
+      return;
+    } else if (minutes < 60) {
+      // x minutes
+      this.translateService.get('tag-cloud-popup.some-minutes', {
+        minutes
+      }).subscribe(subscriber);
+      return;
+    }
+    const hours = Math.floor(minutes / 60);
+    if (hours === 1) {
+      // 1 hour
+      this.translateService.get('tag-cloud-popup.one-hour').subscribe(subscriber);
+      return;
+    } else if (hours < 24) {
+      // x hours
+      this.translateService.get('tag-cloud-popup.some-hours', {
+        hours
+      }).subscribe(subscriber);
+      return;
+    }
+    const days = Math.floor(hours / 24);
+    if (days === 1) {
+      // 1 day
+      this.translateService.get('tag-cloud-popup.one-day').subscribe(subscriber);
+      return;
+    } else if (days < 7) {
+      // x days
+      this.translateService.get('tag-cloud-popup.some-days', {
+        days
+      }).subscribe(subscriber);
+      return;
+    }
+    const weeks = Math.floor(days / 7);
+    if (weeks === 1) {
+      // 1 week
+      this.translateService.get('tag-cloud-popup.one-week').subscribe(subscriber);
+      return;
+    } else if (weeks < 12) {
+      // x weeks
+      this.translateService.get('tag-cloud-popup.some-weeks', {
+        weeks
+      }).subscribe(subscriber);
+      return;
+    }
+    const months = Math.floor(weeks / 4);
+    // x months
+    this.translateService.get('tag-cloud-popup.some-months', {
+      months
+    }).subscribe(subscriber);
+  }
+}
diff --git a/src/app/components/shared/tag-cloud/tag-cloud.component.html b/src/app/components/shared/tag-cloud/tag-cloud.component.html
index 16b972cd20d071719f62bcf3de098167f4c343f8..e8e27e6d8bfec5089f452aa426a80d8dda8640a2 100644
--- a/src/app/components/shared/tag-cloud/tag-cloud.component.html
+++ b/src/app/components/shared/tag-cloud/tag-cloud.component.html
@@ -1,28 +1,44 @@
+<link rel="preconnect" href="https://fonts.gstatic.com">
+<link
+  href="https://fonts.googleapis.com/css2?family=Abril+Fatface&family=Dancing+Script&family=Indie+Flower&family=Permanent+Marker&display=swap"
+  rel="stylesheet">
 <ars-screen ars-flex-box>
-  <ars-row [height]="65">
-  </ars-row>
-  <mat-drawer-container class="spacyTagCloudContainer">
-    <mat-drawer [(opened)]="configurationOpen" position="end" mode="push">
-      <app-cloud-configuration [parent]="this"></app-cloud-configuration>
+  <mat-drawer-container class="spacyTagCloudContainer" [hasBackdrop]="true">
+    <mat-drawer position="end" mode="over" (closed)="cloudComponent.closePanel()" (opened)="cloudComponent.openPanel()">
+      <app-cloud-configuration #cloudComponent [parent]="this"></app-cloud-configuration>
     </mat-drawer>
     <mat-drawer-content>
+      <h1 *ngIf="user && user.role > 0 && question" class="tag-cloud-brainstorming-question mat-display-1">
+        {{question}}
+      </h1>
       <ars-fill ars-flex-box>
+        <app-tag-cloud-pop-up></app-tag-cloud-pop-up>
+        <app-mat-spinner-overlay *ngIf="isLoading" overlay="true"></app-mat-spinner-overlay>
         <angular-tag-cloud
+          id="tagCloudComponent"
           class="spacyTagCloud"
           (window:resize)="onResize($event)"
-          (afterInit)="initTagCloud()"
+          (clicked)="openTags($event)"
           [data]="data"
           [width]="options.width"
           [height]="options.height"
           [overflow]="options.overflow"
-          [delay]="options.delay"
+          [delay]="currentCloudParameters.delayWord"
           [randomizeAngle]="false"
           [zoomOnHover]="zoomOnHoverOptions"
           [realignOnResize]="false">
         </angular-tag-cloud>
+        <app-active-user *ngIf="room" [alwaysShowInHeader]="true" [room]="this.room" [top]="120"></app-active-user>
       </ars-fill>
+      <button *ngIf="((user && user.role > 0) || (room && !room.questionsBlocked)) && drawer && !drawer.opened"
+              mat-fab
+              mat-icon-button
+              aria-labelledby="add"
+              class="fab_add_comment"
+              (click)="createCommentWrapper.openCreateDialog(this.user)"
+              matTooltip="{{ 'comment-list.add-comment' | translate }}">
+        <mat-icon>add</mat-icon>
+      </button>
     </mat-drawer-content>
   </mat-drawer-container>
-  <ars-row [height]="37">
-  </ars-row>
 </ars-screen>
diff --git a/src/app/components/shared/tag-cloud/tag-cloud.component.scss b/src/app/components/shared/tag-cloud/tag-cloud.component.scss
index 711b33256f6068560f5a4178ce8c58135622cd5f..e277c89c4e79591d037bb07a1d02498f6a39b206 100644
--- a/src/app/components/shared/tag-cloud/tag-cloud.component.scss
+++ b/src/app/components/shared/tag-cloud/tag-cloud.component.scss
@@ -1,20 +1,71 @@
-.mat-drawer.mat-drawer-push {
+$header-size: 56px;
+$margin: 15px;
+
+mat-drawer,
+.mat-drawer {
   background-color: var(--background);
-}
 
-mat-drawer {
-  background-color: var(--dialog);
+  @media (max-width: 450px) {
+    width: 100vw;
+  }
+
 }
 
 ars-fill {
-  width: calc(100% - 30px);
-  height: calc(100% - 30px);
-  margin: 15px;
+  width: calc(100% - #{2 * $margin});
+  height: calc(100% - #{2 * $margin});
+  margin: $margin;
 }
 
 mat-drawer-container {
-  height: 100%;
+  height: calc(100% - #{$header-size});
   width: 100%;
   position: fixed;
+  margin-top: $header-size;
+}
+
+mat-drawer-content {
+  overflow: hidden;
+  height: 100%;
+}
+
+.hidden {
+  display: none !important;
+}
+
+app-tag-cloud-pop-up {
+  width: max-content;
+  height: max-content;
+}
+
+::ng-deep .spacyTagCloud span {
+  user-select: none !important;
+}
+
+::ng-deep .spacyTagCloud span:hover {
+  cursor: pointer;
+}
+
+.fab_add_comment {
+  position: fixed;
+  right: 30px;
+  bottom: 30px;
+  background-color: var(--primary);
+  color: var(--on-primary);
+  transform: scale(1.4);
+  transition: all 0.1s ease-in-out;
+  z-index: 2;
 }
 
+.tag-cloud-brainstorming-question {
+  position: fixed;
+  top: 80px;
+  left: 20px;
+  z-index: 2;
+  color: var(--tag-cloud-inverted-background, black);
+  text-transform: var(--tag-cloud-transform, unset);
+  font-weight: var(--tag-cloud-font-weight, normal);
+  font-style: var(--tag-cloud-font-style, normal);
+  font-family: var(--tag-cloud-font-family, 'Dancing Script');
+  font-size: 50px;
+}
diff --git a/src/app/components/shared/tag-cloud/tag-cloud.component.ts b/src/app/components/shared/tag-cloud/tag-cloud.component.ts
index 224904e5c93c3590171627f8caca6353d20d7bc2..6c78127838023a545ff36d1a6a0610923dd92171 100644
--- a/src/app/components/shared/tag-cloud/tag-cloud.component.ts
+++ b/src/app/components/shared/tag-cloud/tag-cloud.component.ts
@@ -1,30 +1,36 @@
-import {Component, OnInit, ViewChild, Input} from '@angular/core';
+import { AfterContentInit, Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
 
 import {
   CloudData,
   CloudOptions,
   Position,
-  ZoomOnHoverOptions,
-  TagCloudComponent as TCloudComponent
+  TagCloudComponent as TCloudComponent,
+  ZoomOnHoverOptions
 } from 'angular-tag-cloud-module';
-import {CommentService} from '../../../services/http/comment.service';
-import {Result, SpacyService} from '../../../services/http/spacy.service';
-import {Comment} from '../../../models/comment';
-import {LanguageService} from '../../../services/util/language.service';
-import {TranslateService} from '@ngx-translate/core';
-import {CreateCommentComponent} from '../_dialogs/create-comment/create-comment.component';
-import {MatDialog} from '@angular/material/dialog';
-import {User} from '../../../models/user';
-import {Room} from '../../../models/room';
-import {NotificationService} from '../../../services/util/notification.service';
-import {EventService} from '../../../services/util/event.service';
-import {AuthenticationService} from '../../../services/http/authentication.service';
-import {ActivatedRoute} from '@angular/router';
-import {UserRole} from '../../../models/user-roles.enum';
-import {RoomService} from '../../../services/http/room.service';
-import {ThemeService} from '../../../../theme/theme.service';
-import {CloudParameters} from './tag-cloud.interface';
+import { CommentService } from '../../../services/http/comment.service';
+import { LanguageService } from '../../../services/util/language.service';
+import { TranslateService } from '@ngx-translate/core';
+import { MatDialog } from '@angular/material/dialog';
+import { User } from '../../../models/user';
+import { Room } from '../../../models/room';
+import { NotificationService } from '../../../services/util/notification.service';
+import { EventService } from '../../../services/util/event.service';
+import { AuthenticationService } from '../../../services/http/authentication.service';
+import { ActivatedRoute, Router } from '@angular/router';
+import { UserRole } from '../../../models/user-roles.enum';
+import { RoomService } from '../../../services/http/room.service';
+import { ThemeService } from '../../../../theme/theme.service';
 import { TopicCloudAdministrationComponent } from '../_dialogs/topic-cloud-administration/topic-cloud-administration.component';
+import { WsCommentService } from '../../../services/websockets/ws-comment.service';
+import { CreateCommentWrapper } from '../../../utils/create-comment-wrapper';
+import { TopicCloudAdminService } from '../../../services/util/topic-cloud-admin.service';
+import { TagCloudPopUpComponent } from './tag-cloud-pop-up/tag-cloud-pop-up.component';
+import { TagCloudDataService, TagCloudDataTagEntry } from '../../../services/util/tag-cloud-data.service';
+import { WsRoomService } from '../../../services/websockets/ws-room.service';
+import { CloudParameters, CloudTextStyle } from '../../../utils/cloud-parameters';
+import { SmartDebounce } from '../../../utils/smart-debounce';
+import { Theme } from '../../../../theme/Theme';
+import { MatDrawer } from '@angular/material/sidenav';
 
 class CustomPosition implements Position {
   left: number;
@@ -34,150 +40,77 @@ class CustomPosition implements Position {
               public relativeTop: number) {
   }
 
-  updatePosition(width: number, height: number, text: string, style: CSSStyleDeclaration) {
-    const offsetY = parseFloat(style.height) / 2;
-    const offsetX = parseFloat(style.width) / 2;
+  updatePosition(width: number, height: number, metrics: TextMetrics) {
+    const offsetY = (metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent) / 2;
+    const offsetX = metrics.width / 2;
     this.left = width * this.relativeLeft - offsetX;
     this.top = height * this.relativeTop - offsetY;
   }
 }
 
 class TagComment implements CloudData {
-  constructor(public color: string,
-              public external: boolean,
-              public link: string,
-              public position: Position,
+
+  constructor(public text: string,
               public rotate: number,
-              public text: string,
-              public tooltip: string,
-              public weight: number) {
+              public weight: number,
+              public tagData: TagCloudDataTagEntry,
+              public index: number,
+              public color: string = null,
+              public external: boolean = false,
+              public link: string = null,
+              public position: Position = null,
+              public tooltip: string = null) {
   }
 }
 
-//CSS styles Array
-type TagCloudStyleData = [
-  string, // hover
-  string, // w1
-  string, // w2
-  string, // w3
-  string, // w4
-  string, // w5
-  string, // w6
-  string, // w7
-  string, // w8
-  string, // w9
-  string, // w10
-  string // background
-];
-
-const colorRegex = /rgba?\((\d+), (\d+), (\d+)(?:, (\d(?:\.\d+)?))?\)/;
-const defaultColors: string[] = [
-  // variable, fallback
-  'var(--secondary, greenyellow)', // hover
-  'var(--moderator, lightblue)', // w1
-  'var(--blue, green)', // w2
-  'var(--grey, yellow)', // w3
-  'var(--red, orange)', // w4
-  'var(--primary, pink)', // w5
-  'var(--yellow, gray)', // w6
-  'var(--on-background, lightgreen)', // w7
-  'var(--purple, tomato)', // w8
-  'var(--magenta, white)', // w9
-  'var(--light-green, brown)', // w10
-  'var(--background, black)' //background
-];
-
-const getResolvedDefaultColors = (): string[] => {
-  const elem = document.createElement('p');
-  elem.style.display = 'none';
-  document.body.appendChild(elem);
-  const results = [];
-  for (const color of defaultColors) {
-    elem.style.backgroundColor = 'rgb(0, 0, 0)'; // fallback
-    elem.style.backgroundColor = color;
-    const result = window.getComputedStyle(elem).backgroundColor.match(colorRegex);
-    const r = parseInt(result[1], 10);
-    const g = parseInt(result[2], 10);
-    const b = parseInt(result[3], 10);
-    results.push(`#${((r * 256 + g) * 256 + b).toString(16).padStart(6, '0')}`);
-  }
-  elem.remove();
-  return results;
-};
-
-const setGlobalStyles = (styles: TagCloudStyleData): void => {
-  let customTagCloudStyles = document.getElementById('tagCloudStyles') as HTMLStyleElement;
-  if (!customTagCloudStyles) {
-    customTagCloudStyles = document.createElement('style');
-    customTagCloudStyles.id = 'tagCloudStyles';
-    document.head.appendChild(customTagCloudStyles);
-  }
-  const rules = customTagCloudStyles.sheet.cssRules;
-  for (let i = rules.length - 1; i >= 0; i--) {
-    customTagCloudStyles.sheet.deleteRule(i);
-  }
-  for (let i = 1; i <= 10; i++) {
-    customTagCloudStyles.sheet.insertRule('.spacyTagCloud > span.w' + i + ' { ' + styles[i] + ' }', rules.length);
-    customTagCloudStyles.sheet.insertRule('.spacyTagCloud > span.w' + i + ' > a { ' + styles[i] + ' }', rules.length);
-  }
-  customTagCloudStyles.sheet.insertRule('.spacyTagCloud > span:hover { ' + styles[0] + ' }', rules.length);
-  customTagCloudStyles.sheet.insertRule('.spacyTagCloud > span:hover > a { ' + styles[0] + ' }', rules.length);
-  customTagCloudStyles.sheet.insertRule('.spacyTagCloudContainer {' + styles[11] + '}', rules.length);
-};
-
-const getDefaultCloudParameters = (): CloudParameters => {
-  const resDefaultColors = getResolvedDefaultColors();
-  return {
-    backgroundColor: resDefaultColors[11],
-    fontColor: resDefaultColors[0],
-    fontSizeMin: 100,
-    fontSizeMax: 380,
-    hoverScale: 1.3,
-    hoverTime: 0.6,
-    hoverDelay: 0.4,
-    delayWord: 0,
-    randomAngles: false
-  }
-};
+const transformationScaleKiller = /scale\([^)]*\)/;
+const transformationRotationKiller = /rotate\(([^)]*)\)/;
 
 @Component({
   selector: 'app-tag-cloud',
   templateUrl: './tag-cloud.component.html',
   styleUrls: ['./tag-cloud.component.scss']
 })
-export class TagCloudComponent implements OnInit {
+export class TagCloudComponent implements OnInit, OnDestroy, AfterContentInit {
+
+  @ViewChild(TCloudComponent, { static: false }) child: TCloudComponent;
+  @ViewChild(TagCloudPopUpComponent) popup: TagCloudPopUpComponent;
+  @ViewChild(MatDrawer) drawer: MatDrawer;
 
-  @ViewChild(TCloudComponent, {static: false}) child: TCloudComponent;
   @Input() user: User;
   @Input() roomId: string;
   room: Room;
-  headerInterface = null;
   directSend = true;
   shortId: string;
   options: CloudOptions = {
-    // if width is between 0 and 1 it will be set to the width of the upper element multiplied by the value
-    width: 0.99,
-    // if height is between 0 and 1 it will be set to the height of the upper element multiplied by the value
-    height: 0.99,
+    width: 1,
+    height: 1,
     overflow: false,
-    font: 'Georgia', // not working
+    font: 'Not used',
     delay: 0
   };
   zoomOnHoverOptions: ZoomOnHoverOptions = {
-    scale: 1.3, // Elements will become 130 % of current size on hover
-    transitionTime: 0.6, // it will take 0.6 seconds until the zoom level defined in scale property has been reached
-    delay: 0.4 // Zoom will take affect after 0.4 seconds
+    scale: 1.3,
+    transitionTime: 0.6,
+    delay: 0.4
   };
   userRole: UserRole;
-  data: CloudData[] = [];
-  sorted = false;
-  debounceTimer = 0;
-  lastDebounceTime = 0;
-  configurationOpen = false;
-  randomizeAngle = false;
+  data: TagComment[] = [];
+  isLoading = true;
+  headerInterface = null;
+  themeSubscription = null;
+  createCommentWrapper: CreateCommentWrapper = null;
+  question = '';
+  private _currentSettings: CloudParameters;
+  private _subscriptionCommentlist = null;
+  private _subscriptionRoom = null;
+  private _calcCanvas: HTMLCanvasElement = null;
+  private _calcRenderContext: CanvasRenderingContext2D = null;
+  private _calcFont: string = null;
+  private readonly _smartDebounce = new SmartDebounce(50, 1_000);
+  private _currentTheme: Theme;
 
   constructor(private commentService: CommentService,
-              private spacyService: SpacyService,
               private langService: LanguageService,
               private translateService: TranslateService,
               public dialog: MatDialog,
@@ -186,24 +119,67 @@ export class TagCloudComponent implements OnInit {
               private authenticationService: AuthenticationService,
               private route: ActivatedRoute,
               protected roomService: RoomService,
-              private themeService: ThemeService) {
+              private themeService: ThemeService,
+              private wsCommentService: WsCommentService,
+              private topicCloudAdmin: TopicCloudAdminService,
+              private router: Router,
+              public dataManager: TagCloudDataService,
+              private wsRoomService: WsRoomService) {
     this.roomId = localStorage.getItem('roomId');
     this.langService.langEmitter.subscribe(lang => {
       this.translateService.use(lang);
     });
+    this._currentSettings = TagCloudComponent.getCurrentCloudParameters();
+    this.question = localStorage.getItem('tag-cloud-question');
+    this._calcCanvas = document.createElement('canvas');
+    this._calcRenderContext = this._calcCanvas.getContext('2d');
+  }
+
+  private static getCurrentCloudParameters(): CloudParameters {
+    return CloudParameters.currentParameters;
+  }
+
+  private static invertHex(hexStr: string) {
+    const r = 255 - parseInt(hexStr.substr(1, 2), 16);
+    const g = 255 - parseInt(hexStr.substr(3, 2), 16);
+    const b = 255 - parseInt(hexStr.substr(5, 2), 16);
+    return `#${((r * 256 + g) * 256 + b).toString(16).padStart(6, '0')}`;
   }
 
   ngOnInit(): void {
+    this.updateGlobalStyles();
     this.headerInterface = this.eventService.on<string>('navigate').subscribe(e => {
       if (e === 'createQuestion') {
-        this.openCreateDialog();
+        this.createCommentWrapper.openCreateDialog(this.user);
       } else if (e === 'topicCloudConfig') {
-        this.configurationOpen = !this.configurationOpen;
-      } else if (e === 'topicCloudAdministration') {
-          this.dialog.open(TopicCloudAdministrationComponent, {
-            minWidth: '50%'
-          });
+        if (this.drawer.opened) {
+          this.drawer.close();
+        } else {
+          this.drawer.open();
         }
+      } else if (e === 'topicCloudAdministration') {
+        this.dialog.open(TopicCloudAdministrationComponent, {
+          minWidth: '50%',
+          maxHeight: '95%',
+          data: {
+            user: this.user
+          }
+        });
+      } else if (e === 'questionBoard') {
+        this.router.navigate(['../'], { relativeTo: this.route });
+      }
+    });
+    this.dataManager.getData().subscribe(data => {
+      if (!data) {
+        return;
+      }
+      this.rebuildData();
+    });
+    this.dataManager.getMetaData().subscribe(data => {
+      if (!data) {
+        return;
+      }
+      this.eventService.broadcast('tagCloudHeaderDataOverview', data);
     });
     this.authenticationService.watchUser.subscribe(newUser => {
       if (newUser) {
@@ -213,11 +189,21 @@ export class TagCloudComponent implements OnInit {
     this.userRole = this.route.snapshot.data.roles[0];
     this.route.params.subscribe(params => {
       this.shortId = params['shortId'];
+      this.authenticationService.checkAccess(this.shortId);
       this.authenticationService.guestLogin(UserRole.PARTICIPANT).subscribe(r => {
         this.roomService.getRoomByShortId(this.shortId).subscribe(room => {
           this.room = room;
           this.roomId = room.id;
+          this._subscriptionRoom = this.wsRoomService.getRoomStream(this.roomId).subscribe(msg => {
+            const message = JSON.parse(msg.body);
+            if (message.type === 'RoomPatched') {
+              this.room.questionsBlocked = message.payload.changes.questionsBlocked;
+              this.room.blacklistIsActive = message.payload.changes.blacklistIsActive;
+            }
+          });
           this.directSend = this.room.directSend;
+          this.createCommentWrapper = new CreateCommentWrapper(this.translateService,
+            this.notificationService, this.commentService, this.dialog, this.room);
           if (!this.authenticationService.hasAccess(this.shortId, UserRole.PARTICIPANT)) {
             this.roomService.addToHistory(this.room.id);
             this.authenticationService.setAccess(this.shortId, UserRole.PARTICIPANT);
@@ -226,189 +212,278 @@ export class TagCloudComponent implements OnInit {
       });
     });
     this.translateService.use(localStorage.getItem('currentLang'));
-    this.commentService.getFilteredComments(this.roomId).subscribe((comments: Comment[]) => {
-      this.analyse(comments);
-    });
-    this.themeService.getTheme().subscribe(() => {
+    this.themeSubscription = this.themeService.getTheme().subscribe((themeName) => {
+      this._currentTheme = this.themeService.getThemeByKey(themeName);
       if (this.child) {
         setTimeout(() => {
-          this.setCloudParameters(this.getCurrentCloudParameters(), false);
-          this.updateTagCloud();
+          this.setCloudParameters(TagCloudComponent.getCurrentCloudParameters(), false);
         }, 1);
       }
     });
   }
 
-  initTagCloud() {
-    setTimeout(() => {
-      this.setCloudParameters(this.getCurrentCloudParameters(), false);
-    });
+  ngAfterContentInit() {
+    this._calcFont = window.getComputedStyle(document.getElementById('tagCloudComponent')).fontFamily;
+    setTimeout(() => this.dataManager.bindToRoom(this.roomId, this.userRole));
+    this.dataManager.updateDemoData(this.translateService);
+    this.setCloudParameters(TagCloudComponent.getCurrentCloudParameters(), false);
   }
 
-  resetColorsToTheme() {
-    this.setCloudParameters(getDefaultCloudParameters());
+  ngOnDestroy() {
+    const customTagCloudStyles = document.getElementById('tagCloudStyles') as HTMLStyleElement;
+    if (customTagCloudStyles) {
+      customTagCloudStyles.sheet.disabled = true;
+    }
+    this.headerInterface.unsubscribe();
+    this.themeSubscription.unsubscribe();
+    this.dataManager.unbindRoom();
+    if (this._subscriptionRoom) {
+      this._subscriptionRoom.unsubscribe();
+    }
+  }
+
+  get tagCloudDataManager(): TagCloudDataService {
+    return this.dataManager;
   }
 
-  getCurrentCloudParameters(): CloudParameters {
-    const jsonData = localStorage.getItem('tagCloudConfiguration');
-    const elem: CloudParameters = jsonData != null ? JSON.parse(jsonData) : null;
-    return elem || getDefaultCloudParameters();
+  get currentCloudParameters(): CloudParameters {
+    return new CloudParameters(this._currentSettings);
   }
 
-  setCloudParameters(data: CloudParameters, save = true): void {
-    const arr = getResolvedDefaultColors();
-    arr[0] = data.fontColor;
-    arr[11] = data.backgroundColor;
-    const fontRange = (data.fontSizeMax - data.fontSizeMin) / 10;
-    const styles = arr.map((e, i) => {
-      if (i > 10) {
-        return 'background-color: ' + e + ';';
-      } else if (i > 0) {
-        return 'color: ' + e + '; font-size: ' + (data.fontSizeMin + fontRange * i).toFixed(0) + '%;';
-      } else {
-        return 'color: ' + e + ';';
+  setCloudParameters(parameters: CloudParameters, save = true): void {
+    parameters = new CloudParameters(parameters);
+    const updateIntensity = this.calcUpdateIntensity(parameters);
+    this._currentSettings = parameters;
+    this.zoomOnHoverOptions.delay = parameters.hoverDelay;
+    this.zoomOnHoverOptions.scale = parameters.hoverScale;
+    this.zoomOnHoverOptions.transitionTime = parameters.hoverTime;
+    if (updateIntensity >= 1) {
+      this.updateGlobalStyles();
+    }
+    if (updateIntensity >= 2) {
+      if (!this.dataManager.updateConfig(parameters)) {
+        this.rebuildData();
       }
-    });
-    setGlobalStyles(styles as TagCloudStyleData);
-    this.zoomOnHoverOptions.delay = data.hoverDelay;
-    this.zoomOnHoverOptions.scale = data.hoverScale;
-    this.zoomOnHoverOptions.transitionTime = data.hoverTime;
-    this.options.delay = data.delayWord;
-    this.randomizeAngle = data.randomAngles;
-    if (this.randomizeAngle) {
-      this.data.forEach(e => e.rotate = Math.floor(Math.random() * 30 - 15));
-    } else {
-      this.data.forEach(e => e.rotate = 0);
     }
-    this.updateTagCloud();
     if (save) {
-      localStorage.setItem('tagCloudConfiguration', JSON.stringify(data));
+      CloudParameters.currentParameters = parameters;
     }
   }
 
+  resetColorsToTheme() {
+    const param = new CloudParameters();
+    param.resetToDefault(this._currentTheme.isDark);
+    this.setCloudParameters(param, false);
+    CloudParameters.removeParameters();
+  }
+
   onResize(event: UIEvent): any {
     this.updateTagCloud();
   }
 
-  sortPositionsAlphabetically(sort: boolean): void {
-    if (!sort) {
-      this.sorted = false;
-      this.data.forEach(e => e.position = null);
+  rebuildData() {
+    if (!this.child || !this.dataManager.currentData) {
       return;
     }
-    this.sorted = true;
-    if (!this.data.length) {
-      return;
+    const newElements = [];
+    const data = this.dataManager.currentData;
+    const countFiler = [];
+    for (let i = 0; i < 10; i++) {
+      countFiler.push(this._currentSettings.cloudWeightSettings[i].maxVisibleElements);
+    }
+    for (const [tag, tagData] of data) {
+      const amount = this.dataManager.demoActive ? 10 - tagData.adjustedWeight : 1;
+      for (let i = 0; i < amount; i++) {
+        const remaining = countFiler[tagData.adjustedWeight];
+        if (remaining !== 0) {
+          if (remaining > 0) {
+            --countFiler[tagData.adjustedWeight];
+          }
+          let rotation = this._currentSettings.cloudWeightSettings[tagData.adjustedWeight].rotation;
+          if (rotation === null || this._currentSettings.randomAngles) {
+            rotation = Math.floor(Math.random() * 30 - 15);
+          }
+          newElements.push(new TagComment(tag, rotation, tagData.weight, tagData, newElements.length));
+        }
+      }
     }
-    this.data.sort((a, b) => a.text.localeCompare(b.text));
-    const lines = Math.floor(Math.sqrt(this.data.length - 1) + 1);
-    const divided = Math.floor(this.data.length / lines);
-    let remainder = this.data.length - divided * lines;
-    for (let i = 0, line = 0; line < lines; line++) {
-      const size = divided + (--remainder >= 0 ? 1 : 0);
-      for (let k = 0; k < size; k++, i++) {
-        this.data[i].position = new CustomPosition((k + 1) / (size + 1), (line + 1) / (lines + 1));
+    if (this._currentSettings.sortAlphabetically) {
+      const lines = Math.floor(Math.sqrt(newElements.length - 1) + 1);
+      const divided = Math.floor(newElements.length / lines);
+      let remainder = newElements.length - divided * lines;
+      for (let i = 0, line = 0; line < lines; line++) {
+        const size = divided + (--remainder >= 0 ? 1 : 0);
+        for (let k = 0; k < size; k++, i++) {
+          newElements[i].position = new CustomPosition((k + 1) / (size + 1), (line + 1) / (lines + 1));
+        }
       }
+      this.updateAlphabeticalPosition(newElements);
     }
+    this.data = newElements;
+    setTimeout(() => {
+      this.updateTagCloud(true);
+    }, 2);
   }
 
-  analyse(comments: Comment[]) {
-    const commentsConcatenated = comments.map(c => c.body).join(' ');
+  updateTagCloud(dataUpdated = false) {
+    this.isLoading = true;
+    if (this._currentSettings.sortAlphabetically && this.data.length) {
+      this.updateAlphabeticalPosition(this.data);
+    }
+    this._smartDebounce.call(() => this.redraw(dataUpdated));
+  }
 
-    this.spacyService.analyse(commentsConcatenated, 'de').subscribe((res: Result) => {
-      const map = new Map<string, number>();
-      res.words.filter(w => ['NE', 'NN', 'NMP', 'NNE'].indexOf(w.tag) >= 0).forEach(elem => {
-        const count = (map.get(elem.text) || 0) + 1;
-        map.set(elem.text, count);
-      });
-      map.forEach((val, key) => {
-          this.data.push(new TagComment(null,
-            true, null, null,
-            this.randomizeAngle ? Math.floor(Math.random() * 30 - 15) : 0, key,
-            'TODO', val));
-        }
-      );
-      this.sortPositionsAlphabetically(this.sorted);
-      this.updateTagCloud();
+  openTags(tag: CloudData): void {
+    if (this.dataManager.demoActive || this._subscriptionCommentlist !== null) {
+      return;
+    }
+    this._subscriptionCommentlist = this.eventService.on('commentListCreated').subscribe(() => {
+      this.eventService.broadcast('setTagConfig', tag.text);
+      this._subscriptionCommentlist.unsubscribe();
     });
+    this.router.navigate(['../'], { relativeTo: this.route });
   }
 
-  updateTagCloud() {
-    if (this.sorted && this.data.length) {
-      if (!this.child.cloudDataHtmlElements || !this.child.cloudDataHtmlElements.length) {
-        this.child.reDraw();
-      }
-      const width = this.child.calculatedWidth;
-      const height = this.child.calculatedHeight;
-      this.data.forEach((e, i) => {
-        (e.position as CustomPosition).updatePosition(width, height, e.text,
-          window.getComputedStyle(this.child.cloudDataHtmlElements[i]));
-      });
+  private updateAlphabeticalPosition(elements: TagComment[]): void {
+    const sizes = new Array(10);
+    const fontRange = (this._currentSettings.fontSizeMax - this._currentSettings.fontSizeMin) / 10;
+    for (let i = 1; i <= 10; i++) {
+      sizes[i - 1] = (this._currentSettings.fontSizeMin + fontRange * i).toFixed(0) + '%';
     }
-    const debounceTime = 1_000;
-    const current = new Date().getTime();
-    const diff = current - this.lastDebounceTime;
-    if (diff >= debounceTime) {
-      this.lastDebounceTime = current;
+    const width = this.child.calculatedWidth;
+    const height = this.child.calculatedHeight;
+    elements.forEach((e, i) => {
+      this._calcRenderContext.font = sizes[e.tagData.adjustedWeight] + ' ' + this._calcFont;
+      (e.position as CustomPosition).updatePosition(width, height, this._calcRenderContext.measureText(e.text));
+    });
+  }
+
+  private redraw(dataUpdate: boolean): void {
+    if (this.child === undefined) {
+      return;
+    }
+    this.isLoading = false;
+    if (!dataUpdate) {
       this.child.reDraw();
-    } else {
-      clearTimeout(this.debounceTimer);
-      this.debounceTimer = setTimeout(() => {
-        this.lastDebounceTime = new Date().getTime();
-        this.child.reDraw();
-      }, debounceTime - diff);
     }
+    if (this.dataManager.currentData === null) {
+      return;
+    }
+    this.child.cloudDataHtmlElements.forEach((elem, i) => {
+      const dataElement = this.data[i];
+      elem.addEventListener('mouseleave', () => {
+        elem.style.transform = elem.style.transform.replace(transformationScaleKiller, '').trim() +
+          ' rotate(' + (elem.dataset['tempRotation'] || '0deg') + ')';
+        this.popup.leave();
+      });
+      elem.addEventListener('mouseenter', () => {
+        const transformMatch = elem.style.transform.match(transformationRotationKiller);
+        elem.dataset['tempRotation'] = transformMatch ? transformMatch[1] : '0deg';
+        elem.style.transform = elem.style.transform.replace(transformationRotationKiller, '').trim();
+        this.popup.enter(elem, dataElement.text, dataElement.tagData,
+          (this._currentSettings.hoverTime + this._currentSettings.hoverDelay) * 1_000,
+          this.room && this.room.blacklistIsActive);
+      });
+    });
   }
 
-  openCreateDialog(): void {
-    const dialogRef = this.dialog.open(CreateCommentComponent, {
-      width: '900px',
-      maxWidth: 'calc( 100% - 50px )',
-      maxHeight: 'calc( 100vh - 50px )',
-      autoFocus: false,
-    });
-    dialogRef.componentInstance.user = this.user;
-    dialogRef.componentInstance.roomId = this.roomId;
-    let tags;
-    tags = [];
-    if (this.room.tags) {
-      tags = this.room.tags;
+  private updateGlobalStyles(): void {
+    let customTagCloudStyles = document.getElementById('tagCloudStyles') as HTMLStyleElement;
+    if (!customTagCloudStyles) {
+      customTagCloudStyles = document.createElement('style');
+      customTagCloudStyles.id = 'tagCloudStyles';
+      document.head.appendChild(customTagCloudStyles);
     }
-    dialogRef.componentInstance.tags = tags;
-    dialogRef.afterClosed()
-      .subscribe(result => {
-        if (result) {
-          this.send(result);
-        } else {
-          return;
-        }
-      });
+    customTagCloudStyles.sheet.disabled = false;
+    const rules = customTagCloudStyles.sheet.cssRules;
+    for (let i = rules.length - 1; i >= 0; i--) {
+      customTagCloudStyles.sheet.deleteRule(i);
+    }
+    let textTransform = '';
+    let plainTextTransform = 'unset';
+    if (this._currentSettings.textTransform === CloudTextStyle.capitalized) {
+      textTransform = 'text-transform: capitalize;';
+      plainTextTransform = 'capitalize';
+    } else if (this._currentSettings.textTransform === CloudTextStyle.lowercase) {
+      textTransform = 'text-transform: lowercase;';
+      plainTextTransform = 'lowercase';
+    } else if (this._currentSettings.textTransform === CloudTextStyle.uppercase) {
+      textTransform = 'text-transform: uppercase;';
+      plainTextTransform = 'uppercase';
+    }
+    customTagCloudStyles.sheet.insertRule('.spacyTagCloud > span, .spacyTagCloud > span > a { ' +
+      textTransform + ' font-family: ' + this._currentSettings.fontFamily + '; ' +
+      'font-size: ' + this._currentSettings.fontSize + '; ' +
+      'font-weight: ' + this._currentSettings.fontWeight + '; ' +
+      'font-style:' + this._currentSettings.fontStyle + '; }');
+    const fontRange = (this._currentSettings.fontSizeMax - this._currentSettings.fontSizeMin) / 10;
+    for (let i = 1; i <= 10; i++) {
+      customTagCloudStyles.sheet.insertRule('.spacyTagCloud > span.w' + i + ', ' +
+        '.spacyTagCloud > span.w' + i + ' > a { ' +
+        'color: ' + this._currentSettings.cloudWeightSettings[i - 1].color + '; ' +
+        'font-size: ' + (this._currentSettings.fontSizeMin + fontRange * i).toFixed(0) + '%; }');
+    }
+    customTagCloudStyles.sheet.insertRule('.spacyTagCloud > span:hover, .spacyTagCloud > span:hover > a { ' +
+      'color: ' + this._currentSettings.fontColor + ' !important; ' +
+      'background-color: ' + this._currentSettings.backgroundColor + '; }');
+    customTagCloudStyles.sheet.insertRule('.spacyTagCloudContainer { ' +
+      'background-color: ' + this._currentSettings.backgroundColor + '; }');
+    const invertedBackground = TagCloudComponent.invertHex(this._currentSettings.backgroundColor);
+    customTagCloudStyles.sheet.insertRule(':root { ' +
+      '--tag-cloud-inverted-background: ' + invertedBackground + ';' +
+      '--tag-cloud-transform: ' + plainTextTransform + ';' +
+      '--tag-cloud-background-color: ' + this._currentSettings.backgroundColor + ';' +
+      '--tag-cloud-font-weight: ' + this._currentSettings.fontWeight + ';' +
+      '--tag-cloud-font-style: ' + this._currentSettings.fontStyle + ';' +
+      '--tag-cloud-font-family: ' + this._currentSettings.fontFamily + '; }');
+    customTagCloudStyles.sheet.insertRule('.header-icons { ' +
+      'color: var(--tag-cloud-inverted-background) !important; }');
+    customTagCloudStyles.sheet.insertRule('.header .oldtypo-h2, .header .oldtypo-h2 + span { ' +
+      'color: var(--tag-cloud-inverted-background) !important; }');
+    customTagCloudStyles.sheet.insertRule('#footer_rescale {' +
+      'display: none; }');
+    customTagCloudStyles.sheet.insertRule('div.main_container {' +
+      'background-color: var(--tag-cloud-background-color) !important; }');
   }
 
-  send(comment: Comment): void {
-    if (this.directSend) {
-      this.translateService.get('comment-list.comment-sent').subscribe(msg => {
-        this.notificationService.show(msg);
-      });
-      comment.ack = true;
-    } else {
-      if (this.userRole === 1 || this.userRole === 2 || this.userRole === 3) {
-        this.translateService.get('comment-list.comment-sent').subscribe(msg => {
-          this.notificationService.show(msg);
-        });
-        comment.ack = true;
+  /**
+   * 0 = update nothing,
+   * 1 = update css,
+   * 2 = update data
+   */
+  private calcUpdateIntensity(parameters: CloudParameters): number {
+    if (!this._currentSettings) {
+      return 2;
+    }
+    const cssUpdates = ['backgroundColor', 'fontColor'];
+    const dataUpdates = ['randomAngles', 'sortAlphabetically',
+      'fontSizeMin', 'fontSizeMax', 'textTransform', 'fontStyle', 'fontWeight', 'fontFamily', 'fontSize'];
+    const cssWeightUpdates = ['color'];
+    const dataWeightUpdates = ['maxVisibleElements', 'rotation'];
+    for (const key of dataUpdates) {
+      if (this._currentSettings[key] !== parameters[key]) {
+        return 2;
       }
-      if (this.userRole === 0) {
-        this.translateService.get('comment-list.comment-sent-to-moderator').subscribe(msg => {
-          this.notificationService.show(msg);
-        });
+    }
+    for (let i = 0; i < 10; i++) {
+      for (const key of dataWeightUpdates) {
+        if (this._currentSettings.cloudWeightSettings[i][key] !== parameters.cloudWeightSettings[i][key]) {
+          return 2;
+        }
       }
     }
-    this.commentService.addComment(comment).subscribe();
-  }
-
-  openCloudConfiguration() {
-    this.configurationOpen = true;
+    for (const key of cssUpdates) {
+      if (this._currentSettings[key] !== parameters[key]) {
+        return 1;
+      }
+    }
+    for (let i = 0; i < 10; i++) {
+      for (const key of cssWeightUpdates) {
+        if (this._currentSettings.cloudWeightSettings[i][key] !== parameters.cloudWeightSettings[i][key]) {
+          return 1;
+        }
+      }
+    }
+    return 0;
   }
-
 }
diff --git a/src/app/components/shared/tag-cloud/tag-cloud.interface.ts b/src/app/components/shared/tag-cloud/tag-cloud.interface.ts
deleted file mode 100644
index b3faae6f98bc4f485fc2ed4bbaeaefdbc71be061..0000000000000000000000000000000000000000
--- a/src/app/components/shared/tag-cloud/tag-cloud.interface.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-export interface CloudParameters {
-  /**
-   * Background color of the Tag-cloud
-   */
-  backgroundColor: string;
-  /**
-   * Color when hovering over the elements
-   */
-  fontColor: string;
-  /**
-   * Percentage values for the weight classes, by interpolation all classes are filled with values
-   */
-  fontSizeMin: number;
-  /**
-   * Percentage values fot the weight classes, by interpolation all classes are filled with values
-   */
-  fontSizeMax: number;
-  /**
-   * Describes scaling when hovering
-   */
-  hoverScale: number;
-  /**
-   * Time for hovering in ms
-   */
-  hoverTime: number;
-  /**
-   * Time before hover animation starts in ms
-   */
-  hoverDelay: number;
-  /**
-   * Time for delay in ms between each word during build-up
-   */
-  delayWord: number;
-  /**
-   * Enables random angles
-   */
-  randomAngles: boolean;
-}
diff --git a/src/app/components/shared/write-comment/write-comment.component.html b/src/app/components/shared/write-comment/write-comment.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..a5fd579b1e1fcb5762c72a6b698cd53aee18e1f8
--- /dev/null
+++ b/src/app/components/shared/write-comment/write-comment.component.html
@@ -0,0 +1,139 @@
+<ars-row>
+  <ng-container [ngTemplateOutlet]="additionalTemplate"></ng-container>
+  <div class="lang-selection" *ngIf="enabled">
+    <button class="lang-btn"
+            mat-button
+            (click)="select.open()"
+            matTooltip="{{ 'spacy-dialog.lang-button-hint' | translate }}"
+            matTooltipShowDelay="750">
+      <mat-icon id="langSymbol">language</mat-icon>
+      <span *ngIf="!(grammarChecker.selectedLang === 'auto')">
+          {{'spacy-dialog.' + (languagetoolService.mapLanguageToSpacyModel(grammarChecker.selectedLang)) | translate}}
+        </span>
+      <span *ngIf="(grammarChecker.selectedLang === 'auto')"
+            #langSelect>
+         auto
+        </span>
+      <mat-select class="select-list"
+                  #select
+                  [(ngModel)]="grammarChecker.selectedLang">
+        <mat-option *ngFor="let lang of grammarChecker.languages"
+                    [value]="lang">
+          <span *ngIf="lang == 'de-DE'">{{ 'spacy-dialog.de' | translate }}</span>
+          <span *ngIf="lang == 'en-US'">{{ 'spacy-dialog.en' | translate }}</span>
+          <span *ngIf="lang == 'fr'">{{ 'spacy-dialog.fr' | translate }}</span>
+          <span *ngIf="lang == 'auto'">{{ 'spacy-dialog.auto' | translate }}</span>
+        </mat-option>
+      </mat-select>
+    </button>
+  </div>
+  <div class="anchor-wrp" *ngIf="enabled">
+    <div class="anchor-right">
+      <mat-form-field *ngIf="tags"
+                      class="tag-form-field">
+        <mat-label>
+          <mat-icon class="icon-svg"
+                    svgIcon="comment_tag"></mat-icon>
+          {{'comment-page.tag' | translate}}
+        </mat-label>
+        <label for="tagSelect">{{selectedTag}}</label>
+        <mat-select [(ngModel)]="selectedTag"
+                    class="tag-select"
+                    id="tagSelect">
+          <mat-option>{{'comment-page.tag-reset' | translate}}</mat-option>
+          <mat-option *ngFor="let tag of tags"
+                      value="{{tag}}">{{tag}}</mat-option>
+        </mat-select>
+      </mat-form-field>
+    </div>
+  </div>
+  <mat-tab-group (selectedTabChange)="onTabChange()" *ngIf="enabled">
+    <mat-tab label="{{ 'comment-page.write-comment' | translate }}">
+      <ars-row [height]="12"></ars-row>
+      <ars-row>
+
+      </ars-row>
+      <ars-row [height]="12"></ars-row>
+      <ars-row [overflow]="'visible'"
+               class="comment-write-container">
+        <mat-form-field class="full-width">
+          <input [disabled]="true"
+                 matInput>
+          <div
+            (document:click)="grammarChecker.onDocumentClick($event)"
+            [contentEditable]="true"
+            (paste)="grammarChecker.onPaste($event); grammarChecker.maxLength(commentBody, user.role === 3 ? 1000 : 500)"
+            [spellcheck]="false"
+            (focus)="eventService.makeFocusOnInputTrue()"
+            (blur)="eventService.makeFocusOnInputFalse()"
+            #commentBody
+            aria-labelledby="ask-question-description"
+            autofocus
+            (input)="grammarChecker.maxLength(commentBody, user.role === 3 ? 1000 : 500)"
+            id="answer-input">
+          </div>
+          <mat-placeholder class="placeholder">
+            {{ 'comment-page.enter-comment' | translate }}
+          </mat-placeholder>
+          <mat-hint align="start">
+              <span aria-hidden="true">
+                {{ 'comment-page.Markdown-hint' | translate }}
+              </span>
+          </mat-hint>
+          <mat-hint align="end">
+              <span aria-hidden="true">
+                {{commentBody.innerText.length}} / {{user.role === 3 ? 1000 : 500}}
+              </span>
+          </mat-hint>
+          <span *ngIf="!grammarChecker.hasSpellcheckConfidence">
+              <p class="lang-confidence">{{ 'spacy-dialog.force-language-selection' | translate }}</p>
+            </span>
+
+        </mat-form-field>
+      </ars-row>
+    </mat-tab>
+    <mat-tab label="{{ 'comment-page.preview-comment' | translate }}"
+             [disabled]="!commentBody.innerText">
+      <ars-row [height]="12"></ars-row>
+      <ars-row>
+
+      </ars-row>
+      <ars-row [height]="12"></ars-row>
+      <ars-row>
+        <app-custom-markdown [data]="tempEditView"></app-custom-markdown>
+      </ars-row>
+    </mat-tab>
+  </mat-tab-group>
+</ars-row>
+<ars-row class="filler-row">
+
+</ars-row>
+<ars-row ars-flex-box
+         *ngIf="enabled"
+         class="spellcheck">
+  <ars-col>
+    <button
+      [disabled]="this.commentBody && this.commentBody.nativeElement.innerHTML.length < 4 "
+      mat-flat-button
+      class="spell-button"
+      (click)="grammarChecker.grammarCheck(commentBody.nativeElement)">
+      {{ 'comment-page.grammar-check' | translate}}
+      <mat-icon *ngIf="grammarChecker.isSpellchecking"
+                class="spinner-container">
+        <app-mat-spinner-overlay diameter="20" strokeWidth="2" [color]="'on-primary'"></app-mat-spinner-overlay>
+      </mat-icon>
+    </button>
+  </ars-col>
+  <ars-col>
+    <app-dialog-action-buttons
+      buttonsLabelSection="comment-page"
+      [confirmButtonLabel]="confirmLabel"
+      [cancelButtonLabel]="cancelLabel"
+      [showLoadingCycle]="isSpinning"
+      [showDivider]="false"
+      [spacing]="false"
+      [cancelButtonClickAction]="buildCloseDialogActionCallback()"
+      [confirmButtonClickAction]="buildCreateCommentActionCallback()"
+    ></app-dialog-action-buttons>
+  </ars-col>
+</ars-row>
diff --git a/src/app/components/shared/write-comment/write-comment.component.scss b/src/app/components/shared/write-comment/write-comment.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..71dd4b064b72b7ac9a1dd534575c2f22c59d7de8
--- /dev/null
+++ b/src/app/components/shared/write-comment/write-comment.component.scss
@@ -0,0 +1,226 @@
+button {
+  min-width: 80px;
+}
+
+.mat-flat-button.mat-primary.mat-button-disabled, .mat-flat-button.mat-accent.mat-button-disabled,
+.mat-flat-button.mat-warn.mat-button-disabled, .mat-flat-button.mat-button-disabled.mat-button-disabled,
+.mat-raised-button.mat-primary.mat-button-disabled, .mat-raised-button.mat-accent.mat-button-disabled,
+.mat-raised-button.mat-warn.mat-button-disabled, .mat-raised-button.mat-button-disabled.mat-button-disabled,
+.mat-fab.mat-primary.mat-button-disabled, .mat-fab.mat-accent.mat-button-disabled,
+.mat-fab.mat-warn.mat-button-disabled, .mat-fab.mat-button-disabled.mat-button-disabled,
+.mat-mini-fab.mat-primary.mat-button-disabled, .mat-mini-fab.mat-accent.mat-button-disabled,
+.mat-mini-fab.mat-warn.mat-button-disabled, .mat-mini-fab.mat-button-disabled.mat-button-disabled {
+  display: none;
+}
+
+.spell-button {
+  background-color: var(--primary);
+  color: var(--on-primary);
+  margin-top: 1rem;
+  animation: shake 1.5s;
+}
+
+.spellcheck {
+  @media screen and (max-width: 500px) {
+    overflow: auto;
+    display: flex;
+    justify-content: space-between;
+    flex-direction: column !important;
+    flex-wrap: wrap;
+    align-items: flex-end;
+  }
+}
+
+.spinner-container {
+  font-size: 14px;
+  margin-top: -2px;
+}
+
+#answer-input {
+  line-height: 120%;
+  color: var(--on-surface);
+  caret-color: var(--on-surface);
+  -webkit-appearance: textarea;
+  min-height: 50px;
+  cursor: text;
+  word-wrap: break-word;
+  margin-top: 15px;
+  width: 100%;
+
+  &:focus {
+    outline: none;
+  }
+}
+
+::ng-deep {
+  .mat-form-field-label {
+    color: var(--on-surface) !important;
+  }
+
+  .mat-form-field-underline, .mat-form-field-ripple {
+    background-color: var(--on-surface) !important;
+  }
+
+  .mat-tab-body-content {
+    max-width: 540px !important;
+    overflow-x: hidden !important;
+  }
+}
+
+mat-hint {
+  color: var(--on-surface) !important;
+}
+
+.placeholder {
+  color: var(--on-surface);
+}
+
+.lang-confidence {
+  color: var(--on-cancel);
+  background-color: var(--cancel);
+  font-size: 16px;
+  padding: 5px;
+}
+
+::ng-deep .mat-form-field .mat-form-field-infix {
+  max-width: 500px;
+}
+
+.full-width {
+  width: 100%;
+}
+
+.comment-write-container {
+  max-height: calc(100vh - 250px);
+}
+
+.filler-row {
+  margin-top: 8px;
+}
+
+/*
+Styling for tag selection
+ */
+
+#tagSelect {
+  display: inline;
+}
+
+.tag-form-field {
+  @media screen and (max-width: 500px) {
+    width: 70px;
+  }
+  z-index: 10000;
+}
+
+.anchor-right {
+  @media screen and (max-width: 500px) {
+    width: 70px;
+    left: calc(100% - 70px);
+  }
+  width: 200px;
+  height: 50px;
+  position: relative;
+  left: calc(100% - 200px);
+  top: 0;
+}
+
+.anchor-wrp {
+  width: 100%;
+  height: 0;
+  position: relative;
+  left: 0;
+  top: 0;
+}
+
+/*
+Styling for language select
+ */
+
+#langSymbol {
+  margin-right: 18px;
+}
+
+.select-list {
+  width: calc(100% - 24px);
+}
+
+.lang-selection {
+  vertical-align: middle;
+  margin-right: 0;
+}
+
+/*
+Styling for tag selection and language selection
+ */
+
+::ng-deep {
+  .mat-select-arrow-wrapper .mat-select-arrow {
+    color: var(--on-surface);
+    margin-right: 50px;
+  }
+
+  .mat-select-value {
+    width: auto !important;
+  }
+
+  .mat-select-value-text {
+    color: var(--on-surface);
+    caret-color: var(--on-surface);
+  }
+
+  .mat-primary .mat-option.mat-selected:not(.mat-option-disabled) {
+    color: var(--primary);
+  }
+
+  .mat-select-panel {
+    background: var(--dialog);
+  }
+}
+
+.mat-option {
+  color: var(--on-surface);
+}
+
+/*
+Suggestion classes from Languagetool
+ */
+
+::ng-deep .markUp {
+  position: relative;
+  display: inline-block;
+  border-bottom: 1px dotted black;
+
+  > span {
+    text-decoration: underline wavy red;
+    cursor: pointer;
+  }
+
+  > .dropdownBlock {
+    display: none;
+    width: 160px;
+    background-color: white;
+    border-style: solid;
+    border-color: var(--primary);
+    color: #fff;
+    text-align: center;
+    border-radius: 6px;
+    padding: 5px 0;
+    position: absolute;
+    z-index: 1000;
+    bottom: 100%;
+
+    > .suggestions {
+      color: black;
+      display: block;
+      text-align: center;
+      cursor: pointer;
+    }
+
+    > .error-message {
+      color: black;
+      display: block;
+      text-align: center;
+    }
+  }
+}
diff --git a/src/app/components/shared/write-comment/write-comment.component.spec.ts b/src/app/components/shared/write-comment/write-comment.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3207abc4ccdc0340b98b7eb0f6a907fefd947dc6
--- /dev/null
+++ b/src/app/components/shared/write-comment/write-comment.component.spec.ts
@@ -0,0 +1,26 @@
+/*import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { WriteCommentComponent } from './write-comment.component';
+
+describe('WriteCommentComponent', () => {
+  let component: WriteCommentComponent;
+  let fixture: ComponentFixture<WriteCommentComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ WriteCommentComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(WriteCommentComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
+*/
diff --git a/src/app/components/shared/write-comment/write-comment.component.ts b/src/app/components/shared/write-comment/write-comment.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3198b0b73e321b547d01b58264c694c103721cf4
--- /dev/null
+++ b/src/app/components/shared/write-comment/write-comment.component.ts
@@ -0,0 +1,82 @@
+import { AfterViewInit, Component, ElementRef, Input, OnInit, TemplateRef, ViewChild } from '@angular/core';
+import { GrammarChecker } from '../../../utils/grammar-checker';
+import { TranslateService } from '@ngx-translate/core';
+import { LanguagetoolService } from '../../../services/http/languagetool.service';
+import { Comment } from '../../../models/comment';
+import { User } from '../../../models/user';
+import { NotificationService } from '../../../services/util/notification.service';
+import { EventService } from '../../../services/util/event.service';
+
+@Component({
+  selector: 'app-write-comment',
+  templateUrl: './write-comment.component.html',
+  styleUrls: ['./write-comment.component.scss']
+})
+export class WriteCommentComponent implements OnInit, AfterViewInit {
+
+  @ViewChild('langSelect') langSelect: ElementRef<HTMLDivElement>;
+  @ViewChild('commentBody') commentBody: ElementRef<HTMLDivElement>;
+  @Input() user: User;
+  @Input() tags: string[];
+  @Input() onClose: () => any;
+  @Input() onSubmit: (commentText: string, selectedTag: string) => any;
+  @Input() isSpinning = false;
+  @Input() disableCancelButton = false;
+  @Input() confirmLabel = 'save';
+  @Input() cancelLabel = 'cancel';
+  @Input() additionalTemplate: TemplateRef<any>;
+  @Input() enabled = true;
+  comment: Comment;
+  selectedTag: string;
+  grammarChecker: GrammarChecker;
+  tempEditView: string;
+
+  constructor(private notification: NotificationService,
+              private translateService: TranslateService,
+              public eventService: EventService,
+              public languagetoolService: LanguagetoolService) {
+    this.grammarChecker = new GrammarChecker(this.languagetoolService);
+  }
+
+  ngOnInit(): void {
+    this.translateService.use(localStorage.getItem('currentLang'));
+  }
+
+  ngAfterViewInit() {
+    this.grammarChecker.initBehavior(() => this.commentBody.nativeElement, () => this.langSelect.nativeElement);
+  }
+
+  buildCloseDialogActionCallback(): () => void {
+    if (!this.onClose || this.disableCancelButton) {
+      return undefined;
+    }
+    return () => this.onClose();
+  }
+
+  buildCreateCommentActionCallback(): () => void {
+    if (!this.onSubmit) {
+      return undefined;
+    }
+    return () => {
+      if (this.checkInputData(this.commentBody.nativeElement.innerText)) {
+        this.onSubmit(this.commentBody.nativeElement.innerText, this.selectedTag);
+      }
+    };
+  }
+
+  onTabChange() {
+    this.tempEditView = this.commentBody.nativeElement.innerText;
+  }
+
+  private checkInputData(body: string): boolean {
+    body = body.trim();
+    if (!body) {
+      this.translateService.get('comment-page.error-comment').subscribe(message => {
+        this.notification.show(message);
+      });
+      return false;
+    }
+    return true;
+  }
+
+}
diff --git a/src/app/directives/autofocus.directive.spec.ts b/src/app/directives/autofocus.directive.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..550482e426fb93039b3f74c0844b817484a56265
--- /dev/null
+++ b/src/app/directives/autofocus.directive.spec.ts
@@ -0,0 +1,9 @@
+/*import { AutofocusDirective } from './autofocus.directive';
+
+describe('AutofocusDirective', () => {
+  it('should create an instance', () => {
+    const directive = new AutofocusDirective();
+    expect(directive).toBeTruthy();
+  });
+});
+*/
diff --git a/src/app/directives/autofocus.directive.ts b/src/app/directives/autofocus.directive.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fffc34407d17eb889df0ae18ac10fa6b08db069d
--- /dev/null
+++ b/src/app/directives/autofocus.directive.ts
@@ -0,0 +1,16 @@
+import { AfterViewInit, Directive, ElementRef } from '@angular/core';
+
+@Directive({
+  // eslint-disable-next-line @angular-eslint/directive-selector
+  selector: '[autofocus]'
+})
+export class AutofocusDirective implements AfterViewInit {
+
+  constructor(private host: ElementRef) {
+  }
+
+  ngAfterViewInit() {
+    this.host.nativeElement.focus();
+  }
+
+}
diff --git a/src/app/directives/joyride-template.directive.spec.ts b/src/app/directives/joyride-template.directive.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..81969f47d38aff10415e0ee644db9a2d416721f8
--- /dev/null
+++ b/src/app/directives/joyride-template.directive.spec.ts
@@ -0,0 +1,9 @@
+/*import { JoyrideTemplateDirective } from './joyride-template.directive';
+
+describe('JoyrideTemplateDirective', () => {
+  it('should create an instance', () => {
+    const directive = new JoyrideTemplateDirective();
+    expect(directive).toBeTruthy();
+  });
+});
+ */
diff --git a/src/app/directives/joyride-template.directive.ts b/src/app/directives/joyride-template.directive.ts
new file mode 100644
index 0000000000000000000000000000000000000000..78b18a019cc10ce6d24ddeff70a8ae003d94af00
--- /dev/null
+++ b/src/app/directives/joyride-template.directive.ts
@@ -0,0 +1,37 @@
+import {
+  ComponentFactoryResolver,
+  Directive,
+  Input,
+  OnInit,
+  ViewContainerRef
+} from '@angular/core';
+import { JoyrideDirective } from 'ngx-joyride';
+import { JoyrideTemplateComponent } from '../components/shared/_dialogs/joyride-template/joyride-template.component';
+import { EventService } from '../services/util/event.service';
+
+@Directive({
+  selector: '[appJoyrideTemplate]'
+})
+export class JoyrideTemplateDirective implements OnInit {
+
+  constructor(private viewContainerRef: ViewContainerRef,
+              public joyrideDirective: JoyrideDirective,
+              private eventService: EventService,
+              private componentFactory: ComponentFactoryResolver) {
+  }
+
+  ngOnInit(): void {
+    const factory = this.componentFactory.resolveComponentFactory(JoyrideTemplateComponent);
+    const templates = this.viewContainerRef.createComponent(factory);
+    templates.instance.name = this.joyrideDirective.name;
+    this.joyrideDirective.doneTemplate = templates.instance.doneButton;
+    this.joyrideDirective.nextTemplate = templates.instance.nextButton;
+    this.joyrideDirective.prevTemplate = templates.instance.prevButton;
+    this.joyrideDirective.counterTemplate = templates.instance.counter;
+    this.joyrideDirective.stepContent = templates.instance.translateText;
+    this.joyrideDirective.done.subscribe(_ => {
+      this.eventService.broadcast('onboarding', 'canceled');
+    });
+  }
+
+}
diff --git a/src/app/directives/scroll-into-view.directive.spec.ts b/src/app/directives/scroll-into-view.directive.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..361f509a76fbcbb3d4eccd568c3c478cf131dd84
--- /dev/null
+++ b/src/app/directives/scroll-into-view.directive.spec.ts
@@ -0,0 +1,9 @@
+/*import { ScrollIntoViewDirective } from './scroll-into-view.directive';
+
+describe('ScrollIntoViewDirective', () => {
+  it('should create an instance', () => {
+    const directive = new ScrollIntoViewDirective();
+    expect(directive).toBeTruthy();
+  });
+});
+ */
diff --git a/src/app/directives/scroll-into-view.directive.ts b/src/app/directives/scroll-into-view.directive.ts
new file mode 100644
index 0000000000000000000000000000000000000000..642b24a339ea6861019136102f8b3b930359a0de
--- /dev/null
+++ b/src/app/directives/scroll-into-view.directive.ts
@@ -0,0 +1,18 @@
+import { Directive, ElementRef, Input } from '@angular/core';
+
+@Directive({
+  selector: '[appScrollIntoView]'
+})
+export class ScrollIntoViewDirective {
+
+  @Input('appScrollIntoView')
+  set active(value: boolean) {
+    if (value) {
+      this.element.nativeElement.scrollIntoView({ behavior: 'smooth' });
+    }
+  }
+
+  constructor(private element: ElementRef) {
+  }
+
+}
diff --git a/src/app/models/comment.ts b/src/app/models/comment.ts
index 1d488d077c1638391e1b98accac44441fe1eb5c0..18b77b83d0c11f57a30cf254c2cf7d80337b62db 100644
--- a/src/app/models/comment.ts
+++ b/src/app/models/comment.ts
@@ -1,5 +1,6 @@
+import { SpacyKeyword } from '../services/http/spacy.service';
 import { CorrectWrong } from './correct-wrong.enum';
-import { ViewChild } from '@angular/core';
+import { Model } from '../services/http/spacy.interface';
 
 export class Comment {
   id: string;
@@ -20,7 +21,12 @@ export class Comment {
   answer: string;
   userNumber: number;
   number: number;
-  keywords: string[];
+  keywordsFromQuestioner: SpacyKeyword[];
+  keywordsFromSpacy: SpacyKeyword[];
+  upvotes: number;
+  downvotes: number;
+  language: Language;
+  createdBy;
 
   constructor(roomId: string = '',
               creatorId: string = '',
@@ -37,7 +43,12 @@ export class Comment {
               tag: string = '',
               answer: string = '',
               userNumber: number = 0,
-              keywords: string[] = []) {
+              keywordsFromQuestioner: SpacyKeyword[] = [],
+              keywordsFromSpacy: SpacyKeyword[] = [],
+              upvotes = 0,
+              downvotes = 0,
+              language = Language.auto,
+              createdBy?: any) {
     this.id = '';
     this.roomId = roomId;
     this.creatorId = creatorId;
@@ -55,6 +66,27 @@ export class Comment {
     this.tag = tag;
     this.answer = answer;
     this.userNumber = userNumber;
-    this.keywords = keywords;
+    this.keywordsFromQuestioner = keywordsFromQuestioner;
+    this.keywordsFromSpacy = keywordsFromSpacy;
+    this.upvotes = upvotes;
+    this.downvotes = downvotes;
+    this.language = language;
+    this.createdBy = createdBy;
+  }
+
+  static mapModelToLanguage(model: Model): Language {
+    return Language[model] || Language.auto;
   }
 }
+
+export enum Language {
+  de = 'DE',
+  en = 'EN',
+  fr = 'FR',
+  es = 'ES',
+  it = 'IT',
+  nl = 'NL',
+  pt = 'PT',
+  auto = 'AUTO'
+}
+
diff --git a/src/app/models/export.ts b/src/app/models/export.ts
index 1e7523eddf9538ffb56f524bbe4a83b860a93e63..c6b6d9baff80b0646742f0f2798499d0bcf03576 100644
--- a/src/app/models/export.ts
+++ b/src/app/models/export.ts
@@ -98,7 +98,7 @@ export class Export {
           const date = new Date();
           const dateString = date.toLocaleDateString();
           const data = this.mapper.parse(';', translationMap);
-          const fileName = this.room.name + '_' + this.room.shortId + dateString + '.csv';
+          const fileName = this.room.name + '-' + this.room.shortId + '-' + dateString + '.csv';
           this.exportData(data, fileName);
         }
       });
diff --git a/src/app/models/rescale.ts b/src/app/models/rescale.ts
index dfeeb693f5d8b186ddf2e2a0036179c850fe8552..26c79a97bb87c3f91ab4b4c87059615bd690eee4 100644
--- a/src/app/models/rescale.ts
+++ b/src/app/models/rescale.ts
@@ -1,4 +1,3 @@
-
 export class Rescale {
 
   private static isFullscreen: boolean;
@@ -12,14 +11,20 @@ export class Rescale {
   private state = 0;
 
   public static requestFullscreen() {
-    if (Rescale.isFullscreen) {return; }
+    if (Rescale.isFullscreen) {
+      return;
+    }
     Rescale.isFullscreen = true;
     document.body.requestFullscreen();
   }
 
   public static exitFullscreen() {
-    if (!Rescale.isFullscreen) {return; }
-    if (Rescale.isRescaleFullscreen) {return; }
+    if (!Rescale.isFullscreen) {
+      return;
+    }
+    if (Rescale.isRescaleFullscreen) {
+      return;
+    }
     Rescale.isFullscreen = false;
     document.exitFullscreen();
   }
@@ -52,6 +57,10 @@ export class Rescale {
     this.setScale(this.defaultScale);
   }
 
+  public getInitialScale() {
+    return this.cachedScale;
+  }
+
   public setScale(scale: number) {
     this.scale = scale;
     if (this.scale < 0.1) {
@@ -89,7 +98,7 @@ export class Rescale {
           this.toggleHeader(true);
           this.toggleFooter(true);
         }, 600);
-      break;
+        break;
       case 1:
         Rescale.requestFullscreenByRescale();
         setTimeout(() => {
@@ -99,8 +108,10 @@ export class Rescale {
         setTimeout(() => {
           this.toggleRescaler(true);
         }, 600);
-      break;
-      default: console.error('updateState, this should not happen.'); break;
+        break;
+      default:
+        console.error('updateState, this should not happen.');
+        break;
     }
   }
 
diff --git a/src/app/models/room.ts b/src/app/models/room.ts
index e83d37ce5b7980f6243cc482754bf1876d594211..d90e5be0ea0b2dd4d22898bbba8c2ce21da12e61 100644
--- a/src/app/models/room.ts
+++ b/src/app/models/room.ts
@@ -1,5 +1,3 @@
-import { TSMap } from 'typescript-map';
-
 export class Room {
   id: string;
   revision: string;
@@ -8,11 +6,15 @@ export class Room {
   abbreviation: string;
   name: string;
   description: string;
+  blacklist: string;
   closed: boolean;
   moderated: boolean;
   directSend: boolean;
   threshold: number;
   tags: string[];
+  questionsBlocked: boolean;
+  profanityFilter: ProfanityFilter;
+  blacklistIsActive: boolean;
 
   constructor(
     ownerId: string = '',
@@ -20,11 +22,15 @@ export class Room {
     abbreviation: string = '',
     name: string = '',
     description: string = '',
+    blacklist: string = '[]',
     closed: boolean = false,
     moderated: boolean = true,
     directSend: boolean = true,
     threshold: number = null,
     tags: string[] = [],
+    questionsBlocked: boolean = false,
+    profanityFilter: ProfanityFilter = ProfanityFilter.none,
+    blacklistIsActive: boolean = true
   ) {
     this.id = '';
     this.ownerId = ownerId;
@@ -32,10 +38,22 @@ export class Room {
     this.abbreviation = abbreviation;
     this.name = name;
     this.description = description;
+    this.blacklist = blacklist;
     this.closed = closed;
     this.moderated = moderated;
     this.directSend = directSend;
     this.threshold = threshold;
     this.tags = tags;
+    this.questionsBlocked = questionsBlocked;
+    this.profanityFilter = profanityFilter;
+    this.blacklistIsActive = blacklistIsActive;
   }
 }
+
+export enum ProfanityFilter {
+  all = 'ALL',
+  languageSpecific = 'LANGUAGE_SPECIFIC',
+  partialWords = 'PARTIAL_WORDS',
+  none = 'NONE',
+  deactivated = 'DEACTIVATED'
+}
diff --git a/src/app/services/http/active-user.service.spec.ts b/src/app/services/http/active-user.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fa6f6588c45e4129ffad9e9ffc8fb04b4836988e
--- /dev/null
+++ b/src/app/services/http/active-user.service.spec.ts
@@ -0,0 +1,16 @@
+// import { TestBed } from '@angular/core/testing';
+//
+// import { ActiveUserService } from './active-user.service';
+//
+// describe('ActiveUserService', () => {
+//   let service: ActiveUserService;
+//
+//   beforeEach(() => {
+//     TestBed.configureTestingModule({});
+//     service = TestBed.inject(ActiveUserService);
+//   });
+//
+//   it('should be created', () => {
+//     expect(service).toBeTruthy();
+//   });
+// });
diff --git a/src/app/services/http/active-user.service.ts b/src/app/services/http/active-user.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..672412e0a5a17ea9f06ecf3b172f4af93c6b0d66
--- /dev/null
+++ b/src/app/services/http/active-user.service.ts
@@ -0,0 +1,43 @@
+import { Injectable } from '@angular/core';
+import {Observable} from 'rxjs';
+import {Room} from '../../models/room';
+import {catchError,tap} from 'rxjs/operators';
+import {BaseHttpService} from './base-http.service';
+import {HttpClient,HttpHeaders} from '@angular/common/http';
+import {HeaderService} from '../util/header.service';
+
+const httpOptions = {
+  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
+};
+
+@Injectable({
+  providedIn: 'root'
+})
+export class ActiveUserService extends BaseHttpService {
+
+  constructor(private http: HttpClient) {
+    super();
+  }
+
+  public getActiveUser(room: Room): Observable<any>{
+    const url = '/api/roomsubscription/usercount?ids='+room.id;
+    return this.http.get(url, httpOptions).pipe(
+      tap(_ => ''),
+      catchError(this.handleError<any>('yeet'))
+    );
+  }
+
+  public observeUserActivity(room: Room,a: (num: number) => void): () => void{
+    const f=()=>{
+      this.getActiveUser(room).subscribe(e=>{
+        if(e&&e.length>0){
+          a(e[0]);
+        }
+      });
+    };
+    f();
+    const interval=setInterval(()=>f(),5000);
+    return ()=>clearInterval(interval);
+  }
+
+}
diff --git a/src/app/services/http/base-http.service.ts b/src/app/services/http/base-http.service.ts
index 9bb0703a3cb527b6401af73f63262fe91cc1a9dc..6da60736a0b3cadf74868321c75e9afc58a24647 100644
--- a/src/app/services/http/base-http.service.ts
+++ b/src/app/services/http/base-http.service.ts
@@ -1,16 +1,29 @@
 import { Injectable } from '@angular/core';
-import { of ,  Observable, throwError } from 'rxjs';
+import { Observable, throwError, TimeoutError } from 'rxjs';
 
 @Injectable()
 export class BaseHttpService {
 
+  private nextRequest = 0;
+
   constructor() {
   }
 
   public handleError<T>(operation = 'operation', result?: T) {
     return (error: any): Observable<T> => {
+      if (error instanceof TimeoutError) {
+        this.nextRequest = new Date().getTime() + 1_000;
+      }
       console.error(error);
       return throwError(error);
     };
   }
+
+  protected checkCanSendRequest(operation = 'operation'): Observable<any> {
+    if (new Date().getTime() < this.nextRequest) {
+      console.error(operation + ' is in timeout');
+      return throwError(new TimeoutError());
+    }
+    return null;
+  }
 }
diff --git a/src/app/services/http/comment.service.ts b/src/app/services/http/comment.service.ts
index ef2533769c7ebeb2b64e86254d678fbb804821e6..4befb9e3b9c3e04ce3cee7fa88f54f29484e8394 100644
--- a/src/app/services/http/comment.service.ts
+++ b/src/app/services/http/comment.service.ts
@@ -6,8 +6,10 @@ import { catchError, tap, map } from 'rxjs/operators';
 import { BaseHttpService } from './base-http.service';
 import { TSMap } from 'typescript-map';
 import { Vote } from '../../models/vote';
+import { CommentFilter } from '../../utils/filter-options';
 
 const httpOptions = {
+  // eslint-disable-next-line @typescript-eslint/naming-convention
   headers: new HttpHeaders({ 'Content-Type': 'application/json' })
 };
 
@@ -71,7 +73,7 @@ export class CommentService extends BaseHttpService {
   getComment(commentId: string): Observable<Comment> {
     const connectionUrl = `${this.apiUrl.base}${this.apiUrl.comment}/${commentId}`;
     return this.http.get<Comment>(connectionUrl, httpOptions).pipe(
-      map(comment => this.parseUserNumber(comment)),
+      map(comment => this.parseComment(comment)),
       tap(_ => ''),
       catchError(this.handleError<Comment>('getComment'))
     );
@@ -82,11 +84,14 @@ export class CommentService extends BaseHttpService {
     return this.http.post<Comment>(connectionUrl,
       {
         roomId: comment.roomId, body: comment.body,
-        read: comment.read, creationTimestamp: comment.timestamp, tag: comment.tag, keywords: comment.keywords
+        read: comment.read, creationTimestamp: comment.timestamp, tag: comment.tag,
+        keywordsFromSpacy: JSON.stringify(comment.keywordsFromSpacy),
+        keywordsFromQuestioner: JSON.stringify(comment.keywordsFromQuestioner),
+        language: comment.language
       }, httpOptions).pipe(
-        tap(_ => ''),
-        catchError(this.handleError<Comment>('addComment'))
-      );
+      tap(_ => ''),
+      catchError(this.handleError<Comment>('addComment'))
+    );
   }
 
   deleteComment(commentId: string): Observable<Comment> {
@@ -97,110 +102,13 @@ export class CommentService extends BaseHttpService {
     );
   }
 
-
-  filter(com : Comment) : boolean {
-    /* Get Filter Options */
-    const currentFilters = JSON.parse(localStorage.getItem('currentFilters'));
-    const period = JSON.parse(localStorage.getItem('currentPeriod'));
-    const timestamp = JSON.parse(localStorage.getItem('currentFromNowTimestamp')); 
-
-    /* Filter by Period */
-    const currentTime = new Date();
-    const hourInSeconds = 3600000;
-    let periodInSeconds;
-
-    enum Period {
-      FROMNOW    = 'from-now',
-      ONEHOUR    = 'time-1h',
-      THREEHOURS = 'time-3h',
-      ONEDAY     = 'time-1d',
-      ONEWEEK    = 'time-1w',
-      TWOWEEKS   = 'time-2w',
-      ALL        = 'time-all'
-    }
-
-    if (period !== Period.ALL) {
-      switch (period) {
-        case Period.FROMNOW:
-          break;
-        case Period.ONEHOUR:
-          periodInSeconds = hourInSeconds;
-          break;
-        case Period.THREEHOURS:
-          periodInSeconds = hourInSeconds * 2;
-          break;
-        case Period.ONEDAY:
-          periodInSeconds = hourInSeconds * 24;
-          break;
-        case Period.ONEWEEK:
-          periodInSeconds = hourInSeconds * 168;
-          break;
-        case Period.TWOWEEKS:
-          periodInSeconds = hourInSeconds * 336;
-          break;
-      }
-    }
-
-    const commentTime = new Date(com.timestamp).getTime();
-    const refTime = (period === Period.FROMNOW ? timestamp : (currentTime.getTime() - periodInSeconds));
-    
-    if (commentTime < refTime) {
-      return false;
-    }
-
-    /* Other Filters */
-    const read = 'read';
-    const unread = 'unread';
-    const favorite = 'favorite';
-    const correct = 'correct';
-    const wrong = 'wrong';
-    const bookmark = 'bookmark';
-    const answer = 'answer';
-    const unanswered = 'unanswered';
-
-    enum CorrectWrong {
-      NULL,
-      CORRECT,
-      WRONG
-    }
-    
-    if (currentFilters != '') {  // no filters => return true
-      switch (currentFilters) {
-        case correct:
-          return com.correct === CorrectWrong.CORRECT ? true : false;
-        case wrong:
-          return com.correct === CorrectWrong.WRONG ? true : false;
-        case favorite:
-          return com.favorite;
-        case bookmark:
-          return com.bookmark;
-        case read:
-          return com.read;
-        case unread:
-          return !com.read;
-        case answer:
-          return com.answer != "";
-        case unanswered:
-          return !com.answer;
-      }
-    }
-
-    return true;
-  }
-
-  getFilteredComments(roomId: string) : Observable<Comment[]> {
-    return this.getAckComments(roomId).pipe(map(commentList => commentList.filter(comment => this.filter(comment))));
-  }
-
   getAckComments(roomId: string): Observable<Comment[]> {
     const connectionUrl = this.apiUrl.base + this.apiUrl.comment + this.apiUrl.find;
     return this.http.post<Comment[]>(connectionUrl, {
-      properties: { roomId: roomId, ack: true },
+      properties: { roomId, ack: true },
       externalFilters: {}
     }, httpOptions).pipe(
-      map(commentList => {
-        return commentList.map(comment => this.parseUserNumber(comment));
-      }),
+      map(commentList => commentList.map(comment => this.parseComment(comment))),
       tap(_ => ''),
       catchError(this.handleError<Comment[]>('getComments', []))
     );
@@ -209,12 +117,10 @@ export class CommentService extends BaseHttpService {
   getRejectedComments(roomId: string): Observable<Comment[]> {
     const connectionUrl = this.apiUrl.base + this.apiUrl.comment + this.apiUrl.find;
     return this.http.post<Comment[]>(connectionUrl, {
-      properties: { roomId: roomId, ack: false },
+      properties: { roomId, ack: false },
       externalFilters: {}
     }, httpOptions).pipe(
-      map(commentList => {
-        return commentList.map(comment => this.parseUserNumber(comment));
-      }),
+      map(commentList => commentList.map(comment => this.parseComment(comment))),
       tap(_ => ''),
       catchError(this.handleError<Comment[]>('getComments', []))
     );
@@ -223,12 +129,10 @@ export class CommentService extends BaseHttpService {
   getComments(roomId: string): Observable<Comment[]> {
     const connectionUrl = this.apiUrl.base + this.apiUrl.comment + this.apiUrl.find;
     return this.http.post<Comment[]>(connectionUrl, {
-      properties: { roomId: roomId },
+      properties: { roomId },
       externalFilters: {}
     }, httpOptions).pipe(
-      map(commentList => {
-        return commentList.map(comment => this.parseUserNumber(comment));
-      }),
+      map(commentList => commentList.map(comment => this.parseComment(comment))),
       tap(_ => ''),
       catchError(this.handleError<Comment[]>('getComments', []))
     );
@@ -245,6 +149,7 @@ export class CommentService extends BaseHttpService {
   patchComment(comment: Comment, changes: TSMap<string, any>) {
     const connectionUrl = this.apiUrl.base + this.apiUrl.comment + '/' + comment.id;
     return this.http.patch(connectionUrl, changes, httpOptions).pipe(
+      map(c => this.parseComment(c as Comment)),
       tap(_ => ''),
       catchError(this.handleError<any>('patchComment'))
     );
@@ -266,6 +171,14 @@ export class CommentService extends BaseHttpService {
     );
   }
 
+  role(comment: Comment) {
+    const connectionUrl = this.apiUrl.comment + '/' + comment.id + '/role';
+    return this.http.patch(connectionUrl, httpOptions).pipe(
+      tap(_ => ''),
+      catchError(this.handleError<any>('roleComment'))
+    );
+  }
+
   deleteCommentsByRoomId(roomId: string): Observable<Comment> {
     const connectionUrl = `${this.apiUrl.base + this.apiUrl.comment}/byRoom?roomId=${roomId}`;
     return this.http.delete<Comment>(connectionUrl, httpOptions).pipe(
@@ -277,7 +190,7 @@ export class CommentService extends BaseHttpService {
   countByRoomId(roomId: string, ack: boolean): Observable<number> {
     const connectionUrl = this.apiUrl.base + this.apiUrl.comment + this.apiUrl.find + this.apiUrl.count;
     return this.http.post<number>(connectionUrl, {
-      properties: { roomId: roomId, ack: ack },
+      properties: { roomId, ack },
       externalFilters: {}
     }, httpOptions).pipe(
       tap(_ => ''),
@@ -314,8 +227,15 @@ export class CommentService extends BaseHttpService {
   }
 
 
-  parseUserNumber(comment: Comment): Comment {
+  parseComment(comment: Comment): Comment {
+    if (!comment){
+      return;
+    }
     comment.userNumber = this.hashCode(comment.creatorId);
+    comment.keywordsFromQuestioner = comment.keywordsFromQuestioner ?
+                                     JSON.parse(comment.keywordsFromQuestioner as unknown as string) : null;
+    comment.keywordsFromSpacy = comment.keywordsFromSpacy ? JSON.parse(comment.keywordsFromSpacy as unknown as string) : null;
+    console.log(comment);
     return comment;
   }
 
diff --git a/src/app/services/http/languagetool.service.spec.ts b/src/app/services/http/languagetool.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5f342cc3b200e8cc616aba1f15fe3e73079b8aa8
--- /dev/null
+++ b/src/app/services/http/languagetool.service.spec.ts
@@ -0,0 +1,17 @@
+/*import { TestBed } from '@angular/core/testing';
+
+import { LanguagetoolService } from './languagetool.service';
+
+describe('LanguagetoolService', () => {
+  let service: LanguagetoolService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(LanguagetoolService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
+*/
\ No newline at end of file
diff --git a/src/app/services/http/languagetool.service.ts b/src/app/services/http/languagetool.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b2258ccebdc80bd3ed2f583bea458b3b68394be4
--- /dev/null
+++ b/src/app/services/http/languagetool.service.ts
@@ -0,0 +1,131 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http';
+import { BaseHttpService } from './base-http.service';
+import { catchError, tap, timeout } from 'rxjs/operators';
+import { Observable } from 'rxjs';
+import { CURRENT_SUPPORTED_LANGUAGES, Model } from './spacy.interface';
+
+export type Language = 'de' | 'de-AT' | 'de-CH' | 'de-DE' |
+  'en' | 'en-AU' | 'en-CA' | 'en-GB' | 'en-US' |
+  'fr' |
+  'es' |
+  'it' |
+  'nl' | 'nl-BE' |
+  'pt' | 'pt-BR' | 'pt-PT' |
+  'auto';
+
+export interface LanguagetoolResult {
+  software: {
+    name: string;
+    version: string;
+    buildDate: string;
+    apiVersion: number;
+    status?: string;
+    premium?: boolean;
+    premiumHint?: string;
+  };
+  language: {
+    name: string;
+    code: string;
+    detectedLanguage: {
+      name: string;
+      code: string;
+      confidence?: number;
+    };
+  };
+  matches: {
+    message: string;
+    shortMessage?: string;
+    offset: number;
+    length: number;
+    replacements: {
+      value?: string;
+    }[];
+    context: {
+      text: string;
+      offset: number;
+      length: number;
+    };
+    sentence: string;
+    rule?: {
+      id: string;
+      subId?: string;
+      description: string;
+      urls?: {
+        value?: string;
+      }[];
+      issueType?: string;
+      category: {
+        id?: string;
+        name?: string;
+      };
+    };
+    contextForSureMatch?: number;
+    ignoreForIncompleteSentence?: boolean;
+    type?: {
+      typeName?: string;
+    };
+  }[];
+  warnings?: {
+    incompleteResults?: boolean;
+  };
+}
+
+@Injectable({
+  providedIn: 'root'
+})
+export class LanguagetoolService extends BaseHttpService {
+
+  constructor(private http: HttpClient) {
+    super();
+  }
+
+  mapLanguageToSpacyModel(language: Language): Model {
+    switch (language) {
+      case 'de':
+      case 'de-AT':
+      case 'de-CH':
+      case 'de-DE':
+        return 'de';
+      case 'en':
+      case 'en-AU':
+      case 'en-CA':
+      case 'en-GB':
+      case 'en-US':
+        return 'en';
+      case 'es':
+        return 'es';
+      case 'fr':
+        return 'fr';
+      case 'it':
+        return 'it';
+      case 'nl':
+      case 'nl-BE':
+        return 'nl';
+      case 'pt':
+      case 'pt-BR':
+      case 'pt-PT':
+        return 'pt';
+      default:
+        return 'auto';
+    }
+  }
+
+  isSupportedLanguage(language: Language) {
+    return CURRENT_SUPPORTED_LANGUAGES.includes(this.mapLanguageToSpacyModel(language));
+  }
+
+  checkSpellings(text: string, language: Language): Observable<LanguagetoolResult> {
+    const url = '/languagetool';
+    return this.checkCanSendRequest('checkSpellings') || this.http
+      .get<LanguagetoolResult>(url, {
+        params: {
+          text, language
+        }
+      }).pipe(
+        tap(_ => ''),
+        timeout(5000),
+        catchError(this.handleError<any>('checkSpellings'))
+      );
+  }
+}
diff --git a/src/app/services/http/room.service.ts b/src/app/services/http/room.service.ts
index fab200a216f1002d549c507efd42cc74c6b85201..2486280dd3dcb657c16b3bd3b37c83a1dbbf8b95 100644
--- a/src/app/services/http/room.service.ts
+++ b/src/app/services/http/room.service.ts
@@ -1,15 +1,15 @@
 import { Injectable } from '@angular/core';
 import { Room } from '../../models/room';
-import { RoomJoined } from '../../models/events/room-joined';
-import { RoomCreated } from '../../models/events/room-created';
 import { UserRole } from '../../models/user-roles.enum';
 import { HttpClient, HttpHeaders } from '@angular/common/http';
-import { Observable } from 'rxjs';
-import { catchError, tap, map } from 'rxjs/operators';
+import { Observable, throwError } from 'rxjs';
+import { catchError, tap } from 'rxjs/operators';
 import { AuthenticationService } from './authentication.service';
 import { BaseHttpService } from './base-http.service';
 import { EventService } from '../util/event.service';
-import { TSMap } from 'typescript-map';
+import { NotificationService } from '../util/notification.service';
+import { Router } from '@angular/router';
+import { TranslateService } from '@ngx-translate/core';
 
 const httpOptions = {
   headers: new HttpHeaders({})
@@ -28,7 +28,10 @@ export class RoomService extends BaseHttpService {
   constructor(
     private http: HttpClient,
     private eventService: EventService,
-    private authService: AuthenticationService
+    private authService: AuthenticationService,
+    private translateService: TranslateService,
+    private notificationService: NotificationService,
+    private router: Router
   ) {
     super();
   }
@@ -36,7 +39,7 @@ export class RoomService extends BaseHttpService {
   getCreatorRooms(): Observable<Room[]> {
     const connectionUrl = this.apiUrl.base + this.apiUrl.rooms + this.apiUrl.findRooms;
     return this.http.post<Room[]>(connectionUrl, {
-      properties: { ownerId: this.authService.getUser().id },
+      properties: {ownerId: this.authService.getUser().id},
       externalFilters: {}
     }).pipe(
       tap((rooms) => {
@@ -52,7 +55,7 @@ export class RoomService extends BaseHttpService {
     const connectionUrl = this.apiUrl.base + this.apiUrl.rooms + this.apiUrl.findRooms;
     return this.http.post<Room[]>(connectionUrl, {
       properties: {},
-      externalFilters: { inHistoryOfUserId: this.authService.getUser().id }
+      externalFilters: {inHistoryOfUserId: this.authService.getUser().id}
     }).pipe(
       tap((rooms) => {
         for (const r of rooms) {
@@ -63,7 +66,7 @@ export class RoomService extends BaseHttpService {
     );
   }
 
-  addRoom(room: Room, exc?: () => void ): Observable<Room> {
+  addRoom(room: Room, exc?: () => void): Observable<Room> {
     delete room.id;
     delete room.revision;
     const connectionUrl = this.apiUrl.base + this.apiUrl.rooms + '/';
@@ -76,29 +79,29 @@ export class RoomService extends BaseHttpService {
         if (exc) {
           exc();
         }
-        return this.handleError<Room>(`add Room ${room}`);
+        return this.handleError<Room>(`add Room ${ room }`);
       })
     );
   }
 
   getRoom(id: string): Observable<Room> {
-    const connectionUrl = `${ this.apiUrl.base +  this.apiUrl.rooms }/${ id }`;
+    const connectionUrl = `${ this.apiUrl.base + this.apiUrl.rooms }/${ id }`;
     return this.http.get<Room>(connectionUrl).pipe(
       tap(room => this.setRoomId(room)),
-      catchError(this.handleError<Room>(`getRoom keyword=${ id }`))
+      catchError(this.handleRoomError<Room>(`getRoom keyword=${ id }`))
     );
   }
 
   getRoomByShortId(shortId: string): Observable<Room> {
-    const connectionUrl = `${ this.apiUrl.base +  this.apiUrl.rooms }/~${ shortId }`;
+    const connectionUrl = `${ this.apiUrl.base + this.apiUrl.rooms }/~${ shortId }`;
     return this.http.get<Room>(connectionUrl).pipe(
       tap(room => this.setRoomId(room)),
-      catchError(this.handleError<Room>(`getRoom shortId=${ shortId }`))
+      catchError(this.handleRoomError<Room>(`getRoom shortId=${ shortId }`))
     );
   }
 
-  getErrorHandledRoomByShortId(shortId: string, err: () => void ): Observable<Room> {
-    const connectionUrl = `${ this.apiUrl.base +  this.apiUrl.rooms }/~${ shortId }`;
+  getErrorHandledRoomByShortId(shortId: string, err: () => void): Observable<Room> {
+    const connectionUrl = `${ this.apiUrl.base + this.apiUrl.rooms }/~${ shortId }`;
     return this.http.get<Room>(connectionUrl).pipe(
       tap(room => this.setRoomId(room)),
       catchError(() => {
@@ -110,11 +113,11 @@ export class RoomService extends BaseHttpService {
 
   addToHistory(roomId: string): void {
     const connectionUrl = `${ this.apiUrl.base + this.apiUrl.user }/${ this.authService.getUser().id }/roomHistory`;
-    this.http.post(connectionUrl, { roomId: roomId, lastVisit: this.joinDate.getTime() }, httpOptions).subscribe(() => {});
+    this.http.post(connectionUrl, {roomId, lastVisit: this.joinDate.getTime()}, httpOptions).subscribe();
   }
 
   removeFromHistory(roomId: string): Observable<Room> {
-    const connectionUrl = `${ this.apiUrl.base + this.apiUrl.user }/${ this.authService.getUser().id }/roomHistory/${roomId}`;
+    const connectionUrl = `${ this.apiUrl.base + this.apiUrl.user }/${ this.authService.getUser().id }/roomHistory/${ roomId }`;
     return this.http.delete<Room>(connectionUrl, httpOptions).pipe(
       tap(() => ''),
       catchError(this.handleError<Room>('deleteRoom'))
@@ -123,7 +126,7 @@ export class RoomService extends BaseHttpService {
 
   updateRoom(updatedRoom: Room): Observable<Room> {
     const connectionUrl = `${ this.apiUrl.base + this.apiUrl.rooms }/~${ updatedRoom.shortId }`;
-    return this.http.put(connectionUrl, updatedRoom , httpOptions).pipe(
+    return this.http.put(connectionUrl, updatedRoom, httpOptions).pipe(
       tap(() => ''),
       catchError(this.handleError<any>('updateRoom'))
     );
@@ -140,4 +143,17 @@ export class RoomService extends BaseHttpService {
   setRoomId(room: Room): void {
     localStorage.setItem('roomId', room.id);
   }
+
+  handleRoomError<T>(operation = 'operation', result?: T) {
+    return (error: any): Observable<T> => {
+      console.error(error);
+      if (error.status === 404) {
+        this.translateService.get('room-list.room-not-exist').subscribe(msg => {
+          this.notificationService.show(msg);
+          this.router.navigateByUrl('');
+        });
+      }
+      return throwError(error);
+    };
+  }
 }
diff --git a/src/app/services/http/spacy.interface.ts b/src/app/services/http/spacy.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..406a9beb75ba3b96ebca87578df50c4e2325b0f9
--- /dev/null
+++ b/src/app/services/http/spacy.interface.ts
@@ -0,0 +1,142 @@
+export type Model = 'de' | 'en' | 'fr' | 'es' | 'it' | 'nl' | 'pt' | 'auto';
+
+export type EnglishParserLabels = 'ROOT' | //None
+  'acl' | //clausal modifier of noun (adjectival clause)
+  'acomp' | //adjectival complement
+  'advcl' | //adverbial clause modifier
+  'advmod' | //adverbial modifier
+  'agent' | //agent
+  'amod' | //adjectival modifier
+  'appos' | //appositional modifier
+  'attr' | //attribute
+  'aux' | //auxiliary
+  'auxpass' | //auxiliary (passive)
+  'case' | //case marking
+  'cc' | //coordinating conjunction
+  'ccomp' | //clausal complement
+  'compound' | //compound
+  'conj' | //conjunct
+  'csubj' | //clausal subject
+  'csubjpass' | //clausal subject (passive)
+  'dative' | //dative
+  'dep' | //unclassified dependent
+  'det' | //determiner
+  'dobj' | //direct object
+  'expl' | //expletive
+  'intj' | //interjection
+  'mark' | //marker
+  'meta' | //meta modifier
+  'neg' | //negation modifier
+  'nmod' | //modifier of nominal
+  'npadvmod' | //noun phrase as adverbial modifier
+  'nsubj' | //nominal subject
+  'nsubjpass' | //nominal subject (passive)
+  'nummod' | //numeric modifier
+  'oprd' | //object predicate
+  'parataxis' | //parataxis
+  'pcomp' | //complement of preposition
+  'pobj' | //object of preposition
+  'poss' | //possession modifier
+  'preconj' | //pre-correlative conjunction
+  'predet' | //None
+  'prep' | //prepositional modifier
+  'prt' | //particle
+  'punct' | //punctuation
+  'quantmod' | //modifier of quantifier
+  'relcl' | //relative clause modifier
+  'xcomp'; //open clausal complement
+
+export type GermanParserLabels = 'ROOT' | 'ac' | 'adc' | 'ag' | 'ams' | 'app' | 'avc' | 'cc' | 'cd' | 'cj' | 'cm' |
+  'cp' | 'cvc' | 'da' | 'dep' | 'dm' | 'ep' | 'ju' | 'mnr' | 'mo' | 'ng' | 'nk' | 'nmc' | 'oa' | 'oc' | 'og' | 'op' |
+  'par' | 'pd' | 'pg' | 'ph' | 'pm' | 'pnc' | 'punct' | 'rc' | 're' | 'rs' | 'sb' | 'sbp' | 'svp' | 'uc' | 'vo';
+
+export type FrenchParserLabels = 'ROOT' | //None
+  'acl' | //clausal modifier of noun (adjectival clause)
+  'acl:relcl' | //None
+  'advcl' | //adverbial clause modifier
+  'advmod' | //adverbial modifier
+  'amod' | //adjectival modifier
+  'appos' | //appositional modifier
+  'aux:pass' | //None
+  'aux:tense' | //None
+  'case' | //case marking
+  'cc' | //coordinating conjunction
+  'ccomp' | //clausal complement
+  'conj' | //conjunct
+  'cop' | //copula
+  'dep' | //unclassified dependent
+  'det' | //determiner
+  'expl:comp' | //None
+  'expl:pass' | //None
+  'expl:subj' | //None
+  'fixed' | //fixed multiword expression
+  'flat:foreign' | //None
+  'flat:name' | //None
+  'iobj' | //indirect object
+  'mark' | //marker
+  'nmod' | //modifier of nominal
+  'nsubj' | //nominal subject
+  'nsubj:pass' | //None
+  'nummod' | //numeric modifier
+  'obj' | //object
+  'obl:agent' | //None
+  'obl:arg' | //None
+  'obl:mod' | //None
+  'parataxis' | //parataxis
+  'punct' | //punctuation
+  'vocative' | //vocative
+  'xcomp'; //open clausal complement
+
+export const GERMAN_TRANSLATION = {
+  // eslint-disable-next-line @typescript-eslint/naming-convention
+  ROOT: 'Satzkernelement',
+  ac: 'Adpositionaler Fallmarker',
+  adc: 'Adjektivkomponente',
+  ag: 'Genitivattribut',
+  ams: 'Messargument des Adjektivs',
+  app: 'Apposition',
+  avc: 'Adverbiale Satzkomponente',
+  cc: 'Koordinierende Konjunktion',
+  cd: 'Koordinierende Konjunktion',
+  cj: 'Konjunktion',
+  cm: 'Vergleichende Konjunktion',
+  cp: 'Komplementierer',
+  cvc: 'Kollokative Verbkonstruktion',
+  da: 'Dativ',
+  dep: 'Nicht klassifizierte Abhängigkeit',
+  dm: 'Diskursmarker',
+  ep: 'Kraftausdruck es',
+  ju: 'Verbindungsstelle',
+  mnr: 'Postnominaler Modifikator',
+  mo: 'Modifikator',
+  ng: 'Negation',
+  nk: 'Nomen Kernelement',
+  nmc: 'Numerische Komponente',
+  oa: 'Akkusativobjekt',
+  oc: 'Klauselobjekt',
+  og: 'Genitivobjekt',
+  op: 'Präpositionalobjekt',
+  par: 'Klammerelement',
+  pd: 'Prädikat',
+  pg: 'Genitiv',
+  ph: 'Platzhalter',
+  pm: 'Morphologisches Teilchen',
+  pnc: 'Eigenname Komponente',
+  punct: 'Zeichensetzung',
+  rc: 'Relativsatz',
+  re: 'Wiederholtes Element',
+  rs: 'Indirekte Rede',
+  sb: 'Subjekt',
+  sbp: 'Passiviertes Subject',
+  svp: 'Trennbares Verbpräfix',
+  uc: 'Einheitskomponente',
+  vo: 'Vokativ',
+};
+
+export const DEFAULT_NOUN_LABELS = {
+  de: ['sb', 'op', 'og', 'da', 'oa'] as GermanParserLabels[],
+  en: [] as EnglishParserLabels[],
+  fr: [] as FrenchParserLabels[],
+};
+
+export const CURRENT_SUPPORTED_LANGUAGES: Model[] = ['de', 'en', 'fr'];
diff --git a/src/app/services/http/spacy.service.ts b/src/app/services/http/spacy.service.ts
index 11625da1fe470bbe316e3a1f5498facf1f1cac10..7b2d776aec96ed8923fbd3ea8f40852106dd050f 100644
--- a/src/app/services/http/spacy.service.ts
+++ b/src/app/services/http/spacy.service.ts
@@ -2,64 +2,37 @@ import { Injectable } from '@angular/core';
 import { HttpClient, HttpHeaders } from '@angular/common/http';
 import { Observable } from 'rxjs';
 import { BaseHttpService } from './base-http.service';
-import { catchError } from 'rxjs/operators';
+import { catchError, map, tap, timeout } from 'rxjs/operators';
+import { CreateCommentKeywords } from '../../utils/create-comment-keywords';
+import { DEFAULT_NOUN_LABELS, Model } from './spacy.interface';
 
-export class Result {
-  arcs: Arc[];
-  words: Word[];
-
-  constructor(
-    arcs: Arc[] = [],
-    words: Word[] = []
-  ) {
-    this.arcs = arcs;
-    this.words = words;
-  }
-
-  static empty(): Result {
-    return new Result();
-  }
+export interface SpacyKeyword {
+  lemma: string;
+  dep: string[];
 }
 
-export class Word {
-  tag: string;
-  text: string;
-
-  constructor(
-    tag: string,
-    text: string
-  ) {
-    this.tag = tag;
-    this.text = text;
-  }
-}
+type KeywordType = 'entity' | 'noun';
 
-export class Arc {
-  dir: string;
-  end: number;
-  label: string;
-  start: number;
+interface NounKeyword {
+  type: KeywordType;
+  lemma: string;
   text: string;
+  dep: string;
+  tag: string;
+  pos: string;
+}
 
-  constructor(
-    dir: string,
-    end: number,
-    label: string,
-    start: number,
-    text: string,
-  ) {
-    this.dir = dir;
-    this.end = end;
-    this.label = label;
-    this.start = start;
-    this.text = text;
-  }
-
+interface EntityKeyword extends NounKeyword {
+  entityType: string;
 }
 
+type AbstractKeyword = NounKeyword | EntityKeyword;
+
+type KeywordList = AbstractKeyword[];
 
 const httpOptions = {
-  headers: new HttpHeaders({'Content-Type': 'application/json'})
+  // eslint-disable-next-line @typescript-eslint/naming-convention
+  headers: new HttpHeaders({ 'Content-Type': 'application/json' })
 };
 
 @Injectable({
@@ -71,11 +44,37 @@ export class SpacyService extends BaseHttpService {
     super();
   }
 
-  analyse(text: string, model: string): Observable<Result> {
+  static getLabelsForModel(model: Model): string[] {
+    return DEFAULT_NOUN_LABELS[model];
+  }
+
+  getKeywords(text: string, model: Model): Observable<SpacyKeyword[]> {
     const url = '/spacy';
-    return this.http.post<Result>(url, {text, model}, httpOptions)
+    return this.checkCanSendRequest('getKeywords') || this.http
+      .post<KeywordList>(url, { text, model }, httpOptions)
       .pipe(
-        catchError(this.handleError<any>('analyse'))
+        tap(_ => ''),
+        timeout(500),
+        catchError(this.handleError<any>('getKeywords')),
+        map((elem: KeywordList) => {
+          const keywordsMap = new Map<string, { lemma: string; dep: Set<string> }>();
+          elem.forEach(e => {
+            const keyword = e.lemma.trim();
+            if (!CreateCommentKeywords.isKeywordAcceptable(keyword)) {
+              return;
+            }
+            let keywordObj = keywordsMap.get(keyword);
+            if (!keywordObj) {
+              keywordObj = {
+                lemma: keyword,
+                dep: new Set<string>()
+              };
+              keywordsMap.set(keyword, keywordObj);
+            }
+            keywordObj.dep.add(e.dep);
+          });
+          return [...keywordsMap.values()].map(e => ({ lemma: e.lemma, dep: [...e.dep] }));
+        })
       );
   }
 }
diff --git a/src/app/services/util/custom-icon.service.ts b/src/app/services/util/custom-icon.service.ts
index 4183d9e8f9ece9f6d5f258a063255af2f2c6c416..b66cc7777ed1d8d6b944e7880fbfe438c5181dff 100644
--- a/src/app/services/util/custom-icon.service.ts
+++ b/src/app/services/util/custom-icon.service.ts
@@ -9,6 +9,7 @@ export class CustomIconService {
     'beamer',
     'meeting_room',
     'comment_tag',
+    'hashtag',
     'qrcode'
   ];
 
diff --git a/src/app/services/util/header.service.spec.ts b/src/app/services/util/header.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a3ba719c26cee0d3287bc9d08536759dd2794132
--- /dev/null
+++ b/src/app/services/util/header.service.spec.ts
@@ -0,0 +1,16 @@
+// import { TestBed } from '@angular/core/testing';
+//
+// import { HeaderService } from './header.service';
+//
+// describe('HeaderService', () => {
+//   let service: HeaderService;
+//
+//   beforeEach(() => {
+//     TestBed.configureTestingModule({});
+//     service = TestBed.inject(HeaderService);
+//   });
+//
+//   it('should be created', () => {
+//     expect(service).toBeTruthy();
+//   });
+// });
diff --git a/src/app/services/util/header.service.ts b/src/app/services/util/header.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6dca0ebe44b103c60c1173e5a39731e96bd4c613
--- /dev/null
+++ b/src/app/services/util/header.service.ts
@@ -0,0 +1,40 @@
+import {Injectable} from '@angular/core';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class HeaderService {
+
+  private userActivity:number;
+  private userActivityListener:((v:number)=>void)[]=[];
+  private userActivityToggle:boolean;
+  private userActivityToggleListener:((v:boolean)=>void)[]=[];
+
+
+  constructor() {}
+
+  public setCurrentUserActivity(e:number){
+    if(this.userActivity!=e){
+      this.userActivity=e;
+      if(this.userActivityToggle){
+        this.userActivityListener.forEach(f=>f(this.userActivity));
+      }
+    }
+  }
+
+  public toggleCurrentUserActivity(e:boolean){
+    if(this.userActivityToggle!=e){
+      this.userActivityToggle=e;
+      this.userActivityToggleListener.forEach(f=>f(this.userActivityToggle));
+    }
+  }
+
+  public onUserChange(f:(v:number)=>void){
+    this.userActivityListener.push(f);
+  }
+
+  public onActivityChange(f:(v:boolean)=>void){
+    this.userActivityToggleListener.push(f);
+  }
+
+}
diff --git a/src/app/services/util/onboarding.service.spec.ts b/src/app/services/util/onboarding.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6a47b206e23a9b2057836da8e70aa751f8caf256
--- /dev/null
+++ b/src/app/services/util/onboarding.service.spec.ts
@@ -0,0 +1,17 @@
+/*import { TestBed } from '@angular/core/testing';
+
+import { OnboardingService } from './onboarding.service';
+
+describe('OnboardingService', () => {
+  let service: OnboardingService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(OnboardingService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
+ */
diff --git a/src/app/services/util/onboarding.service.ts b/src/app/services/util/onboarding.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d884ebffe67445438de131a3d7ead6e85c7e03e5
--- /dev/null
+++ b/src/app/services/util/onboarding.service.ts
@@ -0,0 +1,220 @@
+import { Injectable } from '@angular/core';
+import { JoyrideService } from 'ngx-joyride';
+import { AppComponent } from '../../app.component';
+import { EventService } from './event.service';
+import { AuthenticationService } from '../http/authentication.service';
+import { Router } from '@angular/router';
+import { DataStoreService } from './data-store.service';
+import { Observable, Subscription } from 'rxjs';
+import { initDefaultTour, OnboardingTour, OnboardingTourStepInteraction } from './onboarding.tours';
+import { JoyrideStepInfo } from 'ngx-joyride/lib/models/joyride-step-info.class';
+import { NotificationService } from './notification.service';
+import { RoomService } from '../http/room.service';
+import { TranslateService } from '@ngx-translate/core';
+import { LanguageService } from './language.service';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class OnboardingService {
+
+  private _activeTour: OnboardingTour;
+  private _eventServiceSubscription: Subscription;
+  private _tourSubscription: Subscription;
+  private _currentStep: number;
+
+  constructor(private joyrideService: JoyrideService,
+              private eventService: EventService,
+              private dataStoreService: DataStoreService,
+              private authenticationService: AuthenticationService,
+              private router: Router,
+              private notificationService: NotificationService,
+              private roomService: RoomService,
+              private translateService: TranslateService,
+              private langService: LanguageService) {
+    this.langService.langEmitter.subscribe(lang => {
+      this.translateService.use(lang);
+    });
+    this.translateService.use(localStorage.getItem('currentLang'));
+  }
+
+  startDefaultTour(ignoreDone = false): boolean {
+    return this.startOnboardingTour(
+      initDefaultTour(this.authenticationService, this.dataStoreService, this.router, this.roomService), ignoreDone);
+  }
+
+  doStep(stepDirection: number): boolean {
+    if (!this._activeTour) {
+      return false;
+    }
+    const previous = this._activeTour.tour[this._currentStep - 1].split('@');
+    const current = this._activeTour.tour[this._currentStep - 1 + stepDirection].split('@');
+    if (this._activeTour.tourActions) {
+      const prevObj = this._activeTour.tourActions[previous[0]];
+      const currentObj = this._activeTour.tourActions[current[0]];
+      if (prevObj && prevObj.beforeUnload) {
+        prevObj.beforeUnload(stepDirection === 1);
+      }
+      if (currentObj && currentObj.beforeLoad) {
+        currentObj.beforeLoad(stepDirection === 1);
+      }
+    }
+    if (previous.length < current.length || previous[1] !== current[1]) {
+      //Route gets switched
+      const name = this._activeTour.name;
+      const routeChecker = this._activeTour.checkIfRouteCanBeAccessed;
+      this.cleanup();
+      this.joyrideService.closeTour();
+      this.dataStoreService.set('onboarding_' + name, JSON.stringify({
+        state: 'running',
+        step: this._currentStep + stepDirection
+      }));
+      this.tryNavigate(name, current[1], routeChecker);
+      return true;
+    }
+    return false;
+  }
+
+  private startOnboardingTour(tour: OnboardingTour, ignoreDone = false): boolean {
+    if (this._activeTour) {
+      this.cleanup();
+      return false;
+    }
+    if (ignoreDone) {
+      this.dataStoreService.remove('onboarding_' + tour.name);
+    }
+    const tourInfo = JSON.parse(this.dataStoreService.get('onboarding_' + tour.name));
+    if (tourInfo && tourInfo.state !== 'running') {
+      return false;
+    }
+    AppComponent.rescale.setDefaultScale(1);
+    this._currentStep = tourInfo && tourInfo.step ? tourInfo.step : 1;
+    const firstStepRoute = tour.tour[this._currentStep - 1].split('@');
+    if (firstStepRoute.length > 1 && !this.router.url.endsWith('/' + firstStepRoute[1])) {
+      this.tryNavigate(tour.name, firstStepRoute[1], tour.checkIfRouteCanBeAccessed);
+      return false;
+    }
+    this._activeTour = tour;
+    if (!tourInfo && this._activeTour.startupAction) {
+      this._activeTour.startupAction();
+    }
+    this.emulateWalkthrough();
+    window.addEventListener('keyup', this._keyUpWrapper);
+    this._tourSubscription = this.joyrideService.startTour({
+      steps: tour.tour,
+      logsEnabled: false,
+      stepDefaultPosition: 'center',
+      startWith: this._activeTour.tour[this._currentStep - 1]
+    }).subscribe(step => this.afterStepMade(step));
+    this._eventServiceSubscription = this.eventService.on<string>('onboarding')
+      .subscribe(action => this.checkTourEnding(action));
+    return true;
+  }
+
+  private afterStepMade(step: JoyrideStepInfo) {
+    AppComponent.rescale.setDefaultScale(1);
+    this.dataStoreService.set('onboarding_' + this._activeTour.name, JSON.stringify({
+      state: 'running',
+      step: step.number
+    }));
+    const container: HTMLElement = document.querySelector('.joyride-step__holder');
+    if (container.style.position === 'fixed') {
+      container.classList.add('center');
+    }
+    if (!this._activeTour.tourActions) {
+      return;
+    }
+    const previous = this._activeTour.tourActions[this._activeTour.tour[this._currentStep - 1].split('@')[0]];
+    const current = this._activeTour.tourActions[step.name];
+    const isNext = this._currentStep < step.number;
+    this._currentStep = step.number;
+    if (previous && previous.afterUnload) {
+      previous.afterUnload(isNext);
+    }
+    if (current && current.afterLoad) {
+      current.afterLoad(isNext);
+    }
+  }
+
+  private tryNavigate(tourName: string, route: string, routeChecker: (string) => Observable<boolean>) {
+    if (routeChecker) {
+      routeChecker(route).subscribe(canAccess => {
+        if (canAccess) {
+          this.router.navigate([route]);
+        } else {
+          this.dataStoreService.set('onboarding_' + tourName, JSON.stringify({ state: 'canceled' }));
+          this.translateService.get('joyride.cantAccessRoute').subscribe(message => {
+            this.notificationService.show(message);
+          });
+        }
+      });
+    } else {
+      this.router.navigate([route]);
+    }
+  }
+
+  private emulateWalkthrough() {
+    if (!this._activeTour.tourActions) {
+      return;
+    }
+    let lastTourObject: OnboardingTourStepInteraction = null;
+    let currentTourObject: OnboardingTourStepInteraction;
+    for (let i = 0; i < this._currentStep; i++) {
+      currentTourObject = this._activeTour.tourActions[this._activeTour.tour[i].split('@')[0]];
+      if (lastTourObject && lastTourObject.beforeUnload) {
+        lastTourObject.beforeUnload(true);
+      }
+      if (currentTourObject && currentTourObject.beforeLoad) {
+        currentTourObject.beforeLoad(true);
+      }
+      if (lastTourObject && lastTourObject.afterUnload) {
+        lastTourObject.afterUnload(true);
+      }
+      if (currentTourObject && currentTourObject.afterLoad) {
+        currentTourObject.afterLoad(true);
+      }
+      lastTourObject = currentTourObject;
+    }
+  }
+
+  private checkTourEnding(action: string) {
+    this.dataStoreService.set('onboarding_' + this._activeTour.name, JSON.stringify({ state: action }));
+    AppComponent.rescale.setDefaultScale(AppComponent.rescale.getInitialScale());
+    if (this._activeTour.doneAction) {
+      this._activeTour.doneAction(action === 'finished');
+    }
+    this.cleanup(true);
+  }
+
+  private cleanup(finished = false) {
+    this._eventServiceSubscription.unsubscribe();
+    this._activeTour = null;
+    if (finished) {
+      this._tourSubscription.unsubscribe();
+      window.removeEventListener('keyup', this._keyUpWrapper);
+    }
+  }
+
+  private _keyUpWrapper = (e: KeyboardEvent) => this.onKeyUp(e);
+
+  private onKeyUp(e: KeyboardEvent) {
+    if (!this._activeTour) {
+      e.stopImmediatePropagation();
+      return;
+    }
+    if (e.key === 'ArrowLeft') {
+      if (this._currentStep < 2 || this.doStep(-1)) {
+        e.stopImmediatePropagation();
+      }
+    } else if (e.key === 'ArrowRight') {
+      if (this._currentStep < this._activeTour.tour.length && this.doStep(1)) {
+        e.stopImmediatePropagation();
+      } else if (this._currentStep === this._activeTour.tour.length) {
+        this.eventService.broadcast('onboarding', 'finished');
+      }
+    } else if (e.key === 'Escape') {
+      e.stopImmediatePropagation();
+      this.joyrideService.closeTour();
+    }
+  }
+}
diff --git a/src/app/services/util/onboarding.tours.ts b/src/app/services/util/onboarding.tours.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a7eb6c49ba2569bee810b2c9994250605d98c23e
--- /dev/null
+++ b/src/app/services/util/onboarding.tours.ts
@@ -0,0 +1,90 @@
+import { AuthenticationService } from '../http/authentication.service';
+import { UserRole } from '../../models/user-roles.enum';
+import { DataStoreService } from './data-store.service';
+import { Router } from '@angular/router';
+import { RoomService } from '../http/room.service';
+import { Observable, of, Subject } from 'rxjs';
+
+export interface OnboardingTourStepInteraction {
+  beforeLoad?: (isNext: boolean) => void;
+  afterLoad?: (isNext: boolean) => void;
+  beforeUnload?: (isNext: boolean) => void;
+  afterUnload?: (isNext: boolean) => void;
+}
+
+export interface OnboardingTourStepInteractionObject {
+  [key: string]: OnboardingTourStepInteraction;
+}
+
+export interface OnboardingTour {
+  name: string;
+  tour: string[];
+  tourActions?: OnboardingTourStepInteractionObject;
+  startupAction?: () => void;
+  doneAction?: (finished: boolean) => void;
+  checkIfRouteCanBeAccessed?: (route: string) => Observable<boolean>;
+}
+
+const roomChecker = (roomService: RoomService, roomUrl: string): Observable<boolean> => {
+  const index = roomUrl.indexOf('room/') + 5;
+  const shortId = roomUrl.substring(index, roomUrl.indexOf('/', index));
+  const sub = new Subject<boolean>();
+  roomService.getRoomByShortId(shortId)
+    .subscribe(room => sub.next(room != null), () => sub.next(false));
+  return sub.asObservable();
+};
+
+export const initDefaultTour = (authenticationService: AuthenticationService,
+                                dataStoreService: DataStoreService,
+                                router: Router,
+                                roomService: RoomService): OnboardingTour => ({
+  name: 'default',
+  tour: [
+    'greeting@home',
+    'loginButtonHeader@home',
+    'roomJoin@home',
+    'createRoom@home',
+    'introduction@home',
+    'feedbackLink@home',
+    'createQuestion@participant/room/Feedback/comments',
+    'voting@participant/room/Feedback/comments',
+    'commentFilter@participant/room/Feedback/comments',
+    'commentUserNumber@participant/room/Feedback/comments',
+    'optionHeader@participant/room/Feedback/comments'
+  ],
+  tourActions: {
+    feedbackLink: {
+      beforeLoad: (isNext: boolean) => {
+        if (isNext && dataStoreService.get('onboarding-default-meta') === 'false' && !authenticationService.isLoggedIn()) {
+          authenticationService.guestLogin(UserRole.PARTICIPANT).subscribe();
+        }
+      },
+      beforeUnload: (isNext: boolean) => {
+        if (!isNext && dataStoreService.get('onboarding-default-meta') === 'false' && authenticationService.isLoggedIn()) {
+          authenticationService.logout();
+        }
+      }
+    },
+    voting: {
+      beforeLoad: () => {
+        document.getElementById('scroll_container').scrollTop = 0;
+      }
+    }
+  },
+  doneAction: (_) => {
+    if (dataStoreService.get('onboarding-default-meta') === 'false') {
+      authenticationService.logout();
+    }
+    dataStoreService.remove('onboarding-default-meta');
+    router.navigate(['/home']);
+  },
+  startupAction: () => {
+    dataStoreService.set('onboarding-default-meta', String(authenticationService.isLoggedIn()));
+  },
+  checkIfRouteCanBeAccessed: (route: string) => {
+    if (route.endsWith('home')) {
+      return of(true);
+    }
+    return roomChecker(roomService, route);
+  }
+});
diff --git a/src/app/services/util/profanity-filter.service.spec.ts b/src/app/services/util/profanity-filter.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eedd82f92a4d343ff20c7590b230f0389f0bde1c
--- /dev/null
+++ b/src/app/services/util/profanity-filter.service.spec.ts
@@ -0,0 +1,17 @@
+/*import { TestBed } from '@angular/core/testing';
+
+import { ProfanityFilterService } from './profanity-filter.service';
+
+describe('ProfanityFilterService', () => {
+  let service: ProfanityFilterService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(ProfanityFilterService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
+*/
diff --git a/src/app/services/util/profanity-filter.service.ts b/src/app/services/util/profanity-filter.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ff6bca02830c6c0ea526ca232e63f0a970136466
--- /dev/null
+++ b/src/app/services/util/profanity-filter.service.ts
@@ -0,0 +1,94 @@
+import { Injectable } from '@angular/core';
+import { Observable, Subject } from 'rxjs';
+import * as BadWords from 'naughty-words';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class ProfanityFilterService {
+
+  private customProfanityWords: Subject<string[]>;
+  private readonly profanityKey = 'custom-Profanity-List';
+  private profanityWords = [];
+
+  constructor() {
+    this.customProfanityWords = new Subject<string[]>();
+    this.profanityWords = BadWords['en']
+      .concat(BadWords['de'])
+      .concat(BadWords['fr'])
+      .concat(BadWords['ar'])
+      .concat(BadWords['ru'])
+      .concat(BadWords['es'])
+      .concat(BadWords['it'])
+      .concat(BadWords['nl'])
+      .concat(BadWords['pt'])
+      .concat(BadWords['tr']);
+  }
+
+  get getProfanityList(): string[] {
+    return this.getProfanityListFromStorage().concat(this.profanityWords);
+  }
+
+  getProfanityListFromStorage() {
+    const list = localStorage.getItem(this.profanityKey);
+    return list ? JSON.parse(list) : [];
+  }
+
+  getCustomProfanityList(): Observable<string[]> {
+    this.customProfanityWords.next(this.getProfanityListFromStorage());
+    return this.customProfanityWords.asObservable();
+  }
+
+  addToProfanityList(word: string) {
+    if (word !== undefined) {
+      const plist = this.getProfanityListFromStorage();
+      if (!plist.includes(word.toLowerCase().trim())) {
+        plist.push(word.toLowerCase().trim());
+        localStorage.setItem(this.profanityKey, JSON.stringify(plist));
+        this.customProfanityWords.next(plist);
+      }
+    }
+  }
+
+  removeFromProfanityList(word: string) {
+    const plist = this.getProfanityListFromStorage();
+    plist.splice(plist.indexOf(word, 0), 1);
+    localStorage.setItem(this.profanityKey, JSON.stringify(plist));
+    this.customProfanityWords.next(plist);
+  }
+
+  removeProfanityList() {
+    localStorage.removeItem(this.profanityKey);
+  }
+
+  filterProfanityWords(str: string, censorPartialWordsCheck: boolean, censorLanguageSpecificCheck: boolean, lang?: string){
+    let filteredString = str;
+    let profWords = [];
+    if (censorLanguageSpecificCheck) {
+      profWords = BadWords[(lang !== 'AUTO' ? lang.toLowerCase() : localStorage.getItem('currentLang'))];
+    } else {
+      profWords = this.profanityWords;
+    }
+    str = str.replace(new RegExp(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi), '');
+    // eslint-disable-next-line max-len
+    const toCensoredString = censorPartialWordsCheck ? str.toLowerCase() : str.toLowerCase().split(/[\s,.]+/);
+    profWords.concat(this.getProfanityListFromStorage()).forEach(word => {
+      if (toCensoredString.includes(word)) {
+        filteredString = this.replaceString(filteredString, word, this.generateCensoredWord(word.length));
+      }
+    });
+    return filteredString;
+  }
+
+  private replaceString(str: string, search: string, replace: string) {
+    return str.replace(new RegExp(search, 'gi'), replace);
+  }
+
+  private generateCensoredWord(count: number) {
+    let res = '';
+    for (let i = 0; i < count; i++) {
+      res += '*';
+    }
+    return res;
+  }
+}
diff --git a/src/app/services/util/room-data.service.spec.ts b/src/app/services/util/room-data.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2cf2be03c52c0f6e7f27a9b4bc04eff538be086e
--- /dev/null
+++ b/src/app/services/util/room-data.service.spec.ts
@@ -0,0 +1,17 @@
+/*import { TestBed } from '@angular/core/testing';
+
+import { RoomDataService } from './room-data.service';
+
+describe('RoomDataService', () => {
+  let service: RoomDataService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(RoomDataService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
+*/
diff --git a/src/app/services/util/room-data.service.ts b/src/app/services/util/room-data.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1530f4e58e735f1a1f917e877eca77b02a135fbb
--- /dev/null
+++ b/src/app/services/util/room-data.service.ts
@@ -0,0 +1,425 @@
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, Observable, of, Subject, Subscription } from 'rxjs';
+import { WsCommentService } from '../websockets/ws-comment.service';
+import { Message } from '@stomp/stompjs';
+import { Comment } from '../../models/comment';
+import { CommentService } from '../http/comment.service';
+import { CorrectWrong } from '../../models/correct-wrong.enum';
+import { RoomService } from '../http/room.service';
+import { ProfanityFilterService } from './profanity-filter.service';
+import { ProfanityFilter, Room } from '../../models/room';
+import { WsRoomService } from '../websockets/ws-room.service';
+
+export interface UpdateInformation {
+  type: 'CommentCreated' | 'CommentPatched' | 'CommentHighlighted' | 'CommentDeleted';
+  subtype?: string;
+  comment: Comment;
+  finished?: boolean;
+  updates?: string[];
+}
+
+class RoomDataUpdateSubscription {
+  updateSubject = new Subject<UpdateInformation>();
+  private readonly _filters: Partial<UpdateInformation>[];
+
+  constructor(filters: Partial<UpdateInformation>[]) {
+    this._filters = filters;
+  }
+
+  onUpdate(event: UpdateInformation): void {
+    for (const filter of this._filters) {
+      if (this.ensureEqual(filter, event)) {
+        this.updateSubject.next(event);
+        break;
+      }
+    }
+  }
+
+  /**
+   * Checks if value1 is a subset of value2
+   */
+  private ensureEqual(value1: any, value2: any): boolean {
+    if (Array.isArray(value1)) {
+      if (!Array.isArray(value2)) {
+        return false;
+      }
+      for (const key of value1) {
+        let same = false;
+        for (const otherKey of value2) {
+          if (this.ensureEqual(key, otherKey)) {
+            same = true;
+            break;
+          }
+        }
+        if (!same) {
+          return false;
+        }
+      }
+      return true;
+    } else if (typeof value1 === 'object') {
+      if (typeof value2 !== 'object') {
+        return false;
+      }
+      const keys = Object.keys(value1);
+      for (const key of keys) {
+        if (!this.ensureEqual(value1[key], value2[key])) {
+          return false;
+        }
+      }
+      return true;
+    }
+    return value1 === value2;
+  }
+}
+
+enum UpdateType {
+  force,
+  commentStream
+}
+
+interface FastRoomAccessObject {
+  [commentId: string]: Comment;
+}
+
+@Injectable({
+  providedIn: 'root'
+})
+export class RoomDataService {
+
+  private _currentSubscriptions: RoomDataUpdateSubscription[] = [];
+  private _currentComments: Comment[] = null;
+  private _commentUpdates: BehaviorSubject<Comment[]> = new BehaviorSubject<Comment[]>(null);
+  private _fastCommentAccess: FastRoomAccessObject = null;
+  private _wsCommentServiceSubscription: Subscription = null;
+  private _currentRoomId: string = null;
+  private _savedCommentsBeforeFilter = new Map();
+  private _savedCommentsAfterFilter = new Map();
+  private room: Room;
+
+  constructor(private wsCommentService: WsCommentService,
+              private commentService: CommentService,
+              private roomService: RoomService,
+              private profanityFilterService: ProfanityFilterService,
+              private wsRoomService: WsRoomService) {
+  }
+
+  get currentRoomData() {
+    return this._currentComments;
+  }
+
+  receiveUpdates(updateFilter: Partial<UpdateInformation>[]): Observable<UpdateInformation> {
+    if (!this._currentRoomId) {
+      console.error('Update Subscription got not registered, room is not bound!');
+      return null;
+    }
+    const subscription = new RoomDataUpdateSubscription(updateFilter);
+    this._currentSubscriptions.push(subscription);
+    return subscription.updateSubject.asObservable();
+  }
+
+  getRoomData(roomId: string, freezed: boolean = false): Observable<Comment[]> {
+    const tempSubject = new BehaviorSubject<Comment[]>(null);
+    if (this._currentRoomId !== roomId) {
+      this._commentUpdates.next(null);
+    }
+    let subscription: Subscription = null;
+    subscription = this._commentUpdates.subscribe(comments => {
+      if (comments === null) {
+        return;
+      }
+      tempSubject.next(freezed ? [...comments] : comments);
+      setTimeout(() => subscription.unsubscribe());
+    });
+    this.ensureRoomBinding(roomId);
+    return tempSubject.asObservable();
+  }
+
+  public checkProfanity(comment: Comment) {
+    const finish = new Subject<boolean>();
+    const subscription = finish.asObservable().subscribe(_ => {
+      if (this.room.profanityFilter !== ProfanityFilter.deactivated) {
+        comment.body = this._savedCommentsAfterFilter.get(comment.id);
+      } else {
+        comment.body = this._savedCommentsBeforeFilter.get(comment.id);
+      }
+      subscription.unsubscribe();
+    });
+
+    if (!this._savedCommentsAfterFilter.get(comment.id) || !this.room) {
+      if (!this.room) {
+        this.roomService.getRoom(localStorage.getItem('roomId')).subscribe(room => {
+          this.room = room;
+          this.setCommentBody(comment);
+          finish.next(true);
+        });
+      } else {
+        this.setCommentBody(comment);
+        finish.next(true);
+      }
+    } else {
+      finish.next(true);
+    }
+  }
+
+  getUnFilteredBody(id: string): string {
+    return this._savedCommentsBeforeFilter.get(id);
+  }
+
+  getFilteredBody(id: string): string {
+    return this._savedCommentsAfterFilter.get(id);
+  }
+
+  private setCommentBody(comment: Comment) {
+    this._savedCommentsBeforeFilter.set(comment.id, comment.body);
+    this._savedCommentsAfterFilter.set(comment.id, this.filterCommentOfProfanity(this.room, comment));
+  }
+
+  private filterAllCommentsBodies() {
+    this._currentComments.forEach(comment => {
+      comment.body = this._savedCommentsBeforeFilter.get(comment.id);
+      this.setCommentBody(comment);
+      this.checkProfanity(comment);
+    });
+  }
+
+  private filterCommentOfProfanity(room: Room, comment: Comment): string {
+    const partialWords = room.profanityFilter === ProfanityFilter.all || room.profanityFilter === ProfanityFilter.partialWords;
+    const languageSpecific = room.profanityFilter === ProfanityFilter.all || room.profanityFilter === ProfanityFilter.languageSpecific;
+    return this.profanityFilterService.filterProfanityWords(comment.body, partialWords, languageSpecific, comment.language);
+  }
+
+  private removeCommentBodies(key: string) {
+    this._savedCommentsBeforeFilter.delete(key);
+    this._savedCommentsAfterFilter.delete(key);
+  }
+
+  private ensureRoomBinding(roomId: string) {
+    if (!roomId || roomId === this._currentRoomId) {
+      return;
+    }
+    this._currentSubscriptions.length = 0;
+    this._currentRoomId = roomId;
+    this._currentComments = null;
+    this._fastCommentAccess = {};
+    if (this._wsCommentServiceSubscription) {
+      this._wsCommentServiceSubscription.unsubscribe();
+    }
+    this.roomService.getRoom(roomId).subscribe(room => {
+      this.room = room;
+      this._wsCommentServiceSubscription = this.wsCommentService.getCommentStream(roomId)
+        .subscribe(msg => this.onMessageReceive(msg));
+      this.commentService.getAckComments(roomId).subscribe(comments => {
+        this._currentComments = comments;
+        for (const comment of comments) {
+          this.setCommentBody(comment);
+          this._fastCommentAccess[comment.id] = comment;
+        }
+        this.triggerUpdate(UpdateType.force, null);
+      });
+    });
+    this.wsRoomService.getRoomStream(roomId).subscribe(msg => {
+      const message = JSON.parse(msg.body);
+      if (message.type === 'RoomPatched') {
+        this.room = message.payload.changes;
+        this.filterAllCommentsBodies();
+      }
+    });
+  }
+
+  private triggerUpdate(type: UpdateType, additionalInformation: UpdateInformation) {
+    if (type === UpdateType.force) {
+      this._commentUpdates.next(this._currentComments);
+    } else if (type === UpdateType.commentStream) {
+      for (const subscription of this._currentSubscriptions) {
+        subscription.onUpdate(additionalInformation);
+      }
+    }
+  }
+
+  private onMessageReceive(message: Message) {
+    const msg = JSON.parse(message.body);
+    const payload = msg.payload;
+    switch (msg.type) {
+      case 'CommentCreated':
+        this.onCommentCreate(payload);
+        break;
+      case 'CommentPatched':
+        this.onCommentPatched(payload);
+        break;
+      case 'CommentHighlighted':
+        this.onCommentHighlighted(payload);
+        break;
+      case 'CommentDeleted':
+        this.onCommentDeleted(payload);
+        break;
+    }
+  }
+
+  private onCommentCreate(payload: any) {
+    const c = new Comment();
+    c.roomId = this._currentRoomId;
+    c.body = payload.body;
+    c.id = payload.id;
+    c.timestamp = payload.timestamp;
+    c.tag = payload.tag;
+    c.creatorId = payload.creatorId;
+    c.userNumber = this.commentService.hashCode(c.creatorId);
+    c.keywordsFromQuestioner = JSON.parse(payload.keywordsFromQuestioner);
+    c.language = payload.language;
+    this._fastCommentAccess[c.id] = c;
+    this._currentComments.push(c);
+    this.triggerUpdate(UpdateType.commentStream, {
+      type: 'CommentCreated',
+      finished: false,
+      comment: c
+    });
+    this.commentService.getComment(c.id).subscribe(comment => {
+      for (const key of Object.keys(comment)) {
+        c[key] = comment[key];
+      }
+      this.setCommentBody(c);
+      this.triggerUpdate(UpdateType.commentStream, {
+        type: 'CommentCreated',
+        finished: true,
+        comment: c
+      });
+    });
+  }
+
+  private onCommentPatched(payload: any) {
+    const comment = this._fastCommentAccess[payload.id];
+    if (!comment) {
+      console.error('comment ' + payload.id + ' was not found!');
+      return;
+    }
+    const updates = [];
+    for (const [key, value] of Object.entries(payload.changes)) {
+      updates.push(key);
+      switch (key) {
+        case 'read':
+          comment.read = value as boolean;
+          this.triggerUpdate(UpdateType.commentStream, {
+            type: 'CommentPatched',
+            subtype: 'read',
+            comment
+          });
+          break;
+        case 'correct':
+          comment.correct = value as CorrectWrong;
+          this.triggerUpdate(UpdateType.commentStream, {
+            type: 'CommentPatched',
+            subtype: 'correct',
+            comment
+          });
+          break;
+        case 'favorite':
+          comment.favorite = value as boolean;
+          this.triggerUpdate(UpdateType.commentStream, {
+            type: 'CommentPatched',
+            subtype: 'favorite',
+            comment
+          });
+          break;
+        case 'bookmark':
+          comment.bookmark = value as boolean;
+          this.triggerUpdate(UpdateType.commentStream, {
+            type: 'CommentPatched',
+            subtype: 'bookmark',
+            comment
+          });
+          break;
+        case 'score':
+          comment.score = value as number;
+          this.triggerUpdate(UpdateType.commentStream, {
+            type: 'CommentPatched',
+            subtype: 'score',
+            comment
+          });
+          break;
+        case 'upvotes':
+          comment.upvotes = value as number;
+          break;
+        case 'downvotes':
+          comment.downvotes = value as number;
+          break;
+        case 'keywordsFromSpacy':
+          comment.keywordsFromSpacy = JSON.parse(value as string);
+          break;
+        case 'keywordsFromQuestioner':
+          comment.keywordsFromQuestioner = JSON.parse(value as string);
+          break;
+        case 'ack':
+          const isNowAck = value as boolean;
+          comment.ack = isNowAck;
+          if (!isNowAck) {
+            this.removeComment(payload.id);
+          }
+          this.triggerUpdate(UpdateType.commentStream, {
+            type: 'CommentPatched',
+            subtype: 'ack',
+            comment
+          });
+          break;
+        case 'tag':
+          comment.tag = value as string;
+          this.triggerUpdate(UpdateType.commentStream, {
+            type: 'CommentPatched',
+            subtype: 'tag',
+            comment
+          });
+          break;
+        case 'answer':
+          comment.answer = value as string;
+          this.triggerUpdate(UpdateType.commentStream, {
+            type: 'CommentPatched',
+            subtype: 'answer',
+            comment
+          });
+          break;
+      }
+    }
+    this.triggerUpdate(UpdateType.commentStream, {
+      type: 'CommentPatched',
+      finished: true,
+      updates,
+      comment
+    });
+  }
+
+  private onCommentHighlighted(payload: any) {
+    const comment = this._fastCommentAccess[payload.id];
+    if (!comment) {
+      console.error('comment ' + payload.id + ' was not found!');
+      return;
+    }
+    comment.highlighted = payload.lights as boolean;
+    this.triggerUpdate(UpdateType.commentStream, {
+      type: 'CommentHighlighted',
+      finished: true,
+      comment
+    });
+  }
+
+  private onCommentDeleted(payload: any) {
+    const comment = this._fastCommentAccess[payload.id];
+    if (!comment) {
+      console.error('comment ' + payload.id + ' was not found!');
+      return;
+    }
+    this.removeComment(payload.id);
+    this.triggerUpdate(UpdateType.commentStream, {
+      type: 'CommentDeleted',
+      finished: true,
+      comment
+    });
+  }
+
+  private removeComment(id: string) {
+    const index = this._currentComments.findIndex(el => el.id === id);
+    if (index >= 0) {
+      this._currentComments.splice(index, 1);
+      this.removeCommentBodies(id);
+    }
+    this._fastCommentAccess[id] = undefined;
+  }
+}
diff --git a/src/app/services/util/tag-cloud-data.service.spec.ts b/src/app/services/util/tag-cloud-data.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ee5ff3e99990ea480d89a1d867eb3f7d1236aa89
--- /dev/null
+++ b/src/app/services/util/tag-cloud-data.service.spec.ts
@@ -0,0 +1,16 @@
+/*import { TestBed } from '@angular/core/testing';
+
+import { TagCloudDataService } from './tag-cloud-data.service';
+
+describe('TagCloudDataService', () => {
+  let service: TagCloudDataService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(TagCloudDataService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});*/
diff --git a/src/app/services/util/tag-cloud-data.service.ts b/src/app/services/util/tag-cloud-data.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..477d1240125b504f45fbfce400634b05ee5d5919
--- /dev/null
+++ b/src/app/services/util/tag-cloud-data.service.ts
@@ -0,0 +1,363 @@
+import { Injectable } from '@angular/core';
+import { TopicCloudAdminData } from '../../components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData';
+import { BehaviorSubject, Observable, Subscription } from 'rxjs';
+import { TopicCloudAdminService } from './topic-cloud-admin.service';
+import { CommentFilter } from '../../utils/filter-options';
+import { TranslateService } from '@ngx-translate/core';
+import { Comment } from '../../models/comment';
+import { RoomDataService } from './room-data.service';
+import { SpacyKeyword } from '../http/spacy.service';
+import { UserRole } from '../../models/user-roles.enum';
+import { CloudParameters } from '../../utils/cloud-parameters';
+import { SmartDebounce } from '../../utils/smart-debounce';
+
+export interface TagCloudDataTagEntry {
+  weight: number;
+  adjustedWeight: number;
+  cachedVoteCount: number;
+  cachedUpVotes: number;
+  cachedDownVotes: number;
+  distinctUsers: Set<number>;
+  firstTimeStamp: Date;
+  lastTimeStamp: Date;
+  categories: Set<string>;
+  dependencies: Set<string>;
+  comments: Comment[];
+}
+
+export interface TagCloudMetaData {
+  commentCount: number;
+  userCount: number;
+  tagCount: number;
+  minWeight: number;
+  maxWeight: number;
+  countPerWeight: TagCloudMetaDataCount;
+}
+
+/**
+ * The key is a generated tag (out of all comments).
+ */
+export type TagCloudData = Map<string, TagCloudDataTagEntry>;
+
+export type TagCloudMetaDataCount = [
+  number, // w1
+  number, // w2
+  number, // w3
+  number, // w4
+  number, // w5
+  number, // w6
+  number, // w7
+  number, // w8
+  number, // w9
+  number  // w10
+];
+
+export enum TagCloudCalcWeightType {
+  byLength,
+  byVotes,
+  byLengthAndVotes
+}
+
+@Injectable({
+  providedIn: 'root'
+})
+export class TagCloudDataService {
+  private _isDemoActive: boolean;
+  private _isAlphabeticallySorted: boolean;
+  private _dataBus: BehaviorSubject<TagCloudData>;
+  private _metaDataBus: BehaviorSubject<TagCloudMetaData>;
+  private _commentSubscription = null;
+  private _roomId = null;
+  private _calcWeightType = TagCloudCalcWeightType.byLength;
+  private _lastFetchedData: TagCloudData = null;
+  private _lastFetchedComments: Comment[] = null;
+  private _lastMetaData: TagCloudMetaData = null;
+  private readonly _currentMetaData: TagCloudMetaData;
+  private _demoData: TagCloudData = null;
+  private _adminData: TopicCloudAdminData = null;
+  private _subscriptionAdminData: Subscription;
+  private _currentFilter: CommentFilter;
+  private readonly _smartDebounce = new SmartDebounce(200, 3_000);
+
+  constructor(private _tagCloudAdmin: TopicCloudAdminService,
+              private _roomDataService: RoomDataService) {
+    this._isDemoActive = false;
+    this._isAlphabeticallySorted = false;
+    this._dataBus = new BehaviorSubject<TagCloudData>(null);
+    this._currentMetaData = {
+      tagCount: 0,
+      commentCount: 0,
+      userCount: 0,
+      minWeight: 0,
+      maxWeight: 0,
+      countPerWeight: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+    };
+    this._metaDataBus = new BehaviorSubject<TagCloudMetaData>(null);
+  }
+
+  static buildDataFromComments(adminData: TopicCloudAdminData, comments: Comment[]): [TagCloudData, Set<number>] {
+    const data: TagCloudData = new Map<string, TagCloudDataTagEntry>();
+    const users = new Set<number>();
+    for (const comment of comments) {
+      TopicCloudAdminService.approveKeywordsOfComment(comment, adminData, (keyword: SpacyKeyword) => {
+        let current: TagCloudDataTagEntry = data.get(keyword.lemma);
+        const commentDate = new Date(comment.timestamp);
+        if (current === undefined) {
+          current = {
+            cachedVoteCount: 0,
+            cachedUpVotes: 0,
+            cachedDownVotes: 0,
+            comments: [],
+            weight: 0,
+            adjustedWeight: 0,
+            distinctUsers: new Set<number>(),
+            categories: new Set<string>(),
+            dependencies: new Set<string>([...keyword.dep]),
+            firstTimeStamp: commentDate,
+            lastTimeStamp: commentDate
+          };
+          data.set(keyword.lemma, current);
+        }
+        keyword.dep.forEach(dependency => current.dependencies.add(dependency));
+        current.cachedVoteCount += comment.score;
+        current.cachedUpVotes += comment.upvotes;
+        current.cachedDownVotes += comment.downvotes;
+        current.distinctUsers.add(comment.userNumber);
+        if (comment.tag) {
+          current.categories.add(comment.tag);
+        }
+        // @ts-ignore
+        if (current.firstTimeStamp - commentDate > 0) {
+          current.firstTimeStamp = commentDate;
+        }
+        // @ts-ignore
+        if (current.lastTimeStamp - commentDate < 0) {
+          current.lastTimeStamp = commentDate;
+        }
+        current.comments.push(comment);
+      });
+      users.add(comment.userNumber);
+    }
+    return [
+      new Map<string, TagCloudDataTagEntry>([...data].filter(v => TopicCloudAdminService.isTopicAllowed(adminData,
+        v[1].comments.length, v[1].distinctUsers.size, v[1].cachedUpVotes, v[1].firstTimeStamp, v[1].lastTimeStamp))),
+      users
+    ];
+  }
+
+  bindToRoom(roomId: string, userRole: UserRole): void {
+    if (this._subscriptionAdminData) {
+      throw new Error('Room already bound.');
+    }
+    this._currentFilter = CommentFilter.currentFilter;
+    this._roomId = roomId;
+    this._lastFetchedComments = null;
+    this._subscriptionAdminData = this._tagCloudAdmin.getAdminData.subscribe(adminData => {
+      this.onReceiveAdminData(adminData, true);
+    });
+    this._tagCloudAdmin.ensureRoomBound(roomId, userRole);
+
+    this.fetchData();
+    if (!this._currentFilter.paused) {
+      this._commentSubscription = this._roomDataService.receiveUpdates([
+        { type: 'CommentCreated', finished: true },
+        { type: 'CommentDeleted' },
+        { type: 'CommentPatched', finished: true, updates: ['score'] },
+        { type: 'CommentPatched', finished: true, updates: ['downvotes'] },
+        { type: 'CommentPatched', finished: true, updates: ['upvotes'] },
+        { type: 'CommentPatched', finished: true, updates: ['keywordsFromSpacy'] },
+        { type: 'CommentPatched', finished: true, updates: ['keywordsFromQuestioner'] },
+        { type: 'CommentPatched', finished: true, updates: ['ack'] },
+        { type: 'CommentPatched', finished: true, updates: ['tag'] },
+      ]).subscribe(_ => {
+        this.rebuildTagData();
+      });
+    }
+  }
+
+  unbindRoom(): void {
+    this._subscriptionAdminData.unsubscribe();
+    this._subscriptionAdminData = null;
+    if (this._commentSubscription !== null) {
+      this._commentSubscription.unsubscribe();
+      this._commentSubscription = null;
+    }
+  }
+
+  updateDemoData(translate: TranslateService): void {
+    translate.get('tag-cloud.demo-data-topic').subscribe(text => {
+      this._demoData = new Map<string, TagCloudDataTagEntry>();
+      for (let i = 10; i >= 1; i--) {
+        this._demoData.set(text.replace('%d', '' + i), {
+          cachedVoteCount: 0,
+          cachedUpVotes: 0,
+          cachedDownVotes: 0,
+          comments: [],
+          weight: i,
+          adjustedWeight: i - 1,
+          categories: new Set<string>(),
+          distinctUsers: new Set<number>(),
+          dependencies: new Set<string>(),
+          firstTimeStamp: new Date(),
+          lastTimeStamp: new Date()
+        });
+      }
+    });
+  }
+
+  get metaData(): TagCloudMetaData {
+    return this._currentMetaData;
+  }
+
+  get currentData(): TagCloudData {
+    return this._dataBus.value;
+  }
+
+  set weightCalcType(type: TagCloudCalcWeightType) {
+    if (type !== this._calcWeightType) {
+      this._calcWeightType = type;
+      this.rebuildTagData();
+    }
+  }
+
+  get weightCalcType(): TagCloudCalcWeightType {
+    return this._calcWeightType;
+  }
+
+  get demoActive(): boolean {
+    return this._isDemoActive;
+  }
+
+  set demoActive(active: boolean) {
+    if (active !== this._isDemoActive) {
+      this._isDemoActive = active;
+      if (this._isDemoActive) {
+        this._lastMetaData = {
+          ...this._currentMetaData,
+          countPerWeight: [...this._currentMetaData.countPerWeight]
+        };
+        this._currentMetaData.minWeight = 1;
+        this._currentMetaData.maxWeight = 10;
+        this._currentMetaData.countPerWeight = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
+      } else if (this._lastMetaData !== null) {
+        for (const key of Object.keys(this._lastMetaData)) {
+          this._currentMetaData[key] = this._lastMetaData[key];
+        }
+        this._lastMetaData = null;
+      }
+      this.reformatData();
+    }
+  }
+
+  get alphabeticallySorted(): boolean {
+    return this._isAlphabeticallySorted;
+  }
+
+  blockWord(tag: string): void {
+    this._tagCloudAdmin.addWordToBlacklist(tag.toLowerCase());
+  }
+
+  updateConfig(parameters: CloudParameters): boolean {
+    if (parameters.sortAlphabetically !== this._isAlphabeticallySorted) {
+      this._isAlphabeticallySorted = parameters.sortAlphabetically;
+      this.reformatData();
+      return true;
+    }
+    return false;
+  }
+
+  getData(): Observable<TagCloudData> {
+    return this._dataBus.asObservable();
+  }
+
+  getMetaData(): Observable<TagCloudMetaData> {
+    return this._metaDataBus.asObservable();
+  }
+
+  reformatData(): void {
+    const current = this.getCurrentData();
+    if (!current) {
+      console.error('Got no data for tag cloud!');
+      return;
+    }
+    let newData: TagCloudData;
+    if (this._isAlphabeticallySorted) {
+      newData = new Map<string, TagCloudDataTagEntry>([...current]
+        .sort(([aTag], [bTag]) => aTag.localeCompare(bTag)));
+    } else {
+      newData = new Map<string, TagCloudDataTagEntry>([...current]
+        .sort(([_, aTagData], [__, bTagData]) => bTagData.weight - aTagData.weight));
+    }
+    this._smartDebounce.call(() => this._dataBus.next(newData));
+  }
+
+  private onReceiveAdminData(data: TopicCloudAdminData, update = false) {
+    this._adminData = data;
+    this._calcWeightType = this._adminData.considerVotes ? TagCloudCalcWeightType.byLengthAndVotes : TagCloudCalcWeightType.byLength;
+    if (update) {
+      this.rebuildTagData();
+    }
+  }
+
+  private getCurrentData(): TagCloudData {
+    if (this._isDemoActive) {
+      return this._demoData;
+    }
+    return this._lastFetchedData;
+  }
+
+  private fetchData(): void {
+    this._roomDataService.getRoomData(this._roomId).subscribe((comments: Comment[]) => {
+      if (comments === null) {
+        return;
+      }
+      this._lastFetchedComments = comments;
+      this.rebuildTagData();
+    });
+  }
+
+  private calculateWeight(tagData: TagCloudDataTagEntry): number {
+    switch (this._calcWeightType) {
+      case TagCloudCalcWeightType.byVotes:
+        return tagData.cachedVoteCount;
+      case TagCloudCalcWeightType.byLengthAndVotes:
+        return tagData.cachedVoteCount / 10.0 + tagData.comments.length;
+      default:
+        return tagData.comments.length;
+    }
+  }
+
+  private rebuildTagData() {
+    if (!this._lastFetchedComments) {
+      return;
+    }
+    const currentMeta = this._isDemoActive ? this._lastMetaData : this._currentMetaData;
+    const filteredComments = this._lastFetchedComments.filter(comment => this._currentFilter.checkComment(comment));
+    currentMeta.commentCount = filteredComments.length;
+    const [data, users] = TagCloudDataService.buildDataFromComments(this._adminData, filteredComments);
+    let minWeight = null;
+    let maxWeight = null;
+    for (const value of data.values()) {
+      value.weight = this.calculateWeight(value);
+      minWeight = Math.min(value.weight, minWeight || value.weight);
+      maxWeight = Math.max(value.weight, maxWeight || value.weight);
+    }
+    //calculate weight counts and adjusted weights
+    const same = minWeight === maxWeight;
+    const span = maxWeight - minWeight;
+    currentMeta.countPerWeight = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+    for (const value of data.values()) {
+      value.adjustedWeight = same ? 4 : Math.round((value.weight - minWeight) * 9.0 / span);
+      ++currentMeta.countPerWeight[value.adjustedWeight];
+    }
+    this._lastFetchedData = data;
+    currentMeta.tagCount = data.size;
+    currentMeta.userCount = users.size;
+    currentMeta.minWeight = minWeight;
+    currentMeta.maxWeight = maxWeight;
+    this._metaDataBus.next(currentMeta);
+    if (!this._isDemoActive) {
+      this.reformatData();
+    }
+  }
+}
diff --git a/src/app/services/util/topic-cloud-admin.service.spec.ts b/src/app/services/util/topic-cloud-admin.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..89683b0355d2eb788ff044c5d2873bb452c68b8a
--- /dev/null
+++ b/src/app/services/util/topic-cloud-admin.service.spec.ts
@@ -0,0 +1,18 @@
+/*
+import { TestBed } from '@angular/core/testing';
+
+import { TopicCloudAdminService } from './topic-cloud-admin.service';
+
+describe('TopicCloudAdminServiceService', () => {
+  let service: TopicCloudAdminService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(TopicCloudAdminService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
+*/
diff --git a/src/app/services/util/topic-cloud-admin.service.ts b/src/app/services/util/topic-cloud-admin.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..288d2620866ddf9f63e83210bfd487f16b69657f
--- /dev/null
+++ b/src/app/services/util/topic-cloud-admin.service.ts
@@ -0,0 +1,266 @@
+import { Injectable } from '@angular/core';
+import {
+  KeywordOrFulltext,
+  spacyLabels,
+  TopicCloudAdminData
+} from '../../components/shared/_dialogs/topic-cloud-administration/TopicCloudAdminData';
+import { RoomService } from '../http/room.service';
+import { ProfanityFilter, Room } from '../../models/room';
+import { TranslateService } from '@ngx-translate/core';
+import { NotificationService } from './notification.service';
+import { WsRoomService } from '../websockets/ws-room.service';
+import { ProfanityFilterService } from './profanity-filter.service';
+import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs';
+import { Comment } from '../../models/comment';
+import { UserRole } from '../../models/user-roles.enum';
+
+@Injectable({
+  providedIn: 'root',
+})
+export class TopicCloudAdminService {
+  private static readonly adminKey = 'Topic-Cloud-Admin-Data';
+  private adminData: BehaviorSubject<TopicCloudAdminData>;
+  private blacklist: Subject<string[]>;
+  private blacklistIsActive: Subject<boolean>;
+  private blacklistActive: boolean;
+  private _subscriptionWsRoom: Subscription;
+
+  constructor(private roomService: RoomService,
+              private translateService: TranslateService,
+              private wsRoomService: WsRoomService,
+              private profanityFilterService: ProfanityFilterService,
+              private notificationService: NotificationService) {
+    this.blacklist = new Subject<string[]>();
+    this.blacklistIsActive = new Subject<boolean>();
+    this.adminData = new BehaviorSubject<TopicCloudAdminData>(TopicCloudAdminService.getDefaultAdminData);
+  }
+
+  static approveKeywordsOfComment(comment: Comment, config: TopicCloudAdminData, keywordFunc: (SpacyKeyword) => void) {
+    let source = comment.keywordsFromQuestioner;
+    if (config.keywordORfulltext === KeywordOrFulltext.both) {
+      source = !source || !source.length ? comment.keywordsFromSpacy : source;
+    } else if (config.keywordORfulltext === KeywordOrFulltext.fulltext) {
+      source = comment.keywordsFromSpacy;
+    }
+    if (!source) {
+      return;
+    }
+    const wantedLabels = config.wantedLabels[comment.language.toLowerCase()];
+    for (const keyword of source) {
+      if (wantedLabels && !keyword.dep.some(e => wantedLabels.includes(e))) {
+        continue;
+      }
+      let isProfanity = false;
+      const lowerCasedKeyword = keyword.lemma.toLowerCase();
+      for (const word of config.blacklist) {
+        if (lowerCasedKeyword.includes(word)) {
+          isProfanity = true;
+          break;
+        }
+      }
+      if (!isProfanity) {
+        keywordFunc(keyword);
+      }
+    }
+  }
+
+  static isTopicAllowed(config: TopicCloudAdminData, comments: number, users: number,
+                        upvotes: number, firstTimeStamp: Date, lastTimeStamp: Date) {
+    return !((config.minQuestions > comments) ||
+      (config.minQuestioners > users) ||
+      (config.minUpvotes > upvotes) ||
+      (config.startDate && new Date(config.startDate) > firstTimeStamp) ||
+      (config.endDate && new Date(config.endDate) < lastTimeStamp));
+  }
+
+  static isTopicRequirementDisabled(data: TopicCloudAdminData): boolean {
+    return (data.minQuestioners === 1) && (data.minQuestions === 1) && (data.minUpvotes === 0) &&
+      (data.startDate === null) && (data.endDate === null);
+  }
+
+  static get getDefaultAdminData(): TopicCloudAdminData {
+    let data: TopicCloudAdminData = JSON.parse(localStorage.getItem(this.adminKey));
+    if (!data) {
+      data = {
+        blacklist: [],
+        wantedLabels: {
+          de: this.getDefaultSpacyTagsDE(),
+          en: this.getDefaultSpacyTagsEN()
+        },
+        considerVotes: true,
+        profanityFilter: ProfanityFilter.none,
+        blacklistIsActive: true,
+        keywordORfulltext: KeywordOrFulltext.both,
+        minQuestioners: 1,
+        minQuestions: 1,
+        minUpvotes: 0,
+        startDate: null,
+        endDate: null
+      };
+    }
+    return data;
+  }
+
+  static getDefaultSpacyTagsDE(): string[] {
+    const tags: string[] = [];
+    spacyLabels.de.forEach(label => {
+      if (label.enabledByDefault) {
+        tags.push(label.tag);
+      }
+    });
+    return tags;
+  }
+
+  static getDefaultSpacyTagsEN(): string[] {
+    const tags: string[] = [];
+    spacyLabels.en.forEach(label => {
+      if (label.enabledByDefault) {
+        tags.push(label.tag);
+      }
+    });
+    return tags;
+  }
+
+  get getAdminData(): Observable<TopicCloudAdminData> {
+    return this.adminData.asObservable();
+  }
+
+  ensureRoomBound(roomId: string, userRole: UserRole) {
+    if (this._subscriptionWsRoom) {
+      this._subscriptionWsRoom.unsubscribe();
+      this._subscriptionWsRoom = null;
+    }
+    this._subscriptionWsRoom = this.wsRoomService.getRoomStream(roomId).subscribe(msg => {
+      const message = JSON.parse(msg.body);
+      const room = message.payload.changes;
+      if (message.type === 'RoomPatched') {
+        this.blacklist.next(room.blacklist ? JSON.parse(room.blacklist) : []);
+        this.blacklistActive = room.blacklistIsActive;
+        this.blacklistIsActive.next(room.blacklistIsActive);
+        const data = TopicCloudAdminService.getDefaultAdminData;
+        data.profanityFilter = room.profanityFilter;
+        data.blacklistIsActive = this.blacklistActive;
+        this.setAdminData(data, false, userRole);
+      }
+    });
+    this.roomService.getRoom(roomId).subscribe(room => {
+      this.blacklistActive = room.blacklistIsActive;
+      const adminData = TopicCloudAdminService.getDefaultAdminData;
+      const list = this.finishBlacklist(room.blacklist ? JSON.parse(room.blacklist) : [], room.blacklistIsActive, room.profanityFilter);
+      let areEqual = !!adminData.blacklist && list.length === adminData.blacklist.length;
+      for (let i = 0; i < list.length && areEqual; i++) {
+        areEqual = list[i] === adminData.blacklist[i];
+      }
+      if (adminData.blacklistIsActive !== room.blacklistIsActive ||
+        adminData.profanityFilter !== room.profanityFilter || !areEqual) {
+        this.blacklist.next(list);
+        this.blacklistIsActive.next(room.blacklistIsActive);
+        this.blacklistActive = room.blacklistIsActive;
+        adminData.blacklistIsActive = room.blacklistIsActive;
+        adminData.profanityFilter = room.profanityFilter;
+        this.setAdminData(adminData, false, userRole, list);
+      }
+    });
+  }
+
+  updateLocalAdminData(_adminData: TopicCloudAdminData) {
+    localStorage.setItem(TopicCloudAdminService.adminKey, JSON.stringify(_adminData));
+  }
+
+  setAdminData(_adminData: TopicCloudAdminData, updateRoom: boolean, userRole: UserRole, blacklist: string[] = null) {
+    localStorage.setItem(TopicCloudAdminService.adminKey, JSON.stringify(_adminData));
+    if (updateRoom && userRole && userRole > UserRole.PARTICIPANT) {
+      this.getRoom().subscribe(room => {
+        room.blacklistIsActive = _adminData.blacklistIsActive;
+        this.updateRoom(room);
+      });
+      return;
+    }
+    const applyBlacklist = (list: string[]) => {
+      _adminData.blacklist = this.finishBlacklist(list, _adminData.blacklistIsActive, _adminData.profanityFilter);
+      localStorage.setItem(TopicCloudAdminService.adminKey, JSON.stringify(_adminData));
+      this.adminData.next(_adminData);
+    };
+    if (blacklist) {
+      applyBlacklist(blacklist);
+      return;
+    }
+    const subscription = this.getBlacklist().subscribe(list => {
+      _adminData.blacklistIsActive = this.blacklistActive;
+      applyBlacklist(list);
+      subscription.unsubscribe();
+    });
+  }
+
+  getBlacklist(): Observable<string[]> {
+    this.getRoom().subscribe(room => {
+      const list = room.blacklist ? JSON.parse(room.blacklist) : [];
+      this.blacklist.next(list);
+      this.blacklistIsActive.next(room.blacklistIsActive);
+      this.blacklistActive = room.blacklistIsActive;
+    });
+    return this.blacklist.asObservable();
+  }
+
+  getBlacklistIsActive() {
+    return this.blacklistIsActive.asObservable();
+  }
+
+  getRoom(): Observable<Room> {
+    return this.roomService.getRoom(localStorage.getItem('roomId'));
+  }
+
+  addWordToBlacklist(word: string) {
+    if (word !== undefined) {
+      this.getRoom().subscribe(room => {
+        const newlist = room.blacklist ? JSON.parse(room.blacklist) : [];
+        if (!newlist.includes(word.toLowerCase().trim())) {
+          newlist.push(word.toLowerCase().trim());
+        }
+        this.updateBlacklist(newlist, room, 'add-successful');
+      });
+    }
+  }
+
+  removeWordFromBlacklist(word: string) {
+    if (word !== undefined) {
+      this.getRoom().subscribe(room => {
+        if (room.blacklist && room.blacklist.length > 0) {
+          const newlist = JSON.parse(room.blacklist);
+          newlist.splice(newlist.indexOf(word, 0), 1);
+          this.updateBlacklist(newlist, room, 'remove-successful');
+        }
+      });
+    }
+  }
+
+  updateBlacklist(list: string[], room: Room, msg?: string) {
+    room.blacklist = JSON.stringify(list);
+    this.updateRoom(room, msg);
+  }
+
+  updateRoom(updatedRoom: Room, message?: string) {
+    this.roomService.updateRoom(updatedRoom).subscribe(_ => {
+        if (!message) {
+          message = 'changes-successful';
+        }
+        this.translateService.get('topic-cloud.' + message).subscribe(msg => {
+          this.notificationService.show(msg);
+          this.blacklist.next(JSON.parse(updatedRoom.blacklist));
+        });
+      },
+      error => {
+        this.translateService.get('topic-cloud.changes-gone-wrong').subscribe(msg => {
+          this.notificationService.show(msg);
+        });
+      });
+  }
+
+  private finishBlacklist(list: string[], blacklistIsActive: boolean, profanityFilter: ProfanityFilter): string[] {
+    const blacklist = blacklistIsActive ? list : [];
+    if (profanityFilter === ProfanityFilter.deactivated) {
+      return blacklist;
+    }
+    return blacklist.concat(this.profanityFilterService.getProfanityList);
+  }
+}
diff --git a/src/app/services/websockets/ws-comment-service.service.spec.ts b/src/app/services/websockets/ws-comment-service.service.spec.ts
deleted file mode 100644
index 02c67cb49c83d3beda7ce75f172f69541436b821..0000000000000000000000000000000000000000
--- a/src/app/services/websockets/ws-comment-service.service.spec.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/* import { TestBed } from '@angular/core/testing';
-
-import { WsCommentServiceService } from './ws-comment-service.service';
-
-describe('WsCommentServiceService', () => {
-  beforeEach(() => TestBed.configureTestingModule({}));
-
-  it('should be created', () => {
-    const service: WsCommentServiceService = TestBed.get(WsCommentServiceService);
-    expect(service).toBeTruthy();
-  });
-});
-*/
diff --git a/src/app/services/websockets/ws-comment-service.service.ts b/src/app/services/websockets/ws-comment-service.service.ts
deleted file mode 100644
index e08ea411be3c0c81fe8090501000f401df2724ab..0000000000000000000000000000000000000000
--- a/src/app/services/websockets/ws-comment-service.service.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { Injectable } from '@angular/core';
-import { Comment } from '../../models/comment';
-import { WsConnectorService } from '../../services/websockets/ws-connector.service';
-import { CreateComment } from '../../models/messages/create-comment';
-import { PatchComment } from '../../models/messages/patch-comment';
-import { HighlightComment } from '../../models/messages/highlight-comment';
-import { TSMap } from 'typescript-map';
-import { UpVote } from '../../models/messages/up-vote';
-import { DownVote } from '../../models/messages/down-vote';
-import { ResetVote } from '../../models/messages/reset-vote';
-import { Observable } from 'rxjs';
-import { IMessage } from '@stomp/stompjs';
-
-
-@Injectable({
-  providedIn: 'root'
-})
-export class WsCommentServiceService {
-
-  constructor(private wsConnector: WsConnectorService) { }
-
-  getCommentStream(roomId: string): Observable<IMessage> {
-    return this.wsConnector.getWatcher(`/topic/${roomId}.comment.stream`);
-  }
-
-  getModeratorCommentStream(roomId: string): Observable<IMessage> {
-    return this.wsConnector.getWatcher(`/topic/${roomId}.comment.moderator.stream`);
-  }
-}
diff --git a/src/app/services/websockets/ws-comment.service.spec.ts b/src/app/services/websockets/ws-comment.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5f3e9314b45260ec245ff32669936841e3599afb
--- /dev/null
+++ b/src/app/services/websockets/ws-comment.service.spec.ts
@@ -0,0 +1,13 @@
+/*import { TestBed } from '@angular/core/testing';
+
+import { WsCommentService } from './ws-comment.service';
+
+describe('WsCommentService', () => {
+  beforeEach(() => TestBed.configureTestingModule({}));
+
+  it('should be created', () => {
+    const service: WsCommentService = TestBed.get(WsCommentService);
+    expect(service).toBeTruthy();
+  });
+});
+*/
diff --git a/src/app/services/websockets/ws-comment.service.ts b/src/app/services/websockets/ws-comment.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..60ccb90e72e072ebbff1c43fa13bb791d49e94b1
--- /dev/null
+++ b/src/app/services/websockets/ws-comment.service.ts
@@ -0,0 +1,21 @@
+import { Injectable } from '@angular/core';
+import { WsConnectorService } from './ws-connector.service';
+import { Observable } from 'rxjs';
+import { IMessage } from '@stomp/stompjs';
+
+
+@Injectable({
+  providedIn: 'root'
+})
+export class WsCommentService {
+
+  constructor(private wsConnector: WsConnectorService) { }
+
+  getCommentStream(roomId: string): Observable<IMessage> {
+    return this.wsConnector.getWatcher(`/topic/${roomId}.comment.stream`);
+  }
+
+  getModeratorCommentStream(roomId: string): Observable<IMessage> {
+    return this.wsConnector.getWatcher(`/topic/${roomId}.comment.moderator.stream`);
+  }
+}
diff --git a/src/app/services/websockets/ws-room.service.spec.ts b/src/app/services/websockets/ws-room.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..558c8827b4c64e95bf7a11943920f1377b16369a
--- /dev/null
+++ b/src/app/services/websockets/ws-room.service.spec.ts
@@ -0,0 +1,16 @@
+/*import { TestBed } from '@angular/core/testing';
+
+import { WsRoomService } from './ws-room.service';
+
+describe('WsRoomService', () => {
+  let service: WsRoomService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(WsRoomService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});*/
diff --git a/src/app/services/websockets/ws-room.service.ts b/src/app/services/websockets/ws-room.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ac1cb6817be34200f1806c265a1f441410e97f8f
--- /dev/null
+++ b/src/app/services/websockets/ws-room.service.ts
@@ -0,0 +1,16 @@
+import { Injectable } from '@angular/core';
+import { WsConnectorService } from './ws-connector.service';
+import { Observable } from 'rxjs';
+import { IMessage } from '@stomp/stompjs';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class WsRoomService {
+
+  constructor(private wsConnector: WsConnectorService) { }
+
+  getRoomStream(roomId: string): Observable<IMessage> {
+    return this.wsConnector.getWatcher(`/topic/${roomId}.room.stream`);
+  }
+}
diff --git a/src/app/utils/cloud-parameters.const.ts b/src/app/utils/cloud-parameters.const.ts
new file mode 100644
index 0000000000000000000000000000000000000000..26b493c8efb59d8973b006bf28b5b7f82dd503a1
--- /dev/null
+++ b/src/app/utils/cloud-parameters.const.ts
@@ -0,0 +1,44 @@
+export interface DefaultCloudParameters {
+  w1: string;
+  w2: string;
+  w3: string;
+  w4: string;
+  w5: string;
+  w6: string;
+  w7: string;
+  w8: string;
+  w9: string;
+  w10: string;
+  backgroundColor: string;
+  hoverColor: string;
+}
+
+export const LIGHT_THEME: DefaultCloudParameters = {
+  w1: 'dimgray',
+  w2: 'brown',
+  w3: 'olive',
+  w4: 'seagreen',
+  w5: 'teal',
+  w6: 'navy',
+  w7: 'green',
+  w8: 'salmon',
+  w9: 'darkorange',
+  w10: 'red',
+  backgroundColor: 'var(--background, moccasin)',
+  hoverColor: 'var(--black, black)'
+};
+
+export const DARK_THEME: DefaultCloudParameters = {
+  w1: 'dimgray',
+  w2: 'brown',
+  w3: 'olive',
+  w4: 'seagreen',
+  w5: 'teal',
+  w6: 'green',
+  w7: 'orange',
+  w8: 'magenta',
+  w9: 'greenyellow',
+  w10: 'red',
+  backgroundColor: 'var(--background, #121212)',
+  hoverColor: 'var(--white, white)'
+};
diff --git a/src/app/utils/cloud-parameters.ts b/src/app/utils/cloud-parameters.ts
new file mode 100644
index 0000000000000000000000000000000000000000..751bd0b2eef276658caf730bca3f1cd8303fffbb
--- /dev/null
+++ b/src/app/utils/cloud-parameters.ts
@@ -0,0 +1,219 @@
+import { themes } from '../../theme/arsnova-theme.const';
+import { DARK_THEME, DefaultCloudParameters, LIGHT_THEME } from './cloud-parameters.const';
+
+export interface CloudWeightSetting {
+  maxVisibleElements: number;
+  color: string;
+  rotation: number;
+  allowManualTagNumber: boolean;
+}
+
+export type CloudWeightSettings = [
+  weight1: CloudWeightSetting,
+  weight2: CloudWeightSetting,
+  weight3: CloudWeightSetting,
+  weight4: CloudWeightSetting,
+  weight5: CloudWeightSetting,
+  weight6: CloudWeightSetting,
+  weight7: CloudWeightSetting,
+  weight8: CloudWeightSetting,
+  weight9: CloudWeightSetting,
+  weight10: CloudWeightSetting
+];
+
+export enum CloudTextStyle {
+  normal,
+  lowercase,
+  capitalized,
+  uppercase
+}
+
+const colorRegex = /rgba?\((\d+), (\d+), (\d+)(?:, (\d(?:\.\d+)?))?\)/;
+
+export class CloudParameters {
+
+  static get currentParameters(): CloudParameters {
+    const jsonData = localStorage.getItem('tagCloudConfiguration');
+    const temp = jsonData != null ? JSON.parse(jsonData) : null;
+    const elem = new CloudParameters();
+    elem.resetToDefault(this.isThemeDark());
+    if (temp != null) {
+      for (const key of Object.keys(elem)) {
+        if (temp[key] !== undefined) {
+          elem[key] = temp[key];
+        }
+      }
+    }
+    return elem;
+  }
+
+  static set currentParameters(parameters: CloudParameters) {
+    localStorage.setItem('tagCloudConfiguration', JSON.stringify(parameters));
+  }
+
+  static removeParameters() {
+    localStorage.removeItem('tagCloudConfiguration');
+  }
+
+  fontFamily: string;
+  fontStyle: string;
+  fontWeight: string;
+  fontSize: string;
+  backgroundColor: string;
+  fontColor: string;
+  fontSizeMin: number;
+  fontSizeMax: number;
+  hoverScale: number;
+  hoverTime: number;
+  hoverDelay: number;
+  delayWord: number;
+  randomAngles: boolean;
+  sortAlphabetically: boolean;
+  textTransform: CloudTextStyle;
+  cloudWeightSettings: CloudWeightSettings;
+
+  constructor(obj?: any) {
+    if (obj) {
+      this.fontFamily = obj.fontFamily;
+      this.fontStyle = obj.fontStyle;
+      this.fontWeight = obj.fontWeight;
+      this.fontSize = obj.fontSize;
+      this.backgroundColor = obj.backgroundColor;
+      this.fontColor = obj.fontColor;
+      this.fontSizeMin = obj.fontSizeMin;
+      this.fontSizeMax = obj.fontSizeMax;
+      this.hoverScale = obj.hoverScale;
+      this.hoverTime = obj.hoverTime;
+      this.hoverDelay = obj.hoverDelay;
+      this.delayWord = obj.delayWord;
+      this.randomAngles = obj.randomAngles;
+      this.sortAlphabetically = obj.sortAlphabetically;
+      this.textTransform = obj.textTransform;
+      this.cloudWeightSettings = [
+        { ...obj.cloudWeightSettings[0] },
+        { ...obj.cloudWeightSettings[1] },
+        { ...obj.cloudWeightSettings[2] },
+        { ...obj.cloudWeightSettings[3] },
+        { ...obj.cloudWeightSettings[4] },
+        { ...obj.cloudWeightSettings[5] },
+        { ...obj.cloudWeightSettings[6] },
+        { ...obj.cloudWeightSettings[7] },
+        { ...obj.cloudWeightSettings[8] },
+        { ...obj.cloudWeightSettings[9] }
+      ];
+    }
+  }
+
+  private static isThemeDark() {
+    const currentThemeName = localStorage.getItem('theme');
+    for (const theme in themes) {
+      if (theme === currentThemeName) {
+        return themes[theme].isDark;
+      }
+    }
+    return false;
+  }
+
+  private static resolveColor(element: HTMLParagraphElement, color: string): string {
+    element.style.backgroundColor = 'rgb(0, 0, 0)';
+    element.style.backgroundColor = color;
+    const result = window.getComputedStyle(element).backgroundColor.match(colorRegex);
+    const r = parseInt(result[1], 10);
+    const g = parseInt(result[2], 10);
+    const b = parseInt(result[3], 10);
+    return `#${((r * 256 + g) * 256 + b).toString(16).padStart(6, '0')}`;
+  }
+
+  private static mapValue(current: number, minInput: number, maxInput: number, minOut: number, maxOut: number) {
+    const value = (current - minInput) * (maxOut - minOut) / (maxInput - minInput) + minOut;
+    return Math.min(maxOut, Math.max(minOut, value));
+  }
+
+  resetToDefault(isDark: boolean) {
+    const theme: DefaultCloudParameters = isDark ? DARK_THEME : LIGHT_THEME;
+    const p = document.createElement('p');
+    p.style.display = 'none';
+    document.body.appendChild(p);
+    const minValue = window.innerWidth < window.innerHeight ? window.innerWidth : window.innerHeight;
+    const isMobile = minValue < 700;
+    const elements = isMobile ? 7 : 10;
+    this.fontFamily = 'Dancing Script';
+    this.fontStyle = 'normal';
+    this.fontWeight = 'normal';
+    this.fontSize = '14px';
+    this.backgroundColor = CloudParameters.resolveColor(p, theme.backgroundColor);
+    this.fontColor = CloudParameters.resolveColor(p, theme.hoverColor);
+    this.fontSizeMin = CloudParameters.mapValue(minValue, 375, 750, 125, 200);
+    this.fontSizeMax = CloudParameters.mapValue(minValue, 375, 1500, 300, 900);
+    this.hoverScale = CloudParameters.mapValue(minValue, 375, 1500, 1.4, 2);
+    this.hoverTime = 1;
+    this.hoverDelay = 0.4;
+    this.delayWord = 100;
+    this.randomAngles = false;
+    this.sortAlphabetically = false;
+    this.textTransform = CloudTextStyle.capitalized;
+    this.cloudWeightSettings = [
+      {
+        maxVisibleElements: elements,
+        color: CloudParameters.resolveColor(p, theme.w1),
+        rotation: 0,
+        allowManualTagNumber: isMobile
+      },
+      {
+        maxVisibleElements: elements,
+        color: CloudParameters.resolveColor(p, theme.w2),
+        rotation: 0,
+        allowManualTagNumber: isMobile
+      },
+      {
+        maxVisibleElements: elements,
+        color: CloudParameters.resolveColor(p, theme.w3),
+        rotation: 0,
+        allowManualTagNumber: isMobile
+      },
+      {
+        maxVisibleElements: elements,
+        color: CloudParameters.resolveColor(p, theme.w4),
+        rotation: 0,
+        allowManualTagNumber: isMobile
+      },
+      {
+        maxVisibleElements: elements,
+        color: CloudParameters.resolveColor(p, theme.w5),
+        rotation: 0,
+        allowManualTagNumber: isMobile
+      },
+      {
+        maxVisibleElements: elements,
+        color: CloudParameters.resolveColor(p, theme.w6),
+        rotation: 0,
+        allowManualTagNumber: isMobile
+      },
+      {
+        maxVisibleElements: elements,
+        color: CloudParameters.resolveColor(p, theme.w7),
+        rotation: 0,
+        allowManualTagNumber: isMobile
+      },
+      {
+        maxVisibleElements: elements,
+        color: CloudParameters.resolveColor(p, theme.w8),
+        rotation: 0,
+        allowManualTagNumber: isMobile
+      },
+      {
+        maxVisibleElements: elements,
+        color: CloudParameters.resolveColor(p, theme.w9),
+        rotation: 0,
+        allowManualTagNumber: isMobile
+      },
+      {
+        maxVisibleElements: elements,
+        color: CloudParameters.resolveColor(p, theme.w10),
+        rotation: 0,
+        allowManualTagNumber: isMobile
+      },
+    ];
+    p.remove();
+  }
+}
diff --git a/src/app/utils/create-comment-keywords.ts b/src/app/utils/create-comment-keywords.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ab65318b45f072f678cf7b0f8394a19ec9649ded
--- /dev/null
+++ b/src/app/utils/create-comment-keywords.ts
@@ -0,0 +1,41 @@
+import { Language, LanguagetoolService } from '../services/http/languagetool.service';
+import { map } from 'rxjs/operators';
+
+export class CreateCommentKeywords {
+
+  static isKeywordAcceptable(keyword: string) {
+    const regex = /(^[ -@\[-`{-~]+$)/g;
+    return keyword.match(regex) === null && keyword.length > 2;
+  }
+
+  static isSpellingAcceptable(languagetoolService: LanguagetoolService, text: string, language: Language = 'auto') {
+    text = this.cleaningFunction(text);
+    return languagetoolService.checkSpellings(text, language).pipe(
+      map(result => {
+        const wordCount = text.trim().split(' ').length;
+        const hasConfidence = language === 'auto' ? result.language.detectedLanguage.confidence >= 0.5 : true;
+        const hasLessMistakes = (result.matches.length * 100) / wordCount <= 20;
+        return {
+          isAcceptable: hasConfidence && hasLessMistakes,
+          text,
+          result
+        };
+      })
+    );
+  }
+
+  static cleaningFunction(text: string, removeAsciiNamedEmojis = false): string {
+    // eslint-disable-next-line max-len
+    const regexEmoji = new RegExp('\uD918\uDD28|\ufe0f|\u200D|\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff]', 'g');
+    const regexKatex = new RegExp('\\$[^$\\n ]+\\$|\\$\\$[^$\\n ]+\\$\\$', 'g');
+    const regexMarkdown = new RegExp('(?:__|[*#])|\\[(.+?)]\\((.+?)\\)', 'g');
+    const regexBlank = new RegExp('[\\s]{2,}', 'gu');
+    const regexAsciiNamedEmojis = new RegExp(':([a-z0-9_]+):', 'g');
+    text = text.replace(regexKatex, '');
+    text = text.replace(regexEmoji, '');
+    text = text.replace(regexMarkdown, '');
+    text = text.replace(regexAsciiNamedEmojis, removeAsciiNamedEmojis ? '' : '$1');
+    text = text.replace(regexBlank, ' ');
+    return text;
+  }
+}
diff --git a/src/app/utils/create-comment-wrapper.ts b/src/app/utils/create-comment-wrapper.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4ad3d4ce1803402515c37b7e7dcf956d3281b029
--- /dev/null
+++ b/src/app/utils/create-comment-wrapper.ts
@@ -0,0 +1,55 @@
+import { MatDialog } from '@angular/material/dialog';
+import { TranslateService } from '@ngx-translate/core';
+
+import { CreateCommentComponent } from '../components/shared/_dialogs/create-comment/create-comment.component';
+import { User } from '../models/user';
+import { Room } from '../models/room';
+import { Comment } from '../models/comment';
+import { NotificationService } from '../services/util/notification.service';
+import { CommentService } from '../services/http/comment.service';
+
+export class CreateCommentWrapper {
+  constructor(private translateService: TranslateService,
+              private notificationService: NotificationService,
+              private commentService: CommentService,
+              private dialog: MatDialog,
+              private room: Room) {
+  }
+
+  openCreateDialog(user: User): void {
+    const dialogRef = this.dialog.open(CreateCommentComponent, {
+      width: '900px',
+      maxWidth: 'calc( 100% - 50px )',
+      maxHeight: 'calc( 100vh - 50px )',
+      autoFocus: false,
+    });
+    dialogRef.componentInstance.user = user;
+    dialogRef.componentInstance.roomId = this.room.id;
+    dialogRef.componentInstance.tags = this.room.tags || [];
+    dialogRef.afterClosed()
+      .subscribe(result => {
+        if (result) {
+          this.send(result);
+        } else {
+          return;
+        }
+      });
+  }
+
+  send(comment: Comment): void {
+    let message;
+    if (this.room.directSend) {
+      this.translateService.get('comment-list.comment-sent').subscribe(msg => {
+        message = msg;
+      });
+      comment.ack = true;
+    } else {
+      this.translateService.get('comment-list.comment-sent-to-moderator').subscribe(msg => {
+        message = msg;
+      });
+    }
+    this.commentService.addComment(comment).subscribe(() => {
+      this.notificationService.show(message);
+    });
+  }
+}
diff --git a/src/app/utils/filter-options.ts b/src/app/utils/filter-options.ts
new file mode 100644
index 0000000000000000000000000000000000000000..af92e68b70c03a3d4c54a74d7f1adf1f057da2a8
--- /dev/null
+++ b/src/app/utils/filter-options.ts
@@ -0,0 +1,175 @@
+import { Comment } from '../models/comment';
+import { CorrectWrong } from '../models/correct-wrong.enum';
+
+export const enum FilterNames {
+  read = 'read',
+  unread = 'unread',
+  favorite = 'favorite',
+  correct = 'correct',
+  wrong = 'wrong',
+  bookmark = 'bookmark',
+  answer = 'answer',
+  unanswered = 'unanswered'
+}
+
+export enum Period {
+  fromNow = 'from-now',
+  oneHour = 'time-1h',
+  threeHours = 'time-3h',
+  oneDay = 'time-1d',
+  oneWeek = 'time-1w',
+  twoWeeks = 'time-2w',
+  all = 'time-all'
+}
+
+export class CommentFilter {
+  filterSelected = '';
+  keywordSelected = '';
+  tagSelected = '';
+  userNumberSelected = 0;
+
+  paused = false;
+  timeStampUntil = 0;
+
+  periodSet: Period = Period.twoWeeks;
+  timeStampNow = 0;
+
+  constructor(obj?: any) {
+    if (obj) {
+      this.filterSelected = obj.filterSelected;
+      this.keywordSelected = obj.keywordSelected;
+      this.tagSelected = obj.tagSelected;
+      this.paused = obj.paused;
+      this.timeStampUntil = obj.timeStampUntil;
+      this.periodSet = obj.periodSet;
+      this.timeStampNow = obj.timeStampNow;
+      this.userNumberSelected = obj.userNumberSelected;
+    }
+  }
+
+  public static set currentFilter(filter: CommentFilter) {
+    localStorage.setItem('filter', JSON.stringify(filter));
+  }
+
+  public static get currentFilter(): CommentFilter {
+    return new CommentFilter(JSON.parse(localStorage.getItem('filter')));
+  }
+
+  public static generateFilterNow(filterSelected: string): CommentFilter {
+    const filter = new CommentFilter();
+
+    filter.userNumberSelected = 0;
+    filter.filterSelected = filterSelected;
+    filter.paused = false;
+
+    filter.tagSelected = '';
+    filter.keywordSelected = '';
+
+    filter.periodSet = Period.fromNow;
+    filter.timeStampNow = new Date().getTime();
+
+    return filter;
+  }
+
+  public static generateFilterUntil(filterSelected: string, periodSelected: Period, untilTime: number,
+                                    tagSelected: string, keywordSelected: string): CommentFilter {
+    const filter = new CommentFilter();
+
+
+    filter.userNumberSelected = 0;
+    filter.filterSelected = filterSelected;
+
+    filter.paused = true;
+    filter.timeStampUntil = untilTime;
+
+    filter.tagSelected = tagSelected;
+    filter.keywordSelected = keywordSelected;
+
+    filter.periodSet = periodSelected;
+
+    return filter;
+  }
+
+  public checkComment(com: Comment): boolean {
+    return (this.checkPeriod(com) && this.checkFilters(com));
+  }
+
+  private checkPeriod(com: Comment): boolean {
+    /* Filter by Period */
+    const currentTime = new Date();
+    const hourInSeconds = 3600000;
+    let periodInSeconds;
+
+    if (this.periodSet === Period.all) {
+      return true;
+    }
+
+    switch (this.periodSet) {
+      case Period.fromNow:
+        break;
+      case Period.oneHour:
+        periodInSeconds = hourInSeconds;
+        break;
+      case Period.threeHours:
+        periodInSeconds = hourInSeconds * 3;
+        break;
+      case Period.oneDay:
+        periodInSeconds = hourInSeconds * 24;
+        break;
+      case Period.oneWeek:
+        periodInSeconds = hourInSeconds * 168;
+        break;
+      case Period.twoWeeks:
+        periodInSeconds = hourInSeconds * 336;
+        break;
+    }
+
+    const commentTime = new Date(com.timestamp).getTime();
+
+    if (this.periodSet === Period.fromNow) {
+      return commentTime > this.timeStampNow;
+    }
+
+    if (this.paused) {
+      return commentTime < this.timeStampUntil;
+    }
+
+    return commentTime > (currentTime.getTime() - periodInSeconds);
+  }
+
+  private checkFilters(com: Comment): boolean {
+    if (this.filterSelected) {  // no filters => return true
+      switch (this.filterSelected) {
+        case FilterNames.correct:
+          return com.correct === CorrectWrong.CORRECT;
+        case FilterNames.wrong:
+          return com.correct === CorrectWrong.WRONG;
+        case FilterNames.favorite:
+          return com.favorite;
+        case FilterNames.bookmark:
+          return com.bookmark;
+        case FilterNames.read:
+          return com.read;
+        case FilterNames.unread:
+          return !com.read;
+        case FilterNames.answer:
+          return com.answer !== '';
+        case FilterNames.unanswered:
+          return !com.answer;
+      }
+    }
+
+    if (this.userNumberSelected !== 0) {
+      return com.userNumber === this.userNumberSelected;
+    }
+
+    if (this.keywordSelected !== '') {
+      return com.keywordsFromQuestioner.findIndex(e => e.lemma === this.keywordSelected) >= 0;
+    }
+
+    if (this.tagSelected !== '') {
+      return com.tag === this.tagSelected;
+    }
+    return true;
+  }
+}
diff --git a/src/app/utils/grammar-checker.ts b/src/app/utils/grammar-checker.ts
new file mode 100644
index 0000000000000000000000000000000000000000..760638023e4db051dedac29ea8e64db6943bb575
--- /dev/null
+++ b/src/app/utils/grammar-checker.ts
@@ -0,0 +1,179 @@
+import { Language, LanguagetoolResult, LanguagetoolService } from '../services/http/languagetool.service';
+import { CreateCommentKeywords } from './create-comment-keywords';
+
+export class GrammarChecker {
+
+  languages: Language[] = ['de-DE', 'en-US', 'fr', 'auto'];
+  selectedLang: Language = 'auto';
+  isSpellchecking = false;
+  hasSpellcheckConfidence = true;
+  newLang = 'auto';
+
+  private commentBody: () => HTMLDivElement;
+  private langSelect: () => HTMLSpanElement;
+
+  constructor(private languagetoolService: LanguagetoolService) {
+  }
+
+  initBehavior(commentBody: () => HTMLDivElement, langSelect: () => HTMLSpanElement) {
+    this.commentBody = commentBody;
+    this.langSelect = langSelect;
+  }
+
+  onDocumentClick(e) {
+    const container = document.getElementsByClassName('dropdownBlock');
+    Array.prototype.forEach.call(container, (elem) => {
+      const hasMarkup = (e.target as Node).parentElement ? (e.target as Node).parentElement.classList.contains('markUp') : false;
+      if (!elem.contains(e.target) && (!hasMarkup ||
+        (e.target as HTMLElement).dataset.id !== (elem as Node).parentElement.dataset.id)) {
+        (elem as HTMLElement).style.display = 'none';
+      }
+    });
+  }
+
+  maxLength(commentBody: HTMLDivElement, size: number): void {
+    if (commentBody.innerText.length > size) {
+      commentBody.innerText = commentBody.innerText.slice(0, size);
+    }
+    const body = commentBody.innerText;
+    if (body.length === 1 && body.charCodeAt(body.length - 1) === 10) {
+      commentBody.innerHTML = commentBody.innerHTML.replace('<br>', '');
+    }
+  }
+
+  onPaste(e) {
+    e.preventDefault();
+    const text = e.clipboardData.getData('text');
+    const selection = window.getSelection();
+    const min = Math.min(selection.anchorOffset, selection.focusOffset);
+    const max = Math.max(selection.anchorOffset, selection.focusOffset);
+    const content = selection.anchorNode.textContent;
+    selection.anchorNode.textContent = content.substring(0, min) + text + content.substr(max);
+    const range = document.createRange();
+    const elem = selection.anchorNode instanceof HTMLElement ? selection.anchorNode.lastChild : selection.anchorNode;
+    range.setStart(elem, min + text.length);
+    range.collapse(true);
+    selection.removeAllRanges();
+    selection.addRange(range);
+  }
+
+  grammarCheck(commentBody: HTMLDivElement): void {
+    this.onDocumentClick({
+      target: document
+    });
+    const wrongWords: string[] = [];
+    this.isSpellchecking = true;
+    this.hasSpellcheckConfidence = true;
+    const unfilteredText = commentBody.innerText;
+    const text = CreateCommentKeywords.cleaningFunction(commentBody.innerText, true);
+    this.checkSpellings(text).subscribe((wordsCheck) => {
+      if (!this.checkLanguageConfidence(wordsCheck)) {
+        this.hasSpellcheckConfidence = false;
+        return;
+      }
+      if (this.selectedLang === 'auto' && (this.langSelect().innerText.includes(this.newLang)
+        || this.langSelect().innerText.includes('auto'))) {
+        if (wordsCheck.language.name.includes('German')) {
+          this.selectedLang = 'de-DE';
+        } else if (wordsCheck.language.name.includes('English')) {
+          this.selectedLang = 'en-US';
+        } else if (wordsCheck.language.name.includes('French')) {
+          this.selectedLang = 'fr';
+        } else {
+          this.newLang = wordsCheck.language.name;
+        }
+        this.langSelect().innerHTML = this.newLang;
+      }
+      if (wordsCheck.matches.length <= 0) {
+        return;
+      }
+      wordsCheck.matches.forEach(grammarError => {
+        const wrongWord = text.slice(grammarError.offset, grammarError.offset + grammarError.length);
+        wrongWords.push(wrongWord);
+      });
+
+      let lastFound = unfilteredText.length;
+      this.checkSpellings(unfilteredText).subscribe((res) => {
+        commentBody.innerHTML = '';
+        for (let i = res.matches.length - 1; i >= 0; i--) {
+          const end = res.matches[i].offset + res.matches[i].length;
+          const start = res.matches[i].offset;
+          const wrongWord = unfilteredText.slice(start, end);
+
+          if (!wrongWords.includes(wrongWord)) {
+            continue;
+          }
+
+          if (lastFound > end) {
+            commentBody.prepend(unfilteredText.slice(end, lastFound));
+          }
+          commentBody.prepend(this.createSuggestionHTML(res, i, wrongWord));
+          lastFound = res.matches[i].offset;
+        }
+        if (lastFound > 0) {
+          commentBody.prepend(unfilteredText.slice(0, lastFound));
+        }
+      });
+    }, () => {
+      this.isSpellchecking = false;
+    }, () => {
+      this.isSpellchecking = false;
+    });
+  }
+
+  checkLanguageConfidence(wordsCheck: any) {
+    return this.selectedLang === 'auto' ? wordsCheck.language.detectedLanguage.confidence >= 0.5 : true;
+  }
+
+  checkSpellings(text: string, language: Language = this.selectedLang) {
+    return this.languagetoolService.checkSpellings(text, language);
+  }
+
+  private createSuggestionHTML(result: LanguagetoolResult, index: number, wrongWord: string) {
+    const markUpDiv = document.createElement('div');
+    markUpDiv.classList.add('markUp');
+    markUpDiv.dataset.id = String(index);
+    const wordMarker = document.createElement('span');
+    wordMarker.dataset.id = String(index);
+    wordMarker.append(wrongWord);
+    markUpDiv.append(wordMarker);
+    const dropDownDiv = document.createElement('div');
+    dropDownDiv.classList.add('dropdownBlock');
+    markUpDiv.append(dropDownDiv);
+    markUpDiv.addEventListener('click', () => {
+      dropDownDiv.style.display = 'block';
+      const rectdiv = this.commentBody().getBoundingClientRect();
+      const rectmarkup = markUpDiv.getBoundingClientRect();
+      let offset;
+      if (rectmarkup.x + rectmarkup.width / 2 > rectdiv.right - 80) {
+        offset = rectdiv.right - rectmarkup.x - rectmarkup.width;
+        dropDownDiv.style.right = -offset + 'px';
+      } else if (rectmarkup.x + rectmarkup.width / 2 < rectdiv.left + 80) {
+        offset = rectmarkup.x - rectdiv.left;
+        dropDownDiv.style.left = -offset + 'px';
+      } else {
+        dropDownDiv.style.left = '50%';
+        dropDownDiv.style.marginLeft = '-80px';
+      }
+    });
+    const suggestions = result.matches[index].replacements;
+    if (!suggestions.length) {
+      const elem = document.createElement('span');
+      elem.classList.add('error-message');
+      elem.append(result.matches[index].message);
+      dropDownDiv.append(elem);
+    } else {
+      const length = suggestions.length > 3 ? 3 : suggestions.length;
+      for (let j = 0; j < length; j++) {
+        const elem = document.createElement('span');
+        elem.classList.add('suggestions');
+        elem.append(suggestions[j].value);
+        elem.addEventListener('click', () => {
+          elem.parentElement.parentElement.outerHTML = suggestions[j].value;
+        });
+        dropDownDiv.append(elem);
+      }
+    }
+    return markUpDiv;
+  }
+}
diff --git a/src/app/utils/smart-debounce.ts b/src/app/utils/smart-debounce.ts
new file mode 100644
index 0000000000000000000000000000000000000000..718c7209c9af2eadb94b81ef39dc8c0720895439
--- /dev/null
+++ b/src/app/utils/smart-debounce.ts
@@ -0,0 +1,37 @@
+export class SmartDebounce {
+  private readonly minDelay: number;
+  private readonly maxDelay: number;
+  private debounceTimer;
+  private lastDebounceTime = new Date().getTime();
+  private minDebounceCount = 0;
+
+  constructor(minDelay: number, maxDelay: number) {
+    if (minDelay < 0) {
+      throw new Error('minDelay should be positive.');
+    } else if (maxDelay < minDelay) {
+      throw new Error('maxDelay should be greater than minDelay');
+    }
+    this.minDelay = minDelay;
+    this.maxDelay = maxDelay;
+  }
+
+  call(func: () => void) {
+    clearTimeout(this.debounceTimer);
+    const current = new Date().getTime();
+    const diff = current - this.lastDebounceTime;
+    const callFunc = () => {
+      this.lastDebounceTime = current;
+      this.minDebounceCount = 0;
+      func();
+    };
+    if (diff >= this.maxDelay) {
+      if (this.minDelay * this.minDebounceCount++ >= this.maxDelay) {
+        callFunc();
+      } else {
+        this.debounceTimer = setTimeout(callFunc, this.minDelay);
+      }
+    } else {
+      this.debounceTimer = setTimeout(callFunc, Math.max(this.minDelay, this.maxDelay - diff));
+    }
+  }
+}
diff --git a/src/assets/i18n/cookies/cookies-de.html b/src/assets/i18n/cookies/cookies-de.html
index bbd550b500d7ba8f5d764f03f338c97b4423ab5a..cc9656e839d7a89c5ce382c26eac921d939f5cb8 100644
--- a/src/assets/i18n/cookies/cookies-de.html
+++ b/src/assets/i18n/cookies/cookies-de.html
@@ -6,7 +6,7 @@
 <p tabindex="0">
   Ohne Registrierung kannst du deine Sitzung nur in dem Browser aufrufen,
   wo du sie erstellt oder besucht hast.
-  Löscht du die Browserdaten, werden auch deine Sitzungen gelöscht.
+  Löschst du die Browserdaten, werden auch deine Sitzungen gelöscht.
 </p>
 
 <p tabindex="0">
diff --git a/src/assets/i18n/creator/de.json b/src/assets/i18n/creator/de.json
index bce88114427daeed23b601785149904c4cbf0e27..0a7f82b310bc6a306b81a2fa8bc294a9b773ec95 100644
--- a/src/assets/i18n/creator/de.json
+++ b/src/assets/i18n/creator/de.json
@@ -61,7 +61,7 @@
     "vote-desc": "Absteigende Bewertungen",
     "wrong": "Fragen, die der Vortragende oder Moderator als falsch markiert hat",
     "switch-to-comment-list": "Zur öffentlichen Fragenliste",
-    "switch-to-moderation-list": "Zum Index",
+    "switch-to-moderation-list": "Zur Moderation",
     "select-time": "Zeitraum auswählen",
     "select-from-now": "Fragen ab jetzt anzeigen",
     "select-time-1h": "Letzte Stunde",
@@ -79,14 +79,23 @@
     "token": "Bonus-Token",
     "token-time": "Token-Zeitstempel",
     "no-comments": "Es sind noch keine Fragen vorhanden.",
-    "export-comments": "Fragen speichern"
+    "export-comments": "Fragen speichern",
+    "questions-blocked": "Neue Fragen deaktiviert"
   },
-  "spacy-dialog":{
-    "german": "Deutsch",
-    "english": "Englisch",
-    "french": "Französisch",
-    "empty-nouns": "Keine Nomen enthalten",
-    "select-all": "Alles auswählen"
+  "spacy-dialog": {
+    "auto": "auto",
+    "de": "Deutsch",
+    "en": "Englisch",
+    "fr": "Französisch",
+    "select-all": "Alles auswählen",
+    "lang-button-hint": "Sprache für die Rechtschreibprüfung",
+    "select-all-hint": "Alle Nomen als Stichwörter auswählen",
+    "select-keyword-hint": "Dieses Wort als Stichwort auswählen",
+    "edit-keyword-hint": "Wort editieren",
+    "editing-done-hint": "Editieren beenden",
+    "force-language-selection": "Die Sprache der Eingabe konnte nicht automatisch erkannt werden.",
+    "add-manually": "Gib ein Stichwort zu deiner Frage ein. Trenne mehrere Stichwörter mit einem Komma.",
+    "select-keywords": "Die Textanalyse schlägt folgende Stichwörter vor. Welche kennzeichnen deine Frage am besten?"
   },
   "comment-page": {
     "a11y-comment_delete": "Löscht diese Frage",
@@ -138,7 +147,7 @@
     "export-description": "Exportieren",
     "live-announcer": "Du befindest dich jetzt auf der Fragen-Seite. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
     "live-announcer-moderation": "Du befindest dich jetzt auf der Moderations-Seite. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
-    "Markdown-hint": "Formatiere mit Markdown",
+    "Markdown-hint": "Formatiere mit Markdown & KaTeX",
     "mark-correct": "Frage bejahen",
     "mark-favorite": "Frage für einen Bonus markieren",
     "mark-bookmark": "Lesezeichen setzen",
@@ -152,7 +161,7 @@
     "no-comments": "Keine Fragen zurzeit",
     "no-comments-with-filter": "Keine Fragen mit dem eingestellten Filter",
     "no-comments-with-search": "Keine Fragen mit deiner Suche",
-    "reject": "Frage auf den Index setzen",
+    "reject": "Frage in die Moderation verbannen",
     "search-box-input-description": "Hier kannst du nach Fragen suchen.",
     "semicolon": "CSV-Format (.csv)",
     "send": "Senden",
@@ -161,6 +170,8 @@
     "tag-reset": "Zurücksetzen",
     "tag-to-filter": "Klick auf die Fragekategorie, um Fragen dieser Kategorie zu filtern.",
     "user-number": "Klick auf die Nummer, um die Fragen dieses anonymen Fragenstellers zu filtern.",
+    "keywords-per-question": "Klick auf die Keywords, um die Keywords anzuzeigen die für die Frage hinterlegt wurden.",
+    "keywords": "Stichwörter",
     "vote-down": "Frage abwerten",
     "vote-up": "Frage aufwerten",
     "write-comment": "Eingabe",
@@ -177,8 +188,11 @@
     "edit-favorite": "Für einen Bonus markieren",
     "edit-favorite-reset": "Markierung zurücksetzen",
     "edit-bookmark": "Lesezeichen setzen",
-    "edit-bookmark-reset": "Markierung zurücksetzen"
-  },  
+    "edit-bookmark-reset": "Markierung zurücksetzen",
+    "grammar-check": "Rechtschreibprüfung",
+    "show-comment-with-filter": "Vulgäre Wörter ausixen",
+    "show-comment-without-filter": "Vulgäre Wörter anzeigen"
+  },
   "content": {
     "abort": "Abbrechen",
     "actions": "Option",
@@ -229,7 +243,7 @@
     "a11y-cloud_download": "Direktlink zur Sitzung in die Zwischenablage kopieren",
     "a11y-delete-all-comments": "Löscht alle Fragen.",
     "a11y-delete-moderator": "Löscht diesen Moderator.",
-    "a11y-delete-room" : "Löscht die angegebene Sitzung.",
+    "a11y-delete-room" : "Löscht den angegebenen Raum.",
     "a11y-edit": "Öffnet ein Fenster mit den Optionen, Sitzung umbenennen, Beschreibung hinzufügen und Sitzung löschen.",
     "a11y-export-comments": "Exportiert alle Fragen.",
     "a11y-gavel": "Öffnet  das Moderations-Board.",
@@ -245,31 +259,33 @@
     "abort": "Abbrechen",
     "answer": "Antwort",
     "answer-statistics": "Statistiken",
-    "bonus-token": "Vergebene Sterne",
-    "bonus-token-header": "Vergebene Sterne",
+    "bonus-token": "Bonus-Archiv",
+    "bonus-token-header": "Bonus-Archiv",
     "no-bonus": "Du hast bisher keine Frage mit einem Stern ausgezeichnet.",
     "cancel": "Abbrechen",
     "cancel-description": "Abbrechen",
     "changes-gone-wrong": "Etwas ist schief gelaufen!",
     "changes-successful": "Änderungen gespeichert.",
-    "comments": "Fragen",
+    "comments": "Öffentliche Fragen",
     "comments-deleted": "Alle Fragen wurden gelöscht.",
-    "copy-session-id": "Kopiere den Link zu dieser Sitzung in die Zwischenablage und gib ihn an die Sitzungsteilnehmer weiter.",
+    "copy-session-id": "Kopiert den Link zu diesem Raum in die Zwischenablage.",
     "create-content": "Frage stellen",
     "default-content-group": "Standard",
     "delete-all-comments": "Fragen löschen",
-    "delete-room": "Sitzung Löschen",
+    "delete-room": "Raum löschen",
     "delete-room-description": "Sitzung löschen",
     "deleted": " gelöscht.",
-    "description": "Beschreibung",
+    "description": "Begrüßungstext",
+    "tab1": "Text",
     "email-error": "E-Mail-Adresse ist ungültig.",
     "export-comments": "Fragen speichern",
     "no-comments": "Es sind noch keine Fragen vorhanden.",
     "general": "Sitzung",
     "live-announcer": "Du befindest dich jetzt in der Sitzung. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
     "live-feedback": "Live Feedback",
-    "Markdown-hint": "Formatiere mit Markdown",
-    "moderating-stream": "Index",
+    "Markdown-hint": "Formatiere mit Markdown & KaTeX",
+    "moderating-stream": "Moderation",
+    "moderation-mode": "Moderationsmodus",
     "moderator-added": "Moderator wurde hinzugefügt.",
     "moderator-email": "Mail-Adresse",
     "moderator-not-found": "Ein User mit der angegebenen Mail-Adresse konnte nicht gefunden werden. Bist du sicher, dass sich der User bei »frag.jetzt« mit dieser Adresse registriert hat?",
@@ -278,10 +294,10 @@
     "name-length-error": "Titel muss zwischen 3 und 20 Zeichen liegen.",
     "no-moderators": "",
     "present": "Präsentieren",
-    "public-stream": "Fragen",
-    "really-delete-comments": "Willst du wirklich alle Fragen dieser Sitzung löschen? Die Aktion kann nicht rückgängig gemacht werden.",
-    "really-delete-comments-hint": "Es gibt Fragen in dieser Sitzung, die du für einen Bonus markiert hast. Entferne die Markierungen, um alle Fragen zu löschen.",
-    "delete-comments-alt-header": "Sterne vergeben",
+    "public-stream": "Öffentliche Fragenliste",
+    "really-delete-comments": "Willst du wirklich alle Fragen in diesem Raum löschen? Die Aktion kann nicht rückgängig gemacht werden.",
+    "really-delete-comments-hint": "Es gibt Fragen in diesem Raum, die du für einen Bonus markiert hast. Entferne die Sterne, um alle Fragen zu löschen.",
+    "delete-comments-alt-header": "Achtung!",
     "really-remove-moderator": "Willst du folgenden Moderator wirklich entfernen?",
     "really2": " wirklich löschen? Die Aktion kann nicht rückgängig gemacht werden. Falls du Boni (Sterne) vergeben hast, exportiere alle Fragen, damit du eingereichte Bonus-Tokens überprüfen kannst.",
     "reallyContent": "Willst du die Frage ",
@@ -290,19 +306,20 @@
     "session-id": "Raum",
     "session-id-copied": "Direktlink wurde in die Zwischenablage kopiert.",
     "session-settings": "Sitzungsverwaltung",
-    "session-question-board": "Zur öffentlichen Frageliste",
-    "session-moderation-board": "Zum Index der verbannten Fragen",
+    "session-question-board": "Zur öffentlichen Fragenliste",
+    "session-moderation-board": "Zum Moderationsboard",
     "settings-comment-moderation": "Fragen moderieren",
     "settings-comment-moderation-description": "Du oder einer deiner Moderatoren können Fragen aus der Anzeige verbannen.",
-    "settings-direct-send": "Fragen unmoderiert veröffentlichen? ",
+    "settings-direct-send": "Alle Fragen moderieren",
     "settings-direct-send-description": "Jede Frage wird sofort veröffentlicht. Schalte diese Option ab, wenn du jede Frage einzeln freigeben willst.",
     "sure": "Bist du sicher?",
     "tag-new": "Neue Fragekategorie:",
     "tag-error": "Muss zwischen 3 und 30 Zeichen lang sein",
-    "tags": "Tags",
-    "threshold": "Schwellenwert für die Anzeige? ",
+    "tags": "Kategorien",
+    "threshold": "Schwellenwert",
     "threshold-description": "Lege den Schwellenwert fest, ab dem eine negativ bewertete Frage angezeigt werden soll.",
     "update": "Speichern",
+    "block" : "Fragenstellen sperren",
     "update-description": "Speichert die Änderungen",
     "question": "Frage",
     "favorite": "Favorit",
@@ -318,45 +335,188 @@
     "really-delete-tokens": "Willst du wirklich alle Tokens dieser Sitzung löschen?",
     "delete-all-tokens": "Alle Tokens löschen",
     "token-deleted": "Der Token wurde gelöscht.",
-    "tokens-deleted": "Alle Tokens dieser Sitzung wurden gelöscht."
+    "tokens-deleted": "Alle Tokens dieser Sitzung wurden gelöscht.",
+    "profanity-heading": "Vulgäre Ausdrücke",
+    "profanity-filter": "Vulgäre Ausdrücke zensieren",
+    "language-specific-filter": "Sprachspezifisch zensieren",
+    "partial-words-filter": "Auch Wortteile zensieren",
+    "words-will-be-overwritten": "Profane Wörter werden mit '***' überschrieben",
+    "only-specific-language-will-be-filtered": "Nur Vulgärausdrücke in der Sprache der Frage werden gefiltert",
+    "partial-words-will-be-filtered": "Vulgäre Teilwörter werden auch gefiltert",
+    "keyword-from-spacy": "Stichwort von spaCy",
+    "keyword-from-questioner": "Stichwort vom Fragensteller",
+    "hint": "Nach Token filtern"
   },
   "session": {
     "a11y-description": "Gib eine Beschreibung für die Sitzung ein.",
     "create-session": "Speichern",
-    "description": "Beschreibung",
+    "description": "Text",
     "max-ls": "Maximale Anzahl Zeichen:",
     "session-name": "Name der Sitzung",
     "preview": "Vorschau"
   },
-  "tag-cloud-config":{
-    "title":"Tag-Cloud Einstellungen",
-    "general":"Allgemeine Einstellungen",
-    "overflow":"Ãœberlauf",
-    "height":"Höhe",
-    "random-angle":"Zufallswinkel",
-    "realign":"Neu ausrichten",
-    "background":"Hintergrundfarbe",
-    "word-delay":"Wortverzögerung",
-    "hover-color":"Schriftfarbe",
-    "hover-scale":"Hover Skala",
-    "hover-time":"Hover Zeit",
-    "hover-title":"Hover Einstellungen",
-    "hover-delay":"Hover Verzögerung",
-    "cancel-btn":"Abbruch",
-    "save-btn":"Speichern",
-    "font-size-min":"Schriftgröße min",
-    "font-size-max":"Schriftgröße max",
+  "tag-cloud-popup": {
+    "few-seconds": "wenige Sekunden",
+    "few-minutes": "wenige Minuten",
+    "some-minutes": "{{minutes}} Minuten",
+    "one-hour": "1 Stunde",
+    "some-hours": "{{hours}} Stunden",
+    "one-day": "1 Tag",
+    "some-days": "{{days}} Tage",
+    "one-week": "1 Woche",
+    "some-weeks": "{{weeks}} Wochen",
+    "some-months": "{{months}} Monate",
+    "tag-correction-placeholder": "Korrektur…"
+  },
+  "topic-cloud-dialog": {
+    "cancel": "Abbrechen",
+    "save": "Speichern",
+    "edit": "Bearbeiten",
+    "delete": "Löschen",
+    "question-count-singular": "Frage",
+    "question-count-plural": "Fragen",
+    "edit-keyword-tip": "Neues Thema",
+    "no-keywords-note": "Es gibt keine Themen.",
+    "consider-votes": "Bewertungen der Fragen berücksichtigen",
+    "profanity": "Vulgäre Wörter mit »***« überschreiben",
+    "hide-blacklist-words": "Themen aus der Blacklist verbergen",
+    "sort-alpha": "Alphabetisch",
+    "sort-count": "Anzahl Fragen",
+    "sort-vote": "Anzahl Up-Votes",
+    "keyword-search": "Thema suchen …",
+    "edit-profanity-list": "Liste der Vulgärausdrücke bearbeiten",
+    "edit-blacklist-list": "Blacklist bearbeiten",
+    "add-word": "Wort hinzufügen",
+    "enter-word": "Wort eingeben",
+    "settings": "Einstellungen",
+    "keyword": "Stichwörter",
+    "full-text": "Volltext",
+    "both": "Beides",
+    "select-choice": "Wähle aus",
+    "show-blacklist": "Zeige Blacklist",
+    "hide-blacklist": "Verberge Blacklist",
+    "show-profanity-list": "Zeige Liste der Vulgärausdrücke",
+    "hide-profanity-list": "Verberge Liste der Vulgärausdrücke",
+    "keyword-delete": "Thema gelöscht",
+    "keyword-edit": "Thema umbenannt",
+    "keywords-merge": "Themen zusammengefügt",
+    "spacy-labels": "Welche Nomen aus der Textanalyse sollen angezeigt werden?",
+    "changes-gone-wrong": "Etwas ist schiefgelaufen",
+    "english": "Englisch",
+    "german": "Deutsch",
+    "select-all": "Alle auswählen",
+    "keyword-counter": "Anzahl Themen",
+    "sort": "Sortieren",
+    "language-specific-filter": "Sprachspezifisch zensieren",
+    "partial-words-filter": "Auch Teilwörter zensieren",
+    "words-will-be-overwritten": "Vulgäre Wörter mit »***« überschreiben",
+    "only-specific-language-will-be-filtered": "Nur Vulgärausdrücke in der Sprache der Frage filtern",
+    "partial-words-will-be-filtered": "Vulgäre Teilwörter auch filtern",
+    "keyword-from-spacy": "Stichwort aus der Textanalyse",
+    "keyword-from-questioner": "Stichwort vom Fragesteller",
+    "Keyword-from-both": "Stichwort vom Fragensteller und aus der Textanalyse",
+    "test-profanity": "Profanität testen",
+    "word": "Wort",
+    "word-is-profanity": "Wort ist profan",
+    "word-is-not-profanity": "Wort ist nicht profan",
+    "words-in-profanity": "Profane Wörter",
+    "language": "Sprache",
+    "preview": "Vorschau",
+    "topic-requirement-title": "Schwellenwerte für die Anzeige eines Themas",
+    "topic-requirement-questions": "Minimale Anzahl Fragen",
+    "topic-requirement-questioners": "Minimale Anzahl Fragensteller*innen",
+    "topic-requirement-upvotes": "Minimale Anzahl Up-Votes",
+    "topic-requirement-begin-datetime": "Beginn der Zeitspanne",
+    "topic-requirement-end-datetime": "Ende der Zeitspanne",
+    "keywords": "Stichwörter",
+    "blacklist-is-active": "Die Blacklist wird verborgen",
+    "blacklist-is-not-active": "Die Blacklist wird nicht verborgen",
+    "topic-requirement-reset": "Zurücksetzen"
+  },
+  "topic-cloud-confirm-dialog": {
+    "cancel": "Abbrechen",
+    "delete": "Löschen",
+    "merge": "Zusammenfügen",
+    "delete-message": "Willst du das Thema wirklich löschen?",
+    "merge-message": "Thema existiert bereits. Willst du die beiden Themen zusammenfügen?",
+    "confirm": "Bist du sicher?"
+  },
+  "dialog-comment": {
+    "read-more": "Mehr lesen",
+    "read-less": "Weniger lesen"
+  },
+  "tag-cloud": {
+    "demo-data-topic": "Thema %d",
+    "overview-question-topic-tooltip": "Anzahl Fragen mit diesem Thema",
+    "overview-questioners-topic-tooltip": "Anzahl Fragensteller*innen mit diesem Thema",
+    "period-since-first-comment":"Zeitraum seit der ersten Frage",
+    "upvote-topic": "Up-Votes für dieses Thema",
+    "downvote-topic": "Down-Votes für dieses Thema",
+    "blacklist-topic": "Thema auf die »Blacklist« setzen"
+  },
+  "tag-cloud-config": {
+    "general": "Allgemein",
+    "overflow": "Ãœberlauf",
+    "height": "Höhe",
+    "random-angle": "Themen drehen",
+    "realign": "Neu ausrichten",
+    "background": "Hintergrundfarbe",
+    "word-delay": "Themen verzögert anzeigen",
+    "hover-color": "Schriftfarbe",
+    "hover-scale": "Fokus vergrößern",
+    "hover-time": "Fokus animieren",
+    "hover-title": "Fokus",
+    "hover-delay": "Ansprechzeit",
+    "cancel-btn": "Abbruch",
+    "save-btn": "Speichern",
+    "font-size-min": "Schriftgröße minimal",
+    "font-size-max": "Schriftgröße maximal",
     "select-color": "Farbauswahl",
-
-    "random-angle-tooltip": "Anordnung der Winkel zufällig generieren",
+    "random-angle-tooltip": "Drehwinkel der Wörter zufällig generieren",
+    "random-angle-note": "Wenn aktiviert, wird die Wortdrehung in den Häufigkeitsgruppen deaktiviert",
     "background-tooltip": "Auswahl der Hintergrundfarbe",
-    "word-delay-tooltip": "Animationsverzögerung der Wörter",
-    "font-size-min-tooltip": "Auswahl der minimalen Schriftgrösse",
-    "font-size-max-tooltip": "Auswahl der maximalen Schriftgrösse",
+    "word-delay-tooltip": "Animationsverzögerung der Themen",
+    "font-size-min-tooltip": "Auswahl der minimalen Schriftgröße",
+    "font-size-max-tooltip": "Verhältnis maximaler zu minimaler Schriftgröße",
     "select-color-tooltip": "Auswahl der Schriftfarbe",
-    "hover-scale-tooltip": "Skallierung der Wörter beim Erscheinen",
-    "hover-time-tooltip": "Festlegen der Erscheinungszeit der Wörter",
-    "hover-delay-tooltip": "Verzögerung der Wörter beim Erscheinen"
-    
+    "hover-scale-tooltip": "Vergrößerungsfaktor des fokussierten Themas",
+    "hover-time-tooltip": "Langsames Vergrößern des fokussierten Themas",
+    "hover-delay-tooltip": "Zeit bis der Hover-Effekt eintritt",
+    "extended-btn": "Häufigkeitsgruppen",
+    "back-btn": "Zurück",
+    "weight-class-settings": "Häufigkeitsgruppen",
+    "weight-class": "Häufigkeitsgruppe",
+    "weight-color": "Schriftfarbe",
+    "weight-number": "max. Anzahl Themen",
+    "weight-color-tooltip": "Auswahl der Schriftfarbe",
+    "weight-number-tooltip": "maximale Anzahl Themen festlegen",
+    "notation": "Schreibweise der Themen",
+    "lowerCase": "Kleinschreibung",
+    "capitalization": "Wortbeginn groß",
+    "upperCase": "Großschreibung",
+    "standard": "wie vom User eingegeben",
+    "alphabetical-sorting": "Alphabetisch sortieren",
+    "cleanUpView": "Tag-Cleanup Einstellungen",
+    "rotation": "Drehgrad zufälliger Einträge",
+    "highestWeight": "Anzahl Themen mit maximaler Gewichtung",
+    "notation-tooltip": "Einstellung der Schreibweise: klein, groß, wie vorgegeben",
+    "alphabetical-sorting-tooltip": "Alphabetische Sortierung",
+    "highestWeight-tooltip": "x Themen mit der höchsten Gewichtung anzeigen",
+    "rotate-weight": "Themen dieser Häufigkeitsgruppe um x Grad drehen",
+    "rotate-weight-tooltip": "Themen dieser Häufigkeitsgruppe um x Grad drehen",
+    "font":"Schrift",
+    "reset-btn": "Auf Standardwerte setzen",
+    "font-family-tooltip": "Schrift auswählen …",
+    "bold-notation-tooltip": "Schrift fett setzen",
+    "font-style-bold" : "Fette Schrift",
+    "font-family":"Schriftart",
+    "manual-weight-number": "Anzahl Themen beschränken",
+    "manual-weight-number-tooltip": "Anzahl Themen der Häufigkeitsgruppe",
+    "manual-weight-number-note": "Begrenzt die Anzahl Themen einer Häufigkeitsgruppe auf den eingestellten Wert"
+  },
+  "token-validator": {
+    "valid": "VALID",
+    "invalid": "INVALID",
+    "cant-find-comment": "Die Frage kann nicht gefunden werden"
   }
 }
diff --git a/src/assets/i18n/creator/en.json b/src/assets/i18n/creator/en.json
index d2f23d6a75882b6874f22d9cb24787eb3f08235e..06fb9f2881a6c927472b090c7099aa36f9a787e3 100644
--- a/src/assets/i18n/creator/en.json
+++ b/src/assets/i18n/creator/en.json
@@ -80,14 +80,23 @@
     "token": "Bonus token",
     "token-time": "Token timestamp",
     "no-comments": "There are no questions yet.",
-    "export-comments": "Save questions"
+    "export-comments": "Save questions",
+    "questions-blocked": "New questions blocked"
   },
   "spacy-dialog": {
-    "german": "German",
-    "english": "English",
-    "french": "French",
-    "empty-nouns": "No nouns included",
-    "select-all": "Select all"
+    "auto": "auto",
+    "de": "German",
+    "en": "English",
+    "fr": "French",
+    "select-all": "Select all",
+    "lang-button-hint": "Language for the spell checker",
+    "select-all-hint": "Select all keywords",
+    "select-keyword-hint": "Select this keyword",
+    "edit-keyword-hint": "Edit keyword",
+    "editing-done-hint": "Finish editing",
+    "force-language-selection": "The language of the text input could not be detected automatically.",
+    "add-manually": "Enter a keyword for your question. Separate several keywords with a comma.",
+    "select-keywords": "The text analysis suggests the following keywords. Which best characterise your question?"
   },
   "comment-page": {
     "a11y-comment_delete": "Deletes this question",
@@ -139,7 +148,7 @@
     "export-description": "Export",
     "live-announcer": "You are now on the questions page. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
     "live-announcer-moderation": "You are now on the moderation page. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
-    "Markdown-hint": "Format with Markdown",
+    "Markdown-hint": "Format with Markdown & KaTeX",
     "mark-correct": "Mark as correct",
     "mark-favorite": "Mark for bonus",
     "mark-bookmark": "Bookmark",
@@ -153,7 +162,7 @@
     "no-comments": "No questions at present",
     "no-comments-with-filter": "No questions with selected filter settings",
     "no-comments-with-search": "No questions with your search",
-    "reject": "Put the question on the index",
+    "reject": "Ban the question to moderation",
     "search-box-input-description": "Search for questions",
     "semicolon": "CSV format (.csv)",
     "send": "Send",
@@ -162,6 +171,8 @@
     "tag-reset": "Reset",
     "tag-to-filter": "Click on the question category to filter questions in that category.",
     "user-number": "Click on the number to filter the questions from this anonymous questioner.",
+    "keywords-per-question": "Click to display the keywords that have been entered for the question.",
+    "keywords": "Keywords",
     "vote-down": "Vote down",
     "vote-up": "Vote up",
     "write-comment": "Input",
@@ -178,15 +189,18 @@
     "edit-favorite": "Mark for bonus",
     "edit-favorite-reset": "Remove marker",
     "edit-bookmark": "Bookmark",
-    "edit-bookmark-reset": "Remove marker"
+    "edit-bookmark-reset": "Remove marker",
+    "grammar-check": "Spell check",
+    "show-comment-with-filter": "Hide vulgar words",
+    "show-comment-without-filter": "Show vulgar words"
   },
   "content": {
     "abort": "Abort",
     "actions": "Option",
     "add-answer": "Add answer",
     "answer": "Answer",
-    "answer-deleted": "Answer deleted.",
-    "answer-recovered": "Answer recovered.",
+    "answer-deleted": "Answer deleted",
+    "answer-recovered": "Answer recovered",
     "answers": "Answers",
     "at-least-one": "In multiple choice mode you have to select at least 1 true answer.",
     "body": "Body",
@@ -230,8 +244,8 @@
     "a11y-cloud_download": "Copy link to session to the clipboard",
     "a11y-delete-all-comments": "Deletes all questions",
     "a11y-delete-moderator": "Delete this Moderator",
-    "a11y-delete-room": "Deletes the entered session",
-    "a11y-edit": "Opens a window with options, rename session, add description and delete session",
+    "a11y-delete-room": "Deletes the entered room",
+    "a11y-edit": "Opens a window with options, rename room, add description and delete room",
     "a11y-export-comments": "Exports all questions",
     "a11y-gavel": "Opens all questions selected by the moderator",
     "a11y-insert_comment": "Opens a window to manage questions",
@@ -253,24 +267,26 @@
     "cancel-description": "Cancel",
     "changes-gone-wrong": "Something went wrong!",
     "changes-successful": "Successfully updated.",
-    "comments": "Questions",
+    "comments": "Public questions",
     "comments-deleted": "All questions have been deleted.",
     "copy-session-id": "Copy the link to this session to the clipboard and pass it on to the session participants.",
     "create-content": "Create content",
     "default-content-group": "Default",
     "delete-all-comments": "Delete questions",
-    "delete-room": "Delete session",
+    "delete-room": "Delete room",
     "delete-room-description": "Delete session",
     "deleted": " deleted.",
-    "description": "Description",
+    "description": "Welcome text",
+    "tab1": "Text",
     "email-error": "E-Mail is invalid.",
     "export-comments": "Save questions",
     "no-comments": "There are no questions yet.",
     "general": "Session",
     "live-announcer": "You're in the session now. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
     "live-feedback": "Live feedback",
-    "Markdown-hint": "Format with Markdown",
-    "moderating-stream": "Index",
+    "Markdown-hint": "Format with Markdown & KaTeX",
+    "moderating-stream": "Moderation",
+    "moderation-mode": "Moderation mode",
     "moderator-added": "Moderator was added.",
     "moderator-email": "Mail address",
     "moderator-not-found": "A user with the entered mail address could not be found. Are you sure that the user has registered at »frag.jetzt« with this address?",
@@ -280,9 +296,9 @@
     "no-moderators": "No moderators yet",
     "present": "Present",
     "public-stream": "Questions",
-    "really-delete-comments": "Do you really want to delete all questions of this session? This action cannot be undone.",
-    "really-delete-comments-hint": "There are questions in this session that you marked for a bonus. Remove the stars to delete all questions.",
-    "delete-comments-alt-header": "Bonus tokens awarded",
+    "really-delete-comments": "Do you really want to delete all questions in this room? This action cannot be undone.",
+    "really-delete-comments-hint": "There are questions in this room that you marked for a bonus. Remove the stars to delete all questions.",
+    "delete-comments-alt-header": "Attention!",
     "really-remove-moderator": "Do you really want to remove the following moderator?",
     "really2": "? This action cannot be undone. If you have given bonus stars, export all questions so that you can check submitted bonus tokens.",
     "reallyContent": "Do you really want to delete content ",
@@ -292,18 +308,19 @@
     "session-id-copied": "Session link was copied to the clipboard.",
     "session-settings": "Session administration",
     "session-question-board": "To the public question list",
-    "session-moderation-board": "To the index of banned questions",
+    "session-moderation-board": "To the moderation board",
     "settings-comment-moderation": "Moderate questions",
     "settings-comment-moderation-description": "You or one of your moderators can ban questions from the display.",
-    "settings-direct-send": "Publish questions unmoderated? ",
+    "settings-direct-send": "Moderate all questions",
     "settings-direct-send-description": "Every question is published immediately. Disable this option if you want to publish each question individually.",
     "sure": "Are you sure?",
     "tag-new": "New question tag:",
     "tag-error": "Must be between 3 and 30 characters long",
     "tags": "Tags",
-    "threshold": "Threshold value for display? ",
+    "threshold": "Threshold value",
     "threshold-description": "Set the threshold value above which a negatively rated question should be displayed.",
     "update": "Save",
+    "block" : "Block questions",
     "update-description": "Save changes",
     "question": "Question",
     "favorite": "Favorite",
@@ -319,7 +336,15 @@
     "really-delete-tokens": "Do you really want to delete all tokens of this session?",
     "delete-all-tokens": "Delete all tokens",
     "token-deleted": "Token has been deleted.",
-    "tokens-deleted": "All tokens of this sessions have been deleted."
+    "tokens-deleted": "All tokens of this sessions have been deleted.",
+    "profanity-heading": "Profanity filter",
+    "profanity-filter": "Activate profanity filter",
+    "language-specific-filter": "Filter language specific",
+    "partial-words-filter": "Filter also parts of words",
+    "words-will-be-overwritten": "Profane words will be overwritten with '***'",
+    "only-specific-language-will-be-filtered": "Only the language of the question will be filtered",
+    "partial-words-will-be-filtered": "Profane partial words will be also filtered",
+    "hint": "Filter by token"
   },
   "session": {
     "a11y-description": "Enter a description of the session",
@@ -329,9 +354,107 @@
     "session-name": "Session name",
     "preview": "Preview"
   },
+  "tag-cloud": {
+    "demo-data-topic": "Topic %d",
+    "overview-question-topic-tooltip": "Number of questions with this topic",
+    "overview-questioners-topic-tooltip": "Number of questioners with this topic",
+    "period-since-first-comment":"Period since first comment",
+    "upvote-topic": "Upvotes for this topic",
+    "downvote-topic": "Downvotes for this topic",
+    "blacklist-topic": "Add topic to blacklist"
+  },
+  "tag-cloud-popup": {
+    "few-seconds": "few seconds",
+    "few-minutes": "few minutes",
+    "some-minutes": "{{minutes}} minutes",
+    "one-hour": "1 hour",
+    "some-hours": "{{hours}} hours",
+    "one-day": "1 day",
+    "some-days": "{{days}} days",
+    "one-week": "1 week",
+    "some-weeks": "{{weeks}} weeks",
+    "some-months": "{{months}} months",
+    "tag-correction-placeholder": "Correction"
+  },
+  "topic-cloud-dialog":{
+    "edit": "Edit",
+    "delete": "Delete",
+    "cancel": "Cancel",
+    "save": "Save",
+    "question-count-singular": "Question",
+    "question-count-plural": "Questions",
+    "edit-keyword-tip": "New topic",
+    "no-keywords-note": "There are no topics.",
+    "consider-votes": "Consider Votes",
+    "profanity": "Censor profanity",
+    "hide-blacklist-words": "Hide blacklist keywords",
+    "sort-alpha": "Alphabetically",
+    "sort-count": "Questions count",
+    "sort-vote": "Votes",
+    "keyword-search": "Search keyword",
+    "edit-profanity-list": "Edit profanity list",
+    "edit-blacklist-list": "Edit blacklist list",
+    "add-word": "Add Word",
+    "enter-word": "Enter word",
+    "settings": "Settings",
+    "keyword": "Keyword",
+    "full-text": "Full-text",
+    "both": "Both",
+    "select-choice": "Select one",
+    "show-blacklist": "Show blacklist",
+    "hide-blacklist": "Hide blacklist",
+    "show-profanity-list": "Show profanity list",
+    "hide-profanity-list": "Hide profanity list",
+    "keyword-delete": "keyword deleted",
+    "keyword-edit": "keyword renamed",
+    "keywords-merge": "keywords merged",
+    "spacy-labels": "Which nouns of the text analysis should be displayed as topics?",
+    "changes-gone-wrong": "somthing has gone wrong",
+    "english": "English",
+    "german": "German",
+    "select-all": "Select all",
+    "keyword-counter": "Topic count",
+    "sort": "Sort",
+    "language-specific-filter": "Filter language-specific",
+    "partial-words-filter": "Filter partial words",
+    "words-will-be-overwritten": "profane words will be overwritten with '***'",
+    "only-specific-language-will-be-filtered": "Only the language of the question will be filtered",
+    "partial-words-will-be-filtered": "Profane partial words will be also filtered",
+    "keyword-from-spacy": "Keyword from spaCy",
+    "keyword-from-questioner": "Keyword from questioner",
+    "Keyword-from-both": "Keyword from questioner and spaCy",
+    "test-profanity": "Test profanity",
+    "word": "word",
+    "word-is-profanity": "Word is profane",
+    "word-is-not-profanity": "Word is not profane",
+    "words-in-profanity": "Words in profanity filter",
+    "language": "Language",
+    "preview": "Preview",
+    "topic-requirement-title": "Topic requirement",
+    "topic-requirement-questions": "Minimum number of questions",
+    "topic-requirement-questioners": "Minimum number of questioners",
+    "topic-requirement-upvotes": "Minimum number of upvotes",
+    "topic-requirement-begin-datetime": "Earliest comment",
+    "topic-requirement-end-datetime": "Last comment",
+    "keywords": "Keywords",
+    "blacklist-is-active": "The blacklist is hidden",
+    "blacklist-is-not-active": "The blacklist is not hidden",
+    "topic-requirement-reset": "Reset"
+  },
+  "topic-cloud-confirm-dialog":{
+    "cancel": "Cancel",
+    "delete": "Delete",
+    "merge": "Merge",
+    "delete-message": "Do you really want to delete the topic",
+    "merge-message": "Keyword already exists, do you want to merge both keywords",
+    "confirm": "Are you sure?"
+  },
+  "dialog-comment": {
+    "read-more": "read more",
+    "read-less": "read less"
+  },
   "tag-cloud-config":{
-    "title":"Tag-Cloud Options",
-    "general":"General Options",
+    "general":"General",
     "overflow":"Overflow",
     "height":"Height",
     "random-angle":"Randomize angle",
@@ -341,23 +464,57 @@
     "hover-color":"Font-color",
     "hover-scale":"Scale",
     "hover-time":"Hover time",
-    "hover-title":"Hover Options",
+    "hover-title":"Hover",
     "hover-delay":"Hover delay",
     "cancel-btn":"Cancel",
     "save-btn":"Save",
     "font-size-min":"Font size min",
     "font-size-max":"Font size max",
     "select-color": "Selected color",
-
     "random-angle-tooltip": "Generate angle randomly",
+    "random-angle-note": "If Enabled, the rotation of the individual weight-class is disabled",
     "background-tooltip": "Select background-color",
     "word-delay-tooltip": "Select word-delay",
     "font-size-min-tooltip": "Select minimum font-size",
-    "font-size-max-tooltip": "Select maximum font-size",
+    "font-size-max-tooltip": "Size ratio max. / min. font size",
     "select-color-tooltip": "Select font-color",
     "hover-scale-tooltip": "Select hover-scale",
     "hover-time-tooltip": "Select hover-time",
-    "hover-delay-tooltip": "Select hover-delay"
-    
+    "hover-delay-tooltip": "Select hover-delay",
+    "weight-class-settings": "Weight-classes",
+    "weight-class": "Weight-class",
+    "back-btn": "Back",
+    "weight-color": "Font color",
+    "weight-number": "max. number of keywords",
+    "weight-color-tooltip": "Select font-color",
+    "weight-number-tooltip": "Select maximal number of keywords",
+    "notation": "Notation:",
+    "lowerCase": "Lower case",
+    "capitalization": "Capitalization",
+    "upperCase": "Upper Case",
+    "standard": "Standard",
+    "alphabetical-sorting": "Alphabetical sorting",
+    "cleanUpView": "Tag-Cleanup Settings",
+    "rotation": "rotation of random entries",
+    "highestWeight": "Number of tags with highest weight",
+    "notation-tooltip": "Notation-Settings: small, large, standard",
+    "alphabetical-sorting-tooltip": "Alphabetical sorting",
+    "highestWeight-tooltip": "show x tags with the highest weight",
+    "rotate-weight": "Rotate all entries of this class by x degrees",
+    "rotate-weight-tooltip": "Rotate all entries of this class by x degrees",
+    "font":"Font",
+    "reset-btn": "Reset",
+    "font-family-tooltip": "Select font",
+    "bold-notation-tooltip": "Select font-thickness bold",
+    "font-style-bold" : "Bold",
+    "font-family":"Font Family",
+    "manual-weight-number": "Set quantity",
+    "manual-weight-number-tooltip": "Quantity Limitation of this weight class",
+    "manual-weight-number-note": "Limits the respective weight class to a self-defined value"
+  },
+  "token-validator": {
+    "valid": "VALID",
+    "invalid": "INVALID",
+    "cant-find-comment": "Can't find comment"
   }
 }
diff --git a/src/assets/i18n/demo/demo-de.html b/src/assets/i18n/demo/demo-de.html
index b378351d893f4b1f1d4402554ae91373224c6e6d..908c88f483dbd4141f27a990f9408f1c2fa48ebe 100644
--- a/src/assets/i18n/demo/demo-de.html
+++ b/src/assets/i18n/demo/demo-de.html
@@ -1,4 +1,4 @@
-<h2 tabindex="0">»Haben Sie Fragen?«</h2>
+<h2 tabindex="0">»Noch Fragen?«</h2>
 
 <img tabindex="-1"
      src="/assets/background/auditorium.webp"
@@ -70,8 +70,30 @@
     Kategorisierte Fragen können durch Klicken des »Tags« gefiltert werden.
     Das Tagging ermöglicht es dem Moderator einer Podiumsdiskussion,
     die Fragen aus dem Publikum nach Themen oder Adressaten zu filtern:
-    Tag »Frage an Herrn Scholz«, Tag »Frage an Herrn Söder« …
+    Tag »Frage an Herrn Scholz«, Tag »Frage an Frau Baerbock« …
   </p>
+
+  <p>
+    <strong>Fragen KI-gestützt analysieren</strong><br><br>
+    Mittels NLP (Natural Language Processing) werden alle Fragen grammatikalisch analysiert.
+    Die erkannten Nomen werden in ihre Grundform gebracht (lemmatisiert)
+    und dem Fragensteller als Stichwörter vorgeschlagen.
+    Wir verwenden die NLP-Software
+    <a class="info"
+       href="https://spacy.io/"
+       target="_blank"
+       rel="noreferrer">»spaCy«
+      <span>Öffnet neue Seite</span>
+    </a>.
+    Aus den analysierten oder den selbst vergebenen Stichwörtern kann eine Wortwolke erzeugt werden,
+    in »frag.jetzt« als Themenwolke bezeichnet.
+    Sie visualisiert die Häufigkeit der Stichwörter:
+    Je größer die Schrift, desto mehr Fragen beziehen sich auf das Stichwort.
+    Auch die Bewertung der Fragen geht in die Schriftgröße mit ein.
+    Die Themenwolke fungiert zugleich als Navigator zu allen Fragen eines ausgewählten Stichwortes:
+    Klickt man auf ein Wort in der Wolke, gelangt man zu den Fragen mit diesem  Stichwort.
+  </p>
+
   <p>
     <strong>Fragen fokussiert präsentieren</strong><br><br>
     Für die Besprechung der Fragen am Beamer können diese einzeln in Vollansicht präsentiert werden.
@@ -79,10 +101,10 @@
     Man kann die Anzeige auch im »Kiosk-Modus« schalten:
     Dann werden eingehende neue Fragen automatisch in Vollansicht gezeigt.
     Der Wechsel zur nächsten Frage wird verzögert, um das Lesen zu ermöglichen.
-    Auf der Frageliste können laufend neue Fragen oder Bewertungen das Lesen und Präsentieren erschweren, da sich die Positionen der Fragen ändern.
+    Auf der Fragenliste können laufend neue Fragen oder Bewertungen das Lesen und Präsentieren erschweren, da sich die Positionen der Fragen ändern.
     Mit dem Pause-Icon kann der Fragenstrom eingefroren werden.
     Neue Fragen oder Bewertungen sind aber weiterhin möglich.
-    Klickt der Vortragende auf eine Frage in der Frageliste, erscheint diese in Vollansicht.
+    Klickt der Vortragende auf eine Frage in der Fragenliste, erscheint diese in Vollansicht.
     Gleichzeitig blitzt die Frage auf den Endgeräten aller Teilnehmenden auf, um deren Aufmerksamkeit zu bekommen.
   </p>
   <p>
@@ -140,12 +162,6 @@
     Aber bis dahin werden hunderte Informatikstudierende der THM engagiert und kontinuierlich an allen Aspekten der Software-Entwicklung
     (User Experience, Hochverfügbarkeit und Sicherheit) weiter arbeiten  – nicht für Geld, sondern Credit Points und gute Noten.
   </p>
-  <p>
-    <strong>Ausblick</strong><br><br>
-    Wir werden in nächster Zeit »frag.jetzt« in das freie Video-Konferenzsystem »Big&shy;Blue&shy;Button« (BBB) als Plugin integrieren.
-    So werden wir alle Vorteile unserer Feedback-App in BBB anbieten können, ohne zwischen den Browser-Tabs wechseln zu müssen.
-    Stay tuned!
-  </p>
 </div>
 
 <h2 tabindex="0">Studierende online aktivieren</h2>
@@ -211,170 +227,6 @@
   </ol>
 </div>
 
-<h2 tabindex=0>Icons und Buttons</h2>
-
-<img tabindex=-1 src="/assets/images/poster.webp"
-     class="screenshot"
-     width="850"
-     height="1200"
-     alt="Info-Poster zu frag.jetzt">
-
-<h2 tabindex="0">Frageliste aus Teilnehmersicht</h2>
-
-<img tabindex=-1 src="/assets/images/participant.webp"
-     class="screenshot"
-     width="400"
-     height="805"
-     alt="Screenshot einer Frage">
-
-<p tabindex="0">Kopfleiste des Fra&shy;gen&shy;boards</p>
-<ol tabindex="0">
-  <li>Zurück zur vorherigen Seite</li>
-  <li>Sitzung wird moderiert</li>
-  <li>QR-Code der Sitzung</li>
-  <li>Besuchte Sitzungen und erhaltene Sterne</li>
-</ol>
-
-<p tabindex="0">Werkzeugleiste des Fra&shy;gen&shy;boards</p>
-<ol tabindex="0">
-  <li>Anzahl eingegangener Fragen</li>
-  <li>Fragenliste durchsuchen</li>
-  <li>Fragen sortieren</li>
-  <li>Fragen filtern</li>
-  <li>Fragenstrom anhalten</li>
-  <li>Frage stellen</li>
-</ol>
-
-<p tabindex="0">Obere Werkzeugleiste einer Fragekarte</p>
-<ol tabindex="0">
-  <li>Zeitstempel der Frage</li>
-  <li>Dozent hat die Frage besprochen (Beamer-Icon)</li>
-  <li>Dozent hat die Frage kommentiert</li>
-  <li>Dozent hat die Frage bejaht</li>
-  <li>Die Frage wurde vom Dozenten oder Moderator mit einem Stern ausgezeichnet</li>
-</ol>
-
-<p tabindex="0">Untere Werkzeugleiste einer Fragekarte</p>
-<ol tabindex="0">
-  <li>Fragen nach der Kategorie (Tag-Icon) filtern</li>
-  <li>Fragen einer bestimmten Person (User-Icon) filtern</li>
-</ol>
-
-
-<h2 tabindex="0">Sitzungsverwaltung aus Dozentensicht</h2>
-
-<img tabindex=-1 src="/assets/images/lecturer.webp"
-     class="screenshot"
-     width="800"
-     height="600"
-     alt="Screenshot der Optionen für die Sitzungsverwaltung">
-
-<p tabindex="0">Mit einem Klick auf das Zahnrad-Icon öffnest du die Verwaltungs&shy;optionen:</p>
-<ol tabindex="0">
-  <li>Sitzung: Hier kannst du den Namen der Sitzung ändern und eine Beschreibung hinzufügen.
-      Für die Textformatierung steht dir <a class="info" href="https://de.wikipedia.org/wiki/Markdown" target="_blank">Markdown<span>Öffnet neue Seite</span></a> zur Verfügung.
-    Hier ist auch der Ort, um die Sitzung mit allen Fragen und Bewertungen zu löschen.
-  </li>
-  <li>Fragen: Du kannst einen Schwellenwert für die Veröffentlichung einer Frage festlegen,
-    das heißt, ab welcher negativen Bewertung eine Frage angezeigt wird. Der Wert liegt zwischen -100 und 0.
-
-    Weiterhin legst du fest, ob neue Fragen vor der Moderation sofort angezeigt werden sollen.
-
-    Hier ist auch der Ort, um alle Fragen mit ihren Bewertungen in eine Excel-Tabelle zu exportieren.
-
-    Ferner kannst du alle Fragen löschen, um die Sitzung aufs Neue zu verwenden.
-  </li>
-  <li>Moderatoren: Als Moderatoren können registrierte User aufgenommen werden.
-    Dazu benötigst du deren Mailadresse, mit der er oder sie sich registriert hat.
-  </li>
-  <li>Tokens für Bonus-Sterne: Wenn du eine Frage mit einem Stern auszeichnest,
-    wird ein 8-ziffriger Code (»Token«) für die Frage generiert und hier gelistet.
-    Der Autor der Frage findet den Token in seinem Konto und kann damit den Bonus bei dir einlösen.
-  </li>
-  <li>Tags: Hier kannst du sitzungsspezifische Kategorien festlegen (»Tags«), die deine Zuhörer zum Verschlagworten
-    (»Taggen«) ihrer Fragen verwenden können.
-    Der Tag erscheint dann bei der jeweiligen Frage.
-    Mit einem Klick darauf, werden alle Fragen mit diesem Tag gefiltert.
-  </li>
-</ol>
-
-<h2 tabindex="0">Rollenkonzept von »frag.jetzt«</h2>
-
-<div class="video">
-  <div class="videoWrapper">
-    <iframe tabindex="0"
-            width="560" height="315"
-            src="https://www.youtube.com/embed/qHRC6z9VtWs?autoplay=0" frameborder="0"
-            allowfullscreen
-    ></iframe>
-  </div>
-</div>
-
-<div id="demoContentTranscript" class="overflow_hide" tabindex="2">
-  <h2>Willkommen zur Demo von frag.jetzt!</h2>
-
-
-  <p>Mein Name ist Klaus Quibeldey-Cirkel. Ich bin Informatik-Professor an der Technischen Hochschule Mittelhessen und
-    Projektleiter von frag.jetzt.
-    Im Impressum der App finden Sie eine detaillierte Beschreibung des Projekts.</p>
-
-  <p>Nun zur Demo:
-    In frag.jetzt gibt es drei Rollen: die Lehrperson, die Studentin oder den Studenten und die Moderatorin oder den
-    Moderator.
-    Entsprechend sehen Sie drei Browser, in denen ich in in der jeweiligen Rolle das Nutzungs-Szenario von frag.jetzt
-    demonstrieren werde.</p>
-
-  <p>Eine Sitzung erstellen Sie mit einem Klick auf den Plus-Button.
-    Sie geben Ihrer Sitzung eine Bezeichnung
-    und das war es auch schon!
-    Ihren Studierenden teilen Sie den Raum-Code oder den Link der Sitzung mit.</p>
-
-
-  <p>Als Student gebe ich nun den Raum-Code ein oder den Link zur Sitzung.
-    Ich könnte sofort eine Frage stellen. Aber zunächst möchte ich den Moderator des Fragen-Boards ins Spiel bringen:
-    Dazu gehe ich in meine Sitzung, rufe die Einstellungen auf und dort den Menüpunkt „Fragen“.</p>
-
-
-  <p>Standardmäßig ist die Moderation aktiviert und alle Fragen der Studierenden werden direkt veröffentlicht.
-    Wenn die Freigabe einer Frage durch den Moderator erfolgen soll, ist der entsprechende Schalter umzulegen.
-    Mit dem Schwellenwert-Schalter kann ich bestimmen, ab welcher negativen Bewertung Fragen überhaupt angezeigt
-    werden
-    sollen.
-    Nun muss ich noch einen Moderator in meine Sitzung aufnehmen:
-    Dazu trage ich seine Mailadresse ein, mit der er sich bei frag.jetzt registriert hat.
-    Ich melde mich nun als Moderator an der App an und gehe in die zu moderierende Sitzung.
-    In der Vorlesung gehe ich auf das Fragen-Board der Sitzung in der Rolle des Moderators
-    und in der Rolle des Dozenten und warte auf Fragen seitens der Studierenden.
-    Als Moderator kann ich unerwünschte oder nicht zielführende Fragen vom Fragen-Board verbannen.
-    Ich könnte auch geschlossene Fragen (auf die ich mit Ja oder Nein antworten kann) mit den entsprechenden Icons
-    auszeichnen
-    und besonders interessante Fragen mit einem Stern hervorheben.
-    Alle Teilnehmerinnen und Teilnehmer sehen diese Bewertungen.</p>
-
-  <p>Als Dozent kann ich die von den Studierenden mehrheitlich hoch bewerteten Fragen am Ende der Vorlesung
-    besprechen.
-    Dazu klicke ich auf die Frage.
-    Diese wird in Vollansicht am Beamer angezeigt und in den Browsern der Teilnehmenden optisch hervorgehoben.
-    Ein Moderator kann Fragen nur vom Fragen-Board verbannen, nicht aber löschen. Das kann nur der Dozent.</p>
-
-  <p>Alle weiteren Funktionen, wie das Sortieren und Filtern von Fragen oder das Anhalten des Fragen-Streams,
-    können Sie spielerisch herausfinden, indem Sie selbst zwei oder drei Browser auf Ihrem Laptop nebeneinander
-    stellen
-    und das Nutzungs-Szenario in verschiedenen Rollen durchspielen.
-    Wie Sie frag.jetzt in Ihrer Vorlesung oder in Ihrem Kurs über das Semester einsetzen können, beschreibe ich weiter
-    unten.</p>
-
-  <p>Ich danke Ihnen für Ihr Interesse an frag.jetzt und freue mich über Ihr Feedback. Meine Mailadresse finden Sie im
-    Impressum.</p>
-</div>
-
-<h2 tabindex="0">Feedback an die Entwickler</h2>
-
-<p tabindex="0">
-  Gehe in den Raum »Feedback« für Fragen, Anregungen, Lob und Kritik.
-    Weitere Informationen findest du im <a class="info" href="https://arsnova.thm.de/blog/frag-jetzt/" target="_blank">ARSnova-Blog<span>Öffnet neue Seite</span></a>.
-</p>
-
 <h2 tabindex="0">Screen Reader und »Gender«-gerechte Sprache</h2>
 
 <p tabindex="0">
diff --git a/src/assets/i18n/demo/demo-en.html b/src/assets/i18n/demo/demo-en.html
index 67412b85ef807784d5eaa283cb59092f28213a2e..5a98007180816fffb174cda34545f77544b6bbf7 100644
--- a/src/assets/i18n/demo/demo-en.html
+++ b/src/assets/i18n/demo/demo-en.html
@@ -84,6 +84,27 @@
        For example, tagging allows the moderator of a panel discussion to filter questions from the audience by topic or addressee:
        tag »Question to Mr. Biden«, tag »Question to Mr. Trump« …
   </p>
+  <p>
+    <strong>Analyzing questions with AI support</strong><br><br>
+                                                              Using NLP (Natural Language Processing), all questions are grammatically analyzed.
+                                                              The recognized nouns are brought into their basic form (lemmatized)
+                                                              and suggested to the questioner as keywords.
+                                                              We use the NLP software
+    <a class="info"
+       href="https://spacy.io/"
+       target="_blank"
+       rel="noreferrer">»spaCy«
+      <span>Opens new page</span>
+    </a>.
+                                                              A word cloud can be created from the analyzed keywords or the keywords you have assigned yourself,
+                                                              called a topic cloud in »frag.jetzt«.
+                                                              It visualizes the frequency of the keywords:
+                                                              The larger the font, the more questions refer to the keyword.
+                                                              The rating of the questions is also included in the font size.
+                                                              The topic cloud also serves as a navigator to all questions of a selected keyword:
+                                                              Clicking on a word in the cloud takes you to the questions with that keyword.
+  </p>
+
   <p>
     <strong>Presenting questions in a focused way</strong><br><br>For the discussion of the questions on the beamer, they can be presented individually in full view.
     To move on to the next question, simply press the space bar.
@@ -152,12 +173,6 @@
     But until then, hundreds of computer science students of THM will be engaged and continuously working on all aspects of software development
     (user experience, high availability and security) —not for money, but for credit points and good grades.
   </p>
-  <p>
-    <strong>Outlook</strong><br><br>
-    We will integrate »frag.jetzt« into the free video conferencing system »Big&shy;Blue&shy;Button« (BBB) as a plugin in the near future.
-    So we will be able to offer all advantages of our feedback app in BBB without switching between browser tabs.
-    Stay tuned!
-  </p>
 </div>
 
 <h2 tabindex="0">Activate students online</h2>
@@ -221,176 +236,6 @@
   </ol>
 </div>
 
-<h2 tabindex=0>Icons and buttons</h2>
-
-<img tabindex=-1 src="/assets/images/poster.webp"
-class="screenshot"
-width="850"
-height="1200"
-alt="Info poster about frag. jetzt">
-
-<h2 tabindex="0">Question board from the view of a participant</h2>
-
-<img tabindex=-1 src="/assets/images/participant.webp"
-     class="screenshot"
-     width="400"
-     height="805"
-     alt="Question board from the view of a participant">
-
-<p tabindex="0">Header of the question list</p>
-<div tabindex="0">
-  <ol>
-    <li>Back to previous page</li>
-    <li>Session is moderated</li>
-    <li>QR code of the session</li>
-    <li>Sessions attended and bonus tokens received</li>
-  </ol>
-</div>
-
-<p tabindex="0">Toolbar of the question list</p>
-<ol tabindex="0">
-  <li>Number of incoming questions</li>
-  <li>Browse question list</li>
-  <li>Sort questions</li>
-  <li>Filter questions</li>
-  <li>Stop question stream</li>
-  <li>Ask a question</li>
-</ol>
-
-<p tabindex="0">Top toolbar of a question card</p>
-<ol tabindex="0">
-  <li>Time stamp of question</li>
-  <li>Lecturer has discussed the question (beamer icon)</li>
-  <li>Lecturer has commented on the question</li>
-  <li>Lecturer has affirmed the question</li>
-  <li>The question was marked by the lecturer or moderator (star icon)</li>
-</ol>
-
-<p tabindex="0">Bottom toolbar of a question card</p>
-<ol tabindex="0">
-  <li>Filter questions by category (tag icon)</li>
-  <li>Filter questions of a certain person (user icon)</li>
-</ol>
-
-<h2 tabindex="0">Session management</h2>
-
-<img tabindex=-1 src="/assets/images/lecturer.webp"
-     class="screenshot"
-     width="800"
-     height="600"
-     alt="Screenshot of the session management options">
-
-<p tabindex="0">Click on the gearwheel icon to open the management options:</p>
-<ol tabindex="0">
-  <li>Session: Here you can change the name of the session and add a description.
-      You can use <a class="info" href="https://en.wikipedia.org/wiki/Markdown" target="_blank">Markdown <span>Opens new window</span></a> for text formatting.
-    This is also the place to delete the session with all questions and ratings.
-  </li>
-  <li><p>Questions:</p>
-    <p>You can set a threshold for publishing a question,
-      that is, the negative rating at which a question is displayed. The value is between -100 and 0.</p>
-
-    <p>You also specify whether new questions are to be displayed before being moderated.
-      This is also the place to export all questions with their ratings to an Excel spreadsheet.
-      Furthermore you can delete all questions to use the session again.</p>
-  </li>
-  <li><p>Moderators:</p>
-    <p>You can only accept registered users as moderators.
-      For this you need the email address with which he or she registered.</p>
-  </li>
-  <li><p>Tokens for bonus stars:</p>
-    <p>If you annotate a question with a star,
-      an 8-digit number code (»token«) is generated for the question and listed here.
-      The author of the question will find the token in his account and can use it to redeem the bonus.</p>
-  </li>
-  <li><p>Tags:</p>
-    <p>Here you can define session-specific categories that your listeners can use to tag their questions.
-      The tag will then appear next to each question.
-      With a click on it, all questions will be filtered with this tag.</p>
-  </li>
-</ol>
-
-<h2 tabindex="0">Role concept of »frag.jetzt«</h2>
-
-
-<div tabindex=0 class="video">
-  <div class="videoWrapper">
-    <iframe tabindex="0"
-            width="560" height="315"
-            src="https://www.youtube.com/embed/qHRC6z9VtWs?autoplay=0" frameborder="0"
-            allowfullscreen
-    ></iframe>
-  </div>
-</div>
-
-<div id="demoContentTranscript" class="overflow_hide" tabindex="2">
-  <h2>Welcome to the demo of frag.jetzt!</h2>
-
-
-  <p>My name is Klaus Quibeldey-Cirkel. I am a professor of computer science at the Technical University
-    Mittelhessen
-    and
-    Project manager of frag.jetzt.
-    In the imprint of the app you can find a detailed description of the project.</p>
-
-  <p>Now for the demo:
-    In frag.jetzt there are three roles: the teacher, the student and the moderator.
-    Correspondingly, you see three browsers in which I play in the respective role the usage scenario of frag.jetzt
-    I will demonstrate.</p>
-
-  <p>Create a session by clicking the plus button.
-    You give your session a name
-    and that's it!
-    You tell your students the room code or the link to the session.</p>
-
-
-  <p>As a student I now enter the room code or the link to the session.
-    I could ask a question right away. But first I want to bring the moderator of the question list into the game:
-    I go to my session, open the settings and select the menu item "Questions".</p>
-
-
-  <p>By default, moderation is activated and all student questions are published directly.
-    If a question is to be released by the moderator, the corresponding switch must be flipped.
-    With the threshold value switch I can determine the negative rating above which questions are displayed.
-    should.
-    Now I have to add a moderator to my session:
-    To do this, I enter the email address with which he registered himself at frag.jetzt.
-    I register now as a moderator at the app and go into the session to be moderated.
-    In the lecture I go to the question list of the session in the role of moderator.
-    and in the role of lecturer, waiting for questions from students.
-    As a moderator, I can ban unwanted or inappropriate questions from the question list.
-    I could also ban closed questions (to which I can answer yes or no) with the corresponding icons.
-    mark
-    and highlight particularly interesting questions with a star.
-    All participants will see these ratings.</p>
-
-  <p>As a lecturer I can discuss the questions at the end of the lecture, which are mostly highly rated by the
-    students.
-    I click on the question to do this.
-    The question is displayed in full view on the beamer and highlighted in the participants' browsers.
-    A moderator can only ban questions from the question list, not delete them. Only the lecturer can do that.</p>
-
-  <p>All other functions, such as sorting and filtering questions or stopping the question stream,
-    you can find out in a playful way by placing two or three browsers next to each other on your laptop yourself
-    and play through the usage scenario in different roles.
-    How you can use frag.jetzt in your lecture or in your course during the semester, I describe further
-    below.</p>
-
-  <p>I thank you for your interest in frag.jetzt and look forward to your feedback. You can find my e-mail address
-    in
-    the
-    Imprint.</p>
-</div>
-
-<h2 tabindex="0">Feedback to the developers</h2>
-
-<p tabindex="0">
-  Go to the »Feedback« room for questions, suggestions, praise and criticism.
-  For further information please visit the <a class="info" href="https://arsnova.thm.de/blog/frag-jetzt/" target="_blank">ARSnova
-  blog <span>Opens new window</span></a>.
-
-</p>
-
 <h2 tabindex="0">Screen Readers </h2>
 
 <p tabindex="0">
diff --git a/src/assets/i18n/home/de.json b/src/assets/i18n/home/de.json
index 2b479ee8c3314b36a78739f99b38354e51e91b2f..a4fe29b4558dcb73e9b36da9cdade1cd2544245f 100644
--- a/src/assets/i18n/home/de.json
+++ b/src/assets/i18n/home/de.json
@@ -39,24 +39,30 @@
     "imprint": "Impressum",
     "language": "Sprache",
     "style": "Anzeige",
-    "motd-title-main": "News",
+    "motd-title-main": "News & FAQ",
     "motd-mark-all-read": "Alles gelesen",
     "motd-title-old": "Archiv",
     "motd-title-new": "Aktuell",
     "motd-mark-read": "Gelesen"
   },
   "content": {
-    "topic-cloud-content": "Weiter zur Topic-Cloud mit den aktuellen Filtern?",
     "cancel": "Abbrechen",
     "continue": "Weiter",
     "reset": "Zurücksetzen",
-    "continue-with-all-questions" : "Weiter mit kompletter Fragenliste",
-    "continue-with-current-questions": "Weiter mit aktuellen Filtern",
-    "continue-with-all-questions-from-now": "Weiter mit allen Fragen ab jetzt"
+    "brainstorming-question": "Ãœberschrift der Wortwolke",
+    "tag-cloud-info": "Je größer die Schrift, desto häufiger wurde das Wort  in den Fragen verwendet oder als Stichwort vergeben. Auch die Bewertungen der Fragen beeinflussen die Schriftgröße.",
+    "tag-cloud-questions-title": "Welche Fragen sollen berücksichtigt werden?",
+    "tag-cloud-questions-all": "Alle",
+    "tag-cloud-questions-all-short": "Alle",
+    "tag-cloud-questions-current-filtered": "Fragenliste",
+    "tag-cloud-questions-brainstorming": "Fragen, die ab jetzt gestellt werden (Brainstorming)",
+    "tag-cloud-questions-brainstorming-short": "Brainstorming",
+    "tag-cloud-create": "Anzeigen"
   },
   "header": {
     "abort": "Abbrechen",
     "accessibility-back": "Führt zur vorherigen Seite",
+    "accessibility-tour": "Startet die Onboarding Tour",
     "accessibility-login": "Öffnet das Anmeldungs-Fenster.",
     "accessibility-session": "Öffnet das Options-Menü. Hier kannst du deine besuchten Sitzungen einsehen oder die aktuelle Sitzung verlassen.",
     "account-deleted": "Dein Konto wurde gelöscht.",
@@ -64,38 +70,58 @@
     "cancel": "Abbrechen",
     "delete": "Löschen",
     "delete-account": "Konto löschen",
-    "home-header": "Fragen sammeln und bewerten",
+    "home-header": "",
+    "home-header-mobile": "",
     "id": "Code",
     "logged-out": "Du bist jetzt abgemeldet.",
     "login": "Anmelden",
     "logout": "Abmelden",
+    "block": "Fragenstellen sperren",
+    "unlock": "Fragenstellen freigeben",
     "moderation-enabled": "Die Sitzung wird moderiert.",
     "QR": "QR-Code der Sitzung in Vollansicht",
     "my-account": "Optionen",
     "my-guest-account": "Gastkonto",
-    "my-sessions": "Sitzungsliste",
+    "my-sessions": "Zu den Räumen",
     "really-delete-account": "Willst du dein Konto mit allen Sitzungen unwiderruflich löschen? Falls du Boni vergeben hast (Sterne), exportiere die Fragen, damit du eingereichte Bonus-Tokens überprüfen kannst.",
     "sure": "Bist du sicher?",
-    "user-bonus-token": "Deine Sterne",
+    "user-bonus-token": "Bonus-Sterne",
     "user-got-tokens": "Du hast noch Sterne für Bonuspunkte, die verloren gehen!",
+    "users-online": "Aktuell eingeloggte User",
     "visited-sessions": "Sitzungen",
     "question-wall": "Fragen präsentieren",
     "room-qr": "Raum-Code",
-    "question-board": "Frageliste",
-    "bonustoken": "Vergebene Sterne",
+    "question-board": "Fragenliste",
+    "moderation-mode": "Moderationsmodus",
+    "bonustoken": "Bonus-Archiv",
     "edit-moderator": "Moderatoren",
-    "edit-tags": "Kategorien",
+    "edit-session-description": "Begrüßungstext",
+    "edit-tags": "Fragen-Kategorien",
+    "profanity-filter": "Vulgäre Wörter ausixen",
     "export-questions": "Fragen speichern",
     "delete-questions": "Fragen löschen",
-    "back-to-questionboard": "Frageliste",
-    "moderationboard": "Zum Index",
+    "delete-room": "Raum löschen",
+    "back-to-questionboard": "Fragenliste",
+    "back-to-room": "Begrüßung",
+    "back-to-room-creator": "Raumverwaltung",
+    "back-to-room-moderator": "Raumverwaltung",
+    "moderationboard": "Moderation",
     "create-question": "Frage stellen",
-    "questionwall": "Fragen-Fokus",
+    "questionwall": "Präsentation",
     "tag-cloud": "Themenwolke",
-    "fullscreen": "Text skalieren",
-    "motd": "News",
-    "tag-cloud-config": "Wolkenansicht ändern",
-    "tag-cloud-administration": "Wolkenthemen editieren"
+    "fullscreen": "Vollbild & Text",
+    "motd": "News & FAQ",
+    "tag-cloud-config": "Aussehen & Animation",
+    "tag-cloud-administration": "Einstellungen & Suche",
+    "questions-blocked": "Neue Fragen deaktiviert ",
+    "overview-question-tooltip": "Anzahl Fragen",
+    "overview-questioners-tooltip": "Anzahl Fragensteller*innen",
+    "overview-keywords-tooltip": "Anzahl Stichwörter",
+    "update-spacy-keywords": "Fragen analysieren",
+    "overview-admin-config-enabled": "Themeneinschränkung aktiv",
+    "quiz-now": "Quizzen",
+    "moderation-warning": "Moderationsboard mit nicht freigegebenen Fragen",
+    "tour": "Tour"
   },
   "help": {
     "cancel": "Schließen",
@@ -106,7 +132,7 @@
     "accessibility-create": "Erstellt eine neue Sitzung.",
     "accessibility-join-button": "Betritt die Sitzung, deren Code du eingegeben hast.",
     "accessibility-join-input": "Hier kannst du den Namen der Sitzung eingeben der du beitreten möchtest. Den Namen sagt dir die Sitzungsleitung.",
-    "create-session": " Raum erstellen",
+    "create-session": "Raum erstellen",
     "created-1": "Die Sitzung »",
     "created-2": "« wurde erstellt.",
     "exactly-8": "Der Code ist eine Kombination aus 8 Ziffern.",
@@ -114,16 +140,17 @@
     "live-announcer": "Willkommen auf der Seite fragpunktjetzt. Diese Seite wurde für Screenreader wie ChromeVox, Voiceover und viele andere optimiert. Ein Audioguide kann dir bei der Navigation helfen. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
     "live-announcer-user": "Du befindest dich jetzt auf der Benutzer-Seite. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
     "install": "Installieren",
-    "no-empty-name": "Gib einen Namen für die Sitzung ein.",
-    "no-empty-key-code": "Gib einen Raum-Code für die Sitzung ein.",
-    "no-room-found": "Es wurde keine Sitzung mit diesem Namen gefunden.",
+    "no-empty-name": "Wie soll die Veranstaltung heißen?",
+    "no-empty-key-code": "Gib einen leicht zu merkenden Code ein.",
+    "no-room-found": "Ein Raum mit diesem Namen oder Code existiert nicht.",
     "only-numbers": "Der Raum-Code ist alphanumerisch.",
-    "please-enter": "Wie heißt der Raum, wo die Sitzung stattfindet?",
+    "please-enter": "Raum-Code eingeben",
     "room-name-input": "Gib hier den Namen der Sitzung ein, die du erstellen möchtest.",
     "session-id": "Welcher Raum?",
+    "join-room": "Teilnehmen",
     "update-available": "Eine neue Version ist verfügbar.",
-    "custom-shortid": "Raum-Code selbst bestimmen?",
-    "custom-shortid-placeholder": "a-z, A-Z, 0-9, - _ . ~ keine Leerzeichen",
+    "custom-shortid": "Raum-Code selbst bestimmen",
+    "custom-shortid-placeholder": "Code aus: a-z, A-Z, 0-9, - , _ , . , ~ ",
     "invalid-shortid": "Der eingegebene Raum-Code ist nicht verfügbar.",
     "invalid-char-shortid": "Der Raum-Code enthält unzulässige Zeichen."
   },
@@ -137,6 +164,27 @@
     "cancel-description": "Schließe die Einführung und gehe zurück zur Anmeldung.",
     "title": "Einführung"
   },
+  "joyride": {
+    "next": "Weiter",
+    "prev": "Zurück",
+    "step": "{{step}} / {{total}}",
+    "done": "Fertig",
+    "cantAccessRoute": "Diese Route ist nicht verfügbar. Die Tour wird abgebrochen.",
+    "greeting": "Wir führen dich zu den wichtigsten Stellen in unserem Audience-Response-System »frag.jetzt«. Die Tour dauert nur wenige Minuten.",
+    "greetingTitle": "Willkommen!",
+    "loginButtonHeader": "Nicht nötig, es sei denn du willst deine besuchten oder selbst erstellten Räume auf unserem Server speichern. Ein Konto ist auch für die Verwaltung von Bonuspunkten ratsam.",
+    "loginButtonHeaderTitle": "Muss ich mich registrieren?",
+    "roomJoin": "Gib hier den Zugangscode für den Raum ein, um an der Veranstaltung teilzunehmen.",
+    "roomJoinTitle": "Veranstaltung besuchen",
+    "createRoom": "Jeder kann einen Raum für eine Veranstaltung erstellen. Der Zugangscode wird entweder generiert oder du bestimmst ihn selbst.",
+    "createRoomTitle": "Raum erstellen",
+    "introduction": "Wenn du eigene Räume erstellen willst, dann informiere dich hier über das didaktische Konzept und die Einsatz-Szenarien von »frag.jetzt«.",
+    "introductionTitle": "Einführung in »frag.jetzt«",
+    "feedbackLink": "Du hast einen Bug gefunden? Du hättest gern ein weiteres Feature? Der Link führt dich in den Feedback-Raum. Die Tour wird in diesem Raum fortgesetzt.",
+    "feedbackLinkTitle": "Raum für Feedback",
+    "optionHeader": "Hier befindet sich das Hauptmenü von »frag.jetzt«. Neben den Optionen der aktuellen Seite findest du hier auch allgemeine Funktionen, darunter die FAQ.",
+    "optionHeaderTitle": "Optionen"
+  },
   "login": {
     "activation-key": "Aktivierungs-Schlüssel",
     "cancel": "Abbrechen",
@@ -164,8 +212,8 @@
     "restart-account-activation-button": "Falls ungültig, neuen Schlüssel anfordern.",
     "restart-account-activation-correct": "Der Aktivierungs-Schlüssel wurde erneut gesendet.",
     "restart-account-activation-tooltip": "Sendet den Aktivierungs-Schlüssel erneut an die angegebene Adresse.",
-    "welcome": "»Haben Sie Fragen?«",
-    "welcome-feedback": "➜ Feedback",
+    "welcome": "»Noch Fragen?«",
+    "welcome-feedback": "➜ Feedback an das »frag.jetzt«-Team",
     "feedback-aria": "Baggs, Features, Lob und Tadel kannst du über diesen Link in unserer Feedback-Säschen äussern."
   },
   "overlay": {
@@ -234,31 +282,31 @@
   "room-create": {
     "cancel": "Abbrechen",
     "cancel-description": "Abbrechen",
-    "create-room": "Speichern",
+    "create-room": "Raum erstellen",
     "create-room-description": "Neue Sitzung."
   },
   "room-list": {
-    "creator-role": "Vortragender",
+    "creator-role": "Du bist der Ersteller dieses Raumes.",
     "entry": "Eintrag ",
-    "executive-moderator-role": "Moderator",
+    "executive-moderator-role": "Du bist ein Moderator in diesem Raum.",
     "filter": "In diesem Textfeld kannst du die besuchten Sitzungen nach Name oder Code filtern.",
-    "filter-message": "Sitzungsliste durchsuchen …",
+    "filter-message": "Suchen …",
     "join-message-template": "An der Sitzung {{session}} mit dem Code {{id}} und in der Rolle {{role}} teilnehmen.",
-    "moderator-role": "Moderator",
-    "no-room-history": "Deine Sitzungsliste ist leer.",
+    "moderator-role": "Du bist ein Moderator in diesem Raum.",
+    "no-room-history": "Deine Raumliste ist leer.",
     "panel-join-button": "",
-    "panel-remove-button": "Sitzung aus der Liste streichen",
-    "delete-room": "Sitzung löschen",
-    "panel-session-id": "Raum-Code",
-    "panel-session-name": "Sitzung",
+    "panel-remove-button": "Eintrag entfernen",
+    "delete-room": "Raum löschen",
+    "panel-session-id": "Raum",
+    "panel-session-name": "Veranstaltung",
     "panel-user-role": "Rolle",
-    "participant-role": "Teilnehmer",
-    "really-remove": "Willst du die besuchte Sitzung »",
+    "participant-role": "Du bist Teilnehmer*in in diesem Raum.",
+    "really-remove": "Willst du die besuchte Veranstaltung »",
     "really-remove-2": "« wirklich aus der Liste streichen?",
-    "really-delete": "Willst du deine Sitzung »",
+    "really-delete": "Willst du den Raum »",
     "really-delete-2": "« wirklich unwiderruflich löschen?",
-    "room-successfully-removed": "Die Sitzung wurde aus der Liste entfernt.",
-    "room-successfully-deleted": "Die Sitzung wurde gelöscht.",
+    "room-successfully-removed": "Die Veranstaltung wurde aus der Liste entfernt.",
+    "room-successfully-deleted": "Der Raum wurde gelöscht.",
     "canceled-remove": "Vorgang wurde abgebrochen.",
     "session-history": "Dein Sitzungsverlauf enthält {{count}} Sitzungen.",
     "session-history-1": "Dein Sitzungsverlauf enthält genau eine Sitzung.",
@@ -272,15 +320,16 @@
     "token": "Bonus-Token",
     "token-time": "Token-Zeitstempel",
     "no-comments": "Es sind noch keine Fragen vorhanden.",
-    "export-comments": "Fragen speichern"
+    "export-comments": "Fragen speichern",
+    "room-not-exist": "Es tut uns leid, aber die Sitzung, der du beitreten möchtest, existiert nicht.\nBitte informiere die Person, die dir diesen Link gegeben hat."
   },
   "session": {
     "create-session": "Speichern",
-    "description": "Beschreibung der Sitzung",
+    "description": "Beschreibung der Veranstaltung",
     "join": "Sitzung beitreten",
     "max-ls": "Maximale Anzahl Zeichen:",
-    "session-name": "Sitzungsname",
-    "session-name-with-key-code-generated": "Sitzungsname (Code wird generiert)"
+    "session-name": "Veranstaltung",
+    "session-name-with-key-code-generated": "Veranstaltung (Raum-Code wird generiert)"
   },
   "user-activation": {
     "activate": "Konto aktivieren",
@@ -306,5 +355,23 @@
   },
   "qr-dialog": {
     "session": "Raum"
+  },
+  "topic-cloud": {
+    "changes-gone-wrong": "Etwas ist schiefgelaufen!",
+    "changes-successful": "Änderungen gespeichert.",
+    "add-successful": "Wort hinzugefügt",
+    "remove-successful": "Wort entfernt"
+  },
+  "worker-dialog": {
+    "running": "Laufend",
+    "room-name" : "Raum",
+    "comments" : "Abgearbeitete Fragen",
+    "bad-spelled" : "Zu schlechte Rechtschreibung",
+    "failed" : "Fehler aufgetreten",
+    "inline-header": "Laufende Stichwort-Aktualisierungen"
+  },
+  "topic-cloud-filter": {
+    "info-no-keywords": "Es gibt keine Stichwörter. Die Wortwolke wird leer sein. Eine KI-basierte Fragen-Analyse kann Stichwörter nachträglich erstellen. Fragen-Analyse starten?",
+    "label-refresh-keywords-start": "Starten"
   }
 }
diff --git a/src/assets/i18n/home/en.json b/src/assets/i18n/home/en.json
index 3dda55a3730c7f2a357d3ad41fa2cd9dcf125d60..6c95f7d8be68d87841f9458bdfc14d8cc1996888 100644
--- a/src/assets/i18n/home/en.json
+++ b/src/assets/i18n/home/en.json
@@ -40,23 +40,27 @@
     "language": "Language",
     "open": "Open",
     "style": "Display",
-    "motd-title-main": "News",
+    "motd-title-main": "News & FAQ",
     "motd-mark-all-read": "Mark all as read",
-    "motd-title-old": "News archive",
-    "motd-title-new": "Latest news",
+    "motd-title-old": "Archive",
+    "motd-title-new": "Latest",
     "motd-mark-read": "Mark as read"
   },
   "header": {
     "abort": "Cancel",
     "accessibility-back": "Go back to the previous page",
+    "accessibility-tour": "Starts the onboarding tour",
     "accessibility-login": "Open the login window",
     "accessibility-session": "Open the session menu. Here you can view the sessions you have attended or leave the current session.",
     "account-deleted": "Your account has been deleted.",
     "back": "Back",
     "cancel": "Cancel",
     "delete": "Delete",
+    "block": "Block new questions",
+    "unlock": "Release for new questions",
     "delete-account": "Delete account",
-    "home-header": "Collect and rate questions",
+    "home-header": "",
+    "home-header-mobile": "",
     "id": "Key",
     "logged-out": "You are logged out now.",
     "login": "Log in",
@@ -65,29 +69,46 @@
     "QR": "QR code of the session in full view",
     "my-account": "Options",
     "my-guest-account": "Guest Account",
-    "my-sessions": "Session list",
+    "my-sessions": "Room list",
     "really-delete-account": "Do you want to irrevocably delete your account with all sessions? If you have given bonus stars, export the questions so that you can check submitted bonus tokens.",
     "sure": "Are you sure?",
-    "user-bonus-token": "Your stars",
+    "user-bonus-token": "Bonus stars",
     "user-got-tokens": "You haven't received a star for a good question yet.",
+    "users-online": "Currently logged-in users",
     "visited-sessions": "Sessions",
     "question-wall": "Present questions",
     "room-qr": "Key code",
     "question-board": "Question list",
-    "bonustoken": "Assigned Stars",
+    "moderation-mode": "Moderation mode",
+    "bonustoken": "Assigned bonus stars",
     "edit-moderator": "Moderators",
-    "edit-tags": "Tags",
+    "edit-session-description": "Welcome text",
+    "edit-tags": "Question tags",
+    "profanity-filter": "Filter vulgar words",
     "export-questions": "Save questions",
     "delete-questions": "Delete questions",
+    "delete-room": "Delete room",
     "back-to-questionboard": "Question list",
-    "moderationboard": "To the index",
+    "back-to-room": "Welcoming",
+    "back-to-room-creator": "Room management",
+    "back-to-room-moderator": "Entrance",
+    "moderationboard": "Moderation",
     "create-question": "Ask a question",
-    "questionwall": "Question focus",
+    "questionwall": "Presentation",
     "tag-cloud": "Topic cloud",
-    "fullscreen": "Text scaling",
-    "motd": "News",
+    "fullscreen": "Fullscreen & Text",
+    "motd": "News & FAQ",
     "tag-cloud-config": "Modify cloud view",
-    "tag-cloud-administration": "Edit cloud topics"
+    "tag-cloud-administration": "Edit cloud topics",
+    "questions-blocked": "New questions blocked",
+    "overview-question-tooltip": "Number of questions",
+    "overview-questioners-tooltip": "Number of questioners",
+    "overview-keywords-tooltip": "Number of Keywords",
+    "update-spacy-keywords": "Add keywords",
+    "overview-admin-config-enabled": "Themes requirement active",
+    "quiz-now": "Quizzing",
+    "moderation-warning": "Moderation board with unreleased questions",
+    "tour": "Tour"
   },
   "help": {
     "cancel": "Close",
@@ -106,28 +127,33 @@
     "live-announcer": "Welcome to fragpunktjetzt. This site has been designed to support screen readers like ChromeVox, Voiceover and many others. Our Audioguide feature can assist you in navigating the site. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
     "live-announcer-user": "You are now on the user page. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
     "install": "Install",
-    "no-empty-name": "Please enter a name for the session.",
-    "no-empty-key-code": "Please enter a key code for the session.",
-    "no-room-found": "No session found with this name.",
+    "no-empty-name": "What should the event be called?",
+    "no-empty-key-code": "Enter an easy-to-remember code for the room.",
+    "no-room-found": "No room found with this name or key code.",
     "only-numbers": "The key code is alphanumeric.",
-    "please-enter": "What is the key code of the room where the session takes place?",
+    "please-enter": "Enter key code",
     "room-name-input": "Enter the name of the session you want to create.",
     "session-id": "Which room?",
+    "join-room": "Join meeting",
     "update-available": "An update is available.",
-    "custom-shortid": "Set the key code yourself?",
-    "custom-shortid-placeholder": "a-z, A-Z, 0-9, - _ . ~ no blanks",
+    "custom-shortid": "Set key code yourself",
+    "custom-shortid-placeholder": "Characters: a-z, A-Z, 0-9, - , _ , . , ~",
     "invalid-shortid": "This key code is not available.",
     "invalid-char-shortid": "This key code contains invalid characters."
-  }, 
+  },
   "content": {
-    "topic-cloud-content": "Continue to the Topic Cloud with the current filters?",
     "cancel": "Cancel",
     "continue": "Continue",
     "reset": "Reset",
-    "continue-with-all-questions" : "Continue with complete list of questions",
-    "continue-with-current-questions": "Continue with current filters",
-    "continue-with-all-questions-from-now": "Continue with all questions from now"
-
+    "brainstorming-question": "Word cloud heading",
+    "tag-cloud-info": "The word cloud in »frag.jetzt« serves as a semantic filter: the larger the font, the more often the word was used grammatically in the questions or assigned as a keyword. The ratings of the questions also influence the font size.",
+    "tag-cloud-questions-title": "Which questions should be included?",
+    "tag-cloud-questions-all": "All questions",
+    "tag-cloud-questions-all-short": "All questions",
+    "tag-cloud-questions-current-filtered": "Question list",
+    "tag-cloud-questions-brainstorming": "Brain storming session: questions that will be asked from now on",
+    "tag-cloud-questions-brainstorming-short": "Brain storming session",
+    "tag-cloud-create": "Create word cloud"
   },
   "imprint": {
     "cancel": "Close",
@@ -139,6 +165,27 @@
     "cancel-description": "Close introduction.",
     "title": "Introduction"
   },
+  "joyride": {
+    "next": "Next",
+    "prev": "Previous",
+    "step": "{{step}} / {{total}}",
+    "done": "Finish",
+    "cantAccessRoute": "This route is not available. The tour will be cancelled.",
+    "greeting": "We guide you to the most important places in our audience response system »frag.jetzt«. The tour will only take a few minutes.",
+    "greetingTitle": "Welcome!",
+    "loginButtonHeader": "Not necessary, unless you want to store your visited or self-created rooms on our server. An account is also advisable for managing bonus points.",
+    "loginButtonHeaderTitle": "Do I have to register?",
+    "roomJoin": "Enter the access code for the room where the event you want to attend is taking place.",
+    "roomJoinTitle": "Join an event",
+    "createRoom": "Everyone can create a room for an event. The access code is either generated or you determine it yourself.",
+    "createRoomTitle": "Create a room",
+    "introduction": "If you want to create your own rooms, then find out about the didactic concept and the usage scenarios of »frag.jetzt«.",
+    "introductionTitle": "Introduction to »frag.jetzt«",
+    "feedbackLink": "You found a bug? You would like to have another feature? The link leads you to the feedback room. The tour will continue in this room.",
+    "feedbackLinkTitle": "Feedback room",
+    "optionHeader": "This is the main menu of »frag.jetzt«. In addition to the options of the current page, you will also find general functions here such as the FAQ.",
+    "optionHeaderTitle": "Options"
+  },
   "login": {
     "activation-key": "Activation key",
     "cancel": "Cancel",
@@ -168,7 +215,7 @@
     "restart-account-activation-tooltip": "Sends the activation key again",
     "welcome": "»Any questions?«",
     "welcome-subtitle": "anonymous | in your browser | for free",
-    "welcome-feedback": "➜ Feedback",
+    "welcome-feedback": "➜ Feedback to the »frag.jetzt« team",
     "feedback-aria": "Please use the following Link to offer the developers bugs, features, praise and blame"
   },
   "overlay": {
@@ -237,25 +284,25 @@
   "room-create": {
     "cancel": "Cancel",
     "cancel-description": "Cancel",
-    "create-room": "Create session",
+    "create-room": "Create room",
     "create-room-description": "New session"
   },
   "room-list": {
-    "creator-role": "Presenter",
+    "creator-role": "You are the creator of this room.",
     "entry": "Entry ",
-    "executive-moderator-role": "Moderator",
+    "executive-moderator-role": "You are a moderator in this room.",
     "filter": "Here you can filter your visited sessions.",
-    "filter-message": "Search in session list …",
+    "filter-message": "Search …",
     "join-message-template": "Join the session {{session}} with code {{id}} and in the role {{role}}",
-    "moderator-role": "Moderator",
-    "no-room-history": "Your session list is empty.",
+    "moderator-role": "You are a moderator in this room.",
+    "no-room-history": "Your room list is empty.",
     "panel-join-button": "",
     "panel-remove-button": "Remove session from list",
-    "delete-room": "Delete session",
-    "panel-session-id": "Key code",
-    "panel-session-name": "Session",
+    "delete-room": "Delete room",
+    "panel-session-id": "Room",
+    "panel-session-name": "Meeting",
     "panel-user-role": "Role",
-    "participant-role": "Participant",
+    "participant-role": "You are a participant in this room.",
     "really-remove": "Do you really want to remove session ",
     "really-remove-2": " from your history?",
     "really-delete": "Do you really want to delete your session ",
@@ -275,7 +322,8 @@
     "token": "Bonus token",
     "token-time": "Token timestamp",
     "no-comments": "There are no questions yet.",
-    "export-comments": "Save questions"
+    "export-comments": "Save questions",
+    "room-not-exist": "We are sorry, but the session you want to join does not exist.\nPlease inform the person who gave you this direct link."
   },
   "session": {
     "create-session": "Save",
@@ -283,8 +331,7 @@
     "join": "Join session",
     "max-ls": "Max. characters:",
     "session-name": "Session name",
-    "session-name-with-key-code-generated": "Session name (code will be generated)"
-
+    "session-name-with-key-code-generated": "Name of the meeting (key code will be generated)"
   },
   "user-activation": {
     "activate": "Activate account",
@@ -310,5 +357,23 @@
   },
   "qr-dialog": {
     "session": "Key code"
+  },
+  "topic-cloud": {
+    "changes-gone-wrong": "Something went wrong!",
+    "changes-successful": "Successfully updated.",
+    "add-successful": "Word added",
+    "remove-successful": "Word removed"
+  },
+  "worker-dialog": {
+    "running": "Running",
+    "room-name": "Session name",
+    "comments": "Questions",
+    "bad-spelled": "Spelling too bad",
+    "failed": "Error occurred",
+    "inline-header": "Ongoing keyword updates"
+  },
+  "topic-cloud-filter": {
+    "info-no-keywords": "There are no keywords. The word cloud will be empty. An AI-based question analysis can create keywords afterwards. Start question analysis?",
+    "label-refresh-keywords-start": "Start"
   }
 }
diff --git a/src/assets/i18n/participant/de.json b/src/assets/i18n/participant/de.json
index b9e581e5c728f2d0d90489adec92f5a6b2165029..7a63a6d40d38729a87658bfe6c909e0577f83927 100644
--- a/src/assets/i18n/participant/de.json
+++ b/src/assets/i18n/participant/de.json
@@ -25,6 +25,7 @@
     "a11y-select-time-1w": "Zeige alle kommentare der letzten 7 Tage an",
     "a11y-select-time-2w": "Zeige alle kommentare der letzten 14 Tage an",
     "a11y-select-time-all": "Zeige alle Kommentare an",
+    "a11y-activity": "Aktive Benutzer",
     "answered": "Beantwortete Fragen",
     "add-comment": "Stell deine Frage!",
     "pause-comments": "Friert die Anzeige ein, um die Fragen in Ruhe zu lesen. Fragen können weiterhin gestellt und bewertet werden. Die Anzeige aktualisiert sich wieder durch Klicken des Buttons.",
@@ -80,18 +81,27 @@
     "token": "Bonus-Token",
     "token-time": "Token-Zeitstempel",
     "no-comments": "Es sind noch keine Fragen vorhanden.",
-    "export-comments": "Fragen speichern"
+    "export-comments": "Fragen speichern",
+    "questions-blocked": "Neue Fragen deaktiviert "
   },
   "content": {
     "cancel": "Abbrechen",
     "delete": "Löschen"
   },
-  "spacy-dialog":{
-    "german": "Deutsch",
-    "english": "Englisch",
-    "french": "Französisch",
-    "empty-nouns": "Keine Nomen enthalten",
-    "select-all": "Alles auswählen"
+  "spacy-dialog": {
+    "auto": "auto",
+    "de": "Deutsch",
+    "en": "Englisch",
+    "fr": "Französisch",
+    "select-all": "Alles auswählen",
+    "lang-button-hint": "Sprache für die Rechtschreibprüfung",
+    "select-all-hint": "Alle Nomen als Stichwörter auswählen",
+    "select-keyword-hint": "Dieses Wort als Stichwort auswählen",
+    "edit-keyword-hint": "Wort editieren",
+    "editing-done-hint": "Editieren beenden",
+    "force-language-selection": "Die Sprache der Eingabe konnte nicht automatisch erkannt werden.",
+    "add-manually": "Gib ein Stichwort zu deiner Frage ein. Trenne mehrere Stichwörter mit einem Komma.",
+    "select-keywords": "Die Textanalyse schlägt folgende Stichwörter vor. Welche kennzeichnen deine Frage am besten?"
   },
   "comment-page": {
     "a11y-comment_input": "Gib deine Frage ein",
@@ -108,18 +118,20 @@
     "fullscreen": "Die Frage wurde beantwortet oder kommentiert. Klick auf das Symbol für die Ansicht.",
     "abort": "Abbrechen",
     "ask-question-description": "Gib hier deine Frage ein!",
+    "save-answer": "Speichern",
+    "delete-answer": "Löschen",
     "cancel": "Abbrechen",
     "cancel-description": "Abbrechen",
     "comment": "Die Frage {{ comment }} wurde um {{ time }} Uhr gestellt und hat derzeitig {{ votes }}. {{correct}} {{wrong}} {{bonus}} {{beamer}}",
     "delete": "Deine Frage löschen",
     "enter-comment": "Gib deine Frage ein …",
-    "Markdown-hint": "Formatiere mit Markdown",
+    "Markdown-hint": "Formatiere mit Markdown & KaTeX",
     "enter-title": "Titel",
     "error-both-fields": "Bitte fülle alle Felder aus.",
     "error-comment": "Bitte gib deine Frage ein.",
     "error-title": "Bitte gib einen Titel ein.",
     "has-answer": "Die Frage wurde kommentiert. Klick hier, um den Kommentar zu lesen.",
-    "exit-description": "Präsentations-Modus verlassen",
+    "exit-description": "Präsentationsmodus verlassen",
     "live-announcer": "Du befindest dich jetzt auf der Fragen-Seite. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
     "mark-not-correct": "Die Frage wurde bejaht.",
     "mark-not-favorite": "Die Frage wurde ausgezeichnet.",
@@ -135,23 +147,39 @@
     "send-description": "Frage abschicken",
     "tag": "Tag",
     "tag-reset": "Zurücksetzen",
-    "tag-to-filter": "Klick auf die Fragekategorie, um Fragen dieser Kategorie zu filtern.",
-    "user-number": "Klick auf die Nummer, um die Fragen dieses anonymen Fragenstellers zu filtern.",
+    "tag-to-filter": "Klick auf die Fragekategorie, um alle Fragen dieser Kategorie zu filtern.",
+    "user-number": "Klick auf die Nummer, um alle Fragen dieses Fragenstellers zu filtern.",
+    "keywords-per-question": "Klick auf ein Stichwort, um alle Fragen mit diesem Stichwort zu filtern.",
+    "keywords": "Stichwörter",
     "vote-down": "Frage abwerten",
     "vote-up": "Frage aufwerten",
     "write-comment": "Eingabe",
     "preview-comment": "Vorschau",
     "show-more": "Mehr ansehen",
     "show-less": "Weniger anzeigen",
-    "sure": "Bist du sicher?"
+    "sure": "Bist du sicher?",
+    "grammar-check": "Rechtschreibprüfung"
   },
-
   "home-page": {
     "exactly-8": "Ein Raum-Code hat genau 8 Ziffern.",
-    "no-room-found": "Es wurde keine Sitzung mit diesem Raum-Code gefunden.",
+    "no-room-found": "Es wurde kein Raum mit diesem Raum-Code gefunden.",
     "only-numbers": "Ein Raum-Code besteht aus Ziffern.",
     "please-enter": "Bitte Raum-Code eingeben."
   },
+  "joyride": {
+    "next": "Weiter",
+    "prev": "Zurück",
+    "step": "{{step}} / {{total}}",
+    "done": "Fertig",
+    "createQuestion": "Mit dem Plus-Button rufst du den Editor auf. Eine KI schlägt dir Stichwörter für deine Frage vor. Diese dienen dem Erstellen einer Themenwolke aus allen Fragen der Veranstaltung.",
+    "createQuestionTitle": "Eine Frage stellen",
+    "voting": "Das Publikum kann Fragen auf- oder abwerten und so sein Interesse an der Frage oder seine Zustimmung oder Ablehnung bekunden.",
+    "votingTitle": "Eine Frage bewerten",
+    "commentFilter": "Es gibt zahlreiche Sortier- und Filteroptionen für die Fragenliste. Ein aktiver Filter wird rot angezeigt. Für eine bessere Lesbarkeit bei großer Dynamik kann der Fragenstrom auch angehalten werden.",
+    "commentFilterTitle": "Fragenliste verwalten",
+    "commentUserNumber": "Alle User stellen ihre Fragen anonym. Jedem User wird eine zufällige Nummer zugewiesen, um alle Fragen dieses Users zu finden. Dies geschieht mit einem Klick auf die Nummer.",
+    "commentUserNumberTitle": "Fragen eines Users finden"
+  },
   "room-page": {
     "a11y-announcer": "Du befindest dich nun in der Sitzung mit dem von dir eingegebenen Raum-Code.",
     "a11y-question_answer": "Öffnet die Fragen-Seite und bietet dir die Möglichkeit, Fragen zu stellen.",
@@ -208,7 +236,7 @@
     "filter-lbl": "Filter-Menü anzeigen",
     "filter-lbl-favorites": "Favorisierte Fragen filtern",
     "filter-lbl-approved": "Bejahte Fragen filtern",
-    "filter-lbl-disapproved":"Verneinte Fragen filtern",
+    "filter-lbl-disapproved": "Verneinte Fragen filtern",
     "filter-tags-lbl": "Nach Kategorien filtern",
     "user-lbl": "Benutzer-Menü öffnen",
     "slider-lbl": "Fragen-Zoom einstellen",
@@ -216,12 +244,31 @@
     "autofocus-on-lbl": "Neue Fragen automatisch fokussieren",
     "prev-comment-lbl": "Vorherige Frage",
     "next-comment-lbl": "Nächste Frage",
-    "overview-question-tooltip": "Anzahl gestellter Fragen",
-    "overview-questioners-tooltip": "Anzahl Fragensteller*innen"
+    "overview-question-tooltip": "Anzahl Fragen",
+    "overview-questioners-tooltip": "Anzahl Fragensteller*innen",
+    "questions-blocked": "Neue Fragen deaktiviert "
   },
   "tag-cloud": {
-    "config": "Wolkenansicht ändern",
-    "administration": "Wolkenthemen editieren"
+    "demo-data-topic": "Thema %d",
+    "overview-question-topic-tooltip": "Anzahl Fragen mit diesem Thema",
+    "overview-questioners-topic-tooltip": "Anzahl Fragensteller*innen mit diesem Thema",
+    "period-since-first-comment":"Zeitraum seit der ersten Frage",
+    "upvote-topic": "Up-Votes für dieses Thema",
+    "downvote-topic": "Down-Votes für dieses Thema",
+    "blacklist-topic": "Thema auf die »Blacklist« setzen"
+  },
+  "tag-cloud-popup": {
+    "few-seconds": "wenige Sekunden",
+    "few-minutes": "wenige Minuten",
+    "some-minutes": "{{minutes}} Minuten",
+    "one-hour": "1 Stunde",
+    "some-hours": "{{hours}} Stunden",
+    "one-day": "1 Tag",
+    "some-days": "{{days}} Tage",
+    "one-week": "1 Woche",
+    "some-weeks": "{{weeks}} Wochen",
+    "some-months": "{{months}} Monate",
+    "tag-correction-placeholder": "Korrektur…"
   },
   "topic-cloud-dialog": {
     "cancel": "Abbrechen",
@@ -231,51 +278,135 @@
     "question-count-singular": "Frage",
     "question-count-plural": "Fragen",
     "edit-keyword-tip": "Neues Thema",
-    "no-keywords-note": "Es gibt keine Themen",
-    "consider-votes": "Votes berücksichtigen",
-    "tags-lowercase": "Themen klein schreiben",
+    "no-keywords-note": "Es gibt keine Themen.",
+    "consider-votes": "Bewertungen der Fragen berücksichtigen",
+    "profanity": "Vulgäre Wörter mit »***« überschreiben",
+    "hide-blacklist-words": "Themen aus der Blacklist verbergen",
     "sort-alpha": "Alphabetisch",
-    "sort-count": "Fragenanzahl",
-    "sort-vote": "Votes",
-    "keyword-search": "Stichwort suchen"
-  },
-  "topic-cloud-confirm-dialog": {
-    "cancel": "Abbrechen",
-    "delete": "Löschen",
-    "confirm": "Sind Sie sicher?",
-    "will-be-deleted": "Thema wird gelöscht"
+    "sort-count": "Anzahl Fragen",
+    "sort-vote": "Anzahl Up-Votes",
+    "keyword-search": "Thema suchen …",
+    "edit-profanity-list": "Liste der Vulgärausdrücke bearbeiten",
+    "edit-blacklist-list": "Blacklist bearbeiten",
+    "add-word": "Wort hinzufügen",
+    "enter-word": "Wort eingeben",
+    "settings": "Einstellungen",
+    "keyword": "Nur Stichwörter der Fragensteller*innen",
+    "full-text": "Nur Nomen aus der Textanalyse der Fragen",
+    "both": "Beides",
+    "select-choice": "Was soll in der Themenwolke angezeigt werden?",
+    "show-blacklist": "Zeige Blacklist",
+    "hide-blacklist": "Verberge Blacklist",
+    "show-profanity-list": "Zeige Liste der Vulgärausdrücke",
+    "hide-profanity-list": "Verberge Liste der Vulgärausdrücke",
+    "keyword-delete": "Thema gelöscht",
+    "keyword-edit": "Thema umbenannt",
+    "keywords-merge": "Themen zusammengefügt",
+    "spacy-labels": "Welche Nomen aus der Textanalyse sollen angezeigt werden?",
+    "changes-gone-wrong": "Etwas ist schiefgelaufen",
+    "english": "Englisch",
+    "german": "Deutsch",
+    "select-all": "Alle auswählen",
+    "keyword-counter": "Anzahl Themen",
+    "sort": "Sortieren",
+    "keyword-from-spacy": "Stichwort aus der Textanalyse",
+    "keyword-from-questioner": "Stichwort vom Fragesteller",
+    "Keyword-from-both": "Stichwort vom Fragensteller und aus der Textanalyse",
+    "test-profanity": "Profanität testen",
+    "word": "Wort",
+    "word-is-profanity": "Wort ist profan",
+    "word-is-not-profanity": "Wort ist nicht profan",
+    "words-in-profanity": "Profane Wörter",
+    "language": "Sprache",
+    "preview": "Vorschau",
+    "topic-requirement-title": "Schwellenwerte für die Anzeige eines Themas",
+    "topic-requirement-questions": "Minimale Anzahl Fragen",
+    "topic-requirement-questioners": "Minimale Anzahl Fragensteller*innen",
+    "topic-requirement-upvotes": "Minimale Anzahl Up-Votes",
+    "topic-requirement-begin-datetime": "Beginn der Zeitspanne",
+    "topic-requirement-end-datetime": "Ende der Zeitspanne",
+    "keywords": "Stichwörter",
+    "topic-requirement-reset": "Zurücksetzen"
   },
   "dialog-comment": {
     "read-more": "Mehr lesen",
     "read-less": "Weniger lesen"
   },
-  "tag-cloud-config":{
-    "title":"Tag-Cloud Einstellungen",
-    "general":"Allgemeine Einstellungen",
-    "overflow":"Ãœberlauf",
-    "height":"Höhe",
-    "random-angle":"Zufallswinkel",
-    "realign":"Neu ausrichten",
-    "background":"Hintergrundfarbe",
-    "word-delay":"Wortverzögerung",
-    "hover-color":"Schriftfarbe",
-    "hover-scale":"Hover Skala",
-    "hover-time":"Hover Zeit",
-    "hover-title":"Hover Einstellungen",
-    "hover-delay":"Hover Verzögerung",
-    "cancel-btn":"Abbruch",
-    "save-btn":"Speichern",
-    "font-size-min":"Schriftgröße min",
-    "font-size-max":"Schriftgröße max",
+  "tag-cloud-config": {
+    "general": "Allgemein",
+    "overflow": "Ãœberlauf",
+    "height": "Höhe",
+    "random-angle": "Themen drehen",
+    "realign": "Neu ausrichten",
+    "background": "Hintergrundfarbe",
+    "word-delay": "Themen verzögert anzeigen",
+    "hover-color": "Schriftfarbe",
+    "hover-scale": "Fokus vergrößern",
+    "hover-time": "Fokus animieren",
+    "hover-title": "Fokus",
+    "hover-delay": "Ansprechzeit",
+    "cancel-btn": "Abbruch",
+    "save-btn": "Speichern",
+    "font-size-min": "Schriftgröße minimal",
+    "font-size-max": "Schriftgröße maximal",
     "select-color": "Farbauswahl",
-    "random-angle-tooltip": "Anordnung der Winkel zufällig generieren",
+    "random-angle-tooltip": "Drehwinkel der Wörter zufällig generieren",
+    "random-angle-note": "Wenn aktiviert, wird die Wortdrehung in den Häufigkeitsgruppen deaktiviert",
     "background-tooltip": "Auswahl der Hintergrundfarbe",
-    "word-delay-tooltip": "Animationsverzögerung der Wörter",
-    "font-size-min-tooltip": "Auswahl der minimalen Schriftgrösse",
-    "font-size-max-tooltip": "Auswahl der maximalen Schriftgrösse",
+    "word-delay-tooltip": "Animationsverzögerung der Themen",
+    "font-size-min-tooltip": "Auswahl der minimalen Schriftgröße",
+    "font-size-max-tooltip": "Verhältnis maximaler zu minimaler Schriftgröße",
     "select-color-tooltip": "Auswahl der Schriftfarbe",
-    "hover-scale-tooltip": "Skallierung der Wörter beim Erscheinen",
-    "hover-time-tooltip": "Festlegen der Erscheinungszeit der Wörter",
-    "hover-delay-tooltip": "Verzögerung der Wörter beim Erscheinen"
+    "hover-scale-tooltip": "Vergrößerungsfaktor des fokussierten Themas",
+    "hover-time-tooltip": "Langsames Vergrößern des fokussierten Themas",
+    "hover-delay-tooltip": "Zeit bis der Hover-Effekt eintritt",
+    "extended-btn": "Häufigkeitsgruppen",
+    "back-btn": "Zurück",
+    "weight-class-settings": "Häufigkeitsgruppen",
+    "weight-class": "Häufigkeitsgruppe",
+    "weight-color": "Schriftfarbe",
+    "weight-number": "max. Anzahl Themen",
+    "weight-color-tooltip": "Auswahl der Schriftfarbe",
+    "weight-number-tooltip": "maximale Anzahl Themen festlegen",
+    "notation": "Schreibweise der Themen",
+    "lowerCase": "Kleinschreibung",
+    "capitalization": "Wortbeginn groß",
+    "upperCase": "Großschreibung",
+    "standard": "wie vom User eingegeben",
+    "alphabetical-sorting": "Alphabetisch sortieren",
+    "cleanUpView": "Tag-Cleanup Einstellungen",
+    "rotation": "Drehgrad zufälliger Einträge",
+    "highestWeight": "Anzahl Themen mit maximaler Gewichtung",
+    "notation-tooltip": "Einstellung der Schreibweise: klein, groß, wie vorgegeben",
+    "alphabetical-sorting-tooltip": "Alphabetische Sortierung",
+    "highestWeight-tooltip": "x Themen mit der höchsten Gewichtung anzeigen",
+    "rotate-weight": "Themen dieser Häufigkeitsgruppe um x Grad drehen",
+    "rotate-weight-tooltip": "Themen dieser Häufigkeitsgruppe um x Grad drehen",
+    "font":"Schrift",
+    "reset-btn": "Auf Standardwerte setzen",
+    "font-family-tooltip": "Schrift auswählen …",
+    "bold-notation-tooltip": "Schrift fett setzen",
+    "font-style-bold" : "Fette Schrift",
+    "font-family":"Schriftart",
+    "manual-weight-number": "Anzahl Themen beschränken",
+    "manual-weight-number-tooltip": "Anzahl Themen der Häufigkeitsgruppe",
+    "manual-weight-number-note": "Begrenzt die Anzahl Themen einer Häufigkeitsgruppe auf den eingestellten Wert"
+  },
+  "user-bonus-token": {
+    "header": "Sterne für Bonuspunkte einlösen",
+    "no-bonus": "Du hast noch keinen Stern für eine gute Frage erhalten.",
+    "redeem-tokens": "Sterne per Mail einlösen",
+    "mail-subject": "Bitte%20um%20Einl%C3%B6sung%20meiner%20Tokens%20aus%20der%20%C2%BBfrag.jetzt%C2%AB-Sitzung%20%C2%BB",
+    "mail-body-1": "Hallo%2C%0D%0A%0D%0Aich%20habe%20heute%20in%20der%20%C2%BBfrag.jetzt%C2%AB-Sitzung%20%C2%BB",
+    "mail-body-2": "%C2%AB%20mit%20dem%20Raum-Code%20%C2%BB",
+    "mail-body-3": "%C2%AB%20die%20folgenden%20Tokens%20erhalten%3A%0D%0A%0D%0A",
+    "mail-body-4": "%0D%0A%0D%0AIch%20bitte%20um%20die%20Einl%C3%B6sung%20in%20Bonuspunkte.%0D%0A%0D%0ADanke%20f%C3%BCr%20%C2%BBfrag.jetzt%C2%AB!%0D%0A%0D%0A---",
+    "choose-session": "Wähle eine Sitzung aus",
+    "please-choose": "Bitte wähle zuerst eine Sitzung aus!"
+  },
+  "introduction": {
+    "cancel": "Schließen",
+    "cancel-description": "Schließe die Einführung und gehe zurück zur Anmeldung.",
+    "title": "Einführung"
   }
 }
diff --git a/src/assets/i18n/participant/en.json b/src/assets/i18n/participant/en.json
index a3ee89b889b31056e4c5e42054c7c7c94c59f5ce..488955f7973462404a894c67166c1968a02c14e2 100644
--- a/src/assets/i18n/participant/en.json
+++ b/src/assets/i18n/participant/en.json
@@ -35,6 +35,7 @@
     "a11y-select-time-1w": "Show all comments of the last 7 days",
     "a11y-select-time-2w": "Show all comments of the last 14 days",
     "a11y-select-time-all": "Show all comments",
+    "a11y-activity": "active user",
     "answered": "Answered questions",
     "add-comment": "Ask a question!",
     "pause-comments": "Freezes the display to read the questions at rest. Questions can still be asked and scored. The display is only updated again by clicking the button.",
@@ -90,18 +91,27 @@
     "token": "Bonus token",
     "token-time": "Token timestamp",
     "no-comments": "There are no questions yet.",
-    "export-comments": "Save questions"
+    "export-comments": "Save questions",
+    "questions-blocked": "New questions blocked"
   },
   "content": {
     "cancel": "Cancel",
     "delete": "Delete"
   },
   "spacy-dialog": {
-    "german": "German",
-    "english": "English",
-    "french": "French",
-    "empty-nouns": "No nouns included",
-    "select-all": "Select all"
+    "auto": "auto",
+    "de": "German",
+    "en": "English",
+    "fr": "French",
+    "select-all": "Select all",
+    "lang-button-hint": "Language for the spell checker",
+    "select-all-hint": "Select all keywords",
+    "select-keyword-hint": "Select this keyword",
+    "edit-keyword-hint": "Edit keyword",
+    "editing-done-hint": "Finish editing",
+    "force-language-selection": "The language of the text input could not be detected automatically.",
+    "add-manually": "Enter a keyword for your question. Separate several keywords with a comma.",
+    "select-keywords": "The text analysis suggests the following keywords. Which best characterise your question?"
   },
   "comment-page": {
     "a11y-comment_input": "Enter your question",
@@ -118,11 +128,13 @@
     "fullscreen": "Click for full view.",
     "abort": "Cancel",
     "ask-question-description": "Enter your question …",
+    "save-answer": "Save",
+    "delete-answer": "Delete",
     "cancel": "Cancel",
     "cancel-description": "Cancel",
     "comment": "Question {{ comment }} was asked at {{ time }} and has currently {{ votes }}. {{correct}} {{wrong}} {{bonus}} {{beamer}}",
     "enter-comment": "Enter your question …",
-    "Markdown-hint": "Format with Markdown",
+    "Markdown-hint": "Format with Markdown & KaTeX",
     "enter-title": "Title",
     "error-both-fields": "Please fill in all fields.",
     "error-comment": "Please enter a question.",
@@ -146,13 +158,16 @@
     "tag-reset": "Reset",
     "tag-to-filter": "Click on the question category to filter questions in that category.",
     "user-number": "Click on the number to filter the questions from this anonymous questioner.",
+    "keywords-per-question": "Click to display the keywords that have been entered for the question.",
+    "keywords": "Keywords",
     "vote-down": "Vote down",
     "vote-up": "Vote up",
     "write-comment": "Write",
     "preview-comment": "Preview",
     "show-more": "Show more",
     "show-less": "Show less",
-    "delete": "Delete question"
+    "delete": "Delete question",
+    "grammar-check": "Spell check"
   },
   "home-page": {
     "exactly-8": "A key is a combination of 8 digits.",
@@ -160,6 +175,20 @@
     "only-numbers": "A key is a combination of digits.",
     "please-enter": "Please enter a session key"
   },
+  "joyride": {
+    "next": "Next",
+    "prev": "Previous",
+    "step": "{{step}} / {{total}}",
+    "done": "Finish",
+    "createQuestion": "Call up the editor with the plus button. An AI will suggest keywords for your question. These will be used to create a topic cloud from all questions of the event.",
+    "createQuestionTitle": "Ask a question",
+    "voting": "The audience can rank questions up or down., indicating their interest in the question or their agreement or disagreement with it.",
+    "votingTitle": "Rate a question",
+    "commentFilter": "There are numerous sorting and filtering options for the question list. An active filter is shown in red. For better readability, the question stream can also be paused if it is very dynamic.",
+    "commentFilterTitle": "Manage question list",
+    "commentUserNumber": "All users ask their questions anonymously. A random number is assigned to each user in order to find all questions of that user. This is done by clicking on the number.",
+    "commentUserNumberTitle": "Find all questions of a user"
+  },
   "room-page": {
     "a11y-announcer": "You are now in the session with the key you entered.",
     "a11y-question_answer": "Opens the page where you can ask questions and vote up or down other questions.",
@@ -222,11 +251,30 @@
     "prev-comment-lbl": "Previous question",
     "next-comment-lbl": "Next question",
     "overview-question-tooltip": "Number of questions",
-    "overview-questioners-tooltip": "Number of questioners"
+    "overview-questioners-tooltip": "Number of questioners",
+    "questions-blocked": "New questions blocked"
   },
   "tag-cloud": {
-    "config": "Modify cloud view",
-    "administration": "Edit cloud topics"
+    "demo-data-topic": "Topic %d",
+    "overview-question-topic-tooltip": "Number of questions with this topic",
+    "overview-questioners-topic-tooltip": "Number of questioners with this topic",
+    "period-since-first-comment":"Period since first comment",
+    "upvote-topic": "Upvotes for this topic",
+    "downvote-topic": "Downvotes for this topic",
+    "blacklist-topic": "Add topic to blacklist"
+  },
+  "tag-cloud-popup": {
+    "few-seconds": "few seconds",
+    "few-minutes": "few minutes",
+    "some-minutes": "{{minutes}} minutes",
+    "one-hour": "1 hour",
+    "some-hours": "{{hours}} hours",
+    "one-day": "1 day",
+    "some-days": "{{days}} days",
+    "one-week": "1 week",
+    "some-weeks": "{{weeks}} weeks",
+    "some-months": "{{months}} months",
+    "tag-correction-placeholder": "Correction"
   },
   "topic-cloud-dialog":{
     "edit": "Edit",
@@ -236,27 +284,62 @@
     "question-count-singular": "Question",
     "question-count-plural": "Questions",
     "edit-keyword-tip": "New topic",
-    "no-keywords-note": "There are no topics!",
+    "no-keywords-note": "There are no topics.",
     "consider-votes": "Consider Votes",
-    "tags-lowercase": "Topics in lowercase",
+    "profanity": "Censor profanity",
+    "hide-blacklist-words": "Hide blacklist keywords",
     "sort-alpha": "Alphabetically",
     "sort-count": "Questions count",
     "sort-vote": "Votes",
-    "keyword-search": "Search keyword"
-  },
-  "topic-cloud-confirm-dialog":{
-    "cancel": "Cancel",
-    "delete": "Delete",
-    "confirm": "Are you sure?",
-    "will-be-deleted": "Topic will be deleted"
+    "keyword-search": "Search keyword",
+    "edit-profanity-list": "Edit profanity list",
+    "edit-blacklist-list": "Edit blacklist list",
+    "add-word": "Add Word",
+    "enter-word": "Enter word",
+    "settings": "Settings",
+    "keyword": "Keyword",
+    "full-text": "Full-text",
+    "both": "Both",
+    "select-choice": "Select one",
+    "show-blacklist": "Show blacklist",
+    "hide-blacklist": "Hide blacklist",
+    "show-profanity-list": "Show profanity list",
+    "hide-profanity-list": "Hide profanity list",
+    "keyword-delete": "keyword deleted",
+    "keyword-edit": "keyword renamed",
+    "keywords-merge": "keywords merged",
+    "spacy-labels": "Which nouns of the text analysis should be displayed as topics?",
+    "changes-gone-wrong": "Something has gone wrong",
+    "english": "English",
+    "german": "German",
+    "select-all": "Select all",
+    "keyword-counter": "Topic count",
+    "sort": "Sort",
+    "keyword-from-spacy": "Keyword from spaCy",
+    "keyword-from-questioner": "Keyword from questioner",
+    "Keyword-from-both": "Keyword from questioner and spaCy",
+    "test-profanity": "Test profanity",
+    "word": "word",
+    "word-is-profanity": "Word is profane",
+    "word-is-not-profanity": "Word is not profane",
+    "words-in-profanity": "Words in profanity filter",
+    "language": "Language",
+    "preview": "Preview",
+    "topic-requirement-title": "Topic requirement",
+    "topic-requirement-questions": "Minimum number of questions",
+    "topic-requirement-questioners": "Minimum number of questioners",
+    "topic-requirement-upvotes": "Minimum number of upvotes",
+    "topic-requirement-begin-datetime": "Earliest comment",
+    "topic-requirement-end-datetime": "Last comment",
+    "keywords": "Keywords",
+    "topic-requirement-reset": "Reset"
   },
   "dialog-comment":{
     "read-more": "Read more",
     "read-less": "Read less"
   },
   "tag-cloud-config":{
-    "title":"Tag-Cloud Options",
-    "general":"General Options",
+    "general":"General",
     "overflow":"Overflow",
     "height":"Height",
     "random-angle":"Randomize angle",
@@ -266,7 +349,7 @@
     "hover-color":"Font-color",
     "hover-scale":"Scale",
     "hover-time":"Hover time",
-    "hover-title":"Hover Options",
+    "hover-title":"Hover",
     "hover-delay":"Hover delay",
     "cancel-btn":"Cancel",
     "save-btn":"Save",
@@ -274,13 +357,62 @@
     "font-size-max":"Font size max",
     "select-color": "Selected color",
     "random-angle-tooltip": "Generate angle randomly",
+    "random-angle-note": "If Enabled, the rotation of the individual weight-class is disabled",
     "background-tooltip": "Select background-color",
     "word-delay-tooltip": "Select word-delay",
     "font-size-min-tooltip": "Select minimum font-size",
-    "font-size-max-tooltip": "Select maximum font-size",
+    "font-size-max-tooltip": "Size ratio max. / min. font size",
     "select-color-tooltip": "Select font-color",
     "hover-scale-tooltip": "Select hover-scale",
     "hover-time-tooltip": "Select hover-time",
-    "hover-delay-tooltip": "Select hover-delay"
+    "hover-delay-tooltip": "Select hover-delay",
+    "extended-btn": "Weight classes",
+    "weight-class-settings": "Weight-classes",
+    "weight-class": "Weight-class",
+    "back-btn": "Back",
+    "weight-color": "Font color",
+    "weight-number": "max. number of keywords",
+    "weight-color-tooltip": "Select font-color",
+    "weight-number-tooltip": "Select maximal number of keywords",
+    "notation": "Notation:",
+    "lowerCase": "Lower case",
+    "capitalization": "Capitalization",
+    "upperCase": "Upper Case",
+    "standard": "Standard",
+    "alphabetical-sorting": "Alphabetical sorting",
+    "cleanUpView": "Tag-Cleanup Settings",
+    "rotation": "rotation of random entries",
+    "highestWeight": "Number of tags with highest weight",
+    "notation-tooltip": "Notation-Settings: small, large, standard",
+    "alphabetical-sorting-tooltip": "Alphabetical sorting",
+    "highestWeight-tooltip": "Show x tags with the highest weight",
+    "rotate-weight": "Rotate all entries of this class by x degrees",
+    "rotate-weight-tooltip": "Rotate all entries of this class by x degrees",
+    "font":"Font",
+    "reset-btn": "Reset",
+    "font-family-tooltip": "Select font",
+    "bold-notation-tooltip": "Select font-thickness bold",
+    "font-style-bold" : "Bold",
+    "font-family":"Font Family",
+    "manual-weight-number": "Set quantity",
+    "manual-weight-number-tooltip": "Quantity Limitation of this weight class",
+    "manual-weight-number-note": "Limits the respective weight class to a self-defined Quantity"
+  },
+  "user-bonus-token": {
+    "header": "Redeem stars for bonus",
+    "no-bonus": "You haven't received a bonus star for a good question yet.",
+    "redeem-tokens": "Redeem stars by mail",
+    "mail-subject": "Request%20to%20redeem%20my%20tokens%20from%20the%20%C2%BBfrag.jetzt%C2%AB-session%20%C2%BB",
+    "mail-body-1": "Hello%2C%0D%0A%0D%0Ai%20have%20received%20the%20following%20tokens%20today%20in%20the%20%C2%BBfrag.jetzt%C2%AB-session%20%C2%BB",
+    "mail-body-2": "%C2%AB%20with%20the%20session%20code%20%C2%BB",
+    "mail-body-3": "%C2%AB%3A%0D%0A%0D%0A",
+    "mail-body-4": "%0D%0A%0D%0AI%20ask%20for%20the%20redemption%20in%20bonus%20points.%0D%0A%0D%0AThanks%20for%20%C2%BBfrag.jetzt%C2%AB!%0D%0A%0D%0A---",
+    "choose-session": "Choose a session",
+    "please-choose": "Please select a session first!"
+  },
+  "introduction": {
+    "cancel": "Close",
+    "cancel-description": "Close introduction.",
+    "title": "Introduction"
   }
 }
diff --git a/src/assets/icons/activity.svg b/src/assets/icons/activity.svg
new file mode 100644
index 0000000000000000000000000000000000000000..7d6eced419daca6d74b1a962ba50d7023bc42321
--- /dev/null
+++ b/src/assets/icons/activity.svg
@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 640 400" enable-background="new 0 0 100 100" xml:space="preserve">
+    <path d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7
+    64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1
+    68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1
+    112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5
+    16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0
+    48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256
+    128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z">
+    </path>
+</svg>
diff --git a/src/assets/icons/hashtag.svg b/src/assets/icons/hashtag.svg
new file mode 100644
index 0000000000000000000000000000000000000000..430432bf99b6471dce98b2e8cf87fd5cefebda05
--- /dev/null
+++ b/src/assets/icons/hashtag.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px"><g><rect fill="none" height="24" width="24"/></g><g><path d="M20,10V8h-4V4h-2v4h-4V4H8v4H4v2h4v4H4v2h4v4h2v-4h4v4h2v-4h4v-2h-4v-4H20z M14,14h-4v-4h4V14z"/></g></svg>
\ No newline at end of file
diff --git a/src/styles.scss b/src/styles.scss
index b8c2a4a3c74eab6efc23a6acfba1fa812baad934..c0d3fa024ba5c9d047e918d0701c414e7d92dd41 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -2,6 +2,11 @@
 @import 'theme/dark-theme/dark-theme';
 @import 'theme/blue-theme/blue-theme';
 @import 'theme/purple-theme/purple-theme';
+
+@import '~katex/dist/katex.min.css';
+@import '~prismjs/plugins/line-numbers/prism-line-numbers.css';
+@import '~prismjs/plugins/line-highlight/prism-line-highlight.css';
+
 // Plus imports for other components in your app.
 
 // Include the common styles for Angular Material. We include this here so that you only
@@ -134,6 +139,7 @@ address {
 
 .mat-card {
   line-height: 1.5 !important;
+  color: var(--on-surface) !important;
 }
 
 a.info {
@@ -184,12 +190,8 @@ a {
   outline: none !important;
 }
 
-.mat-dialog-content {
-  max-height: 40vh !important;
-}
-
 .mat-dialog-container {
-  max-width: 600px !important;
+  max-width: 650px !important;
   margin: 0 auto;
   line-height: 1.5 !important;
 }
@@ -202,6 +204,14 @@ a {
   color: var(--yellow) !important;
 }
 
+.faq {
+  color: var(--on-dialog) !important;
+}
+
+.fullscreen {
+  color: var(--on-dialog) !important;
+}
+
 .mat-icon-button i, .mat-icon-button .mat-icon {
   line-height: 1 !important;
 }
@@ -231,7 +241,10 @@ a {
   height: 3px !important;
 }
 
-.mat-divider {
-  height: 1px !important;
-  border-top-color: rgba(0, 0, 0, 0.12) !important;
+.mat-error {
+  color: var(--red);
+}
+
+.mat-spinner circle {
+  stroke: var(--on-background);
 }
diff --git a/src/theme/blue-theme/blueTheme.const.ts b/src/theme/blue-theme/blueTheme.const.ts
index a53402005dd81b165efc9a0e6b7be8843686a7fd..0a931c7373de92c158462b32792489814ef04b86 100644
--- a/src/theme/blue-theme/blueTheme.const.ts
+++ b/src/theme/blue-theme/blueTheme.const.ts
@@ -39,12 +39,9 @@ export const blue_meta = {
       en: 'ENGLISH_NAME',
       de: 'GERMAN_NAME'
     },
-    description: {
-      en: 'ENGLISH_DESCRIPTION',
-      de: 'GERMAN_DESCRIPTION'
-    }
   },
   isDark: false,
+  availableOnMobile: true,
   order: 4,
   scale_desktop: 1,
   scale_mobile: 1,
diff --git a/src/theme/dark-theme/_dark-theme.scss b/src/theme/dark-theme/_dark-theme.scss
index 6665aa50c89fcf6c94d3c8b85d2d9124a0f7e038..04513bca7b90a69c36c99c9479c96b3c28d93bad 100644
--- a/src/theme/dark-theme/_dark-theme.scss
+++ b/src/theme/dark-theme/_dark-theme.scss
@@ -28,3 +28,16 @@ a {
   background-color: var(--dialog) !important;
   color: var(--on-dialog) !important;
 }
+
+.mat-menu-panel .mat-menu-item:hover {
+  background-color: gray !important;
+  color: white !important;
+}
+
+.mat-radio-outer-circle {
+  border-color: var(--on-dialog) !important;
+}
+
+.mat-radio-button.mat-accent .mat-radio-inner-circle, .mat-radio-button.mat-accent .mat-radio-ripple .mat-ripple-element:not(.mat-radio-persistent-ripple), .mat-radio-button.mat-accent.mat-radio-checked .mat-radio-persistent-ripple, .mat-radio-button.mat-accent:active .mat-radio-persistent-ripple {
+  background-color: var(--on-dialog) !important;
+}
diff --git a/src/theme/dark-theme/darkTheme.const.ts b/src/theme/dark-theme/darkTheme.const.ts
index 51ab726c42ea8336cb8d3c25c68248190f572892..6b66f40413904eb2d434023b5ed0b244d4d19b45 100644
--- a/src/theme/dark-theme/darkTheme.const.ts
+++ b/src/theme/dark-theme/darkTheme.const.ts
@@ -18,7 +18,7 @@ export const dark = {
   '--on-background': '#eadabf',
   '--on-surface': '#eadabf',
   '--on-dialog': '#eadabf',
-  '--on-cancel': '#ffffff',
+  '--on-cancel': '#000000',
 
   '--green': 'lightgreen',
   '--red': 'red',
@@ -42,12 +42,9 @@ export const dark_meta = {
       en: 'Dark Mode',
       de: 'Dark Mode'
     },
-    description: {
-      en: '',
-      de: ''
-    }
   },
   isDark: true,
+  availableOnMobile: true,
   order: 2,
   scale_desktop: 1,
   scale_mobile: 1,
diff --git a/src/theme/high-contrast-theme/highContrastTheme.const.ts b/src/theme/high-contrast-theme/highContrastTheme.const.ts
index e0f84f21daa348932586a46a41a30fdfe6436d52..f5f64d878afb522e3a4d3d3f5121b1055b0705db 100644
--- a/src/theme/high-contrast-theme/highContrastTheme.const.ts
+++ b/src/theme/high-contrast-theme/highContrastTheme.const.ts
@@ -42,12 +42,9 @@ export const highcontrast_meta = {
       en: 'High Contrast',
       de: 'Hoher Kontrast',
     },
-    description: {
-      en: 'Color contrast WCAG 2.1 AA',
-      de: 'Farbkontrast WCAG 2.1 AA',
-    },
   },
   isDark: true,
+  availableOnMobile: true,
   order: 0,
   scale_desktop: 1,
   scale_mobile: 1,
diff --git a/src/theme/light-theme/light-theme.ts b/src/theme/light-theme/light-theme.ts
index cd1c580a4b1ffd038a89943ff365a37dcf3833ce..f2b14a77d573b5c84b4fb38876861380e45cee31 100644
--- a/src/theme/light-theme/light-theme.ts
+++ b/src/theme/light-theme/light-theme.ts
@@ -1,6 +1,6 @@
 export const arsnova = {
 
-  '--primary' : '#00324a',
+  '--primary': 'green',
   '--primary-variant': 'LightGoldenrodYellow',
 
   '--secondary': 'maroon',
@@ -20,7 +20,7 @@ export const arsnova = {
   '--on-dialog': '#000000',
   '--on-cancel': '#ffffff',
 
-  '--green': '#00FF00',
+  '--green': 'green',
   '--red': 'red',
   '--white': '#ffffff',
   '--yellow': 'red',
@@ -42,12 +42,9 @@ export const arsnova_meta = {
       en: 'Light Mode',
       de: 'Light Mode'
     },
-    description: {
-      en: '',
-      de: ''
-    }
   },
   isDark: false,
+  availableOnMobile: true,
   order: 3,
   scale_desktop: 1,
   scale_mobile: 1,
diff --git a/src/theme/purple-theme/purpleTheme.const.ts b/src/theme/purple-theme/purpleTheme.const.ts
index 9dc5b0bbcf647c41be74cd093732b0b17be81b48..1e60f396d0406d473e98301c3bce58c749055614 100644
--- a/src/theme/purple-theme/purpleTheme.const.ts
+++ b/src/theme/purple-theme/purpleTheme.const.ts
@@ -1,6 +1,6 @@
 export const purple = {
 
-  '--primary' : '#00324a',
+  '--primary': '#00324a',
   '--primary-variant': 'white',
 
   '--secondary': '#ff4500',
@@ -31,7 +31,7 @@ export const purple = {
   '--grey': 'slategrey',
   '--grey-light': 'lightgrey',
   '--black': 'black',
-  '--moderator': 'lightsalmon'
+  '--moderator': 'lightsalmon',
 
 };
 
@@ -40,17 +40,14 @@ export const purple_meta = {
   translation: {
     name: {
       en: 'Projector',
-      de: 'Beamer'
+      de: 'Beamer',
     },
-    description: {
-      en: 'Optimized for canvas',
-      de: 'Optimiert für die Leinwand'
-    }
   },
   isDark: false,
+  availableOnMobile: false,
   order: 1,
-  scale_desktop: 1.3,
+  scale_desktop: 1.5,
   scale_mobile: 1,
-  previewColor: 'background'
+  previewColor: 'background',
 
 };
diff --git a/src/theme/theme.directive.ts b/src/theme/theme.directive.ts
index 40d08c6e9faecb15ffb2e396a8e1cf3b9813e3ca..b175ba97362385e711c0f461622713c96c5fff1b 100644
--- a/src/theme/theme.directive.ts
+++ b/src/theme/theme.directive.ts
@@ -10,7 +10,7 @@ import { Subscription } from 'rxjs';
 
 export class ThemeDirective implements OnInit, OnDestroy {
 
-  private themeName = 'dark';
+  private themeName;
   private themServiceSubscription: Subscription;
 
   constructor(private elementRef: ElementRef,
@@ -20,7 +20,6 @@ export class ThemeDirective implements OnInit, OnDestroy {
   }
 
   ngOnInit() {
-    this.updateTheme(this.themeName);
     this.themService.getTheme()
       .subscribe(themeName => {
         this.themeName = themeName;
@@ -29,7 +28,7 @@ export class ThemeDirective implements OnInit, OnDestroy {
   }
 
   updateTheme(themeName: string) {
-    const them = themes[ themeName ];
+    const them = themes[themeName];
     for (const key in them) {
       if (them.hasOwnProperty(key)) {
         this.renderer.setProperty(this.elementRef.nativeElement, key, them[key]);
diff --git a/src/theme/theme.service.ts b/src/theme/theme.service.ts
index e541a0f282f194b5129b9c42dada89494981c173..d35a3129029a019c03c74e54035999b5f7827cd2 100644
--- a/src/theme/theme.service.ts
+++ b/src/theme/theme.service.ts
@@ -1,7 +1,7 @@
 import { Injectable } from '@angular/core';
 import { BehaviorSubject } from 'rxjs';
 import { themes, themes_meta } from './arsnova-theme.const';
-import { Theme, ThemeTranslationList } from './Theme';
+import { Theme } from './Theme';
 
 @Injectable({
   providedIn: 'root'
@@ -12,8 +12,12 @@ export class ThemeService {
   private themes: Theme[] = [];
 
   constructor() {
+    const isMobile = window.matchMedia && window.matchMedia('(max-width: 499px)').matches;
     // eslint-disable-next-line guard-for-in
     for (const k in themes) {
+      if (!themes_meta[k].availableOnMobile && isMobile) {
+        continue;
+      }
       this.themes.push(new Theme(
         k,
         themes[k],
@@ -28,6 +32,18 @@ export class ThemeService {
       }
       return 0;
     });
+    const isDark = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)').matches : true;
+    const selectedTheme = this.themes.find(elem => elem.key === this.themeName);
+    if (!this.themeName || !selectedTheme || selectedTheme.isDark !== isDark) {
+      for (let i = this.themes.length - 1; i > 0; i--) {
+        const theme = this.themes[i];
+        if (theme.isDark === isDark) {
+          this.themeName = theme.key;
+          break;
+        }
+      }
+      this.activate(this.themeName);
+    }
   }
 
   public getTheme() {