diff --git a/angular.json b/angular.json index a1cf4f69c7fa2591a298a70475469dcd2efa40ca..94cb7e5259bcd28c9dd604dd9d4629300e7244f4 100644 --- a/angular.json +++ b/angular.json @@ -59,7 +59,8 @@ "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { - "browserTarget": "arsnova-angular-frontend:build" + "browserTarget": "arsnova-angular-frontend:build", + "proxyConfig": "proxy.conf.json" }, "configurations": { "production": { diff --git a/package-lock.json b/package-lock.json index 637d9c346f53eafcda1a2bf24900f56f2f414ea4..6ee4ddaa1060204a511f0c9f88180a134d23b096 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1951,11 +1951,6 @@ "yargs": "8.0.2" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -2056,11 +2051,6 @@ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", @@ -2115,14 +2105,6 @@ } } }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", @@ -3881,7 +3863,8 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "base": { "version": "0.11.2", @@ -4166,6 +4149,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4943,7 +4927,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.2", @@ -5777,15 +5762,6 @@ "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", "dev": true }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -6448,36 +6424,9 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, "requires": { "is-arrayish": "^0.2.1" - }, - "dependencies": { - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "requires": { - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } } }, "es-to-primitive": { @@ -7335,10 +7284,20 @@ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "qs": { "version": "6.7.0", @@ -7648,6 +7607,12 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -7934,7 +7899,8 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "fsevents": { "version": "2.3.2", @@ -8064,6 +8030,7 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -8122,7 +8089,8 @@ "graceful-fs": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", + "dev": true }, "handle-thing": { "version": "2.0.1", @@ -8848,6 +8816,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -8856,7 +8825,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "ini": { "version": "2.0.0", @@ -9002,7 +8972,8 @@ "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true }, "ip": { "version": "1.1.5", @@ -9060,7 +9031,8 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true }, "is-bigint": { "version": "1.0.1", @@ -9246,10 +9218,9 @@ } }, "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" }, "is-regex": { "version": "1.0.5", @@ -9269,7 +9240,8 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true }, "is-string": { "version": "1.0.5", @@ -9330,7 +9302,8 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "isobject": { "version": "3.0.1", @@ -9997,6 +9970,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, "requires": { "invert-kv": "^1.0.0" } @@ -10144,6 +10118,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -10155,6 +10130,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, "requires": { "error-ex": "^1.2.0" } @@ -10162,7 +10138,8 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true } } }, @@ -10439,6 +10416,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, "requires": { "mimic-fn": "^1.0.0" }, @@ -10446,7 +10424,8 @@ "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true } } }, @@ -10652,6 +10631,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -11150,6 +11130,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -11160,7 +11141,8 @@ "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true } } }, @@ -11380,6 +11362,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, "requires": { "path-key": "^2.0.0" } @@ -11603,6 +11586,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } @@ -11766,6 +11750,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, "requires": { "execa": "^0.7.0", "lcid": "^1.0.0", @@ -11776,6 +11761,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, "requires": { "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", @@ -11786,6 +11772,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, "requires": { "cross-spawn": "^5.0.1", "get-stream": "^3.0.0", @@ -11799,12 +11786,14 @@ "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true }, "lru-cache": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -11813,7 +11802,8 @@ "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true } } }, @@ -11826,7 +11816,8 @@ "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true }, "p-map": { "version": "4.0.0", @@ -11952,6 +11943,14 @@ "dev": true, "requires": { "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } } }, "parse-asn1": { @@ -12108,7 +12107,8 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-is-inside": { "version": "1.0.2", @@ -12119,12 +12119,14 @@ "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true }, "path-to-regexp": { "version": "0.1.7", @@ -12810,11 +12812,6 @@ "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", "dev": true }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" - }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -13211,7 +13208,8 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true }, "psl": { "version": "1.8.0", @@ -13438,6 +13436,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, "requires": { "load-json-file": "^2.0.0", "normalize-package-data": "^2.3.2", @@ -13448,6 +13447,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, "requires": { "pify": "^2.0.0" } @@ -13455,7 +13455,8 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true } } }, @@ -13463,6 +13464,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, "requires": { "find-up": "^2.0.0", "read-pkg": "^2.0.0" @@ -13472,6 +13474,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, "requires": { "locate-path": "^2.0.0" } @@ -13480,6 +13483,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -13489,6 +13493,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, "requires": { "p-try": "^1.0.0" } @@ -13497,6 +13502,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, "requires": { "p-limit": "^1.1.0" } @@ -13504,7 +13510,8 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true } } }, @@ -13703,6 +13710,7 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, "requires": { "path-parse": "^1.0.6" } @@ -13927,6 +13935,14 @@ "dev": true, "requires": { "is-promise": "^2.1.0" + }, + "dependencies": { + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + } } }, "run-parallel": { @@ -14198,7 +14214,8 @@ "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true }, "semver-intersect": { "version": "1.4.0", @@ -14401,6 +14418,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, "requires": { "shebang-regex": "^1.0.0" } @@ -14408,12 +14426,14 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true }, "simple-swizzle": { "version": "0.2.2", @@ -14894,6 +14914,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -14902,12 +14923,14 @@ "spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -14916,7 +14939,8 @@ "spdx-license-ids": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true }, "spdy": { "version": "4.0.2", @@ -15306,12 +15330,14 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true }, "strip-json-comments": { "version": "2.0.1", @@ -16317,9 +16343,9 @@ } }, "url-parse": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", - "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", + "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", "dev": true, "requires": { "querystringify": "^2.1.1", @@ -16386,6 +16412,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -17665,6 +17692,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, "requires": { "isexe": "^2.0.0" } @@ -17784,7 +17812,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "xml2js": { "version": "0.4.23", @@ -17964,9 +17993,9 @@ "dev": true }, "zone.js": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz", - "integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==" + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.2.tgz", + "integrity": "sha512-UAYfiuvxLN4oyuqhJwd21Uxb4CNawrq6fPS/05Su5L4G+1TN+HVDJMUHNMobVQDFJRir2cLAODXwluaOKB7HFg==" } } } diff --git a/package.json b/package.json index 8a0376f0f305f79aba9ed5e33e43f9bbc27cd1a8..0490a9415e23746ff989add14c41778ccbdfee5c 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "license": "MIT", "scripts": { "ng": "ng", - "start": "ng serve --proxy-config proxy.conf.json", + "start": "ng serve", "build": "ng build --prod", "test": "ng test --watch=false --browsers=ChromeHeadlessCustom --source-map=false --code-coverage", "lint": "ng lint", @@ -33,6 +33,7 @@ "chart.js": "^2.7.3", "core-js": "^2.5.7", "is-docker": "^1.1.0", + "is-promise": "^4.0.0", "material-design-icons": "^3.0.1", "ngx-markdown": "^11.1.3", "ngx-matomo-v9": "^0.3.0", diff --git a/proxy.conf.json b/proxy.conf.json index d77258a7a9e95751643c69901ad3180eabda246e..d9c429863b7cd7022076d74148411dac622414e8 100644 --- a/proxy.conf.json +++ b/proxy.conf.json @@ -5,7 +5,8 @@ "changeOrigin": true, "pathRewrite": { "^/spacy": "" - } + }, + "logLevel": "debug" }, "/api/ws/websocket": { "target": "ws://localhost:8080", diff --git a/src/app/components/shared/header/header.component.html b/src/app/components/shared/header/header.component.html index 6b6736b44a8e50281069a4066190c4c9c56de869..0c56aa0ccfd73a9ced7a025b6e46cdce9f75e8d4 100644 --- a/src/app/components/shared/header/header.component.html +++ b/src/app/components/shared/header/header.component.html @@ -65,7 +65,8 @@ <!-- Moderator board / index --> - <ng-container *ngIf="user && user.role > 0 && (router.url.endsWith('/moderator/comments') || router.url.includes('/comment/'))"> + <ng-container + *ngIf="user && user.role > 0 && (router.url.endsWith('/moderator/comments') || router.url.includes('/comment/'))"> <button mat-menu-item tabindex="0" @@ -138,11 +139,8 @@ </button> - - <button mat-menu-item tabindex="0" - *ngIf="deviceType !== 'mobile'" routerLink="participant/room/{{shortId}}/comments/tagcloud"> <mat-icon>cloud </mat-icon> @@ -218,7 +216,8 @@ <!-- Room General Options - bot --> - <ng-container *ngIf="user && user.role == 3 && !router.url.includes('/participant') && !router.url.includes('/comment/')"> + <ng-container + *ngIf="user && user.role == 3 && !router.url.includes('/participant') && !router.url.includes('/comment/')"> <button mat-menu-item *ngIf="user" @@ -239,7 +238,7 @@ </ng-container> <button mat-menu-item - *ngIf="user && user.role > 0 && !router.url.includes('/comment/')" + *ngIf="user && user.role > 0 && !router.url.includes('/comment/') && !router.url.endsWith('/tagcloud')" tabindex="0" (click)="showQRDialog();"> <mat-icon svgIcon="qrcode" @@ -248,6 +247,42 @@ <span>{{'header.room-qr' | translate}}</span> </button> + <button mat-menu-item + *ngIf="router.url.endsWith('/tagcloud')" + tabindex="0" + (click)="navigateTopicCloudConfig()"> + <mat-icon aria-label="Configuration Icon">cloud</mat-icon> + <span>{{'header.tag-cloud-config' | translate}}</span> + </button> + + <button mat-menu-item + *ngIf="router.url.endsWith('/tagcloud')" + tabindex="0" + (click)="navigateTopicCloudAdministration()"> + <mat-icon aria-hidden="false" aria-label="Control Icon">edit</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 + </mat-icon> + <span>{{'header.create-question' | 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> + </button> + </ng-container> </div> diff --git a/src/app/components/shared/header/header.component.ts b/src/app/components/shared/header/header.component.ts index af57ebfd933f8e6c31dbf413172f57a926fbad05..10c46b58c5d226e313c1e82b8a901089ee5a4a4e 100644 --- a/src/app/components/shared/header/header.component.ts +++ b/src/app/components/shared/header/header.component.ts @@ -281,4 +281,12 @@ export class HeaderComponent implements OnInit { this.eventService.broadcast('navigate', 'createQuestion'); } + public navigateTopicCloudConfig() { + this.eventService.broadcast('navigate', 'topicCloudConfig'); + } + + public navigateTopicCloudAdministration() { + this.eventService.broadcast('navigate', 'topicCloudAdministration'); + } + } 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 5cdc8bf3a72815c8d63038145b163fe506e9f75a..b818b9809361b0c1c17050f04154a7fda5b2a9f3 100644 --- a/src/app/components/shared/tag-cloud/tag-cloud.component.html +++ b/src/app/components/shared/tag-cloud/tag-cloud.component.html @@ -1,38 +1,28 @@ <ars-screen ars-flex-box> - <ars-row [height]="100"> - + <ars-row [height]="65"> </ars-row> - <ars-row ars-flex-box> - <ars-col> - - </ars-col> - <ars-col class="config"> - <button mat-menu-item> - <mat-icon aria-hidden="false" aria-label="Configuration Icon">cloud</mat-icon> - <span>{{'tag-cloud.config' | translate}}</span> - </button> - <button mat-menu-item (click)="openAdministrationDialog()"> - <mat-icon aria-hidden="false" aria-label="Control Icon">edit</mat-icon> - <span>{{'tag-cloud.administration' | translate}}</span> - </button> - </ars-col> - </ars-row> - - <ars-fill ars-flex-box style="width:100%;height:100%;"> + <mat-drawer-container class="spacyTagCloudContainer"> + <mat-drawer [(opened)]="configurationOpen" position="start"> + Test <!-- TODO: Gruppe 4 --> + </mat-drawer> + <mat-drawer-content> + <ars-fill ars-flex-box> <angular-tag-cloud class="spacyTagCloud" + (window:resize)="onResize($event)" + (afterInit)="initTagCloud()" [data]="data" [width]="options.width" [height]="options.height" [overflow]="options.overflow" + [delay]="options.delay" + [randomizeAngle]="false" [zoomOnHover]="zoomOnHoverOptions" - [realignOnResize]="true" - [log]='"debug"'> + [realignOnResize]="false"> </angular-tag-cloud> - </ars-fill> - - <ars-row [height]="100"> - + </ars-fill> + </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 3520bd22be8fb8bd3be3c52a59aa8e0a2a1aeecd..c7f5e1cf8ec487752240700f43686de7bbec8c19 100644 --- a/src/app/components/shared/tag-cloud/tag-cloud.component.scss +++ b/src/app/components/shared/tag-cloud/tag-cloud.component.scss @@ -1,63 +1,15 @@ -.config { - span { - display: none; - } - - mat-icon { - margin: 0; - } +ars-fill { + width: calc(100% - 30px); + height: calc(100% - 30px); + margin: 15px; } -.config:hover { - background-color:#052338; - span { - margin-left: 16px; - display: inline; - } +mat-drawer-container { + height: 100%; + width: 100%; + position: fixed; } -::ng-deep .spacyTagCloud > span { - &.w10 { - color: brown !important; - font-size: 380% !important; - } - &.w9 { - color: white !important; - font-size: 330% !important; - } - &.w8 { - color: tomato !important; - font-size: 280% !important; - } - &.w7 { - color: lightgreen !important; - font-size: 240% !important; - } - &.w6 { - color: gray !important; - font-size: 210% !important; - } - &.w5 { - color: pink !important; - font-size: 180% !important; - } - &.w4 { - color: orange !important; - font-size: 160% !important; - } - &.w3 { - color: yellow !important; - font-size: 140% !important; - } - &.w2 { - color: green !important; - font-size: 120% !important; - } - &.w1 { - color: lightblue !important; - font-size: 100% !important; - } - &:hover { - color: greenyellow !important; - } +mat-drawer { + background-color: var(--dialog); } 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 6891443b59810b28733c34d6aeddfa216796b13d..4cfd621062c94d1811e4b2e81b1151b796aa86e6 100644 --- a/src/app/components/shared/tag-cloud/tag-cloud.component.ts +++ b/src/app/components/shared/tag-cloud/tag-cloud.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit, ViewChild} from '@angular/core'; +import {Component, OnInit, ViewChild, Input} from '@angular/core'; import { CloudData, @@ -10,11 +10,36 @@ import { 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 {QuestionWallComment} from "../questionwall/QuestionWallComment"; -import { MatDialog } from '@angular/material/dialog'; -import { TopicCloudAdministrationComponent } from '../_dialogs/topic-cloud-administration/topic-cloud-administration.component'; +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'; + +class CustomPosition implements Position { + left: number; + top: number; + + constructor(public relativeLeft: number, + public relativeTop: number) { + } + + updatePosition(width: number, height: number, text: string, style: CSSStyleDeclaration) { + const offsetY = parseFloat(style.height) / 2; + const offsetX = parseFloat(style.width) / 2; + this.left = width * this.relativeLeft - offsetX; + this.top = height * this.relativeTop - offsetY; + } +} class TagComment implements CloudData { constructor(public color: string, @@ -28,17 +53,90 @@ class TagComment implements CloudData { } } -const weight2color = { - 1: 'blue', - 2: 'green', - 3: 'yellow', - 4: 'orange', - 5: 'pink', - 6: 'gray', - 7: 'lightgreen', - 8: 'tomato', - 9: 'white', - 10: 'brown' +//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 + } }; @Component({ @@ -49,30 +147,45 @@ const weight2color = { export class TagCloudComponent implements OnInit { @ViewChild(TCloudComponent, {static: false}) child: TCloudComponent; - roomId: string; + @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: 1, + 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: 1, + height: 0.99, overflow: false, - font: 'Georgia' // not working + font: 'Georgia', // not working + 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 - color: 'red' + delay: 0.4 // Zoom will take affect after 0.4 seconds }; - + userRole: UserRole; data: CloudData[] = []; - + sorted = false; + debounceTimer = 0; + lastDebounceTime = 0; + configurationOpen = false; + randomizeAngle = false; constructor(private commentService: CommentService, private spacyService: SpacyService, private langService: LanguageService, private translateService: TranslateService, - public dialog: MatDialog) { + public dialog: MatDialog, + private notificationService: NotificationService, + public eventService: EventService, + private authenticationService: AuthenticationService, + private route: ActivatedRoute, + protected roomService: RoomService, + private themeService: ThemeService) { this.roomId = localStorage.getItem('roomId'); this.langService.langEmitter.subscribe(lang => { this.translateService.use(lang); @@ -80,10 +193,120 @@ export class TagCloudComponent implements OnInit { } ngOnInit(): void { + this.headerInterface = this.eventService.on<string>('navigate').subscribe(e => { + if (e === 'createQuestion') { + this.openCreateDialog(); + } else if (e === 'topicCloudConfig') { + this.configurationOpen = !this.configurationOpen; + } else if (e === 'topicCloudAdministration') { + // TODO Group 5: OPEN Topic Cloud Administration + } + }); + this.authenticationService.watchUser.subscribe(newUser => { + if (newUser) { + this.user = newUser; + } + }); + this.userRole = this.route.snapshot.data.roles[0]; + this.route.params.subscribe(params => { + this.shortId = params['shortId']; + this.authenticationService.guestLogin(UserRole.PARTICIPANT).subscribe(r => { + this.roomService.getRoomByShortId(this.shortId).subscribe(room => { + this.room = room; + this.roomId = room.id; + this.directSend = this.room.directSend; + if (!this.authenticationService.hasAccess(this.shortId, UserRole.PARTICIPANT)) { + this.roomService.addToHistory(this.room.id); + this.authenticationService.setAccess(this.shortId, UserRole.PARTICIPANT); + } + }); + }); + }); this.translateService.use(localStorage.getItem('currentLang')); this.commentService.getAckComments(this.roomId).subscribe((comments: Comment[]) => { this.analyse(comments); }); + this.themeService.getTheme().subscribe(() => { + if (this.child) { + setTimeout(() => { + this.setCloudParameters(this.getCurrentCloudParameters(), false); + this.updateTagCloud(); + }, 1); + } + }); + } + + initTagCloud() { + setTimeout(() => { + this.setCloudParameters(this.getCurrentCloudParameters(), false); + }); + } + + resetColorsToTheme() { + this.setCloudParameters(getDefaultCloudParameters()); + } + + getCurrentCloudParameters(): CloudParameters { + const jsonData = localStorage.getItem('tagCloudConfiguration'); + const elem: CloudParameters = jsonData != null ? JSON.parse(jsonData) : null; + return elem || getDefaultCloudParameters(); + } + + 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 + ';'; + } + }); + 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)); + } + } + + onResize(event: UIEvent): any { + this.updateTagCloud(); + } + + sortPositionsAlphabetically(sort: boolean): void { + if (!sort) { + this.sorted = false; + this.data.forEach(e => e.position = null); + return; + } + this.sorted = true; + if (!this.data.length) { + return; + } + 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)); + } + } } analyse(comments: Comment[]) { @@ -91,31 +314,93 @@ export class TagCloudComponent implements OnInit { this.spacyService.analyse(commentsConcatenated, 'de').subscribe((res: Result) => { const map = new Map<string, number>(); - let maxCount = 0; res.words.filter(w => ['NE', 'NN', 'NMP', 'NNE'].indexOf(w.tag) >= 0).forEach(elem => { const count = (map.get(elem.text) || 0) + 1; - if (count > maxCount) { - maxCount = count; - } map.set(elem.text, count); }); - this.data.length = 0; // Clear array map.forEach((val, key) => { - const weight = 9 * val / maxCount + 1; - console.log(weight + ' ' + typeof weight); this.data.push(new TagComment(null, true, null, null, - /*Math.floor(Math.random() * 30 - 15)*/0, key, - 'TODO', weight)); + this.randomizeAngle ? Math.floor(Math.random() * 30 - 15) : 0, key, + 'TODO', val)); } ); + this.sortPositionsAlphabetically(this.sorted); + this.updateTagCloud(); + }); + } + + 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])); + }); + } + const debounceTime = 1_000; + const current = new Date().getTime(); + const diff = current - this.lastDebounceTime; + if (diff >= debounceTime) { + this.lastDebounceTime = current; this.child.reDraw(); + } else { + clearTimeout(this.debounceTimer); + this.debounceTimer = setTimeout(() => { + this.lastDebounceTime = new Date().getTime(); + this.child.reDraw(); + }, debounceTime - diff); + } + } + + 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; + } + }); } - openAdministrationDialog(){ - this.dialog.open(TopicCloudAdministrationComponent, { - minWidth: '50%' + 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; + } + if (this.userRole === 0) { + this.translateService.get('comment-list.comment-sent-to-moderator').subscribe(msg => { + this.notificationService.show(msg); + }); + } + } + this.commentService.addComment(comment).subscribe(); } } diff --git a/src/app/components/shared/tag-cloud/tag-cloud.interface.ts b/src/app/components/shared/tag-cloud/tag-cloud.interface.ts new file mode 100644 index 0000000000000000000000000000000000000000..b3faae6f98bc4f485fc2ed4bbaeaefdbc71be061 --- /dev/null +++ b/src/app/components/shared/tag-cloud/tag-cloud.interface.ts @@ -0,0 +1,38 @@ +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/assets/i18n/home/de.json b/src/assets/i18n/home/de.json index 75c63c88f35ba3bd3d76f93bf6a75885d9edb36e..867cde48d834dcf2268d4cff10388c7b462c31c2 100644 --- a/src/assets/i18n/home/de.json +++ b/src/assets/i18n/home/de.json @@ -82,9 +82,11 @@ "moderationboard": "Zum Index", "create-question": "Frage stellen", "questionwall": "Fragen-Fokus", - "tag-cloud": "Wortwolke", + "tag-cloud": "Themenwolke", "fullscreen": "Text skalieren", - "motd": "News" + "motd": "News", + "tag-cloud-config": "Wolkenansicht ändern", + "tag-cloud-administration": "Wolkenthemen editieren" }, "help": { "cancel": "Schließen", diff --git a/src/assets/i18n/home/en.json b/src/assets/i18n/home/en.json index 51e5bfc71d3a61e081631a1c2303dbca1a456c27..aa0bf64d612e7d8cfe9fec3b78e6051dd101d00d 100644 --- a/src/assets/i18n/home/en.json +++ b/src/assets/i18n/home/en.json @@ -85,7 +85,9 @@ "questionwall": "Question focus", "tag-cloud": "Topic cloud", "fullscreen": "Text scaling", - "motd": "News" + "motd": "News", + "tag-cloud-config": "Modify cloud view", + "tag-cloud-administration": "Edit cloud topics" }, "help": { "cancel": "Close",