diff --git a/.gitignore b/.gitignore index af98ecfb6..f37d1f47b 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ src/environments/environment.researchfi.ts src/environments/environment.researchfi.prod.ts src/assets/config/config.json src/assets/config/auth_config.json +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/angular.json b/angular.json index 10a7014ca..8795a6481 100644 --- a/angular.json +++ b/angular.json @@ -92,11 +92,23 @@ "en": { "localize": [ "en" + ], + "fileReplacements": [ + { + "replace": "src/environments/locale.ts", + "with": "src/environments/locale.en.ts" + } ] }, "sv": { "localize": [ "sv" + ], + "fileReplacements": [ + { + "replace": "src/environments/locale.ts", + "with": "src/environments/locale.sv.ts" + } ] }, "es5": { diff --git a/package-lock.json b/package-lock.json index 5d841ebe9..90afe3d6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55,6 +55,7 @@ "mississippi": "^4.0.0", "ngx-bootstrap": "^9.0.0", "ngx-countup": "^13.0.0", + "ngx-pipes": "^3.2.2", "nodemailer": "^6.7.8", "popper.js": "^1.16.0", "referrer-policy": "^1.2.0", @@ -66,6 +67,7 @@ "through2": "^4.0.2", "timers": "^0.1.1", "tslib": "^2.1.0", + "valibot": "^0.17.0", "zone.js": "~0.11.8" }, "devDependencies": { @@ -83,6 +85,7 @@ "@babel/preset-env": "^7.16.11", "@fortawesome/fontawesome-free": "^6.0.0", "@ngx-i18nsupport/ngx-i18nsupport": "^1.1.6", + "@playwright/test": "^1.39.0", "@types/d3": "^7.1.0", "@types/express": "^4.17.11", "@types/jasmine": "~3.6.6", @@ -3610,10 +3613,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -3623,7 +3625,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -3934,6 +3935,21 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/@playwright/test": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.39.0.tgz", + "integrity": "sha512-3u1iFqgzl7zr004bGPYiN/5EZpRUSFddQBra8Rqll5N0/vfpqlP9I9EXqAoGacuAbX6c9Ulg/Cjqglp5VkK6UQ==", + "dev": true, + "dependencies": { + "playwright": "1.39.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -4281,7 +4297,6 @@ "version": "8.4.10", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", - "dev": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -4291,7 +4306,6 @@ "version": "3.7.4", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -4300,8 +4314,7 @@ "node_modules/@types/estree": { "version": "0.0.51", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" }, "node_modules/@types/express": { "version": "4.17.14", @@ -4359,8 +4372,7 @@ "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" }, "node_modules/@types/lodash": { "version": "4.14.188", @@ -4386,8 +4398,7 @@ "node_modules/@types/node": { "version": "17.0.45", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", - "dev": true + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -4739,7 +4750,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.1" @@ -4748,26 +4758,22 @@ "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.1", "@webassemblyjs/helper-api-error": "1.11.1", @@ -4777,14 +4783,12 @@ "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-buffer": "1.11.1", @@ -4796,7 +4800,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -4805,7 +4808,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -4813,14 +4815,12 @@ "node_modules/@webassemblyjs/utf8": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-buffer": "1.11.1", @@ -4836,7 +4836,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.1", @@ -4849,7 +4848,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-buffer": "1.11.1", @@ -4861,7 +4859,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-api-error": "1.11.1", @@ -4875,7 +4872,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.1", "@xtuc/long": "4.2.2" @@ -4920,14 +4916,12 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", @@ -4959,9 +4953,9 @@ } }, "node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "bin": { "acorn": "bin/acorn" }, @@ -4990,10 +4984,9 @@ } }, "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "peerDependencies": { "acorn": "^8" } @@ -5101,7 +5094,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5156,7 +5148,6 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -5965,7 +5956,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, "engines": { "node": ">=6.0" } @@ -6095,8 +6085,7 @@ "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "node_modules/commondir": { "version": "1.0.1", @@ -7701,10 +7690,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", - "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", - "dev": true, + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -7813,8 +7801,7 @@ "node_modules/es-module-lexer": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" }, "node_modules/es6-promise": { "version": "4.2.8", @@ -8316,7 +8303,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -8329,7 +8315,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } @@ -8667,7 +8652,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -8715,7 +8699,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } @@ -8885,8 +8868,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.2.12", @@ -8919,8 +8901,7 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -9401,8 +9382,7 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "node_modules/globals": { "version": "11.12.0", @@ -9446,8 +9426,7 @@ "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "node_modules/grapheme-splitter": { "version": "1.0.4", @@ -10763,7 +10742,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -10777,7 +10755,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -10786,7 +10763,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -10917,8 +10893,7 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema": { "version": "0.4.0", @@ -10929,8 +10904,7 @@ "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -11409,7 +11383,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, "engines": { "node": ">=6.11.5" } @@ -11844,8 +11817,7 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", @@ -12174,9 +12146,15 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -12248,8 +12226,7 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/ngx-bootstrap": { "version": "9.0.0", @@ -12279,6 +12256,223 @@ "@angular/core": ">=13.0.0" } }, + "node_modules/ngx-pipes": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/ngx-pipes/-/ngx-pipes-3.2.2.tgz", + "integrity": "sha512-nhNIUJe/bud5ir4RD2YDA6MdrJUh3YASIcNrMFX9WljTxuvAb99SZ88PaKSFGy9SXjHg8MxjxHfCoOLlTkxxlQ==", + "dependencies": { + "postcss": "^8.4.19", + "tslib": "^2.3.0", + "webpack": "^5.75.0" + }, + "peerDependencies": { + "@angular/core": ">=14" + } + }, + "node_modules/ngx-pipes/node_modules/@types/estree": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", + "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==" + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/ngx-pipes/node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/ngx-pipes/node_modules/es-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", + "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==" + }, + "node_modules/ngx-pipes/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/ngx-pipes/node_modules/webpack": { + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, "node_modules/nice-napi": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", @@ -13467,6 +13661,36 @@ "node": ">=8" } }, + "node_modules/playwright": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.39.0.tgz", + "integrity": "sha512-naE5QT11uC/Oiq0BwZ50gDmy8c8WLPRTEWuSSFVG2egBka/1qMoSqYQcROMT9zLwJ86oPofcTH2jBY/5wWOgIw==", + "dev": true, + "dependencies": { + "playwright-core": "1.39.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.39.0.tgz", + "integrity": "sha512-+k4pdZgs1qiM+OUkSjx96YiKsXsmb59evFoqv8SKO067qBA+Z2s/dCzJij/ZhdQcs2zlTAgRKfeiiLm8PQ2qvw==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/popper.js": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", @@ -13478,9 +13702,9 @@ } }, "node_modules/postcss": { - "version": "8.4.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz", - "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -13489,10 +13713,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -14729,7 +14957,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -15583,10 +15810,9 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "dependencies": { "randombytes": "^2.1.0" } @@ -15853,7 +16079,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -15903,7 +16128,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -16238,7 +16462,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -16278,16 +16501,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", - "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", - "dev": true, + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.14", + "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" }, "engines": { "node": ">= 10.13.0" @@ -16315,7 +16537,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -16329,6 +16550,23 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/terser-webpack-plugin/node_modules/terser": { + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.22.0.tgz", + "integrity": "sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw==", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -16794,7 +17032,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -16830,6 +17067,11 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/valibot": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-0.17.0.tgz", + "integrity": "sha512-ykoYfBc4HOH+osdWaFBmeL7yX35bFfKg1WdwHYZhNVuvGIRH5f2gtYT6cnU85XOsOE7R8la5RnVY6yAScWU9qg==" + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -16913,7 +17155,6 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -16965,7 +17206,6 @@ "version": "5.74.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", - "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", @@ -17274,7 +17514,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -17304,7 +17543,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -20087,10 +20325,9 @@ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" }, "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "requires": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -20100,7 +20337,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, "requires": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -20340,6 +20576,15 @@ "which": "^2.0.2" } }, + "@playwright/test": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.39.0.tgz", + "integrity": "sha512-3u1iFqgzl7zr004bGPYiN/5EZpRUSFddQBra8Rqll5N0/vfpqlP9I9EXqAoGacuAbX6c9Ulg/Cjqglp5VkK6UQ==", + "dev": true, + "requires": { + "playwright": "1.39.0" + } + }, "@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -20675,7 +20920,6 @@ "version": "8.4.10", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", - "dev": true, "requires": { "@types/estree": "*", "@types/json-schema": "*" @@ -20685,7 +20929,6 @@ "version": "3.7.4", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, "requires": { "@types/eslint": "*", "@types/estree": "*" @@ -20694,8 +20937,7 @@ "@types/estree": { "version": "0.0.51", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" }, "@types/express": { "version": "4.17.14", @@ -20753,8 +20995,7 @@ "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" }, "@types/lodash": { "version": "4.14.188", @@ -20780,8 +21021,7 @@ "@types/node": { "version": "17.0.45", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", - "dev": true + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" }, "@types/parse-json": { "version": "4.0.0", @@ -21023,7 +21263,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, "requires": { "@webassemblyjs/helper-numbers": "1.11.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.1" @@ -21032,26 +21271,22 @@ "@webassemblyjs/floating-point-hex-parser": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" }, "@webassemblyjs/helper-api-error": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" }, "@webassemblyjs/helper-buffer": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" }, "@webassemblyjs/helper-numbers": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, "requires": { "@webassemblyjs/floating-point-hex-parser": "1.11.1", "@webassemblyjs/helper-api-error": "1.11.1", @@ -21061,14 +21296,12 @@ "@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" }, "@webassemblyjs/helper-wasm-section": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, "requires": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-buffer": "1.11.1", @@ -21080,7 +21313,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } @@ -21089,7 +21321,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, "requires": { "@xtuc/long": "4.2.2" } @@ -21097,14 +21328,12 @@ "@webassemblyjs/utf8": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" }, "@webassemblyjs/wasm-edit": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, "requires": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-buffer": "1.11.1", @@ -21120,7 +21349,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, "requires": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.1", @@ -21133,7 +21361,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, "requires": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-buffer": "1.11.1", @@ -21145,7 +21372,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, "requires": { "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/helper-api-error": "1.11.1", @@ -21159,7 +21385,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, "requires": { "@webassemblyjs/ast": "1.11.1", "@xtuc/long": "4.2.2" @@ -21191,14 +21416,12 @@ "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "@yarnpkg/lockfile": { "version": "1.1.0", @@ -21227,9 +21450,9 @@ } }, "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==" + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==" }, "acorn-globals": { "version": "6.0.0", @@ -21248,10 +21471,9 @@ } }, "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "requires": {} }, "acorn-jsx": { @@ -21335,7 +21557,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -21376,7 +21597,6 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, "requires": {} }, "angular-auth-oidc-client": { @@ -21961,8 +22181,7 @@ "chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" }, "clean-stack": { "version": "2.2.0", @@ -22059,8 +22278,7 @@ "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "commondir": { "version": "1.0.1", @@ -23390,10 +23608,9 @@ "dev": true }, "enhanced-resolve": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", - "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", - "dev": true, + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "requires": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -23483,8 +23700,7 @@ "es-module-lexer": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" }, "es6-promise": { "version": "4.2.8", @@ -23935,7 +24151,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "requires": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -23944,8 +24159,7 @@ "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" } } }, @@ -24001,7 +24215,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "requires": { "estraverse": "^5.2.0" } @@ -24036,8 +24249,7 @@ "events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" }, "execa": { "version": "5.1.1", @@ -24168,8 +24380,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { "version": "3.2.12", @@ -24198,8 +24409,7 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-levenshtein": { "version": "2.0.6", @@ -24565,8 +24775,7 @@ "glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "globals": { "version": "11.12.0", @@ -24598,8 +24807,7 @@ "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "grapheme-splitter": { "version": "1.0.4", @@ -25573,7 +25781,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "requires": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -25583,14 +25790,12 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -25686,8 +25891,7 @@ "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "json-schema": { "version": "0.4.0", @@ -25698,8 +25902,7 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -26082,8 +26285,7 @@ "loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==" }, "loader-utils": { "version": "3.2.1", @@ -26418,8 +26620,7 @@ "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "merge2": { "version": "1.4.1", @@ -26663,9 +26864,9 @@ "dev": true }, "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" }, "natural-compare": { "version": "1.4.0", @@ -26721,8 +26922,7 @@ "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "ngx-bootstrap": { "version": "9.0.0", @@ -26741,6 +26941,200 @@ "tslib": "^2.0.0" } }, + "ngx-pipes": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/ngx-pipes/-/ngx-pipes-3.2.2.tgz", + "integrity": "sha512-nhNIUJe/bud5ir4RD2YDA6MdrJUh3YASIcNrMFX9WljTxuvAb99SZ88PaKSFGy9SXjHg8MxjxHfCoOLlTkxxlQ==", + "requires": { + "postcss": "^8.4.19", + "tslib": "^2.3.0", + "webpack": "^5.75.0" + }, + "dependencies": { + "@types/estree": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", + "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==" + }, + "@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "requires": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "es-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", + "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==" + }, + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "webpack": { + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + } + } + } + }, "nice-napi": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", @@ -27657,17 +28051,33 @@ "find-up": "^4.0.0" } }, + "playwright": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.39.0.tgz", + "integrity": "sha512-naE5QT11uC/Oiq0BwZ50gDmy8c8WLPRTEWuSSFVG2egBka/1qMoSqYQcROMT9zLwJ86oPofcTH2jBY/5wWOgIw==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.39.0" + } + }, + "playwright-core": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.39.0.tgz", + "integrity": "sha512-+k4pdZgs1qiM+OUkSjx96YiKsXsmb59evFoqv8SKO067qBA+Z2s/dCzJij/ZhdQcs2zlTAgRKfeiiLm8PQ2qvw==", + "dev": true + }, "popper.js": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" }, "postcss": { - "version": "8.4.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz", - "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "requires": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } @@ -28498,7 +28908,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "requires": { "safe-buffer": "^5.1.0" } @@ -29155,10 +29564,9 @@ } }, "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "requires": { "randombytes": "^2.1.0" } @@ -29376,8 +29784,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "devOptional": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-js": { "version": "1.0.2", @@ -29410,7 +29817,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -29660,8 +30066,7 @@ "tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" }, "tar": { "version": "6.1.12", @@ -29689,28 +30094,37 @@ } }, "terser-webpack-plugin": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", - "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", - "dev": true, + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "requires": { - "@jridgewell/trace-mapping": "^0.3.14", + "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" }, "dependencies": { "schema-utils": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, "requires": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } + }, + "terser": { + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.22.0.tgz", + "integrity": "sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw==", + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } } } }, @@ -30041,7 +30455,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "requires": { "punycode": "^2.1.0" } @@ -30071,6 +30484,11 @@ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true }, + "valibot": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-0.17.0.tgz", + "integrity": "sha512-ykoYfBc4HOH+osdWaFBmeL7yX35bFfKg1WdwHYZhNVuvGIRH5f2gtYT6cnU85XOsOE7R8la5RnVY6yAScWU9qg==" + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -30140,7 +30558,6 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, "requires": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -30183,7 +30600,6 @@ "version": "5.74.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", - "dev": true, "requires": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", @@ -30215,7 +30631,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, "requires": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -30403,8 +30818,7 @@ "webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" }, "webpack-subresource-integrity": { "version": "5.1.0", diff --git a/package.json b/package.json index a4c982900..7f44a6962 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "mississippi": "^4.0.0", "ngx-bootstrap": "^9.0.0", "ngx-countup": "^13.0.0", + "ngx-pipes": "^3.2.2", "nodemailer": "^6.7.8", "popper.js": "^1.16.0", "referrer-policy": "^1.2.0", @@ -81,6 +82,7 @@ "through2": "^4.0.2", "timers": "^0.1.1", "tslib": "^2.1.0", + "valibot": "^0.17.0", "zone.js": "~0.11.8" }, "devDependencies": { @@ -98,6 +100,7 @@ "@babel/preset-env": "^7.16.11", "@fortawesome/fontawesome-free": "^6.0.0", "@ngx-i18nsupport/ngx-i18nsupport": "^1.1.6", + "@playwright/test": "^1.39.0", "@types/d3": "^7.1.0", "@types/express": "^4.17.11", "@types/jasmine": "~3.6.6", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 000000000..301801ee1 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,77 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/src/app/portal/components/collapsible/collapsible.component.html b/src/app/portal/components/collapsible/collapsible.component.html new file mode 100644 index 000000000..449cf2a1a --- /dev/null +++ b/src/app/portal/components/collapsible/collapsible.component.html @@ -0,0 +1,37 @@ + +
+ +
+
+ +
+
+
+ +
-
+
+ + +
+
+
+ +
+ {{label}} + + +
+ +
+
+
+
+ + + + +
+ +
+ +
+
diff --git a/src/app/portal/components/collapsible/collapsible.component.scss b/src/app/portal/components/collapsible/collapsible.component.scss new file mode 100644 index 000000000..372b2fdd0 --- /dev/null +++ b/src/app/portal/components/collapsible/collapsible.component.scss @@ -0,0 +1,39 @@ +.collapsible-container { + background-color: rgb(247, 247, 251); +} + +.collapsible-label { + font-size: 1.1rem; + font-weight: bolder; + + padding: 11px 16px; + border-radius: 4px; + + user-select: none; + cursor: pointer; + + display: flex; + justify-content: space-between; +} + +.icon-collapsed { + transition: transform 0.25s linear; + transform: rotate(0deg); +} + +.icon-expanded { + transition: transform 0.25s ease-out; + transform: rotate(180deg); +} + +.collapsible-content { + transition: max-height 0.4s ease-out; + overflow: hidden; + + max-height: 1000px; +} + +.collapsed { + // transition: 0.2s linear; + max-height: 0; +} diff --git a/src/app/portal/components/collapsible/collapsible.component.ts b/src/app/portal/components/collapsible/collapsible.component.ts new file mode 100644 index 000000000..be78034f8 --- /dev/null +++ b/src/app/portal/components/collapsible/collapsible.component.ts @@ -0,0 +1,39 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { NgClass, NgIf } from '@angular/common'; +import { MatIconModule } from '@angular/material/icon'; +import { animate, state, style, transition, trigger } from '@angular/animations'; +import { TooltipModule } from 'ngx-bootstrap/tooltip'; + +@Component({ + selector: 'app-collapsible', + templateUrl: './collapsible.component.html', + styleUrls: ['./collapsible.component.scss'], + imports: [ + NgIf, + MatIconModule, + NgClass, + TooltipModule + ], + standalone: true, + animations: [ + trigger('expandCollapse', [ + state('collapsed', style({ height: '0px', overflow: 'hidden' })), + state('expanded', style({ height: '*', overflow: 'hidden' })), + transition('expanded <=> collapsed', animate('0.1s ease-out')) + ]) + ] +}) +export class CollapsibleComponent { + @Input() label = ''; + @Input() decoration = "none"; + + @Input() isOpen = false; + @Output() isOpenChange = new EventEmitter(); + + @Input() hasTooltip = false; + + toggle() { + this.isOpen = !this.isOpen; + this.isOpenChange.emit(this.isOpen); + } +} diff --git a/src/app/portal/components/filter-limit-button/filter-limit-button.component.html b/src/app/portal/components/filter-limit-button/filter-limit-button.component.html new file mode 100644 index 000000000..33c7cbcf2 --- /dev/null +++ b/src/app/portal/components/filter-limit-button/filter-limit-button.component.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/src/app/portal/components/filter-limit-button/filter-limit-button.component.scss b/src/app/portal/components/filter-limit-button/filter-limit-button.component.scss new file mode 100644 index 000000000..b13f833f6 --- /dev/null +++ b/src/app/portal/components/filter-limit-button/filter-limit-button.component.scss @@ -0,0 +1,7 @@ +.limit-button { + height: 3rem; +} + +.limit-button:enabled { + color: #4546b9; +} diff --git a/src/app/portal/components/filter-limit-button/filter-limit-button.component.spec.ts b/src/app/portal/components/filter-limit-button/filter-limit-button.component.spec.ts new file mode 100644 index 000000000..be14282fd --- /dev/null +++ b/src/app/portal/components/filter-limit-button/filter-limit-button.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FilterLimitButtonComponent } from './filter-limit-button.component'; + +describe('FilterLimitButtonComponent', () => { + let component: FilterLimitButtonComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ FilterLimitButtonComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(FilterLimitButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/portal/components/filter-limit-button/filter-limit-button.component.ts b/src/app/portal/components/filter-limit-button/filter-limit-button.component.ts new file mode 100644 index 000000000..3d0e481ee --- /dev/null +++ b/src/app/portal/components/filter-limit-button/filter-limit-button.component.ts @@ -0,0 +1,23 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { MatButtonModule } from '@angular/material/button'; + +@Component({ + selector: 'app-filter-limit-button', + standalone: true, + imports: [CommonModule, MatButtonModule], + templateUrl: './filter-limit-button.component.html', + styleUrls: ['./filter-limit-button.component.scss'] +}) +export class FilterLimitButtonComponent { + @Input() value = 0; + @Output() valueChange = new EventEmitter(); + + @Input() step = 0; + @Input() min = 0; + @Input() max = 0; + + clamp(value: number) { + return Math.min(Math.max(value, this.min), this.max); + } +} diff --git a/src/app/portal/components/filter-option/filter-option.component.html b/src/app/portal/components/filter-option/filter-option.component.html new file mode 100644 index 000000000..5ba7644a1 --- /dev/null +++ b/src/app/portal/components/filter-option/filter-option.component.html @@ -0,0 +1,20 @@ +
+
+ + +
+ +
+ +
+ +
+
+ {{label}} +
+ +
+ {{count}} +
+
+
diff --git a/src/app/portal/components/filter-option/filter-option.component.scss b/src/app/portal/components/filter-option/filter-option.component.scss new file mode 100644 index 000000000..0fcbfe167 --- /dev/null +++ b/src/app/portal/components/filter-option/filter-option.component.scss @@ -0,0 +1,20 @@ +.label-text { + text-overflow: ellipsis; + flex-shrink: 1; +} + +.filter-option-layout { + display: flex; + justify-content: center; + align-items: center; + + // padding: 16px 12px; + padding: 8px; + + cursor: pointer; + user-select: none; + + &:hover { + background-color: rgba(0, 0, 0, 0.04); + } +} diff --git a/src/app/portal/components/filter-option/filter-option.component.ts b/src/app/portal/components/filter-option/filter-option.component.ts new file mode 100644 index 000000000..b9d37ef15 --- /dev/null +++ b/src/app/portal/components/filter-option/filter-option.component.ts @@ -0,0 +1,28 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { MatRippleModule } from '@angular/material/core'; +import { MatCheckboxModule } from '@angular/material/checkbox'; + +@Component({ + selector: 'app-filter-option', + templateUrl: './filter-option.component.html', + styleUrls: ['./filter-option.component.scss'], + imports: [ + FormsModule, + MatRippleModule, + MatCheckboxModule + ], + standalone: true +}) +export class FilterOptionComponent { + @Input() label = ""; + @Input() count = 0; + + @Input() value: boolean = false; + @Output() valueChange = new EventEmitter(); + + toggleValue() { + this.value = !this.value; + this.valueChange.emit(this.value); + } +} diff --git a/src/app/portal/components/organization-filter/organization-filter.component.html b/src/app/portal/components/organization-filter/organization-filter.component.html new file mode 100644 index 000000000..58bb1c93e --- /dev/null +++ b/src/app/portal/components/organization-filter/organization-filter.component.html @@ -0,0 +1,35 @@ +
+ + + Julkaisun tekijän suomalainen organisaatio. Palvelu ei toistaiseksi sisällä tietoja julkaisujen ulkomaisista organisaatioista. + + + + +
Valitse kaikki
+ + + + + + + + +
+ + + +
+ +
+
+ + + diff --git a/src/app/portal/components/organization-filter/organization-filter.component.scss b/src/app/portal/components/organization-filter/organization-filter.component.scss new file mode 100644 index 000000000..dd50f90b7 --- /dev/null +++ b/src/app/portal/components/organization-filter/organization-filter.component.scss @@ -0,0 +1,53 @@ +.example-accordion { + display: block; + max-width: 500px; +} + +.example-accordion-item { + display: block; + border: solid 1px #ccc; +} + +.example-accordion-item + .example-accordion-item { + border-top: none; +} + +.example-accordion-item-header { + display: flex; + align-content: center; + justify-content: space-between; +} + +.example-accordion-item-description { + font-size: 0.85em; + color: #999; +} + +/*.example-accordion-item-header, +.example-accordion-item-body { + padding: 16px; +}*/ + +.example-accordion-item-header:hover { + cursor: pointer; + background-color: #eee; +} + +.example-accordion-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +.example-accordion-item:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +/**/ + +.filter-heading { + font-size: 17.6px; + font-weight: 700; + + padding: 11px 16px; +} diff --git a/src/app/portal/components/organization-filter/organization-filter.component.ts b/src/app/portal/components/organization-filter/organization-filter.component.ts new file mode 100644 index 000000000..fa735d5d8 --- /dev/null +++ b/src/app/portal/components/organization-filter/organization-filter.component.ts @@ -0,0 +1,56 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { AsyncPipe, NgForOf, NgIf } from '@angular/common'; +import { FilterOptionComponent } from '@portal/components/filter-option/filter-option.component'; +import { NgArrayPipesModule } from 'ngx-pipes'; +import { FormsModule } from '@angular/forms'; +import { LimitPipe } from '@portal/pipes/limit.pipe'; +import { CdkAccordionModule } from '@angular/cdk/accordion'; +import { CollapsibleComponent } from '@portal/components/collapsible/collapsible.component'; + +@Component({ + selector: 'app-organization-filter', + templateUrl: './organization-filter.component.html', + styleUrls: ['./organization-filter.component.scss'], + imports: [ + NgIf, + AsyncPipe, + FilterOptionComponent, + LimitPipe, + NgArrayPipesModule, + NgForOf, + FormsModule, + CdkAccordionModule, + CollapsibleComponent + ], + standalone: true +}) +export class OrganizationFilterComponent { + @Input() filterData: unknown; + @Output() selected = new EventEmitter(); + + selectedSector = -1; + + expanded = false; + sectorFilter: Record = {}; + + sectorLimits: Record = { + 1: 10, + 2: 10, + 3: 10, + 4: 10, + 6: 10, + }; + + /* TODO localization solution */ // TODO ? + public sectorNames = { + 1: $localize`:@@organizationSector1:Yliopisto`, + 2: $localize`:@@organizationSector2:Ammattikorkeakoulu`, + 3: $localize`:@@organizationSector3:Tutkimuslaitos`, + 4: $localize`:@@organizationSector4:Yliopistollisen sairaalan erityisvastuualue`, + 6: $localize`:@@organizationSector5:Muu` + } + + toggleExpanded() { + this.expanded = !this.expanded; + } +} diff --git a/src/app/portal/components/results/publications2/publications2.component.html b/src/app/portal/components/results/publications2/publications2.component.html new file mode 100644 index 000000000..4eeab11ed --- /dev/null +++ b/src/app/portal/components/results/publications2/publications2.component.html @@ -0,0 +1,951 @@ + +
+ + +
+ +

Rajaa hakua

+
+ + +
+
+ + + +
+ + + + + + + +
+ + Näytä enemmän + + + + Näytä vähemmän + +
+
+ +
+
+ + +
+ + + + +
+ +
+ + + Tilastokeskuksen tieteenalaluokitus. Taiteenalat OKM:n luokituksen mukaisesti. Julkaisulla voi olla 1-6 tieteen- tai taiteenalaa. + + + + + + + + + + + + + + + + + +
+ + +
+ +
+ + + OKM:n julkaisutiedonkeruun mukainen julkaisutyyppi A–G. + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ + +

+ Artikkeli: + Sisältää alkuperäis- ja katsausartikkelit, kirjan tai lehden johdannot ja esipuheet, lyhyet tutkimusselostukset, pääkirjoitukset, keskustelupuheenvuorot ja kommentit. +

+ +

+ Erillisteos: + Sisältää monografiat/kirjat, tutkimus- ja kehitystyöhön perustuva kehittämis- tai tutkimusraportti, selvitykset, ns. white paperit sekä working papers ja discussion papers -tyyppiset julkaisut. +

+ + +

+ Toimitustyö: + Sisältää useista eri kirjoittajien artikkeleista koostuvan tieteellisen kirjan tai lehden erikoisnumeron toimitustyöt. +

+ +

+ Abstrakti: + Sisältää konferenssiesitelmien abstraktit sekä laajennetut abstraktit. +

+ +

+ Posteri: + Sisältää konferenssiesitelmien posterit. +

+ +

+ Blogikirjoitus: + Sisältää blogimuotoiset julkaisut, joiden julkaisemisesta on päättänyt riippumaton toimituskunta tai joiden julkaisualustalla on ISSN-tunnus. +

+
+ + + + + +
+
+
+ + +
+ +
+ + +

+ Julkaisukanavan kohdeyleisö +

+ +

+ Tieteellinen julkaisu: + Julkaisut, jotka on tarkoitettu edistämään tiedettä sekä tuottamaan uutta tietoa. +

+ +

+ Ammatillinen julkaisu: + Julkaisut, jotka levittävät tutkimukseen ja kehitystyöhön perustuvaa tietoa ammattiyhteisön käyttöön. +

+ +

+ Yleistajuinen julkaisu: + Julkaisut, jotka levittävät tutkimus- ja kehitystyöhön perustuvaa tietoa suurelle yleisölle ja joiden sisällön ymmärtäminen ei edellytä erityistä perehtyneisyyttä alaan. +

+
+ + + + + +
+
+ + + +
+ +
+ + +

+ Lehti: + sisältää tieteelliset aikakauslehdet ja ammattilehdet. +

+ +

+ Kokoomateos: + Sisältää tieteelliset kokoomateokset, tieteelliset vuosikirjat ja vastaavat, ammatilliset käsi- tai opaskirjat, ammatilliset tietojärjestelmät tai kokoomateokset, oppikirja-aineistot sekä lyhyet ensyklopediatekstit. +

+ +

+ Konferenssi: + Sisältää konferenssin painetut tai julkisesti saatavilla olevat julkaisut, ns. proceedings-julkaisut. +

+ +

+ Verkkoalusta: + Sisältää muilla sähköisillä alustoilla julkaistut julkaisut. +

+
+ + + + + +
+
+ + +
+ +
+ + +

+ Alkuperäisartikkeli: + + on pääosin aiemmin julkaisemattomasta materiaalista koostuva tieteellinen artikkeli. +

+ +

+ Katsausartikkeli: + + perustuu aikaisempiin samasta aihepiiristä tehtyihin julkaisuihin. +

+ +

+ Data-artikkeli: + + sisältää ns. data journals -julkaisuissa ilmestyneet, tutkimusaineistoja kuvailevat artikkelit. +

+ +

+ Muu artikkeli: + + sisältää muihin luokkiin kuulumattomat artikkelit. +

+
+ + + + + + +
+
+ + +
+ +
+ + Tieteellisten julkaisujen vertaisarvioinnilla tarkoitetaan menettelyä, jossa tutkimustuloksia julkaiseva lehti, konferenssi tai kirjakustantaja pyytää tieteenalan asiantuntijoita suorittamaan ennakkoarvion julkaistavaksi tarjottujen käsikirjoitusten tieteellisestä julkaisukelpoisuudesta. + + + + + + +
+ + +
+ +
+ + + Kotimaisen julkaisun kustantaja on suomalainen tai se on ensisijaisesti julkaistu Suomessa. Kansainvälisen julkaisun kustantaja ei ole suomalainen tai se on ensisijaisesti julkaistu muualla kuin Suomessa. + + + + + + + +
+ + +
+ +
+ + + Kieli, jolla julkaisu on kirjoitettu. + + + + + + + + +
+ + Näytä enemmän + + + + Näytä vähemmän + +
+
+ + +
+
+ + +
+ +
+ + + Julkaisufoorumin (www.julkaisufoorumi.fi) mukainen julkaisukanavan (kirjakustantaja, konferenssi tai julkaisusarja) tasoluokitus: 1 = perustaso, 2 = johtava taso, 3 = korkein taso. Tasolla 0 ovat kanavat, jotka eivät joltain osin täytä tason 1 vaatimuksia tai ovat uusia. Julkaisufoorumitaso määräytyy julkaisun julkaisuvuoden mukaan. + + + + + + + +
+ + +
+ +
+ + + +

+ Avoimesti saatavilla: + Julkaisu on avoimesti saatavilla kustantajan palvelussa. +

+ +

+ Ei avoin: + Julkaisu ei ole avoimesti saatavilla kustantajan palvelussa. +

+ +

+ Ei tietoa: + Tietoa ei ole raportoitu. +

+ +
+ + + + + +
+
+ + +
+ +
+ + +

+ Kokonaan avoin julkaisukanava: + Julkaisukanavan kaikki julkaisut ovat pysyvästi avoimesti saatavilla. +

+ +

+ Osittain avoin julkaisukanava: + Julkaisukanavassa vain osa julkaisuista on pysyvästi avoimesti saatavilla. +

+ +

+ Viivästetysti avoin julkaisukanava: + Julkaisukanavan tieteelliset artikkelit avataan kustantajan määrittelemän viiveajan jälkeen. +

+ +

+ Ei vastausta: + Julkaisukanava ei ole kokonaan, osittain tai viivästetysti avoin. +

+ +

+ Ei tietoa: + Tietoa ei ole raportoitu. +

+ +
+ + + + + +
+
+ + +
+ + +
+ + +

+ Rinnakkaistallennettu: + Julkaisu on tallennettu organisaatio- tai tieteenalakohtaiseen julkaisuarkistoon joko välittömästi tai kustantajan määrittämän kohtuullisen embargoajan jälkeen. +

+
+ + + + + +
+
+ +
+
+ + +
+
+ +

Rajaa hakua

+
+ + +
+ +
+
+ +
+
+
+ + +
+
+ +

Hakuohje

+
+ + +
+ +
+

+ Testaa uudistetun haun betaversiota. Uudistettua hakua on toistaiseksi mahdollista testata ainoastaan julkaisutietojen hakemisessa. +

+ +

+ Kirjoita hakukenttään esimerkiksi julkaisun tai tekijän nimi, tai julkaisuun liittyvä asiasana. +

+ +

+ Haku käyttää sanojen välissä oletuksena OR-hakuoperaattioria. Halutessasi voit käyttää myös AND- ja NOT- hakuoperaattoireita. Esimerkiksi haku Innovation AND gamification NOT games etsii julkaisuja, joissa esiintyvät yhtä aikaa sanat "innovation" ja "gamification", mutta joissa ei ole mukana sanaa "games". Huomioithan, että AND, NOT ja OR -hakuoperaattorit tulee kirjoittaa hakukenttään isoilla kirjaimilla. +

+ +

+ Sulkemalla haussa esiintyvät sanat lainausmerkeillä fraasiksi voit etsiä osumia jotka ovat täsmälleen samassa muodossa. Esimerkiksi fraasihaku "Innovations in gamifications" etsii julkaisuja, joissa esiintyy juuri tämä lause. Voit myös yhdistää useampia fraasihakuja AND-, OR- tai NOT-hakuoperaattoreilla. +

+ +

+ Voit hakea kohdistetusti joitakin metatietoja suoraan hakukentässä käyttämällä niille erikseen määriteltyjä komentoja. Haussa on käytettävä fraasihakua. Toistaiseksi haku on mahdollista kohdistaa seuraaviin metatietoihin: +

+ +
    +
  • + DOI, kirjoita hakukenttään doi:"haettava tunnus", esimerkiksi doi:"100100100" +
  • + +
  • + ISSN, kirjoita hakukenttään issn:"haettava tunnnus", esimerkiksi issn:"1234-1234" +
  • + +
  • + ISBN, kirjoita hakukenttään isbn:"haettava tunnus", esimerkiksi isbn:"123-0-456-12345-1" +
  • + +
  • + JUFO-tunnus, kirjoita hakukenttään jufoCode:"haettava tunnus", esimerkiksi jufoCode:"12345" +
  • +
+ +

+ Huomioithan, että kohdistetussa haussa metatietokentät tulee kirjoittaa pienillä kirjaimilla. +

+
+
+ +
+ + + + + + + + +
+ + + + +
+ +
+

Julkaisut - {{total$ | async}}

+
+ +
+ Näytetään tulokset + + {{(page - 1) * size + 1}} - {{page * size}} / {{total$ | async}} + + + + + tulosta / sivu + + + + + Mitä julkaisutietoja palvelu sisältää? + + + +
+
+
+ + +
+ + +
+
+ +
+ + + +
+ +
+
+ + +
+ + + +
+
+ +
+
+ +
+ +
+
+
+ +
+
+ +
+
Rajaukset ({{searchTermsCount$ | async}})
+ + + +
+
{{yearfilter}}
+ +
+
+ + + +
+
{{organizationFilter.name}}
+ +
+
+ + + +
+
{{fieldsOfScienceFilter.name}}
+ +
+
+ + + +
+
{{publicationTypeCodeFilter.name}}
+ +
+
+ + + +
+
{{languageCodeFilter.name}}
+ +
+
+ + + +
+
{{publicationFormatFilter.name}}
+ +
+
+ + + +
+
{{publicationAudienceFilter.name}}
+ +
+
+ + + +
+
{{peerReviewedFilter.name}}
+ +
+
+ + + +
+
{{parentPublicationTypeFilter.name}}
+ +
+
+ + + +
+
{{internationalPublicationFilter.name}}
+ +
+
+ + + +
+
{{articleTypeCodeFilter.name}}
+ +
+
+ + + +
+
{{jufoClassCodeFilter}}
+ +
+
+ + + + + +
+
{{openAccessFilter.name}}
+ +
+
+ + + +
+
{{publisherOpenAccessFilter.name}}
+ +
+
+ + + +
+
{{selfArchivedCodeFilter.name}}
+ +
+
+ + +
+
Tyhjennä rajaukset
+ +
+ +
+
+
+ +
+ + + + + + + + + + + + + + + +
+
+ Julkaisun nimi +
+ + +
+
+ + + + + +
+
+ +
+ +
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+
+ +
+
+ + + + +
+
Tekijät
+ + +
+ +
+ + +
+
+
+ + + + +
+
+ Julkaisukanava +
+ + +
+ +
+ + +
+
+
+ + + + +
+
+ Julkaisuvuosi +
+ + +
+ +
+ + +
+
+
+ + + +
+
+ +
+
+ +
+
+
+ +
+ + diff --git a/src/app/portal/components/results/publications2/publications2.component.scss b/src/app/portal/components/results/publications2/publications2.component.scss new file mode 100644 index 000000000..c83dc3cbb --- /dev/null +++ b/src/app/portal/components/results/publications2/publications2.component.scss @@ -0,0 +1,131 @@ +.search-container { + display: grid; + + grid-template-rows: + auto + minmax(0, auto) + minmax(0, auto) + minmax(0, auto) + minmax(0, auto); + + grid-template-columns: 1fr minmax(0, 350px) minmax(0, 1100px) 1fr; + + grid-template-areas: + "search search search search" + ". info info ." + ". filters results ."; +} + +@media (max-width: 1200px) { + .search-container { + grid-template-columns: 350px minmax(0, 1fr); + + grid-template-areas: + "search search" + "info info" + "filters results" + } +} + +@media (max-width: 990px) { + .search-container { + grid-template-columns: minmax(0, 1fr); + + grid-template-areas: + "search" + "info" + "filters-toggle" + "results" + } +} + +.search-bar { + grid-area: search; +} + +.search-tabs { + grid-area: tabs; +} + +.search-info { + grid-area: info; +} + +.search-filters { + grid-area: filters; +} + +.search-filters-toggle { + grid-area: filters-toggle; +} + +.search-pagination { + display: flex; + justify-content: center; +} + +.search-combination { + grid-area: results; +} + +/* Ensure the table takes the full width */ +cdk-table { + // width: 100%; +} + +/* Add some spacing and border to the cells */ +cdk-cell { + padding: 1rem 0.5rem; + display: table-cell; + text-align: start; +} + +cdk-header-cell { + padding: 0.25rem 0.5rem 1rem 0.5rem; + display: table-cell; + text-align: start; + + position: sticky; + top: 0; + background: white; + z-index: 1; +} + +/* Define the header row and data row to behave like traditional table rows */ +cdk-header-row, cdk-row { + display: table-row; +} + + + +/* Define columns to ensure they take equal widths - adjust as required */ +/*[cdkColumnDef="publicationName"] { + width: 35%; + background-color: red; +} + +[cdkColumnDef="authorsText"] { + width: 25%; +} + +[cdkColumnDef="publisherName"] { + width: 20%; +} + +[cdkColumnDef="publicationYear"] { + width: 20%; +}*/ + +/*em { + background-color: #FFFF00; + font-style: normal; + padding: 0.1em 0; +}*/ + +.filters-summary { + background-color: #e8e8f5; + padding: 16px; + border: 1px solid #4546b9; + border-radius: 4px; + margin: 0 0 1.5rem 1.5rem; +} diff --git a/src/app/portal/components/results/publications2/publications2.component.ts b/src/app/portal/components/results/publications2/publications2.component.ts new file mode 100644 index 000000000..69d842b9a --- /dev/null +++ b/src/app/portal/components/results/publications2/publications2.component.ts @@ -0,0 +1,714 @@ +import { Component, inject, OnDestroy, TemplateRef, ViewChild } from '@angular/core'; +import { CdkTableModule, DataSource } from '@angular/cdk/table'; +import { BehaviorSubject, combineLatest, interval, Observable } from 'rxjs'; +import { ActivatedRoute, Router, RouterLink, RouterModule } from '@angular/router'; +import { FormsModule } from '@angular/forms'; +import { AsyncPipe, JsonPipe, NgForOf, NgIf, NgStyle, NgTemplateOutlet } from '@angular/common'; +import { + getArticleTypeCodeAdditions, + getFieldsOfScienceAdditions, + getJufoClassCodeAdditions, + getLanguageCodeAdditions, + getOpenAccessAdditions, + getOrganizationAdditions, + getParentPublicationTypeAdditions, + getPeerReviewedAdditions, + getPublicationAudienceAdditions, + getPublicationFormatAdditions, + getPublicationTypeCodeAdditions, + getPublisherInternationalityAdditions, + getPublisherOpenAccessCodeAdditions, + getSelfArchivedCodeAdditions, + getYearAdditions, + HighlightedPublication, + Publication2Service, SearchParams +} from '@portal/services/publication2.service'; +import { filter, map, take, tap } from 'rxjs/operators'; +import { SharedModule } from '@shared/shared.module'; +import { SearchBar2Component } from '@portal/search-bar2/search-bar2.component'; +import { NgArrayPipesModule, NgMathPipesModule } from 'ngx-pipes'; +import { OrganizationFilterComponent } from '@portal/components/organization-filter/organization-filter.component'; +import { FilterOptionComponent } from '@portal/components/filter-option/filter-option.component'; +import { LimitPipe } from '@portal/pipes/limit.pipe'; +import { CollapsibleComponent } from '@portal/components/collapsible/collapsible.component'; +import { MatButtonModule } from '@angular/material/button'; +import { FilterLimitButtonComponent } from '@portal/components/filter-limit-button/filter-limit-button.component'; +import { FirstDigitPipe } from '@shared/pipes/first-digit.pipe'; +import { FirstLetterPipe } from '@shared/pipes/first-letter.pipe'; +import { BreakpointObserver, LayoutModule } from '@angular/cdk/layout'; +import { ColumnSorterComponent } from '@shared/components/column-sorter/column-sorter.component'; +import { faChartBar, faSlidersH } from '@fortawesome/free-solid-svg-icons'; +import { Dialog, DialogRef } from '@angular/cdk/dialog'; +import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; + +@Component({ + selector: 'app-publications2', + templateUrl: './publications2.component.html', + styleUrls: ['./publications2.component.scss'], + imports: [CdkTableModule, FormsModule, AsyncPipe, JsonPipe, NgForOf, NgIf, LimitPipe, NgArrayPipesModule, + SharedModule, //TODO do not depend on shared module + FormsModule, + RouterModule, + SearchBar2Component, OrganizationFilterComponent, FilterOptionComponent, CollapsibleComponent, MatButtonModule, NgStyle, FilterLimitButtonComponent, FirstDigitPipe, FirstLetterPipe, RouterLink, + LayoutModule, ColumnSorterComponent, NgTemplateOutlet, FontAwesomeModule, NgMathPipesModule + ], + standalone: true +}) +export class Publications2Component implements OnDestroy { + route = inject(ActivatedRoute); + router = inject(Router); + publications2Service = inject(Publication2Service); + breakpointObserver = inject(BreakpointObserver); + dialog = inject(Dialog); + + keywords = ""; + page = 1; + size = 10; + + sort = ""; + + dialogRef?: DialogRef; + @ViewChild('searchDialog') dialogTemplate: TemplateRef; + + // Dialog for insturctions / tutorial + tutorialDialogRef?: DialogRef; + @ViewChild('tutorialDialog') tutorialDialogTemplate: TemplateRef; + + openTutorialDialog() { + this.tutorialDialogRef = this.dialog.open(this.tutorialDialogTemplate, { + panelClass: 'large-responsive-panel', + }); + + this.tutorialDialogRef.closed.subscribe(() => { + console.log('The tutorial dialog was closed'); + }); + } + + closeTutorialDialog() { + this.tutorialDialogRef?.close(); + } + + labelText = { + yearOfPublication: $localize`:@@yearOfPublication:Julkaisuvuosi`, + organization: $localize`:@@organization:Organisaatio`, + fieldOfScience: $localize`:@@fieldOfScience:Tieteenala`, + publicationType: $localize`:@@publicationType:Julkaisutyyppi`, + publicationFormat: $localize`:@@publicationFormat:Julkaisumuoto`, + publicationAudience: $localize`:@@publicationAudience:Julkaisun yleisö`, + parentPublicationType: $localize`:@@parentPublicationType:Emojulkaisun tyyppi`, + articleType: $localize`:@@articleType:Artikkelin tyyppi`, + peerReviewed: $localize`:@@peerReviewed:Vertaisarvioitu`, + publisherInternationality: $localize`:@@publisherInternationality:Kustantajan kansainvälisyys`, + language: $localize`:@@language:Kieli`, + jufoLevel: $localize`:@@jufoLevel:Julkaisufoorumitaso`, + openAccess: $localize`:@@openAccess:Avoin saatavuus`, + publisherOpenAccess: $localize`:@@publisherOpenAccess:Julkaisukanavan avoin saatavuus`, + selfArchivedCode: $localize`:@@selfArchivedCode:Rinnakkaistallenne`, + } + + publicationTypeLabels = [ + {id: "A", text: $localize`:@@publicationClassA:Vertaisarvioidut tieteelliset artikkelit`}, + {id: "B", text: $localize`:@@publicationClassB:Vertaisarvioimattomat tieteelliset kirjoitukset`}, + {id: "C", text: $localize`:@@publicationClassC:Tieteelliset kirjat`}, + {id: "D", text: $localize`:@@publicationClassD:Ammattiyhteisölle suunnatut julkaisut`}, + {id: "E", text: $localize`:@@publicationClassE:Suurelle yleisölle suunnatut julkaisut`}, + {id: "F", text: $localize`:@@publicationClassF:Julkinen taiteellinen ja taideteollinen toiminta`}, + {id: "G", text: $localize`:@@publicationClassG:Opinnäytteet`}, + {id: "I", text: $localize`:@@publicationClassI:Audiovisuaaliset julkaisut ja tieto- ja viestintätekniset sovellukset`}, + ]; + + faSlidersH = faSlidersH; + faChartBar = faChartBar; + + openDialog() { + this.dialogRef = this.dialog.open(this.dialogTemplate, { + panelClass: 'fullscreen-panel', + }); + + this.dialogRef.closed.subscribe(() => { + console.log('The dialog2 was closed'); + }); + } + + closeDialog() { + this.dialogRef?.close(); + } + + clearFilters() { + this.router.navigate([], { + relativeTo: this.route, + queryParams: { + q: this.keywords, + page: this.page.toString(), + size: this.size.toString(), + } + }); + } + + displayedColumns: string[] = ['icon', 'publicationName', 'authorsText', 'publisherName', 'publicationYear']; + + highlights$ = this.publications2Service.getSearch(); // TODO: /*: Observable*/ + dataSource = new PublicationDataSource(this.highlights$); + + searchParams$ = this.route.queryParams.pipe( map(splitFields) ); + aggregations$ = this.publications2Service.getAggregations(); + + yearAdditions$ = this.aggregations$.pipe( + map(aggs => + getYearAdditions(aggs).map( + (bucket: any) => ({ year: bucket.key.toString(), count: bucket.doc_count }) + ) ?? [] + ), + map(aggs => aggs.sort((a, b) => b.year - a.year)) + ); + + enabledYearFilters$ = this.searchParams$.pipe(map(params => params.year ?? [])); + + yearFilters$ = combineLatest([this.yearAdditions$, this.enabledYearFilters$]).pipe( + map(([yearAdditions, enabledFilters]) => yearAdditions.map(yearAddition => ({ + year: yearAddition.year, + count: yearAddition.count, + enabled: enabledFilters.includes(yearAddition.year.toString()) + }))) + ); + + organizationNames$ = this.publications2Service.getOrganizationNames(); + + organizationAdditions$ = this.aggregations$.pipe( + map(aggs => getOrganizationAdditions(aggs).map((bucket: any) => ({ id: bucket.key, count: bucket.doc_count})) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + enabledOrganizationFilters$ = this.searchParams$.pipe(map(params => params.organization ?? [])); + + enabledOrganizationFiltersWithNames$ = combineLatest([this.enabledOrganizationFilters$, this.organizationNames$]).pipe( + map(([enabledFilters, organizationNames]) => enabledFilters.map(filter => ({ id: filter, name: organizationNames[filter].name }))) + ); + + organizationFilters$ = combineLatest([this.organizationAdditions$, this.organizationNames$, this.enabledOrganizationFilters$]).pipe( + map(([organizationAdditions, organizationNames, enabledFilters]) => organizationAdditions.map(organizationAddition => ({ + id: organizationAddition.id, + count: organizationAddition.count, + name: organizationNames[organizationAddition.id].name, + sectorId: organizationNames[organizationAddition.id].sectorId, + enabled: enabledFilters.includes(organizationAddition.id) + }))) + ); + + languageCodeAdditions$ = this.aggregations$.pipe( + map(aggs => getLanguageCodeAdditions(aggs).map((bucket: any) => ({ languageCode: bucket.key, count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + languageCodeNames$ = this.publications2Service.getLanguageCodeNames(); + + enabledLanguageCodeFilters$ = this.searchParams$.pipe(map(params => params.language ?? [])); + + enabledLanguageCodeFiltersWithNames$ = combineLatest([this.enabledLanguageCodeFilters$, this.languageCodeNames$]).pipe( + map(([enabledFilters, languageCodeNames]) => enabledFilters.map(filter => ({ id: filter, name: languageCodeNames[filter] }))) + ); + + languageCodeFilters$ = combineLatest([this.languageCodeAdditions$, this.languageCodeNames$, this.enabledLanguageCodeFilters$]).pipe( + map(([languageCodeAdditions, languageCodeNames, enabledFilters]) => languageCodeAdditions.map(languageCodeAddition => ({ + id: languageCodeAddition.languageCode, + count: languageCodeAddition.count, + name: languageCodeNames[languageCodeAddition.languageCode], + enabled: enabledFilters.includes(languageCodeAddition.languageCode) + }))) + ); + + publicationFormatNames$ = this.publications2Service.getPublicationFormatNames(); + + publicationFormatAdditions$ = this.aggregations$.pipe( + map(aggs => getPublicationFormatAdditions(aggs).map((bucket: any) => ({ id: bucket.key, count: bucket.doc_count })) ?? []), + map(aggs => aggs.filter(publicationFormatAddition => publicationFormatAddition.id !== "-1")), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + enabledPublicationFormatFilters$ = this.searchParams$.pipe(map(params => params.format ?? [])); + + enabledPublicationFormatFiltersWithNames$ = combineLatest([this.enabledPublicationFormatFilters$, this.publicationFormatNames$]).pipe( + map(([enabledFilters, publicationFormatNames]) => enabledFilters.map(filter => ({ id: filter, name: publicationFormatNames[filter] }))) + ); + + publicationFormatFilters$ = combineLatest([this.publicationFormatAdditions$, this.publicationFormatNames$, this.enabledPublicationFormatFilters$]).pipe( + map(([publicationFormatAdditions, publicationFormatNames, enabledFilters]) => publicationFormatAdditions.map(publicationFormatAddition => ({ + id: publicationFormatAddition.id, + count: publicationFormatAddition.count, + name: publicationFormatNames[publicationFormatAddition.id], + enabled: enabledFilters.includes(publicationFormatAddition.id) + }))) + ); + + publicationAudienceNames$ = this.publications2Service.getPublicationAudienceNames(); + + publicationAudienceAdditions$ = this.aggregations$.pipe( + map(aggs => getPublicationAudienceAdditions(aggs).map((bucket: any) => ({ id: bucket.key, count: bucket.doc_count })) ?? []), + map(aggs => aggs.filter(publicationAudienceAddition => publicationAudienceAddition.id !== "-1")), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + enabledPublicationAudienceFilters$ = this.searchParams$.pipe(map(params => params.audience ?? [])); + + enabledPublicationAudienceFiltersWithNames$ = combineLatest([this.enabledPublicationAudienceFilters$, this.publicationAudienceNames$]).pipe( + map(([enabledFilters, publicationAudienceNames]) => enabledFilters.map(filter => ({ id: filter, name: publicationAudienceNames[filter] }))) + ); + + publicationAudienceFilters$ = combineLatest([this.publicationAudienceAdditions$, this.publicationAudienceNames$, this.enabledPublicationAudienceFilters$]).pipe( + map(([publicationAudienceAdditions, publicationAudienceNames, enabledFilters]) => publicationAudienceAdditions.map(publicationAudienceAddition => ({ + id: publicationAudienceAddition.id, + count: publicationAudienceAddition.count, + name: publicationAudienceNames[publicationAudienceAddition.id], + enabled: enabledFilters.includes(publicationAudienceAddition.id) + }))) + ); + + peerReviewedAdditions$ = this.aggregations$.pipe( + map(aggs => getPeerReviewedAdditions(aggs).map((bucket: any) => ({ id: bucket.key, count: bucket.doc_count })) ?? []), + map(aggs => aggs.filter(peerReviewedAddition => ![' ', '-1'].includes(peerReviewedAddition.id))), + map(aggs => aggs.sort((a, b) => b.count - a.count)), + ); + + peerReviewedNames$ = this.publications2Service.getPeerReviewedNames(); + + enabledPeerReviewedFilters$ = this.searchParams$.pipe(map(params => params.peerReviewed ?? [])); + + enabledPeerReviewedFiltersWithNames$ = combineLatest([this.enabledPeerReviewedFilters$, this.peerReviewedNames$]).pipe( + map(([enabledFilters, peerReviewedNames]) => enabledFilters.map(filter => ({ id: filter, name: peerReviewedNames[filter] }))) + ); + + peerReviewedFilters$ = combineLatest([this.peerReviewedAdditions$, this.peerReviewedNames$, this.enabledPeerReviewedFilters$]).pipe( + map(([peerReviewedAdditions, peerReviewedNames, enabledFilters]) => peerReviewedAdditions.map(peerReviewedAddition => ({ + id: peerReviewedAddition.id, + count: peerReviewedAddition.count, + name: peerReviewedNames[peerReviewedAddition.id], + enabled: enabledFilters.includes(peerReviewedAddition.id) + }))) + ); + + parentPublicationTypeAdditions$ = this.aggregations$.pipe( + map(aggs => getParentPublicationTypeAdditions(aggs).map((bucket: any) => ({ id: bucket.key, count: bucket.doc_count })) ?? []), + map(aggs => aggs.filter(parentPublicationTypeAddition => parentPublicationTypeAddition.id !== "-1")), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + publisherInternationalityAdditions$ = this.aggregations$.pipe( + map(aggs => getPublisherInternationalityAdditions(aggs).map((bucket: any) => ({ id: bucket.key.toString(), count: bucket.doc_count })) ?? []), + map(aggs => aggs.filter(internationalPublicationAddition => internationalPublicationAddition.id !== "9")), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + publisherInternationalityNames$ = this.publications2Service.getInternationalPublicationNames(); + + enabledPublisherInternationalityFilters$ = this.searchParams$.pipe(map(params => params.international ?? [])); + + enabledPublisherInternationalityFiltersWithNames$ = combineLatest([this.enabledPublisherInternationalityFilters$, this.publisherInternationalityNames$]).pipe( + map(([enabledFilters, publisherInternationalityNames]) => enabledFilters.map(filter => ({ id: filter, name: publisherInternationalityNames[filter] }))) + ); + + publisherInternationalityFilters$ = combineLatest([this.publisherInternationalityAdditions$, this.publisherInternationalityNames$, this.enabledPublisherInternationalityFilters$]).pipe( + map(([internationalPublicationAdditions, internationalPublicationNames, enabledFilters]) => internationalPublicationAdditions.map(internationalPublicationAddition => ({ + id: internationalPublicationAddition.id, + count: internationalPublicationAddition.count, + name: internationalPublicationNames[internationalPublicationAddition.id], + enabled: enabledFilters.includes(internationalPublicationAddition.id) + }))) + ); + + articleTypeCodeAdditions$ = this.aggregations$.pipe( + map(aggs => getArticleTypeCodeAdditions(aggs).map((bucket: any) => ({ id: bucket.key.toString(), count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + articleTypeCodeNames$ = this.publications2Service.getArticleTypeCodeNames(); + + enabledArticleTypeCodeFilters$ = this.searchParams$.pipe(map(params => params.articleType ?? [])); + + enabledArticleTypeCodeFiltersWithNames$ = combineLatest([this.enabledArticleTypeCodeFilters$, this.articleTypeCodeNames$]).pipe( + map(([enabledFilters, articleTypeCodeNames]) => enabledFilters.map(filter => ({ id: filter, name: articleTypeCodeNames[filter] }))) + ); + + articleTypeCodeFilters$ = combineLatest([this.articleTypeCodeAdditions$, this.articleTypeCodeNames$, this.enabledArticleTypeCodeFilters$]).pipe( + map(([articleTypeCodeAdditions, articleTypeCodeNames, enabledFilters]) => articleTypeCodeAdditions.map(articleTypeCodeAddition => ({ + id: articleTypeCodeAddition.id, + count: articleTypeCodeAddition.count, + name: articleTypeCodeNames[articleTypeCodeAddition.id], + enabled: enabledFilters.includes(articleTypeCodeAddition.id) + }))) + ); + + jufoClassCodeAdditions$ = this.aggregations$.pipe( + map(aggs => getJufoClassCodeAdditions(aggs).map((bucket: any) => ({ id: bucket.key.toString(), count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + enabledJufoClassCodeFilters$ = this.searchParams$.pipe(map(params => params.jufo ?? [])); + + jufoClassCodeFilters$ = combineLatest([this.jufoClassCodeAdditions$, this.enabledJufoClassCodeFilters$]).pipe( + map(([jufoClassCodeAdditions, enabledFilters]) => jufoClassCodeAdditions.map(jufoClassCodeAddition => ({ + id: jufoClassCodeAddition.id, + count: jufoClassCodeAddition.count, + name: jufoClassCodeAddition.id, + enabled: enabledFilters.includes(jufoClassCodeAddition.id) + }))) + ); + + fieldsOfScienceNames$ = this.publications2Service.getFieldsOfScienceNames(); + + fieldsOfScienceAdditions$ = this.aggregations$.pipe( + map(aggs => getFieldsOfScienceAdditions(aggs).map((bucket: any) => ({ id: bucket.key.toString(), count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + enabledFieldsOfScienceFilters$ = this.searchParams$.pipe(map(params => params.fieldsOfScience ?? [])); + + enabledFieldsOfScienceFiltersWithNames$ = combineLatest([this.enabledFieldsOfScienceFilters$, this.fieldsOfScienceNames$]).pipe( + map(([enabledFilters, fieldsOfScienceNames]) => enabledFilters.map(filter => ({ id: filter, name: fieldsOfScienceNames[filter] }))) + ); + + fieldsOfScienceFilters$ = combineLatest([this.fieldsOfScienceAdditions$, this.fieldsOfScienceNames$, this.enabledFieldsOfScienceFilters$]).pipe( + map(([fieldsOfScienceAdditions, fieldsOfScienceNames, enabledFilters]) => fieldsOfScienceAdditions.map(fieldsOfScienceAddition => ({ + id: fieldsOfScienceAddition.id, + count: fieldsOfScienceAddition.count, + name: fieldsOfScienceNames[fieldsOfScienceAddition.id], + enabled: enabledFilters.includes(fieldsOfScienceAddition.id) + }))) + ); + + publicationTypeCodeNames$ = this.publications2Service.getPublicationTypeCodeNames(); + + publicationTypeCodeAdditions$ = this.aggregations$.pipe( + map(aggs => getPublicationTypeCodeAdditions(aggs).map((bucket: any) => ({ id: bucket.key.toString(), count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + enabledPublicationTypeCodeFilters$ = this.searchParams$.pipe(map(params => params.publicationTypeCode ?? [])); + + enabledPublicationTypeCodeFiltersWithNames$ = combineLatest([this.enabledPublicationTypeCodeFilters$, this.publicationTypeCodeNames$]).pipe( + map(([enabledFilters, publicationTypeCodeNames]) => enabledFilters.map(filter => ({ id: filter, name: publicationTypeCodeNames[filter] }))) + ); + + publicationTypeCodeFilters$ = combineLatest([this.publicationTypeCodeAdditions$, this.publicationTypeCodeNames$, this.enabledPublicationTypeCodeFilters$]).pipe( + map(([publicationTypeCodeAdditions, publicationTypeCodeNames, enabledFilters]) => publicationTypeCodeAdditions.map(publicationTypeCodeAddition => ({ + id: publicationTypeCodeAddition.id, + count: publicationTypeCodeAddition.count, + name: publicationTypeCodeNames[publicationTypeCodeAddition.id], + enabled: enabledFilters.includes(publicationTypeCodeAddition.id) + }))) + ); + + parentPublicationTypeNames$ = this.publications2Service.getParentPublicationTypeNames(); + + enabledParentPublicationTypeFilters$ = this.searchParams$.pipe(map(params => params.parentPublicationType ?? [])); + + enabledParentPublicationTypeFiltersWithNames$ = combineLatest([this.enabledParentPublicationTypeFilters$, this.parentPublicationTypeNames$]).pipe( + map(([enabledFilters, parentPublicationTypeNames]) => enabledFilters.map(filter => ({ id: filter, name: parentPublicationTypeNames[filter] }))) + ); + + parentPublicationTypeFilters$ = combineLatest([this.parentPublicationTypeAdditions$, this.parentPublicationTypeNames$, this.enabledParentPublicationTypeFilters$]).pipe( + map(([parentPublicationTypeAdditions, parentPublicationTypeNames, enabledFilters]) => parentPublicationTypeAdditions.map(parentPublicationTypeAddition => ({ + id: parentPublicationTypeAddition.id, + count: parentPublicationTypeAddition.count, + name: parentPublicationTypeNames[parentPublicationTypeAddition.id], + enabled: enabledFilters.includes(parentPublicationTypeAddition.id) + }))) + ); + + additionsFromOpenAccess$ = this.aggregations$.pipe( + map(aggs => getOpenAccessAdditions(aggs).map((bucket: any) => ({ id: bucket.key.toString(), count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + openAccessNames$ = this.publications2Service.getOpenAccessNames(); + + enabledOpenAccessFilters$ = this.searchParams$.pipe(map(params => params.openAccess ?? [])); + + enabledOpenAccessFiltersWithNames$ = combineLatest([this.enabledOpenAccessFilters$, this.openAccessNames$]).pipe( + map(([enabledFilters, openAccessNames]) => enabledFilters.map(filter => ({ id: filter, name: openAccessNames[filter] }))) + ); + + openAccessFilters$ = combineLatest([this.additionsFromOpenAccess$, this.openAccessNames$, this.enabledOpenAccessFilters$]).pipe( + map(([additionsFromOpenAccess, openAccessNames, enabledFilters]) => additionsFromOpenAccess.map(additionFromOpenAccess => ({ + id: additionFromOpenAccess.id, + count: additionFromOpenAccess.count, + name: openAccessNames[additionFromOpenAccess.id], + enabled: enabledFilters.includes(additionFromOpenAccess.id) + }))) + ); + + additionsFromPublisherOpenAccess$ = this.aggregations$.pipe( + map(aggs => getPublisherOpenAccessCodeAdditions(aggs).map((bucket: any) => ({ id: bucket.key.toString(), count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + publisherOpenAccessNames$ = this.publications2Service.getPublisherOpenAccessNames(); + + enabledPublisherOpenAccessFilters$ = this.searchParams$.pipe(map(params => params.publisherOpenAccessCode ?? [])); + + enabledPublisherOpenAccessFiltersWithNames$ = combineLatest([this.enabledPublisherOpenAccessFilters$, this.publisherOpenAccessNames$]).pipe( + map(([enabledFilters, publisherOpenAccessNames]) => enabledFilters.map(filter => ({ id: filter, name: publisherOpenAccessNames[filter] }))) + ); + + publisherOpenAccessFilters$ = combineLatest([this.additionsFromPublisherOpenAccess$, this.publisherOpenAccessNames$, this.enabledPublisherOpenAccessFilters$]).pipe( + map(([additionsFromPublisherOpenAccess, publisherOpenAccessNames, enabledFilters]) => additionsFromPublisherOpenAccess.map(additionFromPublisherOpenAccess => ({ + id: additionFromPublisherOpenAccess.id, + count: additionFromPublisherOpenAccess.count, + name: publisherOpenAccessNames[additionFromPublisherOpenAccess.id], + enabled: enabledFilters.includes(additionFromPublisherOpenAccess.id) + }))) + ); + + additionsFromSelfArchivedCode$ = this.aggregations$.pipe( + map(aggs => getSelfArchivedCodeAdditions(aggs).map((bucket: any) => ({ id: bucket.key.toString(), count: bucket.doc_count })) ?? []), + map(aggs => aggs.sort((a, b) => b.count - a.count)) + ); + + selfArchivedCodeNames$ = this.publications2Service.getSelfArchivedCodeNames(); + + enabledSelfArchivedCodeFilters$ = this.searchParams$.pipe(map(params => params.selfArchivedCode ?? [])); + + enabledSelfArchivedCodeFiltersWithNames$ = combineLatest([this.enabledSelfArchivedCodeFilters$, this.selfArchivedCodeNames$]).pipe( + map(([enabledFilters, selfArchivedCodeNames]) => enabledFilters.map(filter => ({ id: filter, name: selfArchivedCodeNames[filter] }))) + ); + + selfArchivedCodeFilters$ = combineLatest([this.additionsFromSelfArchivedCode$, this.selfArchivedCodeNames$, this.enabledSelfArchivedCodeFilters$]).pipe( + map(([additionsFromSelfArchivedCode, selfArchivedCodeNames, enabledFilters]) => additionsFromSelfArchivedCode.map(additionFromSelfArchivedCode => ({ + id: additionFromSelfArchivedCode.id, + count: additionFromSelfArchivedCode.count, + name: selfArchivedCodeNames[additionFromSelfArchivedCode.id], + enabled: enabledFilters.includes(additionFromSelfArchivedCode.id) + }))) + ); + + searchTermsCount$ = this.searchParams$.pipe( + map(params => Object.keys(params).filter(key => !['q', 'page', 'size', 'sort'].includes(key)).reduce((acc, key) => acc + params[key].length, 0)) + ); + + public mainFieldOfScienceName = { + "1": $localize`:@@naturalSciences:Luonnontieteet`, + "2": $localize`:@@engineeringTecnology:Tekniikka`, + "3": $localize`:@@medicalHealthSciences:Lääke- ja terveystieteet`, + "4": $localize`:@@agriculturalSciences:Maatalous- ja metsätieteet`, + "5": $localize`:@@socialSciences:Yhteiskuntatieteet`, + "6": $localize`:@@humanities:Humanistiset tieteet`, + // 7 not used + "8": $localize`:@@fieldsOfArt:Taiteenala`, + } + + public filterLimits = { + year: 10, + language: 10, + }; + + breakpointSubscription = this.breakpointObserver.observe(['(max-width: 1200px)', '(max-width: 990px)']).subscribe(result => { + this.displayedColumns = ['icon', 'publicationName', 'authorsText', 'publisherName', 'publicationYear']; + + if (result.breakpoints['(max-width: 990px)']) { + this.displayedColumns = ['publicationName', 'publicationYear']; + } else if (result.breakpoints['(max-width: 1200px)']) { + this.displayedColumns = ['icon', 'publicationName', 'authorsText', 'publicationYear']; + } + }); + + narrowBreakpoint$: Observable = this.breakpointObserver.observe('(max-width: 990px)').pipe(map(result => result.matches)); + + searchParamsSubscription = this.searchParams$.subscribe(searchParams => { + this.publications2Service.updateSearchTerms(searchParams); + + this.keywords = searchParams.q?.[0] ?? ""; + this.page = parseInt(searchParams.page?.[0] ?? "1"); + this.size = parseInt(searchParams.size?.[0] ?? "10"); + this.sort = searchParams.sort?.[0] ?? ""; + }); + + total$ = this.publications2Service.getTotal(); + + ngOnDestroy() { + this.searchParamsSubscription.unsubscribe(); + this.breakpointSubscription.unsubscribe(); + } + + toggleParam(key: string, value: string) { + this.searchParams$.pipe(take(1)).subscribe(filterParams => { + const queryParams = { ...filterParams }; + + if (queryParams[key] == null) { + queryParams[key] = []; + } + + const index = queryParams[key].indexOf(value); + + if (index === -1) { + queryParams[key].push(value); + } else { + queryParams[key].splice(index, 1); + } + + if (queryParams[key].length === 0) { + delete queryParams[key]; + } + + queryParams.page = ["1"]; + + this.router.navigate([], { + relativeTo: this.route, + // skipLocationChange: true, + queryParams: concatFields(queryParams) + }); + }); + } + + setParam(key: string, value: string) { + this.searchParams$.pipe(take(1)).subscribe(filterParams => { + const queryParams = { ...filterParams }; + + queryParams[key] = [value]; + + queryParams.page = ["1"]; + + this.router.navigate([], { + relativeTo: this.route, + // skipLocationChange: true, + queryParams: concatFields(queryParams) + }); + }); + } + + clearParam(key: string) { + this.searchParams$.pipe(take(1)).subscribe(filterParams => { + const queryParams = { ...filterParams }; + + delete queryParams[key]; + + queryParams.page = ["1"]; + + this.router.navigate([], { + relativeTo: this.route, + // skipLocationChange: true, + queryParams: concatFields(queryParams) + }); + }); + } + + toggleSort(field: string) { + this.searchParams$.pipe(take(1)).subscribe(params => { + const existingSort = params.sort?.pop() ?? ""; + + if (existingSort === field + "Desc") { + this.clearParam("sort"); + } else if (existingSort === field) { + this.setParam("sort", field + "Desc"); + } else { + this.setParam("sort", field); + } + }); + } + + setKeywords(keywords: string) { + this.router.navigate([], { + relativeTo: this.route, + // skipLocationChange: true, + + queryParams: { + q: keywords, + page: "1" + }, + + queryParamsHandling: 'merge' + }); + } + + nextPage() { + this.searchParams$.pipe(take(1)).subscribe(searchParams => { + const queryParams = { ...searchParams }; + + const page = parseInt(queryParams.page?.[0] ?? "1"); + queryParams.page = [`${page + 1}`]; + + this.router.navigate([], { + relativeTo: this.route, + // skipLocationChange: true, + queryParams: queryParams + }); + }); + } + + previousPage() { + this.searchParams$.pipe(take(1)).subscribe(searchParams => { + const queryParams = { ...searchParams }; + + const page = parseInt(queryParams.page?.[0] ?? "1"); + queryParams.page = [`${page - 1}`]; + + this.router.navigate([], { + relativeTo: this.route, + // skipLocationChange: true, + queryParams: queryParams + }); + }); + } + + setPageSize(size: number) { + console.log(size); + + this.router.navigate([], { + relativeTo: this.route, + // skipLocationChange: true, + queryParams: { size }, queryParamsHandling: 'merge' + }); + } + + clamp(value: number, min: number, max: number) { + return Math.min(Math.max(value, min), max); + } +} + +export class PublicationDataSource extends DataSource { + constructor(private data$: Observable) { + super(); + } + + connect(): Observable { + return this.data$; + } + + disconnect() { /**/ } +} + +function concatParams(strings: string[]): string { + return strings.sort().join(","); +} + +function splitParams(input: string | string[]): string[] { + if (Array.isArray(input)) { + return input.flatMap(item => item.split(",")); + } + + return input.split(","); +} + +function splitFields(obj: Record): Record { + const result: Record = {}; + + for (const key in obj) { + if (key === 'q') { + result[key] = [obj[key] as string]; + } else { + const value = obj[key]; + result[key] = splitParams(value); + } + } + + return result; +} + +function concatFields(obj: Record): Record { + const result: Record = {}; + + for (const key in obj) { + const value = obj[key]; + result[key] = concatParams(value); + } + + return result; +} diff --git a/src/app/portal/components/results/results.component.html b/src/app/portal/components/results/results.component.html index 2882283a1..dc9a2f770 100644 --- a/src/app/portal/components/results/results.component.html +++ b/src/app/portal/components/results/results.component.html @@ -16,10 +16,49 @@

[allData]="tabValues" > + + + + + + +