diff --git a/angular.json b/angular.json index 24f70a21a733..bb1e8e3817f7 100644 --- a/angular.json +++ b/angular.json @@ -18,7 +18,7 @@ "prefix": "jhi", "architect": { "build": { - "builder": "@angular-devkit/build-angular:application", + "builder": "@angular/build:application", "options": { "allowedCommonJsDependencies": [ "@vscode/markdown-it-katex", @@ -187,7 +187,7 @@ "defaultConfiguration": "production" }, "serve": { - "builder": "@angular-devkit/build-angular:dev-server", + "builder": "@angular/build:dev-server", "options": { "buildTarget": "artemis:build:development", "proxyConfig": "proxy.conf.mjs", diff --git a/eslint.config.js b/eslint.config.js index 6029bf30bcd8..045271a554d2 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -51,22 +51,6 @@ module.exports = [ ...tsPlugin.configs.recommended.rules, ...angularPlugin.configs.recommended.rules, 'custom-rules/enforce-no-http-client-testing-module': 'error', - '@angular-eslint/directive-selector': [ - 'warn', - { - type: 'attribute', - prefix: 'jhi', - style: 'camelCase', - }, - ], - '@angular-eslint/component-selector': [ - 'warn', - { - type: 'element', - prefix: 'jhi', - style: 'kebab-case', - }, - ], '@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/no-unsafe-return': 'off', '@typescript-eslint/no-unsafe-member-access': 'off', diff --git a/package-lock.json b/package-lock.json index a543cb1fb222..642fa6184984 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,30 +10,30 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@angular/animations": "18.2.13", - "@angular/cdk": "18.2.14", - "@angular/common": "18.2.13", - "@angular/compiler": "18.2.13", - "@angular/core": "18.2.13", - "@angular/forms": "18.2.13", - "@angular/localize": "18.2.13", - "@angular/material": "18.2.14", - "@angular/platform-browser": "18.2.13", - "@angular/platform-browser-dynamic": "18.2.13", - "@angular/router": "18.2.13", - "@angular/service-worker": "18.2.13", + "@angular/animations": "19.0.6", + "@angular/cdk": "19.0.5", + "@angular/common": "19.0.6", + "@angular/compiler": "19.0.6", + "@angular/core": "19.0.6", + "@angular/forms": "19.0.6", + "@angular/localize": "19.0.6", + "@angular/material": "19.0.5", + "@angular/platform-browser": "19.0.6", + "@angular/platform-browser-dynamic": "19.0.6", + "@angular/router": "19.0.6", + "@angular/service-worker": "19.0.6", "@ctrl/ngx-emoji-mart": "9.2.0", - "@danielmoncada/angular-datetime-picker": "18.1.0", + "@danielmoncada/angular-datetime-picker": "19.0.0", "@fingerprintjs/fingerprintjs": "4.5.1", - "@fortawesome/angular-fontawesome": "0.15.0", + "@fortawesome/angular-fontawesome": "1.0.0", "@fortawesome/fontawesome-svg-core": "6.7.2", "@fortawesome/free-regular-svg-icons": "6.7.2", "@fortawesome/free-solid-svg-icons": "6.7.2", "@ls1intum/apollon": "3.3.15", - "@ng-bootstrap/ng-bootstrap": "17.0.1", + "@ng-bootstrap/ng-bootstrap": "18.0.0", "@ngx-translate/core": "16.0.4", "@ngx-translate/http-loader": "16.0.1", - "@sentry/angular": "8.47.0", + "@sentry/angular": "8.48.0", "@siemens/ngx-datatable": "22.4.1", "@swimlane/ngx-charts": "21.1.2", "@swimlane/ngx-graph": "9.0.1", @@ -41,7 +41,7 @@ "@vscode/markdown-it-katex": "1.1.1", "bootstrap": "5.3.3", "compare-versions": "6.1.1", - "core-js": "3.39.0", + "core-js": "3.40.0", "crypto-js": "4.2.0", "dayjs": "1.11.13", "diff-match-patch-typescript": "1.1.0", @@ -61,9 +61,9 @@ "markdown-it-highlightjs": "4.2.0", "mobile-drag-drop": "3.0.0-rc.0", "monaco-editor": "0.52.2", - "ngx-infinite-scroll": "18.0.0", - "ngx-webstorage": "18.0.0", - "papaparse": "5.4.1", + "ngx-infinite-scroll": "19.0.0", + "ngx-webstorage": "19.0.1", + "papaparse": "5.5.1", "pdf-lib": "1.17.1", "pdfjs-dist": "4.10.38", "rxjs": "7.8.1", @@ -74,27 +74,27 @@ "ts-cacheable": "1.0.10", "tslib": "2.8.1", "turndown": "7.2.0", - "uuid": "11.0.4", + "uuid": "11.0.5", "webstomp-client": "1.2.6", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz", - "zone.js": "0.14.10" + "zone.js": "0.15.0" }, "devDependencies": { - "@analogjs/vite-plugin-angular": "1.11.0", - "@angular-builders/jest": "18.0.0", - "@angular-devkit/build-angular": "18.2.12", - "@angular-eslint/builder": "18.4.3", - "@angular-eslint/eslint-plugin": "18.4.3", - "@angular-eslint/eslint-plugin-template": "18.4.3", - "@angular-eslint/schematics": "18.4.3", - "@angular-eslint/template-parser": "18.4.3", - "@angular/cli": "18.2.12", - "@angular/compiler-cli": "18.2.13", - "@angular/language-service": "18.2.13", - "@sentry/types": "8.47.0", + "@analogjs/vite-plugin-angular": "1.12.0", + "@angular-builders/jest": "19.0.0", + "@angular-eslint/builder": "19.0.2", + "@angular-eslint/eslint-plugin": "19.0.2", + "@angular-eslint/eslint-plugin-template": "19.0.2", + "@angular-eslint/schematics": "19.0.2", + "@angular-eslint/template-parser": "19.0.2", + "@angular/build": "19.0.7", + "@angular/cli": "19.0.7", + "@angular/compiler-cli": "19.0.6", + "@angular/language-service": "19.0.6", + "@sentry/types": "8.48.0", "@testing-library/angular": "17.3.5", "@types/crypto-js": "4.2.2", - "@types/d3-shape": "3.1.6", + "@types/d3-shape": "3.1.7", "@types/dompurify": "3.0.5", "@types/emoji-js": "3.5.2", "@types/jest": "29.5.14", @@ -106,15 +106,15 @@ "@types/sockjs-client": "1.5.4", "@types/turndown": "5.0.5", "@types/uuid": "10.0.0", - "@typescript-eslint/eslint-plugin": "8.19.0", - "@typescript-eslint/parser": "8.19.0", + "@typescript-eslint/eslint-plugin": "8.19.1", + "@typescript-eslint/parser": "8.19.1", "eslint": "9.17.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-deprecation": "3.0.0", "eslint-plugin-jest": "28.10.0", "eslint-plugin-jest-extended": "2.4.0", "eslint-plugin-prettier": "5.2.1", - "folder-hash": "4.1.0", + "folder-hash": "4.1.1", "husky": "9.1.7", "jest": "29.7.0", "jest-canvas-mock": "2.5.2", @@ -122,7 +122,7 @@ "jest-extended": "4.0.2", "jest-fail-on-console": "3.3.1", "jest-junit": "16.0.0", - "jest-preset-angular": "14.4.2", + "jest-preset-angular": "14.5.0", "lint-staged": "15.3.0", "ng-mocks": "14.13.1", "ngxtension": "4.2.0", @@ -131,8 +131,8 @@ "rimraf": "6.0.1", "sass": "1.83.1", "ts-jest": "29.2.5", - "typescript": "5.5.4", - "typescript-eslint": "8.19.0", + "typescript": "5.6.3", + "typescript-eslint": "8.19.1", "vite-tsconfig-paths": "5.1.4", "vitest": "2.1.8", "weak-napi": "2.0.2" @@ -155,9 +155,9 @@ } }, "node_modules/@analogjs/vite-plugin-angular": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@analogjs/vite-plugin-angular/-/vite-plugin-angular-1.11.0.tgz", - "integrity": "sha512-18HSwOAVFQjwwRQPq9+duOoubuiut0INo55h0gV3v2TWS+tAP2wXP8SPyAG99P3ySNQB7zMUYE8mVsqLM+8bDA==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@analogjs/vite-plugin-angular/-/vite-plugin-angular-1.12.0.tgz", + "integrity": "sha512-D/INewdBlO24eYs1wvau9uaEsIg74GqSYx457SL/wHw3WTtqagCVPcOhAI4UlnIryjw1EAvUQiwbgFnMo+bYfQ==", "dev": true, "license": "MIT", "dependencies": { @@ -182,41 +182,41 @@ } }, "node_modules/@angular-builders/common": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@angular-builders/common/-/common-2.0.0.tgz", - "integrity": "sha512-O5YJc++DtJVJhqA/OomRKN2jGYzvU/YXtfrPAqcA9Is3Ob5jvV0L0JHSAjSw/KaLvk/FjBIqoRVcYdLp5LKddA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@angular-builders/common/-/common-3.0.0.tgz", + "integrity": "sha512-AACGMwlBFYF3PaFekgJDCmqO1hMBrK5eyjHMN5aqJk3PV46BhnlNcQEa9pftLUKxoGijXBQzlalDZkceatyoMw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "^18.0.0", + "@angular-devkit/core": "^19.0.0", "ts-node": "^10.0.0", "tsconfig-paths": "^4.1.0" }, "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" } }, "node_modules/@angular-builders/jest": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@angular-builders/jest/-/jest-18.0.0.tgz", - "integrity": "sha512-nPNWMlV1ryjir6CC8dY8f6yaNe0lM1VJwbvYM99HmJSeRo+1IwouQQGUjRM/2Dx4OMAmL4EAPh7Ud2nr3Gj/FA==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@angular-builders/jest/-/jest-19.0.0.tgz", + "integrity": "sha512-DEKragHT26kwUhXx9goYehQ/WxFzpVrMHIicYF+L7sLVmFyCwPwAslYZZBe/eTm/x++tKRHnun1lbcf1ZDccRg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-builders/common": "2.0.0", - "@angular-devkit/architect": ">=0.1800.0 < 0.1900.0", - "@angular-devkit/core": "^18.0.0", - "jest-preset-angular": "14.1.0", + "@angular-builders/common": "3.0.0", + "@angular-devkit/architect": ">=0.1900.0 < 0.2000.0", + "@angular-devkit/core": "^19.0.0", + "jest-preset-angular": "14.4.2", "lodash": "^4.17.15" }, "engines": { - "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular-devkit/build-angular": "^18.0.0", - "@angular/compiler-cli": "^18.0.0", - "@angular/core": "^18.0.0", - "@angular/platform-browser-dynamic": "^18.0.0", + "@angular-devkit/build-angular": "^19.0.0", + "@angular/compiler-cli": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/platform-browser-dynamic": "^19.0.0", "jest": ">=29" } }, @@ -234,9 +234,9 @@ } }, "node_modules/@angular-builders/jest/node_modules/jest-preset-angular": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-14.1.0.tgz", - "integrity": "sha512-UJwPtpsAMl30UtBjHW0Ai0hhoKsNURC1dXH5tSYjumUsWR7iDke+oBEykz7uXv4rN+PWgeNIqkxo4KHQjOITlw==", + "version": "14.4.2", + "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-14.4.2.tgz", + "integrity": "sha512-BYYv0FaTDfBNh8WyA9mpOV3krfw20kurBGK8INZUnv7KZDAWZuQtCET4TwTWxSNQ9jS1OX1+a5weCm/bTDDM1A==", "dev": true, "license": "MIT", "dependencies": { @@ -254,10 +254,9 @@ "esbuild": ">=0.15.13" }, "peerDependencies": { - "@angular-devkit/build-angular": ">=15.0.0 <19.0.0", - "@angular/compiler-cli": ">=15.0.0 <19.0.0", - "@angular/core": ">=15.0.0 <19.0.0", - "@angular/platform-browser-dynamic": ">=15.0.0 <19.0.0", + "@angular/compiler-cli": ">=15.0.0 <20.0.0", + "@angular/core": ">=15.0.0 <20.0.0", + "@angular/platform-browser-dynamic": ">=15.0.0 <20.0.0", "jest": "^29.0.0", "typescript": ">=4.8" } @@ -285,13 +284,13 @@ "license": "MIT" }, "node_modules/@angular-devkit/architect": { - "version": "0.1802.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.12.tgz", - "integrity": "sha512-bepVb2/GtJppYKaeW8yTGE6egmoWZ7zagFDsmBdbF+BYp+HmeoPsclARcdryBPVq68zedyTRdvhWSUTbw1AYuw==", + "version": "0.1900.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1900.7.tgz", + "integrity": "sha512-3dRV0IB+MbNYbAGbYEFMcABkMphqcTvn5MG79dQkwcf2a9QZxCq2slwf/rIleWoDUcFm9r1NnVPYrTYNYJaqQg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.12", + "@angular-devkit/core": "19.0.7", "rxjs": "7.8.1" }, "engines": { @@ -301,40 +300,39 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.12.tgz", - "integrity": "sha512-quVUi7eqTq9OHumQFNl9Y8t2opm8miu4rlYnuF6rbujmmBDvdUvR6trFChueRczl2p5HWqTOr6NPoDGQm8AyNw==", + "version": "19.0.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-19.0.7.tgz", + "integrity": "sha512-R0vpJ+P5xBqF82zOMq2FvOP7pJz5NZ7PwHAIFuQ6z50SHLW/VcUA19ZoFKwxBX6A/Soyb66QXTcjZ5wbRqMm8w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1802.12", - "@angular-devkit/build-webpack": "0.1802.12", - "@angular-devkit/core": "18.2.12", - "@angular/build": "18.2.12", - "@babel/core": "7.25.2", - "@babel/generator": "7.25.0", - "@babel/helper-annotate-as-pure": "7.24.7", + "@angular-devkit/architect": "0.1900.7", + "@angular-devkit/build-webpack": "0.1900.7", + "@angular-devkit/core": "19.0.7", + "@angular/build": "19.0.7", + "@babel/core": "7.26.0", + "@babel/generator": "7.26.2", + "@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-transform-async-generator-functions": "7.25.0", - "@babel/plugin-transform-async-to-generator": "7.24.7", - "@babel/plugin-transform-runtime": "7.24.7", - "@babel/preset-env": "7.25.3", - "@babel/runtime": "7.25.0", - "@discoveryjs/json-ext": "0.6.1", - "@ngtools/webpack": "18.2.12", + "@babel/plugin-transform-async-generator-functions": "7.25.9", + "@babel/plugin-transform-async-to-generator": "7.25.9", + "@babel/plugin-transform-runtime": "7.25.9", + "@babel/preset-env": "7.26.0", + "@babel/runtime": "7.26.0", + "@discoveryjs/json-ext": "0.6.3", + "@ngtools/webpack": "19.0.7", "@vitejs/plugin-basic-ssl": "1.1.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.20", - "babel-loader": "9.1.3", + "babel-loader": "9.2.1", "browserslist": "^4.21.5", "copy-webpack-plugin": "12.0.2", - "critters": "0.0.24", "css-loader": "7.1.2", - "esbuild-wasm": "0.23.0", + "esbuild-wasm": "0.24.0", "fast-glob": "3.3.2", "http-proxy-middleware": "3.0.3", - "https-proxy-agent": "7.0.5", "istanbul-lib-instrument": "6.0.3", "jsonc-parser": "3.3.1", "karma-source-map-support": "1.4.0", @@ -342,31 +340,26 @@ "less-loader": "12.2.0", "license-webpack-plugin": "4.0.2", "loader-utils": "3.3.1", - "magic-string": "0.30.11", - "mini-css-extract-plugin": "2.9.0", - "mrmime": "2.0.0", + "mini-css-extract-plugin": "2.9.2", "open": "10.1.0", "ora": "5.4.1", - "parse5-html-rewriting-stream": "7.0.0", "picomatch": "4.0.2", - "piscina": "4.6.1", - "postcss": "8.4.41", + "piscina": "4.7.0", + "postcss": "8.4.49", "postcss-loader": "8.1.1", "resolve-url-loader": "5.0.0", "rxjs": "7.8.1", - "sass": "1.77.6", - "sass-loader": "16.0.0", + "sass": "1.80.7", + "sass-loader": "16.0.3", "semver": "7.6.3", "source-map-loader": "5.0.0", "source-map-support": "0.5.21", - "terser": "5.31.6", + "terser": "5.36.0", "tree-kill": "1.2.2", - "tslib": "2.6.3", - "vite": "5.4.6", - "watchpack": "2.4.1", - "webpack": "5.94.0", + "tslib": "2.8.1", + "webpack": "5.96.1", "webpack-dev-middleware": "7.4.2", - "webpack-dev-server": "5.0.4", + "webpack-dev-server": "5.1.0", "webpack-merge": "6.0.1", "webpack-subresource-integrity": "5.1.0" }, @@ -376,22 +369,23 @@ "yarn": ">= 1.13.0" }, "optionalDependencies": { - "esbuild": "0.23.0" + "esbuild": "0.24.0" }, "peerDependencies": { - "@angular/compiler-cli": "^18.0.0", - "@angular/localize": "^18.0.0", - "@angular/platform-server": "^18.0.0", - "@angular/service-worker": "^18.0.0", - "@web/test-runner": "^0.18.0", + "@angular/compiler-cli": "^19.0.0", + "@angular/localize": "^19.0.0", + "@angular/platform-server": "^19.0.0", + "@angular/service-worker": "^19.0.0", + "@angular/ssr": "^19.0.7", + "@web/test-runner": "^0.19.0", "browser-sync": "^3.0.2", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "karma": "^6.3.0", - "ng-packagr": "^18.0.0", + "ng-packagr": "^19.0.0", "protractor": "^7.0.0", "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.4 <5.6" + "typescript": ">=5.5 <5.7" }, "peerDependenciesMeta": { "@angular/localize": { @@ -403,6 +397,9 @@ "@angular/service-worker": { "optional": true }, + "@angular/ssr": { + "optional": true + }, "@web/test-runner": { "optional": true }, @@ -429,22 +426,16 @@ } } }, - "node_modules/@angular-devkit/build-angular/node_modules/immutable": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", - "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", - "dev": true, - "license": "MIT" - }, "node_modules/@angular-devkit/build-angular/node_modules/sass": { - "version": "1.77.6", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz", - "integrity": "sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==", + "version": "1.80.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.7.tgz", + "integrity": "sha512-MVWvN0u5meytrSjsU7AWsbhoXi1sc58zADXFllfZzbsBT1GHjjar6JwBINYPRrkx/zqnQ6uqbQuHgE95O+C+eQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", + "chokidar": "^4.0.0", + "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { @@ -452,23 +443,20 @@ }, "engines": { "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" } }, - "node_modules/@angular-devkit/build-angular/node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true, - "license": "0BSD" - }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1802.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.12.tgz", - "integrity": "sha512-0Z3fdbZVRnjYWE2/VYyfy+uieY+6YZyEp4ylzklVkc+fmLNsnz4Zw6cK1LzzcBqAwKIyh1IdW20Cg7o8b0sONA==", + "version": "0.1900.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1900.7.tgz", + "integrity": "sha512-F0S0iyspo/9w9rP5F9wmL+ZkBr48YQIWiFu+PaQ0in/lcdRmY/FjVHTMa5BMnlew9VCtFHPvpoN9x4u8AIoWXA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@angular-devkit/architect": "0.1802.12", + "@angular-devkit/architect": "0.1900.7", "rxjs": "7.8.1" }, "engines": { @@ -482,9 +470,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.12.tgz", - "integrity": "sha512-NtB6ypsaDyPE6/fqWOdfTmACs+yK5RqfH5tStEzWFeeDsIEDYKsJ06ypuRep7qTjYus5Rmttk0Ds+cFgz8JdUQ==", + "version": "19.0.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.7.tgz", + "integrity": "sha512-VyuORSitT6LIaGUEF0KEnv2TwNaeWl6L3/4L4stok0BJ23B4joVca2DYVcrLC1hSzz8V4dwVgSlbNIgjgGdVpg==", "dev": true, "license": "MIT", "dependencies": { @@ -501,7 +489,7 @@ "yarn": ">= 1.13.0" }, "peerDependencies": { - "chokidar": "^3.5.2" + "chokidar": "^4.0.0" }, "peerDependenciesMeta": { "chokidar": { @@ -510,15 +498,15 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.12.tgz", - "integrity": "sha512-mMea9txHbnCX5lXLHlo0RAgfhFHDio45/jMsREM2PA8UtVf2S8ltXz7ZwUrUyMQRv8vaSfn4ijDstF4hDMnRgQ==", + "version": "19.0.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.7.tgz", + "integrity": "sha512-BHXQv6kMc9xo4TH9lhwMv8nrZXHkLioQvLun2qYjwvOsyzt3qd+sUM9wpHwbG6t+01+FIQ05iNN9ox+Cvpndgg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.12", + "@angular-devkit/core": "19.0.7", "jsonc-parser": "3.3.1", - "magic-string": "0.30.11", + "magic-string": "0.30.12", "ora": "5.4.1", "rxjs": "7.8.1" }, @@ -529,14 +517,14 @@ } }, "node_modules/@angular-eslint/builder": { - "version": "18.4.3", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-18.4.3.tgz", - "integrity": "sha512-NzmrXlr7GFE+cjwipY/CxBscZXNqnuK0us1mO6Z2T6MeH6m+rRcdlY/rZyKoRniyNNvuzl6vpEsfMIMmnfebrA==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-19.0.2.tgz", + "integrity": "sha512-BdmMSndQt2fSBiTVniskUcUpQaeweUapbsL0IDfQ7a13vL0NVXpc3K89YXuVE/xsb08uHtqphuwxPAAj6kX3OA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": ">= 0.1800.0 < 0.1900.0", - "@angular-devkit/core": ">= 18.0.0 < 19.0.0" + "@angular-devkit/architect": ">= 0.1900.0 < 0.2000.0", + "@angular-devkit/core": ">= 19.0.0 < 20.0.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", @@ -544,21 +532,21 @@ } }, "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "18.4.3", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-18.4.3.tgz", - "integrity": "sha512-zdrA8mR98X+U4YgHzUKmivRU+PxzwOL/j8G7eTOvBuq8GPzsP+hvak+tyxlgeGm9HsvpFj9ERHLtJ0xDUPs8fg==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-19.0.2.tgz", + "integrity": "sha512-HPmp92r70SNO/0NdIaIhxrgVSpomqryuUk7jszvNRtu+OzYCJGcbLhQD38T3dbBWT/AV0QXzyzExn6/2ai9fEw==", "dev": true, "license": "MIT" }, "node_modules/@angular-eslint/eslint-plugin": { - "version": "18.4.3", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-18.4.3.tgz", - "integrity": "sha512-AyJbupiwTBR81P6T59v+aULEnPpZBCBxL2S5QFWfAhNCwWhcof4GihvdK2Z87yhvzDGeAzUFSWl/beJfeFa+PA==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-19.0.2.tgz", + "integrity": "sha512-DLuNVVGGFicSThOcMSJyNje+FZSPdG0B3lCBRiqcgKH/16kfM4pV8MobPM7RGK2NhaOmmZ4zzJNwpwWPSgi+Lw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "18.4.3", - "@angular-eslint/utils": "18.4.3" + "@angular-eslint/bundled-angular-compiler": "19.0.2", + "@angular-eslint/utils": "19.0.2" }, "peerDependencies": { "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", @@ -567,14 +555,14 @@ } }, "node_modules/@angular-eslint/eslint-plugin-template": { - "version": "18.4.3", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-18.4.3.tgz", - "integrity": "sha512-ijGlX2N01ayMXTpeQivOA31AszO8OEbu9ZQUCxnu9AyMMhxyi2q50bujRChAvN9YXQfdQtbxuajxV6+aiWb5BQ==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-19.0.2.tgz", + "integrity": "sha512-f/OCF9ThnxQ8m0eNYPwnCrySQPhYfCOF6STL7F9LnS8Bs3ZeW3/oT1yLaMIZ1Eg0ogIkgxksMAJZjrJPUPBD1Q==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "18.4.3", - "@angular-eslint/utils": "18.4.3", + "@angular-eslint/bundled-angular-compiler": "19.0.2", + "@angular-eslint/utils": "19.0.2", "aria-query": "5.3.2", "axobject-query": "4.1.0" }, @@ -586,29 +574,29 @@ } }, "node_modules/@angular-eslint/schematics": { - "version": "18.4.3", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-18.4.3.tgz", - "integrity": "sha512-D5maKn5e6n58+8n7jLFLD4g+RGPOPeDSsvPc1sqial5tEKLxAJQJS9WZ28oef3bhkob6C60D+1H0mMmEEVvyVA==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-19.0.2.tgz", + "integrity": "sha512-wI4SyiAnUCrpigtK6PHRlVWMC9vWljqmlLhbsJV5O5yDajlmRdvgXvSHDefhJm0hSfvZYRXuiAARYv2+QVfnGA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": ">= 18.0.0 < 19.0.0", - "@angular-devkit/schematics": ">= 18.0.0 < 19.0.0", - "@angular-eslint/eslint-plugin": "18.4.3", - "@angular-eslint/eslint-plugin-template": "18.4.3", + "@angular-devkit/core": ">= 19.0.0 < 20.0.0", + "@angular-devkit/schematics": ">= 19.0.0 < 20.0.0", + "@angular-eslint/eslint-plugin": "19.0.2", + "@angular-eslint/eslint-plugin-template": "19.0.2", "ignore": "6.0.2", "semver": "7.6.3", "strip-json-comments": "3.1.1" } }, "node_modules/@angular-eslint/template-parser": { - "version": "18.4.3", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-18.4.3.tgz", - "integrity": "sha512-JZMPtEB8yNip3kg4WDEWQyObSo2Hwf+opq2ElYuwe85GQkGhfJSJ2CQYo4FSwd+c5MUQAqESNRg9QqGYauDsiw==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-19.0.2.tgz", + "integrity": "sha512-z3rZd2sBfuYcFf9rGDsB2zz2fbGX8kkF+0ftg9eocyQmzWrlZHFmuw9ha7oP/Mz8gpblyCS/aa1U/Srs6gz0UQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "18.4.3", + "@angular-eslint/bundled-angular-compiler": "19.0.2", "eslint-scope": "^8.0.2" }, "peerDependencies": { @@ -617,13 +605,13 @@ } }, "node_modules/@angular-eslint/utils": { - "version": "18.4.3", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-18.4.3.tgz", - "integrity": "sha512-w0bJ9+ELAEiPBSTPPm9bvDngfu1d8JbzUhvs2vU+z7sIz/HMwUZT5S4naypj2kNN0gZYGYrW0lt+HIbW87zTAQ==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-19.0.2.tgz", + "integrity": "sha512-HotBT8OKr7zCaX1S9k27JuhRiTVIbbYVl6whlb3uwdMIPIWY8iOcEh1tjI4qDPUafpLfR72Dhwi5bO1E17F3/Q==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "18.4.3" + "@angular-eslint/bundled-angular-compiler": "19.0.2" }, "peerDependencies": { "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", @@ -632,9 +620,9 @@ } }, "node_modules/@angular/animations": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.13.tgz", - "integrity": "sha512-rG5J5Ek5Hg+Tz2NjkNOaG6PupiNK/lPfophXpsR1t/nWujqnMWX2krahD/i6kgD+jNWNKCJCYSOVvCx/BHOtKA==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.0.6.tgz", + "integrity": "sha512-dlXrFcw7RQNze1zjmrbwqcFd6zgEuqKwuExtEN1Fy26kQ+wqKIhYO6IG7PZGef53XpwN5DT16yve6UihJ2XeNg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -643,56 +631,61 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.13" + "@angular/core": "19.0.6" } }, "node_modules/@angular/build": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.12.tgz", - "integrity": "sha512-4Ohz+OSILoL+cCAQ4UTiCT5v6pctu3fXNoNpTEUK46OmxELk9jDITO5rNyNS7TxBn9wY69kjX5VcDf7MenquFQ==", + "version": "19.0.7", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-19.0.7.tgz", + "integrity": "sha512-AFvhRa6sfXG8NmS8AN7TvE8q2kVcMw+zXMZzo981cqwnOwJy4VHU0htqm5OZQnohVJM0pP8SBAuROWO4yRrxCA==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1802.12", - "@babel/core": "7.25.2", - "@babel/helper-annotate-as-pure": "7.24.7", + "@angular-devkit/architect": "0.1900.7", + "@babel/core": "7.26.0", + "@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-syntax-import-attributes": "7.24.7", - "@inquirer/confirm": "3.1.22", + "@babel/plugin-syntax-import-attributes": "7.26.0", + "@inquirer/confirm": "5.0.2", "@vitejs/plugin-basic-ssl": "1.1.0", + "beasties": "0.1.0", "browserslist": "^4.23.0", - "critters": "0.0.24", - "esbuild": "0.23.0", + "esbuild": "0.24.0", "fast-glob": "3.3.2", "https-proxy-agent": "7.0.5", - "listr2": "8.2.4", - "lmdb": "3.0.13", - "magic-string": "0.30.11", + "istanbul-lib-instrument": "6.0.3", + "listr2": "8.2.5", + "magic-string": "0.30.12", "mrmime": "2.0.0", "parse5-html-rewriting-stream": "7.0.0", "picomatch": "4.0.2", - "piscina": "4.6.1", - "rollup": "4.22.4", - "sass": "1.77.6", + "piscina": "4.7.0", + "rollup": "4.26.0", + "sass": "1.80.7", "semver": "7.6.3", - "vite": "5.4.6", - "watchpack": "2.4.1" + "vite": "5.4.11", + "watchpack": "2.4.2" }, "engines": { "node": "^18.19.1 || ^20.11.1 || >=22.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, + "optionalDependencies": { + "lmdb": "3.1.5" + }, "peerDependencies": { - "@angular/compiler-cli": "^18.0.0", - "@angular/localize": "^18.0.0", - "@angular/platform-server": "^18.0.0", - "@angular/service-worker": "^18.0.0", + "@angular/compiler": "^19.0.0", + "@angular/compiler-cli": "^19.0.0", + "@angular/localize": "^19.0.0", + "@angular/platform-server": "^19.0.0", + "@angular/service-worker": "^19.0.0", + "@angular/ssr": "^19.0.7", "less": "^4.2.0", "postcss": "^8.4.0", "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.4 <5.6" + "typescript": ">=5.5 <5.7" }, "peerDependenciesMeta": { "@angular/localize": { @@ -704,6 +697,9 @@ "@angular/service-worker": { "optional": true }, + "@angular/ssr": { + "optional": true + }, "less": { "optional": true }, @@ -715,22 +711,15 @@ } } }, - "node_modules/@angular/build/node_modules/immutable": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", - "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", - "dev": true, - "license": "MIT" - }, "node_modules/@angular/build/node_modules/sass": { - "version": "1.77.6", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz", - "integrity": "sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==", + "version": "1.80.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.7.tgz", + "integrity": "sha512-MVWvN0u5meytrSjsU7AWsbhoXi1sc58zADXFllfZzbsBT1GHjjar6JwBINYPRrkx/zqnQ6uqbQuHgE95O+C+eQ==", "dev": true, "license": "MIT", "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", + "chokidar": "^4.0.0", + "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { @@ -738,12 +727,15 @@ }, "engines": { "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" } }, "node_modules/@angular/cdk": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.2.14.tgz", - "integrity": "sha512-vDyOh1lwjfVk9OqoroZAP8pf3xxKUvyl+TVR8nJxL4c5fOfUFkD7l94HaanqKSRwJcI2xiztuu92IVoHn8T33Q==", + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-19.0.5.tgz", + "integrity": "sha512-+D++QUrJlDuwk5RhQBDTejQseb0ZP6c6S4r8wBBab7UPtrwigySudSb0PxhiAzp2YHr5Ch3klhkTf/NSWeUXUQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -752,31 +744,31 @@ "parse5": "^7.1.2" }, "peerDependencies": { - "@angular/common": "^18.0.0 || ^19.0.0", - "@angular/core": "^18.0.0 || ^19.0.0", + "@angular/common": "^19.0.0 || ^20.0.0", + "@angular/core": "^19.0.0 || ^20.0.0", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/cli": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.12.tgz", - "integrity": "sha512-xhuZ/b7IhqNw1MgXf+arWf4x+GfUSt/IwbdWU4+CO8A7h0Y46zQywouP/KUK3cMQZfVdHdciTBvlpF3vFacA6Q==", + "version": "19.0.7", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-19.0.7.tgz", + "integrity": "sha512-y6C4B4XdiZwe2+OADLWXyKqUVvW/XDzTuJ2mZ5PhTnSiiXDN4zRWId1F5wA8ve8vlbUKApPHXRQuaqiQJmA24g==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1802.12", - "@angular-devkit/core": "18.2.12", - "@angular-devkit/schematics": "18.2.12", - "@inquirer/prompts": "5.3.8", - "@listr2/prompt-adapter-inquirer": "2.0.15", - "@schematics/angular": "18.2.12", + "@angular-devkit/architect": "0.1900.7", + "@angular-devkit/core": "19.0.7", + "@angular-devkit/schematics": "19.0.7", + "@inquirer/prompts": "7.1.0", + "@listr2/prompt-adapter-inquirer": "2.0.18", + "@schematics/angular": "19.0.7", "@yarnpkg/lockfile": "1.1.0", - "ini": "4.1.3", + "ini": "5.0.0", "jsonc-parser": "3.3.1", - "listr2": "8.2.4", - "npm-package-arg": "11.0.3", - "npm-pick-manifest": "9.1.0", - "pacote": "18.0.6", + "listr2": "8.2.5", + "npm-package-arg": "12.0.0", + "npm-pick-manifest": "10.0.0", + "pacote": "20.0.0", "resolve": "1.22.8", "semver": "7.6.3", "symbol-observable": "4.0.0", @@ -792,9 +784,9 @@ } }, "node_modules/@angular/common": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.13.tgz", - "integrity": "sha512-4ZqrNp1PoZo7VNvW+sbSc2CB2axP1sCH2wXl8B0wdjsj8JY1hF1OhuugwhpAHtGxqewed2kCXayE+ZJqSTV4jw==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.0.6.tgz", + "integrity": "sha512-r9IDD0+UGkrQkjyX+pApeDmIJ9INpr1uYlgmmlWNBJCVNr9SKKIVZV60sssgadew6bGynKN9dW4mGsmEzzb5BA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -803,14 +795,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.13", + "@angular/core": "19.0.6", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.13.tgz", - "integrity": "sha512-TzWcrkopyjFF+WeDr2cRe8CcHjU72KfYV3Sm2TkBkcXrkYX5sDjGWrBGrG3hRB4e4okqchrOCvm1MiTdy2vKMA==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.0.6.tgz", + "integrity": "sha512-g8A6QOsiCJnRi5Hz0sASIpRQoAGxEgnjz0JanfrMNRedY4MpdIS1V0AeCSKTsMRlV7tQl3ng2Gse/tsb51HI3Q==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -819,7 +811,7 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.13" + "@angular/core": "19.0.6" }, "peerDependenciesMeta": { "@angular/core": { @@ -828,12 +820,12 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.13.tgz", - "integrity": "sha512-DBSh4AQwkiJDSiVvJATRmjxf6wyUs9pwQLgaFdSlfuTRO+sdb0J2z1r3BYm8t0IqdoyXzdZq2YCH43EmyvD71g==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-19.0.6.tgz", + "integrity": "sha512-fHtwI5rCe3LmKDoaqlqLAPdNmLrbeCiMYVe+X1BHgApaqNCyAwcuJxuf8Q5R5su7nHiLmlmB74o1ZS/V+0cQ+g==", "license": "MIT", "dependencies": { - "@babel/core": "7.25.2", + "@babel/core": "7.26.0", "@jridgewell/sourcemap-codec": "^1.4.14", "chokidar": "^4.0.0", "convert-source-map": "^1.5.1", @@ -851,42 +843,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "18.2.13", - "typescript": ">=5.4 <5.6" - } - }, - "node_modules/@angular/compiler-cli/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular/compiler-cli/node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "license": "MIT", - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "@angular/compiler": "19.0.6", + "typescript": ">=5.5 <5.7" } }, "node_modules/@angular/core": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.13.tgz", - "integrity": "sha512-8mbWHMgO95OuFV1Ejy4oKmbe9NOJ3WazQf/f7wks8Bck7pcihd0IKhlPBNjFllbF5o+04EYSwFhEtvEgjMDClA==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.0.6.tgz", + "integrity": "sha512-9N7FmdRHtS7zfXC/wnyap/reX7fgiOrWpVivayHjWP4RkLYXJAzJIpLyew0jrx4vf8r3lZnC0Zmq0PW007Ngjw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -896,13 +860,13 @@ }, "peerDependencies": { "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.14.10" + "zone.js": "~0.15.0" } }, "node_modules/@angular/forms": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.13.tgz", - "integrity": "sha512-A67D867fu3DSBhdLWWZl/F5pr7v2+dRM2u3U7ZJ0ewh4a+sv+0yqWdJW+a8xIoiHxS+btGEJL2qAKJiH+MCFfg==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-19.0.6.tgz", + "integrity": "sha512-HogauPvgDQHw2xxqKBaFgKTRRcc1xWeI/PByDCf3U6YsaqpF53Mz2CJh8X2bg2bY1RGKb67MZw7DBGFRvXx4bg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -911,16 +875,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.13", - "@angular/core": "18.2.13", - "@angular/platform-browser": "18.2.13", + "@angular/common": "19.0.6", + "@angular/core": "19.0.6", + "@angular/platform-browser": "19.0.6", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.2.13.tgz", - "integrity": "sha512-4E4VJDrbOAxS69F9C1twQPbR9AjY47Qlz8+lwg5lJOyUJ4GoEThLbXKfadt/vIeYBwMJ7fIsYWXD0Dlmxh4k+w==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-19.0.6.tgz", + "integrity": "sha512-k8gPWVgJI5tM77Dpehcq0NmJoBpMH2T2RUA7kmrX+gPUjviKZNYvDv0agAyUbvb/MWkjSBD89CJ12e5523WWpw==", "dev": true, "license": "MIT", "engines": { @@ -928,14 +892,14 @@ } }, "node_modules/@angular/localize": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-18.2.13.tgz", - "integrity": "sha512-qQaIYdDS/l1w6tr/wpOoimjpmoJU0WmB8AGbNeKLoM36K+ix6hkvn67+UgkpZtaDHZylm8GsGW1NjzpM2tr3pA==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-19.0.6.tgz", + "integrity": "sha512-U3qP/m8/f7hbDG9RlaLHKnuE7jJZm/nvW/wobpN7/eXTfZ9HVyIuBmfA1SEToDcXYh75GorbguzFbqWKFA0b8g==", "license": "MIT", "dependencies": { - "@babel/core": "7.25.2", + "@babel/core": "7.26.0", "@types/babel__core": "7.20.5", - "fast-glob": "3.3.2", + "fast-glob": "3.3.3", "yargs": "^17.2.1" }, "bin": { @@ -947,32 +911,60 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "18.2.13", - "@angular/compiler-cli": "18.2.13" + "@angular/compiler": "19.0.6", + "@angular/compiler-cli": "19.0.6" + } + }, + "node_modules/@angular/localize/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@angular/localize/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/@angular/material": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-18.2.14.tgz", - "integrity": "sha512-28pxzJP49Mymt664WnCtPkKeg7kXUsQKTKGf/Kl95rNTEdTJLbnlcc8wV0rT0yQNR7kXgpfBnG7h0ETLv/iu5Q==", + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-19.0.5.tgz", + "integrity": "sha512-yiW/ZJNkOPlQdqgj5U8DHTu3r7OHMI5R1cAbCpOmHlsVHEoc/Vw4V3RFUgpWLqCGgdRIkayoilMAooT52gG2Dg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/animations": "^18.0.0 || ^19.0.0", - "@angular/cdk": "18.2.14", - "@angular/common": "^18.0.0 || ^19.0.0", - "@angular/core": "^18.0.0 || ^19.0.0", - "@angular/forms": "^18.0.0 || ^19.0.0", - "@angular/platform-browser": "^18.0.0 || ^19.0.0", + "@angular/animations": "^19.0.0 || ^20.0.0", + "@angular/cdk": "19.0.5", + "@angular/common": "^19.0.0 || ^20.0.0", + "@angular/core": "^19.0.0 || ^20.0.0", + "@angular/forms": "^19.0.0 || ^20.0.0", + "@angular/platform-browser": "^19.0.0 || ^20.0.0", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/platform-browser": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.13.tgz", - "integrity": "sha512-tu7ZzY6qD3ATdWFzcTcsAKe7M6cJeWbT/4/bF9unyGO3XBPcNYDKoiz10+7ap2PUd0fmPwvuvTvSNJiFEBnB8Q==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.0.6.tgz", + "integrity": "sha512-MWiToGy7Pa0rR61sgnEuu7dfZXpAw0g7nkSnw4xdjUf974OOOfI1LS9O9YevJibtdW8sPa1HaoXXwcb7N03B5A==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -981,9 +973,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "18.2.13", - "@angular/common": "18.2.13", - "@angular/core": "18.2.13" + "@angular/animations": "19.0.6", + "@angular/common": "19.0.6", + "@angular/core": "19.0.6" }, "peerDependenciesMeta": { "@angular/animations": { @@ -992,9 +984,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.13.tgz", - "integrity": "sha512-kbQCf9+8EpuJC7buBxhSiwBtXvjAwAKh6MznD6zd2pyCYqfY6gfRCZQRtK59IfgVtKmEONWI9grEyNIRoTmqJg==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.0.6.tgz", + "integrity": "sha512-5TGLOwPlLHXJ1+Hs9b3dEmGdTpb7dfLYalVmiMUZOFBry1sMaRuw+nyqjmWn1GP3yD156hzt5QDzWA8A134AfQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1003,16 +995,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.13", - "@angular/compiler": "18.2.13", - "@angular/core": "18.2.13", - "@angular/platform-browser": "18.2.13" + "@angular/common": "19.0.6", + "@angular/compiler": "19.0.6", + "@angular/core": "19.0.6", + "@angular/platform-browser": "19.0.6" } }, "node_modules/@angular/router": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.13.tgz", - "integrity": "sha512-VKmfgi/r/CkyBq9nChQ/ptmfu0JT/8ONnLVJ5H+SkFLRYJcIRyHLKjRihMCyVm6xM5yktOdCaW73NTQrFz7+bg==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-19.0.6.tgz", + "integrity": "sha512-G1oz+TclPk48h6b6B4s5J3DfrDVJrrxKOA+KWeVQP4e1B8ld7/dCMf5nn3yqS4BGs4yLecxMxyvbOvOiZ//lxw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1021,16 +1013,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.13", - "@angular/core": "18.2.13", - "@angular/platform-browser": "18.2.13", + "@angular/common": "19.0.6", + "@angular/core": "19.0.6", + "@angular/platform-browser": "19.0.6", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/service-worker": { - "version": "18.2.13", - "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-18.2.13.tgz", - "integrity": "sha512-fVC943qEqGNUy923NMmSSzfoIqNw2k2UbG/3Y4QEmel/nZFWHA3PhiYr+lE7J3RhRHFMmnNP1bmXDJgy+R+pzA==", + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-19.0.6.tgz", + "integrity": "sha512-5uRkHgyI3LuzTxtAw8nZGoV6owykYQoMHc04WhBUtPdQmjImG6w4B5xAiCPvxGn+ZJ8fpOe/GNpkLeSeOQWumg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1042,8 +1034,32 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.13", - "@angular/core": "18.2.13" + "@angular/common": "19.0.6", + "@angular/core": "19.0.6" + } + }, + "node_modules/@asamuzakjp/css-color": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-2.8.2.tgz", + "integrity": "sha512-RtWv9jFN2/bLExuZgFFZ0I3pWWeezAHGgrmjqGGWclATl1aDe3yhCUaI0Ilkp6OCk9zX7+FjvDasEX8Q9Rxc5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.1", + "@csstools/css-color-parser": "^3.0.7", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^11.0.2" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" } }, "node_modules/@babel/code-frame": { @@ -1070,21 +1086,21 @@ } }, "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -1106,27 +1122,28 @@ "license": "MIT" }, "node_modules/@babel/generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", - "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.0", + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1154,6 +1171,7 @@ "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-member-expression-to-functions": "^7.25.9", @@ -1170,25 +1188,13 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-create-regexp-features-plugin": { "version": "7.26.3", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "regexpu-core": "^6.2.0", @@ -1201,25 +1207,13 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-define-polyfill-provider": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -1237,6 +1231,7 @@ "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" @@ -1281,6 +1276,7 @@ "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/types": "^7.25.9" }, @@ -1303,6 +1299,7 @@ "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-wrap-function": "^7.25.9", @@ -1315,25 +1312,13 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-replace-supers": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz", "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-member-expression-to-functions": "^7.25.9", "@babel/helper-optimise-call-expression": "^7.25.9", @@ -1352,6 +1337,7 @@ "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" @@ -1406,6 +1392,7 @@ "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/template": "^7.25.9", "@babel/traverse": "^7.25.9", @@ -1449,6 +1436,7 @@ "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/traverse": "^7.25.9" @@ -1466,6 +1454,7 @@ "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -1482,6 +1471,7 @@ "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -1498,6 +1488,7 @@ "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", @@ -1516,6 +1507,7 @@ "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/traverse": "^7.25.9" @@ -1533,6 +1525,7 @@ "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6.9.0" }, @@ -1595,38 +1588,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-import-assertions": { "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -1638,13 +1606,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", - "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1826,6 +1794,7 @@ "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -1843,6 +1812,7 @@ "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -1854,16 +1824,16 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz", - "integrity": "sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", + "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-remap-async-to-generator": "^7.25.0", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/traverse": "^7.25.0" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1873,15 +1843,16 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", - "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-remap-async-to-generator": "^7.24.7" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1896,6 +1867,7 @@ "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -1912,6 +1884,7 @@ "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -1928,6 +1901,7 @@ "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" @@ -1945,6 +1919,7 @@ "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" @@ -1962,6 +1937,7 @@ "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-compilation-targets": "^7.25.9", @@ -1977,25 +1953,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/template": "^7.25.9" @@ -2013,6 +1977,7 @@ "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2029,6 +1994,7 @@ "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" @@ -2046,6 +2012,7 @@ "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2062,6 +2029,7 @@ "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" @@ -2079,6 +2047,7 @@ "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2095,6 +2064,7 @@ "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2111,6 +2081,7 @@ "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2127,6 +2098,7 @@ "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" @@ -2144,6 +2116,7 @@ "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-compilation-targets": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", @@ -2162,6 +2135,7 @@ "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2178,6 +2152,7 @@ "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2194,6 +2169,7 @@ "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2210,6 +2186,7 @@ "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2226,6 +2203,7 @@ "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" @@ -2243,6 +2221,7 @@ "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.26.0", "@babel/helper-plugin-utils": "^7.25.9" @@ -2260,6 +2239,7 @@ "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", @@ -2279,6 +2259,7 @@ "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-module-transforms": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" @@ -2296,6 +2277,7 @@ "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" @@ -2313,6 +2295,7 @@ "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2329,6 +2312,7 @@ "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2345,6 +2329,7 @@ "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2361,6 +2346,7 @@ "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-compilation-targets": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", @@ -2379,6 +2365,7 @@ "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-replace-supers": "^7.25.9" @@ -2396,6 +2383,7 @@ "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2412,6 +2400,7 @@ "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" @@ -2429,6 +2418,7 @@ "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2445,6 +2435,7 @@ "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" @@ -2462,6 +2453,7 @@ "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-create-class-features-plugin": "^7.25.9", @@ -2474,25 +2466,13 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-private-property-in-object/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-property-literals": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2509,6 +2489,7 @@ "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "regenerator-transform": "^0.15.2" @@ -2520,12 +2501,31 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2537,16 +2537,17 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz", - "integrity": "sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz", + "integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-corejs3": "^0.10.6", "babel-plugin-polyfill-regenerator": "^0.6.1", "semver": "^6.3.1" }, @@ -2563,6 +2564,7 @@ "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2579,6 +2581,7 @@ "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" @@ -2596,6 +2599,7 @@ "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2612,6 +2616,7 @@ "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2628,6 +2633,7 @@ "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2644,6 +2650,7 @@ "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, @@ -2660,6 +2667,7 @@ "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" @@ -2677,6 +2685,7 @@ "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" @@ -2694,6 +2703,7 @@ "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" @@ -2706,94 +2716,81 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.3.tgz", - "integrity": "sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", + "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-validator-option": "^7.24.8", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", + "@babel/compat-data": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.7", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.0", - "@babel/plugin-transform-async-to-generator": "^7.24.7", - "@babel/plugin-transform-block-scoped-functions": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.25.0", - "@babel/plugin-transform-class-properties": "^7.24.7", - "@babel/plugin-transform-class-static-block": "^7.24.7", - "@babel/plugin-transform-classes": "^7.25.0", - "@babel/plugin-transform-computed-properties": "^7.24.7", - "@babel/plugin-transform-destructuring": "^7.24.8", - "@babel/plugin-transform-dotall-regex": "^7.24.7", - "@babel/plugin-transform-duplicate-keys": "^7.24.7", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", - "@babel/plugin-transform-dynamic-import": "^7.24.7", - "@babel/plugin-transform-exponentiation-operator": "^7.24.7", - "@babel/plugin-transform-export-namespace-from": "^7.24.7", - "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.25.1", - "@babel/plugin-transform-json-strings": "^7.24.7", - "@babel/plugin-transform-literals": "^7.25.2", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", - "@babel/plugin-transform-member-expression-literals": "^7.24.7", - "@babel/plugin-transform-modules-amd": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-modules-systemjs": "^7.25.0", - "@babel/plugin-transform-modules-umd": "^7.24.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", - "@babel/plugin-transform-new-target": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-numeric-separator": "^7.24.7", - "@babel/plugin-transform-object-rest-spread": "^7.24.7", - "@babel/plugin-transform-object-super": "^7.24.7", - "@babel/plugin-transform-optional-catch-binding": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.8", - "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.24.7", - "@babel/plugin-transform-private-property-in-object": "^7.24.7", - "@babel/plugin-transform-property-literals": "^7.24.7", - "@babel/plugin-transform-regenerator": "^7.24.7", - "@babel/plugin-transform-reserved-words": "^7.24.7", - "@babel/plugin-transform-shorthand-properties": "^7.24.7", - "@babel/plugin-transform-spread": "^7.24.7", - "@babel/plugin-transform-sticky-regex": "^7.24.7", - "@babel/plugin-transform-template-literals": "^7.24.7", - "@babel/plugin-transform-typeof-symbol": "^7.24.8", - "@babel/plugin-transform-unicode-escapes": "^7.24.7", - "@babel/plugin-transform-unicode-property-regex": "^7.24.7", - "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.25.9", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.25.9", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.25.9", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.25.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.25.9", + "@babel/plugin-transform-typeof-symbol": "^7.25.9", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-corejs3": "^0.10.6", "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.37.1", + "core-js-compat": "^3.38.1", "semver": "^6.3.1" }, "engines": { @@ -2809,6 +2806,7 @@ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -2819,9 +2817,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", - "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -2878,18 +2876,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/@babel/types": { "version": "7.26.3", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", @@ -2934,6 +2920,121 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@csstools/color-helpers": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.1.tgz", + "integrity": "sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.1.tgz", + "integrity": "sha512-rL7kaUnTkL9K+Cvo2pnCieqNpTKgQzy5f+N+5Iuko9HAoasP+xgprVh7KN/MaJVvVL1l0EzQq2MoqBHKSrDrag==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.7.tgz", + "integrity": "sha512-nkMp2mTICw32uE5NN+EsJ4f5N+IGFeCFu4bGpiKgb2Pq/7J/MpyLBeQ5ry4KKtRFZaYs6sTmcMYrSRIyj5DFKA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.0.1", + "@csstools/css-calc": "^2.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", + "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.3" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", + "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@ctrl/ngx-emoji-mart": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/@ctrl/ngx-emoji-mart/-/ngx-emoji-mart-9.2.0.tgz", @@ -2947,25 +3048,26 @@ } }, "node_modules/@danielmoncada/angular-datetime-picker": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/@danielmoncada/angular-datetime-picker/-/angular-datetime-picker-18.1.0.tgz", - "integrity": "sha512-hNp0DBFlCMIKa6yvZKocmm2ZCVzevX60z/ZIhRlNVaKwU+Wwh9B/KfvqwT03uvmZWSFQSnNUoPGBTyx0fyTayw==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@danielmoncada/angular-datetime-picker/-/angular-datetime-picker-19.0.0.tgz", + "integrity": "sha512-et7y0E7Yn24ey757Txyoq0xokPOzhtqqj23fDvdBmR9oLh4w9A9dQoFA1aizpPw+7kc0dwbid+gGNZxdbrxfng==", "license": "MIT", "dependencies": { "tslib": "^2.6.2" }, "peerDependencies": { - "@angular/cdk": "^18.0.0", - "@angular/common": "^18.0.0", - "@angular/core": "^18.0.0" + "@angular/cdk": "^19.0.0", + "@angular/common": "^19.0.0", + "@angular/core": "^19.0.0" } }, "node_modules/@discoveryjs/json-ext": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.1.tgz", - "integrity": "sha512-boghen8F0Q8D+0/Q1/1r6DUEieUJ8w2a1gIknExMSHBsJFOr2+0KUfHiVYBvucPwl3+RU5PFBK833FjFCh3BhA==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", + "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=14.17.0" } @@ -3029,9 +3131,9 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", - "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", + "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", "cpu": [ "ppc64" ], @@ -3046,9 +3148,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", - "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", + "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", "cpu": [ "arm" ], @@ -3063,9 +3165,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", - "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", + "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", "cpu": [ "arm64" ], @@ -3080,9 +3182,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", - "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", + "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", "cpu": [ "x64" ], @@ -3097,9 +3199,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", + "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", "cpu": [ "arm64" ], @@ -3114,9 +3216,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", - "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", + "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", "cpu": [ "x64" ], @@ -3131,9 +3233,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", - "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", + "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", "cpu": [ "arm64" ], @@ -3148,9 +3250,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", - "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", + "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", "cpu": [ "x64" ], @@ -3165,9 +3267,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", - "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", + "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", "cpu": [ "arm" ], @@ -3182,9 +3284,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", - "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", + "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", "cpu": [ "arm64" ], @@ -3199,9 +3301,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", - "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", + "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", "cpu": [ "ia32" ], @@ -3216,9 +3318,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", - "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", + "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", "cpu": [ "loong64" ], @@ -3233,9 +3335,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", - "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", + "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", "cpu": [ "mips64el" ], @@ -3250,9 +3352,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", - "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", + "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", "cpu": [ "ppc64" ], @@ -3267,9 +3369,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", - "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", + "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", "cpu": [ "riscv64" ], @@ -3284,9 +3386,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", - "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", + "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", "cpu": [ "s390x" ], @@ -3301,9 +3403,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", - "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", + "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", "cpu": [ "x64" ], @@ -3318,9 +3420,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", - "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", + "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", "cpu": [ "x64" ], @@ -3335,9 +3437,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", - "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", + "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", "cpu": [ "arm64" ], @@ -3352,9 +3454,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", - "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", + "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", "cpu": [ "x64" ], @@ -3369,9 +3471,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", - "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", + "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", "cpu": [ "x64" ], @@ -3386,9 +3488,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", - "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", + "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", "cpu": [ "arm64" ], @@ -3403,9 +3505,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", - "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", + "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", "cpu": [ "ia32" ], @@ -3420,9 +3522,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", - "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", + "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", "cpu": [ "x64" ], @@ -3655,16 +3757,16 @@ } }, "node_modules/@fortawesome/angular-fontawesome": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-0.15.0.tgz", - "integrity": "sha512-oxmJDYGNSym5ycFR0LX4ZOPAU+wWmMAznYpkm5DNAtWWkhMLcrZl15eZQmVIEE+qruQ7JiVrg3tpo8bEkFlDgw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-1.0.0.tgz", + "integrity": "sha512-EC2fYuXIuw2ld1kzJi+zysWus6OeGGfLQtbh0hW9zyyq5aBo8ZJkcJKBsVQ8E6Mg7nHyTWaXn+sdcXTPDWz+UQ==", "license": "MIT", "dependencies": { - "@fortawesome/fontawesome-svg-core": "^6.5.2", - "tslib": "^2.6.2" + "@fortawesome/fontawesome-svg-core": "^6.7.1", + "tslib": "^2.8.1" }, "peerDependencies": { - "@angular/core": "^18.0.0" + "@angular/core": "^19.0.0" } }, "node_modules/@fortawesome/fontawesome-common-types": { @@ -3788,51 +3890,54 @@ } }, "node_modules/@inquirer/checkbox": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.5.0.tgz", - "integrity": "sha512-sMgdETOfi2dUHT8r7TT1BTKOwNvdDGFDXYWtQ2J69SvlYNntk9I/gJe7r5yvMwwsuKnYbuRs3pNhx4tgNck5aA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.0.4.tgz", + "integrity": "sha512-fYAKCAcGNMdfjL6hZTRUwkIByQ8EIZCXKrIQZH7XjADnN/xvRUhj8UdBbpC4zoUzvChhkSC/zRKaP/tDs3dZpg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/figures": "^1.0.5", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.2", + "@inquirer/figures": "^1.0.9", + "@inquirer/type": "^3.0.2", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/confirm": { - "version": "3.1.22", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.22.tgz", - "integrity": "sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.0.2.tgz", + "integrity": "sha512-KJLUHOaKnNCYzwVbryj3TNBxyZIrr56fR5N45v6K9IPrbT6B7DcudBMfylkV1A8PUdJE15mybkEQyp2/ZUpxUA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.0.10", - "@inquirer/type": "^1.5.2" + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/core": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.2.1.tgz", - "integrity": "sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.2.tgz", + "integrity": "sha512-bHd96F3ezHg1mf/J0Rb4CV8ndCN0v28kUlrHqP7+ECm1C/A+paB7Xh2lbMk6x+kweQC+rZOxM/YeKikzxco8bQ==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.6", - "@inquirer/type": "^2.0.0", - "@types/mute-stream": "^0.0.4", - "@types/node": "^22.5.5", - "@types/wrap-ansi": "^3.0.0", + "@inquirer/figures": "^1.0.9", + "@inquirer/type": "^3.0.2", "ansi-escapes": "^4.3.2", "cli-width": "^4.1.0", - "mute-stream": "^1.0.0", + "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^6.2.0", @@ -3842,47 +3947,40 @@ "node": ">=18" } }, - "node_modules/@inquirer/core/node_modules/@inquirer/type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-2.0.0.tgz", - "integrity": "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==", - "dev": true, - "license": "MIT", - "dependencies": { - "mute-stream": "^1.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@inquirer/editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.2.0.tgz", - "integrity": "sha512-9KHOpJ+dIL5SZli8lJ6xdaYLPPzB8xB9GZItg39MBybzhxA16vxmszmQFrRwbOA918WA2rvu8xhDEg/p6LXKbw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.1.tgz", + "integrity": "sha512-xn9aDaiP6nFa432i68JCaL302FyL6y/6EG97nAtfIPnWZ+mWPgCMLGc4XZ2QQMsZtu9q3Jd5AzBPjXh10aX9kA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.2", + "@inquirer/type": "^3.0.2", "external-editor": "^3.1.0" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/expand": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.3.0.tgz", - "integrity": "sha512-qnJsUcOGCSG1e5DTOErmv2BPQqrtT6uzqn1vI/aYGiPKq+FgslGZmtdnXbhuI7IlT7OByDoEEqdnhUnVR2hhLw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.4.tgz", + "integrity": "sha512-GYocr+BPyxKPxQ4UZyNMqZFSGKScSUc0Vk17II3J+0bDcgGsQm0KYQNooN1Q5iBfXsy3x/VWmHGh20QnzsaHwg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.2", + "@inquirer/type": "^3.0.2", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/figures": { @@ -3896,130 +3994,151 @@ } }, "node_modules/@inquirer/input": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.3.0.tgz", - "integrity": "sha512-XfnpCStx2xgh1LIRqPXrTNEEByqQWoxsWYzNRSEUxJ5c6EQlhMogJ3vHKu8aXuTacebtaZzMAHwEL0kAflKOBw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.1.tgz", + "integrity": "sha512-nAXAHQndZcXB+7CyjIW3XuQZZHbQQ0q8LX6miY6bqAWwDzNa9JUioDBYrFmOUNIsuF08o1WT/m2gbBXvBhYVxg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3" + "@inquirer/core": "^10.1.2", + "@inquirer/type": "^3.0.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/number": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-1.1.0.tgz", - "integrity": "sha512-ilUnia/GZUtfSZy3YEErXLJ2Sljo/mf9fiKc08n18DdwdmDbOzRcTv65H1jjDvlsAuvdFXf4Sa/aL7iw/NanVA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.4.tgz", + "integrity": "sha512-DX7a6IXRPU0j8kr2ovf+QaaDiIf+zEKaZVzCWdLOTk7XigqSXvoh4cul7x68xp54WTQrgSnW7P1WBJDbyY3GhA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3" + "@inquirer/core": "^10.1.2", + "@inquirer/type": "^3.0.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/password": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.2.0.tgz", - "integrity": "sha512-5otqIpgsPYIshqhgtEwSspBQE40etouR8VIxzpJkv9i0dVHIpyhiivbkH9/dGiMLdyamT54YRdGJLfl8TFnLHg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.4.tgz", + "integrity": "sha512-wiliQOWdjM8FnBmdIHtQV2Ca3S1+tMBUerhyjkRCv1g+4jSvEweGu9GCcvVEgKDhTBT15nrxvk5/bVrGUqSs1w==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.2", + "@inquirer/type": "^3.0.2", "ansi-escapes": "^4.3.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/prompts": { - "version": "5.3.8", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-5.3.8.tgz", - "integrity": "sha512-b2BudQY/Si4Y2a0PdZZL6BeJtl8llgeZa7U2j47aaJSCeAl1e4UI7y8a9bSkO3o/ZbZrgT5muy/34JbsjfIWxA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.1.0.tgz", + "integrity": "sha512-5U/XiVRH2pp1X6gpNAjWOglMf38/Ys522ncEHIKT1voRUvSj/DQnR22OVxHnwu5S+rCFaUiPQ57JOtMFQayqYA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/checkbox": "^2.4.7", - "@inquirer/confirm": "^3.1.22", - "@inquirer/editor": "^2.1.22", - "@inquirer/expand": "^2.1.22", - "@inquirer/input": "^2.2.9", - "@inquirer/number": "^1.0.10", - "@inquirer/password": "^2.1.22", - "@inquirer/rawlist": "^2.2.4", - "@inquirer/search": "^1.0.7", - "@inquirer/select": "^2.4.7" + "@inquirer/checkbox": "^4.0.2", + "@inquirer/confirm": "^5.0.2", + "@inquirer/editor": "^4.1.0", + "@inquirer/expand": "^4.0.2", + "@inquirer/input": "^4.0.2", + "@inquirer/number": "^3.0.2", + "@inquirer/password": "^4.0.2", + "@inquirer/rawlist": "^4.0.2", + "@inquirer/search": "^3.0.2", + "@inquirer/select": "^4.0.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/rawlist": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.3.0.tgz", - "integrity": "sha512-zzfNuINhFF7OLAtGHfhwOW2TlYJyli7lOUoJUXw/uyklcwalV6WRXBXtFIicN8rTRK1XTiPWB4UY+YuW8dsnLQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.0.4.tgz", + "integrity": "sha512-IsVN2EZdNHsmFdKWx9HaXb8T/s3FlR/U1QPt9dwbSyPtjFbMTlW9CRFvnn0bm/QIsrMRD2oMZqrQpSWPQVbXXg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.2", + "@inquirer/type": "^3.0.2", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/search": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-1.1.0.tgz", - "integrity": "sha512-h+/5LSj51dx7hp5xOn4QFnUaKeARwUCLs6mIhtkJ0JYPBLmEYjdHSYh7I6GrLg9LwpJ3xeX0FZgAG1q0QdCpVQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.4.tgz", + "integrity": "sha512-tSkJk2SDmC2MEdTIjknXWmCnmPr5owTs9/xjfa14ol1Oh95n6xW7SYn5fiPk4/vrJPys0ggSWiISdPze4LTa7A==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/figures": "^1.0.5", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.2", + "@inquirer/figures": "^1.0.9", + "@inquirer/type": "^3.0.2", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/select": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.5.0.tgz", - "integrity": "sha512-YmDobTItPP3WcEI86GvPo+T2sRHkxxOq/kXmsBjHS5BVXUgvgZ5AfJjkvQvZr03T81NnI3KrrRuMzeuYUQRFOA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.0.4.tgz", + "integrity": "sha512-ZzYLuLoUzTIW9EJm++jBpRiTshGqS3Q1o5qOEQqgzaBlmdsjQr6pA4TUNkwu6OBYgM2mIRbCz6mUhFDfl/GF+w==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/figures": "^1.0.5", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.2", + "@inquirer/figures": "^1.0.9", + "@inquirer/type": "^3.0.2", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/type": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.5.tgz", - "integrity": "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.2.tgz", + "integrity": "sha512-ZhQ4TvhwHZF+lGhQ2O/rsjo80XoZR5/5qhOY3t6FJuX5XBg5Be8YzYTvaUGJnc12AUGI2nr4QSUE4PhKSigx7g==", "dev": true, "license": "MIT", - "dependencies": { - "mute-stream": "^1.0.0" - }, "engines": { "node": ">=18" - } + }, + "peerDependencies": { + "@types/node": ">=18" + } }, "node_modules/@interactjs/types": { "version": "1.10.27", @@ -4130,6 +4249,19 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -4676,6 +4808,7 @@ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -4703,6 +4836,7 @@ "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", "dev": true, "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=10.0" }, @@ -4720,6 +4854,7 @@ "integrity": "sha512-osjeBqMJ2lb/j/M8NCPjs1ylqWIcTRTycIhVB5pt6LgzgeRSb0YRZ7j9RfA8wIUrsr/medIuhVyonXRZWLyfdw==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@jsonjoy.com/base64": "^1.1.1", "@jsonjoy.com/util": "^1.1.2", @@ -4743,6 +4878,7 @@ "integrity": "sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==", "dev": true, "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=10.0" }, @@ -4759,28 +4895,52 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@listr2/prompt-adapter-inquirer": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-2.0.15.tgz", - "integrity": "sha512-MZrGem/Ujjd4cPTLYDfCZK2iKKeiO/8OX13S6jqxldLs0Prf2aGqVlJ77nMBqMv7fzqgXEgjrNHLXcKR8l9lOg==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-2.0.18.tgz", + "integrity": "sha512-0hz44rAcrphyXcA8IS7EJ2SCoaBZD2u5goE8S/e+q/DL+dOGpqpcLidVOFeLG3VgML62SXmfRLAhWt0zL1oW4Q==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/type": "^1.5.1" + "@inquirer/type": "^1.5.5" }, "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@inquirer/prompts": ">= 3 < 6" + "@inquirer/prompts": ">= 3 < 8" + } + }, + "node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.5.tgz", + "integrity": "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mute-stream": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@listr2/prompt-adapter-inquirer/node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.0.13.tgz", - "integrity": "sha512-uiKPB0Fv6WEEOZjruu9a6wnW/8jrjzlZbxXscMB8kuCJ1k6kHpcBnuvaAWcqhbI7rqX5GKziwWEdD+wi2gNLfA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.1.5.tgz", + "integrity": "sha512-ue5PSOzHMCIYrfvPP/MRS6hsKKLzqqhcdAvJCO8uFlDdj598EhgnacuOTuqA6uBK5rgiZXfDWyb7DVZSiBKxBA==", "cpu": [ "arm64" ], @@ -4792,9 +4952,9 @@ ] }, "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.0.13.tgz", - "integrity": "sha512-bEVIIfK5mSQoG1R19qA+fJOvCB+0wVGGnXHT3smchBVahYBdlPn2OsZZKzlHWfb1E+PhLBmYfqB5zQXFP7hJig==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.1.5.tgz", + "integrity": "sha512-CGhsb0R5vE6mMNCoSfxHFD8QTvBHM51gs4DBeigTYHWnYv2V5YpJkC4rMo5qAAFifuUcc0+a8a3SIU0c9NrfNw==", "cpu": [ "x64" ], @@ -4806,9 +4966,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.0.13.tgz", - "integrity": "sha512-Yml1KlMzOnXj/tnW7yX8U78iAzTk39aILYvCPbqeewAq1kSzl+w59k/fiVkTBfvDi/oW/5YRxL+Fq+Y1Fr1r2Q==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.1.5.tgz", + "integrity": "sha512-3WeW328DN+xB5PZdhSWmqE+t3+44xWXEbqQ+caWJEZfOFdLp9yklBZEbVqVdqzznkoaXJYxTCp996KD6HmANeg==", "cpu": [ "arm" ], @@ -4820,9 +4980,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.0.13.tgz", - "integrity": "sha512-afbVrsMgZ9dUTNUchFpj5VkmJRxvht/u335jUJ7o23YTbNbnpmXif3VKQGCtnjSh+CZaqm6N3CPG8KO3zwyZ1Q==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.1.5.tgz", + "integrity": "sha512-LAjaoOcBHGj6fiYB8ureiqPoph4eygbXu4vcOF+hsxiY74n8ilA7rJMmGUT0K0JOB5lmRQHSmor3mytRjS4qeQ==", "cpu": [ "arm64" ], @@ -4834,9 +4994,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-x64": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.0.13.tgz", - "integrity": "sha512-vOtxu0xC0SLdQ2WRXg8Qgd8T32ak4SPqk5zjItRszrJk2BdeXqfGxBJbP7o4aOvSPSmSSv46Lr1EP4HXU8v7Kg==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.1.5.tgz", + "integrity": "sha512-k/IklElP70qdCXOQixclSl2GPLFiopynGoKX1FqDd1/H0E3Fo1oPwjY2rEVu+0nS3AOw1sryStdXk8CW3cVIsw==", "cpu": [ "x64" ], @@ -4848,9 +5008,9 @@ ] }, "node_modules/@lmdb/lmdb-win32-x64": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.0.13.tgz", - "integrity": "sha512-UCrMJQY/gJnOl3XgbWRZZUvGGBuKy6i0YNSptgMzHBjs+QYDYR1Mt/RLTOPy4fzzves65O1EDmlL//OzEqoLlA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.1.5.tgz", + "integrity": "sha512-KYar6W8nraZfSJspcK7Kp7hdj238X/FNauYbZyrqPBrtsXI1hvI4/KcRcRGP50aQoV7fkKDyJERlrQGMGTZUsA==", "cpu": [ "x64" ], @@ -4931,33 +5091,324 @@ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", "cpu": [ - "x64" + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@napi-rs/canvas": { + "version": "0.1.65", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.65.tgz", + "integrity": "sha512-YcFhXQcp+b2d38zFOJNbpyPHnIL7KAEkhJQ+UeeKI5IpE9B8Cpf/M6RiHPQXSsSqnYbrfFylnW49dyh2oeSblQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@napi-rs/canvas-android-arm64": "0.1.65", + "@napi-rs/canvas-darwin-arm64": "0.1.65", + "@napi-rs/canvas-darwin-x64": "0.1.65", + "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.65", + "@napi-rs/canvas-linux-arm64-gnu": "0.1.65", + "@napi-rs/canvas-linux-arm64-musl": "0.1.65", + "@napi-rs/canvas-linux-riscv64-gnu": "0.1.65", + "@napi-rs/canvas-linux-x64-gnu": "0.1.65", + "@napi-rs/canvas-linux-x64-musl": "0.1.65", + "@napi-rs/canvas-win32-x64-msvc": "0.1.65" + } + }, + "node_modules/@napi-rs/canvas-android-arm64": { + "version": "0.1.65", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.65.tgz", + "integrity": "sha512-ZYwqFYEKcT5Zr8lbiaJNJj/poLaeK2TncolY914r+gD2TJNeP7ZqvE7A2SX/1C9MB4E3DQEwm3YhL3WEf0x3MQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-darwin-arm64": { + "version": "0.1.65", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.65.tgz", + "integrity": "sha512-Pg1pfiJEyDIsX+V0QaJPRWvXbw5zmWAk3bivFCvt/5pwZb37/sT6E/RqPHT9NnqpDyKW6SriwY9ypjljysUA1Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-darwin-x64": { + "version": "0.1.65", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.65.tgz", + "integrity": "sha512-3Tr+/HjdJN7Z/VKIcsxV2DvDIibZCExgfYTgljCkUSFuoI7iNkOE6Dc1Q6j212EB9PeO8KmfrViBqHYT6IwWkA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { + "version": "0.1.65", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.65.tgz", + "integrity": "sha512-3KP+dYObH7CVkZMZWwk1WX9jRjL+EKdQtD43H8MOI+illf+dwqLlecdQ4d9bQRIxELKJ8dyPWY4fOp/Ngufrdg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-gnu": { + "version": "0.1.65", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.65.tgz", + "integrity": "sha512-Ka3StKz7Dq7kjTF3nNJCq43UN/VlANS7qGE3dWkn1d+tQNsCRy/wRmyt1TUFzIjRqcTFMQNRbgYq84+53UBA0A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-musl": { + "version": "0.1.65", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.65.tgz", + "integrity": "sha512-O4xMASm2JrmqYoiDyxVWi+z5C14H+oVEag2rZ5iIA67dhWqYZB+iO7wCFpBYRj31JPBR29FOsu6X9zL+DwBFdw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { + "version": "0.1.65", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.65.tgz", + "integrity": "sha512-dblWDaA59ZU8bPbkfM+riSke7sFbNZ70LEevUdI5rgiFEUzYUQlU34gSBzemTACj5rCWt1BYeu0GfkLSjNMBSw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-gnu": { + "version": "0.1.65", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.65.tgz", + "integrity": "sha512-wsp+atutw13OJXGU3DDkdngtBDoEg01IuK5xMe0L6VFPV8maGkh17CXze078OD5QJOc6kFyw3DDscMLOPF8+oA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-musl": { + "version": "0.1.65", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.65.tgz", + "integrity": "sha512-odX+nN+IozWzhdj31INcHz3Iy9+EckNw+VqsZcaUxZOTu7/3FmktRNI6aC1qe5minZNv1m05YOS1FVf7fvmjlA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/canvas-win32-x64-msvc": { + "version": "0.1.65", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.65.tgz", + "integrity": "sha512-RZQX3luWnlNWgdMnLMQ1hyfQraeAn9lnxWWVCHuUM4tAWEV8UDdeb7cMwmJW7eyt8kAosmjeHt3cylQMHOxGFg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.0.1.tgz", + "integrity": "sha512-zM0mVWSXE0a0h9aKACLwKmD6nHcRiKrPpCfvaKqG1CqDEyjEawId0ocXxVzPMCAm6kkWr2P025msfxXEnt8UGQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/nice-android-arm-eabi": "1.0.1", + "@napi-rs/nice-android-arm64": "1.0.1", + "@napi-rs/nice-darwin-arm64": "1.0.1", + "@napi-rs/nice-darwin-x64": "1.0.1", + "@napi-rs/nice-freebsd-x64": "1.0.1", + "@napi-rs/nice-linux-arm-gnueabihf": "1.0.1", + "@napi-rs/nice-linux-arm64-gnu": "1.0.1", + "@napi-rs/nice-linux-arm64-musl": "1.0.1", + "@napi-rs/nice-linux-ppc64-gnu": "1.0.1", + "@napi-rs/nice-linux-riscv64-gnu": "1.0.1", + "@napi-rs/nice-linux-s390x-gnu": "1.0.1", + "@napi-rs/nice-linux-x64-gnu": "1.0.1", + "@napi-rs/nice-linux-x64-musl": "1.0.1", + "@napi-rs/nice-win32-arm64-msvc": "1.0.1", + "@napi-rs/nice-win32-ia32-msvc": "1.0.1", + "@napi-rs/nice-win32-x64-msvc": "1.0.1" + } + }, + "node_modules/@napi-rs/nice-android-arm-eabi": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.0.1.tgz", + "integrity": "sha512-5qpvOu5IGwDo7MEKVqqyAxF90I6aLj4n07OzpARdgDRfz8UbBztTByBp0RC59r3J1Ij8uzYi6jI7r5Lws7nn6w==", + "cpu": [ + "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "darwin" - ] + "android" + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", - "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "node_modules/@napi-rs/nice-android-arm64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.0.1.tgz", + "integrity": "sha512-GqvXL0P8fZ+mQqG1g0o4AO9hJjQaeYG84FRfZaYjyJtZZZcMjXW5TwkL8Y8UApheJgyE13TQ4YNUssQaTgTyvA==", "cpu": [ - "arm" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "android" + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", - "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "node_modules/@napi-rs/nice-darwin-arm64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.0.1.tgz", + "integrity": "sha512-91k3HEqUl2fsrz/sKkuEkscj6EAj3/eZNCLqzD2AA0TtVbkQi8nqxZCZDMkfklULmxLkMxuUdKe7RvG/T6s2AA==", "cpu": [ "arm64" ], @@ -4965,13 +5416,16 @@ "license": "MIT", "optional": true, "os": [ - "linux" - ] + "darwin" + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", - "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "node_modules/@napi-rs/nice-darwin-x64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.0.1.tgz", + "integrity": "sha512-jXnMleYSIR/+TAN/p5u+NkCA7yidgswx5ftqzXdD5wgy/hNR92oerTXHc0jrlBisbd7DpzoaGY4cFD7Sm5GlgQ==", "cpu": [ "x64" ], @@ -4979,13 +5433,16 @@ "license": "MIT", "optional": true, "os": [ - "linux" - ] + "darwin" + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", - "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "node_modules/@napi-rs/nice-freebsd-x64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.0.1.tgz", + "integrity": "sha512-j+iJ/ezONXRQsVIB/FJfwjeQXX7A2tf3gEXs4WUGFrJjpe/z2KB7sOv6zpkm08PofF36C9S7wTNuzHZ/Iiccfw==", "cpu": [ "x64" ], @@ -4993,86 +5450,88 @@ "license": "MIT", "optional": true, "os": [ - "win32" - ] + "freebsd" + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/@napi-rs/canvas": { - "version": "0.1.65", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.65.tgz", - "integrity": "sha512-YcFhXQcp+b2d38zFOJNbpyPHnIL7KAEkhJQ+UeeKI5IpE9B8Cpf/M6RiHPQXSsSqnYbrfFylnW49dyh2oeSblQ==", + "node_modules/@napi-rs/nice-linux-arm-gnueabihf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.0.1.tgz", + "integrity": "sha512-G8RgJ8FYXYkkSGQwywAUh84m946UTn6l03/vmEXBYNJxQJcD+I3B3k5jmjFG/OPiU8DfvxutOP8bi+F89MCV7Q==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", "optional": true, + "os": [ + "linux" + ], "engines": { "node": ">= 10" - }, - "optionalDependencies": { - "@napi-rs/canvas-android-arm64": "0.1.65", - "@napi-rs/canvas-darwin-arm64": "0.1.65", - "@napi-rs/canvas-darwin-x64": "0.1.65", - "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.65", - "@napi-rs/canvas-linux-arm64-gnu": "0.1.65", - "@napi-rs/canvas-linux-arm64-musl": "0.1.65", - "@napi-rs/canvas-linux-riscv64-gnu": "0.1.65", - "@napi-rs/canvas-linux-x64-gnu": "0.1.65", - "@napi-rs/canvas-linux-x64-musl": "0.1.65", - "@napi-rs/canvas-win32-x64-msvc": "0.1.65" } }, - "node_modules/@napi-rs/canvas-android-arm64": { - "version": "0.1.65", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.65.tgz", - "integrity": "sha512-ZYwqFYEKcT5Zr8lbiaJNJj/poLaeK2TncolY914r+gD2TJNeP7ZqvE7A2SX/1C9MB4E3DQEwm3YhL3WEf0x3MQ==", + "node_modules/@napi-rs/nice-linux-arm64-gnu": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.0.1.tgz", + "integrity": "sha512-IMDak59/W5JSab1oZvmNbrms3mHqcreaCeClUjwlwDr0m3BoR09ZiN8cKFBzuSlXgRdZ4PNqCYNeGQv7YMTjuA==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "android" + "linux" ], "engines": { "node": ">= 10" } }, - "node_modules/@napi-rs/canvas-darwin-arm64": { - "version": "0.1.65", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.65.tgz", - "integrity": "sha512-Pg1pfiJEyDIsX+V0QaJPRWvXbw5zmWAk3bivFCvt/5pwZb37/sT6E/RqPHT9NnqpDyKW6SriwY9ypjljysUA1Q==", + "node_modules/@napi-rs/nice-linux-arm64-musl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.0.1.tgz", + "integrity": "sha512-wG8fa2VKuWM4CfjOjjRX9YLIbysSVV1S3Kgm2Fnc67ap/soHBeYZa6AGMeR5BJAylYRjnoVOzV19Cmkco3QEPw==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { "node": ">= 10" } }, - "node_modules/@napi-rs/canvas-darwin-x64": { - "version": "0.1.65", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.65.tgz", - "integrity": "sha512-3Tr+/HjdJN7Z/VKIcsxV2DvDIibZCExgfYTgljCkUSFuoI7iNkOE6Dc1Q6j212EB9PeO8KmfrViBqHYT6IwWkA==", + "node_modules/@napi-rs/nice-linux-ppc64-gnu": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.0.1.tgz", + "integrity": "sha512-lxQ9WrBf0IlNTCA9oS2jg/iAjQyTI6JHzABV664LLrLA/SIdD+I1i3Mjf7TsnoUbgopBcCuDztVLfJ0q9ubf6Q==", "cpu": [ - "x64" + "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "darwin" + "linux" ], "engines": { "node": ">= 10" } }, - "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { - "version": "0.1.65", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.65.tgz", - "integrity": "sha512-3KP+dYObH7CVkZMZWwk1WX9jRjL+EKdQtD43H8MOI+illf+dwqLlecdQ4d9bQRIxELKJ8dyPWY4fOp/Ngufrdg==", + "node_modules/@napi-rs/nice-linux-riscv64-gnu": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.0.1.tgz", + "integrity": "sha512-3xs69dO8WSWBb13KBVex+yvxmUeEsdWexxibqskzoKaWx9AIqkMbWmE2npkazJoopPKX2ULKd8Fm9veEn0g4Ig==", "cpu": [ - "arm" + "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5082,13 +5541,14 @@ "node": ">= 10" } }, - "node_modules/@napi-rs/canvas-linux-arm64-gnu": { - "version": "0.1.65", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.65.tgz", - "integrity": "sha512-Ka3StKz7Dq7kjTF3nNJCq43UN/VlANS7qGE3dWkn1d+tQNsCRy/wRmyt1TUFzIjRqcTFMQNRbgYq84+53UBA0A==", + "node_modules/@napi-rs/nice-linux-s390x-gnu": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.0.1.tgz", + "integrity": "sha512-lMFI3i9rlW7hgToyAzTaEybQYGbQHDrpRkg+1gJWEpH0PLAQoZ8jiY0IzakLfNWnVda1eTYYlxxFYzW8Rqczkg==", "cpu": [ - "arm64" + "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5098,13 +5558,14 @@ "node": ">= 10" } }, - "node_modules/@napi-rs/canvas-linux-arm64-musl": { - "version": "0.1.65", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.65.tgz", - "integrity": "sha512-O4xMASm2JrmqYoiDyxVWi+z5C14H+oVEag2rZ5iIA67dhWqYZB+iO7wCFpBYRj31JPBR29FOsu6X9zL+DwBFdw==", + "node_modules/@napi-rs/nice-linux-x64-gnu": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.0.1.tgz", + "integrity": "sha512-XQAJs7DRN2GpLN6Fb+ZdGFeYZDdGl2Fn3TmFlqEL5JorgWKrQGRUrpGKbgZ25UeZPILuTKJ+OowG2avN8mThBA==", "cpu": [ - "arm64" + "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5114,13 +5575,14 @@ "node": ">= 10" } }, - "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { - "version": "0.1.65", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.65.tgz", - "integrity": "sha512-dblWDaA59ZU8bPbkfM+riSke7sFbNZ70LEevUdI5rgiFEUzYUQlU34gSBzemTACj5rCWt1BYeu0GfkLSjNMBSw==", + "node_modules/@napi-rs/nice-linux-x64-musl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.0.1.tgz", + "integrity": "sha512-/rodHpRSgiI9o1faq9SZOp/o2QkKQg7T+DK0R5AkbnI/YxvAIEHf2cngjYzLMQSQgUhxym+LFr+UGZx4vK4QdQ==", "cpu": [ - "riscv64" + "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5130,45 +5592,48 @@ "node": ">= 10" } }, - "node_modules/@napi-rs/canvas-linux-x64-gnu": { - "version": "0.1.65", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.65.tgz", - "integrity": "sha512-wsp+atutw13OJXGU3DDkdngtBDoEg01IuK5xMe0L6VFPV8maGkh17CXze078OD5QJOc6kFyw3DDscMLOPF8+oA==", + "node_modules/@napi-rs/nice-win32-arm64-msvc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.0.1.tgz", + "integrity": "sha512-rEcz9vZymaCB3OqEXoHnp9YViLct8ugF+6uO5McifTedjq4QMQs3DHz35xBEGhH3gJWEsXMUbzazkz5KNM5YUg==", "cpu": [ - "x64" + "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" + "win32" ], "engines": { "node": ">= 10" } }, - "node_modules/@napi-rs/canvas-linux-x64-musl": { - "version": "0.1.65", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.65.tgz", - "integrity": "sha512-odX+nN+IozWzhdj31INcHz3Iy9+EckNw+VqsZcaUxZOTu7/3FmktRNI6aC1qe5minZNv1m05YOS1FVf7fvmjlA==", + "node_modules/@napi-rs/nice-win32-ia32-msvc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.0.1.tgz", + "integrity": "sha512-t7eBAyPUrWL8su3gDxw9xxxqNwZzAqKo0Szv3IjVQd1GpXXVkb6vBBQUuxfIYaXMzZLwlxRQ7uzM2vdUE9ULGw==", "cpu": [ - "x64" + "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" + "win32" ], "engines": { "node": ">= 10" } }, - "node_modules/@napi-rs/canvas-win32-x64-msvc": { - "version": "0.1.65", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.65.tgz", - "integrity": "sha512-RZQX3luWnlNWgdMnLMQ1hyfQraeAn9lnxWWVCHuUM4tAWEV8UDdeb7cMwmJW7eyt8kAosmjeHt3cylQMHOxGFg==", + "node_modules/@napi-rs/nice-win32-x64-msvc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.0.1.tgz", + "integrity": "sha512-JlF+uDcatt3St2ntBG8H02F1mM45i5SF9W+bIKiReVE6wiy3o16oBP/yxt+RZ+N6LbCImJXJ6bXNO2kn9AXicg==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5191,36 +5656,37 @@ } }, "node_modules/@ng-bootstrap/ng-bootstrap": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-17.0.1.tgz", - "integrity": "sha512-utbm8OXIoqVVYGVzQkOS773ymbjc+UMkXv8lyi7hTqLhCQs0rZ0yA74peqVZRuOGXLHgcSTA7fnJhA80iQOblw==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-18.0.0.tgz", + "integrity": "sha512-GeSAz4yiGq49psdte8kcf+Y562wB3jK/qKRAkh6iA32lcXmy2sfQXVAmlHdjZ3AyP+E8lf3yMwuPdSKiYcDgSg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": "^18.0.0", - "@angular/core": "^18.0.0", - "@angular/forms": "^18.0.0", - "@angular/localize": "^18.0.0", + "@angular/common": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/forms": "^19.0.0", + "@angular/localize": "^19.0.0", "@popperjs/core": "^2.11.8", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@ngtools/webpack": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.12.tgz", - "integrity": "sha512-FFJAwtWbtpncMOVNuULPBwFJB7GSjiUwO93eGTzRp8O4EPQ8lCQeFbezQm/NP34+T0+GBLGzPSuQT+muob8YKw==", + "version": "19.0.7", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-19.0.7.tgz", + "integrity": "sha512-jWyMuqtLKZB8Jnuqo27mG2cCQdl71lhM1oEdq3x7Z/QOrm2I+8EfyAzOLxB1f1vXt85O1bz3nf66CkuVCVGGTQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": "^18.19.1 || ^20.11.1 || >=22.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, "peerDependencies": { - "@angular/compiler-cli": "^18.0.0", - "typescript": ">=5.4 <5.6", + "@angular/compiler-cli": "^19.0.0", + "typescript": ">=5.5 <5.7", "webpack": "^5.54.0" } }, @@ -5286,9 +5752,9 @@ } }, "node_modules/@npmcli/agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz", - "integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", + "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==", "dev": true, "license": "ISC", "dependencies": { @@ -5299,7 +5765,7 @@ "socks-proxy-agent": "^8.0.3" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/agent/node_modules/lru-cache": { @@ -5310,37 +5776,37 @@ "license": "ISC" }, "node_modules/@npmcli/fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", - "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, "license": "ISC", "dependencies": { "semver": "^7.3.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/git": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.8.tgz", - "integrity": "sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-6.0.1.tgz", + "integrity": "sha512-BBWMMxeQzalmKadyimwb2/VVQyJB01PH0HhVSNLHNBDZN/M/h/02P6f8fxedIiFhpMj11SO9Ep5tKTBE7zL2nw==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/promise-spawn": "^7.0.0", - "ini": "^4.1.3", + "@npmcli/promise-spawn": "^8.0.0", + "ini": "^5.0.0", "lru-cache": "^10.0.1", - "npm-pick-manifest": "^9.0.0", - "proc-log": "^4.0.0", + "npm-pick-manifest": "^10.0.0", + "proc-log": "^5.0.0", "promise-inflight": "^1.0.1", "promise-retry": "^2.0.1", "semver": "^7.3.5", - "which": "^4.0.0" + "which": "^5.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/git/node_modules/isexe": { @@ -5361,9 +5827,9 @@ "license": "ISC" }, "node_modules/@npmcli/git/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { @@ -5373,53 +5839,53 @@ "node-which": "bin/which.js" }, "engines": { - "node": "^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/installed-package-contents": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz", - "integrity": "sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-3.0.0.tgz", + "integrity": "sha512-fkxoPuFGvxyrH+OQzyTkX2LUEamrF4jZSmxjAtPPHHGO0dqsQ8tTKjnIS8SAnPHdk2I03BDtSMR5K/4loKg79Q==", "dev": true, "license": "ISC", "dependencies": { - "npm-bundled": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" + "npm-bundled": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" }, "bin": { "installed-package-contents": "bin/index.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/node-gyp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", - "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-4.0.0.tgz", + "integrity": "sha512-+t5DZ6mO/QFh78PByMq1fGSAub/agLJZDRfJRMeOSNCt8s9YVlTjmGpIPwPhvXTGUIJk+WszlT0rQa1W33yzNA==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/package-json": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.2.1.tgz", - "integrity": "sha512-f7zYC6kQautXHvNbLEWgD/uGu1+xCn9izgqBfgItWSx22U0ZDekxN08A1vM8cTxj/cRVe0Q94Ode+tdoYmIOOQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-6.1.0.tgz", + "integrity": "sha512-t6G+6ZInT4X+tqj2i+wlLIeCKnKOTuz9/VFYDtj+TGTur5q7sp/OYrQA19LdBbWfXDOi0Y4jtedV6xtB8zQ9ug==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/git": "^5.0.0", + "@npmcli/git": "^6.0.0", "glob": "^10.2.2", - "hosted-git-info": "^7.0.0", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^6.0.0", - "proc-log": "^4.0.0", + "hosted-git-info": "^8.0.0", + "json-parse-even-better-errors": "^4.0.0", + "normalize-package-data": "^7.0.0", + "proc-log": "^5.0.0", "semver": "^7.5.3" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/package-json/node_modules/glob": { @@ -5444,16 +5910,16 @@ } }, "node_modules/@npmcli/promise-spawn": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz", - "integrity": "sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-8.0.2.tgz", + "integrity": "sha512-/bNJhjc+o6qL+Dwz/bqfTQClkEO5nTQ1ZEcdCkAQjhkZMHIh22LPG7fNh1enJP1NKWDqYiiABnjFCY7E0zHYtQ==", "dev": true, "license": "ISC", "dependencies": { - "which": "^4.0.0" + "which": "^5.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/promise-spawn/node_modules/isexe": { @@ -5467,9 +5933,9 @@ } }, "node_modules/@npmcli/promise-spawn/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { @@ -5479,35 +5945,35 @@ "node-which": "bin/which.js" }, "engines": { - "node": "^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/redact": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-2.0.1.tgz", - "integrity": "sha512-YgsR5jCQZhVmTJvjduTOIHph0L73pK8xwMVaDY0PatySqVM9AZj93jpoXYSJqfHFxFkN9dmqTw6OiqExsS3LPw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-3.0.0.tgz", + "integrity": "sha512-/1uFzjVcfzqrgCeGW7+SZ4hv0qLWmKXVzFahZGJ6QuJBj6Myt9s17+JL86i76NV9YSnJRcGXJYQbAU0rn1YTCQ==", "dev": true, "license": "ISC", "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/run-script": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-8.1.0.tgz", - "integrity": "sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-9.0.2.tgz", + "integrity": "sha512-cJXiUlycdizQwvqE1iaAb4VRUM3RX09/8q46zjvy+ct9GhfZRWd7jXYVc1tn/CfRlGPVkX/u4sstRlepsm7hfw==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^5.0.0", - "@npmcli/promise-spawn": "^7.0.0", - "node-gyp": "^10.0.0", - "proc-log": "^4.0.0", - "which": "^4.0.0" + "@npmcli/node-gyp": "^4.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "node-gyp": "^11.0.0", + "proc-log": "^5.0.0", + "which": "^5.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/run-script/node_modules/isexe": { @@ -5521,9 +5987,9 @@ } }, "node_modules/@npmcli/run-script/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { @@ -5533,13 +5999,13 @@ "node-which": "bin/which.js" }, "engines": { - "node": "^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@nx/devkit": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.3.0.tgz", - "integrity": "sha512-u9oRd2F33DLNWPbzpYGW7xuMEYUAOwO9DLP9nGYpxbZXy6Z4AdoKeqhN+KBTyg8+DyQGuKUSEXcWriDyLLgcHw==", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.3.1.tgz", + "integrity": "sha512-Z6VdBg5GRu2Vg9FpeQJY+zQ1TvBoMWk8cTCZOf8J6myjoWYbksRfpWfNIvEk9OUsEMhpg98vxH2Cc8JR1zfiew==", "dev": true, "license": "MIT", "dependencies": { @@ -5593,9 +6059,9 @@ } }, "node_modules/@nx/nx-darwin-arm64": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.3.0.tgz", - "integrity": "sha512-9PqSe1Sh7qNqA4GL0cZH0t3S0EZzb2Xn14XY9au7yf0+eoxyag1oETjjULrxLeUmSoXW2hDxzNtoqKFE9zF07Q==", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.3.1.tgz", + "integrity": "sha512-bx++T9/8l4PK1yDTxPnROT7RG8CkWGkxKC0D7xlS/YQzE7CelDfgNYu0Bd7upZF4gafW2Uz3dd3j6WhvZLxbbg==", "cpu": [ "arm64" ], @@ -5610,9 +6076,9 @@ } }, "node_modules/@nx/nx-darwin-x64": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.3.0.tgz", - "integrity": "sha512-gsGGhJVvi5QZVVTZie5sNMo1zOAU+A2edm6DGegObdFRLV41Ju/Yrm/gTaSp4yUtywd3UU4S/30C/nI2c55adA==", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.3.1.tgz", + "integrity": "sha512-elg2GiSivMHU1iLFYZ+FojM2V/FmTlC8e5FKM6nZ+bIqeoBoJm8Rxxe/kEtcsPdvjj+YiKSmXOP9s45DJb9WWw==", "cpu": [ "x64" ], @@ -5627,9 +6093,9 @@ } }, "node_modules/@nx/nx-freebsd-x64": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.3.0.tgz", - "integrity": "sha512-DiymYZBBu0upbiskdfn9KRyoXdyvKohezJiV3j4VkeRE8KR2p04NgwRQviDFbeD1cjWrDy9wk8y+G5PabLlqAA==", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.3.1.tgz", + "integrity": "sha512-1iKZOCcU7bVAC2kdoukfJ7AOTLBhm69+vPff3HCJQ0DI/5ZbmiaPeBMsAVFtJ0jFGix8yYIhgvtXgDEfbXXRFQ==", "cpu": [ "x64" ], @@ -5644,9 +6110,9 @@ } }, "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.3.0.tgz", - "integrity": "sha512-Aksx66e8jmt/4rGJ/5z34SWXbPcYr9Ht52UonEeuCdQdoEvAOs7yBUbllYOjIcUsfZikEyZgvqfiQslsggSJdQ==", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.3.1.tgz", + "integrity": "sha512-LAteJ1/mWYdvj7zpXuWRUq1lvUiV6YVXCdFK3+7lDW+qvW3bb5zzUwbVDAF/pPeTjBrsdHDzSWOCLm/LKtYtMw==", "cpu": [ "arm" ], @@ -5661,9 +6127,9 @@ } }, "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.3.0.tgz", - "integrity": "sha512-Y5wmYEwF1bl014Ps8QjagI911VbViQSFHSTVOCNSObdAzig9E5o6NOkoWe+doT1UZLrrInnlkrggQUsbtdKjOg==", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.3.1.tgz", + "integrity": "sha512-2Qf+6NcAeODELyJR+V9hjC9kl2DwJTdI7Bw+BuiyXftfPHvZ86P//FC8kPjNaJCEEm/ZStP6Jcb1zlp4Eo2wBw==", "cpu": [ "arm64" ], @@ -5678,9 +6144,9 @@ } }, "node_modules/@nx/nx-linux-arm64-musl": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.3.0.tgz", - "integrity": "sha512-yGcIkmImyOMfPkQSYH2EVjPmFE0VkLcO71Bbkpr3RlJ1N/vjYxsGbdnqPiBb8Wshib/hmwpiMHf/yzQtKH0SQw==", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.3.1.tgz", + "integrity": "sha512-8S8jlN6GFQpRakZ2ZVWq6eFnLVrEObIaxnYD0QMbsMf+qiedDJt+cDh1xebcPRvgpSgJVlJ8P6hun5+K/FiQDQ==", "cpu": [ "arm64" ], @@ -5695,9 +6161,9 @@ } }, "node_modules/@nx/nx-linux-x64-gnu": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.3.0.tgz", - "integrity": "sha512-nkA2DLI+rpmiuiy7dyXP4l9s7dgHkQWDX7lG1XltiT41RzAReJF1h8qBE6XrsAYE1CtI76DRWVphnc93+iZr+A==", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.3.1.tgz", + "integrity": "sha512-qC2On2qwYCtn/Kt8epvUn0H3NY6zG9yYhiNjkm6RvVTDmvogFQ4gtfiWSRP/EnabCRqM8FACDIO/ws5CnRBX+Q==", "cpu": [ "x64" ], @@ -5712,9 +6178,9 @@ } }, "node_modules/@nx/nx-linux-x64-musl": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.3.0.tgz", - "integrity": "sha512-sPMtTt9iTrCmFEIp9Qv27UX9PeL1aqKck2dz2TAFbXKVtF6+djOdTcNnTYw45KIP6izcUcOXXAq4G0QSQE7CLg==", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.3.1.tgz", + "integrity": "sha512-KKwHSfV1PEKW82eJ8vxZTPepoaLbaXH/aI0VOKZbBO4ytGyGUr9wFuWPsyo06rK7qtSD7w9bN7xpiBGQk0QTsg==", "cpu": [ "x64" ], @@ -5729,9 +6195,9 @@ } }, "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.3.0.tgz", - "integrity": "sha512-ppfNa/8OfpWA9o26Pz3vArN4ulAC+Hx70/ghPRCP7ed1Mb3Z6yR2Ry9KfBRImbqajvuAExM0TePKMGq9LCdXmg==", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.3.1.tgz", + "integrity": "sha512-YujkXXHn9rhtwZRDxiaxSPOMX7JkfGmXAFdyEfxhE3Dc/HjFgI+xJZ478/atttR7DWIwGpQJVLpbFWbFFpoNNg==", "cpu": [ "arm64" ], @@ -5746,9 +6212,9 @@ } }, "node_modules/@nx/nx-win32-x64-msvc": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.3.0.tgz", - "integrity": "sha512-8FOejZ4emtLSVn3pYWs4PIc3n4//qMbwMDPVxmPE8us3ir91Qh0bzr5zRj7Q8sEdSgvneXRXqtBp2grY2KMJsw==", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.3.1.tgz", + "integrity": "sha512-Os8iCamvHhE5noQKFE9D9xkiI529918tufTYmEhJ9ZmLU/ybVA0We6r7gXjYzdNfA3DtwfGXvNvUpy3u+pZXOg==", "cpu": [ "x64" ], @@ -6204,9 +6670,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.26.0.tgz", + "integrity": "sha512-gJNwtPDGEaOEgejbaseY6xMFu+CPltsc8/T+diUTTbOQLqD+bnrJq9ulH6WD69TqwqWmrfRAtUv30cCFZlbGTQ==", "cpu": [ "arm" ], @@ -6218,9 +6684,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.26.0.tgz", + "integrity": "sha512-YJa5Gy8mEZgz5JquFruhJODMq3lTHWLm1fOy+HIANquLzfIOzE9RA5ie3JjCdVb9r46qfAQY/l947V0zfGJ0OQ==", "cpu": [ "arm64" ], @@ -6232,9 +6698,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.26.0.tgz", + "integrity": "sha512-ErTASs8YKbqTBoPLp/kA1B1Um5YSom8QAc4rKhg7b9tyyVqDBlQxy7Bf2wW7yIlPGPg2UODDQcbkTlruPzDosw==", "cpu": [ "arm64" ], @@ -6246,9 +6712,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.26.0.tgz", + "integrity": "sha512-wbgkYDHcdWW+NqP2mnf2NOuEbOLzDblalrOWcPyY6+BRbVhliavon15UploG7PpBRQ2bZJnbmh8o3yLoBvDIHA==", "cpu": [ "x64" ], @@ -6259,10 +6725,38 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.26.0.tgz", + "integrity": "sha512-Y9vpjfp9CDkAG4q/uwuhZk96LP11fBz/bYdyg9oaHYhtGZp7NrbkQrj/66DYMMP2Yo/QPAsVHkV891KyO52fhg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.26.0.tgz", + "integrity": "sha512-A/jvfCZ55EYPsqeaAt/yDAG4q5tt1ZboWMHEvKAH9Zl92DWvMIbnZe/f/eOXze65aJaaKbL+YeM0Hz4kLQvdwg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.26.0.tgz", + "integrity": "sha512-paHF1bMXKDuizaMODm2bBTjRiHxESWiIyIdMugKeLnjuS1TCS54MF5+Y5Dx8Ui/1RBPVRE09i5OUlaLnv8OGnA==", "cpu": [ "arm" ], @@ -6274,9 +6768,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.26.0.tgz", + "integrity": "sha512-cwxiHZU1GAs+TMxvgPfUDtVZjdBdTsQwVnNlzRXC5QzIJ6nhfB4I1ahKoe9yPmoaA/Vhf7m9dB1chGPpDRdGXg==", "cpu": [ "arm" ], @@ -6288,9 +6782,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.26.0.tgz", + "integrity": "sha512-4daeEUQutGRCW/9zEo8JtdAgtJ1q2g5oHaoQaZbMSKaIWKDQwQ3Yx0/3jJNmpzrsScIPtx/V+1AfibLisb3AMQ==", "cpu": [ "arm64" ], @@ -6302,9 +6796,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.26.0.tgz", + "integrity": "sha512-eGkX7zzkNxvvS05ROzJ/cO/AKqNvR/7t1jA3VZDi2vRniLKwAWxUr85fH3NsvtxU5vnUUKFHKh8flIBdlo2b3Q==", "cpu": [ "arm64" ], @@ -6316,9 +6810,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.26.0.tgz", + "integrity": "sha512-Odp/lgHbW/mAqw/pU21goo5ruWsytP7/HCC/liOt0zcGG0llYWKrd10k9Fj0pdj3prQ63N5yQLCLiE7HTX+MYw==", "cpu": [ "ppc64" ], @@ -6330,9 +6824,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.26.0.tgz", + "integrity": "sha512-MBR2ZhCTzUgVD0OJdTzNeF4+zsVogIR1U/FsyuFerwcqjZGvg2nYe24SAHp8O5sN8ZkRVbHwlYeHqcSQ8tcYew==", "cpu": [ "riscv64" ], @@ -6344,9 +6838,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.26.0.tgz", + "integrity": "sha512-YYcg8MkbN17fMbRMZuxwmxWqsmQufh3ZJFxFGoHjrE7bv0X+T6l3glcdzd7IKLiwhT+PZOJCblpnNlz1/C3kGQ==", "cpu": [ "s390x" ], @@ -6358,9 +6852,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.26.0.tgz", + "integrity": "sha512-ZuwpfjCwjPkAOxpjAEjabg6LRSfL7cAJb6gSQGZYjGhadlzKKywDkCUnJ+KEfrNY1jH5EEoSIKLCb572jSiglA==", "cpu": [ "x64" ], @@ -6372,9 +6866,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.26.0.tgz", + "integrity": "sha512-+HJD2lFS86qkeF8kNu0kALtifMpPCZU80HvwztIKnYwym3KnA1os6nsX4BGSTLtS2QVAGG1P3guRgsYyMA0Yhg==", "cpu": [ "x64" ], @@ -6386,9 +6880,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.26.0.tgz", + "integrity": "sha512-WUQzVFWPSw2uJzX4j6YEbMAiLbs0BUysgysh8s817doAYhR5ybqTI1wtKARQKo6cGop3pHnrUJPFCsXdoFaimQ==", "cpu": [ "arm64" ], @@ -6400,9 +6894,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.26.0.tgz", + "integrity": "sha512-D4CxkazFKBfN1akAIY6ieyOqzoOoBV1OICxgUblWxff/pSjCA2khXlASUx7mK6W1oP4McqhgcCsu6QaLj3WMWg==", "cpu": [ "ia32" ], @@ -6414,9 +6908,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.26.0.tgz", + "integrity": "sha512-2x8MO1rm4PGEP0xWbubJW5RtbNLk3puzAMaLQd3B3JHVw4KcHlmXcO+Wewx9zCoo7EUFiMlu/aZbCJ7VjMzAag==", "cpu": [ "x64" ], @@ -6428,14 +6922,14 @@ ] }, "node_modules/@schematics/angular": { - "version": "18.2.12", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.12.tgz", - "integrity": "sha512-sIoeipsisK5eTLW3XuNZYcal83AfslBbgI7LnV+3VrXwpasKPGHwo2ZdwhCd2IXAkuJ02Iyu7MyV0aQRM9i/3g==", + "version": "19.0.7", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.0.7.tgz", + "integrity": "sha512-1WtTqKFPuEaV99VIP+y/gf/XW3TVJh/NbJbbEF4qYpp7qQiJ4ntF4klVZmsJcQzFucZSzlg91QVMPQKev5WZGA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.12", - "@angular-devkit/schematics": "18.2.12", + "@angular-devkit/core": "19.0.7", + "@angular-devkit/schematics": "19.0.7", "jsonc-parser": "3.3.1" }, "engines": { @@ -6445,63 +6939,63 @@ } }, "node_modules/@sentry-internal/browser-utils": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.47.0.tgz", - "integrity": "sha512-vOXzYzHTKkahTLDzWWIA4EiVCQ+Gk+7xGWUlNcR2ZiEPBqYZVb5MjsUozAcc7syrSUy6WicyFjcomZ3rlCVQhg==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.48.0.tgz", + "integrity": "sha512-pLtu0Fa1Ou0v3M1OEO1MB1EONJVmXEGtoTwFRCO1RPQI2ulmkG6BikINClFG5IBpoYKZ33WkEXuM6U5xh+pdZg==", "license": "MIT", "dependencies": { - "@sentry/core": "8.47.0" + "@sentry/core": "8.48.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/feedback": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.47.0.tgz", - "integrity": "sha512-IAiIemTQIalxAOYhUENs9bZ8pMNgJnX3uQSuY7v0gknEqClOGpGkG04X/cxCmtJUj1acZ9ShTGDxoh55a+ggAQ==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.48.0.tgz", + "integrity": "sha512-6PwcJNHVPg0EfZxmN+XxVOClfQpv7MBAweV8t9i5l7VFr8sM/7wPNSeU/cG7iK19Ug9ZEkBpzMOe3G4GXJ5bpw==", "license": "MIT", "dependencies": { - "@sentry/core": "8.47.0" + "@sentry/core": "8.48.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.47.0.tgz", - "integrity": "sha512-G/S40ZBORj0HSMLw/uVC6YDEPN/dqVk901vf4VYfml686DEhJrZesfAfp5SydJumQ0NKZQrdtvny+BWnlI5H1w==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.48.0.tgz", + "integrity": "sha512-csILVupc5RkrsTrncuUTGmlB56FQSFjXPYWG8I8yBTGlXEJ+o8oTuF6+55R4vbw3EIzBveXWi4kEBbnQlXW/eg==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "8.47.0", - "@sentry/core": "8.47.0" + "@sentry-internal/browser-utils": "8.48.0", + "@sentry/core": "8.48.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.47.0.tgz", - "integrity": "sha512-M4W9UGouEeELbGbP3QsXLDVtGiQSZoWJlKwqMWyqdQgZuLoKw0S33+60t6teLVMhuQZR0UI9VJTF5coiXysnnA==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.48.0.tgz", + "integrity": "sha512-LdivLfBXXB9us1aAc6XaL7/L2Ob4vi3C/fEOXElehg3qHjX6q6pewiv5wBvVXGX1NfZTRvu+X11k6TZoxKsezw==", "license": "MIT", "dependencies": { - "@sentry-internal/replay": "8.47.0", - "@sentry/core": "8.47.0" + "@sentry-internal/replay": "8.48.0", + "@sentry/core": "8.48.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry/angular": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/angular/-/angular-8.47.0.tgz", - "integrity": "sha512-SHKyzd8OOrlGcnKItIFYp9wJXIReo1LwNDRQ8zJvUhMwdCHfZW0oZOSXTt8Ol4MfU/lWEgrFg+SyhA3Ltiz2uw==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@sentry/angular/-/angular-8.48.0.tgz", + "integrity": "sha512-jJRrsm5y72L9TPBIRITOEryiO4MM0XP2ZAKc943v76dk6Q47SdataUdF6Lwf+MxobnE7S+zY97DnsxLGsOxF4w==", "license": "MIT", "dependencies": { - "@sentry/browser": "8.47.0", - "@sentry/core": "8.47.0", + "@sentry/browser": "8.48.0", + "@sentry/core": "8.48.0", "tslib": "^2.4.1" }, "engines": { @@ -6515,38 +7009,38 @@ } }, "node_modules/@sentry/browser": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.47.0.tgz", - "integrity": "sha512-K6BzHisykmbFy/wORtGyfsAlw7ShevLALzu3ReZZZ18dVubO1bjSNjkZQU9MJD5Jcb9oLwkq89n3N9XIBfvdRA==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.48.0.tgz", + "integrity": "sha512-fuuVULB5/1vI8NoIwXwR3xwhJJqk+y4RdSdajExGF7nnUDBpwUJyXsmYJnOkBO+oLeEs58xaCpotCKiPUNnE3g==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "8.47.0", - "@sentry-internal/feedback": "8.47.0", - "@sentry-internal/replay": "8.47.0", - "@sentry-internal/replay-canvas": "8.47.0", - "@sentry/core": "8.47.0" + "@sentry-internal/browser-utils": "8.48.0", + "@sentry-internal/feedback": "8.48.0", + "@sentry-internal/replay": "8.48.0", + "@sentry-internal/replay-canvas": "8.48.0", + "@sentry/core": "8.48.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry/core": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.47.0.tgz", - "integrity": "sha512-iSEJZMe3DOcqBFZQAqgA3NB2lCWBc4Gv5x/SCri/TVg96wAlss4VrUunSI2Mp0J4jJ5nJcJ2ChqHSBAU48k3FA==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.48.0.tgz", + "integrity": "sha512-VGwYgTfLpvJ5LRO5A+qWo1gpo6SfqaGXL9TOzVgBucAdpzbrYHpZ87sEarDVq/4275uk1b0S293/mfsskFczyw==", "license": "MIT", "engines": { "node": ">=14.18" } }, "node_modules/@sentry/types": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.47.0.tgz", - "integrity": "sha512-ruiowlIBQUPDwNcO0KTudKP9T2QYF3S2TLhDdoJb+0ZGJduH4PsgGAojUSpGR+idKfrlOSlUpcdg9+WxsoOckg==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.48.0.tgz", + "integrity": "sha512-3Ad38BF9b+sVRh7ag8jryHuqVOzQ4mBKjT6vnm+jQz45Qbhri//LSdhhJ7KpiSm3/EYpRjQekTr6mjYZmfOaeA==", "dev": true, "license": "MIT", "dependencies": { - "@sentry/core": "8.47.0" + "@sentry/core": "8.48.0" }, "engines": { "node": ">=14.18" @@ -6568,26 +7062,26 @@ } }, "node_modules/@sigstore/bundle": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.3.2.tgz", - "integrity": "sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-3.0.0.tgz", + "integrity": "sha512-XDUYX56iMPAn/cdgh/DTJxz5RWmqKV4pwvUAEKEWJl+HzKdCd/24wUa9JYNMlDSCb7SUHAdtksxYX779Nne/Zg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.3.2" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sigstore/core": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-1.1.0.tgz", - "integrity": "sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-2.0.0.tgz", + "integrity": "sha512-nYxaSb/MtlSI+JWcwTHQxyNmWeWrUXJJ/G4liLrGG7+tS4vAz6LF3xRXqLH6wPIVUoZQel2Fs4ddLx4NCpiIYg==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sigstore/protobuf-specs": { @@ -6601,50 +7095,50 @@ } }, "node_modules/@sigstore/sign": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.3.2.tgz", - "integrity": "sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-3.0.0.tgz", + "integrity": "sha512-UjhDMQOkyDoktpXoc5YPJpJK6IooF2gayAr5LvXI4EL7O0vd58okgfRcxuaH+YTdhvb5aa1Q9f+WJ0c2sVuYIw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", "@sigstore/protobuf-specs": "^0.3.2", - "make-fetch-happen": "^13.0.1", - "proc-log": "^4.2.0", + "make-fetch-happen": "^14.0.1", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sigstore/tuf": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-2.3.4.tgz", - "integrity": "sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-3.0.0.tgz", + "integrity": "sha512-9Xxy/8U5OFJu7s+OsHzI96IX/OzjF/zj0BSSaWhgJgTqtlBhQIV2xdrQI5qxLD7+CWWDepadnXAxzaZ3u9cvRw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.3.2", - "tuf-js": "^2.2.1" + "tuf-js": "^3.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sigstore/verify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-1.2.1.tgz", - "integrity": "sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-2.0.0.tgz", + "integrity": "sha512-Ggtq2GsJuxFNUvQzLoXqRwS4ceRfLAJnrIHUDrzAD0GgnOhwujJkKkxM/s5Bako07c3WtAs/sZo5PJq7VHjeDg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.1.0", + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", "@sigstore/protobuf-specs": "^0.3.2" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sinclair/typebox": { @@ -6660,6 +7154,7 @@ "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -6864,17 +7359,17 @@ } }, "node_modules/@tufjs/models": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.1.tgz", - "integrity": "sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-3.0.1.tgz", + "integrity": "sha512-UUYHISyhCU3ZgN8yaear3cGATHb3SMuKHsQ/nVbHXcmnBf+LzQ/cQfhNG+rfaSHgqGKNEm2cOCLVLELStUQ1JA==", "dev": true, "license": "MIT", "dependencies": { "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.4" + "minimatch": "^9.0.5" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@tybys/wasm-util": { @@ -6942,6 +7437,7 @@ "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -6953,6 +7449,7 @@ "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*" } @@ -6963,6 +7460,7 @@ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*" } @@ -6973,6 +7471,7 @@ "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" @@ -6993,9 +7492,9 @@ "license": "MIT" }, "node_modules/@types/d3-shape": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", - "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", "dev": true, "license": "MIT", "dependencies": { @@ -7019,6 +7518,30 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -7032,6 +7555,7 @@ "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -7040,11 +7564,12 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.3.tgz", - "integrity": "sha512-JEhMNwUJt7bw728CydvYzntD0XJeTmDnvwLlbfbAhE7Tbslm/ax6bdIiUwTgeVlZTsJQPwZwKpAkyDtIjsvx3g==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.4.tgz", + "integrity": "sha512-5kz9ScmzBdzTgB/3susoCgfqNDzBjvLL4taparufgSvlwjdLy6UyUy9T/tCpYd2GIdIilCatC4iSQS0QSYHt0w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -7058,6 +7583,7 @@ "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -7090,7 +7616,8 @@ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/http-proxy": { "version": "1.17.15", @@ -7098,6 +7625,7 @@ "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*" } @@ -7241,17 +7769,8 @@ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true, - "license": "MIT" - }, - "node_modules/@types/mute-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", - "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", - "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*" - } + "peer": true }, "node_modules/@types/node": { "version": "22.10.5", @@ -7269,6 +7788,7 @@ "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*" } @@ -7286,28 +7806,28 @@ "node_modules/@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", - "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", - "license": "MIT" + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==" }, "node_modules/@types/qs": { "version": "6.9.17", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/range-parser": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/react": { "version": "18.3.18", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", - "license": "MIT", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -7318,7 +7838,8 @@ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/semver": { "version": "7.5.8", @@ -7333,6 +7854,7 @@ "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/mime": "^1", "@types/node": "*" @@ -7344,6 +7866,7 @@ "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/express": "*" } @@ -7354,6 +7877,7 @@ "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/http-errors": "*", "@types/node": "*", @@ -7373,6 +7897,7 @@ "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*" } @@ -7438,19 +7963,13 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/wrap-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", - "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/ws": { "version": "8.5.13", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*" } @@ -7473,21 +7992,21 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.0.tgz", - "integrity": "sha512-NggSaEZCdSrFddbctrVjkVZvFC6KGfKfNK0CU7mNK/iKHGKbzT4Wmgm08dKpcZECBu9f5FypndoMyRHkdqfT1Q==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.1.tgz", + "integrity": "sha512-tJzcVyvvb9h/PB96g30MpxACd9IrunT7GF9wfA9/0TJ1LxGOJx1TdPzSbBBnNED7K9Ka8ybJsnEpiXPktolTLg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.19.0", - "@typescript-eslint/type-utils": "8.19.0", - "@typescript-eslint/utils": "8.19.0", - "@typescript-eslint/visitor-keys": "8.19.0", + "@typescript-eslint/scope-manager": "8.19.1", + "@typescript-eslint/type-utils": "8.19.1", + "@typescript-eslint/utils": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7513,16 +8032,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.0.tgz", - "integrity": "sha512-6M8taKyOETY1TKHp0x8ndycipTVgmp4xtg5QpEZzXxDhNvvHOJi5rLRkLr8SK3jTgD5l4fTlvBiRdfsuWydxBw==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.1.tgz", + "integrity": "sha512-67gbfv8rAwawjYx3fYArwldTQKoYfezNUT4D5ioWetr/xCrxXxvleo3uuiFuKfejipvq+og7mjz3b0G2bVyUCw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.19.0", - "@typescript-eslint/types": "8.19.0", - "@typescript-eslint/typescript-estree": "8.19.0", - "@typescript-eslint/visitor-keys": "8.19.0", + "@typescript-eslint/scope-manager": "8.19.1", + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/typescript-estree": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1", "debug": "^4.3.4" }, "engines": { @@ -7538,14 +8057,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.0.tgz", - "integrity": "sha512-hkoJiKQS3GQ13TSMEiuNmSCvhz7ujyqD1x3ShbaETATHrck+9RaDdUbt+osXaUuns9OFwrDTTrjtwsU8gJyyRA==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.1.tgz", + "integrity": "sha512-60L9KIuN/xgmsINzonOcMDSB8p82h95hoBfSBtXuO4jlR1R9L1xSkmVZKgCPVfavDlXihh4ARNjXhh1gGnLC7Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.0", - "@typescript-eslint/visitor-keys": "8.19.0" + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7556,16 +8075,16 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.0.tgz", - "integrity": "sha512-TZs0I0OSbd5Aza4qAMpp1cdCYVnER94IziudE3JU328YUHgWu9gwiwhag+fuLeJ2LkWLXI+F/182TbG+JaBdTg==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.1.tgz", + "integrity": "sha512-Rp7k9lhDKBMRJB/nM9Ksp1zs4796wVNyihG9/TU9R6KCJDNkQbc2EOKjrBtLYh3396ZdpXLtr/MkaSEmNMtykw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.19.0", - "@typescript-eslint/utils": "8.19.0", + "@typescript-eslint/typescript-estree": "8.19.1", + "@typescript-eslint/utils": "8.19.1", "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7580,9 +8099,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz", - "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.1.tgz", + "integrity": "sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==", "dev": true, "license": "MIT", "engines": { @@ -7594,20 +8113,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.0.tgz", - "integrity": "sha512-WW9PpDaLIFW9LCbucMSdYUuGeFUz1OkWYS/5fwZwTA+l2RwlWFdJvReQqMUMBw4yJWJOfqd7An9uwut2Oj8sLw==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.1.tgz", + "integrity": "sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.0", - "@typescript-eslint/visitor-keys": "8.19.0", + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7621,16 +8140,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.0.tgz", - "integrity": "sha512-PTBG+0oEMPH9jCZlfg07LCB2nYI0I317yyvXGfxnvGvw4SHIOuRnQ3kadyyXY6tGdChusIHIbM5zfIbp4M6tCg==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.1.tgz", + "integrity": "sha512-IxG5gLO0Ne+KaUc8iW1A+XuKLd63o4wlbI1Zp692n1xojCl/THvgIKXJXBZixTh5dd5+yTJ/VXH7GJaaw21qXA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.19.0", - "@typescript-eslint/types": "8.19.0", - "@typescript-eslint/typescript-estree": "8.19.0" + "@typescript-eslint/scope-manager": "8.19.1", + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/typescript-estree": "8.19.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7645,13 +8164,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.0.tgz", - "integrity": "sha512-mCFtBbFBJDCNCWUl5y6sZSCHXw1DEFEk3c/M3nRK2a4XUB8StGFtmcEMizdjKuBzB6e/smJAAWYug3VrdLMr1w==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.1.tgz", + "integrity": "sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/types": "8.19.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -7731,16 +8250,6 @@ } } }, - "node_modules/@vitest/mocker/node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, "node_modules/@vitest/pretty-format": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.8.tgz", @@ -7783,16 +8292,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/snapshot/node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, "node_modules/@vitest/spy": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.8.tgz", @@ -7842,6 +8341,7 @@ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" @@ -7852,21 +8352,24 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.13.2", @@ -7874,6 +8377,7 @@ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", @@ -7885,7 +8389,8 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.14.1", @@ -7893,6 +8398,7 @@ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -7906,6 +8412,7 @@ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -7916,6 +8423,7 @@ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -7925,7 +8433,8 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.14.1", @@ -7933,6 +8442,7 @@ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -7950,6 +8460,7 @@ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", @@ -7964,6 +8475,7 @@ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -7977,6 +8489,7 @@ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", @@ -7992,6 +8505,7 @@ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" @@ -8002,14 +8516,16 @@ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "dev": true, - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "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, - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", @@ -8092,6 +8608,7 @@ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" @@ -8106,6 +8623,7 @@ "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -8116,6 +8634,7 @@ "integrity": "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "mime-db": "^1.53.0" }, @@ -8123,16 +8642,6 @@ "node": ">= 0.6" } }, - "node_modules/accepts/node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/acorn": { "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", @@ -8146,16 +8655,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -8185,6 +8684,7 @@ "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "loader-utils": "^2.0.0", "regex-parser": "^2.2.11" @@ -8199,6 +8699,7 @@ "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -8218,20 +8719,6 @@ "node": ">= 14" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", @@ -8273,6 +8760,7 @@ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -8315,6 +8803,7 @@ "node >= 0.8.0" ], "license": "Apache-2.0", + "peer": true, "bin": { "ansi-html": "bin/ansi-html" } @@ -8398,7 +8887,8 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz", "integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/array-union": { "version": "2.1.0", @@ -8464,6 +8954,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "browserslist": "^4.23.3", "caniuse-lite": "^1.0.30001646", @@ -8537,11 +9028,12 @@ } }, "node_modules/babel-loader": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", - "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "find-cache-dir": "^4.0.0", "schema-utils": "^4.0.0" @@ -8610,6 +9102,7 @@ "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.3", @@ -8625,6 +9118,7 @@ "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2", "core-js-compat": "^3.38.0" @@ -8639,6 +9133,7 @@ "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.3" }, @@ -8751,7 +9246,25 @@ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true + }, + "node_modules/beasties": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.1.0.tgz", + "integrity": "sha512-+Ssscd2gVG24qRNC+E2g88D+xsQW4xwakWtKAiGEQ3Pw54/FGdyo9RrfxhGhEv6ilFVbB7r3Lgx+QnAxnSpECw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "htmlparser2": "^9.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-media-query-parser": "^0.2.3" + } }, "node_modules/big.js": { "version": "5.2.2", @@ -8759,6 +9272,7 @@ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": "*" } @@ -8769,6 +9283,7 @@ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=8" }, @@ -8809,6 +9324,7 @@ "integrity": "sha512-SNMk0OONlQ01uk8EPeiBvTW7W4ovpL5b1O3t1sjpPgfxOQ6BqQJ6XjxinDPR79Z6HdcD5zBBwr5ssiTlgdNztQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -8831,6 +9347,7 @@ "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -8844,6 +9361,7 @@ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -8854,6 +9372,7 @@ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -8868,6 +9387,7 @@ "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" @@ -8922,9 +9442,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", - "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "funding": [ { "type": "opencollective", @@ -9014,6 +9534,7 @@ "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "run-applescript": "^7.0.0" }, @@ -9030,6 +9551,7 @@ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8" } @@ -9045,13 +9567,13 @@ } }, "node_modules/cacache": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", - "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^3.1.0", + "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", @@ -9059,13 +9581,23 @@ "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/cacache/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/cacache/node_modules/glob": { @@ -9096,6 +9628,50 @@ "dev": true, "license": "ISC" }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -9176,9 +9752,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001690", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", - "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", + "version": "1.0.30001692", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz", + "integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==", "funding": [ { "type": "opencollective", @@ -9257,41 +9833,18 @@ } }, "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 14.16.0" }, "funding": { "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" } }, "node_modules/chownr": { @@ -9310,6 +9863,7 @@ "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6.0" } @@ -9337,16 +9891,6 @@ "dev": true, "license": "MIT" }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", @@ -9479,6 +10023,7 @@ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -9494,6 +10039,7 @@ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "isobject": "^3.0.1" }, @@ -9588,7 +10134,8 @@ "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", "dev": true, - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/compare-versions": { "version": "6.1.1", @@ -9602,6 +10149,7 @@ "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "mime-db": ">= 1.43.0 < 2" }, @@ -9615,6 +10163,7 @@ "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", @@ -9628,6 +10177,17 @@ "node": ">= 0.8.0" } }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/compression/node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -9647,7 +10207,8 @@ "url": "https://feross.org/support" } ], - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/concat-map": { "version": "0.0.1", @@ -9662,6 +10223,7 @@ "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.8" } @@ -9672,6 +10234,7 @@ "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "safe-buffer": "5.2.1" }, @@ -9698,7 +10261,8 @@ "url": "https://feross.org/support" } ], - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/content-type": { "version": "1.0.5", @@ -9706,6 +10270,7 @@ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -9722,6 +10287,7 @@ "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -9732,6 +10298,7 @@ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6.6.0" } @@ -9742,6 +10309,7 @@ "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "is-what": "^3.14.1" }, @@ -9755,6 +10323,7 @@ "integrity": "sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-glob": "^3.3.2", "glob-parent": "^6.0.1", @@ -9775,9 +10344,9 @@ } }, "node_modules/core-js": { - "version": "3.39.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz", - "integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==", + "version": "3.40.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.40.0.tgz", + "integrity": "sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -9786,13 +10355,14 @@ } }, "node_modules/core-js-compat": { - "version": "3.39.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", - "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", + "version": "3.40.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.40.0.tgz", + "integrity": "sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "browserslist": "^4.24.2" + "browserslist": "^4.24.3" }, "funding": { "type": "opencollective", @@ -9811,6 +10381,7 @@ "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", @@ -9861,23 +10432,6 @@ "dev": true, "license": "MIT" }, - "node_modules/critters": { - "version": "0.0.25", - "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.25.tgz", - "integrity": "sha512-ROF/tjJyyRdM8/6W0VqoN5Ql05xAGnkf5b7f3sTEl1bI5jTQQf8O918RD/V9tEb9pRY/TKcvJekDbJtniHyPtQ==", - "deprecated": "Ownership of Critters has moved to the Nuxt team, who will be maintaining the project going forward. If you'd like to keep using Critters, please switch to the actively-maintained fork at https://github.com/danielroe/beasties", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "chalk": "^4.1.0", - "css-select": "^5.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.2", - "htmlparser2": "^8.0.2", - "postcss": "^8.4.23", - "postcss-media-query-parser": "^0.2.3" - } - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -9914,6 +10468,7 @@ "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.4.33", @@ -9991,6 +10546,7 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "cssesc": "bin/cssesc" }, @@ -10006,18 +10562,26 @@ "license": "MIT" }, "node_modules/cssstyle": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", - "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.2.1.tgz", + "integrity": "sha512-9+vem03dMXG7gDmZ62uqmRiMRNtinIZ9ZyuF6BdxzfOD+FdN5hretzynkn0ReS2DO2GSw76RWHs0UmJPI2zUjw==", "dev": true, "license": "MIT", "dependencies": { - "rrweb-cssom": "^0.7.1" + "@asamuzakjp/css-color": "^2.8.2", + "rrweb-cssom": "^0.8.0" }, "engines": { "node": ">=18" } }, + "node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true, + "license": "MIT" + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -10385,6 +10949,7 @@ "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" @@ -10402,6 +10967,7 @@ "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -10446,6 +11012,7 @@ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -10469,6 +11036,7 @@ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8" } @@ -10490,6 +11058,7 @@ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -10501,6 +11070,7 @@ "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "dev": true, "license": "Apache-2.0", + "optional": true, "engines": { "node": ">=8" } @@ -10520,7 +11090,8 @@ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/diff": { "version": "4.0.2", @@ -10577,6 +11148,7 @@ "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" }, @@ -10646,9 +11218,9 @@ } }, "node_modules/domutils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.1.tgz", - "integrity": "sha512-xWXmuRnN9OMP6ptPd2+H0cCbcYBULa5YDTbMm/2lvkWvNA3O4wcW+GvzooqBuNM8yy6pl3VIAeJTUUWUbfI5Fw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -10716,7 +11288,8 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/ejs": { "version": "3.1.10", @@ -10735,9 +11308,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.76", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz", - "integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==", + "version": "1.5.80", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.80.tgz", + "integrity": "sha512-LTrKpW0AqIuHwmlVNV+cjFYTnXtM9K37OGhpe0ZI10ScPSxqVSryZHIY3WnCS5NSYbBODRTZyhRMS2h5FAEqAw==", "license": "ISC" }, "node_modules/emittery": { @@ -10781,6 +11354,7 @@ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 4" } @@ -10791,6 +11365,7 @@ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8" } @@ -10836,6 +11411,7 @@ "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -10906,6 +11482,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "prr": "~1.0.1" }, @@ -10964,9 +11541,9 @@ } }, "node_modules/esbuild": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", - "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", + "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -10977,36 +11554,36 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.0", - "@esbuild/android-arm": "0.23.0", - "@esbuild/android-arm64": "0.23.0", - "@esbuild/android-x64": "0.23.0", - "@esbuild/darwin-arm64": "0.23.0", - "@esbuild/darwin-x64": "0.23.0", - "@esbuild/freebsd-arm64": "0.23.0", - "@esbuild/freebsd-x64": "0.23.0", - "@esbuild/linux-arm": "0.23.0", - "@esbuild/linux-arm64": "0.23.0", - "@esbuild/linux-ia32": "0.23.0", - "@esbuild/linux-loong64": "0.23.0", - "@esbuild/linux-mips64el": "0.23.0", - "@esbuild/linux-ppc64": "0.23.0", - "@esbuild/linux-riscv64": "0.23.0", - "@esbuild/linux-s390x": "0.23.0", - "@esbuild/linux-x64": "0.23.0", - "@esbuild/netbsd-x64": "0.23.0", - "@esbuild/openbsd-arm64": "0.23.0", - "@esbuild/openbsd-x64": "0.23.0", - "@esbuild/sunos-x64": "0.23.0", - "@esbuild/win32-arm64": "0.23.0", - "@esbuild/win32-ia32": "0.23.0", - "@esbuild/win32-x64": "0.23.0" + "@esbuild/aix-ppc64": "0.24.0", + "@esbuild/android-arm": "0.24.0", + "@esbuild/android-arm64": "0.24.0", + "@esbuild/android-x64": "0.24.0", + "@esbuild/darwin-arm64": "0.24.0", + "@esbuild/darwin-x64": "0.24.0", + "@esbuild/freebsd-arm64": "0.24.0", + "@esbuild/freebsd-x64": "0.24.0", + "@esbuild/linux-arm": "0.24.0", + "@esbuild/linux-arm64": "0.24.0", + "@esbuild/linux-ia32": "0.24.0", + "@esbuild/linux-loong64": "0.24.0", + "@esbuild/linux-mips64el": "0.24.0", + "@esbuild/linux-ppc64": "0.24.0", + "@esbuild/linux-riscv64": "0.24.0", + "@esbuild/linux-s390x": "0.24.0", + "@esbuild/linux-x64": "0.24.0", + "@esbuild/netbsd-x64": "0.24.0", + "@esbuild/openbsd-arm64": "0.24.0", + "@esbuild/openbsd-x64": "0.24.0", + "@esbuild/sunos-x64": "0.24.0", + "@esbuild/win32-arm64": "0.24.0", + "@esbuild/win32-ia32": "0.24.0", + "@esbuild/win32-x64": "0.24.0" } }, "node_modules/esbuild-wasm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.23.0.tgz", - "integrity": "sha512-6jP8UmWy6R6TUUV8bMuC3ZyZ6lZKI56x0tkxyCIqWwRRJ/DgeQKneh/Oid5EoGoPFLrGNkz47ZEtWAYuiY/u9g==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.24.0.tgz", + "integrity": "sha512-xhNn5tL1AhkPg4ft59yXT6FkwKXiPSYyz1IeinJHUJpjvOHOIPvdmFQc0pGdjxlKSbzZc2mNmtVOWAR1EF/JAg==", "dev": true, "license": "MIT", "bin": { @@ -11030,7 +11607,8 @@ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/escape-string-regexp": { "version": "4.0.0", @@ -11277,6 +11855,19 @@ "node": ">=8" } }, + "node_modules/eslint-plugin-deprecation/node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/eslint-plugin-jest": { "version": "28.10.0", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.10.0.tgz", @@ -11728,6 +12319,7 @@ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -11737,7 +12329,8 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/events": { "version": "3.3.0", @@ -11745,6 +12338,7 @@ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.8.x" } @@ -11847,6 +12441,7 @@ "integrity": "sha512-ORF7g6qGnD+YtUG9yx4DFoqCShNMmUKiXuT5oWMHiOvt/4WFbHC6yCwQMTSBMno7AqntNCAzzcnnjowRkTL9eQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.0.1", @@ -11891,6 +12486,7 @@ "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -11901,6 +12497,7 @@ "integrity": "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "mime-db": "^1.53.0" }, @@ -11927,7 +12524,8 @@ "url": "https://feross.org/support" } ], - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/external-editor": { "version": "3.1.0", @@ -11962,6 +12560,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -11978,6 +12577,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -12007,9 +12607,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.4.tgz", - "integrity": "sha512-G3iTQw1DizJQ5eEqj1CbFCWhq+pzum7qepkxU7rS1FGZDqjYKcrguo9XDRbV7EgPnn8CgaPigTq+NEjyioeYZQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", + "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", "dev": true, "funding": [ { @@ -12134,6 +12734,7 @@ "integrity": "sha512-MX6Zo2adDViYh+GcxxB1dpO43eypOGUOL12rLCOTMQv/DfIbpSJUy4oQIIZhVZkH9e+bZWKMon0XHFEju16tkQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -12153,6 +12754,7 @@ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8" } @@ -12163,6 +12765,7 @@ "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "common-path-prefix": "^3.0.0", "pkg-dir": "^7.0.0" @@ -12233,14 +12836,14 @@ "license": "ISC" }, "node_modules/folder-hash": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/folder-hash/-/folder-hash-4.1.0.tgz", - "integrity": "sha512-45DBqW/wE1FdEynQ922zoKsICdAkZEkuyWijChitENaoI+AF/FsTlKOB+EwaEqhNfBZ5dEgLVv694wbpNMIC5g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/folder-hash/-/folder-hash-4.1.1.tgz", + "integrity": "sha512-1ZSlKJSbET3XpglnEXC9g+QF4QRZhqHIjpFfa4pAMfO4tu/XYPafpeHEX6zOFS2EolOIXr0lPh1eSjmdWItX2w==", "dev": true, "license": "MIT", "dependencies": { "debug": "4.4.0", - "minimatch": "10.0.1" + "minimatch": "7.4.6" }, "bin": { "folder-hash": "bin/folder-hash" @@ -12250,16 +12853,16 @@ } }, "node_modules/folder-hash/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", + "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": "20 || >=22" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -12324,6 +12927,7 @@ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -12334,6 +12938,7 @@ "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": "*" }, @@ -12361,6 +12966,7 @@ "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8" } @@ -12665,6 +13271,7 @@ "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", "fast-glob": "^3.3.2", @@ -12686,6 +13293,7 @@ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 4" } @@ -12747,7 +13355,8 @@ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/has-flag": { "version": "4.0.0", @@ -12823,16 +13432,16 @@ "license": "MIT" }, "node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.0.2.tgz", + "integrity": "sha512-sYKnA7eGln5ov8T8gnYlkSOxFJvywzEx9BueN6xo/GKO8PGiI6uK6xx+DIGe45T3bdVjLAQDQW1aicT8z8JwQg==", "dev": true, "license": "ISC", "dependencies": { "lru-cache": "^10.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/hosted-git-info/node_modules/lru-cache": { @@ -12848,6 +13457,7 @@ "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "inherits": "^2.0.1", "obuf": "^1.0.0", @@ -12882,9 +13492,9 @@ "license": "MIT" }, "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", "dev": true, "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", @@ -12897,8 +13507,8 @@ "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" + "domutils": "^3.1.0", + "entities": "^4.5.0" } }, "node_modules/http-cache-semantics": { @@ -12913,7 +13523,8 @@ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/http-errors": { "version": "2.0.0", @@ -12921,6 +13532,7 @@ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -12933,9 +13545,9 @@ } }, "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz", + "integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==", "license": "MIT" }, "node_modules/http-proxy": { @@ -12944,6 +13556,7 @@ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -12973,6 +13586,7 @@ "integrity": "sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/http-proxy": "^1.17.15", "debug": "^4.3.6", @@ -13031,6 +13645,7 @@ "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10.18" } @@ -13054,6 +13669,7 @@ "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", "dev": true, "license": "ISC", + "peer": true, "engines": { "node": "^10 || ^12 || >= 14" }, @@ -13093,16 +13709,16 @@ } }, "node_modules/ignore-walk": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.5.tgz", - "integrity": "sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-7.0.0.tgz", + "integrity": "sha512-T4gbf83A4NH95zvhVYZc+qWocBBGlpzUXLPGurJggw/WIOwicfXJChLDP/iBZnN5WqROSu5Bm3hhle4z8a8YGQ==", "dev": true, "license": "ISC", "dependencies": { "minimatch": "^9.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/image-size": { @@ -13112,6 +13728,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "bin": { "image-size": "bin/image-size.js" }, @@ -13248,16 +13865,6 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -13277,13 +13884,13 @@ "license": "ISC" }, "node_modules/ini": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", - "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-5.0.0.tgz", + "integrity": "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/interactjs": { @@ -13324,6 +13931,7 @@ "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 10" } @@ -13341,6 +13949,7 @@ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -13370,6 +13979,7 @@ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "is-docker": "cli.js" }, @@ -13430,6 +14040,7 @@ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "is-docker": "^3.0.0" }, @@ -13453,13 +14064,6 @@ "node": ">=8" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/is-mobile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-4.0.0.tgz", @@ -13472,6 +14076,7 @@ "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=16" }, @@ -13494,6 +14099,7 @@ "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -13507,6 +14113,7 @@ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -13523,7 +14130,8 @@ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/is-stream": { "version": "2.0.1", @@ -13556,7 +14164,8 @@ "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/is-wsl": { "version": "3.1.0", @@ -13564,6 +14173,7 @@ "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "is-inside-container": "^1.0.0" }, @@ -13600,6 +14210,7 @@ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -14459,17 +15070,17 @@ } }, "node_modules/jest-preset-angular": { - "version": "14.4.2", - "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-14.4.2.tgz", - "integrity": "sha512-BYYv0FaTDfBNh8WyA9mpOV3krfw20kurBGK8INZUnv7KZDAWZuQtCET4TwTWxSNQ9jS1OX1+a5weCm/bTDDM1A==", + "version": "14.5.0", + "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-14.5.0.tgz", + "integrity": "sha512-L7eScW3IX5pZi2GRi0/q6Eo58qf76bdK93ozZxOI2gSK2fE+nnSIirkl2zvZ21AiJM5f4IawwBcqBhAPDvOs+Q==", "dev": true, "license": "MIT", "dependencies": { "bs-logger": "^0.2.6", "esbuild-wasm": ">=0.15.13", - "jest-environment-jsdom": "^29.0.0", - "jest-util": "^29.0.0", - "pretty-format": "^29.0.0", + "jest-environment-jsdom": "^29.7.0", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0", "ts-jest": "^29.0.0" }, "engines": { @@ -14483,7 +15094,13 @@ "@angular/core": ">=15.0.0 <20.0.0", "@angular/platform-browser-dynamic": ">=15.0.0 <20.0.0", "jest": "^29.0.0", + "jsdom": ">=20.0.0", "typescript": ">=4.8" + }, + "peerDependenciesMeta": { + "jsdom": { + "optional": true + } } }, "node_modules/jest-preset-angular/node_modules/ansi-styles": { @@ -14896,6 +15513,7 @@ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", + "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -14974,15 +15592,15 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { @@ -14993,13 +15611,13 @@ "license": "MIT" }, "node_modules/json-parse-even-better-errors": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", - "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", + "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", "dev": true, "license": "MIT", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/json-schema-traverse": { @@ -15106,6 +15724,7 @@ "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "source-map-support": "^0.5.5" } @@ -15142,6 +15761,7 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -15172,6 +15792,7 @@ "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "picocolors": "^1.0.0", "shell-quote": "^1.8.1" @@ -15183,6 +15804,7 @@ "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "copy-anything": "^2.0.1", "parse-node-version": "^1.0.1", @@ -15210,6 +15832,7 @@ "integrity": "sha512-MYUxjSQSBUQmowc0l5nPieOYwMzGPUaTzB6inNW/bdPEG9zOL3eAAD1Qw5ZxSPk7we5dMojHwNODYMV1hq4EVg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 18.12.0" }, @@ -15238,6 +15861,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -15253,6 +15877,7 @@ "dev": true, "license": "BSD-3-Clause", "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -15287,6 +15912,7 @@ "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "webpack-sources": "^3.0.0" }, @@ -15368,32 +15994,6 @@ "url": "https://opencollective.com/lint-staged" } }, - "node_modules/lint-staged/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/lint-staged/node_modules/chalk": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", @@ -15417,13 +16017,6 @@ "node": ">=18" } }, - "node_modules/lint-staged/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true, - "license": "MIT" - }, "node_modules/lint-staged/node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -15484,24 +16077,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/listr2": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-truncate": "^4.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/lint-staged/node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -15560,22 +16135,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/lint-staged/node_modules/strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", @@ -15589,28 +16148,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/listr2": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.4.tgz", - "integrity": "sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==", + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", "dev": true, "license": "MIT", "dependencies": { @@ -15693,29 +16234,30 @@ } }, "node_modules/lmdb": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.0.13.tgz", - "integrity": "sha512-UGe+BbaSUQtAMZobTb4nHvFMrmvuAQKSeaqAX2meTEQjfsbpl5sxdHD8T72OnwD4GU9uwNhYXIVe4QGs8N9Zyw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.1.5.tgz", + "integrity": "sha512-46Mch5Drq+A93Ss3gtbg+Xuvf5BOgIuvhKDWoGa3HcPHI6BL2NCOkRdSx1D4VfzwrxhnsjbyIVsLRlQHu6URvw==", "dev": true, "hasInstallScript": true, "license": "MIT", + "optional": true, "dependencies": { - "msgpackr": "^1.10.2", + "msgpackr": "^1.11.2", "node-addon-api": "^6.1.0", "node-gyp-build-optional-packages": "5.2.2", - "ordered-binary": "^1.4.1", + "ordered-binary": "^1.5.3", "weak-lru-cache": "^1.2.2" }, "bin": { "download-lmdb-prebuilds": "bin/download-prebuilds.js" }, "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "3.0.13", - "@lmdb/lmdb-darwin-x64": "3.0.13", - "@lmdb/lmdb-linux-arm": "3.0.13", - "@lmdb/lmdb-linux-arm64": "3.0.13", - "@lmdb/lmdb-linux-x64": "3.0.13", - "@lmdb/lmdb-win32-x64": "3.0.13" + "@lmdb/lmdb-darwin-arm64": "3.1.5", + "@lmdb/lmdb-darwin-x64": "3.1.5", + "@lmdb/lmdb-linux-arm": "3.1.5", + "@lmdb/lmdb-linux-arm64": "3.1.5", + "@lmdb/lmdb-linux-x64": "3.1.5", + "@lmdb/lmdb-win32-x64": "3.1.5" } }, "node_modules/loader-runner": { @@ -15724,6 +16266,7 @@ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6.11.5" } @@ -15734,6 +16277,7 @@ "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 12.13.0" } @@ -15771,7 +16315,8 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.memoize": { "version": "4.1.2", @@ -15973,9 +16518,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dev": true, "license": "MIT", "dependencies": { @@ -16006,27 +16551,26 @@ "license": "ISC" }, "node_modules/make-fetch-happen": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", - "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", + "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "ssri": "^10.0.0" + "ssri": "^12.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/makeerror": { @@ -16099,16 +16643,18 @@ "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8" } }, "node_modules/memfs": { - "version": "4.15.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.15.3.tgz", - "integrity": "sha512-vR/g1SgqvKJgAyYla+06G4p/EOcEmwhYuVb1yc1ixcKf8o/sh7Zngv63957ZSNd1xrZJoinmNyDf2LzuP8WJXw==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.17.0.tgz", + "integrity": "sha512-4eirfZ7thblFmqFjywlTmuWVSvccHAJbn1r8qQLzmTO11qcqpohOjmY2mFce6x7x7WtskzRqApPD0hv+Oa74jg==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@jsonjoy.com/json-pack": "^1.0.3", "@jsonjoy.com/util": "^1.3.0", @@ -16129,6 +16675,7 @@ "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -16158,6 +16705,7 @@ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -16194,6 +16742,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "bin": { "mime": "cli.js" }, @@ -16248,11 +16797,12 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz", - "integrity": "sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", + "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "schema-utils": "^4.0.0", "tapable": "^2.2.1" @@ -16273,7 +16823,8 @@ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true, - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/minimatch": { "version": "9.0.5", @@ -16325,18 +16876,18 @@ } }, "node_modules/minipass-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", - "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.0.tgz", + "integrity": "sha512-2v6aXUXwLP1Epd/gc32HAMIWoczx+fZwEPRHm/VwtrJzRGwR1qGZXEYV3Zp8ZjjbwaZhMrM6uHV4KVkk+XCc2w==", "dev": true, "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "minizlib": "^3.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" }, "optionalDependencies": { "encoding": "^0.1.13" @@ -16442,39 +16993,19 @@ "license": "ISC" }, "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", "dev": true, "license": "MIT", "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" + "minipass": "^7.0.4", + "rimraf": "^5.0.5" }, "engines": { - "node": ">=8" + "node": ">= 18" } }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -16532,6 +17063,7 @@ "integrity": "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==", "dev": true, "license": "MIT", + "optional": true, "optionalDependencies": { "msgpackr-extract": "^3.0.2" } @@ -16565,6 +17097,7 @@ "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "dns-packet": "^5.2.2", "thunky": "^1.0.2" @@ -16574,13 +17107,13 @@ } }, "node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/n-gram": { @@ -16626,6 +17159,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "iconv-lite": "^0.6.3", "sax": "^1.2.4" @@ -16644,6 +17178,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -16652,9 +17187,9 @@ } }, "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "dev": true, "license": "MIT", "engines": { @@ -16666,7 +17201,8 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/ng-mocks": { "version": "14.13.1", @@ -16685,29 +17221,29 @@ } }, "node_modules/ngx-infinite-scroll": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/ngx-infinite-scroll/-/ngx-infinite-scroll-18.0.0.tgz", - "integrity": "sha512-D183TDwpsd9Zl56UmItsl3RzHdN25srAISfg6lc3A8mEKkEgOq0s7ZzRAYcx8DHsAkMgtZqjIPEvMifD3DOB/g==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/ngx-infinite-scroll/-/ngx-infinite-scroll-19.0.0.tgz", + "integrity": "sha512-Ft4xNNDLXoDGi2hF6ylehjxbG8JIgfoL6qDWWcebGMcbh1CEfEsh0HGkDuFlX/cBBMenRh2HFbXlYq8BAtbvLw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": ">=18.0.0 <19.0.0", - "@angular/core": ">=18.0.0 <19.0.0" + "@angular/common": ">=19.0.0 <20.0.0", + "@angular/core": ">=19.0.0 <20.0.0" } }, "node_modules/ngx-webstorage": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/ngx-webstorage/-/ngx-webstorage-18.0.0.tgz", - "integrity": "sha512-Fg9y0Vb89CBSjSmJPjvotZljyqSNo97TlWpR6OIsHzuMwrj7u9OgEBmqOgiRK2GGsUdVMy8SF3s3Ymier6xuew==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/ngx-webstorage/-/ngx-webstorage-19.0.1.tgz", + "integrity": "sha512-5Z7YowQKvmABb2d80AavOo+DSRu+bduxDpDTc7go7clJyMtIwidINa3UC3m13LgkBc8QJj9K8LkY0ugwTmYDdA==", "license": "MIT", "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { - "@angular/common": "^18.0.0", - "@angular/core": "^18.0.0" + "@angular/common": "^19.0.0", + "@angular/core": "^19.0.0" } }, "node_modules/ngxtension": { @@ -16738,6 +17274,13 @@ } } }, + "node_modules/ngxtension/node_modules/@angular-eslint/bundled-angular-compiler": { + "version": "18.4.3", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-18.4.3.tgz", + "integrity": "sha512-zdrA8mR98X+U4YgHzUKmivRU+PxzwOL/j8G7eTOvBuq8GPzsP+hvak+tyxlgeGm9HsvpFj9ERHLtJ0xDUPs8fg==", + "dev": true, + "license": "MIT" + }, "node_modules/ngxtension/node_modules/@ts-morph/common": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.23.0.tgz", @@ -16785,36 +17328,13 @@ "code-block-writer": "^13.0.1" } }, - "node_modules/nice-napi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", - "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "!win32" - ], - "dependencies": { - "node-addon-api": "^3.0.0", - "node-gyp-build": "^4.2.2" - } - }, - "node_modules/nice-napi/node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/node-addon-api": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/node-forge": { "version": "1.3.1", @@ -16822,14 +17342,15 @@ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", "dev": true, "license": "(BSD-3-Clause OR GPL-2.0)", + "peer": true, "engines": { "node": ">= 6.13.0" } }, "node_modules/node-gyp": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.3.1.tgz", - "integrity": "sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.0.0.tgz", + "integrity": "sha512-zQS+9MTTeCMgY0F3cWPyJyRFAkVltQ1uXm+xXu/ES6KFgC6Czo1Seb9vQW2wNxSX2OrDTiqL0ojtkFxBQ0ypIw==", "dev": true, "license": "MIT", "dependencies": { @@ -16837,18 +17358,18 @@ "exponential-backoff": "^3.1.1", "glob": "^10.3.10", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^4.1.0", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", "semver": "^7.3.5", - "tar": "^6.2.1", - "which": "^4.0.0" + "tar": "^7.4.3", + "which": "^5.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/node-gyp-build": { @@ -16869,6 +17390,7 @@ "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "detect-libc": "^2.0.1" }, @@ -16878,6 +17400,16 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, + "node_modules/node-gyp/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/node-gyp/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -16909,10 +17441,44 @@ "node": ">=16" } }, + "node_modules/node-gyp/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/node-gyp/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { @@ -16922,7 +17488,17 @@ "node-which": "bin/which.js" }, "engines": { - "node": "^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/node-gyp/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/node-int64": { @@ -16946,9 +17522,9 @@ "license": "MIT" }, "node_modules/nopt": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", - "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.0.0.tgz", + "integrity": "sha512-1L/fTJ4UmV/lUxT2Uf006pfZKTvAgCF+chz+0OgBHO8u2Z67pE7AaAUUj7CJy0lXqHmymUvGFt6NE9R3HER0yw==", "dev": true, "license": "ISC", "dependencies": { @@ -16958,22 +17534,22 @@ "nopt": "bin/nopt.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/normalize-package-data": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", - "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-7.0.0.tgz", + "integrity": "sha512-k6U0gKRIuNCTkwHGZqblCfLfBRh+w1vI6tBo+IeJwq2M8FUiOqhX7GH+GArQGScA7azd1WfyRCvxoXDO3hQDIA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "hosted-git-info": "^7.0.0", + "hosted-git-info": "^8.0.0", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/normalize-path": { @@ -16992,109 +17568,110 @@ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } }, "node_modules/npm-bundled": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.1.tgz", - "integrity": "sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-4.0.0.tgz", + "integrity": "sha512-IxaQZDMsqfQ2Lz37VvyyEtKLe8FsRZuysmedy/N06TU1RyVppYKXrO4xIhR0F+7ubIBox6Q7nir6fQI3ej39iA==", "dev": true, "license": "ISC", "dependencies": { - "npm-normalize-package-bin": "^3.0.0" + "npm-normalize-package-bin": "^4.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-install-checks": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", - "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-7.1.1.tgz", + "integrity": "sha512-u6DCwbow5ynAX5BdiHQ9qvexme4U3qHW3MWe5NqH+NeBm0LbiH6zvGjNNew1fY+AZZUtVHbOPF3j7mJxbUzpXg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "semver": "^7.1.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-package-arg": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz", - "integrity": "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.0.tgz", + "integrity": "sha512-ZTE0hbwSdTNL+Stx2zxSqdu2KZfNDcrtrLdIk7XGnQFYBWYDho/ORvXtn5XEePcL3tFpGjHCV3X3xrtDh7eZ+A==", "dev": true, "license": "ISC", "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^4.0.0", + "hosted-git-info": "^8.0.0", + "proc-log": "^5.0.0", "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" + "validate-npm-package-name": "^6.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-packlist": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", - "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-9.0.0.tgz", + "integrity": "sha512-8qSayfmHJQTx3nJWYbbUmflpyarbLMBc6LCAjYsiGtXxDB68HaZpb8re6zeaLGxZzDuMdhsg70jryJe+RrItVQ==", "dev": true, "license": "ISC", "dependencies": { - "ignore-walk": "^6.0.4" + "ignore-walk": "^7.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-pick-manifest": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.1.0.tgz", - "integrity": "sha512-nkc+3pIIhqHVQr085X9d2JzPzLyjzQS96zbruppqC9aZRm/x8xx6xhI98gHtsfELP2bE+loHq8ZaHFHhe+NauA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-10.0.0.tgz", + "integrity": "sha512-r4fFa4FqYY8xaM7fHecQ9Z2nE9hgNfJR+EmoKv0+chvzWkBcORX3r0FpTByP+CbOVJDladMXnPQGVN8PBLGuTQ==", "dev": true, "license": "ISC", "dependencies": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^11.0.0", + "npm-install-checks": "^7.1.0", + "npm-normalize-package-bin": "^4.0.0", + "npm-package-arg": "^12.0.0", "semver": "^7.3.5" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-registry-fetch": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-17.1.0.tgz", - "integrity": "sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==", + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-18.0.2.tgz", + "integrity": "sha512-LeVMZBBVy+oQb5R6FDV9OlJCcWDU+al10oKpe+nsvcHnG24Z3uM3SvJYKfGJlfGjVU8v9liejCrUR/M5HO5NEQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/redact": "^2.0.0", + "@npmcli/redact": "^3.0.0", "jsonparse": "^1.3.1", - "make-fetch-happen": "^13.0.0", + "make-fetch-happen": "^14.0.0", "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minizlib": "^2.1.2", - "npm-package-arg": "^11.0.0", - "proc-log": "^4.0.0" + "minipass-fetch": "^4.0.0", + "minizlib": "^3.0.1", + "npm-package-arg": "^12.0.0", + "proc-log": "^5.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-run-path": { @@ -17131,9 +17708,9 @@ "license": "MIT" }, "node_modules/nx": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/nx/-/nx-20.3.0.tgz", - "integrity": "sha512-Nzi4k7tV22zwO2iBLk+pHxorLEWPJpPrVCACtz0SQ63j/LiAgfhoqruJO+VU+V+E9qdyPsvmqIL/Iaf/GRQlqA==", + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/nx/-/nx-20.3.1.tgz", + "integrity": "sha512-pO48DoQAwVKBEF7/od3bc1tHBYfafgiuS/hHX3yGmhpWW58baIlxMWFp6QY9+A9Q0R+26pd6AEGnE7d1f7+i/g==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -17178,16 +17755,16 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "20.3.0", - "@nx/nx-darwin-x64": "20.3.0", - "@nx/nx-freebsd-x64": "20.3.0", - "@nx/nx-linux-arm-gnueabihf": "20.3.0", - "@nx/nx-linux-arm64-gnu": "20.3.0", - "@nx/nx-linux-arm64-musl": "20.3.0", - "@nx/nx-linux-x64-gnu": "20.3.0", - "@nx/nx-linux-x64-musl": "20.3.0", - "@nx/nx-win32-arm64-msvc": "20.3.0", - "@nx/nx-win32-x64-msvc": "20.3.0" + "@nx/nx-darwin-arm64": "20.3.1", + "@nx/nx-darwin-x64": "20.3.1", + "@nx/nx-freebsd-x64": "20.3.1", + "@nx/nx-linux-arm-gnueabihf": "20.3.1", + "@nx/nx-linux-arm64-gnu": "20.3.1", + "@nx/nx-linux-arm64-musl": "20.3.1", + "@nx/nx-linux-x64-gnu": "20.3.1", + "@nx/nx-linux-x64-musl": "20.3.1", + "@nx/nx-win32-arm64-msvc": "20.3.1", + "@nx/nx-win32-x64-msvc": "20.3.1" }, "peerDependencies": { "@swc-node/register": "^1.8.0", @@ -17406,6 +17983,7 @@ "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.4" }, @@ -17428,7 +18006,8 @@ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/on-finished": { "version": "2.4.1", @@ -17436,6 +18015,7 @@ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ee-first": "1.1.1" }, @@ -17449,6 +18029,7 @@ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8" } @@ -17485,6 +18066,7 @@ "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", @@ -17579,7 +18161,8 @@ "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.3.tgz", "integrity": "sha512-oGFr3T+pYdTGJ+YFEILMpS3es+GiIbs9h/XQrclBXUtd44ey7XwfsMzM31f64I1SQOawDoDr/D823kNCADI8TA==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/os-tmpdir": { "version": "1.0.2", @@ -17624,16 +18207,13 @@ } }, "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", "dev": true, "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -17645,6 +18225,7 @@ "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/retry": "0.12.2", "is-network-error": "^1.0.0", @@ -17663,6 +18244,7 @@ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 4" } @@ -17685,35 +18267,35 @@ "license": "BlueOak-1.0.0" }, "node_modules/pacote": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-18.0.6.tgz", - "integrity": "sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-20.0.0.tgz", + "integrity": "sha512-pRjC5UFwZCgx9kUFDVM9YEahv4guZ1nSLqwmWiLUnDbGsjs+U5w7z6Uc8HNR1a6x8qnu5y9xtGE6D1uAuYz+0A==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/git": "^5.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/package-json": "^5.1.0", - "@npmcli/promise-spawn": "^7.0.0", - "@npmcli/run-script": "^8.0.0", - "cacache": "^18.0.0", + "@npmcli/git": "^6.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "@npmcli/run-script": "^9.0.0", + "cacache": "^19.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", - "npm-package-arg": "^11.0.0", - "npm-packlist": "^8.0.0", - "npm-pick-manifest": "^9.0.0", - "npm-registry-fetch": "^17.0.0", - "proc-log": "^4.0.0", + "npm-package-arg": "^12.0.0", + "npm-packlist": "^9.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^18.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "sigstore": "^2.2.0", - "ssri": "^10.0.0", + "sigstore": "^3.0.0", + "ssri": "^12.0.0", "tar": "^6.1.11" }, "bin": { "pacote": "bin/index.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/pako": { @@ -17723,9 +18305,9 @@ "license": "(MIT AND Zlib)" }, "node_modules/papaparse": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz", - "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.5.1.tgz", + "integrity": "sha512-EuEKUhyxrHVozD7g3/ztsJn6qaKse8RPfR6buNB2dMJvdtXNhcw8jccVi/LxNEY3HVrV6GO6Z4OoeCG9Iy9wpA==", "license": "MIT" }, "node_modules/parent-module": { @@ -17780,6 +18362,7 @@ "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.10" } @@ -17831,6 +18414,7 @@ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8" } @@ -17996,6 +18580,7 @@ "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=16" } @@ -18006,6 +18591,7 @@ "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -18105,6 +18691,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">=6" } @@ -18120,13 +18707,13 @@ } }, "node_modules/piscina": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.6.1.tgz", - "integrity": "sha512-z30AwWGtQE+Apr+2WBZensP2lIvwoaMcOPkQlIEmSGMJNUvaYACylPYrQM6wSdUNJlnDVMSpLv7xTMJqlVshOA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.7.0.tgz", + "integrity": "sha512-b8hvkpp9zS0zsfa939b/jXbe64Z2gZv0Ha7FYPNUiDIB1y2AtxcOZdfP8xN8HFjUaqQiT9gRlfjAsoL8vdJ1Iw==", "dev": true, "license": "MIT", "optionalDependencies": { - "nice-napi": "^1.0.2" + "@napi-rs/nice": "^1.0.1" } }, "node_modules/pkg-dir": { @@ -18135,6 +18722,7 @@ "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "find-up": "^6.3.0" }, @@ -18151,6 +18739,7 @@ "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "locate-path": "^7.1.0", "path-exists": "^5.0.0" @@ -18168,6 +18757,7 @@ "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "p-locate": "^6.0.0" }, @@ -18184,6 +18774,7 @@ "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "yocto-queue": "^1.0.0" }, @@ -18200,6 +18791,7 @@ "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "p-limit": "^4.0.0" }, @@ -18216,6 +18808,7 @@ "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } @@ -18226,6 +18819,7 @@ "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12.20" }, @@ -18268,6 +18862,7 @@ "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cosmiconfig": "^9.0.0", "jiti": "^1.20.0", @@ -18307,6 +18902,7 @@ "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", "dev": true, "license": "ISC", + "peer": true, "engines": { "node": "^10 || ^12 || >= 14" }, @@ -18320,6 +18916,7 @@ "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^7.0.0", @@ -18338,6 +18935,7 @@ "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "postcss-selector-parser": "^7.0.0" }, @@ -18354,6 +18952,7 @@ "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "icss-utils": "^5.0.0" }, @@ -18370,6 +18969,7 @@ "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -18462,13 +19062,13 @@ "peer": true }, "node_modules/proc-log": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", - "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/process-nextick-args": { @@ -18535,6 +19135,7 @@ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -18549,6 +19150,7 @@ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.10" } @@ -18566,7 +19168,8 @@ "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/punycode": { "version": "2.3.1", @@ -18610,6 +19213,7 @@ "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "dependencies": { "side-channel": "^1.0.6" }, @@ -18652,6 +19256,7 @@ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -18662,6 +19267,7 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -18672,6 +19278,7 @@ "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -18688,6 +19295,7 @@ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -18847,29 +19455,16 @@ "license": "MIT" }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">= 14.16.0" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/redux": { @@ -18910,7 +19505,8 @@ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/regenerate-unicode-properties": { "version": "10.2.0", @@ -18918,6 +19514,7 @@ "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "regenerate": "^1.4.2" }, @@ -18937,6 +19534,7 @@ "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.8.4" } @@ -18946,7 +19544,8 @@ "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz", "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/regexpu-core": { "version": "6.2.0", @@ -18954,6 +19553,7 @@ "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.0", @@ -18971,7 +19571,8 @@ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/regjsparser": { "version": "0.12.0", @@ -18979,6 +19580,7 @@ "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "jsesc": "~3.0.2" }, @@ -18992,6 +19594,7 @@ "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, "license": "MIT", + "peer": true, "bin": { "jsesc": "bin/jsesc" }, @@ -19081,6 +19684,7 @@ "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "adjust-sourcemap-loader": "^4.0.0", "convert-source-map": "^1.7.0", @@ -19098,6 +19702,7 @@ "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -19113,6 +19718,7 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -19208,9 +19814,9 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", - "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", + "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", "dev": true, "license": "ISC", "dependencies": { @@ -19291,13 +19897,13 @@ } }, "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.26.0.tgz", + "integrity": "sha512-ilcl12hnWonG8f+NxU6BlgysVA0gvY2l8N0R84S1HcINbW20bvwuCngJkkInV6LXhwRpucsW5k1ovDwEdBVrNg==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -19307,38 +19913,34 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", + "@rollup/rollup-android-arm-eabi": "4.26.0", + "@rollup/rollup-android-arm64": "4.26.0", + "@rollup/rollup-darwin-arm64": "4.26.0", + "@rollup/rollup-darwin-x64": "4.26.0", + "@rollup/rollup-freebsd-arm64": "4.26.0", + "@rollup/rollup-freebsd-x64": "4.26.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.26.0", + "@rollup/rollup-linux-arm-musleabihf": "4.26.0", + "@rollup/rollup-linux-arm64-gnu": "4.26.0", + "@rollup/rollup-linux-arm64-musl": "4.26.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.26.0", + "@rollup/rollup-linux-riscv64-gnu": "4.26.0", + "@rollup/rollup-linux-s390x-gnu": "4.26.0", + "@rollup/rollup-linux-x64-gnu": "4.26.0", + "@rollup/rollup-linux-x64-musl": "4.26.0", + "@rollup/rollup-win32-arm64-msvc": "4.26.0", + "@rollup/rollup-win32-ia32-msvc": "4.26.0", + "@rollup/rollup-win32-x64-msvc": "4.26.0", "fsevents": "~2.3.2" } }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "license": "MIT" - }, "node_modules/router": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/router/-/router-2.0.0.tgz", "integrity": "sha512-dIM5zVoG8xhC6rnSN8uoAgFARwTE7BQs8YwHEvK0VCmfxQXMaOuA1uiR1IPwsW7JyK5iTt7Od/TC9StasS2NPQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "array-flatten": "3.0.0", "is-promise": "4.0.0", @@ -19365,6 +19967,7 @@ "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -19439,11 +20042,12 @@ } }, "node_modules/sass-loader": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.0.tgz", - "integrity": "sha512-n13Z+3rU9A177dk4888czcVFiC8CL9dii4qpXWUg3YIIgZEvi9TCFKjOQcbK0kJM7DJu9VucrZFddvNfYCPwtw==", + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.3.tgz", + "integrity": "sha512-gosNorT1RCkuCMyihv6FBRR7BMV06oKRAs+l4UMp1mlcVg9rWN6KMmUj3igjQwmYys4mDP3etEYJgiHRbgHCHA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "neo-async": "^2.6.2" }, @@ -19479,43 +20083,14 @@ } } }, - "node_modules/sass/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/sass/node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/sax": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", "dev": true, "license": "ISC", - "optional": true + "optional": true, + "peer": true }, "node_modules/saxes": { "version": "6.0.0", @@ -19545,6 +20120,7 @@ "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -19565,6 +20141,7 @@ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ajv": "^8.0.0" }, @@ -19582,7 +20159,8 @@ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/selfsigned": { "version": "2.4.1", @@ -19590,6 +20168,7 @@ "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node-forge": "^1.3.0", "node-forge": "^1" @@ -19616,6 +20195,7 @@ "integrity": "sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "debug": "^4.3.5", "destroy": "^1.2.0", @@ -19640,6 +20220,7 @@ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -19650,6 +20231,7 @@ "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "dependencies": { "randombytes": "^2.1.0" } @@ -19660,6 +20242,7 @@ "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "accepts": "~1.3.4", "batch": "0.6.1", @@ -19679,6 +20262,7 @@ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -19693,6 +20277,7 @@ "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -19703,6 +20288,7 @@ "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -19718,7 +20304,8 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", "dev": true, - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/serve-index/node_modules/negotiator": { "version": "0.6.3", @@ -19726,6 +20313,7 @@ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -19735,7 +20323,8 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true, - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/serve-index/node_modules/statuses": { "version": "1.5.0", @@ -19743,6 +20332,7 @@ "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -19753,6 +20343,7 @@ "integrity": "sha512-A3We5UfEjG8Z7VkDv6uItWw6HY2bBSBJT1KtVESn6EOoOr2jAxNhxWCLY3jDE2WcuHXByWju74ck3ZgLwL8xmA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", @@ -19803,7 +20394,8 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true, - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/shallow-clone": { "version": "3.0.1", @@ -19811,6 +20403,7 @@ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "kind-of": "^6.0.2" }, @@ -19853,6 +20446,7 @@ "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.4" }, @@ -19866,6 +20460,7 @@ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", @@ -19886,6 +20481,7 @@ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" @@ -19903,6 +20499,7 @@ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -19922,6 +20519,7 @@ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -19957,21 +20555,21 @@ } }, "node_modules/sigstore": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.3.1.tgz", - "integrity": "sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-3.0.0.tgz", + "integrity": "sha512-PHMifhh3EN4loMcHCz6l3v/luzgT3za+9f8subGgeMNjbJjzH4Ij/YoX3Gvu+kaouJRIlVdTHHCREADYf+ZteA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", "@sigstore/protobuf-specs": "^0.3.2", - "@sigstore/sign": "^2.3.2", - "@sigstore/tuf": "^2.3.4", - "@sigstore/verify": "^1.2.1" + "@sigstore/sign": "^3.0.0", + "@sigstore/tuf": "^3.0.0", + "@sigstore/verify": "^2.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/simple-statistics": { @@ -19996,6 +20594,7 @@ "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=14.16" }, @@ -20056,6 +20655,7 @@ "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "faye-websocket": "^0.11.3", "uuid": "^8.3.2", @@ -20087,6 +20687,7 @@ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -20147,6 +20748,7 @@ "integrity": "sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "iconv-lite": "^0.6.3", "source-map-js": "^1.0.2" @@ -20168,6 +20770,7 @@ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -20181,6 +20784,7 @@ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -20192,6 +20796,7 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -20238,6 +20843,7 @@ "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "debug": "^4.1.0", "handle-thing": "^2.0.0", @@ -20255,6 +20861,7 @@ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "debug": "^4.1.0", "detect-node": "^2.0.4", @@ -20270,6 +20877,7 @@ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -20293,16 +20901,16 @@ "license": "BSD-3-Clause" }, "node_modules/ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/stack-utils": { @@ -20341,6 +20949,7 @@ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8" } @@ -20641,6 +21250,7 @@ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6" } @@ -20731,6 +21341,33 @@ "node": ">=8" } }, + "node_modules/tar/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tar/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -20739,11 +21376,12 @@ "license": "ISC" }, "node_modules/terser": { - "version": "5.31.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz", - "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==", + "version": "5.36.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", + "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -20763,6 +21401,7 @@ "integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -20798,6 +21437,7 @@ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -20813,6 +21453,7 @@ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -20828,7 +21469,8 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/test-exclude": { "version": "6.0.0", @@ -20875,6 +21517,7 @@ "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", "dev": true, "license": "Unlicense", + "peer": true, "engines": { "node": ">=10.18" }, @@ -20887,7 +21530,8 @@ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/tinybench": { "version": "2.9.0", @@ -20950,22 +21594,22 @@ } }, "node_modules/tldts": { - "version": "6.1.70", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.70.tgz", - "integrity": "sha512-/W1YVgYVJd9ZDjey5NXadNh0mJXkiUMUue9Zebd0vpdo1sU+H4zFFTaJ1RKD4N6KFoHfcXy6l+Vu7bh+bdWCzA==", + "version": "6.1.71", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.71.tgz", + "integrity": "sha512-LQIHmHnuzfZgZWAf2HzL83TIIrD8NhhI0DVxqo9/FdOd4ilec+NTNZOlDZf7EwrTNoutccbsHjvWHYXLAtvxjw==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.70" + "tldts-core": "^6.1.71" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.70", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.70.tgz", - "integrity": "sha512-RNnIXDB1FD4T9cpQRErEqw6ZpjLlGdMOitdV+0xtbsnwr4YFka1zpc7D4KD+aAn8oSG5JyFrdasZTE04qDE9Yg==", + "version": "6.1.71", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.71.tgz", + "integrity": "sha512-LRbChn2YRpic1KxY+ldL1pGXN/oVvKfCVufwfVzEQdFYNo39uF7AJa/WXdo+gYO7PTvdfkCPCed6Hkvz/kR7jg==", "dev": true, "license": "MIT" }, @@ -21007,6 +21651,7 @@ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.6" } @@ -21052,6 +21697,7 @@ "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", "dev": true, "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=10.0" }, @@ -21069,6 +21715,7 @@ "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, "license": "MIT", + "peer": true, "bin": { "tree-kill": "cli.js" } @@ -21088,16 +21735,16 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", + "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/ts-cacheable": { @@ -21289,18 +21936,18 @@ "license": "0BSD" }, "node_modules/tuf-js": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.1.tgz", - "integrity": "sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-3.0.1.tgz", + "integrity": "sha512-+68OP1ZzSF84rTckf3FA95vJ1Zlx/uaXyiiKyPd1pA4rZNkpEvDAKmsu1xUSmbF/chCRYgZ6UZkDwC7PmzmAyA==", "dev": true, "license": "MIT", "dependencies": { - "@tufjs/models": "2.0.1", - "debug": "^4.3.4", - "make-fetch-happen": "^13.0.1" + "@tufjs/models": "3.0.1", + "debug": "^4.3.6", + "make-fetch-happen": "^14.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/turndown": { @@ -21354,6 +22001,7 @@ "integrity": "sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", @@ -21369,6 +22017,7 @@ "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -21379,6 +22028,7 @@ "integrity": "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "mime-db": "^1.53.0" }, @@ -21391,12 +22041,13 @@ "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -21416,15 +22067,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.19.0.tgz", - "integrity": "sha512-Ni8sUkVWYK4KAcTtPjQ/UTiRk6jcsuDhPpxULapUDi8A/l8TSBk+t1GtJA1RsCzIJg0q6+J7bf35AwQigENWRQ==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.19.1.tgz", + "integrity": "sha512-LKPUQpdEMVOeKluHi8md7rwLcoXHhwvWp3x+sJkMuq3gGm9yaYJtPo8sRZSblMFJ5pcOGCAak/scKf1mvZDlQw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.19.0", - "@typescript-eslint/parser": "8.19.0", - "@typescript-eslint/utils": "8.19.0" + "@typescript-eslint/eslint-plugin": "8.19.1", + "@typescript-eslint/parser": "8.19.1", + "@typescript-eslint/utils": "8.19.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -21472,6 +22123,7 @@ "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=4" } @@ -21482,6 +22134,7 @@ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -21496,6 +22149,7 @@ "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=4" } @@ -21506,6 +22160,7 @@ "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=4" } @@ -21516,6 +22171,7 @@ "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -21524,29 +22180,29 @@ } }, "node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^4.0.0" + "unique-slug": "^5.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/unist-util-stringify-position": { @@ -21579,14 +22235,15 @@ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8" } }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", "funding": [ { "type": "opencollective", @@ -21604,7 +22261,7 @@ "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -21654,14 +22311,15 @@ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.4.0" } }, "node_modules/uuid": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.4.tgz", - "integrity": "sha512-IzL6VtTTYcAhA/oghbFJ1Dkmqev+FpQWnCBaKq/gUluLxliWvO8DPFWfIviRmYbtaavtSQe4WBL++rFjdcGWEg==", + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", + "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -21712,13 +22370,13 @@ } }, "node_modules/validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.0.tgz", + "integrity": "sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/vary": { @@ -21727,6 +22385,7 @@ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8" } @@ -22360,16 +23019,6 @@ } } }, - "node_modules/vitest/node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", @@ -22394,9 +23043,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dev": true, "license": "MIT", "dependencies": { @@ -22413,6 +23062,7 @@ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "minimalistic-assert": "^1.0.0" } @@ -22432,7 +23082,8 @@ "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/weak-napi": { "version": "2.0.2", @@ -22520,19 +23171,20 @@ } }, "node_modules/webpack": { - "version": "5.94.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", - "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "version": "5.96.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", + "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@types/estree": "^1.0.5", + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", "@webassemblyjs/ast": "^1.12.1", "@webassemblyjs/wasm-edit": "^1.12.1", "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", @@ -22572,6 +23224,7 @@ "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "colorette": "^2.0.10", "memfs": "^4.6.0", @@ -22602,6 +23255,7 @@ "integrity": "sha512-90SqqYXA2SK36KcT6o1bvwvZfJFcmoamqeJY7+boioffX9g9C0wjjJRGUrQIuh43pb0ttX7+ssavmj/WN2RHtA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", @@ -22653,12 +23307,53 @@ } } }, + "node_modules/webpack-dev-server/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/webpack-dev-server/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/http-proxy": "^1.17.8", "http-proxy": "^1.18.1", @@ -22678,12 +23373,41 @@ } } }, + "node_modules/webpack-dev-server/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/webpack-dev-server/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/webpack-merge": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", @@ -22699,6 +23423,7 @@ "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10.13.0" } @@ -22709,6 +23434,7 @@ "integrity": "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "typed-assert": "^1.0.8" }, @@ -22731,6 +23457,7 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -22748,6 +23475,7 @@ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, "license": "MIT", + "peer": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -22758,6 +23486,7 @@ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -22772,6 +23501,7 @@ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "engines": { "node": ">=4.0" } @@ -22781,14 +23511,16 @@ "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, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/webpack/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, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/webpack/node_modules/schema-utils": { "version": "3.3.0", @@ -22796,6 +23528,7 @@ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -22926,7 +23659,8 @@ "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/word-wrap": { "version": "1.2.5", @@ -23243,9 +23977,9 @@ } }, "node_modules/zone.js": { - "version": "0.14.10", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.10.tgz", - "integrity": "sha512-YGAhaO7J5ywOXW6InXNlLmfU194F8lVgu7bRntUF3TiG8Y3nBK0x1UJJuHUP/e8IyihkjCYqhCScpSwnlaSRkQ==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.0.tgz", + "integrity": "sha512-9oxn0IIjbCZkJ67L+LkhYWRyAy7axphb3VgE2MBDlOqnmHMPWGYMxJxBYFueFq/JGY2GMwS0rU+UCLunEmy5UA==", "license": "MIT" } } diff --git a/package.json b/package.json index d392de262aa4..957b769bdc7b 100644 --- a/package.json +++ b/package.json @@ -13,30 +13,30 @@ "node_modules" ], "dependencies": { - "@angular/animations": "18.2.13", - "@angular/cdk": "18.2.14", - "@angular/common": "18.2.13", - "@angular/compiler": "18.2.13", - "@angular/core": "18.2.13", - "@angular/forms": "18.2.13", - "@angular/localize": "18.2.13", - "@angular/material": "18.2.14", - "@angular/platform-browser": "18.2.13", - "@angular/platform-browser-dynamic": "18.2.13", - "@angular/router": "18.2.13", - "@angular/service-worker": "18.2.13", + "@angular/animations": "19.0.6", + "@angular/cdk": "19.0.5", + "@angular/common": "19.0.6", + "@angular/compiler": "19.0.6", + "@angular/core": "19.0.6", + "@angular/forms": "19.0.6", + "@angular/localize": "19.0.6", + "@angular/material": "19.0.5", + "@angular/platform-browser": "19.0.6", + "@angular/platform-browser-dynamic": "19.0.6", + "@angular/router": "19.0.6", + "@angular/service-worker": "19.0.6", "@ctrl/ngx-emoji-mart": "9.2.0", - "@danielmoncada/angular-datetime-picker": "18.1.0", + "@danielmoncada/angular-datetime-picker": "19.0.0", "@fingerprintjs/fingerprintjs": "4.5.1", - "@fortawesome/angular-fontawesome": "0.15.0", + "@fortawesome/angular-fontawesome": "1.0.0", "@fortawesome/fontawesome-svg-core": "6.7.2", "@fortawesome/free-regular-svg-icons": "6.7.2", "@fortawesome/free-solid-svg-icons": "6.7.2", "@ls1intum/apollon": "3.3.15", - "@ng-bootstrap/ng-bootstrap": "17.0.1", + "@ng-bootstrap/ng-bootstrap": "18.0.0", "@ngx-translate/core": "16.0.4", "@ngx-translate/http-loader": "16.0.1", - "@sentry/angular": "8.47.0", + "@sentry/angular": "8.48.0", "@siemens/ngx-datatable": "22.4.1", "@swimlane/ngx-charts": "21.1.2", "@swimlane/ngx-graph": "9.0.1", @@ -44,7 +44,7 @@ "@vscode/markdown-it-katex": "1.1.1", "bootstrap": "5.3.3", "compare-versions": "6.1.1", - "core-js": "3.39.0", + "core-js": "3.40.0", "crypto-js": "4.2.0", "dayjs": "1.11.13", "diff-match-patch-typescript": "1.1.0", @@ -64,9 +64,9 @@ "markdown-it-highlightjs": "4.2.0", "mobile-drag-drop": "3.0.0-rc.0", "monaco-editor": "0.52.2", - "ngx-infinite-scroll": "18.0.0", - "ngx-webstorage": "18.0.0", - "papaparse": "5.4.1", + "ngx-infinite-scroll": "19.0.0", + "ngx-webstorage": "19.0.1", + "papaparse": "5.5.1", "pdf-lib": "1.17.1", "pdfjs-dist": "4.10.38", "rxjs": "7.8.1", @@ -77,12 +77,33 @@ "ts-cacheable": "1.0.10", "tslib": "2.8.1", "turndown": "7.2.0", - "uuid": "11.0.4", + "uuid": "11.0.5", "webstomp-client": "1.2.6", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz", - "zone.js": "0.14.10" + "zone.js": "0.15.0" }, "overrides": { + "@angular-builders/jest": { + "@angular-devkit/build-angular": "^19.0.0", + "@angular/compiler-cli": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/platform-browser-dynamic": "^19.0.0" + }, + "@swimlane/ngx-charts": { + "@angular/animations": "^19.0.0", + "@angular/cdk": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/common": "^19.0.0", + "@angular/forms": "^19.0.0", + "@angular/platform-browser": "^19.0.0", + "@angular/platform-browser-dynamic": "^19.0.0" + }, + "@swimlane/ngx-graph": { + "@angular/animations": "^19.0.0", + "@angular/common": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/cdk": "^19.0.0" + }, "@typescript-eslint/utils": { "eslint": "^9.17.0" }, @@ -95,6 +116,12 @@ }, "express": "5.0.1", "jsdom": "25.0.1", + "ng-mocks": { + "@angular/common": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/forms": "^19.0.0", + "@angular/platform-browser": "^19.0.0" + }, "postcss": "8.4.49", "rimraf": "6.0.1", "semver": "7.6.3", @@ -107,21 +134,21 @@ "yargs-parser": "21.1.1" }, "devDependencies": { - "@analogjs/vite-plugin-angular": "1.11.0", - "@angular-builders/jest": "18.0.0", - "@angular-devkit/build-angular": "18.2.12", - "@angular-eslint/builder": "18.4.3", - "@angular-eslint/eslint-plugin": "18.4.3", - "@angular-eslint/eslint-plugin-template": "18.4.3", - "@angular-eslint/schematics": "18.4.3", - "@angular-eslint/template-parser": "18.4.3", - "@angular/cli": "18.2.12", - "@angular/compiler-cli": "18.2.13", - "@angular/language-service": "18.2.13", - "@sentry/types": "8.47.0", + "@analogjs/vite-plugin-angular": "1.12.0", + "@angular-builders/jest": "19.0.0", + "@angular-eslint/builder": "19.0.2", + "@angular-eslint/eslint-plugin": "19.0.2", + "@angular-eslint/eslint-plugin-template": "19.0.2", + "@angular-eslint/schematics": "19.0.2", + "@angular-eslint/template-parser": "19.0.2", + "@angular/build": "19.0.7", + "@angular/cli": "19.0.7", + "@angular/compiler-cli": "19.0.6", + "@angular/language-service": "19.0.6", + "@sentry/types": "8.48.0", "@testing-library/angular": "17.3.5", "@types/crypto-js": "4.2.2", - "@types/d3-shape": "3.1.6", + "@types/d3-shape": "3.1.7", "@types/dompurify": "3.0.5", "@types/emoji-js": "3.5.2", "@types/jest": "29.5.14", @@ -133,15 +160,15 @@ "@types/sockjs-client": "1.5.4", "@types/turndown": "5.0.5", "@types/uuid": "10.0.0", - "@typescript-eslint/eslint-plugin": "8.19.0", - "@typescript-eslint/parser": "8.19.0", + "@typescript-eslint/eslint-plugin": "8.19.1", + "@typescript-eslint/parser": "8.19.1", "eslint": "9.17.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-deprecation": "3.0.0", "eslint-plugin-jest": "28.10.0", "eslint-plugin-jest-extended": "2.4.0", "eslint-plugin-prettier": "5.2.1", - "folder-hash": "4.1.0", + "folder-hash": "4.1.1", "husky": "9.1.7", "jest": "29.7.0", "jest-canvas-mock": "2.5.2", @@ -149,7 +176,7 @@ "jest-extended": "4.0.2", "jest-fail-on-console": "3.3.1", "jest-junit": "16.0.0", - "jest-preset-angular": "14.4.2", + "jest-preset-angular": "14.5.0", "lint-staged": "15.3.0", "ng-mocks": "14.13.1", "ngxtension": "4.2.0", @@ -158,8 +185,8 @@ "rimraf": "6.0.1", "sass": "1.83.1", "ts-jest": "29.2.5", - "typescript": "5.5.4", - "typescript-eslint": "8.19.0", + "typescript": "5.6.3", + "typescript-eslint": "8.19.1", "vite-tsconfig-paths": "5.1.4", "vitest": "2.1.8", "weak-napi": "2.0.2" diff --git a/patches/ng-mocks+14.13.1.patch b/patches/ng-mocks+14.13.1.patch new file mode 100644 index 000000000000..2a370550a707 --- /dev/null +++ b/patches/ng-mocks+14.13.1.patch @@ -0,0 +1,16 @@ +diff --git a/node_modules/ng-mocks/index.js b/node_modules/ng-mocks/index.js +index e49d71d..049e8ed 100644 +--- a/node_modules/ng-mocks/index.js ++++ b/node_modules/ng-mocks/index.js +@@ -1,2 +1,2 @@ +-!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@angular/core"),require("@angular/core/testing"),require("@angular/forms"),require("@angular/common"),require("@angular/platform-browser"));else if("function"==typeof define&&define.amd)define(["@angular/core","@angular/core/testing","@angular/forms","@angular/common","@angular/platform-browser"],t);else{var r="object"==typeof exports?t(require("@angular/core"),require("@angular/core/testing"),require("@angular/forms"),require("@angular/common"),require("@angular/platform-browser")):t(e["@angular/core"],e["@angular/core/testing"],e["@angular/forms"],e["@angular/common"],e["@angular/platform-browser"]);for(var n in r)("object"==typeof exports?exports:e)[n]=r[n]}}(this,(function(__WEBPACK_EXTERNAL_MODULE__860__,__WEBPACK_EXTERNAL_MODULE__2603__,__WEBPACK_EXTERNAL_MODULE__7182__,__WEBPACK_EXTERNAL_MODULE__4358__,__WEBPACK_EXTERNAL_MODULE__1165__){return function(){"use strict";var __webpack_modules__={5170:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r);var o=Object.getOwnPropertyDescriptor(t,r);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),o=this&&this.__exportStar||function(e,t){for(var r in e)"default"===r||Object.prototype.hasOwnProperty.call(t,r)||n(t,e,r)};Object.defineProperty(t,"__esModule",{value:!0}),t.MockRenderFactory=t.MockRender=t.ngMocks=t.MockService=t.MockProviders=t.MockProvider=t.MockDeclarations=t.MockDeclaration=t.MockedPipe=t.MockPipes=t.MockPipe=t.MockedDirective=t.MockDirectives=t.MockDirective=t.MockedComponent=t.MockComponents=t.MockComponent=t.MockedModule=t.MockModule=t.IMockBuilderProvider=t.IMockBuilderResult=t.IMockBuilderConfigModule=t.IMockBuilderConfigDirective=t.IMockBuilderConfigComponent=t.IMockBuilderConfigAll=t.IMockBuilderConfig=t.IMockBuilderExtended=t.IMockBuilder=t.MockBuilder=t.MockReset=t.MockInstance=t.LegacyControlValueAccessor=t.MockValidator=t.MockControlValueAccessor=t.Mock=t.isNgInjectionToken=t.isNgDef=t.isMockedNgDefOf=t.isMockValidator=t.isMockOf=t.isMockNgDef=t.isMockControlValueAccessor=t.getSourceOfMock=t.getMockedNgDefOf=t.getInjection=t.getTestBedInjection=void 0,r(7592),r(4081),o(r(1763),t);var a=r(6456);Object.defineProperty(t,"getTestBedInjection",{enumerable:!0,get:function(){return a.getTestBedInjection}}),Object.defineProperty(t,"getInjection",{enumerable:!0,get:function(){return a.getInjection}});var i=r(5590);Object.defineProperty(t,"getMockedNgDefOf",{enumerable:!0,get:function(){return i.getMockedNgDefOf}});var l=r(6739);Object.defineProperty(t,"getSourceOfMock",{enumerable:!0,get:function(){return l.getSourceOfMock}});var u=r(7105);Object.defineProperty(t,"isMockControlValueAccessor",{enumerable:!0,get:function(){return u.isMockControlValueAccessor}});var f=r(6763);Object.defineProperty(t,"isMockNgDef",{enumerable:!0,get:function(){return f.isMockNgDef}});var c=r(7675);Object.defineProperty(t,"isMockOf",{enumerable:!0,get:function(){return c.isMockOf}});var d=r(2650);Object.defineProperty(t,"isMockValidator",{enumerable:!0,get:function(){return d.isMockValidator}});var s=r(732);Object.defineProperty(t,"isMockedNgDefOf",{enumerable:!0,get:function(){return s.isMockedNgDefOf}});var v=r(5974);Object.defineProperty(t,"isNgDef",{enumerable:!0,get:function(){return v.isNgDef}});var p=r(4152);Object.defineProperty(t,"isNgInjectionToken",{enumerable:!0,get:function(){return p.isNgInjectionToken}});var h=r(1946);Object.defineProperty(t,"Mock",{enumerable:!0,get:function(){return h.Mock}});var y=r(5980);Object.defineProperty(t,"MockControlValueAccessor",{enumerable:!0,get:function(){return y.MockControlValueAccessor}}),Object.defineProperty(t,"MockValidator",{enumerable:!0,get:function(){return y.MockValidator}}),Object.defineProperty(t,"LegacyControlValueAccessor",{enumerable:!0,get:function(){return y.LegacyControlValueAccessor}});var _=r(3001);Object.defineProperty(t,"MockInstance",{enumerable:!0,get:function(){return _.MockInstance}}),Object.defineProperty(t,"MockReset",{enumerable:!0,get:function(){return _.MockReset}});var g=r(3771);Object.defineProperty(t,"MockBuilder",{enumerable:!0,get:function(){return g.MockBuilder}});var b=r(2938);Object.defineProperty(t,"IMockBuilder",{enumerable:!0,get:function(){return b.IMockBuilder}}),Object.defineProperty(t,"IMockBuilderExtended",{enumerable:!0,get:function(){return b.IMockBuilderExtended}}),Object.defineProperty(t,"IMockBuilderConfig",{enumerable:!0,get:function(){return b.IMockBuilderConfig}}),Object.defineProperty(t,"IMockBuilderConfigAll",{enumerable:!0,get:function(){return b.IMockBuilderConfigAll}}),Object.defineProperty(t,"IMockBuilderConfigComponent",{enumerable:!0,get:function(){return b.IMockBuilderConfigComponent}}),Object.defineProperty(t,"IMockBuilderConfigDirective",{enumerable:!0,get:function(){return b.IMockBuilderConfigDirective}}),Object.defineProperty(t,"IMockBuilderConfigModule",{enumerable:!0,get:function(){return b.IMockBuilderConfigModule}}),Object.defineProperty(t,"IMockBuilderResult",{enumerable:!0,get:function(){return b.IMockBuilderResult}}),Object.defineProperty(t,"IMockBuilderProvider",{enumerable:!0,get:function(){return b.IMockBuilderProvider}});var m=r(3821);Object.defineProperty(t,"MockModule",{enumerable:!0,get:function(){return m.MockModule}});var M=r(3877);Object.defineProperty(t,"MockedModule",{enumerable:!0,get:function(){return M.MockedModule}});var k=r(5395);Object.defineProperty(t,"MockComponent",{enumerable:!0,get:function(){return k.MockComponent}}),Object.defineProperty(t,"MockComponents",{enumerable:!0,get:function(){return k.MockComponents}});var w=r(2350);Object.defineProperty(t,"MockedComponent",{enumerable:!0,get:function(){return w.MockedComponent}});var O=r(8339);Object.defineProperty(t,"MockDirective",{enumerable:!0,get:function(){return O.MockDirective}}),Object.defineProperty(t,"MockDirectives",{enumerable:!0,get:function(){return O.MockDirectives}});var x=r(4748);Object.defineProperty(t,"MockedDirective",{enumerable:!0,get:function(){return x.MockedDirective}});var j=r(2937);Object.defineProperty(t,"MockPipe",{enumerable:!0,get:function(){return j.MockPipe}}),Object.defineProperty(t,"MockPipes",{enumerable:!0,get:function(){return j.MockPipes}});var D=r(5861);Object.defineProperty(t,"MockedPipe",{enumerable:!0,get:function(){return D.MockedPipe}});var S=r(5269);Object.defineProperty(t,"MockDeclaration",{enumerable:!0,get:function(){return S.MockDeclaration}}),Object.defineProperty(t,"MockDeclarations",{enumerable:!0,get:function(){return S.MockDeclarations}});var P=r(7413);Object.defineProperty(t,"MockProvider",{enumerable:!0,get:function(){return P.MockProvider}}),Object.defineProperty(t,"MockProviders",{enumerable:!0,get:function(){return P.MockProviders}});var C=r(5779);Object.defineProperty(t,"MockService",{enumerable:!0,get:function(){return C.MockService}});var N=r(6189);Object.defineProperty(t,"ngMocks",{enumerable:!0,get:function(){return N.ngMocks}});var T=r(1661);Object.defineProperty(t,"MockRender",{enumerable:!0,get:function(){return T.MockRender}});var E=r(8406);Object.defineProperty(t,"MockRenderFactory",{enumerable:!0,get:function(){return E.MockRenderFactory}}),o(r(7325),t),o(r(534),t)},3295:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default={flags:["cacheModule","cacheComponent","cacheDirective","cacheProvider","correctModuleExports"],mockRenderCacheSize:25,neverMockModule:["ApplicationModule","CommonModule","BrowserModule","_ApplicationModule","_CommonModule","_BrowserModule"],neverMockProvidedFunction:["DomRendererFactory2","EventManager","Injector","RendererFactory2","Sanitizer","DomSanitizer","DomSanitizerImpl","ApplicationInitStatus","ApplicationRef","Compiler","IterableDiffers","KeyValueDiffers","_DomRendererFactory2","_EventManager","_Injector","_Sanitizer","_DomSanitizer","_DomSanitizerImpl","_ApplicationInitStatus","_ApplicationRef","_Compiler","_IterableDiffers","_KeyValueDiffers"],neverMockToken:["InjectionToken Set Injector scope.","InjectionToken EventManagerPlugins","InjectionToken HammerGestureConfig","InjectionToken AppId","InjectionToken DefaultCurrencyCode","InjectionToken LocaleId","InjectionToken SCHEDULER_TOKEN"],onMockBuilderMissingDependency:"throw",onMockInstanceRestoreNeed:"warn",onTestBedFlushNeed:"warn",dependencies:["declarations","hostDirectives","entryComponents","bootstrap","providers","viewProviders","imports","exports"]}},5551:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=function(){function e(){this.stack=[],this.push()}return e.prototype.push=function(){this.stack.push(new Map)},e.prototype.pop=function(){var e;return null!==(e=this.stack.pop())&&void 0!==e?e:new Map},e.prototype.has=function(e){for(var t=this.stack.length-1;t>=0;t-=1)if(this.stack[t].has(e))return!0;return!1},e.prototype.get=function(e){for(var t=this.stack.length-1;t>=0;t-=1)if(this.stack[t].has(e))return this.stack[t].get(e)},e.prototype.set=function(e,t){for(var r=this.stack.length-1;r>=0;r-=1)this.stack[r].set(e,t);return this},e.prototype.merge=function(e){var t,r;try{for(var i=n((0,a.mapEntries)(e)),l=i.next();!l.done;l=i.next()){var u=o(l.value,2),f=u[0],c=u[1];this.set(f,c)}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}return this},e}();t.default=i},3174:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(445));t.default=function(e,t,r,n){void 0===n&&(n=!1),o.default.definePropertyDescriptor(e,t,{configurable:!0,enumerable:n,value:r,writable:!0})}},2023:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r);var o=Object.getOwnPropertyDescriptor(t,r);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),a=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)"default"!==r&&Object.prototype.hasOwnProperty.call(e,r)&&n(t,e,r);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(7182)),l=i.AbstractControl,u=i.DefaultValueAccessor,f=i.FormControl,c=i.FormControlDirective,d=i.NG_ASYNC_VALIDATORS,s=i.NG_VALIDATORS,v=i.NG_VALUE_ACCESSOR,p=i.NgControl,h=i.NgModel;t.default={AbstractControl:l,DefaultValueAccessor:u,FormControl:f,FormControlDirective:c,NG_ASYNC_VALIDATORS:d,NG_VALIDATORS:s,NG_VALUE_ACCESSOR:v,NgControl:p,NgModel:h}},6456:function(__unused_webpack_module,exports,__webpack_require__){var __extends=this&&this.__extends||(extendStatics=function(e,t){return extendStatics=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},extendStatics(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function r(){this.constructor=e}extendStatics(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),extendStatics,__values=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},__read=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},__spreadArray=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o0&&(0,core_define_property_1.default)(t,"parameters",__spreadArray([],__read(r),!1)),t};exports.extendClass=extendClass},4201:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(6456),o={};t.default=function(e,t){if(void 0===t&&(t=o),t===o)return(0,n.getTestBedInjection)(e);try{return t.get(e)}catch(e){return}}},4874:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8641)),a=n(r(1585)),i=n(r(2129));t.default=function(e){return function(t){(0,o.default)(t);try{return e(t)}catch(e){(0,a.default)(t),(0,i.default)(t)}}}},8862:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4673)),a=n(r(4874));t.default=function(e){return(0,a.default)((function(e){var t=(0,o.default)(e);if(t.Component)return t.Component;if(t.Directive)return t.Directive;throw new Error("Cannot resolve declarations")}))(e)}},1381:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8862)),a=n(r(1345)),i=r(5974);t.default=function(e){return(0,i.isNgDef)(e,"c")||(0,i.isNgDef)(e,"d")?(0,o.default)(e):(0,i.isNgDef)(e,"m")?(0,a.default)(e):void 0}},1345:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4673)),a=n(r(4874));t.default=function(e){return(0,a.default)((function(e){var t=(0,o.default)(e);if(t.NgModule)return t.NgModule;throw new Error("Cannot resolve declarations")}))(e)}},8749:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4673));t.default=function(e){var t;return null!==(t=(0,o.default)(e).parameters)&&void 0!==t?t:[]}},8773:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4673)),a=n(r(4874));t.default=function(e){return(0,a.default)((function(e){var t=(0,o.default)(e);if(t.Pipe)return t.Pipe;throw new Error("Cannot resolve declarations")}))(e)}},8911:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t,r,n;if(e&&("object"==typeof e||"function"==typeof e))return null!==(r=null===(t=e.ɵprov)||void 0===t?void 0:t.providedIn)&&void 0!==r?r:null===(n=e.ngInjectableDef)||void 0===n?void 0:n.providedIn}},1763:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.NG_MOCKS_ROOT_PROVIDERS=t.NG_MOCKS_INTERCEPTORS=t.NG_MOCKS_RESOLVERS=t.NG_MOCKS_GUARDS=t.NG_MOCKS_OVERRIDES=t.NG_MOCKS_TOUCHES=t.NG_MOCKS=void 0;var n=r(860);t.NG_MOCKS=new n.InjectionToken("NG_MOCKS"),t.NG_MOCKS.__ngMocksSkip=!0,t.NG_MOCKS_TOUCHES=new n.InjectionToken("NG_MOCKS_TOUCHES"),t.NG_MOCKS_TOUCHES.__ngMocksSkip=!0,t.NG_MOCKS_OVERRIDES=new n.InjectionToken("NG_MOCKS_OVERRIDES"),t.NG_MOCKS_OVERRIDES.__ngMocksSkip=!0,t.NG_MOCKS_GUARDS=new n.InjectionToken("NG_MOCKS_GUARDS"),t.NG_MOCKS_GUARDS.__ngMocksSkip=!0,t.NG_MOCKS_RESOLVERS=new n.InjectionToken("NG_MOCKS_RESOLVERS"),t.NG_MOCKS_RESOLVERS.__ngMocksSkip=!0,t.NG_MOCKS_INTERCEPTORS=new n.InjectionToken("NG_MOCKS_INTERCEPTORS"),t.NG_MOCKS_INTERCEPTORS.__ngMocksSkip=!0,t.NG_MOCKS_ROOT_PROVIDERS=new n.InjectionToken("NG_MOCKS_ROOT_PROVIDERS"),t.NG_MOCKS_ROOT_PROVIDERS.__ngMocksSkip=!0},5756:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(860),i=o(r(6439)),l=o(r(1184));t.default=function(e,t,r){var o,u;if(t)try{for(var f=n(t),c=f.next();!c.done;c=f.next()){var d=c.value,s=(0,l.default)(d),v=s.name,p=s.alias,h=s.required;r&&-1!==r.indexOf(v)||(0,a.Input)((0,i.default)({name:v,alias:p,required:h},!0))(e.prototype,v)}}catch(e){o={error:e}}finally{try{c&&!c.done&&(u=f.return)&&u.call(f)}finally{if(o)throw o.error}}}},615:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(860),i=o(r(6439)),l=o(r(1184));t.default=function(e,t){var r,o;if(t)try{for(var u=n(t),f=u.next();!f.done;f=u.next()){var c=f.value,d=(0,l.default)(c),s=d.name,v=d.alias,p=d.required;(0,a.Output)((0,i.default)({name:s,alias:v,required:p},!0))(e.prototype,s)}}catch(e){r={error:e}}finally{try{f&&!f.done&&(o=u.return)&&o.call(u)}finally{if(r)throw r.error}}}},8385:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i};Object.defineProperty(t,"__esModule",{value:!0});var i=r(860),l={ContentChild:i.ContentChild,ContentChildren:i.ContentChildren,ViewChild:i.ViewChild,ViewChildren:i.ViewChildren},u=function(e){return 0===e.indexOf("__mock")},f=function(e){return n(n({},e),{ngMetadataName:e.ngMetadataName,read:i.ViewContainerRef})};t.default=function(e,t){var r,n;if(!t)return[];var i=a(function(e){var t,r,n=[],a=[];try{for(var i=o(Object.keys(e)),l=i.next();!l.done;l=i.next()){var c=l.value,d=e[c];n.push([c,d]),d.isViewQuery||u(c)||(a.push(c),n.push(["__ngMocksVcr_".concat(c),f(d)]))}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}return[n,a]}(t),2),c=i[0],d=i[1];try{for(var s=o(c),v=s.next();!v.done;v=s.next()){var p=a(v.value,2),h=p[0],y=p[1];y.ngMetadataName&&(0,l[y.ngMetadataName])(y.selector,y)(e.prototype,h)}}catch(e){r={error:e}}finally{try{v&&!v.done&&(n=s.return)&&n.call(s)}finally{if(r)throw r.error}}return d}},8641:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){if(!e)throw new Error(["undefined / null has been passed into ng-mocks as a declaration / provider.","Please ensure that the current test file has correct imports:","imported files exist and imported declarations have been exported in the file."].join(" "))}},1585:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2970)),a=n(r(9628));t.default=function(e){if((0,a.default)(e))throw new Error(["ng-mocks got ".concat((0,o.default)(e)," which has been already mocked by jest.mock()."),"It is not possible to produce correct mocks for it, because jest.mock() removes Angular decorators.","To fix this, please avoid jest.mock() on the file which exports ".concat((0,o.default)(e)," or add jest.dontMock() on it."),"The same should be done for all related dependencies."].join(" "))}},2129:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2970));t.default=function(e){throw new Error(["".concat((0,o.default)(e)," declaration has been passed into ng-mocks without Angular decorators."),"Therefore, it cannot be properly handled.","Highly likely,","undefined"==typeof jest?"":"jest.mock() has been used on its file, or","ng-mocks is imported in production code, or got a class without Angular decoration.","Otherwise, please create an issue on github: https://github.com/help-me-mom/ng-mocks/issues/new?title=False%20positive%20ng-mocks%20not%20in%20JIT.","Thank you in advance for support."].join(" "))}},6439:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){var r=e.name,n=e.alias,o=e.required;return void 0===t&&(t=!1),o?{name:r,alias:n,required:o}:n&&r!==n?t?n:"".concat(r,":").concat(n):t?"":r}},1184:function(e,t){var r=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i};Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){if("string"==typeof e){var t=r(e.split(":").map((function(e){return e.trim()})),2),n=t[0],o=t[1];return n!==o&&o?{name:n,alias:o}:{name:n}}return e}},5204:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.funcExtractDeps=void 0;var a=o(r(4673)),i=o(r(3295)),l=r(6456),u=r(9335),f=o(r(6297));t.funcExtractDeps=function(e,r,o){var c,d,s,v;void 0===o&&(o=!1);var p=(0,a.default)(e),h=(0,u.getNgType)(e);if(!h||"Injectable"===h)return r;var y=p[h];try{for(var _=n(i.default.dependencies),g=_.next();!g.done;g=_.next()){var b=g.value;if(y[b])try{for(var m=(s=void 0,n((0,l.flatten)(y[b]))),M=m.next();!M.done;M=m.next()){var k=M.value,w=(0,f.default)(k);r.has(w)||(r.add(w),o&&(0,t.funcExtractDeps)(w,r))}}catch(e){s={error:e}}finally{try{M&&!M.done&&(v=m.return)&&v.call(m)}finally{if(s)throw s.error}}}}catch(e){c={error:e}}finally{try{g&&!g.done&&(d=_.return)&&d.call(_)}finally{if(c)throw c.error}}return r}},7285:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return"function"==typeof e&&e.__forward_ref__?e():e}},1102:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return"undefined"==typeof window?r.g:window}},5590:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getMockedNgDefOf=function(e,t){var r,n=null!==(r=e.mockOf)&&void 0!==r?r:e,u=(0,o.default)(a.NG_MOCKS),c=f(e,n,u);if(c&&!t)return c;if(c&&t&&(0,l.isMockedNgDefOf)(c,n,t))return c;throw new Error("There is no mock for ".concat((0,i.default)(n)))};var o=n(r(4201)),a=r(1763),i=n(r(2970)),l=r(732),u=n(r(8073)),f=function(e,t,r){if(r&&!r.has(t))throw new Error("There is no mock for ".concat((0,i.default)(t)));var n=r?r.get(t):void 0;return n===t&&(n=void 0),n||t===e?!n&&u.default.cacheDeclarations.has(t)&&(n=u.default.cacheDeclarations.get(t)):n=e,n}},2970:function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=new RegExp("[^0-9a-z]+","mgi");t.default=function(e){var t;return"function"==typeof e&&e.name?t=e.name:"function"==typeof e?t="arrowFunction":"object"==typeof e&&e&&"InjectionToken"===e.ngMetadataName?t=e._desc:"object"==typeof e&&e&&"function"==typeof e.constructor&&(t=e.constructor.name),t||(t="unknown"),t.replace(r,"_")}},9335:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getNgType=void 0;var o=n(r(4673)),a=r(4152);t.getNgType=function(e){if("string"!=typeof e){if((0,a.isNgInjectionToken)(e))return"Injectable";for(var t=(0,o.default)(e).decorators,r=t.length-1;r>=0;r-=1)if("Injectable"!==t[r])return t[r];return t.length>0?"Injectable":void 0}}},6739:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.getSourceOfMock=function(e){return"function"==typeof e&&e.mockOf?e.mockOf:e}},6297:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(3659);t.default=function(e){return e&&"object"==typeof e&&e.provide?e.provide:(0,n.isNgModuleDefWithProviders)(e)?e.ngModule:e&&"object"==typeof e&&e.directive?e.directive:e}},6804:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2970)),a=r(5974);t.default=function(e,t){if(null==e)throw new Error("null / undefined has been passed into ".concat(t,". Please check that its import is correct."));if(!("MockPipe"===t&&(0,a.isNgDef)(e,"p")||"MockDirective"===t&&(0,a.isNgDef)(e,"d")||"MockComponent"===t&&(0,a.isNgDef)(e,"c")||"MockModule"===t&&(0,a.isNgDef)(e,"m"))){var r=function(e){return(0,a.isNgDef)(e,"p")?"pipe":(0,a.isNgDef)(e,"d")?"directive":(0,a.isNgDef)(e,"c")?"component":(0,a.isNgDef)(e,"m")?"module":(0,a.isNgDef)(e,"i")?"service":(0,a.isNgDef)(e,"t")?"token":""}(e);if(r&&"MockPipe"===t)throw new Error("".concat(t," accepts pipes, whereas ").concat((0,o.default)(e)," is a ").concat(r,"."));if(r&&"MockDirective"===t)throw new Error("".concat(t," accepts directives, whereas ").concat((0,o.default)(e)," is a ").concat(r,"."));if(r&&"MockComponent"===t)throw new Error("".concat(t," accepts components, whereas ").concat((0,o.default)(e)," is a ").concat(r,"."));if(r&&"MockModule"===t)throw new Error("".concat(t," accepts modules, whereas ").concat((0,o.default)(e)," is a ").concat(r,"."))}}},9628:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return!(!e||"function"!=typeof e&&"object"!=typeof e||!(e._isMockFunction&&e.mockName&&e.__annotations__))}},7105:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.isMockControlValueAccessor=void 0;var o=n(r(2137));t.isMockControlValueAccessor=function(e){return!!(0,o.default)(e)&&!!e.__ngMocksConfig.isControlValueAccessor}},6763:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.isMockNgDef=function(e,t){return!!e.mockOf&&(!t||(0,n.isNgDef)(e.mockOf,t))};var n=r(5974)},7675:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.isMockOf=function(e,t,r){return(0,o.default)(e)&&e.constructor===t&&(r?(0,a.isNgDef)(e.constructor,r):(0,a.isNgDef)(e.constructor))};var o=n(r(2137)),a=r(5974)},2650:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.isMockValidator=void 0;var o=n(r(2137));t.isMockValidator=function(e){return!!(0,o.default)(e)&&!!e.__ngMocksConfig.isValidator}},2137:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return e&&"object"==typeof e&&!!e.__ngMocks}},732:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.isMockedNgDefOf=function(e,t,r){return"function"==typeof e&&e.mockOf===t&&(!r||(0,n.isNgDef)(e,r))};var n=r(5974)},5974:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.isNgDef=function(e,t){if("t"===t)return(0,n.isNgInjectionToken)(e);if("function"!=typeof e)return!1;var r=a(e,t),o=i(e,t),c=l(e,t),d=u(e,t),s=f(e,t);return r||o||c||d||s};var n=r(4152),o=r(7297),a=function(e,t){return(!t||"m"===t)&&(0,o.isNgType)(e,"NgModule")},i=function(e,t){return(!t||"c"===t)&&(0,o.isNgType)(e,"Component")},l=function(e,t){return(!t||"d"===t)&&(0,o.isNgType)(e,"Directive")},u=function(e,t){return(!t||"p"===t)&&(0,o.isNgType)(e,"Pipe")},f=function(e,t){return(!t||"i"===t)&&(0,o.isNgType)(e,"Injectable")}},4152:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.isNgInjectionToken=void 0,t.isNgInjectionToken=function(e){return e&&"object"==typeof e&&"InjectionToken"===e.ngMetadataName}},3659:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.isNgModuleDefWithProviders=void 0,t.isNgModuleDefWithProviders=function(e){return e&&"object"==typeof e&&"function"==typeof e.ngModule}},7297:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.isNgType=void 0;var o=n(r(4673));t.isNgType=function(e,t){var r=(0,o.default)(e).decorators;if(0===r.length)return!1;var n=1;if("Injectable"===t&&-1!==r.indexOf("Injectable"))return!0;for(;"Injectable"===r[r.length-n];)n+=1;return r[r.length-n]===t}},6580:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.isStandalone=function(e){var t=(0,a.getNgType)(e);return!(!t||"Injectable"===t)&&!0===(0,o.default)(e)[t].standalone};var o=n(r(4673)),a=r(9335)},6259:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(4673)),i=o(r(3295)),l=r(6456),u=o(r(6297)),f=function(e,t,r){var o,c,d,s,v,p;void 0===r&&(r=new Set);var h=(0,a.default)(e);try{for(var y=n(h.decorators),_=y.next();!_.done;_=y.next()){var g=_.value;try{for(var b=(d=void 0,n(i.default.dependencies)),m=b.next();!m.done;m=b.next()){var M=m.value;if(h[g][M])try{for(var k=(v=void 0,n((0,l.flatten)(h[g][M]))),w=k.next();!w.done;w=k.next()){var O=w.value,x=(0,u.default)(O);x&&!r.has(x)&&(r.add(x),t(x),f(x,t,r))}}catch(e){v={error:e}}finally{try{w&&!w.done&&(p=k.return)&&p.call(k)}finally{if(v)throw v.error}}}}catch(e){d={error:e}}finally{try{m&&!m.done&&(s=b.return)&&s.call(b)}finally{if(d)throw d.error}}}}catch(e){o={error:e}}finally{try{_&&!_.done&&(c=y.return)&&c.call(y)}finally{if(o)throw o.error}}};t.default=f},1433:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.MockAsyncValidatorProxy=t.MockValidatorProxy=t.MockControlValueAccessorProxy=void 0;var r=function(e,t,r,n){if(e.instance&&n&&(e.instance[n]=r),e.instance&&e.instance[t])return e.instance[t](r)},n=function(){function e(e){this.target=e}return e.prototype.registerOnChange=function(e){r(this,"registerOnChange",e,"__simulateChange")},e.prototype.registerOnTouched=function(e){r(this,"registerOnTouched",e,"__simulateTouch")},e.prototype.setDisabledState=function(e){r(this,"setDisabledState",e)},e.prototype.writeValue=function(e){r(this,"writeValue",e)},e}();t.MockControlValueAccessorProxy=n;var o=function(){function e(e){this.target=e}return e.prototype.registerOnValidatorChange=function(e){r(this,"registerOnValidatorChange",e,"__simulateValidatorChange")},e.prototype.validate=function(e){return this.instance&&this.instance.validate?this.instance.validate(e):null},e}();t.MockValidatorProxy=o;var a=function(){function e(e){this.target=e}return e.prototype.registerOnValidatorChange=function(e){r(this,"registerOnValidatorChange",e,"__simulateValidatorChange")},e.prototype.validate=function(e){if(this.instance&&this.instance.validate){var t=this.instance.validate(e);return void 0===t?Promise.resolve(null):t}return Promise.resolve(null)},e}();t.MockAsyncValidatorProxy=a},5980:function(e,t,r){var n,o=this&&this.__extends||(n=function(e,t){return n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},n(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0}),t.LegacyControlValueAccessor=void 0;var a=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t.prototype.__simulateChange=function(){},t.prototype.__simulateTouch=function(){},t.prototype.__simulateValidatorChange=function(){},t}(r(1946).Mock);t.LegacyControlValueAccessor=a},1946:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o0&&((o=(0,c.default)(e._providers||(null===(n=e._compiler)||void 0===n?void 0:n.providers)).touches)||(o=new Set,t.providers=t.providers||[],t.providers.push({provide:O.NG_MOCKS_TOUCHES,useValue:o})),T(t,o)),o}(Y,K,J.touches);return Z&&v.ngMocks.flushTestBed(),ee&&function(e){var t,r;try{for(var i=o((0,b.mapEntries)(e)),l=i.next();!l.done;l=i.next()){var u=a(l.value,2),c=u[0],d=a(u[1],2),s=d[0],v=d[1];f.TestBed.ngMocksOverrides.set(c,n(n({},v),{override:s})),N(c,s)}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}}(ee),!te||Y._instantiated||Y._testModuleRef||function(e,t){var r,n;if(f.TestBed.ngMocksOverrides){var i=C.default.touches;C.default.touches=t;try{for(var l=o((0,b.flatten)(e.ngModule||[])),u=l.next();!u.done;u=l.next()){var c=u.value;E(c)}}catch(e){r={error:e}}finally{try{u&&!u.done&&(n=l.return)&&n.call(l)}finally{if(r)throw r.error}}!function(e){var t,r;try{for(var n=o((0,b.mapEntries)(C.default.getDefaults())),i=n.next();!i.done;i=n.next()){var l=a(i.value,2),u=l[0];"mock"===a(l[1],1)[0]&&((0,S.isNgDef)(u,"i")||(0,S.isNgDef)(u,"t"))&&(e.has(u)||f.TestBed.ngMocksOverrides.has(u)||A(u,e))}}catch(e){t={error:e}}finally{try{i&&!i.done&&(r=n.return)&&r.call(n)}finally{if(t)throw t.error}}}(t),C.default.touches=i}}(Y,te),e.call(t,K)}},I=function(e,t){return function(){return C.default.global.delete("builder:config"),C.default.global.delete("builder:module"),f.TestBed.ngMocksSelectors=void 0,function(e){var t,r,n;if(null===(n=e.ngMocksOverrides)||void 0===n?void 0:n.size){v.ngMocks.flushTestBed();try{for(var i=o((0,b.mapEntries)(e.ngMocksOverrides)),l=i.next();!l.done;l=i.next()){var u=a(l.value,2),f=u[0],c=u[1];N(f,c)}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}}e.ngMocksOverrides=void 0}(f.TestBed),e.call(t)}},V=function(e){if(!u.ViewContainerRef.ngMocksOverridesPatched&&((0,g.default)(u.ViewContainerRef,"ngMocksOverridesPatched",!0),e.createComponent)){var t=e.createComponent,r=(0,y.default)(t,void 0,void 0,(function(e){for(var r,n=[],o=1;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},l=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var u=l(r(8073)),f={id:{},level:"root"},c=u.default.global.get("reporter-stack")||[a({},f)];u.default.global.set("reporter-stack",c);var d=null!==(n=u.default.global.get("reporter-stack-push"))&&void 0!==n?n:[];u.default.global.set("reporter-stack-push",d);var s=null!==(o=u.default.global.get("reporter-stack-pop"))&&void 0!==o?o:[];u.default.global.set("reporter-stack-pop",s),t.default={current:function(){return c[c.length-1]},stackPop:function(){var e,t,r=c.pop();if(0===c.length&&c.push("root"===(null==r?void 0:r.level)?r:a({},f)),r&&"root"!==r.level)try{for(var n=i(s),o=n.next();!o.done;o=n.next())(0,o.value)(r,c)}catch(t){e={error:t}}finally{try{o&&!o.done&&(t=n.return)&&t.call(n)}finally{if(e)throw e.error}}u.default.global.set("reporter-stack-id",c[c.length-1].id)},stackPush:function(){var e,t,r={};u.default.global.set("reporter-stack-id",r);var n={id:r,level:"runtime"};c.push(n);try{for(var o=i(d),a=o.next();!a.done;a=o.next())(0,a.value)(n,c)}catch(t){e={error:t}}finally{try{a&&!a.done&&(t=o.return)&&t.call(o)}finally{if(e)throw e.error}}},subscribePop:function(e){-1===s.indexOf(e)&&s.push(e)},subscribePush:function(e){d.indexOf(e)&&d.push(e),c.length>0&&e(c[c.length-1],c)},unsubscribePop:function(e){var t=s.indexOf(e);-1!==t&&s.splice(t,1)},unsubscribePush:function(e){var t=d.indexOf(e);-1!==t&&d.splice(t,1)}}},8073:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3295)),i=o(r(1102)),l=o(r(2970)),u=function(e){return function(){return f.global.has(e)||f.global.set(e,new Map),f.global.get(e)}};(0,i.default)().ngMocksUniverse=(0,i.default)().ngMocksUniverse||{};var f=(0,i.default)().ngMocksUniverse;f.builtDeclarations=new Map,f.builtProviders=new Map,f.cacheDeclarations=new Map,f.cacheProviders=new Map,f.config=new Map,f.configInstance=new Map,f.flags=new Set(a.default.flags),f.global=new Map,f.touches=new Set,f.global.set("flags",{onMockBuilderMissingDependency:a.default.onMockBuilderMissingDependency,onMockInstanceRestoreNeed:a.default.onMockInstanceRestoreNeed,onTestBedFlushNeed:a.default.onTestBedFlushNeed}),f.getOverrides=u("overrides"),f.getDefaults=u("defaults"),f.getConfigMock=u("configMock");var c=function(e){var t;return(t=f.getDefaults().get(e))||(t="function"==typeof e?f.getDefaults().get("@".concat((0,l.default)(e))):void 0)?t:[]};f.getResolution=function(e){var t=f.config.get("ngMocksDepsResolution");return(null==t?void 0:t.has(e))?t.get(e):n(c(e),1)[0]},f.getBuildDeclaration=function(e){if(f.builtDeclarations.has(e))return f.builtDeclarations.get(e);var t=n(c(e),2),r=t[0],o=t[1];return"exclude"===r?null:r&&"keep"!==r?"replace"===r?o:void 0:e},f.hasBuildDeclaration=function(e){if(f.builtDeclarations.has(e))return void 0!==f.builtDeclarations.get(e);var t=n(c(e),1)[0];return!!t&&"mock"!==t};var d=function(e){return f.hasBuildDeclaration(e)},s=function(e){return f.getBuildDeclaration(e)};f.isExcludedDef=function(e){var t=f.getResolution(e);return(!t||"exclude"===t)&&d(e)&&null===s(e)},f.isProvidedDef=function(e){return d(e)&&null!==s(e)},f.getDefaults().set("@StoreDevtoolsModule",["exclude"]),f.indexValue=0,f.index=function(){return f.indexValue++},t.default=f},4117:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0});var o=r(6456),a=r(1763);t.default=function(e){var t,r,i,l,u;try{for(var f=n((0,o.flatten)(e||[])),c=f.next();!c.done;c=f.next()){var d=c.value;"object"==typeof d&&(d.provide===a.NG_MOCKS&&(i=d.useValue),d.provide===a.NG_MOCKS_OVERRIDES&&(l=d.useValue),d.provide===a.NG_MOCKS_TOUCHES&&(u=d.useValue))}}catch(e){t={error:e}}finally{try{c&&!c.done&&(r=f.return)&&r.call(f)}finally{if(t)throw t.error}}return{mocks:i,overrides:l,touches:u}}},9539:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockBuilderStash=void 0;var a=o(r(3295)),i=o(r(8073)),l=function(){function e(){this.data={}}return e.prototype.backup=function(){this.data={builtDeclarations:i.default.builtDeclarations,builtProviders:i.default.builtProviders,cacheDeclarations:i.default.cacheDeclarations,cacheProviders:i.default.cacheProviders,config:i.default.config,configInstance:i.default.configInstance,flags:i.default.flags,touches:i.default.touches},i.default.builtDeclarations=new Map,i.default.builtProviders=new Map,i.default.cacheDeclarations=new Map,i.default.cacheProviders=new Map,i.default.config=new Map,i.default.configInstance=new Map,i.default.flags=new Set(a.default.flags),i.default.touches=new Set},e.prototype.restore=function(){var e,t;try{for(var r=n(Object.keys(this.data)),o=r.next();!o.done;o=r.next()){var a=o.value;i.default[a]=this.data[a]}}catch(t){e={error:t}}finally{try{o&&!o.done&&(t=r.return)&&t.call(r)}finally{if(e)throw e.error}}},e}();t.MockBuilderStash=l},9755:function(e,t,r){var n,o=this&&this.__extends||(n=function(e,t){return n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},n(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),a=this&&this.__awaiter||function(e,t,r,n){return new(r||(r=Promise))((function(o,a){function i(e){try{u(n.next(e))}catch(e){a(e)}}function l(e){try{u(n.throw(e))}catch(e){a(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,l)}u((n=n.apply(e,t||[])).next())}))},i=this&&this.__generator||function(e,t){var r,n,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function l(l){return function(u){return function(l){if(r)throw new TypeError("Generator is already executing.");for(;a&&(a=0,l[0]&&(i=0)),i;)try{if(r=1,n&&(o=2&l[0]?n.return:l[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,l[1])).done)return o;switch(n=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return i.label++,{value:l[1],done:!1};case 5:i.label++,n=l[1],l=[0];continue;case 7:l=i.ops.pop(),i.trys.pop();continue;default:if(!((o=(o=i.trys).length>0&&o[o.length-1])||6!==l[0]&&2!==l[0])){i=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},u=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockBuilderPerformance=void 0;var f=r(2603),c=r(6456),d=u(r(8073)),s=r(9620),v=u(r(2739)),p=u(r(9049)),h=u(r(7570)),y=u(r(1271)),_=u(r(5633)),g=u(r(4503)),b=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t.prototype.build=function(){var t=d.default.global;if(t.has("builder:module")&&t.has("builder:config")&&this.equalsTo(t.get("builder:config")))return(0,g.default)(t.get("builder:module"));t.has("builder:module")&&t.delete(t.get("builder:module"));var r=this.cloneConfig(),n=e.prototype.build.call(this);return t.set("builder:config",r),t.set("builder:module",n),(0,g.default)(n)},t.prototype.then=function(t,r){return a(this,void 0,Promise,(function(){var n,o;return i(this,(function(a){return(n=d.default.global).has("bullet")&&n.has("builder:module")&&n.has("builder:config")&&this.equalsTo(n.get("builder:config"))?[2,n.get(n.get("builder:module")).then(t,r)]:(n.has("bullet")&&n.has("bullet:reset")&&(console.warn("ngMocks.faster has zero effect due to changes in testing module between runs"),n.delete("bullet"),f.TestBed.resetTestingModule(),n.set("bullet",!0)),o=e.prototype.then.call(this,t,r),n.set(n.get("builder:module"),o),[2,o])}))}))},t.prototype.cloneConfig=function(){var e=(0,_.default)();return(0,c.mapValues)(this.beforeCC,e.beforeCC),(0,c.mapValues)(this.excludeDef,e.excludeDef),(0,c.mapValues)(this.keepDef,e.keepDef),(0,c.mapValues)(this.mockDef,e.mockDef),(0,c.mapValues)(this.replaceDef,e.replaceDef),(0,c.mapEntries)(this.configDef,e.configDef),(0,c.mapEntries)(this.defProviders,e.defProviders),(0,c.mapEntries)(this.defValue,e.defValue),(0,c.mapEntries)(this.providerDef,e.providerDef),e},t.prototype.equalsTo=function(e){var t,r,n,o,a,i;try{for(var u=l(["beforeCC","keepDef","replaceDef","excludeDef","mockDef"]),f=u.next();!f.done;f=u.next()){var c=f.value;if(!(0,y.default)(this[c],e[c]))return!1}}catch(e){t={error:e}}finally{try{f&&!f.done&&(r=u.return)&&r.call(u)}finally{if(t)throw t.error}}try{for(var d=l(["defValue"]),s=d.next();!s.done;s=d.next())if(c=s.value,!(0,p.default)(this[c],e[c]))return!1}catch(e){n={error:e}}finally{try{s&&!s.done&&(o=d.return)&&o.call(d)}finally{if(n)throw n.error}}try{for(var _=l(["providerDef","defProviders"]),g=_.next();!g.done;g=_.next())if(c=g.value,!(0,p.default)(this[c],e[c],h.default))return!1}catch(e){a={error:e}}finally{try{g&&!g.done&&(i=_.return)&&i.call(_)}finally{if(a)throw a.error}}return(0,p.default)(this.configDef,e.configDef,v.default)},t}(s.MockBuilderPromise);t.MockBuilderPerformance=b},9620:function(e,t,r){var n=this&&this.__awaiter||function(e,t,r,n){return new(r||(r=Promise))((function(o,a){function i(e){try{u(n.next(e))}catch(e){a(e)}}function l(e){try{u(n.throw(e))}catch(e){a(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,l)}u((n=n.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var r,n,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function l(l){return function(u){return function(l){if(r)throw new TypeError("Generator is already executing.");for(;a&&(a=0,l[0]&&(i=0)),i;)try{if(r=1,n&&(o=2&l[0]?n.return:l[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,l[1])).done)return o;switch(n=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return i.label++,{value:l[1],done:!1};case 5:i.label++,n=l[1],l=[0];continue;case 7:l=i.ops.pop(),i.trys.pop();continue;default:if(!((o=(o=i.trys).length>0&&o[o.length-1])||6!==l[0]&&2!==l[0])){i=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},u=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockBuilderPromise=void 0;var f=r(2603),c=u(r(5551)),d=r(6456),s=u(r(2970)),v=r(5974),p=r(3659),h=u(r(8073)),y=r(3771),_=r(9539),g=u(r(7140)),b=u(r(1649)),m=u(r(4387)),M=u(r(1267)),k=u(r(9961)),w=u(r(7703)),O=u(r(5195)),x=u(r(1391)),j=u(r(7235)),D=u(r(8792)),S=u(r(9102)),P=function(e){return(0,p.isNgModuleDefWithProviders)(e)?{def:e.ngModule,providers:e.providers}:{def:e,providers:void 0}},C=function(e,t,r){return r?i(i([],a(Array.isArray(t)?t:[]),!1),[e],!1):e},N={},T=function(){function e(e){this.configDefault=e,this.beforeCC=new Set,this.configDef=new Map,this.defProviders=new Map,this.defValue=new Map,this.excludeDef=new Set,this.keepDef=new Set,this.mockDef=new Set,this.providerDef=new Map,this.replaceDef=new Set,this.stash=new _.MockBuilderStash,"undefined"!=typeof Symbol&&(this[Symbol.toStringTag]="Promise")}return e.prototype.beforeCompileComponents=function(e){return this.beforeCC.add(e),this},e.prototype.build=function(){this.stash.backup();var e=new c.default;h.default.config.set("mockNgDefResolver",e),h.default.flags.add("hasRootModule");try{var t=this.combineParams(),r=(0,x.default)(t,(0,j.default)(t));return(0,g.default)(r,t,e),(0,O.default)(r,t,e),(0,w.default)(r),(0,b.default)(),r.providers.push((0,M.default)(),(0,k.default)(),(0,m.default)(this.replaceDef,this.defValue),y.MockBuilder),r}finally{h.default.flags.delete("hasRootModule"),h.default.config.delete("mockNgDefResolver"),this.stash.restore()}},e.prototype.catch=function(e){return n(this,void 0,Promise,(function(){return o(this,(function(t){return[2,this.then().catch(e)]}))}))},e.prototype.exclude=function(e){return this.wipe(e),this.excludeDef.add(e),this.setConfigDef(e),this},e.prototype.finally=function(e){return n(this,void 0,Promise,(function(){return o(this,(function(t){return[2,this.then().finally(e)]}))}))},e.prototype.keep=function(e,t){var r=P(e),n=r.def,o=r.providers,l=this.keepDef.has(n)?this.defProviders.get(n):[];return this.wipe(n),this.keepDef.add(n),o&&this.defProviders.set(n,i(i([],a(l||[]),!1),a(o),!1)),this.setConfigDef(n,t),this},e.prototype.mock=function(e,t,r){void 0===t&&(t=N);var n=P(e),o=n.def,l=n.providers,u=(0,D.default)(o,t,r,N),f=u.config,c=u.mock;if((0,v.isNgDef)(c)&&(0,v.isNgDef)(e)&&!(0,v.isNgDef)(e,"t"))throw new Error(["MockBuilder.mock(".concat((0,s.default)(e),") received a class when its shape is expected."),"Please try ngMocks.defaultMock instead."].join(" "));var d=this.mockDef.has(o)?this.defProviders.get(o):[];return this.wipe(o),this.mockDef.add(o),l&&this.defProviders.set(o,i(i([],a(d||[]),!1),a(l),!1)),this.setDefValue(o,c),this.setConfigDef(o,f),this},e.prototype.provide=function(e){var t,r;try{for(var n=l((0,d.flatten)(e)),o=n.next();!o.done;o=n.next()){var a=o.value,i=(0,S.default)(a),u=i.provide,f=i.multi,c=this.providerDef.has(u)?this.providerDef.get(u):[];this.providerDef.set(u,C(a,c,f))}}catch(e){t={error:e}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(t)throw t.error}}return this},e.prototype.replace=function(e,t,r){if(!(0,v.isNgDef)(t)||!(0,v.isNgDef)(e)||(0,v.isNgDef)(t,"i")||(0,v.isNgDef)(e,"i"))throw new Error("Cannot replace the declaration, both have to be a Module, a Component, a Directive or a Pipe, for Providers use `.mock` or `.provide`");return this.wipe(e),this.replaceDef.add(e),this.defValue.set(e,t),this.setConfigDef(e,r),this},e.prototype.then=function(e,t){return n(this,void 0,Promise,(function(){var r,n=this;return o(this,(function(o){return r=new Promise((function(e){var t,r,o=f.TestBed.configureTestingModule(n.build());try{for(var a=l((0,d.mapValues)(n.beforeCC)),i=a.next();!i.done;i=a.next())(0,i.value)(o)}catch(e){t={error:e}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}o.compileComponents().then((function(){e({testBed:o})}))})),[2,r.then(e,t)]}))}))},e.prototype.combineParams=function(){return{configDef:this.configDef,configDefault:this.configDefault,defProviders:this.defProviders,defValue:this.defValue,excludeDef:this.excludeDef,keepDef:this.keepDef,mockDef:this.mockDef,providerDef:this.providerDef,replaceDef:this.replaceDef}},e.prototype.setConfigDef=function(e,t){!t&&this.configDef.has(e)||this.configDef.set(e,null!=t?t:this.configDefault)},e.prototype.setDefValue=function(e,t){t===N?this.defValue.delete(e):this.defValue.set(e,t)},e.prototype.wipe=function(e){this.defProviders.delete(e),this.defValue.delete(e),this.excludeDef.delete(e),this.keepDef.delete(e),this.mockDef.delete(e),this.providerDef.delete(e),this.replaceDef.delete(e)},e}();t.MockBuilderPromise=T},3771:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockBuilder=s;var i=a(r(3174)),l=r(6456),u=r(6580),f=a(r(8073)),c=a(r(5020)),d=r(9755);function s(){for(var e,t,r,a,s,v,p=[],h=0;h=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0});var o=r(6456);t.default=function(e,t,r){var a,i;if(void 0===r&&(r=function(e,t){return e===t}),!t||t.size!==e.size)return!1;try{for(var l=n((0,o.mapKeys)(e)),u=l.next();!u.done;u=l.next()){var f=u.value;if(!t.has(f))return!1;if(!r(t.get(f),e.get(f)))return!1}}catch(e){a={error:e}}finally{try{u&&!u.done&&(i=l.return)&&i.call(l)}finally{if(a)throw a.error}}return!0}},7570:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=function(e,t){for(var r,o,a=[],i=2;i=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0});var o=r(6456);t.default=function(e,t){var r,a;if(!t||t.size!==e.size)return!1;try{for(var i=n((0,o.mapValues)(e)),l=i.next();!l.done;l=i.next()){var u=l.value;if(!t.has(u))return!1}}catch(e){r={error:e}}finally{try{l&&!l.done&&(a=i.return)&&a.call(i)}finally{if(r)throw r.error}}return!0}},2801:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(5432));t.default=function(e,t){return!(!(0,a.default)(t,e)||"object"==typeof t&&"object"==typeof e&&function(e,t){var r,o;if(Object.keys(e).length!==Object.keys(t).length)return!0;try{for(var i=n(Object.keys(e)),l=i.next();!l.done;l=i.next()){var u=l.value;if(!(0,a.default)(e[u],t[u]))return!0}}catch(e){r={error:e}}finally{try{l&&!l.done&&(o=i.return)&&o.call(i)}finally{if(r)throw r.error}}return!1}(t,e))}},5432:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(9382));t.default=function(e,t){return e===t||("boolean"!=typeof e&&"boolean"!=typeof t||e===t)&&e.$implicit===t.$implicit&&(0,o.default)(e.variables,t.variables)}},9382:function(e,t){var r=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){return e===t||!(e&&!t||!e&&t)&&!function(e,t){var n,o,a=Object.keys(e),i=Object.keys(t);if(a.length!==i.length)return!0;try{for(var l=r(a),u=l.next();!u.done;u=l.next()){var f=u.value;if(e[f]!==t[f])return!0}}catch(e){n={error:e}}finally{try{u&&!u.done&&(o=l.return)&&o.call(l)}finally{if(n)throw n.error}}return!1}(e,t)}},5633:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return{beforeCC:new Set,configDef:new Map,defProviders:new Map,defValue:new Map,excludeDef:new Set,keepDef:new Set,mockDef:new Set,providerDef:new Map,replaceDef:new Set}}},4503:function(e,t){var r=this&&this.__assign||function(){return r=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(8911)),l=o(r(6297)),u=o(r(8073)),f=o(r(3663));t.default=function(e,t,r){var o,c,d,s,v,p,h=t.providerDef,y=t.mockDef;try{for(var _=n((0,a.mapValues)(h)),g=_.next();!g.done;g=_.next()){var b=g.value;e.providers.push(b)}}catch(e){o={error:e}}finally{try{g&&!g.done&&(c=_.return)&&c.call(_)}finally{if(o)throw o.error}}try{for(var m=n((0,a.flatten)(e.providers)),M=m.next();!M.done;M=m.next()){b=M.value;var k=(0,l.default)(b);u.default.touches.add(k),k!==b&&b.deps&&(0,a.extractDependency)(b.deps,u.default.config.get("ngMocksDeps"))}}catch(e){d={error:e}}finally{try{M&&!M.done&&(s=m.return)&&s.call(m)}finally{if(d)throw d.error}}try{for(var w=n((0,a.mapValues)(y)),O=w.next();!O.done;O=w.next()){var x=O.value;u.default.touches.has(x)||"root"!==(0,i.default)(x)||(e.providers.push((0,f.default)(x,r)),u.default.touches.add(x))}}catch(e){v={error:e}}finally{try{O&&!O.done&&(p=w.return)&&p.call(w)}finally{if(v)throw v.error}}}},1649:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(2603),i=r(6456),l=o(r(6297)),u=o(r(8073));t.default=function(){var e,t,r=(0,a.getTestBed)();if(r.ngModule)try{for(var o=n((0,i.flatten)(r.ngModule)),f=o.next();!f.done;f=o.next()){var c=f.value;u.default.touches.add((0,l.default)(c))}}catch(t){e={error:t}}finally{try{f&&!f.done&&(t=o.return)&&t.call(o)}finally{if(e)throw e.error}}}},646:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t,r){"function"==typeof e&&-1===r.indexOf(e)&&(r.push(e),t.push(e))}},4387:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(1381)),l=r(1763),u=o(r(8073)),f=o(r(5884)),c=o(r(4483));t.default=function(e,t){var r,o,d,s,v=new Map;try{for(var p=n((0,a.mapValues)(u.default.touches)),h=p.next();!h.done;h=p.next()){var y=h.value,_=u.default.getBuildDeclaration(y)||y;if(!(0,c.default)(e,t,y,_)){var g=(0,i.default)(_),b=(0,f.default)(g);if(b){var m={};try{for(var M=(d=void 0,n(Object.keys(b))),k=M.next();!k.done;k=M.next()){var w=k.value;m[w]=g[w]}}catch(e){d={error:e}}finally{try{k&&!k.done&&(s=M.return)&&s.call(M)}finally{if(d)throw d.error}}v.set(_,[{set:b},{set:m}])}}}}catch(e){r={error:e}}finally{try{h&&!h.done&&(o=p.return)&&o.call(p)}finally{if(r)throw r.error}}return{provide:l.NG_MOCKS_OVERRIDES,useValue:v}}},1267:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=r(6456),u=r(1763),f=i(r(8073));t.default=function(){var e,t,r=new Map;try{for(var i=a(o(o(o(o([],n((0,l.mapEntries)(f.default.builtProviders)),!1),n((0,l.mapEntries)(f.default.builtDeclarations)),!1),n((0,l.mapEntries)(f.default.cacheDeclarations)),!1),n((0,l.mapEntries)(f.default.cacheProviders)),!1)),c=i.next();!c.done;c=i.next()){var d=n(c.value,2),s=d[0],v=d[1];r.has(s)||r.set(s,v)}}catch(t){e={error:t}}finally{try{c&&!c.done&&(t=i.return)&&t.call(i)}finally{if(e)throw e.error}}return{provide:u.NG_MOCKS,useValue:r}}},9961:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=r(1763),l=o(r(8073));t.default=function(){var e,t,r=new Set;try{for(var o=n((0,a.mapValues)(l.default.touches)),u=o.next();!u.done;u=o.next()){var f=u.value,c=l.default.getBuildDeclaration(f);void 0===c&&(c=f),r.add(f),r.add(c)}}catch(t){e={error:t}}finally{try{u&&!u.done&&(t=o.return)&&t.call(o)}finally{if(e)throw e.error}}return{provide:i.NG_MOCKS_TOUCHES,useValue:r}}},8608:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(7285));t.default=function(e){var t,r;if(e){var o;try{for(var i=n(e),l=i.next();!l.done;l=i.next()){var u=l.value;u&&"object"==typeof u&&u.token&&(o=u.token),o||!u||"object"==typeof u&&u.ngMetadataName||(o=u)}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}return(0,a.default)(o)}}},5884:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(8073)),i=o(r(224));t.default=function(e){if(e){var t=a.default.flags.has("skipMock");t||a.default.flags.add("skipMock");var r=n((0,i.default)(e),2),o=r[0],l=r[1];if(t||a.default.flags.delete("skipMock"),o)return l}}},8703:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(8749)),i=r(1763),l=o(r(8073)),u=o(r(2504)),f=o(r(646)),c=o(r(8608)),d=o(r(1978)),s=o(r(7213)),v=o(r(4995));t.default=function(e){var t,r,o,p,h,y,_=new Set,g=(0,d.default)(),b=g.buckets,m=g.touched;try{for(var M=n(b),k=M.next();!k.done;k=M.next()){var w=k.value;try{for(var O=(o=void 0,n(w)),x=O.next();!x.done;x=O.next()){var j=x.value;(0,u.default)(_,e,j);try{for(var D=(h=void 0,n((0,a.default)(j))),S=D.next();!S.done;S=D.next()){var P=S.value,C=(0,c.default)(P);(0,s.default)(C),(0,v.default)(C)||((0,f.default)(C,m,w),e.has(i.NG_MOCKS_ROOT_PROVIDERS)||!l.default.config.get("ngMocksDepsSkip").has(j)?_.add(C):l.default.config.get("ngMocksDepsSkip").add(C))}}catch(e){h={error:e}}finally{try{S&&!S.done&&(y=D.return)&&y.call(D)}finally{if(h)throw h.error}}}}catch(e){o={error:e}}finally{try{x&&!x.done&&(p=O.return)&&p.call(O)}finally{if(o)throw o.error}}}}catch(e){t={error:e}}finally{try{k&&!k.done&&(r=M.return)&&r.call(M)}finally{if(t)throw t.error}}return _}},1978:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=r(860),u=i(r(3174)),f=r(6456),c=r(1763),d=r(5974),s=i(r(1365)),v=function(e,t){if(t){var r=t.resolveComponentFactory;t.resolveComponentFactory=(0,s.default)(r,void 0,void 0,(function(a){for(var i,l=[],u=1;u=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=r(1763),l=r(4152),u=o(r(8073)),f=o(r(3663)),c=o(r(9465)),d=o(r(8703));t.default=function(e,t,r){var o,s,v=t.keepDef,p=t.mockDef,h=v.has(i.NG_MOCKS_ROOT_PROVIDERS)?new Set:(0,d.default)(p);if(h.size>0){var y=function(t){var n=(0,f.default)(t,r);if(n)e.providers.push(n);else if((0,l.isNgInjectionToken)(t)){var o=u.default.config.has("ngMocksMulti")&&u.default.config.get("ngMocksMulti").has(t);e.providers.push((0,c.default)(t,(function(){return o?[]:void 0})))}};try{for(var _=n((0,a.mapValues)(h)),g=_.next();!g.done;g=_.next())y(g.value)}catch(e){o={error:e}}finally{try{g&&!g.done&&(s=_.return)&&s.call(_)}finally{if(o)throw o.error}}}}},2710:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(8073));t.default=function(e){var t,r,o=i.default.builtDeclarations,l=i.default.builtProviders,u=i.default.config.get("ngMocksDepsResolution");try{for(var f=n((0,a.mapValues)(e)),c=f.next();!c.done;c=f.next()){var d=c.value;o.set(d,null),l.set(d,null),u.set(d,"exclude")}}catch(e){t={error:e}}finally{try{c&&!c.done&&(r=f.return)&&r.call(f)}finally{if(t)throw t.error}}}},7651:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=r(5204),l=o(r(8073));t.default=function(e,t){var r,o,u=new Set,f=l.default.builtDeclarations,c=l.default.builtProviders,d=l.default.config.get("ngMocksDepsResolution");try{for(var s=n((0,a.mapValues)(e)),v=s.next();!v.done;v=s.next()){var p=v.value;f.set(p,p),c.set(p,p),d.set(p,"keep"),t.get(p).shallow&&(0,i.funcExtractDeps)(p,u)}}catch(e){r={error:e}}finally{try{v&&!v.done&&(o=s.return)&&o.call(s)}finally{if(r)throw r.error}}return u}},102:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(8073)),l=o(r(4161));t.default=function(e,t){var r,o,u=i.default.builtDeclarations,f=i.default.config.get("ngMocksDepsResolution");try{for(var c=n((0,a.mapValues)(e)),d=c.next();!d.done;d=c.next()){var s=d.value,v=!i.default.touches.has(s);f.set(s,"mock"),u.set(s,void 0),(0,l.default)(s,t),v&&i.default.touches.delete(s)}}catch(e){r={error:e}}finally{try{d&&!d.done&&(o=c.return)&&o.call(c)}finally{if(r)throw r.error}}}},3680:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8073));t.default=function(e,t){var r,n=null!==(r=o.default.config.get("mockNgDefResolver").get(e))&&void 0!==r?r:o.default.getBuildDeclaration(e),a=t.has(e)?t.get(e):void 0;return a?{ngModule:n,providers:a}:n}},1159:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=r(6456),u=r(5974),f=i(r(8073)),c=r(3821),d=i(r(224)),s=i(r(4673)),v=i(r(8150));t.default=function(e,t,r,i){var p,h,y,_,g,b,m,M,k,w=new Map;try{for(var O=a(o(o(o([],n((0,l.mapValues)(e)),!1),n((0,l.mapValues)(t)),!1),n((0,l.mapValues)(r)),!1)),x=O.next();!x.done;x=O.next()){var j=x.value,D=(0,s.default)(j),S=o(o(o([],n(null!==(g=i.get(j))&&void 0!==g?g:[]),!1),n(null!==(m=null===(b=D.Component)||void 0===b?void 0:b.providers)&&void 0!==m?m:[]),!1),n(null!==(k=null===(M=D.Directive)||void 0===M?void 0:M.providers)&&void 0!==k?k:[]),!1),P=!f.default.touches.has(j);t.has(j)||f.default.flags.add("skipMock");var C=(0,u.isNgDef)(j,"m");if(S.length>0){var N=n((0,d.default)({providers:S,skipMarkProviders:!C,skipExports:!0}),2)[1];w.set(j,N.providers)}C&&f.default.builtDeclarations.set(j,(0,c.MockModule)(j)),f.default.flags.delete("skipMock"),P&&f.default.touches.delete(j)}}catch(e){p={error:e}}finally{try{x&&!x.done&&(h=O.return)&&h.call(O)}finally{if(p)throw p.error}}try{for(var T=a((0,l.mapValues)(t)),E=T.next();!E.done;E=T.next())j=E.value,(0,v.default)(j)}catch(e){y={error:e}}finally{try{E&&!E.done&&(_=T.return)&&_.call(T)}finally{if(y)throw y.error}}return w}},1391:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(8073));t.default=function(e,t){var r,o,l=i.default.builtDeclarations,u=i.default.config.get("ngMocksDepsResolution");try{for(var f=n((0,a.mapValues)(e)),c=f.next();!c.done;c=f.next()){var d=c.value;l.set(d,t.get(d)),u.set(d,"replace")}}catch(e){r={error:e}}finally{try{c&&!c.done&&(o=f.return)&&o.call(f)}finally{if(r)throw r.error}}}},7235:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=r(6456),u=r(5204),f=i(r(8073)),c=i(r(2710)),d=i(r(7651)),s=i(r(102)),v=i(r(1159)),p=i(r(8500));t.default=function(e){var t,r,i,h,y,_,g,b,m,M,k,w,O=e.configDef,x=e.defProviders,j=e.defValue,D=e.excludeDef,S=e.keepDef,P=e.mockDef,C=e.replaceDef;f.default.flags.add("cachePipe"),f.default.config.set("ngMocksMulti",new Set),f.default.config.set("ngMocksDeps",new Set),f.default.config.set("ngMocksDepsSkip",new Set),f.default.config.set("ngMocksDepsResolution",new Map);var N=(0,d.default)(S,O);try{for(var T=o((0,l.mapValues)(N)),E=T.next();!E.done;E=T.next()){var A=E.value;f.default.touches.add(A)}}catch(e){t={error:e}}finally{try{E&&!E.done&&(r=T.return)&&r.call(T)}finally{if(t)throw t.error}}try{for(var R=o((0,l.mapValues)(S)),I=R.next();!I.done;I=R.next())A=I.value,N.add(A),(0,u.funcExtractDeps)(A,N,!0)}catch(e){i={error:e}}finally{try{I&&!I.done&&(h=R.return)&&h.call(R)}finally{if(i)throw i.error}}try{for(var V=o((0,l.mapValues)(P)),B=V.next();!B.done;B=V.next())A=B.value,N.add(A),(0,u.funcExtractDeps)(A,N,!0)}catch(e){y={error:e}}finally{try{B&&!B.done&&(_=V.return)&&_.call(V)}finally{if(y)throw y.error}}try{for(var F=o((0,l.mapValues)(C)),L=F.next();!L.done;L=F.next())A=L.value,N.add(A),(0,u.funcExtractDeps)(A,N,!0)}catch(e){g={error:e}}finally{try{L&&!L.done&&(b=F.return)&&b.call(F)}finally{if(g)throw g.error}}try{for(var K=o((0,l.mapValues)(N)),G=K.next();!G.done;G=K.next())if(A=G.value,!O.has(A)){var q=f.default.getResolution(A);"replace"===q?(C.add(A),j.set(A,f.default.getBuildDeclaration(A))):"keep"===q?S.add(A):"exclude"===q?D.add(A):("mock"===q||f.default.touches.has(A))&&P.add(A),O.set(A,f.default.touches.has(A)?{dependency:!0,__internal:!0}:{})}}catch(e){m={error:e}}finally{try{G&&!G.done&&(M=K.return)&&M.call(K)}finally{if(m)throw m.error}}try{for(var U=o((0,l.mapEntries)(O)),z=U.next();!z.done;z=U.next()){var W=a(z.value,2),H=W[0],$=W[1];f.default.config.set(H,n(n(n({},f.default.getConfigMock().get(H)),$),{defValue:j.get(H)}))}}catch(e){k={error:e}}finally{try{z&&!z.done&&(w=U.return)&&w.call(U)}finally{if(k)throw k.error}}return(0,p.default)(C,j),(0,c.default)(D),(0,s.default)(P,j),(0,v.default)(S,P,C,x)}},8792:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(5974);t.default=function(e,t,r,o){var a=e===t?o:t,i=null!=r?r:t!==o&&"object"==typeof t?t:void 0;return(0,n.isNgDef)(e,"p")&&"function"==typeof t&&t!==e&&!(0,n.isNgDef)(t,"p")?(a={transform:t},i=r):!(0,n.isNgDef)(e,"i")&&(0,n.isNgDef)(e)||(i=r),{config:i,mock:a=a===i?o:a}}},9102:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(6297));t.default=function(e){var t=(0,o.default)(e);return{multi:t!==e&&e.multi,provide:t}}},70:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(4358),a=n(r(3295)),i=n(r(8911)),l=r(4152),u=n(r(8073));t.default=function(e){if(function(e){if(!e||e===o.DOCUMENT||u.default.touches.has(e))return!0;var t=function(e){var t=u.default.getResolution(e);return"keep"===t||"exclude"===t||"mock"!==t&&void 0}(e);return void 0!==t?t:"function"==typeof e&&-1!==a.default.neverMockProvidedFunction.indexOf(e.name)||!(!(0,l.isNgInjectionToken)(e)||-1===a.default.neverMockToken.indexOf(e.toString()))}(e))return!0;var t=(0,i.default)(e);return!("function"!=typeof e||t&&"platform"!==t)}},4483:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8073));t.default=function(e,t,r,n){return!!o.default.cacheDeclarations.has(n)||!(!e.has(r)||n!==t.get(r))}},4995:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8073)),a=n(r(70));t.default=function(e){return!!(0,a.default)(e)||o.default.config.get("ngMocksDepsSkip").has(e)}},8150:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(5974),a=n(r(8073)),i=r(5395),l=r(8339),u=r(2937);t.default=function(e){void 0===a.default.builtDeclarations.get(e)&&((0,o.isNgDef)(e,"c")&&a.default.builtDeclarations.set(e,(0,i.MockComponent)(e)),(0,o.isNgDef)(e,"d")&&a.default.builtDeclarations.set(e,(0,l.MockDirective)(e)),(0,o.isNgDef)(e,"p")&&a.default.builtDeclarations.set(e,(0,u.MockPipe)(e)))}},4161:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(5974),a=n(r(8073)),i=n(r(8195)),l=n(r(9465)),u=n(r(2415));t.default=function(e,t){if((0,o.isNgDef)(e,"i")&&t.has(e)){var r=a.default.config.get(e),n=t.get(e);a.default.builtProviders.set(e,(0,l.default)(e,void 0,(function(e){return function(e,t,r){return r.precise?t:(0,i.default)(e,t)}(e,n,r)})))}else(0,o.isNgDef)(e,"i")&&a.default.builtProviders.set(e,(0,u.default)(e,!0));if(!(0,o.isNgDef)(e)&&t.has(e)){var f=t.get(e);a.default.builtProviders.set(e,(0,l.default)(e,void 0,(function(){return f})))}else(0,o.isNgDef)(e)||a.default.builtProviders.set(e,(0,u.default)(e,!0))}},2938:function(e,t){Object.defineProperty(t,"__esModule",{value:!0})},5395:function(e,t,r){var n,o=this&&this.__extends||(n=function(e,t){return n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},n(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),a=this&&this.__assign||function(){return a=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},l=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},u=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockComponents=function(){for(var e=[],t=0;t=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0});var o=r(860),a={read:o.ViewContainerRef,static:!1},i={read:o.TemplateRef,static:!1},l=function(e,t){var r="
");return"").concat(r,"")},u=function(e){return!(e.isViewQuery||e.read&&e.read!==o.TemplateRef||"string"!=typeof e.selector&&!e.read)};t.default=function(e){var t,r,f=[""];if(!e)return f.join("");try{for(var c=n(Object.keys(e)),d=c.next();!d.done;d=c.next()){var s=d.value,v=e[s];if(0!==s.indexOf("__mock")&&u(v)){if("string"==typeof v.selector){var p=v.selector.replace(new RegExp("\\W","mg"),"_");e["__vcrIf_key_".concat(p)]=new o.ViewChild("ngIf_key_".concat(p),a),e["__trIf_key_".concat(p)]=new o.ViewChild("ngIf_key_".concat(p),i),e["__mockView_key_".concat(p)]=new o.ViewChild("key_".concat(p),a),e["__mockTpl_key_".concat(p)]=v,f.push(l(p,"key"))}e["__vcrIf_prop_".concat(s)]=new o.ViewChild("ngIf_prop_".concat(s),a),e["__trIf_prop_".concat(s)]=new o.ViewChild("ngIf_prop_".concat(s),i),e["__mockView_prop_".concat(s)]=new o.ViewChild("prop_".concat(s),a),f.push(l(s,"prop"))}}}catch(e){t={error:e}}finally{try{d&&!d.done&&(r=c.return)&&r.call(c)}finally{if(t)throw t.error}}return f.join("")}},8970:function(e,t){var r=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i};Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){if("string"==typeof e)return["key","__mockTpl_key_".concat(e),e,void 0];var t=r(e),n=t[0],o=t.slice(1);return["prop",n,n,o.length>0?o:void 0]}},2350:function(e,t){Object.defineProperty(t,"__esModule",{value:!0})},5269:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockDeclarations=function(){for(var e=[],t=0;t=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(1184)),l=a(r(6755)),u=a(r(1692));t.default=function(e,t){return function(r){return!!function(e,t,r){for(var n,a,i,l=(null===(n=e.injector._tNode)||void 0===n?void 0:n.attrs)||[],u=2,f=0;f0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(5465)),i=o(r(908));t.default=function(e){return function(t){var r=n((0,i.default)(t),2),o=r[0];return-1!==r[1].indexOf(e)||!!(0,a.default)(o,e)}}},12:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4201)),a=r(6739);t.default=function(e){var t=(0,a.getSourceOfMock)(e);return function(e){return!!e&&-1!==e.providerTokens.indexOf(t)&&void 0!==(0,o.default)(t,e.injector)}}},1863:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return function(t){return!!t.references[e]}}},5494:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(908)),i=o(r(4747));t.default=function(e){return function(t){var r=n((0,a.default)(t),1)[0];return(0,i.default)(r,e)}}},5465:function(e,t){var r=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){var n,o,a,i;try{for(var l=r(e),u=l.next();!u.done;u=l.next()){var f=u.value.match(/\[([^=\]]+)/g);if(f)try{for(var c=(a=void 0,r(f)),d=c.next();!d.done;d=c.next())if(d.value==="[".concat(t))return!0}catch(e){a={error:e}}finally{try{d&&!d.done&&(i=c.return)&&i.call(c)}finally{if(a)throw a.error}}}}catch(e){n={error:e}}finally{try{u&&!u.done&&(o=l.return)&&o.call(l)}finally{if(n)throw n.error}}return!1}},4476:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8864)),a=n(r(8060)),i=n(r(12)),l=n(r(1863)),u=n(r(5494));t.default=function(e){if(function(e){return Array.isArray(e)&&1===e.length&&"string"==typeof e[0]}(e))return(0,o.default)(e[0]);if(function(e){return Array.isArray(e)&&2===e.length&&"string"==typeof e[0]}(e))return(0,a.default)(e[0],e[1]);if(function(e){return"string"==typeof e&&0===e.indexOf("#")&&e.length>1}(e))return(0,l.default)(e.slice(1));if(function(e){return"string"==typeof e&&0!==e.indexOf("#")&&e.length>0}(e))return(0,u.default)(e);if(function(e){return"function"==typeof e}(e))return(0,i.default)(e);throw new Error("Unknown selector")}},908:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0});var n=new RegExp("\\[.*?\\]","g");t.default=function(e,t){var o,a,i,l;try{for(var u=r(e),f=u.next();!f.done;f=u.next()){var c=f.value.replace(n,"").split(",");try{for(var d=(i=void 0,r(c)),s=d.next();!s.done;s=d.next())if(s.value.trim()===t)return!0}catch(e){i={error:e}}finally{try{s&&!s.done&&(l=d.return)&&l.call(d)}finally{if(i)throw i.error}}}}catch(e){o={error:e}}finally{try{f&&!f.done&&(a=u.return)&&a.call(u)}finally{if(o)throw o.error}}return!1}},3942:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return"#text"===e.nativeNode.nodeName}},5079:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){return!(!e||!t)&&e===t}},6121:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(3942));t.default=function(e){return(0,o.default)(e)?void 0:e.injector._tNode||e.injector.elDef||void 0}},1061:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=r(860),l=a(r(4201)),u=a(r(6121)),f=function(e,t){var r=function(e,t){if(e!==t&&"#comment"===t.nativeNode.nodeName)return(0,l.default)(i.ViewContainerRef,t.injector)}(e,t);if(!r)return[];for(var n=[],o=0;o0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(590)),i=o(r(5687)),l=o(r(951)),u=o(r(4476)),f=o(r(3942)),c=o(r(6547)),d=o(r(8344));t.default=function(){for(var e=[],t=0;t0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(590)),i=o(r(5687)),l=o(r(951)),u=o(r(4811)),f=o(r(4476)),c=o(r(3942)),d=o(r(6547)),s=o(r(8344)),v={};t.default=function(){for(var e=[],t=0;t=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3942)),i=o(r(5079)),l=o(r(6121)),u=o(r(1061));t.default=function(e){var t,r,o,f,c=(0,l.default)(e);if(!c||(0,a.default)(e))return[];var d=void 0!==e.childNodes,s=[];try{for(var v=n(e.childNodes||(null===(o=e.parent)||void 0===o?void 0:o.childNodes)||[]),p=v.next();!p.done;p=v.next()){var h=p.value,y=(0,u.default)(h);(d||(0,i.default)(c,y))&&(y&&!(0,i.default)(c,y)||s.push(h))}}catch(e){t={error:e}}finally{try{p&&!p.done&&(r=v.return)&&r.call(v)}finally{if(t)throw t.error}}if("BODY"===(null===(f=e.parent)||void 0===f?void 0:f.name)){for(var _=e.parent.childNodes,g=_.length,b=0,m=_.length-1;m>=0;m-=1)if("#comment"===(h=_[m]).nativeNode.nodeName)b=m;else if(h.nativeNode===e.nativeNode){g=m+1;break}for(m=g;m=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(5079)),i=o(r(6121)),l=o(r(1061));t.default=function(e,t){var r,o,u;if(t)return t;var f=(0,l.default)(e),c=e.parent?(0,i.default)(e.parent):void 0;if(e.parent&&(0,a.default)(f,c))return e.parent;try{for(var d=n((null===(u=e.parent)||void 0===u?void 0:u.childNodes)||[]),s=d.next();!s.done;s=d.next()){var v=s.value,p=(0,i.default)(v);if((0,a.default)(f,p))return v}}catch(e){r={error:e}}finally{try{s&&!s.done&&(o=d.return)&&o.call(d)}finally{if(r)throw r.error}}}},8732:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3942)),i=o(r(7790)),l=o(r(345)),u=function(e,t,r,o){var f,c;if(void 0===o&&(o=!1),!e)return!1;if(!o&&(0,a.default)(e))return!1;if(r(e,(0,l.default)(e,t)))return!0;try{for(var d=n((0,i.default)(e)),s=d.next();!s.done;s=d.next()){var v=s.value;if(u(v,e,r,o))return!0}}catch(e){f={error:e}}finally{try{s&&!s.done&&(c=d.return)&&c.call(d)}finally{if(f)throw f.error}}return!1};t.default=u},6016:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2023)),a=n(r(4201)),i=["Cannot find ControlValueAccessor on the element.","If it is a mock input with [formControlName],","you need either to avoid mocking ReactiveFormsModule","or to avoid accessing the control in such a way,","because this tests ReactiveFormsModule instead of own implementation."].join(" ");t.default=function(e){var t=o.default&&(0,a.default)(o.default.NgControl,e.injector),r=null==t?void 0:t.valueAccessor;if(r)return r;var n=o.default&&(0,a.default)(o.default.FormControlDirective,e.injector);if(null==n?void 0:n.form)return n.form;var l=o.default&&(0,a.default)(o.default.NgModel,e.injector);if(l)return l;throw new Error(i)}},2298:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(2023)),i=r(7105),l=o(r(5006)),u=o(r(7331)),f=o(r(1991)),c=o(r(590)),d=o(r(5687)),s=o(r(4811)),v=o(r(589)),p=o(r(6016)),h=["onChange","onChangeCallback","onChangeCb","onChangeClb","onChangeFn","_onChange","_onChangeCallback","_onChangeCb","_onChangeClb","_onChangeFn","changeFn","_changeFn","onModelChange","cvaOnChange","cvaOnChangeCallback","cvaOnChangeCb","cvaOnChangeClb","cvaOnChangeFn","_cvaOnChange","_cvaOnChangeCallback","_cvaOnChangeCb","_cvaOnChangeClb","_cvaOnChangeFn"];t.default=function(e,t,r){var o,y,_=(0,c.default)((0,d.default)(),e,void 0);if(!_)throw new Error("Cannot find an element via ngMocks.change(".concat((0,s.default)(e),")"));var g=(0,p.default)(_);if(!function(e,t){return a.default&&e instanceof a.default.AbstractControl?(e.setValue(t),!0):a.default&&e instanceof a.default.NgModel?(e.update.emit(t),!0):!!(0,i.isMockControlValueAccessor)(e.instance)&&(e.instance.__simulateChange(t),!0)}(g,t)&&!function(e){return e.listeners.some((function(e){return"input"===e.name||"change"===e.name}))}(_)){try{for(var b=n(r?[r]:h),m=b.next();!m.done;m=b.next()){var M=m.value;if("function"==typeof g[M])return g.writeValue(t),void g[M](t)}}catch(e){o={error:e}}finally{try{m&&!m.done&&(y=b.return)&&y.call(b)}finally{if(o)throw o.error}}var k=(0,u.default)(g);throw new Error(["Unsupported type of ControlValueAccessor,","please ensure it has '".concat(r||"onChange","' method."),"If it is a 3rd-party library, please provide the correct name of the method in the 'methodName' parameter.","Possible Names: "+k.join(", ")+"."].join(" "))}!function(e,t){(0,f.default)(e,"focus");var r=Object.getOwnPropertyDescriptor(e.nativeElement,"value");(0,v.default)(e.nativeElement,"value",t),(0,f.default)(e,"input"),(0,f.default)(e,"change"),r&&((0,l.default)(e.nativeElement,"value",r),e.nativeElement.value=t),(0,f.default)(e,"blur")}(_,t)}},7655:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(2023)),i=r(7105),l=o(r(7331)),u=o(r(1991)),f=o(r(590)),c=o(r(5687)),d=o(r(4811)),s=o(r(6016)),v=["onTouched","onTouchedCallback","onTouchedCb","onTouchedClb","onTouchedFn","_onTouched","_onTouchedCallback","_onTouchedCb","_onTouchedClb","_onTouchedFn","markAsTouched","_markAsTouched","onModelTouched","cvaOnTouch","cvaOnTouchCallback","cvaOnTouchCb","cvaOnTouchClb","cvaOnTouchFn","_cvaOnTouch","_cvaOnTouchCallback","_cvaOnTouchCb","_cvaOnTouchClb","_cvaOnTouchFn"];t.default=function(e,t){var r,o,p=(0,f.default)((0,c.default)(),e,void 0);if(!p)throw new Error("Cannot find an element via ngMocks.touch(".concat((0,d.default)(e),")"));var h=(0,s.default)(p);if(!function(e){return a.default&&e instanceof a.default.AbstractControl?(e.markAsTouched(),!0):!!(0,i.isMockControlValueAccessor)(e.instance)&&(e.instance.__simulateTouch(),!0)}(h)&&!function(e){return e.listeners.some((function(e){return"focus"===e.name||"blur"===e.name}))}(p)){try{for(var y=n(t?[t]:v),_=y.next();!_.done;_=y.next()){var g=_.value;if("function"==typeof h[g])return void h[g]()}}catch(e){r={error:e}}finally{try{_&&!_.done&&(o=y.return)&&o.call(y)}finally{if(r)throw r.error}}var b=(0,l.default)(h);throw new Error(["Unsupported type of ControlValueAccessor,","please ensure it has '".concat(t||"onTouched","' method."),"If it is a 3rd-party library, please provide the correct name of the method in the 'methodName' parameter.","Possible Names: "+b.join(", ")+"."].join(" "))}!function(e){(0,u.default)(e,"focus"),(0,u.default)(e,"blur")}(p)}},9903:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(1991));t.default=function(e,t){(0,o.default)(e,"click",t)}},6843:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});for(var l=i(r(8195)),u=["focus","blur","load","unload","change","reset","scroll"],f="function"==typeof Event?function(e,t){return new CustomEvent(e,t)}:function(e,t){var r=n({bubbles:!1,cancelable:!1},t),o=document.createEvent("CustomEvent");return o.initCustomEvent(e,r.bubbles,r.cancelable,null),o},c={alt:{altKey:!0,code:"AltLeft",key:"Alt",location:1,which:18},arrowdown:{code:"ArrowDown",key:"ArrowDown",location:0,which:40},arrowleft:{code:"ArrowLeft",key:"ArrowLeft",location:0,which:37},arrowright:{code:"ArrowRight",key:"ArrowRight",location:0,which:39},arrowup:{code:"ArrowUp",key:"ArrowUp",location:0,which:38},backspace:{code:"Backspace",key:"Backspace",location:0,which:8},control:{code:"ControlLeft",ctrlKey:!0,key:"Control",location:1,which:17},enter:{code:"Enter",key:"Enter",location:0,which:13},esc:{code:"Escape",key:"Escape",location:0,which:27},meta:{code:"MetaLeft",key:"Meta",location:1,metaKey:!0,which:91},shift:{code:"ShiftLeft",key:"Shift",location:1,shiftKey:!0,which:16},space:{code:"Space",key:" ",location:0,which:32},tab:{code:"Tab",key:"Tab",location:0,which:9}},d=1;d<=12;d+=1)c["f".concat(d)]={code:"F".concat(d),key:"F".concat(d),location:0,which:d+111};t.default=function(e,t,r){var i=e.indexOf("."),d=a(-1===i?[e]:[e.slice(0,Math.max(0,i)),e.slice(i+1)],2),s=d[0],v=d[1],p=f(s,n({bubbles:-1===u.indexOf(e),cancelable:!0},t));return function(e,t){var r,n,a,i,u={};try{for(var f=o(t?t.split("."):[]),d=f.next();!d.done;d=f.next()){var s=d.value,v=c[s];if(v||1!==s.length||(v={code:(a=s,void 0,i=a.codePointAt(0),i&&i>=97&&i<=122||i&&i>=65&&i<=90?"Key".concat(a.toUpperCase()):i&&i>=48&&i<=57?"Digit".concat(a):"Unknown"),key:s}),!v)throw new Error("Unknown event part ".concat(s));(0,l.default)(u,v)}}catch(e){r={error:e}}finally{try{d&&!d.done&&(n=f.return)&&n.call(f)}finally{if(r)throw r.error}}t&&(0,l.default)(e,u)}(p,v),r&&(0,l.default)(p,r),p}},1991:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(590)),a=n(r(771)),i=n(r(4792)),l=n(r(4993)),u=n(r(5687)),f=n(r(8195)),c=n(r(6843)),d=["focus","blur","load","unload","change","reset","scroll"];t.default=function(e,t,r){var n,s=(n=(0,l.default)(e)?e:(0,o.default)((0,u.default)(),e,void 0),(0,a.default)(n)||(0,i.default)(n)?n.nativeElement:(0,l.default)(n)?n:void 0);if(!s)throw new Error("Cannot trigger ".concat("string"==typeof t?t:t.type," event undefined element"));if(!s.disabled){var v=function(e){return"string"==typeof e?(0,c.default)(e,{bubbles:-1===d.indexOf(e),cancelable:!0}):e}(t);v.target||(0,f.default)(v,{target:s}),r&&(0,f.default)(v,r),s.dispatchEvent(v)}}},343:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(5974);t.default=function(e){return"function"==typeof e||(0,n.isNgDef)(e,"t")}},4212:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=r(6739),l=r(5974),u=o(r(8344)),f=o(r(590)),c=o(r(1771)),d=o(r(5687)),s=o(r(951)),v=o(r(4811)),p=o(r(343)),h={};t.default=function(){for(var e=[],t=0;t0}),!0);else try{b.push((0,a.getInjection)(g))}catch(e){if(!e||"object"!=typeof e||void 0===e.ngTempTokenPath)throw e}if(b.length>0)return b[0];if(_!==h)return _;throw new Error("Cannot find an instance via ngMocks.findInstance(".concat((0,v.default)(y),")"))}},147:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=r(6456),l=r(6739),u=r(5974),f=a(r(8344)),c=a(r(7316)),d=a(r(1771)),s=a(r(5687)),v=a(r(951)),p=a(r(343));t.default=function(){for(var e,t,r=[],a=0;a0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(4792)),i=o(r(5687)),l=function(e){return(0,a.default)(e)?l(e.debugElement):e&&e.injector&&e.query?e:void 0};t.default=function(e,t){var r,o,a,u,f=t;return 3===e.length?(a=l(e[0]),u=e[1],f=e[2]):1===e.length?(a=l((0,i.default)()),u=n(e,1)[0]):e[0]?(a=l(e[0]))?u=e[1]:(a=l((0,i.default)()),u=(r=n(e,2))[0],f=r[1]):u=e[1],[a,u=null!==(o=l(u))&&void 0!==o?o:u,f]}},654:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(1165),o=r(6739);t.default=function(e){return Array.isArray(e)?n.By.css(1===e.length?"[".concat(e[0],"]"):"[".concat(e[0],'="').concat(e[1],'"]')):"string"==typeof e?n.By.css(e):n.By.directive((0,o.getSourceOfMock)(e))}},7316:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(771)),i=o(r(7453)),l=o(r(654));t.default=function(){for(var e=[],t=0;t0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(771)),i=o(r(4811)),l=o(r(7453)),u=o(r(654)),f={};t.default=function(){for(var e=[],t=0;t\\s+<","mg"),"><").replace(new RegExp('"\\s+>',"mg"),'">'):"";return r?n:n.trim()}var o;return(0,i.default)(t)?e(function(e,t){return t?e.outerHTML:e.innerHTML}(t,r)):(0,l.default)(t)?u(e,(0,a.default)(t).replace(new RegExp("&","mg"),"&").replace(new RegExp('"',"mg"),""").replace(new RegExp("<","mg"),"<").replace(new RegExp(">","mg"),">").replace(new RegExp("'","mg"),"'"),r):void 0};t.default=(0,o.default)(u)},9512:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4858)),a=n(r(9280)),i=n(r(4993)),l=n(r(8209)),u=function(e,t,r){if("string"==typeof t||void 0===t){var n=(o=t)?o.replace(new RegExp("\\s+","mg")," "):"";return r?n:n.trim()}var o;return(0,i.default)(t)?e(function(e,t){var r,n=null!==(r=e.textContent)&&void 0!==r?r:"";return t?n:n.trim()}(t,r)):(0,l.default)(t)?u(e,(0,a.default)(t),r):void 0};t.default=(0,o.default)(u)},3341:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t;return"#text"===(null===(t=e.nativeNode)||void 0===t?void 0:t.nodeName)&&e.parent?e.parent:e}},7717:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4201)),a=r(5974);t.default=function(e,t,r){if(t.injector&&"NullInjector"!==t.injector.constructor.name){var n=function(e){for(var t=e;"NullInjector"===(null==t?void 0:t.injector.constructor.name);)t=t.parent;if(t)return t.injector}(t.parent),i=n?(0,o.default)(r,n):void 0,l=(0,o.default)(r,t.injector);i!==l&&((0,a.isNgDef)(r,"t")&&void 0!==l||void 0!==l&&-1===e.indexOf(l))&&e.push(l)}}},2631:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(3341)),a=n(r(1484)),i=function(e){for(var t,r=e,n=null===(t=r.nativeNode)||void 0===t?void 0:t.__ngContext__;void 0===n&&r.parent;)n=(r=r.parent).nativeNode.__ngContext__;if("number"!=typeof n)return n;var o=r.injector._lView;return Array.isArray(o)?function(e,t){if("object"==typeof e[1]&&e[20]===t)return e;for(var r=21;r1&&f[1]&&"object"==typeof f[1]&&f[1].bindingStartIndex&&(v=f[1].bindingStartIndex);for(var p=0;p=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3341)),i=o(r(1484)),l=function(e){var t,r;if(!e||"object"!=typeof e)return e;try{for(var o=n(["renderElement","renderText","instance"]),a=o.next();!a.done;a=o.next()){var i=a.value;if(e[i])return e[i]}}catch(e){t={error:e}}finally{try{a&&!a.done&&(r=o.return)&&r.call(o)}finally{if(t)throw t.error}}return null};t.default=function(e,t,r){if(t&&t._debugContext){var n=(0,a.default)(t);(0,i.default)({el:n,nodes:t._debugContext.view.nodes,normalize:l,proto:r,result:e},!0)}}},1771:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(5974),a=n(r(7717)),i=n(r(2631)),l=n(r(2096));t.default=function(e,t,r){return(0,a.default)(e,t,r),(0,o.isNgDef)(r,"t")||"string"==typeof r||((0,l.default)(e,t,r),(0,i.default)(e,t,r)),e}},5687:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(2603);t.default=function(){var e=(0,n.getTestBed)()._activeFixtures;return e[e.length-1]}},4317:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8073));t.default=function(){var e;o.default.cacheDeclarations.clear(),null===(e=o.default.config.get("ngMocksDepsSkip"))||void 0===e||e.clear()}},4811:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(5974);t.default=function(e){return"string"==typeof e?e:"function"==typeof e?e.name:(0,n.isNgDef)(e,"t")?e._desc:Array.isArray(e)?e[0]:e?"":""}},951:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(771)),i=o(r(4792)),l=o(r(5687));t.default=function(e,t,r){var o,u,f,c,d,s,v=r;return 3===e.length?(c=(o=n(e,3))[0],d=o[1],v=o[2]):1===e.length?(c=(0,l.default)(),d=n(e,1)[0]):t(e[1])&&("string"==typeof(s=e[0])||Array.isArray(s)&&"string"==typeof s[0]||(0,i.default)(s)||(0,a.default)(s),1)?(c=(u=n(e,2))[0],d=u[1]):(c=(0,l.default)(),d=(f=n(e,2))[0],v=f[1]),[c,d,v]}},4641:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4201)),a=n(r(8862)),i=n(r(6297));t.default=function(e,t){if(e)try{var r=(0,i.default)(t);return function(e){try{return(0,a.default)(e)}catch(e){return}}((0,o.default)(r,e.injector).constructor)}catch(e){return}}},5018:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(1184)),l=a(r(590)),u=a(r(5687)),f=a(r(4641)),c=a(r(8027)),d={},s=function(e,t){var r=(0,i.default)(e),n=r.name,o=r.alias,a=void 0===o?"":o;if(!a&&n===t||a&&a===t)return n};t.default=function(e,t){for(var r=[],a=2;a=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3174));t.default=function(e,t){return function(){for(var r=[],o=0;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(8073));t.default=function(e,t){var r,o,l=i.default.getConfigMock();try{for(var u=n((0,a.flatten)(e)),f=u.next();!f.done;f=u.next()){var c=f.value;t?l.set(c,t):l.delete(c)}}catch(e){r={error:e}}finally{try{f&&!f.done&&(o=u.return)&&o.call(u)}finally{if(r)throw r.error}}}},8909:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(8073));t.default=function(e,t){var r,o,l=i.default.getOverrides();try{for(var u=n((0,a.flatten)(e)),f=u.next();!f.done;f=u.next()){var c=f.value;if(t){var d=l.has(c)?l.get(c):new Set;d.add(t),l.set(c,d)}else l.delete(c)}}catch(e){r={error:e}}finally{try{f&&!f.done&&(o=u.return)&&o.call(u)}finally{if(r)throw r.error}}}},1640:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(2603),i=o(r(3174)),l=o(r(8073)),u=l.default.global.get("faster-hooks")||{after:[],before:[]};l.default.global.set("faster-hooks",u);var f=function(e,t){return function(r){var o,f;if(a.TestBed.ngMocksFasterLock)return e.call(t,r);l.default.global.set("bullet:customized",!0);var c=e;try{for(var d=n(u.before),s=d.next();!s.done;s=d.next())c=(0,s.value)(c,t)}catch(e){o={error:e}}finally{try{s&&!s.done&&(f=d.return)&&f.call(d)}finally{if(o)throw o.error}}try{return(0,i.default)(a.TestBed,"ngMocksFasterLock",!0),c.call(t,r)}finally{(0,i.default)(a.TestBed,"ngMocksFasterLock",void 0)}}},c=function(e,t){return function(){var r,o;if(a.TestBed.ngMocksFasterLock)return e.call(t);if(l.default.global.has("bullet"))return l.default.global.has("bullet:customized")&&l.default.global.set("bullet:reset",!0),t;l.default.global.delete("bullet:customized"),l.default.global.delete("bullet:reset");var f=e;try{for(var c=n(u.after),d=c.next();!d.done;d=c.next())f=(0,d.value)(f,t)}catch(e){r={error:e}}finally{try{d&&!d.done&&(o=c.return)&&o.call(c)}finally{if(r)throw r.error}}try{return(0,i.default)(a.TestBed,"ngMocksFasterLock",!0),f.call(t)}finally{(0,i.default)(a.TestBed,"ngMocksFasterLock",void 0)}}};t.default=function(){a.TestBed.ngMocksFasterInstalled||(a.TestBed.configureTestingModule=f(a.TestBed.configureTestingModule,a.TestBed),a.TestBed.resetTestingModule=c(a.TestBed.resetTestingModule,a.TestBed),(0,i.default)(a.TestBed,"ngMocksFasterInstalled",!0));var e=(0,a.getTestBed)();return e.ngMocksFasterInstalled||(e.configureTestingModule=f(e.configureTestingModule,e),e.resetTestingModule=c(e.resetTestingModule,e),(0,i.default)(e,"ngMocksFasterInstalled",!0)),u}},7346:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(2603),a=n(r(8073)),i=n(r(1640)),l=n(r(2776)),u=function(e){var t,r=null!==(t=a.default.global.get("bullet:stack"))&&void 0!==t?t:[];r.push(e),a.default.global.set("bullet:stack",r),a.default.global.set("bullet:stack:id",e)},f=function(e){var t=a.default.global.get("bullet:stack");t.splice(t.indexOf(e),1),t.length>0?a.default.global.set("bullet:stack:id",t[t.length-1]):a.default.global.delete("bullet:stack:id"),function(e){for(var t=(0,o.getTestBed)()._activeFixtures||[],r=0,n=t.length-1;n>=0;n-=1)t[n].ngMocksStackId&&t[n].ngMocksStackId!==e?r+=1:(t[n].ngMocksStackId=void 0,t[n].destroy(),t.splice(n,1));0===r&&(0,l.default)()}(e)};t.default=function(){(0,i.default)();var e={},t={};beforeAll((function(){a.default.global.has("bullet:customized")&&o.TestBed.resetTestingModule(),a.default.global.set("bullet",!0),u(e)})),beforeEach((function(){u(t)})),afterEach((function(){f(t)})),afterAll((function(){f(e),a.default.global.delete("bullet"),a.default.global.has("bullet:reset")&&o.TestBed.resetTestingModule()}))}},2776:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(2603);t.default=function(){var e=(0,n.getTestBed)();e._instantiated=!1,e._moduleFactory=void 0,e._testModuleRef=null}},8027:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(2603),a=n(r(2970)),i=r(6739),l=n(r(345)),u=n(r(590)),f=n(r(1771)),c=n(r(5687)),d=n(r(4811)),s={};t.default=function(){for(var e=[],t=0;t0)return _[0];if(h){var _,g=(0,l.default)(h,void 0);if(g&&"#comment"===g.nativeNode.nodeName&&(_=(0,f.default)([],g,y)).length>0)return _[0]}if(p!==s)return p;throw new Error("Cannot find ".concat((0,a.default)(v)," instance via ngMocks.get"))}},4071:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(6259)),a=n(r(8073)),i=n(r(4317)),l=function(e){a.default.getDefaults().set(e,["exclude"])};t.default=function(e,t){void 0===t&&(t=!1),(0,i.default)(),l(e),t&&(0,o.default)(e,l)}},5228:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(6259)),a=n(r(8073)),i=n(r(4317)),l=function(e){a.default.getDefaults().set(e,["keep"])};t.default=function(e,t){void 0===t&&(t=!1),(0,i.default)(),l(e),t&&(0,o.default)(e,l)}},763:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(6259)),a=n(r(8073)),i=n(r(4317)),l=function(e){a.default.getDefaults().set(e,["mock"])};t.default=function(e,t){void 0===t&&(t=!1),(0,i.default)(),l(e),t&&(0,o.default)(e,l)}},3757:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(5974),a=n(r(8073)),i=n(r(4317));t.default=function(e,t){var r=!0;if(((0,o.isNgDef)(e,"m")&&(0,o.isNgDef)(t,"m")||(0,o.isNgDef)(e,"c")&&(0,o.isNgDef)(t,"c")||(0,o.isNgDef)(e,"d")&&(0,o.isNgDef)(t,"d")||(0,o.isNgDef)(e,"p")&&(0,o.isNgDef)(t,"p"))&&(r=!1),r)throw new Error("Cannot replace the declaration, both have to be a Module, a Component, a Directive or a Pipe");(0,i.default)(),a.default.getDefaults().set(e,["replace",t])}},4102:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(6259)),a=n(r(8073)),i=n(r(4317)),l=n(r(8909)),u=function(e){a.default.getDefaults().delete(e),(0,l.default)(e)};t.default=function(e,t){void 0===t&&(t=!1),(0,i.default)(),u(e),t&&(0,o.default)(e,u)}},7418:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(5551)),l=r(6456),u=a(r(1345)),f=a(r(6297)),c=r(5974),d=r(4152),s=r(3659),v=a(r(8073)),p=r(5395),h=r(8339),y=r(3821),_=r(2937),g=a(r(2415)),b=function(e,t,r){return!!t.has(e)||(t.add(e),r.has(e))},m=function(e,t,r,n,o){var a=e.get(t)||t;(0,c.isNgDef)(a,"m")?r.push(a):(0,c.isNgDef)(a,"c")||(0,c.isNgDef)(a,"d")?n.push(a):(0,c.isNgDef)(a,"p")?(n.push(a),o.push(a)):(0,d.isNgInjectionToken)(a)||o.push(a)},M=[["m","module"],["c","component"],["d","directive"],["p","pipe"]],k=function(e,t,r,n){b(t,e.skip,e.exclude)||n.push(e.keep.has(t)?t:r(t))},w=function(e,t){var r=e.skip,n=e.keep,o=e.providers,a=e.exclude,i=(0,f.default)(t);if(r.add(i),!a.has(i)){var l=n.has(i)?t:(0,g.default)(t);l&&o.push(l)}},O={component:p.MockComponent,directive:h.MockDirective,pipe:_.MockPipe},x=function(e,t,r){if(void 0===r&&(r=!0),t){var a,i=function(e,t){var r,a;if((0,s.isNgModuleDefWithProviders)(e))return"module-with-providers";try{for(var i=n(M),l=i.next();!l.done;l=i.next()){var u=o(l.value,2),f=u[0],d=u[1];if((0,c.isNgDef)(e,f))return"m"===f&&t.has(e)?"".concat(d,"-keep"):d}}catch(e){r={error:e}}finally{try{l&&!l.done&&(a=i.return)&&a.call(i)}finally{if(r)throw r.error}}return""}(t,e.keep);if("module-with-providers"!==i){var f=e.optional.get(t);f&&f!==t&&(a=f,e.keep.add(a))}a||(a=t),function(e,t,r,o){"module-with-providers"===t?function(e,t){e.skip.has(t.ngModule)||(e.skip.add(t.ngModule),e.exclude.has(t.ngModule)||e.imports.push(e.keep.has(t.ngModule)?t:(0,y.MockModule)(t)))}(e,r):"module-keep"===t||"module"===t&&o?k(e,r,y.MockModule,e.imports):"module"===t?function(e,t,r){var o,a,i,f;if(!b(t,e.skip,e.exclude)){var c=(0,u.default)(t);try{for(var d=n((0,l.flatten)([c.declarations,c.imports])),s=d.next();!s.done;s=d.next())r(e,h=s.value)}catch(e){o={error:e}}finally{try{s&&!s.done&&(a=d.return)&&a.call(d)}finally{if(o)throw o.error}}try{for(var v=n(c.providers?(0,l.flatten)(c.providers):[]),p=v.next();!p.done;p=v.next()){var h=p.value;w(e,h)}}catch(e){i={error:e}}finally{try{p&&!p.done&&(f=v.return)&&f.call(v)}finally{if(i)throw i.error}}}}(e,r,x):O[t]?k(e,r,O[t],e.declarations):w(e,r)}(e,i,a,r)}};t.default=function(e,t,r){var o,a,u,f,c,d;void 0===t&&(t=null),void 0===r&&(r=null);var s=function(e,t,r){var o=new Set((0,l.flatten)(e||[])),a=new Set((0,l.flatten)(t||[])),i=new Set((0,l.flatten)(r||[])),u=new Map;return function(e,t,r,o){var a,i;try{for(var u=n((0,l.mapKeys)(v.default.getDefaults())),f=u.next();!f.done;f=u.next()){var c=f.value,d=v.default.getBuildDeclaration(c);e.has(c)||t.has(c)||r.has(c)||(o.set(c,d),null===d?r.add(c):void 0===d?t.add(c):c===d&&e.add(c))}}catch(e){a={error:e}}finally{try{f&&!f.done&&(i=u.return)&&i.call(u)}finally{if(a)throw a.error}}}(o,a,i,u),{declarations:[],exclude:i,imports:[],keep:o,mock:a,optional:u,providers:[],skip:new Set}}(e,t,r),p=new Map;v.default.config.set("ngMocksDepsResolution",p);try{for(var h=n((0,l.mapValues)(s.keep)),y=h.next();!y.done;y=h.next()){var _=y.value;p.set(_,"keep")}}catch(e){o={error:e}}finally{try{y&&!y.done&&(a=h.return)&&a.call(h)}finally{if(o)throw o.error}}try{for(var g=n((0,l.mapValues)(s.exclude)),b=g.next();!b.done;b=g.next())_=b.value,p.set(_,"exclude")}catch(e){u={error:e}}finally{try{b&&!b.done&&(f=g.return)&&f.call(g)}finally{if(u)throw u.error}}v.default.config.set("mockNgDefResolver",new i.default);try{for(var M=n((0,l.mapValues)(s.mock)),k=M.next();!k.done;k=M.next()){var w=k.value;p.set(w,"mock"),s.optional.has(w)||x(s,w,!1)}}catch(e){c={error:e}}finally{try{k&&!k.done&&(d=M.return)&&d.call(M)}finally{if(c)throw c.error}}var O=function(e){var t,r,o=e.keep,a=e.skip,i=e.optional,l=e.exclude,u=e.imports,f=e.declarations,c=e.providers;try{for(var d=n(o),s=d.next();!s.done;s=d.next()){var v=s.value;a.has(v)||l.has(v)||i.has(v)||m(i,v,u,f,c)}}catch(e){t={error:e}}finally{try{s&&!s.done&&(r=d.return)&&r.call(d)}finally{if(t)throw t.error}}return{declarations:f,imports:u,providers:c}}(s);return v.default.config.delete("mockNgDefResolver"),v.default.config.delete("ngMocksDepsResolution"),O}},7411:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3295)),i=o(r(8073)),l=o(r(8344)),u=o(r(8458)),f=o(r(9400)),c=o(r(2298)),d=o(r(7655)),s=o(r(9903)),v=o(r(6843)),p=o(r(1991)),h=o(r(590)),y=o(r(7316)),_=o(r(4212)),g=o(r(147)),b=o(r(8062)),m=o(r(9512)),M=o(r(3539)),k=o(r(7977)),w=o(r(9311)),O=o(r(2237)),x=o(r(8909)),j=o(r(7346)),D=o(r(2776)),S=o(r(8027)),P=o(r(4071)),C=o(r(5228)),N=o(r(763)),T=o(r(3757)),E=o(r(4102)),A=o(r(7418)),R=o(r(7411)),I=o(r(5526)),V=o(r(2448)),B=o(r(8195)),F=o(r(589)),L=o(r(3048)),K=o(r(2120)),G=o(r(1368)),q=o(r(5535)),U=["onMockBuilderMissingDependency","onMockInstanceRestoreNeed","onTestBedFlushNeed"];t.default={autoSpy:M.default,change:c.default,click:s.default,config:function(e){var t,r,o=i.default.global.get("flags");try{for(var l=n(U),u=l.next();!u.done;u=l.next()){var f=u.value;null===e[f]?o[f]=a.default[f]:void 0!==e[f]&&(o[f]=e[f])}}catch(e){t={error:e}}finally{try{u&&!u.done&&(r=l.return)&&r.call(l)}finally{if(t)throw t.error}}null===e.mockRenderCacheSize?i.default.global.delete("mockRenderCacheSize"):void 0!==e.mockRenderCacheSize&&i.default.global.set("mockRenderCacheSize",e.mockRenderCacheSize)},crawl:l.default,defaultConfig:O.default,defaultMock:x.default,event:v.default,faster:j.default,find:h.default,findAll:y.default,findInstance:_.default,findInstances:g.default,findTemplateRef:G.default,findTemplateRefs:q.default,flushTestBed:D.default,formatHtml:b.default,formatText:m.default,get:S.default,globalExclude:P.default,globalKeep:C.default,globalMock:N.default,globalReplace:T.default,globalWipe:E.default,guts:A.default,hide:L.default,ignoreOnConsole:k.default,input:R.default,output:I.default,render:K.default,reset:V.default,reveal:u.default,revealAll:f.default,stub:B.default,stubMember:F.default,throwOnConsole:w.default,touch:d.default,trigger:p.default}},5526:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=i(r(7331)),u=i(r(7794)),f=i(r(5020)),c=i(r(445));t.default=function(e,t,r){var i,d;if("string"==typeof t)return c.default.mock(e,t,r);var s=e,v=t,p=["__zone_symbol__unconfigurables"];"function"==typeof t&&(s=c.default.createClone(t),v=e,p.push.apply(p,o([],n(Object.getOwnPropertyNames(s)),!1)));var h=o(o([],n((0,l.default)(v)),!1),n((0,u.default)(v)),!1);try{for(var y=a(h),_=y.next();!_.done;_=y.next()){var g=_.value,b=-1===p.indexOf(g)?(0,f.default)(v,g):void 0;b&&Object.prototype.hasOwnProperty.call(b,"value")&&void 0===b.value||c.default.definePropertyDescriptor(s,g,b)}}catch(e){i={error:e}}finally{try{_&&!_.done&&(d=y.return)&&d.call(y)}finally{if(i)throw i.error}}return s}},6189:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.ngMocks=void 0;var o=n(r(492));t.ngMocks=o.default},845:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=r(860),l=a(r(2137)),u=function(e,t,r){return!!e&&t instanceof i.TemplateRef&&r(t)},f=function(e,t,r){var a,c;if(!(0,l.default)(e))throw new Error("Only instances of mock declarations are accepted");if(function(e,t,r){return!!e.__template&&!!e.__vcr&&t(e.__template)&&r(e.__vcr,e.__template)}(e,t,r))return!0;try{for(var d=n(function(e){var t,r,o=[];try{for(var a=n(e.__ngMocksConfig.queryScanKeys||[]),l=a.next();!l.done;l=a.next())for(var u=l.value,f=e[u],c=e["__ngMocksVcr_".concat(u)],d=f instanceof i.QueryList?f.toArray():[f],s=c instanceof i.QueryList?c.toArray():[c],v=0;v0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(8732)),i=o(r(590)),l=o(r(5687)),u=o(r(951)),f=o(r(4811)),c=o(r(2789)),d=o(r(6703)),s=o(r(7845)),v={};t.default=function(){for(var e=[],t=0;t0)return y[0];if(h!==v)return h;throw new Error("Cannot find a TemplateRef via ngMocks.findTemplateRef(".concat((0,f.default)(p),")"))}},5535:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(8732)),i=o(r(590)),l=o(r(5687)),u=o(r(951)),f=o(r(2789)),c=o(r(6703)),d=o(r(7845));t.default=function(){for(var e=[],t=0;t=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(8073)),l=a(r(589));t.default=function(e){var t,r,a=[],u=i.default.configInstance.get(e);if(null==u?void 0:u.overloads){var f=function(e,t,r){e?a.push((function(n){(0,l.default)(n,e,t,r)})):a.push(t)};try{for(var c=n(u.overloads),d=c.next();!d.done;d=c.next()){var s=o(d.value,3);f(s[0],s[1],s[2])}}catch(e){t={error:e}}finally{try{d&&!d.done&&(r=c.return)&&r.call(c)}finally{if(t)throw t.error}}}return a}},6691:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(2970)),i=o(r(8073));t.default=function(e){for(var t=[];e.length>0;){var r=n(e.pop()||[],2),o=r[0];r[1]===i.default.configInstance.get(o)&&t.push("function"==typeof o?(0,a.default)(o):o)}if(t.length>0){var l=i.default.global.get("flags"),u=["MockInstance: side effects have been detected (".concat(t.join(", "),")."),"Forgot to add MockInstance.scope() or to call MockInstance.restore()?"].join(" ");if("warn"===l.onMockInstanceRestoreNeed)console.warn(u);else if("throw"===l.onMockInstanceRestoreNeed)throw new Error(u)}}},3001:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockInstance=h,t.MockReset=function(){f.default.configInstance.clear()};var i,l=a(r(6804)),u=a(r(7592)),f=a(r(8073)),c=a(r(6691));u.default.subscribePush((function(e){i=e})),u.default.subscribePop((function(e,t){var r,a;try{for(var l=o(e.mockInstance||[]),u=l.next();!u.done;u=l.next()){var c=u.value;if(f.default.configInstance.has(c)){var d=f.default.configInstance.get(c);d.overloads.pop(),f.default.configInstance.set(c,n({},d))}}}catch(e){r={error:e}}finally{try{u&&!u.done&&(a=l.return)&&a.call(l)}finally{if(r)throw r.error}}i=t[t.length-1]}));var d=function(e){var t={};return"string"==typeof e[0]?(t.key=e[0],t.value=e[1],t.accessor=e[2]):(t.value=e[0],t.value&&"object"==typeof t.value&&(t.value=t.value.init)),t},s=[],v=!1;"undefined"!=typeof beforeEach&&(beforeEach((function(){return v=!0})),beforeEach((function(){return(0,c.default)(s)})),afterEach((function(){return v=!1})));var p=function(e,t,r,o){var a,l=f.default.configInstance.has(e)?f.default.configInstance.get(e):{},u=l.overloads||[];u.push([t,r,o]),l.overloads=u,f.default.configInstance.set(e,n({},l));var c=null!==(a=i.mockInstance)&&void 0!==a?a:[];return c.push(e),i.mockInstance=c,v&&s.push([e,f.default.configInstance.get(e),i]),r};function h(e){for(var t=[],r=1;r0){var o=d(t),a=o.key,u=o.value,c=o.accessor;return p(e,a,u,c)}var v=f.default.configInstance.get(e)||{};f.default.configInstance.set(e,n(n({},v),{overloads:[]}));for(var h=s.length-1;h>=0;h-=1)s[h][0]===e&&s[h][2]===i&&s.splice(h,1)}!function(e){e.remember=function(){u.default.stackPush()},e.restore=function(){u.default.stackPop()},e.scope=function(t){void 0===t&&(t="case"),"all"!==t&&"suite"!==t||(beforeAll(e.remember),afterAll(e.restore)),"all"!==t&&"case"!==t||(beforeEach(e.remember),afterEach(e.restore))}}(h||(t.MockInstance=h={}))},9988:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(6297)),l=r(5974),u=r(3659),f=a(r(8073)),c=r(5395),d=r(8339),s=r(2937),v=a(r(445)),p=r(3821),h=[["c",c.MockComponent],["d",d.MockDirective],["p",s.MockPipe]];t.default=function(e,t){var r=function(e,t){return function(r){var a;if(e.has(r))return function(e,t,r){var n=t.get(e);return e!==n&&r(),n}(r,e,t);var c=(0,i.default)(r);if(f.default.isExcludedDef(c))return function(e,t,r){t.set(e,void 0),r()}(r,e,t);f.default.touches.add(c);var d=function(e){var t,r;if((0,l.isNgDef)(e,"m")||(0,u.isNgModuleDefWithProviders)(e))return(0,p.MockModule)(e);if(f.default.hasBuildDeclaration(e))return f.default.getBuildDeclaration(e);if(f.default.flags.has("skipMock")&&"mock"!==f.default.getResolution(e))return e;try{for(var a=n(h),i=a.next();!i.done;i=a.next()){var c=o(i.value,2),d=c[0],s=c[1];if((0,l.isNgDef)(e,d))return s(e)}}catch(e){t={error:e}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}}(r);return function(e,t){return(0,u.isNgModuleDefWithProviders)(t)&&(0,u.isNgModuleDefWithProviders)(e)}(r,d)&&e.set(r.ngModule,d.ngModule),f.default.flags.has("skipMock")&&(null===(a=f.default.config.get("ngMocksDepsSkip"))||void 0===a||a.add(d)),e.set(r,d),t(d!==r),d}}(t,e),a=function(e,t){return function(r){return v.default.resolveProvider(r,e,t)}}(t,e);return{resolve:r,resolveProvider:a}}},6860:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(6297)),l=o(r(7610));t.default=function(e){var t,r;try{for(var o=n((0,a.flatten)(null!=e?e:[])),u=o.next();!u.done;u=o.next()){var f=u.value,c=(0,i.default)(f);(0,l.default)(c)}}catch(e){t={error:e}}finally{try{u&&!u.done&&(r=o.return)&&r.call(o)}finally{if(t)throw t.error}}}},3821:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockModule=function(e){var t;(0,v.default)(e,"MockModule");var r=w(e),n=r.ngModule,o=r.ngModuleProviders,a=M(n);try{var i=x(n,O(n,a.isRootModule));g.default.flags.has("cacheModule")&&g.default.cacheDeclarations.set(n,i),g.default.flags.has("skipMock")&&(null===(t=g.default.config.get("ngMocksDepsSkip"))||void 0===t||t.add(i));var l=j(o);return D(e,n,o,i,l)}finally{k(a)}};var i=r(860),l=a(r(3295)),u=a(r(3174)),f=r(6456),c=a(r(1345)),d=a(r(615)),s=a(r(2970)),v=a(r(6804)),p=r(6763),h=r(5974),y=r(3659),_=r(1946),g=a(r(8073)),b=a(r(5937)),m=a(r(224)),M=function(e){var t=!1,r=!0;g.default.flags.has("hasRootModule")?r=!1:g.default.flags.add("hasRootModule");var n=g.default.getResolution(e);return function(e){return"mock"===e&&g.default.flags.has("skipMock")}(n)&&(t=!0,g.default.flags.delete("skipMock")),function(e){return-1!==l.default.neverMockModule.indexOf((0,s.default)(e))&&!g.default.flags.has("skipMock")}(e)&&(t=!0,g.default.flags.add("skipMock")),r||!function(e){return"keep"===e&&!g.default.flags.has("skipMock")}(n)&&!function(e){return"replace"===e&&!g.default.flags.has("skipMock")}(n)||(t=!0,g.default.flags.add("skipMock")),{isRootModule:r,toggleSkipMockFlag:t}},k=function(e){var t=e.isRootModule,r=e.toggleSkipMockFlag;r&&g.default.flags.has("skipMock")?g.default.flags.delete("skipMock"):r&&!g.default.flags.has("skipMock")&&g.default.flags.add("skipMock"),t&&g.default.flags.delete("hasRootModule")},w=function(e){var t,r;return(0,y.isNgModuleDefWithProviders)(e)?(t=e.ngModule,e.providers&&(r=e.providers)):t=e,{ngModule:t,ngModuleProviders:r}},O=function(e,t){var r;if((0,p.isMockNgDef)(e,"m"))return e;if(g.default.flags.has("cacheModule")&&g.default.cacheDeclarations.has(e))return(0,b.default)(e);if(!t&&"mock"!==(null===(r=g.default.config.get("ngMocksDepsResolution"))||void 0===r?void 0:r.get(e))&&g.default.hasBuildDeclaration(e)){var n=g.default.getBuildDeclaration(e);if((0,h.isNgDef)(n,"m")&&n!==e)return n}},x=function(e,t){var r=o(t?[!1]:(0,m.default)((0,c.default)(e),e),3),n=r[0],a=r[1],l=r[2];if(l&&(0,u.default)(e,"__ngMocksResolutions",l),n){var s=g.default.flags.has("skipMock")?e:_.Mock,v=(0,f.extendClass)(s);return(0,i.NgModule)(a)(v),(0,d.default)(v,e),v}return t||e},j=function(e){if(e){var t=o((0,m.default)({providers:e,skipExports:!0}),2),r=t[0],n=t[1];return r?n.providers:e}},D=function(e,t,r,o,a){return o===t&&a===r?e:(0,y.isNgModuleDefWithProviders)(e)?n({ngModule:o},a?{providers:a}:{}):o}},224:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=i(r(5551)),u=r(6456),f=i(r(6297)),c=i(r(8073)),d=i(r(7610)),s=i(r(9988)),v=i(r(6860)),p=function(e,t){return(0,u.flatten)(e).map(t).filter((function(e){return!!e}))},h=function(e,t,r,o){var a=c.default.config.get(o)||{},i=(0,f.default)(e),l=t(i);if(l){var u=c.default.config.get(i);if((null==u?void 0:u.export)&&o&&!a.export&&c.default.config.set(o,n(n({},a),{export:!0})),!r||a.exportAll||(null==u?void 0:u.export))return(0,d.default)(i,o),l}},y=function(e,t){return!e||!!t.exports&&-1!==t.exports.indexOf(e)};t.default=function(e,t){var r,i,_=c.default.config.has("mockNgDefResolver");_||c.default.config.set("mockNgDefResolver",new l.default),c.default.config.get("mockNgDefResolver").push();var g=!c.default.flags.has("skipMock"),b=function(e){void 0===e&&(e=!0),g=g||e},m=(0,s.default)(b,c.default.config.get("mockNgDefResolver")),M=m.resolve,k=function(e,t,r){var i,l,u,d={},s=function(e,t){return[["declarations",e],["hostDirectives",function(t){var r=(0,f.default)(t),o=e(r);return o===r?t:t==r?o:n(n({},t),{directive:o})}],["imports",e],["entryComponents",e],["bootstrap",e],["providers",t],["viewProviders",t],["exports",e],["schemas",function(e){return e}]]}(t,r),h=c.default.flags.has("cachePipe");h||c.default.flags.add("cachePipe");try{for(var y=o(s),_=y.next();!_.done;_=y.next()){var g=a(_.value,2),b=g[0],m=g[1];(null===(u=e[b])||void 0===u?void 0:u.length)&&(d[b]=p(e[b],m))}}catch(e){i={error:e}}finally{try{_&&!_.done&&(l=y.return)&&l.call(y)}finally{if(i)throw i.error}}return e.skipMarkProviders||((0,v.default)(d.providers),(0,v.default)(d.viewProviders)),h||c.default.flags.delete("cachePipe"),d}(e,M,m.resolveProvider);e.skipExports||function(e,t,r,n,a){var i,l,f=c.default.flags.has("skipMock")||c.default.flags.has("correctModuleExports");try{for(var d=o((0,u.flatten)([r.imports||[],r.declarations||[]])),s=d.next();!s.done;s=d.next()){var v=s.value,p=h(v,e,f,a);y(p,n)||(t(),n.exports=n.exports||[],n.exports.push(p))}}catch(e){i={error:e}}finally{try{s&&!s.done&&(l=d.return)&&l.call(d)}finally{if(i)throw i.error}}}(M,b,e,k,t);try{for(var w=o(t&&k.exports?(0,u.flatten)(k.exports):[]),O=w.next();!O.done;O=w.next()){var x=O.value;(0,d.default)(x,t)}}catch(e){r={error:e}}finally{try{O&&!O.done&&(i=w.return)&&i.call(w)}finally{if(r)throw r.error}}var j=c.default.config.get("mockNgDefResolver").pop();return _||c.default.config.delete("mockNgDefResolver"),[g,k,j]}},3877:function(e,t){Object.defineProperty(t,"__esModule",{value:!0})},2937:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockPipes=function(){for(var e=[],t=0;t=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(8773)),i=o(r(1184)),l=r(5974),u=function(e,t){var r=" ".concat(function(e,t){return"i"===t?"[".concat(e,"]"):"(".concat(e,")")}(e,t),'="');return(r+="i"===t?e:"__ngMocksOutput('".concat(e,"', $event)"))+'"'},f=function(e,t,r){var o,a;if(!e&&"o"===r)return"";var l="",f=null!=e?e:t;try{for(var c=n(t),d=c.next();!d.done;d=c.next()){var s=d.value,v=(0,i.default)(s),p=v.name,h=v.alias;l+=-1===f.indexOf(h||p)?"":u(h||p,r)}}catch(e){o={error:e}}finally{try{d&&!d.done&&(a=c.return)&&a.call(c)}finally{if(o)throw o.error}}return l};t.default=function(e,t){var r=t.selector,n=t.bindings,o=t.inputs,i=t.outputs,u="";return"string"==typeof e?u=e:(0,l.isNgDef)(e,"p")&&n&&-1!==n.indexOf("$implicit")?u="{{ $implicit | ".concat((0,a.default)(e).name," }}"):r&&(u+="<".concat(r),u+=f(n,o,"i"),u+=f(n,i,"o"),u+=">")),u}},2091:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=i(r(3174)),u=i(r(5006)),f=i(r(445)),c=function(e,t,r){var n=function(){if("function"==typeof r[e]){if(t["__ngMocks_".concat(e,"__origin")]!==r[e]){var n=f.default.createClone(r[e],t,r);(0,l.default)(t,"__ngMocks_".concat(e),n),(0,l.default)(t,"__ngMocks_".concat(e,"__origin"),r[e])}return t["__ngMocks_".concat(e)]}return r[e]};return(0,l.default)(n,"__ngMocksProxy",!0),n},d=function(e,t,r){var n=function(n){t["__ngMocks_".concat(e)]&&(t["__ngMocks_".concat(e)]=void 0),t["__ngMocks_".concat(e,"__origin")]&&(t["__ngMocks_".concat(e,"__origin")]=void 0),r[e]=n};return(0,l.default)(n,"__ngMocksProxy",!0),n};t.default=function(e,t,r,i){var s,v;if(void 0===i&&(i=!1),t){(0,l.default)(e,"__ngMocks__source",t);var p,h=(p=e,o(o([],n(Object.getOwnPropertyNames(p)),!1),n(Object.keys(p)),!1)),y=o(o([],n(function(e){return o(o(o([],n(f.default.extractPropertiesFromPrototype(Object.getPrototypeOf(e))),!1),n(f.default.extractMethodsFromPrototype(Object.getPrototypeOf(e))),!1),n(Object.keys(e)),!1)}(t)),!1),n(r),!1);try{for(var _=a(y),g=_.next();!g.done;g=_.next()){var b=g.value;(i||-1===h.indexOf(b))&&((0,u.default)(e,b,{get:c(b,e,t),set:d(b,e,t)}),h.push(b))}}catch(e){s={error:e}}finally{try{g&&!g.done&&(v=_.return)&&v.call(_)}finally{if(s)throw s.error}}}}},6086:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},l=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var u=r(860),f=r(2603),c=l(r(3174)),d=r(6456),s=l(r(8862)),v=r(5974);t.default=function(e){var t,r,l;if(!(0,v.isNgDef)(e,"c")&&!(0,v.isNgDef)(e,"d"))return{};var p=(0,s.default)(e),h={};try{for(var y=i(Object.keys(p)),_=y.next();!_.done;_=y.next()){var g=_.value;"standalone"!==g?h[g]=p[g]:(0,c.default)(h,"__ngMocksStandalone",!!p[g])}}catch(e){t={error:e}}finally{try{_&&!_.done&&(r=y.return)&&r.call(y)}finally{if(t)throw t.error}}return h.selector&&/[\s,[\]]/.test(h.selector)&&(h.selector=""),h.selector||(h.selector=(null===(l=f.TestBed.ngMocksSelectors)||void 0===l?void 0:l.get(e))||"",h.selector||(h.selector="ng-mocks-".concat(e.name),function(e,t){var r,i=(0,d.extendClass)(e),l={provide:e,useExisting:i};t.providers=a(a([],o(t.providers||[]),!1),[l],!1);var c={};try{var s=f.TestBed.ngMocksOverrides.get(e).override;(c=n({},s.set)).providers=c.providers?a(a([],o(c.providers),!1),[l],!1):t.providers}catch(e){}var p=!0===t.__ngMocksStandalone;((0,v.isNgDef)(e,"c")?u.Component:u.Directive)(n(n(n({},t),c),p?{standalone:p}:{}))(i),f.TestBed.configureTestingModule(((r={})[p?"imports":"declarations"]=[i],r))}(e,h),f.TestBed.ngMocksSelectors&&f.TestBed.ngMocksSelectors.set(e,h.selector))),h}},8406:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockRenderFactory=function(e,t,r){void 0===r&&(r={}),(0,f.default)(e,"MockRender");var n="string"==typeof e||(0,c.isNgDef)(e,"t")?{}:(0,g.default)(e),o=(0,y.default)(e,n,t,r),a=m(o,t,e,r);return"root"!==d.default.current().level&&!1!==r.configureTestBed&&a.configureTestBed(),a};var o=r(860),a=r(2603),i=n(r(3174)),l=r(6456),u=n(r(2970)),f=n(r(6804)),c=r(5974),d=n(r(7592)),s=n(r(8073)),v=r(6189),p=n(r(5006)),h=r(5779),y=n(r(3078)),_=n(r(2091)),g=n(r(6086)),b=["Forgot to flush TestBed?","MockRender cannot be used without a reset after TestBed.get / TestBed.inject / TestBed.createComponent and another MockRender in the same test.","If you want to mock a service before rendering, consider usage of MockRenderFactory or MockInstance.","To flush TestBed, add a call of ngMocks.flushTestBed() before the call of MockRender, or pass `reset: true` to MockRender options."].join(" "),m=function(e,t,r,n){var f=function(n,d){f.configureTestBed();var y=a.TestBed.createComponent(e);return(0,_.default)(y.componentInstance,null!=n?n:{},null!=t?t:[]),(0,i.default)(y,"ngMocksStackId",s.default.global.get("bullet:stack:id")),(void 0===d||d)&&y.detectChanges(),"string"==typeof r||(0,c.isNgDef)(r,"c")||(0,c.isNgDef)(r,"d")||e.tpl&&(0,c.isNgDef)(r,"p")?function(e,t,r){e.point=e.debugElement.children[0]&&"#text"!==e.debugElement.children[0].nativeElement.nodeName&&"#comment"!==e.debugElement.children[0].nativeElement.nodeName?e.debugElement.children[0]:e.debugElement,(0,c.isNgDef)(t,"d")?(0,p.default)(e.point,"componentInstance",{get:function(){return v.ngMocks.get(e.point,t)}}):(0,c.isNgDef)(t,"p")&&(0,p.default)(e.point,"componentInstance",{get:function(){return v.ngMocks.findInstance(e.point,t)}}),function(e,t){if(e)try{t()}catch(e){}}(!r,(function(){return(0,_.default)(e.componentInstance,e.point.componentInstance,[])}))}(y,r,n):function(e,t,r){var n;try{n=(0,l.getInjection)(t)}catch(e){if((0,c.isNgDef)(t,"p"))throw new Error(["Cannot render ".concat((0,u.default)(t),"."),"Did you forget to set $implicit param, or add the pipe to providers?","https://ng-mocks.sudo.eu/guides/pipe"].join(" "));throw e}r&&v.ngMocks.stub(n,r),e.point=(0,h.MockService)(o.DebugElement,{childNodes:[],children:[],componentInstance:n,nativeElement:(0,h.MockService)(HTMLElement)}),(0,_.default)(e.componentInstance,e.point.componentInstance,[],!0)}(y,r,n),y};return f.declaration=e,f.bindings=t,f.configureTestBed=function(e,t){return function(){var r,n=(0,a.getTestBed)(),o=(null===(r=n._compiler)||void 0===r?void 0:r.declarations)||n.declarations||n._declarations;if(!o||-1===o.indexOf(e)){!function(e){var t=s.default.global.get("flags"),r=(0,a.getTestBed)();e.reset||!r._instantiated&&!r._testModuleRef?v.ngMocks.flushTestBed():"throw"!==t.onTestBedFlushNeed&&(r._instantiated||r._testModuleRef)&&("warn"===t.onTestBedFlushNeed&&console.warn(b),v.ngMocks.flushTestBed())}(t);try{var l=[];e.providers&&l.push(e.providers),l.push(e),a.TestBed.configureTestingModule({declarations:l})}catch(e){!function(e){var t=new Error(b);throw(0,i.default)(t,"parent",e),t}(e)}}}}(e,n),f}},1661:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0)return!0;var n=e.codePointAt(0);if(n&&n>=65&&n<=90&&null!==t.match(/\bthis\./gm))return!0;var o=new RegExp("\\(this,\\s*".concat(e,"\\)"),"mg");return null!==t.match(o)}(r[1],t,e)}},402:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return null!==e&&"object"==typeof e&&"InjectionToken"!==e.ngMetadataName&&"object"==typeof Object.getPrototypeOf(e)}},1365:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=i(r(5006)),u=i(r(7331)),f=i(r(7794)),c=i(r(5020));t.default=function(e,t,r,i){var d,s,v=function(){for(var n=[],o=0;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3174)),i=o(r(2970)),l=o(r(445));t.default=function(e){var t,r,o,u,f=(0,i.default)(e),c={};(0,a.default)(c,"__ngMocks",!0);var d=l.default.extractMethodsFromPrototype(e);try{for(var s=n(d),v=s.next();!v.done;v=s.next()){var p=v.value;l.default.mock(c,p,f)}}catch(e){t={error:e}}finally{try{v&&!v.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}var h=l.default.extractPropertiesFromPrototype(e);try{for(var y=n(h),_=y.next();!_.done;_=y.next()){var g=_.value;l.default.mock(c,g,"get",f),l.default.mock(c,g,"set",f)}}catch(e){o={error:e}}finally{try{_&&!_.done&&(u=y.return)&&u.call(y)}finally{if(o)throw o.error}}return Object.setPrototypeOf(c,e),c}},5006:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(2970)),i=["sanitize","bypassSecurityTrustHtml","bypassSecurityTrustStyle","bypassSecurityTrustScript","bypassSecurityTrustUrl","bypassSecurityTrustResourceUrl"],l={DomSanitizer:i,Sanitizer:i},u=function(e){var t,r,o,i=Object.getOwnPropertyNames(e);try{for(var u=n(null!==(o=l[(0,a.default)(e)])&&void 0!==o?o:[]),f=u.next();!f.done;f=u.next()){var c=f.value;i.push(c)}}catch(e){t={error:e}}finally{try{f&&!f.done&&(r=u.return)&&r.call(u)}finally{if(t)throw t.error}}return i};t.default=function(e){for(var t,r,o=[],a=e;a&&null!==Object.getPrototypeOf(a);){try{for(var i=(t=void 0,n(u(a))),l=i.next();!l.done;l=i.next()){var f=l.value;if("constructor"!==f){var c=Object.getOwnPropertyDescriptor(a,f);c&&(c.get||c.set)||-1!==o.indexOf(f)||o.push(f)}}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}a=Object.getPrototypeOf(a)}return o}},7794:function(e,t){var r=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){for(var t,n,o=[],a=e;a&&null!==Object.getPrototypeOf(a);){try{for(var i=(t=void 0,r(Object.getOwnPropertyNames(a))),l=i.next();!l.done;l=i.next()){var u=l.value;if("constructor"!==u){var f=Object.getOwnPropertyDescriptor(a,u);f&&(f.get||f.set)&&-1===o.indexOf(u)&&o.push(u)}}}catch(e){t={error:e}}finally{try{l&&!l.done&&(n=i.return)&&n.call(i)}finally{if(t)throw t.error}}a=Object.getPrototypeOf(a)}return o}},5020:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){for(var r=e;r&&null!==Object.getPrototypeOf(r);){var n=Object.getOwnPropertyDescriptor(r,t);if(n)return n;r=Object.getPrototypeOf(r)}}},8536:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(3174)),a=function(e,t){void 0===t&&(t=!1);var r,n,i=a.customMockFunction&&!t?a.customMockFunction(e):function(e){return n&&n(e),r};return(0,o.default)(i,"__ngMocks",!0),(0,o.default)(i,"__ngMocksSet",(function(e){return n=e})),(0,o.default)(i,"__ngMocksGet",(function(e){return r=e})),i};t.default=a},445:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.registerMockFunction=function(e){(0,o.default)().ngMockshelperMockService.registerMockFunction(e)};var o=n(r(1102)),a=n(r(1365)),i=n(r(3886)),l=n(r(5006)),u=n(r(7331)),f=n(r(7794)),c=n(r(5020)),d=n(r(4235)),s=n(r(8536)),v=n(r(2004)),p=n(r(3663)),h=n(r(9465));(0,o.default)().ngMockshelperMockService=(0,o.default)().ngMockshelperMockService||{mockFunction:s.default,registerMockFunction:function(e){(0,o.default)().ngMockshelperMockService.mockFunction.customMockFunction=e},createClone:a.default,createMockFromPrototype:i.default,definePropertyDescriptor:l.default,extractMethodsFromPrototype:u.default,extractPropertiesFromPrototype:f.default,extractPropertyDescriptor:c.default,mock:d.default,replaceWithMocks:v.default,resolveProvider:p.default,useFactory:h.default},t.default=(0,o.default)().ngMockshelperMockService},4235:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0&&"get"!==e[0]&&"set"!==e[0]?r=e[0]:e.length>0&&("get"===e[0]||"set"===e[0])&&(t=e[0],r=e[1]),{accessType:t,mockName:r}}(r),u=l.accessType,f=l.mockName,c=Object.getOwnPropertyDescriptor(e,t);if(c&&c[u||"value"])return c[u||"value"];var d=function(e,t,r,n){return"".concat(null!=t?t:"function"==typeof r.prototype?r.prototype.name:(0,a.default)(r),".").concat(e).concat(null!=n?n:"")}(t,f,e,u),s=i.default.mockFunction(d,!!u),v=function(e,t,r){var o;return n(n(n(n({},"get"===r&&e&&e.set?{set:e.set}:{}),"set"===r&&e&&e.get?{get:e.get}:{}),r?{}:{writable:!0}),((o={})[r||"value"]=t,o.configurable=!0,o.enumerable=!0,o))}(c,s,u);return v.get&&v.set&&v.get.__ngMocks&&v.set.__ngMocks&&v.set.__ngMocksSet((function(e){return v.get.__ngMocksGet(e)})),Object.defineProperty(e,t,v),s}},2004:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=r(1763),u=r(5974),f=i(r(8073)),c=["canActivate","canActivateChild","canDeactivate","canMatch","canLoad"],d=function(e,t){return Array.isArray(e[t])?function(e){var t,r,n=[];try{for(var a=o(e),i=a.next();!i.done;i=a.next()){var c=i.value;!f.default.isProvidedDef(c)&&f.default.isExcludedDef(l.NG_MOCKS_GUARDS)||(n.push(c),(0,u.isNgDef)(c)||f.default.touches.add(c))}}catch(e){t={error:e}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}return n}(e[t]):e[t]},s=function(e,t){var r,i,v;if(f.default.cacheDeclarations.has(e))return f.default.cacheDeclarations.get(e);if("object"!=typeof e)return e;if(t.has(e))return e;var p=!1;return Array.isArray(e)?(r=a(function(e,t,r){var n,a,i=[],l=!1;e.set(t,i);try{for(var u=o(t),c=u.next();!c.done;c=u.next()){var d=c.value;f.default.isExcludedDef(d)?l=l||!0:(i.push(r(d,e)),l=l||i[i.length-1]!==d)}}catch(e){n={error:e}}finally{try{c&&!c.done&&(a=u.return)&&a.call(u)}finally{if(n)throw n.error}}return[l,i]}(t,e,s),2),p=r[0],v=r[1]):e&&(i=a(function(e,t,r){var a,i,s,v,p,h,y,_={},g=!1;e.set(t,_);try{for(var b=o(Object.keys(t)),m=b.next();!m.done;m=b.next()){var M=m.value;f.default.isExcludedDef(t[M])?g=g||!0:(_[M]=r(t[M],e),g=g||_[M]!==t[M])}}catch(e){a={error:e}}finally{try{m&&!m.done&&(i=b.return)&&i.call(b)}finally{if(a)throw a.error}}try{for(var k=o(c),w=k.next();!w.done;w=k.next()){var O=w.value,x=d(_,O);x&&_[O].length!==x.length&&(g=g||!0,_=n(n({},_),((p={})[O]=x,p)))}}catch(e){s={error:e}}finally{try{w&&!w.done&&(v=k.return)&&v.call(k)}finally{if(s)throw s.error}}if("object"==typeof _.resolve&&_.resolve){var j={},D=!1;try{for(var S=o(Object.keys(_.resolve)),P=S.next();!P.done;P=S.next()){M=P.value;var C=_.resolve[M];f.default.isProvidedDef(C)||!f.default.isExcludedDef(l.NG_MOCKS_RESOLVERS)?(j[M]=C,(0,u.isNgDef)(C)||f.default.touches.add(C)):D=D||!0}}catch(e){h={error:e}}finally{try{P&&!P.done&&(y=S.return)&&y.call(S)}finally{if(h)throw h.error}}D&&(g=g||!0,_=n(n({},_),{resolve:j}))}return[g,_]}(t,e,s),2),p=i[0],v=i[1]),p?(Object.setPrototypeOf(v,Object.getPrototypeOf(e)),v):e};t.default=function(e){var t=new Map,r=s(e,t);return t.clear(),r}},3663:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=r(6456),l=r(1763),u=a(r(7285)),f=a(r(6297)),c=r(4152),d=a(r(8073)),s=a(r(445)),v=a(r(2415)),p=function(e,t,r){var n=!1,a=!e;return t&&e&&!a&&(a=function(e,t){for(var r,n,a=[],i=2;i=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(3295)),l=a(r(6297)),u=r(4152),f=a(r(8073)),c=a(r(5006)),d=a(r(5020)),s=a(r(9465)),v=r(5779),p=i.default.neverMockProvidedFunction,h=i.default.neverMockToken,y=[[function(e){return"boolean"==typeof e},!1],[function(e){return"number"==typeof e},0],[function(e){return"string"==typeof e},""],[function(e){return null===e},null]],_=function(e,t,r){var a,i;return t===e?r?(0,s.default)(e,(function(){})):void 0:e.multi?void(null===(a=f.default.config.get("ngMocksMulti"))||void 0===a||a.add(t)):(-1!==Object.keys(e).indexOf("useValue")?i=function(e,t){return(0,s.default)(t,(function(){return e.useValue&&"object"==typeof e.useValue?(0,v.MockService)(e.useValue):function(e){var t,r;try{for(var a=n(y),i=a.next();!i.done;i=a.next()){var l=o(i.value,2),u=l[0],f=l[1];if(u(e))return f}}catch(e){t={error:e}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}}(e.useValue)}))}(e,t):-1!==Object.keys(e).indexOf("useExisting")?i=e:-1!==Object.keys(e).indexOf("useClass")?i=function(e,t){return f.default.builtProviders.has(e.useClass)&&f.default.builtProviders.get(e.useClass)===e.useClass?e:(0,s.default)(t,(function(){return(0,v.MockService)(e.useClass)}))}(e,t):-1!==Object.keys(e).indexOf("useFactory")&&(i=(0,s.default)(t,(function(){return{}}))),i)};t.default=function(e,t){void 0===t&&(t=!1);var r=(0,l.default)(e);if("mock"===f.default.getResolution(r));else{if(function(e){return"function"==typeof e&&-1!==p.indexOf(e.name)}(r))return e;if(function(e){return(0,u.isNgInjectionToken)(e)&&-1!==h.indexOf(e.toString())}(r))return}var o=f.default.flags.has("cacheProvider")?f.default.cacheProviders:void 0;return r===e&&o&&o.has(r)?o.get(r):function(e,t,r){var o;return"function"==typeof t&&(o=function(e,t){return(0,s.default)(t,(function(){var r=(0,v.MockService)(t);return t!==e&&-1!==Object.keys(e).indexOf("useClass")&&function(e,t){var r,o,a=Object.getOwnPropertyNames(e),i=(0,v.MockService)(t);try{for(var l=n(Object.getOwnPropertyNames(i)),u=l.next();!u.done;u=l.next()){var f=u.value;if(-1===a.indexOf(f)){var s=(0,d.default)(i,f);(0,c.default)(e,f,s)}}}catch(e){r={error:e}}finally{try{u&&!u.done&&(o=l.return)&&o.call(l)}finally{if(r)throw r.error}}}(r,e.useClass),r}))}(e,t)),t===e&&o&&r&&r.set(t,o),o}(e,r,o)||_(e,r,t)}},5779:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockService=function(e){for(var t=[],r=1;r0&&"string"==typeof t[0]?t[0]:t[1],o=t.length>0&&t[0]&&"object"==typeof t[0]?t[0]:void 0,a=new Map,i=v(a,e,n,o);return a.clear(),i};var i=a(r(2970)),l=a(r(8195)),u=a(r(96)),f=a(r(2956)),c=a(r(402)),d=a(r(445)),s=[[u.default,function(e,t){var r=d.default.createMockFromPrototype(t.prototype);return e.set(t,r),r}],[f.default,function(e,t,r){var n=d.default.mockFunction("func:".concat(r||(0,i.default)(t)));return e.set(t,n()),n}],[function(e){return Array.isArray(e)},function(){return[]}],[c.default,function(e,t,r,o){var a,i,l=d.default.createMockFromPrototype(t.constructor.prototype);e.set(t,l);try{for(var u=n(Object.keys(t)),f=u.next();!f.done;f=u.next()){var c=f.value,s=o(e,t[c],"".concat(r||"instance",".").concat(c));void 0!==s&&(l[c]=s)}}catch(e){a={error:e}}finally{try{f&&!f.done&&(i=u.return)&&i.call(u)}finally{if(a)throw a.error}}return Object.setPrototypeOf(l,Object.getPrototypeOf(t)),l}]],v=function(e,t,r,a){void 0===r&&(r="");var i=function(e,t,r,a){var i,l,u;try{for(var f=n(s),c=f.next();!c.done;c=f.next()){var d=o(c.value,2),v=d[0],p=d[1];if(v(t))return null!==(u=e.get(t))&&void 0!==u?u:p(e,t,r,a)}}catch(e){i={error:e}}finally{try{c&&!c.done&&(l=f.return)&&l.call(f)}finally{if(i)throw i.error}}}(e,t,r,v);return a&&(0,l.default)(i,a),i}},534:function(e,t){Object.defineProperty(t,"__esModule",{value:!0})},9715:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(2023)),i=r(6456),l=o(r(7285)),u=o(r(6297)),f=r(1433),c=o(r(445)),d=o(r(7112)),s=o(r(3309)),v=function(e,t,r,n){var o=function(e,t){var r=(0,u.default)(t);return a.default.NG_VALIDATORS&&r===a.default.NG_VALIDATORS?(0,s.default)(r,(function(){return new f.MockValidatorProxy(e)})):a.default.NG_ASYNC_VALIDATORS&&r===a.default.NG_ASYNC_VALIDATORS?(0,s.default)(r,(function(){return new f.MockAsyncValidatorProxy(e)})):a.default.NG_VALUE_ACCESSOR&&r===a.default.NG_VALUE_ACCESSOR?(0,s.default)(r,(function(){return new f.MockControlValueAccessorProxy(e)})):void 0}(t,r);if(o)return o;var i=function(e,t,r){var n=(0,u.default)(r);if(n!==a.default.NgControl&&n!==a.default.FormControlDirective)return r!==n&&(0,l.default)(r.useExisting)===e?(0,d.default)(n,t):void 0}(e,t,r);return i||c.default.resolveProvider(r,n)};t.default=function(e,t,r,o){var l,f,c,d=[];try{for(var s=n((0,i.flatten)(r||[])),p=s.next();!p.done;p=s.next()){var h=p.value;(0,u.default)(h)===a.default.NG_VALUE_ACCESSOR&&(c=!1);var y=v(e,t,h,o);y&&d.push(y)}}catch(e){l={error:e}}finally{try{p&&!p.done&&(f=s.return)&&f.call(s)}finally{if(l)throw l.error}}return{providers:d,setControlValueAccessor:c}}},6847:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=i(r(5551)),u=i(r(5756)),f=i(r(615)),c=i(r(5555)),d=i(r(8385)),s=i(r(8073)),v=i(r(224)),p=i(r(445)),h=i(r(9715)),y=i(r(7112));t.default=function(e,t,r,i){var _,g,b,m,M=s.default.config.has("mockNgDefResolver");M||s.default.config.set("mockNgDefResolver",new l.default);var k=n({},i);if(void 0!==r.exportAs&&(k.exportAs=r.exportAs),void 0!==r.selector&&(k.selector=r.selector),void 0!==r.standalone&&(k.standalone=r.standalone),r.standalone&&r.imports){var w=o((0,v.default)({imports:r.imports,skipExports:!0}),2)[1].imports;(null==w?void 0:w.length)&&(k.imports=w)}if(r.hostDirectives){var O=o((0,v.default)({hostDirectives:r.hostDirectives,skipExports:!0}),2)[1].hostDirectives;(null==O?void 0:O.length)&&(k.hostDirectives=O)}var x=(0,h.default)(e,t,r.providers||[],s.default.config.get("mockNgDefResolver")),j=x.setControlValueAccessor,D=x.providers;D.push((0,y.default)(e,t)),k.providers=D;var S=(0,h.default)(e,t,r.viewProviders||[],s.default.config.get("mockNgDefResolver")).providers;S.length>0&&(k.viewProviders=S);var P=function(e,t,r){return{config:s.default.config.get(e),outputs:t.outputs,queryScanKeys:[],setControlValueAccessor:r}}(e,r,null!=j?j:-1!==p.default.extractMethodsFromPrototype(e.prototype).indexOf("writeValue"));(0,f.default)(t,e,P),r.queries&&(0,u.default)(t,r.inputs,Object.keys(r.queries)),(0,c.default)(t,r.outputs),P.queryScanKeys=(0,d.default)(t,r.queries),P.hostBindings=[];try{for(var C=a(r.hostBindings||[]),N=C.next();!N.done;N=C.next()){var T=o(N.value,1)[0];-1===P.hostBindings.indexOf(T)&&P.hostBindings.push(T)}}catch(e){_={error:e}}finally{try{N&&!N.done&&(g=C.return)&&g.call(C)}finally{if(_)throw _.error}}P.hostListeners=[];try{for(var E=a(r.hostListeners||[]),A=E.next();!A.done;A=E.next())T=o(A.value,1)[0],-1===P.hostListeners.indexOf(T)&&P.hostListeners.push(T)}catch(e){b={error:e}}finally{try{A&&!A.done&&(m=E.return)&&m.call(E)}finally{if(b)throw b.error}}return M||s.default.config.delete("mockNgDefResolver"),k}},6932:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(6456),a=n(r(6804)),i=r(6763),l=n(r(8073)),u=n(r(5937));t.default=function(e,t,r,n,f,c){if((0,a.default)(e,r),(0,i.isMockNgDef)(e,t))return e;if(l.default.flags.has(n)&&l.default.cacheDeclarations.has(e))return(0,u.default)(e);var d=l.default.config.has("ngMocksDepsResolution");d||l.default.config.set("ngMocksDepsResolution",new Map);var s=(0,o.extendClass)(f);return c(e,s),l.default.flags.has(n)&&l.default.cacheDeclarations.set(e,s),d||l.default.config.delete("ngMocksDepsResolution"),s}},7610:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(6739),a=n(r(8073));t.default=function(e,t){var r,n=(0,o.getSourceOfMock)(e),i=null!==(r=a.default.configInstance.get(n))&&void 0!==r?r:{__set:!0};i.exported||(i.exported=new Set),t&&i.exported.add((0,o.getSourceOfMock)(t)),i.__set&&(i.__set=void 0,a.default.configInstance.set(n,i))}},5937:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(1763),a=n(r(8073)),i=n(r(5687));t.default=function(e){var t;try{t=(0,i.default)().debugElement.injector.get(o.NG_MOCKS).get(e)}catch(e){}return t||(t=a.default.cacheDeclarations.get(e)),e.__ngMocksResolutions&&a.default.config.has("mockNgDefResolver")&&a.default.config.get("mockNgDefResolver").merge(e.__ngMocksResolutions),t}},7112:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){return{provide:e,useExisting:t}}},3309:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){return{multi:!0,provide:e,useFactory:t}}},4673:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=function(){function e(){this.stack=[],this.push()}return e.prototype.push=function(){this.stack.push(new Map)},e.prototype.pop=function(){var e;return null!==(e=this.stack.pop())&&void 0!==e?e:new Map},e.prototype.has=function(e){for(var t=this.stack.length-1;t>=0;t-=1)if(this.stack[t].has(e))return!0;return!1},e.prototype.get=function(e){for(var t=this.stack.length-1;t>=0;t-=1)if(this.stack[t].has(e))return this.stack[t].get(e)},e.prototype.set=function(e,t){for(var r=this.stack.length-1;r>=0;r-=1)this.stack[r].set(e,t);return this},e.prototype.merge=function(e){var t,r;try{for(var i=n((0,a.mapEntries)(e)),l=i.next();!l.done;l=i.next()){var u=o(l.value,2),f=u[0],c=u[1];this.set(f,c)}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}return this},e}();t.default=i},3174:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(445));t.default=function(e,t,r,n){void 0===n&&(n=!1),o.default.definePropertyDescriptor(e,t,{configurable:!0,enumerable:n,value:r,writable:!0})}},2023:function(e,t,r){var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){void 0===n&&(n=r);var o=Object.getOwnPropertyDescriptor(t,r);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[r]}}),Object.defineProperty(e,n,o)}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]}),o=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),a=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)"default"!==r&&Object.prototype.hasOwnProperty.call(e,r)&&n(t,e,r);return o(t,e),t};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(7182)),l=i.AbstractControl,u=i.DefaultValueAccessor,f=i.FormControl,c=i.FormControlDirective,d=i.NG_ASYNC_VALIDATORS,s=i.NG_VALIDATORS,v=i.NG_VALUE_ACCESSOR,p=i.NgControl,h=i.NgModel;t.default={AbstractControl:l,DefaultValueAccessor:u,FormControl:f,FormControlDirective:c,NG_ASYNC_VALIDATORS:d,NG_VALIDATORS:s,NG_VALUE_ACCESSOR:v,NgControl:p,NgModel:h}},6456:function(__unused_webpack_module,exports,__webpack_require__){var __extends=this&&this.__extends||(extendStatics=function(e,t){return extendStatics=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},extendStatics(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function r(){this.constructor=e}extendStatics(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),extendStatics,__values=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},__read=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},__spreadArray=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o0&&(0,core_define_property_1.default)(t,"parameters",__spreadArray([],__read(r),!1)),t};exports.extendClass=extendClass},4201:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(6456),o={};t.default=function(e,t){if(void 0===t&&(t=o),t===o)return(0,n.getTestBedInjection)(e);try{return t.get(e)}catch(e){return}}},4874:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8641)),a=n(r(1585)),i=n(r(2129));t.default=function(e){return function(t){(0,o.default)(t);try{return e(t)}catch(e){(0,a.default)(t),(0,i.default)(t)}}}},8862:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4673)),a=n(r(4874));t.default=function(e){return(0,a.default)((function(e){var t=(0,o.default)(e);if(t.Component)return t.Component;if(t.Directive)return t.Directive;throw new Error("Cannot resolve declarations")}))(e)}},1381:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8862)),a=n(r(1345)),i=r(5974);t.default=function(e){return(0,i.isNgDef)(e,"c")||(0,i.isNgDef)(e,"d")?(0,o.default)(e):(0,i.isNgDef)(e,"m")?(0,a.default)(e):void 0}},1345:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4673)),a=n(r(4874));t.default=function(e){return(0,a.default)((function(e){var t=(0,o.default)(e);if(t.NgModule)return t.NgModule;throw new Error("Cannot resolve declarations")}))(e)}},8749:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4673));t.default=function(e){var t;return null!==(t=(0,o.default)(e).parameters)&&void 0!==t?t:[]}},8773:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4673)),a=n(r(4874));t.default=function(e){return(0,a.default)((function(e){var t=(0,o.default)(e);if(t.Pipe)return t.Pipe;throw new Error("Cannot resolve declarations")}))(e)}},8911:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t,r,n;if(e&&("object"==typeof e||"function"==typeof e))return null!==(r=null===(t=e.ɵprov)||void 0===t?void 0:t.providedIn)&&void 0!==r?r:null===(n=e.ngInjectableDef)||void 0===n?void 0:n.providedIn}},1763:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.NG_MOCKS_ROOT_PROVIDERS=t.NG_MOCKS_INTERCEPTORS=t.NG_MOCKS_RESOLVERS=t.NG_MOCKS_GUARDS=t.NG_MOCKS_OVERRIDES=t.NG_MOCKS_TOUCHES=t.NG_MOCKS=void 0;var n=r(860);t.NG_MOCKS=new n.InjectionToken("NG_MOCKS"),t.NG_MOCKS.__ngMocksSkip=!0,t.NG_MOCKS_TOUCHES=new n.InjectionToken("NG_MOCKS_TOUCHES"),t.NG_MOCKS_TOUCHES.__ngMocksSkip=!0,t.NG_MOCKS_OVERRIDES=new n.InjectionToken("NG_MOCKS_OVERRIDES"),t.NG_MOCKS_OVERRIDES.__ngMocksSkip=!0,t.NG_MOCKS_GUARDS=new n.InjectionToken("NG_MOCKS_GUARDS"),t.NG_MOCKS_GUARDS.__ngMocksSkip=!0,t.NG_MOCKS_RESOLVERS=new n.InjectionToken("NG_MOCKS_RESOLVERS"),t.NG_MOCKS_RESOLVERS.__ngMocksSkip=!0,t.NG_MOCKS_INTERCEPTORS=new n.InjectionToken("NG_MOCKS_INTERCEPTORS"),t.NG_MOCKS_INTERCEPTORS.__ngMocksSkip=!0,t.NG_MOCKS_ROOT_PROVIDERS=new n.InjectionToken("NG_MOCKS_ROOT_PROVIDERS"),t.NG_MOCKS_ROOT_PROVIDERS.__ngMocksSkip=!0},5756:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(860),i=o(r(6439)),l=o(r(1184));t.default=function(e,t,r){var o,u;if(t)try{for(var f=n(t),c=f.next();!c.done;c=f.next()){var d=c.value,s=(0,l.default)(d),v=s.name,p=s.alias,h=s.required;r&&-1!==r.indexOf(v)||(0,a.Input)((0,i.default)({name:v,alias:p,required:h},!0))(e.prototype,v)}}catch(e){o={error:e}}finally{try{c&&!c.done&&(u=f.return)&&u.call(f)}finally{if(o)throw o.error}}}},615:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(860),i=o(r(6439)),l=o(r(1184));t.default=function(e,t){var r,o;if(t)try{for(var u=n(t),f=u.next();!f.done;f=u.next()){var c=f.value,d=(0,l.default)(c),s=d.name,v=d.alias,p=d.required;(0,a.Output)((0,i.default)({name:s,alias:v,required:p},!0))(e.prototype,s)}}catch(e){r={error:e}}finally{try{f&&!f.done&&(o=u.return)&&o.call(u)}finally{if(r)throw r.error}}}},8385:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i};Object.defineProperty(t,"__esModule",{value:!0});var i=r(860),l={ContentChild:i.ContentChild,ContentChildren:i.ContentChildren,ViewChild:i.ViewChild,ViewChildren:i.ViewChildren},u=function(e){return 0===e.indexOf("__mock")},f=function(e){return n(n({},e),{ngMetadataName:e.ngMetadataName,read:i.ViewContainerRef})};t.default=function(e,t){var r,n;if(!t)return[];var i=a(function(e){var t,r,n=[],a=[];try{for(var i=o(Object.keys(e)),l=i.next();!l.done;l=i.next()){var c=l.value,d=e[c];n.push([c,d]),d.isViewQuery||u(c)||(a.push(c),n.push(["__ngMocksVcr_".concat(c),f(d)]))}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}return[n,a]}(t),2),c=i[0],d=i[1];try{for(var s=o(c),v=s.next();!v.done;v=s.next()){var p=a(v.value,2),h=p[0],y=p[1];y.ngMetadataName&&(0,l[y.ngMetadataName])(y.selector,y)(e.prototype,h)}}catch(e){r={error:e}}finally{try{v&&!v.done&&(n=s.return)&&n.call(s)}finally{if(r)throw r.error}}return d}},8641:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){if(!e)throw new Error(["undefined / null has been passed into ng-mocks as a declaration / provider.","Please ensure that the current test file has correct imports:","imported files exist and imported declarations have been exported in the file."].join(" "))}},1585:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2970)),a=n(r(9628));t.default=function(e){if((0,a.default)(e))throw new Error(["ng-mocks got ".concat((0,o.default)(e)," which has been already mocked by jest.mock()."),"It is not possible to produce correct mocks for it, because jest.mock() removes Angular decorators.","To fix this, please avoid jest.mock() on the file which exports ".concat((0,o.default)(e)," or add jest.dontMock() on it."),"The same should be done for all related dependencies."].join(" "))}},2129:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2970));t.default=function(e){throw new Error(["".concat((0,o.default)(e)," declaration has been passed into ng-mocks without Angular decorators."),"Therefore, it cannot be properly handled.","Highly likely,","undefined"==typeof jest?"":"jest.mock() has been used on its file, or","ng-mocks is imported in production code, or got a class without Angular decoration.","Otherwise, please create an issue on github: https://github.com/help-me-mom/ng-mocks/issues/new?title=False%20positive%20ng-mocks%20not%20in%20JIT.","Thank you in advance for support."].join(" "))}},6439:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){var r=e.name,n=e.alias,o=e.required;return void 0===t&&(t=!1),o?{name:r,alias:n,required:o}:n&&r!==n?t?n:"".concat(r,":").concat(n):t?"":r}},1184:function(e,t){var r=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i};Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){if("string"==typeof e){var t=r(e.split(":").map((function(e){return e.trim()})),2),n=t[0],o=t[1];return n!==o&&o?{name:n,alias:o}:{name:n}}return e}},5204:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.funcExtractDeps=void 0;var a=o(r(4673)),i=o(r(3295)),l=r(6456),u=r(9335),f=o(r(6297));t.funcExtractDeps=function(e,r,o){var c,d,s,v;void 0===o&&(o=!1);var p=(0,a.default)(e),h=(0,u.getNgType)(e);if(!h||"Injectable"===h)return r;var y=p[h];try{for(var _=n(i.default.dependencies),g=_.next();!g.done;g=_.next()){var b=g.value;if(y[b])try{for(var m=(s=void 0,n((0,l.flatten)(y[b]))),M=m.next();!M.done;M=m.next()){var k=M.value,w=(0,f.default)(k);r.has(w)||(r.add(w),o&&(0,t.funcExtractDeps)(w,r))}}catch(e){s={error:e}}finally{try{M&&!M.done&&(v=m.return)&&v.call(m)}finally{if(s)throw s.error}}}}catch(e){c={error:e}}finally{try{g&&!g.done&&(d=_.return)&&d.call(_)}finally{if(c)throw c.error}}return r}},7285:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return"function"==typeof e&&e.__forward_ref__?e():e}},1102:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return"undefined"==typeof window?r.g:window}},5590:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getMockedNgDefOf=function(e,t){var r,n=null!==(r=e.mockOf)&&void 0!==r?r:e,u=(0,o.default)(a.NG_MOCKS),c=f(e,n,u);if(c&&!t)return c;if(c&&t&&(0,l.isMockedNgDefOf)(c,n,t))return c;throw new Error("There is no mock for ".concat((0,i.default)(n)))};var o=n(r(4201)),a=r(1763),i=n(r(2970)),l=r(732),u=n(r(8073)),f=function(e,t,r){if(r&&!r.has(t))throw new Error("There is no mock for ".concat((0,i.default)(t)));var n=r?r.get(t):void 0;return n===t&&(n=void 0),n||t===e?!n&&u.default.cacheDeclarations.has(t)&&(n=u.default.cacheDeclarations.get(t)):n=e,n}},2970:function(e,t){Object.defineProperty(t,"__esModule",{value:!0});var r=new RegExp("[^0-9a-z]+","mgi");t.default=function(e){var t;return"function"==typeof e&&e.name?t=e.name:"function"==typeof e?t="arrowFunction":"object"==typeof e&&e&&"InjectionToken"===e.ngMetadataName?t=e._desc:"object"==typeof e&&e&&"function"==typeof e.constructor&&(t=e.constructor.name),t||(t="unknown"),t.replace(r,"_")}},9335:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getNgType=void 0;var o=n(r(4673)),a=r(4152);t.getNgType=function(e){if("string"!=typeof e){if((0,a.isNgInjectionToken)(e))return"Injectable";for(var t=(0,o.default)(e).decorators,r=t.length-1;r>=0;r-=1)if("Injectable"!==t[r])return t[r];return t.length>0?"Injectable":void 0}}},6739:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.getSourceOfMock=function(e){return"function"==typeof e&&e.mockOf?e.mockOf:e}},6297:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(3659);t.default=function(e){return e&&"object"==typeof e&&e.provide?e.provide:(0,n.isNgModuleDefWithProviders)(e)?e.ngModule:e&&"object"==typeof e&&e.directive?e.directive:e}},6804:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2970)),a=r(5974);t.default=function(e,t){if(null==e)throw new Error("null / undefined has been passed into ".concat(t,". Please check that its import is correct."));if(!("MockPipe"===t&&(0,a.isNgDef)(e,"p")||"MockDirective"===t&&(0,a.isNgDef)(e,"d")||"MockComponent"===t&&(0,a.isNgDef)(e,"c")||"MockModule"===t&&(0,a.isNgDef)(e,"m"))){var r=function(e){return(0,a.isNgDef)(e,"p")?"pipe":(0,a.isNgDef)(e,"d")?"directive":(0,a.isNgDef)(e,"c")?"component":(0,a.isNgDef)(e,"m")?"module":(0,a.isNgDef)(e,"i")?"service":(0,a.isNgDef)(e,"t")?"token":""}(e);if(r&&"MockPipe"===t)throw new Error("".concat(t," accepts pipes, whereas ").concat((0,o.default)(e)," is a ").concat(r,"."));if(r&&"MockDirective"===t)throw new Error("".concat(t," accepts directives, whereas ").concat((0,o.default)(e)," is a ").concat(r,"."));if(r&&"MockComponent"===t)throw new Error("".concat(t," accepts components, whereas ").concat((0,o.default)(e)," is a ").concat(r,"."));if(r&&"MockModule"===t)throw new Error("".concat(t," accepts modules, whereas ").concat((0,o.default)(e)," is a ").concat(r,"."))}}},9628:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return!(!e||"function"!=typeof e&&"object"!=typeof e||!(e._isMockFunction&&e.mockName&&e.__annotations__))}},7105:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.isMockControlValueAccessor=void 0;var o=n(r(2137));t.isMockControlValueAccessor=function(e){return!!(0,o.default)(e)&&!!e.__ngMocksConfig.isControlValueAccessor}},6763:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.isMockNgDef=function(e,t){return!!e.mockOf&&(!t||(0,n.isNgDef)(e.mockOf,t))};var n=r(5974)},7675:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.isMockOf=function(e,t,r){return(0,o.default)(e)&&e.constructor===t&&(r?(0,a.isNgDef)(e.constructor,r):(0,a.isNgDef)(e.constructor))};var o=n(r(2137)),a=r(5974)},2650:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.isMockValidator=void 0;var o=n(r(2137));t.isMockValidator=function(e){return!!(0,o.default)(e)&&!!e.__ngMocksConfig.isValidator}},2137:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return e&&"object"==typeof e&&!!e.__ngMocks}},732:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.isMockedNgDefOf=function(e,t,r){return"function"==typeof e&&e.mockOf===t&&(!r||(0,n.isNgDef)(e,r))};var n=r(5974)},5974:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0}),t.isNgDef=function(e,t){if("t"===t)return(0,n.isNgInjectionToken)(e);if("function"!=typeof e)return!1;var r=a(e,t),o=i(e,t),c=l(e,t),d=u(e,t),s=f(e,t);return r||o||c||d||s};var n=r(4152),o=r(7297),a=function(e,t){return(!t||"m"===t)&&(0,o.isNgType)(e,"NgModule")},i=function(e,t){return(!t||"c"===t)&&(0,o.isNgType)(e,"Component")},l=function(e,t){return(!t||"d"===t)&&(0,o.isNgType)(e,"Directive")},u=function(e,t){return(!t||"p"===t)&&(0,o.isNgType)(e,"Pipe")},f=function(e,t){return(!t||"i"===t)&&(0,o.isNgType)(e,"Injectable")}},4152:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.isNgInjectionToken=void 0,t.isNgInjectionToken=function(e){return e&&"object"==typeof e&&"InjectionToken"===e.ngMetadataName}},3659:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.isNgModuleDefWithProviders=void 0,t.isNgModuleDefWithProviders=function(e){return e&&"object"==typeof e&&"function"==typeof e.ngModule}},7297:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.isNgType=void 0;var o=n(r(4673));t.isNgType=function(e,t){var r=(0,o.default)(e).decorators;if(0===r.length)return!1;var n=1;if("Injectable"===t&&-1!==r.indexOf("Injectable"))return!0;for(;"Injectable"===r[r.length-n];)n+=1;return r[r.length-n]===t}},6580:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.isStandalone=function(e){var t=(0,a.getNgType)(e);return"NgModule"!==t};var o=n(r(4673)),a=r(9335)},6259:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(4673)),i=o(r(3295)),l=r(6456),u=o(r(6297)),f=function(e,t,r){var o,c,d,s,v,p;void 0===r&&(r=new Set);var h=(0,a.default)(e);try{for(var y=n(h.decorators),_=y.next();!_.done;_=y.next()){var g=_.value;try{for(var b=(d=void 0,n(i.default.dependencies)),m=b.next();!m.done;m=b.next()){var M=m.value;if(h[g][M])try{for(var k=(v=void 0,n((0,l.flatten)(h[g][M]))),w=k.next();!w.done;w=k.next()){var O=w.value,x=(0,u.default)(O);x&&!r.has(x)&&(r.add(x),t(x),f(x,t,r))}}catch(e){v={error:e}}finally{try{w&&!w.done&&(p=k.return)&&p.call(k)}finally{if(v)throw v.error}}}}catch(e){d={error:e}}finally{try{m&&!m.done&&(s=b.return)&&s.call(b)}finally{if(d)throw d.error}}}}catch(e){o={error:e}}finally{try{_&&!_.done&&(c=y.return)&&c.call(y)}finally{if(o)throw o.error}}};t.default=f},1433:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.MockAsyncValidatorProxy=t.MockValidatorProxy=t.MockControlValueAccessorProxy=void 0;var r=function(e,t,r,n){if(e.instance&&n&&(e.instance[n]=r),e.instance&&e.instance[t])return e.instance[t](r)},n=function(){function e(e){this.target=e}return e.prototype.registerOnChange=function(e){r(this,"registerOnChange",e,"__simulateChange")},e.prototype.registerOnTouched=function(e){r(this,"registerOnTouched",e,"__simulateTouch")},e.prototype.setDisabledState=function(e){r(this,"setDisabledState",e)},e.prototype.writeValue=function(e){r(this,"writeValue",e)},e}();t.MockControlValueAccessorProxy=n;var o=function(){function e(e){this.target=e}return e.prototype.registerOnValidatorChange=function(e){r(this,"registerOnValidatorChange",e,"__simulateValidatorChange")},e.prototype.validate=function(e){return this.instance&&this.instance.validate?this.instance.validate(e):null},e}();t.MockValidatorProxy=o;var a=function(){function e(e){this.target=e}return e.prototype.registerOnValidatorChange=function(e){r(this,"registerOnValidatorChange",e,"__simulateValidatorChange")},e.prototype.validate=function(e){if(this.instance&&this.instance.validate){var t=this.instance.validate(e);return void 0===t?Promise.resolve(null):t}return Promise.resolve(null)},e}();t.MockAsyncValidatorProxy=a},5980:function(e,t,r){var n,o=this&&this.__extends||(n=function(e,t){return n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},n(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0}),t.LegacyControlValueAccessor=void 0;var a=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t.prototype.__simulateChange=function(){},t.prototype.__simulateTouch=function(){},t.prototype.__simulateValidatorChange=function(){},t}(r(1946).Mock);t.LegacyControlValueAccessor=a},1946:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o0&&((o=(0,c.default)(e._providers||(null===(n=e._compiler)||void 0===n?void 0:n.providers)).touches)||(o=new Set,t.providers=t.providers||[],t.providers.push({provide:O.NG_MOCKS_TOUCHES,useValue:o})),T(t,o)),o}(Y,K,J.touches);return Z&&v.ngMocks.flushTestBed(),ee&&function(e){var t,r;try{for(var i=o((0,b.mapEntries)(e)),l=i.next();!l.done;l=i.next()){var u=a(l.value,2),c=u[0],d=a(u[1],2),s=d[0],v=d[1];f.TestBed.ngMocksOverrides.set(c,n(n({},v),{override:s})),N(c,s)}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}}(ee),!te||Y._instantiated||Y._testModuleRef||function(e,t){var r,n;if(f.TestBed.ngMocksOverrides){var i=C.default.touches;C.default.touches=t;try{for(var l=o((0,b.flatten)(e.ngModule||[])),u=l.next();!u.done;u=l.next()){var c=u.value;E(c)}}catch(e){r={error:e}}finally{try{u&&!u.done&&(n=l.return)&&n.call(l)}finally{if(r)throw r.error}}!function(e){var t,r;try{for(var n=o((0,b.mapEntries)(C.default.getDefaults())),i=n.next();!i.done;i=n.next()){var l=a(i.value,2),u=l[0];"mock"===a(l[1],1)[0]&&((0,S.isNgDef)(u,"i")||(0,S.isNgDef)(u,"t"))&&(e.has(u)||f.TestBed.ngMocksOverrides.has(u)||A(u,e))}}catch(e){t={error:e}}finally{try{i&&!i.done&&(r=n.return)&&r.call(n)}finally{if(t)throw t.error}}}(t),C.default.touches=i}}(Y,te),e.call(t,K)}},I=function(e,t){return function(){return C.default.global.delete("builder:config"),C.default.global.delete("builder:module"),f.TestBed.ngMocksSelectors=void 0,function(e){var t,r,n;if(null===(n=e.ngMocksOverrides)||void 0===n?void 0:n.size){v.ngMocks.flushTestBed();try{for(var i=o((0,b.mapEntries)(e.ngMocksOverrides)),l=i.next();!l.done;l=i.next()){var u=a(l.value,2),f=u[0],c=u[1];N(f,c)}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}}e.ngMocksOverrides=void 0}(f.TestBed),e.call(t)}},V=function(e){if(!u.ViewContainerRef.ngMocksOverridesPatched&&((0,g.default)(u.ViewContainerRef,"ngMocksOverridesPatched",!0),e.createComponent)){var t=e.createComponent,r=(0,y.default)(t,void 0,void 0,(function(e){for(var r,n=[],o=1;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},l=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var u=l(r(8073)),f={id:{},level:"root"},c=u.default.global.get("reporter-stack")||[a({},f)];u.default.global.set("reporter-stack",c);var d=null!==(n=u.default.global.get("reporter-stack-push"))&&void 0!==n?n:[];u.default.global.set("reporter-stack-push",d);var s=null!==(o=u.default.global.get("reporter-stack-pop"))&&void 0!==o?o:[];u.default.global.set("reporter-stack-pop",s),t.default={current:function(){return c[c.length-1]},stackPop:function(){var e,t,r=c.pop();if(0===c.length&&c.push("root"===(null==r?void 0:r.level)?r:a({},f)),r&&"root"!==r.level)try{for(var n=i(s),o=n.next();!o.done;o=n.next())(0,o.value)(r,c)}catch(t){e={error:t}}finally{try{o&&!o.done&&(t=n.return)&&t.call(n)}finally{if(e)throw e.error}}u.default.global.set("reporter-stack-id",c[c.length-1].id)},stackPush:function(){var e,t,r={};u.default.global.set("reporter-stack-id",r);var n={id:r,level:"runtime"};c.push(n);try{for(var o=i(d),a=o.next();!a.done;a=o.next())(0,a.value)(n,c)}catch(t){e={error:t}}finally{try{a&&!a.done&&(t=o.return)&&t.call(o)}finally{if(e)throw e.error}}},subscribePop:function(e){-1===s.indexOf(e)&&s.push(e)},subscribePush:function(e){d.indexOf(e)&&d.push(e),c.length>0&&e(c[c.length-1],c)},unsubscribePop:function(e){var t=s.indexOf(e);-1!==t&&s.splice(t,1)},unsubscribePush:function(e){var t=d.indexOf(e);-1!==t&&d.splice(t,1)}}},8073:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3295)),i=o(r(1102)),l=o(r(2970)),u=function(e){return function(){return f.global.has(e)||f.global.set(e,new Map),f.global.get(e)}};(0,i.default)().ngMocksUniverse=(0,i.default)().ngMocksUniverse||{};var f=(0,i.default)().ngMocksUniverse;f.builtDeclarations=new Map,f.builtProviders=new Map,f.cacheDeclarations=new Map,f.cacheProviders=new Map,f.config=new Map,f.configInstance=new Map,f.flags=new Set(a.default.flags),f.global=new Map,f.touches=new Set,f.global.set("flags",{onMockBuilderMissingDependency:a.default.onMockBuilderMissingDependency,onMockInstanceRestoreNeed:a.default.onMockInstanceRestoreNeed,onTestBedFlushNeed:a.default.onTestBedFlushNeed}),f.getOverrides=u("overrides"),f.getDefaults=u("defaults"),f.getConfigMock=u("configMock");var c=function(e){var t;return(t=f.getDefaults().get(e))||(t="function"==typeof e?f.getDefaults().get("@".concat((0,l.default)(e))):void 0)?t:[]};f.getResolution=function(e){var t=f.config.get("ngMocksDepsResolution");return(null==t?void 0:t.has(e))?t.get(e):n(c(e),1)[0]},f.getBuildDeclaration=function(e){if(f.builtDeclarations.has(e))return f.builtDeclarations.get(e);var t=n(c(e),2),r=t[0],o=t[1];return"exclude"===r?null:r&&"keep"!==r?"replace"===r?o:void 0:e},f.hasBuildDeclaration=function(e){if(f.builtDeclarations.has(e))return void 0!==f.builtDeclarations.get(e);var t=n(c(e),1)[0];return!!t&&"mock"!==t};var d=function(e){return f.hasBuildDeclaration(e)},s=function(e){return f.getBuildDeclaration(e)};f.isExcludedDef=function(e){var t=f.getResolution(e);return(!t||"exclude"===t)&&d(e)&&null===s(e)},f.isProvidedDef=function(e){return d(e)&&null!==s(e)},f.getDefaults().set("@StoreDevtoolsModule",["exclude"]),f.indexValue=0,f.index=function(){return f.indexValue++},t.default=f},4117:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0});var o=r(6456),a=r(1763);t.default=function(e){var t,r,i,l,u;try{for(var f=n((0,o.flatten)(e||[])),c=f.next();!c.done;c=f.next()){var d=c.value;"object"==typeof d&&(d.provide===a.NG_MOCKS&&(i=d.useValue),d.provide===a.NG_MOCKS_OVERRIDES&&(l=d.useValue),d.provide===a.NG_MOCKS_TOUCHES&&(u=d.useValue))}}catch(e){t={error:e}}finally{try{c&&!c.done&&(r=f.return)&&r.call(f)}finally{if(t)throw t.error}}return{mocks:i,overrides:l,touches:u}}},9539:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockBuilderStash=void 0;var a=o(r(3295)),i=o(r(8073)),l=function(){function e(){this.data={}}return e.prototype.backup=function(){this.data={builtDeclarations:i.default.builtDeclarations,builtProviders:i.default.builtProviders,cacheDeclarations:i.default.cacheDeclarations,cacheProviders:i.default.cacheProviders,config:i.default.config,configInstance:i.default.configInstance,flags:i.default.flags,touches:i.default.touches},i.default.builtDeclarations=new Map,i.default.builtProviders=new Map,i.default.cacheDeclarations=new Map,i.default.cacheProviders=new Map,i.default.config=new Map,i.default.configInstance=new Map,i.default.flags=new Set(a.default.flags),i.default.touches=new Set},e.prototype.restore=function(){var e,t;try{for(var r=n(Object.keys(this.data)),o=r.next();!o.done;o=r.next()){var a=o.value;i.default[a]=this.data[a]}}catch(t){e={error:t}}finally{try{o&&!o.done&&(t=r.return)&&t.call(r)}finally{if(e)throw e.error}}},e}();t.MockBuilderStash=l},9755:function(e,t,r){var n,o=this&&this.__extends||(n=function(e,t){return n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},n(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),a=this&&this.__awaiter||function(e,t,r,n){return new(r||(r=Promise))((function(o,a){function i(e){try{u(n.next(e))}catch(e){a(e)}}function l(e){try{u(n.throw(e))}catch(e){a(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,l)}u((n=n.apply(e,t||[])).next())}))},i=this&&this.__generator||function(e,t){var r,n,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function l(l){return function(u){return function(l){if(r)throw new TypeError("Generator is already executing.");for(;a&&(a=0,l[0]&&(i=0)),i;)try{if(r=1,n&&(o=2&l[0]?n.return:l[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,l[1])).done)return o;switch(n=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return i.label++,{value:l[1],done:!1};case 5:i.label++,n=l[1],l=[0];continue;case 7:l=i.ops.pop(),i.trys.pop();continue;default:if(!((o=(o=i.trys).length>0&&o[o.length-1])||6!==l[0]&&2!==l[0])){i=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},u=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockBuilderPerformance=void 0;var f=r(2603),c=r(6456),d=u(r(8073)),s=r(9620),v=u(r(2739)),p=u(r(9049)),h=u(r(7570)),y=u(r(1271)),_=u(r(5633)),g=u(r(4503)),b=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),t.prototype.build=function(){var t=d.default.global;if(t.has("builder:module")&&t.has("builder:config")&&this.equalsTo(t.get("builder:config")))return(0,g.default)(t.get("builder:module"));t.has("builder:module")&&t.delete(t.get("builder:module"));var r=this.cloneConfig(),n=e.prototype.build.call(this);return t.set("builder:config",r),t.set("builder:module",n),(0,g.default)(n)},t.prototype.then=function(t,r){return a(this,void 0,Promise,(function(){var n,o;return i(this,(function(a){return(n=d.default.global).has("bullet")&&n.has("builder:module")&&n.has("builder:config")&&this.equalsTo(n.get("builder:config"))?[2,n.get(n.get("builder:module")).then(t,r)]:(n.has("bullet")&&n.has("bullet:reset")&&(console.warn("ngMocks.faster has zero effect due to changes in testing module between runs"),n.delete("bullet"),f.TestBed.resetTestingModule(),n.set("bullet",!0)),o=e.prototype.then.call(this,t,r),n.set(n.get("builder:module"),o),[2,o])}))}))},t.prototype.cloneConfig=function(){var e=(0,_.default)();return(0,c.mapValues)(this.beforeCC,e.beforeCC),(0,c.mapValues)(this.excludeDef,e.excludeDef),(0,c.mapValues)(this.keepDef,e.keepDef),(0,c.mapValues)(this.mockDef,e.mockDef),(0,c.mapValues)(this.replaceDef,e.replaceDef),(0,c.mapEntries)(this.configDef,e.configDef),(0,c.mapEntries)(this.defProviders,e.defProviders),(0,c.mapEntries)(this.defValue,e.defValue),(0,c.mapEntries)(this.providerDef,e.providerDef),e},t.prototype.equalsTo=function(e){var t,r,n,o,a,i;try{for(var u=l(["beforeCC","keepDef","replaceDef","excludeDef","mockDef"]),f=u.next();!f.done;f=u.next()){var c=f.value;if(!(0,y.default)(this[c],e[c]))return!1}}catch(e){t={error:e}}finally{try{f&&!f.done&&(r=u.return)&&r.call(u)}finally{if(t)throw t.error}}try{for(var d=l(["defValue"]),s=d.next();!s.done;s=d.next())if(c=s.value,!(0,p.default)(this[c],e[c]))return!1}catch(e){n={error:e}}finally{try{s&&!s.done&&(o=d.return)&&o.call(d)}finally{if(n)throw n.error}}try{for(var _=l(["providerDef","defProviders"]),g=_.next();!g.done;g=_.next())if(c=g.value,!(0,p.default)(this[c],e[c],h.default))return!1}catch(e){a={error:e}}finally{try{g&&!g.done&&(i=_.return)&&i.call(_)}finally{if(a)throw a.error}}return(0,p.default)(this.configDef,e.configDef,v.default)},t}(s.MockBuilderPromise);t.MockBuilderPerformance=b},9620:function(e,t,r){var n=this&&this.__awaiter||function(e,t,r,n){return new(r||(r=Promise))((function(o,a){function i(e){try{u(n.next(e))}catch(e){a(e)}}function l(e){try{u(n.throw(e))}catch(e){a(e)}}function u(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,l)}u((n=n.apply(e,t||[])).next())}))},o=this&&this.__generator||function(e,t){var r,n,o,a,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return a={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function l(l){return function(u){return function(l){if(r)throw new TypeError("Generator is already executing.");for(;a&&(a=0,l[0]&&(i=0)),i;)try{if(r=1,n&&(o=2&l[0]?n.return:l[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,l[1])).done)return o;switch(n=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return i.label++,{value:l[1],done:!1};case 5:i.label++,n=l[1],l=[0];continue;case 7:l=i.ops.pop(),i.trys.pop();continue;default:if(!((o=(o=i.trys).length>0&&o[o.length-1])||6!==l[0]&&2!==l[0])){i=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},u=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockBuilderPromise=void 0;var f=r(2603),c=u(r(5551)),d=r(6456),s=u(r(2970)),v=r(5974),p=r(3659),h=u(r(8073)),y=r(3771),_=r(9539),g=u(r(7140)),b=u(r(1649)),m=u(r(4387)),M=u(r(1267)),k=u(r(9961)),w=u(r(7703)),O=u(r(5195)),x=u(r(1391)),j=u(r(7235)),D=u(r(8792)),S=u(r(9102)),P=function(e){return(0,p.isNgModuleDefWithProviders)(e)?{def:e.ngModule,providers:e.providers}:{def:e,providers:void 0}},C=function(e,t,r){return r?i(i([],a(Array.isArray(t)?t:[]),!1),[e],!1):e},N={},T=function(){function e(e){this.configDefault=e,this.beforeCC=new Set,this.configDef=new Map,this.defProviders=new Map,this.defValue=new Map,this.excludeDef=new Set,this.keepDef=new Set,this.mockDef=new Set,this.providerDef=new Map,this.replaceDef=new Set,this.stash=new _.MockBuilderStash,"undefined"!=typeof Symbol&&(this[Symbol.toStringTag]="Promise")}return e.prototype.beforeCompileComponents=function(e){return this.beforeCC.add(e),this},e.prototype.build=function(){this.stash.backup();var e=new c.default;h.default.config.set("mockNgDefResolver",e),h.default.flags.add("hasRootModule");try{var t=this.combineParams(),r=(0,x.default)(t,(0,j.default)(t));return(0,g.default)(r,t,e),(0,O.default)(r,t,e),(0,w.default)(r),(0,b.default)(),r.providers.push((0,M.default)(),(0,k.default)(),(0,m.default)(this.replaceDef,this.defValue),y.MockBuilder),r}finally{h.default.flags.delete("hasRootModule"),h.default.config.delete("mockNgDefResolver"),this.stash.restore()}},e.prototype.catch=function(e){return n(this,void 0,Promise,(function(){return o(this,(function(t){return[2,this.then().catch(e)]}))}))},e.prototype.exclude=function(e){return this.wipe(e),this.excludeDef.add(e),this.setConfigDef(e),this},e.prototype.finally=function(e){return n(this,void 0,Promise,(function(){return o(this,(function(t){return[2,this.then().finally(e)]}))}))},e.prototype.keep=function(e,t){var r=P(e),n=r.def,o=r.providers,l=this.keepDef.has(n)?this.defProviders.get(n):[];return this.wipe(n),this.keepDef.add(n),o&&this.defProviders.set(n,i(i([],a(l||[]),!1),a(o),!1)),this.setConfigDef(n,t),this},e.prototype.mock=function(e,t,r){void 0===t&&(t=N);var n=P(e),o=n.def,l=n.providers,u=(0,D.default)(o,t,r,N),f=u.config,c=u.mock;if((0,v.isNgDef)(c)&&(0,v.isNgDef)(e)&&!(0,v.isNgDef)(e,"t"))throw new Error(["MockBuilder.mock(".concat((0,s.default)(e),") received a class when its shape is expected."),"Please try ngMocks.defaultMock instead."].join(" "));var d=this.mockDef.has(o)?this.defProviders.get(o):[];return this.wipe(o),this.mockDef.add(o),l&&this.defProviders.set(o,i(i([],a(d||[]),!1),a(l),!1)),this.setDefValue(o,c),this.setConfigDef(o,f),this},e.prototype.provide=function(e){var t,r;try{for(var n=l((0,d.flatten)(e)),o=n.next();!o.done;o=n.next()){var a=o.value,i=(0,S.default)(a),u=i.provide,f=i.multi,c=this.providerDef.has(u)?this.providerDef.get(u):[];this.providerDef.set(u,C(a,c,f))}}catch(e){t={error:e}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(t)throw t.error}}return this},e.prototype.replace=function(e,t,r){if(!(0,v.isNgDef)(t)||!(0,v.isNgDef)(e)||(0,v.isNgDef)(t,"i")||(0,v.isNgDef)(e,"i"))throw new Error("Cannot replace the declaration, both have to be a Module, a Component, a Directive or a Pipe, for Providers use `.mock` or `.provide`");return this.wipe(e),this.replaceDef.add(e),this.defValue.set(e,t),this.setConfigDef(e,r),this},e.prototype.then=function(e,t){return n(this,void 0,Promise,(function(){var r,n=this;return o(this,(function(o){return r=new Promise((function(e){var t,r,o=f.TestBed.configureTestingModule(n.build());try{for(var a=l((0,d.mapValues)(n.beforeCC)),i=a.next();!i.done;i=a.next())(0,i.value)(o)}catch(e){t={error:e}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}o.compileComponents().then((function(){e({testBed:o})}))})),[2,r.then(e,t)]}))}))},e.prototype.combineParams=function(){return{configDef:this.configDef,configDefault:this.configDefault,defProviders:this.defProviders,defValue:this.defValue,excludeDef:this.excludeDef,keepDef:this.keepDef,mockDef:this.mockDef,providerDef:this.providerDef,replaceDef:this.replaceDef}},e.prototype.setConfigDef=function(e,t){!t&&this.configDef.has(e)||this.configDef.set(e,null!=t?t:this.configDefault)},e.prototype.setDefValue=function(e,t){t===N?this.defValue.delete(e):this.defValue.set(e,t)},e.prototype.wipe=function(e){this.defProviders.delete(e),this.defValue.delete(e),this.excludeDef.delete(e),this.keepDef.delete(e),this.mockDef.delete(e),this.providerDef.delete(e),this.replaceDef.delete(e)},e}();t.MockBuilderPromise=T},3771:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockBuilder=s;var i=a(r(3174)),l=r(6456),u=r(6580),f=a(r(8073)),c=a(r(5020)),d=r(9755);function s(){for(var e,t,r,a,s,v,p=[],h=0;h=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0});var o=r(6456);t.default=function(e,t,r){var a,i;if(void 0===r&&(r=function(e,t){return e===t}),!t||t.size!==e.size)return!1;try{for(var l=n((0,o.mapKeys)(e)),u=l.next();!u.done;u=l.next()){var f=u.value;if(!t.has(f))return!1;if(!r(t.get(f),e.get(f)))return!1}}catch(e){a={error:e}}finally{try{u&&!u.done&&(i=l.return)&&i.call(l)}finally{if(a)throw a.error}}return!0}},7570:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=function(e,t){for(var r,o,a=[],i=2;i=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0});var o=r(6456);t.default=function(e,t){var r,a;if(!t||t.size!==e.size)return!1;try{for(var i=n((0,o.mapValues)(e)),l=i.next();!l.done;l=i.next()){var u=l.value;if(!t.has(u))return!1}}catch(e){r={error:e}}finally{try{l&&!l.done&&(a=i.return)&&a.call(i)}finally{if(r)throw r.error}}return!0}},2801:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(5432));t.default=function(e,t){return!(!(0,a.default)(t,e)||"object"==typeof t&&"object"==typeof e&&function(e,t){var r,o;if(Object.keys(e).length!==Object.keys(t).length)return!0;try{for(var i=n(Object.keys(e)),l=i.next();!l.done;l=i.next()){var u=l.value;if(!(0,a.default)(e[u],t[u]))return!0}}catch(e){r={error:e}}finally{try{l&&!l.done&&(o=i.return)&&o.call(i)}finally{if(r)throw r.error}}return!1}(t,e))}},5432:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(9382));t.default=function(e,t){return e===t||("boolean"!=typeof e&&"boolean"!=typeof t||e===t)&&e.$implicit===t.$implicit&&(0,o.default)(e.variables,t.variables)}},9382:function(e,t){var r=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){return e===t||!(e&&!t||!e&&t)&&!function(e,t){var n,o,a=Object.keys(e),i=Object.keys(t);if(a.length!==i.length)return!0;try{for(var l=r(a),u=l.next();!u.done;u=l.next()){var f=u.value;if(e[f]!==t[f])return!0}}catch(e){n={error:e}}finally{try{u&&!u.done&&(o=l.return)&&o.call(l)}finally{if(n)throw n.error}}return!1}(e,t)}},5633:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(){return{beforeCC:new Set,configDef:new Map,defProviders:new Map,defValue:new Map,excludeDef:new Set,keepDef:new Set,mockDef:new Set,providerDef:new Map,replaceDef:new Set}}},4503:function(e,t){var r=this&&this.__assign||function(){return r=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(8911)),l=o(r(6297)),u=o(r(8073)),f=o(r(3663));t.default=function(e,t,r){var o,c,d,s,v,p,h=t.providerDef,y=t.mockDef;try{for(var _=n((0,a.mapValues)(h)),g=_.next();!g.done;g=_.next()){var b=g.value;e.providers.push(b)}}catch(e){o={error:e}}finally{try{g&&!g.done&&(c=_.return)&&c.call(_)}finally{if(o)throw o.error}}try{for(var m=n((0,a.flatten)(e.providers)),M=m.next();!M.done;M=m.next()){b=M.value;var k=(0,l.default)(b);u.default.touches.add(k),k!==b&&b.deps&&(0,a.extractDependency)(b.deps,u.default.config.get("ngMocksDeps"))}}catch(e){d={error:e}}finally{try{M&&!M.done&&(s=m.return)&&s.call(m)}finally{if(d)throw d.error}}try{for(var w=n((0,a.mapValues)(y)),O=w.next();!O.done;O=w.next()){var x=O.value;u.default.touches.has(x)||"root"!==(0,i.default)(x)||(e.providers.push((0,f.default)(x,r)),u.default.touches.add(x))}}catch(e){v={error:e}}finally{try{O&&!O.done&&(p=w.return)&&p.call(w)}finally{if(v)throw v.error}}}},1649:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(2603),i=r(6456),l=o(r(6297)),u=o(r(8073));t.default=function(){var e,t,r=(0,a.getTestBed)();if(r.ngModule)try{for(var o=n((0,i.flatten)(r.ngModule)),f=o.next();!f.done;f=o.next()){var c=f.value;u.default.touches.add((0,l.default)(c))}}catch(t){e={error:t}}finally{try{f&&!f.done&&(t=o.return)&&t.call(o)}finally{if(e)throw e.error}}}},646:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t,r){"function"==typeof e&&-1===r.indexOf(e)&&(r.push(e),t.push(e))}},4387:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(1381)),l=r(1763),u=o(r(8073)),f=o(r(5884)),c=o(r(4483));t.default=function(e,t){var r,o,d,s,v=new Map;try{for(var p=n((0,a.mapValues)(u.default.touches)),h=p.next();!h.done;h=p.next()){var y=h.value,_=u.default.getBuildDeclaration(y)||y;if(!(0,c.default)(e,t,y,_)){var g=(0,i.default)(_),b=(0,f.default)(g);if(b){var m={};try{for(var M=(d=void 0,n(Object.keys(b))),k=M.next();!k.done;k=M.next()){var w=k.value;m[w]=g[w]}}catch(e){d={error:e}}finally{try{k&&!k.done&&(s=M.return)&&s.call(M)}finally{if(d)throw d.error}}v.set(_,[{set:b},{set:m}])}}}}catch(e){r={error:e}}finally{try{h&&!h.done&&(o=p.return)&&o.call(p)}finally{if(r)throw r.error}}return{provide:l.NG_MOCKS_OVERRIDES,useValue:v}}},1267:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=r(6456),u=r(1763),f=i(r(8073));t.default=function(){var e,t,r=new Map;try{for(var i=a(o(o(o(o([],n((0,l.mapEntries)(f.default.builtProviders)),!1),n((0,l.mapEntries)(f.default.builtDeclarations)),!1),n((0,l.mapEntries)(f.default.cacheDeclarations)),!1),n((0,l.mapEntries)(f.default.cacheProviders)),!1)),c=i.next();!c.done;c=i.next()){var d=n(c.value,2),s=d[0],v=d[1];r.has(s)||r.set(s,v)}}catch(t){e={error:t}}finally{try{c&&!c.done&&(t=i.return)&&t.call(i)}finally{if(e)throw e.error}}return{provide:u.NG_MOCKS,useValue:r}}},9961:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=r(1763),l=o(r(8073));t.default=function(){var e,t,r=new Set;try{for(var o=n((0,a.mapValues)(l.default.touches)),u=o.next();!u.done;u=o.next()){var f=u.value,c=l.default.getBuildDeclaration(f);void 0===c&&(c=f),r.add(f),r.add(c)}}catch(t){e={error:t}}finally{try{u&&!u.done&&(t=o.return)&&t.call(o)}finally{if(e)throw e.error}}return{provide:i.NG_MOCKS_TOUCHES,useValue:r}}},8608:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(7285));t.default=function(e){var t,r;if(e){var o;try{for(var i=n(e),l=i.next();!l.done;l=i.next()){var u=l.value;u&&"object"==typeof u&&u.token&&(o=u.token),o||!u||"object"==typeof u&&u.ngMetadataName||(o=u)}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}return(0,a.default)(o)}}},5884:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(8073)),i=o(r(224));t.default=function(e){if(e){var t=a.default.flags.has("skipMock");t||a.default.flags.add("skipMock");var r=n((0,i.default)(e),2),o=r[0],l=r[1];if(t||a.default.flags.delete("skipMock"),o)return l}}},8703:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(8749)),i=r(1763),l=o(r(8073)),u=o(r(2504)),f=o(r(646)),c=o(r(8608)),d=o(r(1978)),s=o(r(7213)),v=o(r(4995));t.default=function(e){var t,r,o,p,h,y,_=new Set,g=(0,d.default)(),b=g.buckets,m=g.touched;try{for(var M=n(b),k=M.next();!k.done;k=M.next()){var w=k.value;try{for(var O=(o=void 0,n(w)),x=O.next();!x.done;x=O.next()){var j=x.value;(0,u.default)(_,e,j);try{for(var D=(h=void 0,n((0,a.default)(j))),S=D.next();!S.done;S=D.next()){var P=S.value,C=(0,c.default)(P);(0,s.default)(C),(0,v.default)(C)||((0,f.default)(C,m,w),e.has(i.NG_MOCKS_ROOT_PROVIDERS)||!l.default.config.get("ngMocksDepsSkip").has(j)?_.add(C):l.default.config.get("ngMocksDepsSkip").add(C))}}catch(e){h={error:e}}finally{try{S&&!S.done&&(y=D.return)&&y.call(D)}finally{if(h)throw h.error}}}}catch(e){o={error:e}}finally{try{x&&!x.done&&(p=O.return)&&p.call(O)}finally{if(o)throw o.error}}}}catch(e){t={error:e}}finally{try{k&&!k.done&&(r=M.return)&&r.call(M)}finally{if(t)throw t.error}}return _}},1978:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=r(860),u=i(r(3174)),f=r(6456),c=r(1763),d=r(5974),s=i(r(1365)),v=function(e,t){if(t){var r=t.resolveComponentFactory;t.resolveComponentFactory=(0,s.default)(r,void 0,void 0,(function(a){for(var i,l=[],u=1;u=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=r(1763),l=r(4152),u=o(r(8073)),f=o(r(3663)),c=o(r(9465)),d=o(r(8703));t.default=function(e,t,r){var o,s,v=t.keepDef,p=t.mockDef,h=v.has(i.NG_MOCKS_ROOT_PROVIDERS)?new Set:(0,d.default)(p);if(h.size>0){var y=function(t){var n=(0,f.default)(t,r);if(n)e.providers.push(n);else if((0,l.isNgInjectionToken)(t)){var o=u.default.config.has("ngMocksMulti")&&u.default.config.get("ngMocksMulti").has(t);e.providers.push((0,c.default)(t,(function(){return o?[]:void 0})))}};try{for(var _=n((0,a.mapValues)(h)),g=_.next();!g.done;g=_.next())y(g.value)}catch(e){o={error:e}}finally{try{g&&!g.done&&(s=_.return)&&s.call(_)}finally{if(o)throw o.error}}}}},2710:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(8073));t.default=function(e){var t,r,o=i.default.builtDeclarations,l=i.default.builtProviders,u=i.default.config.get("ngMocksDepsResolution");try{for(var f=n((0,a.mapValues)(e)),c=f.next();!c.done;c=f.next()){var d=c.value;o.set(d,null),l.set(d,null),u.set(d,"exclude")}}catch(e){t={error:e}}finally{try{c&&!c.done&&(r=f.return)&&r.call(f)}finally{if(t)throw t.error}}}},7651:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=r(5204),l=o(r(8073));t.default=function(e,t){var r,o,u=new Set,f=l.default.builtDeclarations,c=l.default.builtProviders,d=l.default.config.get("ngMocksDepsResolution");try{for(var s=n((0,a.mapValues)(e)),v=s.next();!v.done;v=s.next()){var p=v.value;f.set(p,p),c.set(p,p),d.set(p,"keep"),t.get(p).shallow&&(0,i.funcExtractDeps)(p,u)}}catch(e){r={error:e}}finally{try{v&&!v.done&&(o=s.return)&&o.call(s)}finally{if(r)throw r.error}}return u}},102:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(8073)),l=o(r(4161));t.default=function(e,t){var r,o,u=i.default.builtDeclarations,f=i.default.config.get("ngMocksDepsResolution");try{for(var c=n((0,a.mapValues)(e)),d=c.next();!d.done;d=c.next()){var s=d.value,v=!i.default.touches.has(s);f.set(s,"mock"),u.set(s,void 0),(0,l.default)(s,t),v&&i.default.touches.delete(s)}}catch(e){r={error:e}}finally{try{d&&!d.done&&(o=c.return)&&o.call(c)}finally{if(r)throw r.error}}}},3680:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8073));t.default=function(e,t){var r,n=null!==(r=o.default.config.get("mockNgDefResolver").get(e))&&void 0!==r?r:o.default.getBuildDeclaration(e),a=t.has(e)?t.get(e):void 0;return a?{ngModule:n,providers:a}:n}},1159:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=r(6456),u=r(5974),f=i(r(8073)),c=r(3821),d=i(r(224)),s=i(r(4673)),v=i(r(8150));t.default=function(e,t,r,i){var p,h,y,_,g,b,m,M,k,w=new Map;try{for(var O=a(o(o(o([],n((0,l.mapValues)(e)),!1),n((0,l.mapValues)(t)),!1),n((0,l.mapValues)(r)),!1)),x=O.next();!x.done;x=O.next()){var j=x.value,D=(0,s.default)(j),S=o(o(o([],n(null!==(g=i.get(j))&&void 0!==g?g:[]),!1),n(null!==(m=null===(b=D.Component)||void 0===b?void 0:b.providers)&&void 0!==m?m:[]),!1),n(null!==(k=null===(M=D.Directive)||void 0===M?void 0:M.providers)&&void 0!==k?k:[]),!1),P=!f.default.touches.has(j);t.has(j)||f.default.flags.add("skipMock");var C=(0,u.isNgDef)(j,"m");if(S.length>0){var N=n((0,d.default)({providers:S,skipMarkProviders:!C,skipExports:!0}),2)[1];w.set(j,N.providers)}C&&f.default.builtDeclarations.set(j,(0,c.MockModule)(j)),f.default.flags.delete("skipMock"),P&&f.default.touches.delete(j)}}catch(e){p={error:e}}finally{try{x&&!x.done&&(h=O.return)&&h.call(O)}finally{if(p)throw p.error}}try{for(var T=a((0,l.mapValues)(t)),E=T.next();!E.done;E=T.next())j=E.value,(0,v.default)(j)}catch(e){y={error:e}}finally{try{E&&!E.done&&(_=T.return)&&_.call(T)}finally{if(y)throw y.error}}return w}},1391:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(8073));t.default=function(e,t){var r,o,l=i.default.builtDeclarations,u=i.default.config.get("ngMocksDepsResolution");try{for(var f=n((0,a.mapValues)(e)),c=f.next();!c.done;c=f.next()){var d=c.value;l.set(d,t.get(d)),u.set(d,"replace")}}catch(e){r={error:e}}finally{try{c&&!c.done&&(o=f.return)&&o.call(f)}finally{if(r)throw r.error}}}},7235:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=r(6456),u=r(5204),f=i(r(8073)),c=i(r(2710)),d=i(r(7651)),s=i(r(102)),v=i(r(1159)),p=i(r(8500));t.default=function(e){var t,r,i,h,y,_,g,b,m,M,k,w,O=e.configDef,x=e.defProviders,j=e.defValue,D=e.excludeDef,S=e.keepDef,P=e.mockDef,C=e.replaceDef;f.default.flags.add("cachePipe"),f.default.config.set("ngMocksMulti",new Set),f.default.config.set("ngMocksDeps",new Set),f.default.config.set("ngMocksDepsSkip",new Set),f.default.config.set("ngMocksDepsResolution",new Map);var N=(0,d.default)(S,O);try{for(var T=o((0,l.mapValues)(N)),E=T.next();!E.done;E=T.next()){var A=E.value;f.default.touches.add(A)}}catch(e){t={error:e}}finally{try{E&&!E.done&&(r=T.return)&&r.call(T)}finally{if(t)throw t.error}}try{for(var R=o((0,l.mapValues)(S)),I=R.next();!I.done;I=R.next())A=I.value,N.add(A),(0,u.funcExtractDeps)(A,N,!0)}catch(e){i={error:e}}finally{try{I&&!I.done&&(h=R.return)&&h.call(R)}finally{if(i)throw i.error}}try{for(var V=o((0,l.mapValues)(P)),B=V.next();!B.done;B=V.next())A=B.value,N.add(A),(0,u.funcExtractDeps)(A,N,!0)}catch(e){y={error:e}}finally{try{B&&!B.done&&(_=V.return)&&_.call(V)}finally{if(y)throw y.error}}try{for(var F=o((0,l.mapValues)(C)),L=F.next();!L.done;L=F.next())A=L.value,N.add(A),(0,u.funcExtractDeps)(A,N,!0)}catch(e){g={error:e}}finally{try{L&&!L.done&&(b=F.return)&&b.call(F)}finally{if(g)throw g.error}}try{for(var K=o((0,l.mapValues)(N)),G=K.next();!G.done;G=K.next())if(A=G.value,!O.has(A)){var q=f.default.getResolution(A);"replace"===q?(C.add(A),j.set(A,f.default.getBuildDeclaration(A))):"keep"===q?S.add(A):"exclude"===q?D.add(A):("mock"===q||f.default.touches.has(A))&&P.add(A),O.set(A,f.default.touches.has(A)?{dependency:!0,__internal:!0}:{})}}catch(e){m={error:e}}finally{try{G&&!G.done&&(M=K.return)&&M.call(K)}finally{if(m)throw m.error}}try{for(var U=o((0,l.mapEntries)(O)),z=U.next();!z.done;z=U.next()){var W=a(z.value,2),H=W[0],$=W[1];f.default.config.set(H,n(n(n({},f.default.getConfigMock().get(H)),$),{defValue:j.get(H)}))}}catch(e){k={error:e}}finally{try{z&&!z.done&&(w=U.return)&&w.call(U)}finally{if(k)throw k.error}}return(0,p.default)(C,j),(0,c.default)(D),(0,s.default)(P,j),(0,v.default)(S,P,C,x)}},8792:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(5974);t.default=function(e,t,r,o){var a=e===t?o:t,i=null!=r?r:t!==o&&"object"==typeof t?t:void 0;return(0,n.isNgDef)(e,"p")&&"function"==typeof t&&t!==e&&!(0,n.isNgDef)(t,"p")?(a={transform:t},i=r):!(0,n.isNgDef)(e,"i")&&(0,n.isNgDef)(e)||(i=r),{config:i,mock:a=a===i?o:a}}},9102:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(6297));t.default=function(e){var t=(0,o.default)(e);return{multi:t!==e&&e.multi,provide:t}}},70:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(4358),a=n(r(3295)),i=n(r(8911)),l=r(4152),u=n(r(8073));t.default=function(e){if(function(e){if(!e||e===o.DOCUMENT||u.default.touches.has(e))return!0;var t=function(e){var t=u.default.getResolution(e);return"keep"===t||"exclude"===t||"mock"!==t&&void 0}(e);return void 0!==t?t:"function"==typeof e&&-1!==a.default.neverMockProvidedFunction.indexOf(e.name)||!(!(0,l.isNgInjectionToken)(e)||-1===a.default.neverMockToken.indexOf(e.toString()))}(e))return!0;var t=(0,i.default)(e);return!("function"!=typeof e||t&&"platform"!==t)}},4483:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8073));t.default=function(e,t,r,n){return!!o.default.cacheDeclarations.has(n)||!(!e.has(r)||n!==t.get(r))}},4995:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8073)),a=n(r(70));t.default=function(e){return!!(0,a.default)(e)||o.default.config.get("ngMocksDepsSkip").has(e)}},8150:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(5974),a=n(r(8073)),i=r(5395),l=r(8339),u=r(2937);t.default=function(e){void 0===a.default.builtDeclarations.get(e)&&((0,o.isNgDef)(e,"c")&&a.default.builtDeclarations.set(e,(0,i.MockComponent)(e)),(0,o.isNgDef)(e,"d")&&a.default.builtDeclarations.set(e,(0,l.MockDirective)(e)),(0,o.isNgDef)(e,"p")&&a.default.builtDeclarations.set(e,(0,u.MockPipe)(e)))}},4161:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(5974),a=n(r(8073)),i=n(r(8195)),l=n(r(9465)),u=n(r(2415));t.default=function(e,t){if((0,o.isNgDef)(e,"i")&&t.has(e)){var r=a.default.config.get(e),n=t.get(e);a.default.builtProviders.set(e,(0,l.default)(e,void 0,(function(e){return function(e,t,r){return r.precise?t:(0,i.default)(e,t)}(e,n,r)})))}else(0,o.isNgDef)(e,"i")&&a.default.builtProviders.set(e,(0,u.default)(e,!0));if(!(0,o.isNgDef)(e)&&t.has(e)){var f=t.get(e);a.default.builtProviders.set(e,(0,l.default)(e,void 0,(function(){return f})))}else(0,o.isNgDef)(e)||a.default.builtProviders.set(e,(0,u.default)(e,!0))}},2938:function(e,t){Object.defineProperty(t,"__esModule",{value:!0})},5395:function(e,t,r){var n,o=this&&this.__extends||(n=function(e,t){return n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},n(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function r(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),a=this&&this.__assign||function(){return a=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},l=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},u=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockComponents=function(){for(var e=[],t=0;t=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0});var o=r(860),a={read:o.ViewContainerRef,static:!1},i={read:o.TemplateRef,static:!1},l=function(e,t){var r="
");return"").concat(r,"")},u=function(e){return!(e.isViewQuery||e.read&&e.read!==o.TemplateRef||"string"!=typeof e.selector&&!e.read)};t.default=function(e){var t,r,f=[""];if(!e)return f.join("");try{for(var c=n(Object.keys(e)),d=c.next();!d.done;d=c.next()){var s=d.value,v=e[s];if(0!==s.indexOf("__mock")&&u(v)){if("string"==typeof v.selector){var p=v.selector.replace(new RegExp("\\W","mg"),"_");e["__vcrIf_key_".concat(p)]=new o.ViewChild("ngIf_key_".concat(p),a),e["__trIf_key_".concat(p)]=new o.ViewChild("ngIf_key_".concat(p),i),e["__mockView_key_".concat(p)]=new o.ViewChild("key_".concat(p),a),e["__mockTpl_key_".concat(p)]=v,f.push(l(p,"key"))}e["__vcrIf_prop_".concat(s)]=new o.ViewChild("ngIf_prop_".concat(s),a),e["__trIf_prop_".concat(s)]=new o.ViewChild("ngIf_prop_".concat(s),i),e["__mockView_prop_".concat(s)]=new o.ViewChild("prop_".concat(s),a),f.push(l(s,"prop"))}}}catch(e){t={error:e}}finally{try{d&&!d.done&&(r=c.return)&&r.call(c)}finally{if(t)throw t.error}}return f.join("")}},8970:function(e,t){var r=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i};Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){if("string"==typeof e)return["key","__mockTpl_key_".concat(e),e,void 0];var t=r(e),n=t[0],o=t.slice(1);return["prop",n,n,o.length>0?o:void 0]}},2350:function(e,t){Object.defineProperty(t,"__esModule",{value:!0})},5269:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockDeclarations=function(){for(var e=[],t=0;t=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(1184)),l=a(r(6755)),u=a(r(1692));t.default=function(e,t){return function(r){return!!function(e,t,r){for(var n,a,i,l=(null===(n=e.injector._tNode)||void 0===n?void 0:n.attrs)||[],u=2,f=0;f0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(5465)),i=o(r(908));t.default=function(e){return function(t){var r=n((0,i.default)(t),2),o=r[0];return-1!==r[1].indexOf(e)||!!(0,a.default)(o,e)}}},12:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4201)),a=r(6739);t.default=function(e){var t=(0,a.getSourceOfMock)(e);return function(e){return!!e&&-1!==e.providerTokens.indexOf(t)&&void 0!==(0,o.default)(t,e.injector)}}},1863:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return function(t){return!!t.references[e]}}},5494:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(908)),i=o(r(4747));t.default=function(e){return function(t){var r=n((0,a.default)(t),1)[0];return(0,i.default)(r,e)}}},5465:function(e,t){var r=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){var n,o,a,i;try{for(var l=r(e),u=l.next();!u.done;u=l.next()){var f=u.value.match(/\[([^=\]]+)/g);if(f)try{for(var c=(a=void 0,r(f)),d=c.next();!d.done;d=c.next())if(d.value==="[".concat(t))return!0}catch(e){a={error:e}}finally{try{d&&!d.done&&(i=c.return)&&i.call(c)}finally{if(a)throw a.error}}}}catch(e){n={error:e}}finally{try{u&&!u.done&&(o=l.return)&&o.call(l)}finally{if(n)throw n.error}}return!1}},4476:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8864)),a=n(r(8060)),i=n(r(12)),l=n(r(1863)),u=n(r(5494));t.default=function(e){if(function(e){return Array.isArray(e)&&1===e.length&&"string"==typeof e[0]}(e))return(0,o.default)(e[0]);if(function(e){return Array.isArray(e)&&2===e.length&&"string"==typeof e[0]}(e))return(0,a.default)(e[0],e[1]);if(function(e){return"string"==typeof e&&0===e.indexOf("#")&&e.length>1}(e))return(0,l.default)(e.slice(1));if(function(e){return"string"==typeof e&&0!==e.indexOf("#")&&e.length>0}(e))return(0,u.default)(e);if(function(e){return"function"==typeof e}(e))return(0,i.default)(e);throw new Error("Unknown selector")}},908:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0});var n=new RegExp("\\[.*?\\]","g");t.default=function(e,t){var o,a,i,l;try{for(var u=r(e),f=u.next();!f.done;f=u.next()){var c=f.value.replace(n,"").split(",");try{for(var d=(i=void 0,r(c)),s=d.next();!s.done;s=d.next())if(s.value.trim()===t)return!0}catch(e){i={error:e}}finally{try{s&&!s.done&&(l=d.return)&&l.call(d)}finally{if(i)throw i.error}}}}catch(e){o={error:e}}finally{try{f&&!f.done&&(a=u.return)&&a.call(u)}finally{if(o)throw o.error}}return!1}},3942:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return"#text"===e.nativeNode.nodeName}},5079:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){return!(!e||!t)&&e===t}},6121:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(3942));t.default=function(e){return(0,o.default)(e)?void 0:e.injector._tNode||e.injector.elDef||void 0}},1061:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=r(860),l=a(r(4201)),u=a(r(6121)),f=function(e,t){var r=function(e,t){if(e!==t&&"#comment"===t.nativeNode.nodeName)return(0,l.default)(i.ViewContainerRef,t.injector)}(e,t);if(!r)return[];for(var n=[],o=0;o0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(590)),i=o(r(5687)),l=o(r(951)),u=o(r(4476)),f=o(r(3942)),c=o(r(6547)),d=o(r(8344));t.default=function(){for(var e=[],t=0;t0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(590)),i=o(r(5687)),l=o(r(951)),u=o(r(4811)),f=o(r(4476)),c=o(r(3942)),d=o(r(6547)),s=o(r(8344)),v={};t.default=function(){for(var e=[],t=0;t=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3942)),i=o(r(5079)),l=o(r(6121)),u=o(r(1061));t.default=function(e){var t,r,o,f,c=(0,l.default)(e);if(!c||(0,a.default)(e))return[];var d=void 0!==e.childNodes,s=[];try{for(var v=n(e.childNodes||(null===(o=e.parent)||void 0===o?void 0:o.childNodes)||[]),p=v.next();!p.done;p=v.next()){var h=p.value,y=(0,u.default)(h);(d||(0,i.default)(c,y))&&(y&&!(0,i.default)(c,y)||s.push(h))}}catch(e){t={error:e}}finally{try{p&&!p.done&&(r=v.return)&&r.call(v)}finally{if(t)throw t.error}}if("BODY"===(null===(f=e.parent)||void 0===f?void 0:f.name)){for(var _=e.parent.childNodes,g=_.length,b=0,m=_.length-1;m>=0;m-=1)if("#comment"===(h=_[m]).nativeNode.nodeName)b=m;else if(h.nativeNode===e.nativeNode){g=m+1;break}for(m=g;m=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(5079)),i=o(r(6121)),l=o(r(1061));t.default=function(e,t){var r,o,u;if(t)return t;var f=(0,l.default)(e),c=e.parent?(0,i.default)(e.parent):void 0;if(e.parent&&(0,a.default)(f,c))return e.parent;try{for(var d=n((null===(u=e.parent)||void 0===u?void 0:u.childNodes)||[]),s=d.next();!s.done;s=d.next()){var v=s.value,p=(0,i.default)(v);if((0,a.default)(f,p))return v}}catch(e){r={error:e}}finally{try{s&&!s.done&&(o=d.return)&&o.call(d)}finally{if(r)throw r.error}}}},8732:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3942)),i=o(r(7790)),l=o(r(345)),u=function(e,t,r,o){var f,c;if(void 0===o&&(o=!1),!e)return!1;if(!o&&(0,a.default)(e))return!1;if(r(e,(0,l.default)(e,t)))return!0;try{for(var d=n((0,i.default)(e)),s=d.next();!s.done;s=d.next()){var v=s.value;if(u(v,e,r,o))return!0}}catch(e){f={error:e}}finally{try{s&&!s.done&&(c=d.return)&&c.call(d)}finally{if(f)throw f.error}}return!1};t.default=u},6016:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(2023)),a=n(r(4201)),i=["Cannot find ControlValueAccessor on the element.","If it is a mock input with [formControlName],","you need either to avoid mocking ReactiveFormsModule","or to avoid accessing the control in such a way,","because this tests ReactiveFormsModule instead of own implementation."].join(" ");t.default=function(e){var t=o.default&&(0,a.default)(o.default.NgControl,e.injector),r=null==t?void 0:t.valueAccessor;if(r)return r;var n=o.default&&(0,a.default)(o.default.FormControlDirective,e.injector);if(null==n?void 0:n.form)return n.form;var l=o.default&&(0,a.default)(o.default.NgModel,e.injector);if(l)return l;throw new Error(i)}},2298:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(2023)),i=r(7105),l=o(r(5006)),u=o(r(7331)),f=o(r(1991)),c=o(r(590)),d=o(r(5687)),s=o(r(4811)),v=o(r(589)),p=o(r(6016)),h=["onChange","onChangeCallback","onChangeCb","onChangeClb","onChangeFn","_onChange","_onChangeCallback","_onChangeCb","_onChangeClb","_onChangeFn","changeFn","_changeFn","onModelChange","cvaOnChange","cvaOnChangeCallback","cvaOnChangeCb","cvaOnChangeClb","cvaOnChangeFn","_cvaOnChange","_cvaOnChangeCallback","_cvaOnChangeCb","_cvaOnChangeClb","_cvaOnChangeFn"];t.default=function(e,t,r){var o,y,_=(0,c.default)((0,d.default)(),e,void 0);if(!_)throw new Error("Cannot find an element via ngMocks.change(".concat((0,s.default)(e),")"));var g=(0,p.default)(_);if(!function(e,t){return a.default&&e instanceof a.default.AbstractControl?(e.setValue(t),!0):a.default&&e instanceof a.default.NgModel?(e.update.emit(t),!0):!!(0,i.isMockControlValueAccessor)(e.instance)&&(e.instance.__simulateChange(t),!0)}(g,t)&&!function(e){return e.listeners.some((function(e){return"input"===e.name||"change"===e.name}))}(_)){try{for(var b=n(r?[r]:h),m=b.next();!m.done;m=b.next()){var M=m.value;if("function"==typeof g[M])return g.writeValue(t),void g[M](t)}}catch(e){o={error:e}}finally{try{m&&!m.done&&(y=b.return)&&y.call(b)}finally{if(o)throw o.error}}var k=(0,u.default)(g);throw new Error(["Unsupported type of ControlValueAccessor,","please ensure it has '".concat(r||"onChange","' method."),"If it is a 3rd-party library, please provide the correct name of the method in the 'methodName' parameter.","Possible Names: "+k.join(", ")+"."].join(" "))}!function(e,t){(0,f.default)(e,"focus");var r=Object.getOwnPropertyDescriptor(e.nativeElement,"value");(0,v.default)(e.nativeElement,"value",t),(0,f.default)(e,"input"),(0,f.default)(e,"change"),r&&((0,l.default)(e.nativeElement,"value",r),e.nativeElement.value=t),(0,f.default)(e,"blur")}(_,t)}},7655:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(2023)),i=r(7105),l=o(r(7331)),u=o(r(1991)),f=o(r(590)),c=o(r(5687)),d=o(r(4811)),s=o(r(6016)),v=["onTouched","onTouchedCallback","onTouchedCb","onTouchedClb","onTouchedFn","_onTouched","_onTouchedCallback","_onTouchedCb","_onTouchedClb","_onTouchedFn","markAsTouched","_markAsTouched","onModelTouched","cvaOnTouch","cvaOnTouchCallback","cvaOnTouchCb","cvaOnTouchClb","cvaOnTouchFn","_cvaOnTouch","_cvaOnTouchCallback","_cvaOnTouchCb","_cvaOnTouchClb","_cvaOnTouchFn"];t.default=function(e,t){var r,o,p=(0,f.default)((0,c.default)(),e,void 0);if(!p)throw new Error("Cannot find an element via ngMocks.touch(".concat((0,d.default)(e),")"));var h=(0,s.default)(p);if(!function(e){return a.default&&e instanceof a.default.AbstractControl?(e.markAsTouched(),!0):!!(0,i.isMockControlValueAccessor)(e.instance)&&(e.instance.__simulateTouch(),!0)}(h)&&!function(e){return e.listeners.some((function(e){return"focus"===e.name||"blur"===e.name}))}(p)){try{for(var y=n(t?[t]:v),_=y.next();!_.done;_=y.next()){var g=_.value;if("function"==typeof h[g])return void h[g]()}}catch(e){r={error:e}}finally{try{_&&!_.done&&(o=y.return)&&o.call(y)}finally{if(r)throw r.error}}var b=(0,l.default)(h);throw new Error(["Unsupported type of ControlValueAccessor,","please ensure it has '".concat(t||"onTouched","' method."),"If it is a 3rd-party library, please provide the correct name of the method in the 'methodName' parameter.","Possible Names: "+b.join(", ")+"."].join(" "))}!function(e){(0,u.default)(e,"focus"),(0,u.default)(e,"blur")}(p)}},9903:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(1991));t.default=function(e,t){(0,o.default)(e,"click",t)}},6843:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});for(var l=i(r(8195)),u=["focus","blur","load","unload","change","reset","scroll"],f="function"==typeof Event?function(e,t){return new CustomEvent(e,t)}:function(e,t){var r=n({bubbles:!1,cancelable:!1},t),o=document.createEvent("CustomEvent");return o.initCustomEvent(e,r.bubbles,r.cancelable,null),o},c={alt:{altKey:!0,code:"AltLeft",key:"Alt",location:1,which:18},arrowdown:{code:"ArrowDown",key:"ArrowDown",location:0,which:40},arrowleft:{code:"ArrowLeft",key:"ArrowLeft",location:0,which:37},arrowright:{code:"ArrowRight",key:"ArrowRight",location:0,which:39},arrowup:{code:"ArrowUp",key:"ArrowUp",location:0,which:38},backspace:{code:"Backspace",key:"Backspace",location:0,which:8},control:{code:"ControlLeft",ctrlKey:!0,key:"Control",location:1,which:17},enter:{code:"Enter",key:"Enter",location:0,which:13},esc:{code:"Escape",key:"Escape",location:0,which:27},meta:{code:"MetaLeft",key:"Meta",location:1,metaKey:!0,which:91},shift:{code:"ShiftLeft",key:"Shift",location:1,shiftKey:!0,which:16},space:{code:"Space",key:" ",location:0,which:32},tab:{code:"Tab",key:"Tab",location:0,which:9}},d=1;d<=12;d+=1)c["f".concat(d)]={code:"F".concat(d),key:"F".concat(d),location:0,which:d+111};t.default=function(e,t,r){var i=e.indexOf("."),d=a(-1===i?[e]:[e.slice(0,Math.max(0,i)),e.slice(i+1)],2),s=d[0],v=d[1],p=f(s,n({bubbles:-1===u.indexOf(e),cancelable:!0},t));return function(e,t){var r,n,a,i,u={};try{for(var f=o(t?t.split("."):[]),d=f.next();!d.done;d=f.next()){var s=d.value,v=c[s];if(v||1!==s.length||(v={code:(a=s,void 0,i=a.codePointAt(0),i&&i>=97&&i<=122||i&&i>=65&&i<=90?"Key".concat(a.toUpperCase()):i&&i>=48&&i<=57?"Digit".concat(a):"Unknown"),key:s}),!v)throw new Error("Unknown event part ".concat(s));(0,l.default)(u,v)}}catch(e){r={error:e}}finally{try{d&&!d.done&&(n=f.return)&&n.call(f)}finally{if(r)throw r.error}}t&&(0,l.default)(e,u)}(p,v),r&&(0,l.default)(p,r),p}},1991:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(590)),a=n(r(771)),i=n(r(4792)),l=n(r(4993)),u=n(r(5687)),f=n(r(8195)),c=n(r(6843)),d=["focus","blur","load","unload","change","reset","scroll"];t.default=function(e,t,r){var n,s=(n=(0,l.default)(e)?e:(0,o.default)((0,u.default)(),e,void 0),(0,a.default)(n)||(0,i.default)(n)?n.nativeElement:(0,l.default)(n)?n:void 0);if(!s)throw new Error("Cannot trigger ".concat("string"==typeof t?t:t.type," event undefined element"));if(!s.disabled){var v=function(e){return"string"==typeof e?(0,c.default)(e,{bubbles:-1===d.indexOf(e),cancelable:!0}):e}(t);v.target||(0,f.default)(v,{target:s}),r&&(0,f.default)(v,r),s.dispatchEvent(v)}}},343:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(5974);t.default=function(e){return"function"==typeof e||(0,n.isNgDef)(e,"t")}},4212:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=r(6739),l=r(5974),u=o(r(8344)),f=o(r(590)),c=o(r(1771)),d=o(r(5687)),s=o(r(951)),v=o(r(4811)),p=o(r(343)),h={};t.default=function(){for(var e=[],t=0;t0}),!0);else try{b.push((0,a.getInjection)(g))}catch(e){if(!e||"object"!=typeof e||void 0===e.ngTempTokenPath)throw e}if(b.length>0)return b[0];if(_!==h)return _;throw new Error("Cannot find an instance via ngMocks.findInstance(".concat((0,v.default)(y),")"))}},147:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=r(6456),l=r(6739),u=r(5974),f=a(r(8344)),c=a(r(7316)),d=a(r(1771)),s=a(r(5687)),v=a(r(951)),p=a(r(343));t.default=function(){for(var e,t,r=[],a=0;a0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(4792)),i=o(r(5687)),l=function(e){return(0,a.default)(e)?l(e.debugElement):e&&e.injector&&e.query?e:void 0};t.default=function(e,t){var r,o,a,u,f=t;return 3===e.length?(a=l(e[0]),u=e[1],f=e[2]):1===e.length?(a=l((0,i.default)()),u=n(e,1)[0]):e[0]?(a=l(e[0]))?u=e[1]:(a=l((0,i.default)()),u=(r=n(e,2))[0],f=r[1]):u=e[1],[a,u=null!==(o=l(u))&&void 0!==o?o:u,f]}},654:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(1165),o=r(6739);t.default=function(e){return Array.isArray(e)?n.By.css(1===e.length?"[".concat(e[0],"]"):"[".concat(e[0],'="').concat(e[1],'"]')):"string"==typeof e?n.By.css(e):n.By.directive((0,o.getSourceOfMock)(e))}},7316:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(771)),i=o(r(7453)),l=o(r(654));t.default=function(){for(var e=[],t=0;t0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(771)),i=o(r(4811)),l=o(r(7453)),u=o(r(654)),f={};t.default=function(){for(var e=[],t=0;t\\s+<","mg"),"><").replace(new RegExp('"\\s+>',"mg"),'">'):"";return r?n:n.trim()}var o;return(0,i.default)(t)?e(function(e,t){return t?e.outerHTML:e.innerHTML}(t,r)):(0,l.default)(t)?u(e,(0,a.default)(t).replace(new RegExp("&","mg"),"&").replace(new RegExp('"',"mg"),""").replace(new RegExp("<","mg"),"<").replace(new RegExp(">","mg"),">").replace(new RegExp("'","mg"),"'"),r):void 0};t.default=(0,o.default)(u)},9512:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4858)),a=n(r(9280)),i=n(r(4993)),l=n(r(8209)),u=function(e,t,r){if("string"==typeof t||void 0===t){var n=(o=t)?o.replace(new RegExp("\\s+","mg")," "):"";return r?n:n.trim()}var o;return(0,i.default)(t)?e(function(e,t){var r,n=null!==(r=e.textContent)&&void 0!==r?r:"";return t?n:n.trim()}(t,r)):(0,l.default)(t)?u(e,(0,a.default)(t),r):void 0};t.default=(0,o.default)(u)},3341:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t;return"#text"===(null===(t=e.nativeNode)||void 0===t?void 0:t.nodeName)&&e.parent?e.parent:e}},7717:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4201)),a=r(5974);t.default=function(e,t,r){if(t.injector&&"NullInjector"!==t.injector.constructor.name){var n=function(e){for(var t=e;"NullInjector"===(null==t?void 0:t.injector.constructor.name);)t=t.parent;if(t)return t.injector}(t.parent),i=n?(0,o.default)(r,n):void 0,l=(0,o.default)(r,t.injector);i!==l&&((0,a.isNgDef)(r,"t")&&void 0!==l||void 0!==l&&-1===e.indexOf(l))&&e.push(l)}}},2631:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(3341)),a=n(r(1484)),i=function(e){for(var t,r=e,n=null===(t=r.nativeNode)||void 0===t?void 0:t.__ngContext__;void 0===n&&r.parent;)n=(r=r.parent).nativeNode.__ngContext__;if("number"!=typeof n)return n;var o=r.injector._lView;return Array.isArray(o)?function(e,t){if("object"==typeof e[1]&&e[20]===t)return e;for(var r=21;r1&&f[1]&&"object"==typeof f[1]&&f[1].bindingStartIndex&&(v=f[1].bindingStartIndex);for(var p=0;p=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3341)),i=o(r(1484)),l=function(e){var t,r;if(!e||"object"!=typeof e)return e;try{for(var o=n(["renderElement","renderText","instance"]),a=o.next();!a.done;a=o.next()){var i=a.value;if(e[i])return e[i]}}catch(e){t={error:e}}finally{try{a&&!a.done&&(r=o.return)&&r.call(o)}finally{if(t)throw t.error}}return null};t.default=function(e,t,r){if(t&&t._debugContext){var n=(0,a.default)(t);(0,i.default)({el:n,nodes:t._debugContext.view.nodes,normalize:l,proto:r,result:e},!0)}}},1771:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(5974),a=n(r(7717)),i=n(r(2631)),l=n(r(2096));t.default=function(e,t,r){return(0,a.default)(e,t,r),(0,o.isNgDef)(r,"t")||"string"==typeof r||((0,l.default)(e,t,r),(0,i.default)(e,t,r)),e}},5687:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(2603);t.default=function(){var e=(0,n.getTestBed)()._activeFixtures;return e[e.length-1]}},4317:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(8073));t.default=function(){var e;o.default.cacheDeclarations.clear(),null===(e=o.default.config.get("ngMocksDepsSkip"))||void 0===e||e.clear()}},4811:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(5974);t.default=function(e){return"string"==typeof e?e:"function"==typeof e?e.name:(0,n.isNgDef)(e,"t")?e._desc:Array.isArray(e)?e[0]:e?"":""}},951:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(771)),i=o(r(4792)),l=o(r(5687));t.default=function(e,t,r){var o,u,f,c,d,s,v=r;return 3===e.length?(c=(o=n(e,3))[0],d=o[1],v=o[2]):1===e.length?(c=(0,l.default)(),d=n(e,1)[0]):t(e[1])&&("string"==typeof(s=e[0])||Array.isArray(s)&&"string"==typeof s[0]||(0,i.default)(s)||(0,a.default)(s),1)?(c=(u=n(e,2))[0],d=u[1]):(c=(0,l.default)(),d=(f=n(e,2))[0],v=f[1]),[c,d,v]}},4641:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(4201)),a=n(r(8862)),i=n(r(6297));t.default=function(e,t){if(e)try{var r=(0,i.default)(t);return function(e){try{return(0,a.default)(e)}catch(e){return}}((0,o.default)(r,e.injector).constructor)}catch(e){return}}},5018:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(1184)),l=a(r(590)),u=a(r(5687)),f=a(r(4641)),c=a(r(8027)),d={},s=function(e,t){var r=(0,i.default)(e),n=r.name,o=r.alias,a=void 0===o?"":o;if(!a&&n===t||a&&a===t)return n};t.default=function(e,t){for(var r=[],a=2;a=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3174));t.default=function(e,t){return function(){for(var r=[],o=0;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(8073));t.default=function(e,t){var r,o,l=i.default.getConfigMock();try{for(var u=n((0,a.flatten)(e)),f=u.next();!f.done;f=u.next()){var c=f.value;t?l.set(c,t):l.delete(c)}}catch(e){r={error:e}}finally{try{f&&!f.done&&(o=u.return)&&o.call(u)}finally{if(r)throw r.error}}}},8909:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(8073));t.default=function(e,t){var r,o,l=i.default.getOverrides();try{for(var u=n((0,a.flatten)(e)),f=u.next();!f.done;f=u.next()){var c=f.value;if(t){var d=l.has(c)?l.get(c):new Set;d.add(t),l.set(c,d)}else l.delete(c)}}catch(e){r={error:e}}finally{try{f&&!f.done&&(o=u.return)&&o.call(u)}finally{if(r)throw r.error}}}},1640:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(2603),i=o(r(3174)),l=o(r(8073)),u=l.default.global.get("faster-hooks")||{after:[],before:[]};l.default.global.set("faster-hooks",u);var f=function(e,t){return function(r){var o,f;if(a.TestBed.ngMocksFasterLock)return e.call(t,r);l.default.global.set("bullet:customized",!0);var c=e;try{for(var d=n(u.before),s=d.next();!s.done;s=d.next())c=(0,s.value)(c,t)}catch(e){o={error:e}}finally{try{s&&!s.done&&(f=d.return)&&f.call(d)}finally{if(o)throw o.error}}try{return(0,i.default)(a.TestBed,"ngMocksFasterLock",!0),c.call(t,r)}finally{(0,i.default)(a.TestBed,"ngMocksFasterLock",void 0)}}},c=function(e,t){return function(){var r,o;if(a.TestBed.ngMocksFasterLock)return e.call(t);if(l.default.global.has("bullet"))return l.default.global.has("bullet:customized")&&l.default.global.set("bullet:reset",!0),t;l.default.global.delete("bullet:customized"),l.default.global.delete("bullet:reset");var f=e;try{for(var c=n(u.after),d=c.next();!d.done;d=c.next())f=(0,d.value)(f,t)}catch(e){r={error:e}}finally{try{d&&!d.done&&(o=c.return)&&o.call(c)}finally{if(r)throw r.error}}try{return(0,i.default)(a.TestBed,"ngMocksFasterLock",!0),f.call(t)}finally{(0,i.default)(a.TestBed,"ngMocksFasterLock",void 0)}}};t.default=function(){a.TestBed.ngMocksFasterInstalled||(a.TestBed.configureTestingModule=f(a.TestBed.configureTestingModule,a.TestBed),a.TestBed.resetTestingModule=c(a.TestBed.resetTestingModule,a.TestBed),(0,i.default)(a.TestBed,"ngMocksFasterInstalled",!0));var e=(0,a.getTestBed)();return e.ngMocksFasterInstalled||(e.configureTestingModule=f(e.configureTestingModule,e),e.resetTestingModule=c(e.resetTestingModule,e),(0,i.default)(e,"ngMocksFasterInstalled",!0)),u}},7346:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(2603),a=n(r(8073)),i=n(r(1640)),l=n(r(2776)),u=function(e){var t,r=null!==(t=a.default.global.get("bullet:stack"))&&void 0!==t?t:[];r.push(e),a.default.global.set("bullet:stack",r),a.default.global.set("bullet:stack:id",e)},f=function(e){var t=a.default.global.get("bullet:stack");t.splice(t.indexOf(e),1),t.length>0?a.default.global.set("bullet:stack:id",t[t.length-1]):a.default.global.delete("bullet:stack:id"),function(e){for(var t=(0,o.getTestBed)()._activeFixtures||[],r=0,n=t.length-1;n>=0;n-=1)t[n].ngMocksStackId&&t[n].ngMocksStackId!==e?r+=1:(t[n].ngMocksStackId=void 0,t[n].destroy(),t.splice(n,1));0===r&&(0,l.default)()}(e)};t.default=function(){(0,i.default)();var e={},t={};beforeAll((function(){a.default.global.has("bullet:customized")&&o.TestBed.resetTestingModule(),a.default.global.set("bullet",!0),u(e)})),beforeEach((function(){u(t)})),afterEach((function(){f(t)})),afterAll((function(){f(e),a.default.global.delete("bullet"),a.default.global.has("bullet:reset")&&o.TestBed.resetTestingModule()}))}},2776:function(e,t,r){Object.defineProperty(t,"__esModule",{value:!0});var n=r(2603);t.default=function(){var e=(0,n.getTestBed)();e._instantiated=!1,e._moduleFactory=void 0,e._testModuleRef=null}},8027:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(2603),a=n(r(2970)),i=r(6739),l=n(r(345)),u=n(r(590)),f=n(r(1771)),c=n(r(5687)),d=n(r(4811)),s={};t.default=function(){for(var e=[],t=0;t0)return _[0];if(h){var _,g=(0,l.default)(h,void 0);if(g&&"#comment"===g.nativeNode.nodeName&&(_=(0,f.default)([],g,y)).length>0)return _[0]}if(p!==s)return p;throw new Error("Cannot find ".concat((0,a.default)(v)," instance via ngMocks.get"))}},4071:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(6259)),a=n(r(8073)),i=n(r(4317)),l=function(e){a.default.getDefaults().set(e,["exclude"])};t.default=function(e,t){void 0===t&&(t=!1),(0,i.default)(),l(e),t&&(0,o.default)(e,l)}},5228:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(6259)),a=n(r(8073)),i=n(r(4317)),l=function(e){a.default.getDefaults().set(e,["keep"])};t.default=function(e,t){void 0===t&&(t=!1),(0,i.default)(),l(e),t&&(0,o.default)(e,l)}},763:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(6259)),a=n(r(8073)),i=n(r(4317)),l=function(e){a.default.getDefaults().set(e,["mock"])};t.default=function(e,t){void 0===t&&(t=!1),(0,i.default)(),l(e),t&&(0,o.default)(e,l)}},3757:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(5974),a=n(r(8073)),i=n(r(4317));t.default=function(e,t){var r=!0;if(((0,o.isNgDef)(e,"m")&&(0,o.isNgDef)(t,"m")||(0,o.isNgDef)(e,"c")&&(0,o.isNgDef)(t,"c")||(0,o.isNgDef)(e,"d")&&(0,o.isNgDef)(t,"d")||(0,o.isNgDef)(e,"p")&&(0,o.isNgDef)(t,"p"))&&(r=!1),r)throw new Error("Cannot replace the declaration, both have to be a Module, a Component, a Directive or a Pipe");(0,i.default)(),a.default.getDefaults().set(e,["replace",t])}},4102:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(6259)),a=n(r(8073)),i=n(r(4317)),l=n(r(8909)),u=function(e){a.default.getDefaults().delete(e),(0,l.default)(e)};t.default=function(e,t){void 0===t&&(t=!1),(0,i.default)(),u(e),t&&(0,o.default)(e,u)}},7418:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(5551)),l=r(6456),u=a(r(1345)),f=a(r(6297)),c=r(5974),d=r(4152),s=r(3659),v=a(r(8073)),p=r(5395),h=r(8339),y=r(3821),_=r(2937),g=a(r(2415)),b=function(e,t,r){return!!t.has(e)||(t.add(e),r.has(e))},m=function(e,t,r,n,o){var a=e.get(t)||t;(0,c.isNgDef)(a,"m")?r.push(a):(0,c.isNgDef)(a,"c")||(0,c.isNgDef)(a,"d")?n.push(a):(0,c.isNgDef)(a,"p")?(n.push(a),o.push(a)):(0,d.isNgInjectionToken)(a)||o.push(a)},M=[["m","module"],["c","component"],["d","directive"],["p","pipe"]],k=function(e,t,r,n){b(t,e.skip,e.exclude)||n.push(e.keep.has(t)?t:r(t))},w=function(e,t){var r=e.skip,n=e.keep,o=e.providers,a=e.exclude,i=(0,f.default)(t);if(r.add(i),!a.has(i)){var l=n.has(i)?t:(0,g.default)(t);l&&o.push(l)}},O={component:p.MockComponent,directive:h.MockDirective,pipe:_.MockPipe},x=function(e,t,r){if(void 0===r&&(r=!0),t){var a,i=function(e,t){var r,a;if((0,s.isNgModuleDefWithProviders)(e))return"module-with-providers";try{for(var i=n(M),l=i.next();!l.done;l=i.next()){var u=o(l.value,2),f=u[0],d=u[1];if((0,c.isNgDef)(e,f))return"m"===f&&t.has(e)?"".concat(d,"-keep"):d}}catch(e){r={error:e}}finally{try{l&&!l.done&&(a=i.return)&&a.call(i)}finally{if(r)throw r.error}}return""}(t,e.keep);if("module-with-providers"!==i){var f=e.optional.get(t);f&&f!==t&&(a=f,e.keep.add(a))}a||(a=t),function(e,t,r,o){"module-with-providers"===t?function(e,t){e.skip.has(t.ngModule)||(e.skip.add(t.ngModule),e.exclude.has(t.ngModule)||e.imports.push(e.keep.has(t.ngModule)?t:(0,y.MockModule)(t)))}(e,r):"module-keep"===t||"module"===t&&o?k(e,r,y.MockModule,e.imports):"module"===t?function(e,t,r){var o,a,i,f;if(!b(t,e.skip,e.exclude)){var c=(0,u.default)(t);try{for(var d=n((0,l.flatten)([c.declarations,c.imports])),s=d.next();!s.done;s=d.next())r(e,h=s.value)}catch(e){o={error:e}}finally{try{s&&!s.done&&(a=d.return)&&a.call(d)}finally{if(o)throw o.error}}try{for(var v=n(c.providers?(0,l.flatten)(c.providers):[]),p=v.next();!p.done;p=v.next()){var h=p.value;w(e,h)}}catch(e){i={error:e}}finally{try{p&&!p.done&&(f=v.return)&&f.call(v)}finally{if(i)throw i.error}}}}(e,r,x):O[t]?k(e,r,O[t],e.declarations):w(e,r)}(e,i,a,r)}};t.default=function(e,t,r){var o,a,u,f,c,d;void 0===t&&(t=null),void 0===r&&(r=null);var s=function(e,t,r){var o=new Set((0,l.flatten)(e||[])),a=new Set((0,l.flatten)(t||[])),i=new Set((0,l.flatten)(r||[])),u=new Map;return function(e,t,r,o){var a,i;try{for(var u=n((0,l.mapKeys)(v.default.getDefaults())),f=u.next();!f.done;f=u.next()){var c=f.value,d=v.default.getBuildDeclaration(c);e.has(c)||t.has(c)||r.has(c)||(o.set(c,d),null===d?r.add(c):void 0===d?t.add(c):c===d&&e.add(c))}}catch(e){a={error:e}}finally{try{f&&!f.done&&(i=u.return)&&i.call(u)}finally{if(a)throw a.error}}}(o,a,i,u),{declarations:[],exclude:i,imports:[],keep:o,mock:a,optional:u,providers:[],skip:new Set}}(e,t,r),p=new Map;v.default.config.set("ngMocksDepsResolution",p);try{for(var h=n((0,l.mapValues)(s.keep)),y=h.next();!y.done;y=h.next()){var _=y.value;p.set(_,"keep")}}catch(e){o={error:e}}finally{try{y&&!y.done&&(a=h.return)&&a.call(h)}finally{if(o)throw o.error}}try{for(var g=n((0,l.mapValues)(s.exclude)),b=g.next();!b.done;b=g.next())_=b.value,p.set(_,"exclude")}catch(e){u={error:e}}finally{try{b&&!b.done&&(f=g.return)&&f.call(g)}finally{if(u)throw u.error}}v.default.config.set("mockNgDefResolver",new i.default);try{for(var M=n((0,l.mapValues)(s.mock)),k=M.next();!k.done;k=M.next()){var w=k.value;p.set(w,"mock"),s.optional.has(w)||x(s,w,!1)}}catch(e){c={error:e}}finally{try{k&&!k.done&&(d=M.return)&&d.call(M)}finally{if(c)throw c.error}}var O=function(e){var t,r,o=e.keep,a=e.skip,i=e.optional,l=e.exclude,u=e.imports,f=e.declarations,c=e.providers;try{for(var d=n(o),s=d.next();!s.done;s=d.next()){var v=s.value;a.has(v)||l.has(v)||i.has(v)||m(i,v,u,f,c)}}catch(e){t={error:e}}finally{try{s&&!s.done&&(r=d.return)&&r.call(d)}finally{if(t)throw t.error}}return{declarations:f,imports:u,providers:c}}(s);return v.default.config.delete("mockNgDefResolver"),v.default.config.delete("ngMocksDepsResolution"),O}},7411:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3295)),i=o(r(8073)),l=o(r(8344)),u=o(r(8458)),f=o(r(9400)),c=o(r(2298)),d=o(r(7655)),s=o(r(9903)),v=o(r(6843)),p=o(r(1991)),h=o(r(590)),y=o(r(7316)),_=o(r(4212)),g=o(r(147)),b=o(r(8062)),m=o(r(9512)),M=o(r(3539)),k=o(r(7977)),w=o(r(9311)),O=o(r(2237)),x=o(r(8909)),j=o(r(7346)),D=o(r(2776)),S=o(r(8027)),P=o(r(4071)),C=o(r(5228)),N=o(r(763)),T=o(r(3757)),E=o(r(4102)),A=o(r(7418)),R=o(r(7411)),I=o(r(5526)),V=o(r(2448)),B=o(r(8195)),F=o(r(589)),L=o(r(3048)),K=o(r(2120)),G=o(r(1368)),q=o(r(5535)),U=["onMockBuilderMissingDependency","onMockInstanceRestoreNeed","onTestBedFlushNeed"];t.default={autoSpy:M.default,change:c.default,click:s.default,config:function(e){var t,r,o=i.default.global.get("flags");try{for(var l=n(U),u=l.next();!u.done;u=l.next()){var f=u.value;null===e[f]?o[f]=a.default[f]:void 0!==e[f]&&(o[f]=e[f])}}catch(e){t={error:e}}finally{try{u&&!u.done&&(r=l.return)&&r.call(l)}finally{if(t)throw t.error}}null===e.mockRenderCacheSize?i.default.global.delete("mockRenderCacheSize"):void 0!==e.mockRenderCacheSize&&i.default.global.set("mockRenderCacheSize",e.mockRenderCacheSize)},crawl:l.default,defaultConfig:O.default,defaultMock:x.default,event:v.default,faster:j.default,find:h.default,findAll:y.default,findInstance:_.default,findInstances:g.default,findTemplateRef:G.default,findTemplateRefs:q.default,flushTestBed:D.default,formatHtml:b.default,formatText:m.default,get:S.default,globalExclude:P.default,globalKeep:C.default,globalMock:N.default,globalReplace:T.default,globalWipe:E.default,guts:A.default,hide:L.default,ignoreOnConsole:k.default,input:R.default,output:I.default,render:K.default,reset:V.default,reveal:u.default,revealAll:f.default,stub:B.default,stubMember:F.default,throwOnConsole:w.default,touch:d.default,trigger:p.default}},5526:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=i(r(7331)),u=i(r(7794)),f=i(r(5020)),c=i(r(445));t.default=function(e,t,r){var i,d;if("string"==typeof t)return c.default.mock(e,t,r);var s=e,v=t,p=["__zone_symbol__unconfigurables"];"function"==typeof t&&(s=c.default.createClone(t),v=e,p.push.apply(p,o([],n(Object.getOwnPropertyNames(s)),!1)));var h=o(o([],n((0,l.default)(v)),!1),n((0,u.default)(v)),!1);try{for(var y=a(h),_=y.next();!_.done;_=y.next()){var g=_.value,b=-1===p.indexOf(g)?(0,f.default)(v,g):void 0;b&&Object.prototype.hasOwnProperty.call(b,"value")&&void 0===b.value||c.default.definePropertyDescriptor(s,g,b)}}catch(e){i={error:e}}finally{try{_&&!_.done&&(d=y.return)&&d.call(y)}finally{if(i)throw i.error}}return s}},6189:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.ngMocks=void 0;var o=n(r(492));t.ngMocks=o.default},845:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=r(860),l=a(r(2137)),u=function(e,t,r){return!!e&&t instanceof i.TemplateRef&&r(t)},f=function(e,t,r){var a,c;if(!(0,l.default)(e))throw new Error("Only instances of mock declarations are accepted");if(function(e,t,r){return!!e.__template&&!!e.__vcr&&t(e.__template)&&r(e.__vcr,e.__template)}(e,t,r))return!0;try{for(var d=n(function(e){var t,r,o=[];try{for(var a=n(e.__ngMocksConfig.queryScanKeys||[]),l=a.next();!l.done;l=a.next())for(var u=l.value,f=e[u],c=e["__ngMocksVcr_".concat(u)],d=f instanceof i.QueryList?f.toArray():[f],s=c instanceof i.QueryList?c.toArray():[c],v=0;v0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(8732)),i=o(r(590)),l=o(r(5687)),u=o(r(951)),f=o(r(4811)),c=o(r(2789)),d=o(r(6703)),s=o(r(7845)),v={};t.default=function(){for(var e=[],t=0;t0)return y[0];if(h!==v)return h;throw new Error("Cannot find a TemplateRef via ngMocks.findTemplateRef(".concat((0,f.default)(p),")"))}},5535:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(8732)),i=o(r(590)),l=o(r(5687)),u=o(r(951)),f=o(r(2789)),c=o(r(6703)),d=o(r(7845));t.default=function(){for(var e=[],t=0;t=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(8073)),l=a(r(589));t.default=function(e){var t,r,a=[],u=i.default.configInstance.get(e);if(null==u?void 0:u.overloads){var f=function(e,t,r){e?a.push((function(n){(0,l.default)(n,e,t,r)})):a.push(t)};try{for(var c=n(u.overloads),d=c.next();!d.done;d=c.next()){var s=o(d.value,3);f(s[0],s[1],s[2])}}catch(e){t={error:e}}finally{try{d&&!d.done&&(r=c.return)&&r.call(c)}finally{if(t)throw t.error}}}return a}},6691:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(2970)),i=o(r(8073));t.default=function(e){for(var t=[];e.length>0;){var r=n(e.pop()||[],2),o=r[0];r[1]===i.default.configInstance.get(o)&&t.push("function"==typeof o?(0,a.default)(o):o)}if(t.length>0){var l=i.default.global.get("flags"),u=["MockInstance: side effects have been detected (".concat(t.join(", "),")."),"Forgot to add MockInstance.scope() or to call MockInstance.restore()?"].join(" ");if("warn"===l.onMockInstanceRestoreNeed)console.warn(u);else if("throw"===l.onMockInstanceRestoreNeed)throw new Error(u)}}},3001:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockInstance=h,t.MockReset=function(){f.default.configInstance.clear()};var i,l=a(r(6804)),u=a(r(7592)),f=a(r(8073)),c=a(r(6691));u.default.subscribePush((function(e){i=e})),u.default.subscribePop((function(e,t){var r,a;try{for(var l=o(e.mockInstance||[]),u=l.next();!u.done;u=l.next()){var c=u.value;if(f.default.configInstance.has(c)){var d=f.default.configInstance.get(c);d.overloads.pop(),f.default.configInstance.set(c,n({},d))}}}catch(e){r={error:e}}finally{try{u&&!u.done&&(a=l.return)&&a.call(l)}finally{if(r)throw r.error}}i=t[t.length-1]}));var d=function(e){var t={};return"string"==typeof e[0]?(t.key=e[0],t.value=e[1],t.accessor=e[2]):(t.value=e[0],t.value&&"object"==typeof t.value&&(t.value=t.value.init)),t},s=[],v=!1;"undefined"!=typeof beforeEach&&(beforeEach((function(){return v=!0})),beforeEach((function(){return(0,c.default)(s)})),afterEach((function(){return v=!1})));var p=function(e,t,r,o){var a,l=f.default.configInstance.has(e)?f.default.configInstance.get(e):{},u=l.overloads||[];u.push([t,r,o]),l.overloads=u,f.default.configInstance.set(e,n({},l));var c=null!==(a=i.mockInstance)&&void 0!==a?a:[];return c.push(e),i.mockInstance=c,v&&s.push([e,f.default.configInstance.get(e),i]),r};function h(e){for(var t=[],r=1;r0){var o=d(t),a=o.key,u=o.value,c=o.accessor;return p(e,a,u,c)}var v=f.default.configInstance.get(e)||{};f.default.configInstance.set(e,n(n({},v),{overloads:[]}));for(var h=s.length-1;h>=0;h-=1)s[h][0]===e&&s[h][2]===i&&s.splice(h,1)}!function(e){e.remember=function(){u.default.stackPush()},e.restore=function(){u.default.stackPop()},e.scope=function(t){void 0===t&&(t="case"),"all"!==t&&"suite"!==t||(beforeAll(e.remember),afterAll(e.restore)),"all"!==t&&"case"!==t||(beforeEach(e.remember),afterEach(e.restore))}}(h||(t.MockInstance=h={}))},9988:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(6297)),l=r(5974),u=r(3659),f=a(r(8073)),c=r(5395),d=r(8339),s=r(2937),v=a(r(445)),p=r(3821),h=[["c",c.MockComponent],["d",d.MockDirective],["p",s.MockPipe]];t.default=function(e,t){var r=function(e,t){return function(r){var a;if(e.has(r))return function(e,t,r){var n=t.get(e);return e!==n&&r(),n}(r,e,t);var c=(0,i.default)(r);if(f.default.isExcludedDef(c))return function(e,t,r){t.set(e,void 0),r()}(r,e,t);f.default.touches.add(c);var d=function(e){var t,r;if((0,l.isNgDef)(e,"m")||(0,u.isNgModuleDefWithProviders)(e))return(0,p.MockModule)(e);if(f.default.hasBuildDeclaration(e))return f.default.getBuildDeclaration(e);if(f.default.flags.has("skipMock")&&"mock"!==f.default.getResolution(e))return e;try{for(var a=n(h),i=a.next();!i.done;i=a.next()){var c=o(i.value,2),d=c[0],s=c[1];if((0,l.isNgDef)(e,d))return s(e)}}catch(e){t={error:e}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}}(r);return function(e,t){return(0,u.isNgModuleDefWithProviders)(t)&&(0,u.isNgModuleDefWithProviders)(e)}(r,d)&&e.set(r.ngModule,d.ngModule),f.default.flags.has("skipMock")&&(null===(a=f.default.config.get("ngMocksDepsSkip"))||void 0===a||a.add(d)),e.set(r,d),t(d!==r),d}}(t,e),a=function(e,t){return function(r){return v.default.resolveProvider(r,e,t)}}(t,e);return{resolve:r,resolveProvider:a}}},6860:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(6456),i=o(r(6297)),l=o(r(7610));t.default=function(e){var t,r;try{for(var o=n((0,a.flatten)(null!=e?e:[])),u=o.next();!u.done;u=o.next()){var f=u.value,c=(0,i.default)(f);(0,l.default)(c)}}catch(e){t={error:e}}finally{try{u&&!u.done&&(r=o.return)&&r.call(o)}finally{if(t)throw t.error}}}},3821:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockModule=function(e){var t;(0,v.default)(e,"MockModule");var r=w(e),n=r.ngModule,o=r.ngModuleProviders,a=M(n);try{var i=x(n,O(n,a.isRootModule));g.default.flags.has("cacheModule")&&g.default.cacheDeclarations.set(n,i),g.default.flags.has("skipMock")&&(null===(t=g.default.config.get("ngMocksDepsSkip"))||void 0===t||t.add(i));var l=j(o);return D(e,n,o,i,l)}finally{k(a)}};var i=r(860),l=a(r(3295)),u=a(r(3174)),f=r(6456),c=a(r(1345)),d=a(r(615)),s=a(r(2970)),v=a(r(6804)),p=r(6763),h=r(5974),y=r(3659),_=r(1946),g=a(r(8073)),b=a(r(5937)),m=a(r(224)),M=function(e){var t=!1,r=!0;g.default.flags.has("hasRootModule")?r=!1:g.default.flags.add("hasRootModule");var n=g.default.getResolution(e);return function(e){return"mock"===e&&g.default.flags.has("skipMock")}(n)&&(t=!0,g.default.flags.delete("skipMock")),function(e){return-1!==l.default.neverMockModule.indexOf((0,s.default)(e))&&!g.default.flags.has("skipMock")}(e)&&(t=!0,g.default.flags.add("skipMock")),r||!function(e){return"keep"===e&&!g.default.flags.has("skipMock")}(n)&&!function(e){return"replace"===e&&!g.default.flags.has("skipMock")}(n)||(t=!0,g.default.flags.add("skipMock")),{isRootModule:r,toggleSkipMockFlag:t}},k=function(e){var t=e.isRootModule,r=e.toggleSkipMockFlag;r&&g.default.flags.has("skipMock")?g.default.flags.delete("skipMock"):r&&!g.default.flags.has("skipMock")&&g.default.flags.add("skipMock"),t&&g.default.flags.delete("hasRootModule")},w=function(e){var t,r;return(0,y.isNgModuleDefWithProviders)(e)?(t=e.ngModule,e.providers&&(r=e.providers)):t=e,{ngModule:t,ngModuleProviders:r}},O=function(e,t){var r;if((0,p.isMockNgDef)(e,"m"))return e;if(g.default.flags.has("cacheModule")&&g.default.cacheDeclarations.has(e))return(0,b.default)(e);if(!t&&"mock"!==(null===(r=g.default.config.get("ngMocksDepsResolution"))||void 0===r?void 0:r.get(e))&&g.default.hasBuildDeclaration(e)){var n=g.default.getBuildDeclaration(e);if((0,h.isNgDef)(n,"m")&&n!==e)return n}},x=function(e,t){var r=o(t?[!1]:(0,m.default)((0,c.default)(e),e),3),n=r[0],a=r[1],l=r[2];if(l&&(0,u.default)(e,"__ngMocksResolutions",l),n){var s=g.default.flags.has("skipMock")?e:_.Mock,v=(0,f.extendClass)(s);return(0,i.NgModule)(a)(v),(0,d.default)(v,e),v}return t||e},j=function(e){if(e){var t=o((0,m.default)({providers:e,skipExports:!0}),2),r=t[0],n=t[1];return r?n.providers:e}},D=function(e,t,r,o,a){return o===t&&a===r?e:(0,y.isNgModuleDefWithProviders)(e)?n({ngModule:o},a?{providers:a}:{}):o}},224:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=i(r(5551)),u=r(6456),f=i(r(6297)),c=i(r(8073)),d=i(r(7610)),s=i(r(9988)),v=i(r(6860)),p=function(e,t){return(0,u.flatten)(e).map(t).filter((function(e){return!!e}))},h=function(e,t,r,o){var a=c.default.config.get(o)||{},i=(0,f.default)(e),l=t(i);if(l){var u=c.default.config.get(i);if((null==u?void 0:u.export)&&o&&!a.export&&c.default.config.set(o,n(n({},a),{export:!0})),!r||a.exportAll||(null==u?void 0:u.export))return(0,d.default)(i,o),l}},y=function(e,t){return!e||!!t.exports&&-1!==t.exports.indexOf(e)};t.default=function(e,t){var r,i,_=c.default.config.has("mockNgDefResolver");_||c.default.config.set("mockNgDefResolver",new l.default),c.default.config.get("mockNgDefResolver").push();var g=!c.default.flags.has("skipMock"),b=function(e){void 0===e&&(e=!0),g=g||e},m=(0,s.default)(b,c.default.config.get("mockNgDefResolver")),M=m.resolve,k=function(e,t,r){var i,l,u,d={},s=function(e,t){return[["declarations",e],["hostDirectives",function(t){var r=(0,f.default)(t),o=e(r);return o===r?t:t==r?o:n(n({},t),{directive:o})}],["imports",e],["entryComponents",e],["bootstrap",e],["providers",t],["viewProviders",t],["exports",e],["schemas",function(e){return e}]]}(t,r),h=c.default.flags.has("cachePipe");h||c.default.flags.add("cachePipe");try{for(var y=o(s),_=y.next();!_.done;_=y.next()){var g=a(_.value,2),b=g[0],m=g[1];(null===(u=e[b])||void 0===u?void 0:u.length)&&(d[b]=p(e[b],m))}}catch(e){i={error:e}}finally{try{_&&!_.done&&(l=y.return)&&l.call(y)}finally{if(i)throw i.error}}return e.skipMarkProviders||((0,v.default)(d.providers),(0,v.default)(d.viewProviders)),h||c.default.flags.delete("cachePipe"),d}(e,M,m.resolveProvider);e.skipExports||function(e,t,r,n,a){var i,l,f=c.default.flags.has("skipMock")||c.default.flags.has("correctModuleExports");try{for(var d=o((0,u.flatten)([r.imports||[],r.declarations||[]])),s=d.next();!s.done;s=d.next()){var v=s.value,p=h(v,e,f,a);y(p,n)||(t(),n.exports=n.exports||[],n.exports.push(p))}}catch(e){i={error:e}}finally{try{s&&!s.done&&(l=d.return)&&l.call(d)}finally{if(i)throw i.error}}}(M,b,e,k,t);try{for(var w=o(t&&k.exports?(0,u.flatten)(k.exports):[]),O=w.next();!O.done;O=w.next()){var x=O.value;(0,d.default)(x,t)}}catch(e){r={error:e}}finally{try{O&&!O.done&&(i=w.return)&&i.call(w)}finally{if(r)throw r.error}}var j=c.default.config.get("mockNgDefResolver").pop();return _||c.default.config.delete("mockNgDefResolver"),[g,k,j]}},3877:function(e,t){Object.defineProperty(t,"__esModule",{value:!0})},2937:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockPipes=function(){for(var e=[],t=0;t=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(8773)),i=o(r(1184)),l=r(5974),u=function(e,t){var r=" ".concat(function(e,t){return"i"===t?"[".concat(e,"]"):"(".concat(e,")")}(e,t),'="');return(r+="i"===t?e:"__ngMocksOutput('".concat(e,"', $event)"))+'"'},f=function(e,t,r){var o,a;if(!e&&"o"===r)return"";var l="",f=null!=e?e:t;try{for(var c=n(t),d=c.next();!d.done;d=c.next()){var s=d.value,v=(0,i.default)(s),p=v.name,h=v.alias;l+=-1===f.indexOf(h||p)?"":u(h||p,r)}}catch(e){o={error:e}}finally{try{d&&!d.done&&(a=c.return)&&a.call(c)}finally{if(o)throw o.error}}return l};t.default=function(e,t){var r=t.selector,n=t.bindings,o=t.inputs,i=t.outputs,u="";return"string"==typeof e?u=e:(0,l.isNgDef)(e,"p")&&n&&-1!==n.indexOf("$implicit")?u="{{ $implicit | ".concat((0,a.default)(e).name," }}"):r&&(u+="<".concat(r),u+=f(n,o,"i"),u+=f(n,i,"o"),u+=">")),u}},2091:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=i(r(3174)),u=i(r(5006)),f=i(r(445)),c=function(e,t,r){var n=function(){if("function"==typeof r[e]){if(t["__ngMocks_".concat(e,"__origin")]!==r[e]){var n=f.default.createClone(r[e],t,r);(0,l.default)(t,"__ngMocks_".concat(e),n),(0,l.default)(t,"__ngMocks_".concat(e,"__origin"),r[e])}return t["__ngMocks_".concat(e)]}return r[e]};return(0,l.default)(n,"__ngMocksProxy",!0),n},d=function(e,t,r){var n=function(n){t["__ngMocks_".concat(e)]&&(t["__ngMocks_".concat(e)]=void 0),t["__ngMocks_".concat(e,"__origin")]&&(t["__ngMocks_".concat(e,"__origin")]=void 0),r[e]=n};return(0,l.default)(n,"__ngMocksProxy",!0),n};t.default=function(e,t,r,i){var s,v;if(void 0===i&&(i=!1),t){(0,l.default)(e,"__ngMocks__source",t);var p,h=(p=e,o(o([],n(Object.getOwnPropertyNames(p)),!1),n(Object.keys(p)),!1)),y=o(o([],n(function(e){return o(o(o([],n(f.default.extractPropertiesFromPrototype(Object.getPrototypeOf(e))),!1),n(f.default.extractMethodsFromPrototype(Object.getPrototypeOf(e))),!1),n(Object.keys(e)),!1)}(t)),!1),n(r),!1);try{for(var _=a(y),g=_.next();!g.done;g=_.next()){var b=g.value;(i||-1===h.indexOf(b))&&((0,u.default)(e,b,{get:c(b,e,t),set:d(b,e,t)}),h.push(b))}}catch(e){s={error:e}}finally{try{g&&!g.done&&(v=_.return)&&v.call(_)}finally{if(s)throw s.error}}}}},6086:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},l=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var u=r(860),f=r(2603),c=l(r(3174)),d=r(6456),s=l(r(8862)),v=r(5974);t.default=function(e){var t,r,l;if(!(0,v.isNgDef)(e,"c")&&!(0,v.isNgDef)(e,"d"))return{};var p=(0,s.default)(e),h={};try{for(var y=i(Object.keys(p)),_=y.next();!_.done;_=y.next()){var g=_.value;"standalone"!==g?h[g]=p[g]:(0,c.default)(h,"__ngMocksStandalone",!!p[g])}}catch(e){t={error:e}}finally{try{_&&!_.done&&(r=y.return)&&r.call(y)}finally{if(t)throw t.error}}return h.selector&&/[\s,[\]]/.test(h.selector)&&(h.selector=""),h.selector||(h.selector=(null===(l=f.TestBed.ngMocksSelectors)||void 0===l?void 0:l.get(e))||"",h.selector||(h.selector="ng-mocks-".concat(e.name),function(e,t){var r,i=(0,d.extendClass)(e),l={provide:e,useExisting:i};t.providers=a(a([],o(t.providers||[]),!1),[l],!1);var c={};try{var s=f.TestBed.ngMocksOverrides.get(e).override;(c=n({},s.set)).providers=c.providers?a(a([],o(c.providers),!1),[l],!1):t.providers}catch(e){}var p=!0===t.__ngMocksStandalone;((0,v.isNgDef)(e,"c")?u.Component:u.Directive)(n(n(n({},t),c),p?{standalone:p}:{}))(i),f.TestBed.configureTestingModule(((r={})[p?"imports":"declarations"]=[i],r))}(e,h),f.TestBed.ngMocksSelectors&&f.TestBed.ngMocksSelectors.set(e,h.selector))),h}},8406:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockRenderFactory=function(e,t,r){void 0===r&&(r={}),(0,f.default)(e,"MockRender");var n="string"==typeof e||(0,c.isNgDef)(e,"t")?{}:(0,g.default)(e),o=(0,y.default)(e,n,t,r),a=m(o,t,e,r);return"root"!==d.default.current().level&&!1!==r.configureTestBed&&a.configureTestBed(),a};var o=r(860),a=r(2603),i=n(r(3174)),l=r(6456),u=n(r(2970)),f=n(r(6804)),c=r(5974),d=n(r(7592)),s=n(r(8073)),v=r(6189),p=n(r(5006)),h=r(5779),y=n(r(3078)),_=n(r(2091)),g=n(r(6086)),b=["Forgot to flush TestBed?","MockRender cannot be used without a reset after TestBed.get / TestBed.inject / TestBed.createComponent and another MockRender in the same test.","If you want to mock a service before rendering, consider usage of MockRenderFactory or MockInstance.","To flush TestBed, add a call of ngMocks.flushTestBed() before the call of MockRender, or pass `reset: true` to MockRender options."].join(" "),m=function(e,t,r,n){var f=function(n,d){f.configureTestBed();var y=a.TestBed.createComponent(e);return(0,_.default)(y.componentInstance,null!=n?n:{},null!=t?t:[]),(0,i.default)(y,"ngMocksStackId",s.default.global.get("bullet:stack:id")),(void 0===d||d)&&y.detectChanges(),"string"==typeof r||(0,c.isNgDef)(r,"c")||(0,c.isNgDef)(r,"d")||e.tpl&&(0,c.isNgDef)(r,"p")?function(e,t,r){e.point=e.debugElement.children[0]&&"#text"!==e.debugElement.children[0].nativeElement.nodeName&&"#comment"!==e.debugElement.children[0].nativeElement.nodeName?e.debugElement.children[0]:e.debugElement,(0,c.isNgDef)(t,"d")?(0,p.default)(e.point,"componentInstance",{get:function(){return v.ngMocks.get(e.point,t)}}):(0,c.isNgDef)(t,"p")&&(0,p.default)(e.point,"componentInstance",{get:function(){return v.ngMocks.findInstance(e.point,t)}}),function(e,t){if(e)try{t()}catch(e){}}(!r,(function(){return(0,_.default)(e.componentInstance,e.point.componentInstance,[])}))}(y,r,n):function(e,t,r){var n;try{n=(0,l.getInjection)(t)}catch(e){if((0,c.isNgDef)(t,"p"))throw new Error(["Cannot render ".concat((0,u.default)(t),"."),"Did you forget to set $implicit param, or add the pipe to providers?","https://ng-mocks.sudo.eu/guides/pipe"].join(" "));throw e}r&&v.ngMocks.stub(n,r),e.point=(0,h.MockService)(o.DebugElement,{childNodes:[],children:[],componentInstance:n,nativeElement:(0,h.MockService)(HTMLElement)}),(0,_.default)(e.componentInstance,e.point.componentInstance,[],!0)}(y,r,n),y};return f.declaration=e,f.bindings=t,f.configureTestBed=function(e,t){return function(){var r,n=(0,a.getTestBed)(),o=(null===(r=n._compiler)||void 0===r?void 0:r.declarations)||n.declarations||n._declarations;if(!o||-1===o.indexOf(e)){!function(e){var t=s.default.global.get("flags"),r=(0,a.getTestBed)();e.reset||!r._instantiated&&!r._testModuleRef?v.ngMocks.flushTestBed():"throw"!==t.onTestBedFlushNeed&&(r._instantiated||r._testModuleRef)&&("warn"===t.onTestBedFlushNeed&&console.warn(b),v.ngMocks.flushTestBed())}(t);try{var l=[];e.providers&&l.push(e.providers),l.push(e),a.TestBed.configureTestingModule({declarations:l})}catch(e){!function(e){var t=new Error(b);throw(0,i.default)(t,"parent",e),t}(e)}}}}(e,n),f}},1661:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0)return!0;var n=e.codePointAt(0);if(n&&n>=65&&n<=90&&null!==t.match(/\bthis\./gm))return!0;var o=new RegExp("\\(this,\\s*".concat(e,"\\)"),"mg");return null!==t.match(o)}(r[1],t,e)}},402:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return null!==e&&"object"==typeof e&&"InjectionToken"!==e.ngMetadataName&&"object"==typeof Object.getPrototypeOf(e)}},1365:function(e,t,r){var n=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},o=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=i(r(5006)),u=i(r(7331)),f=i(r(7794)),c=i(r(5020));t.default=function(e,t,r,i){var d,s,v=function(){for(var n=[],o=0;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(3174)),i=o(r(2970)),l=o(r(445));t.default=function(e){var t,r,o,u,f=(0,i.default)(e),c={};(0,a.default)(c,"__ngMocks",!0);var d=l.default.extractMethodsFromPrototype(e);try{for(var s=n(d),v=s.next();!v.done;v=s.next()){var p=v.value;l.default.mock(c,p,f)}}catch(e){t={error:e}}finally{try{v&&!v.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}var h=l.default.extractPropertiesFromPrototype(e);try{for(var y=n(h),_=y.next();!_.done;_=y.next()){var g=_.value;l.default.mock(c,g,"get",f),l.default.mock(c,g,"set",f)}}catch(e){o={error:e}}finally{try{_&&!_.done&&(u=y.return)&&u.call(y)}finally{if(o)throw o.error}}return Object.setPrototypeOf(c,e),c}},5006:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(2970)),i=["sanitize","bypassSecurityTrustHtml","bypassSecurityTrustStyle","bypassSecurityTrustScript","bypassSecurityTrustUrl","bypassSecurityTrustResourceUrl"],l={DomSanitizer:i,Sanitizer:i},u=function(e){var t,r,o,i=Object.getOwnPropertyNames(e);try{for(var u=n(null!==(o=l[(0,a.default)(e)])&&void 0!==o?o:[]),f=u.next();!f.done;f=u.next()){var c=f.value;i.push(c)}}catch(e){t={error:e}}finally{try{f&&!f.done&&(r=u.return)&&r.call(u)}finally{if(t)throw t.error}}return i};t.default=function(e){for(var t,r,o=[],a=e;a&&null!==Object.getPrototypeOf(a);){try{for(var i=(t=void 0,n(u(a))),l=i.next();!l.done;l=i.next()){var f=l.value;if("constructor"!==f){var c=Object.getOwnPropertyDescriptor(a,f);c&&(c.get||c.set)||-1!==o.indexOf(f)||o.push(f)}}}catch(e){t={error:e}}finally{try{l&&!l.done&&(r=i.return)&&r.call(i)}finally{if(t)throw t.error}}a=Object.getPrototypeOf(a)}return o}},7794:function(e,t){var r=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")};Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){for(var t,n,o=[],a=e;a&&null!==Object.getPrototypeOf(a);){try{for(var i=(t=void 0,r(Object.getOwnPropertyNames(a))),l=i.next();!l.done;l=i.next()){var u=l.value;if("constructor"!==u){var f=Object.getOwnPropertyDescriptor(a,u);f&&(f.get||f.set)&&-1===o.indexOf(u)&&o.push(u)}}}catch(e){t={error:e}}finally{try{l&&!l.done&&(n=i.return)&&n.call(i)}finally{if(t)throw t.error}}a=Object.getPrototypeOf(a)}return o}},5020:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){for(var r=e;r&&null!==Object.getPrototypeOf(r);){var n=Object.getOwnPropertyDescriptor(r,t);if(n)return n;r=Object.getPrototypeOf(r)}}},8536:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=n(r(3174)),a=function(e,t){void 0===t&&(t=!1);var r,n,i=a.customMockFunction&&!t?a.customMockFunction(e):function(e){return n&&n(e),r};return(0,o.default)(i,"__ngMocks",!0),(0,o.default)(i,"__ngMocksSet",(function(e){return n=e})),(0,o.default)(i,"__ngMocksGet",(function(e){return r=e})),i};t.default=a},445:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.registerMockFunction=function(e){(0,o.default)().ngMockshelperMockService.registerMockFunction(e)};var o=n(r(1102)),a=n(r(1365)),i=n(r(3886)),l=n(r(5006)),u=n(r(7331)),f=n(r(7794)),c=n(r(5020)),d=n(r(4235)),s=n(r(8536)),v=n(r(2004)),p=n(r(3663)),h=n(r(9465));(0,o.default)().ngMockshelperMockService=(0,o.default)().ngMockshelperMockService||{mockFunction:s.default,registerMockFunction:function(e){(0,o.default)().ngMockshelperMockService.mockFunction.customMockFunction=e},createClone:a.default,createMockFromPrototype:i.default,definePropertyDescriptor:l.default,extractMethodsFromPrototype:u.default,extractPropertiesFromPrototype:f.default,extractPropertyDescriptor:c.default,mock:d.default,replaceWithMocks:v.default,resolveProvider:p.default,useFactory:h.default},t.default=(0,o.default)().ngMockshelperMockService},4235:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0&&"get"!==e[0]&&"set"!==e[0]?r=e[0]:e.length>0&&("get"===e[0]||"set"===e[0])&&(t=e[0],r=e[1]),{accessType:t,mockName:r}}(r),u=l.accessType,f=l.mockName,c=Object.getOwnPropertyDescriptor(e,t);if(c&&c[u||"value"])return c[u||"value"];var d=function(e,t,r,n){return"".concat(null!=t?t:"function"==typeof r.prototype?r.prototype.name:(0,a.default)(r),".").concat(e).concat(null!=n?n:"")}(t,f,e,u),s=i.default.mockFunction(d,!!u),v=function(e,t,r){var o;return n(n(n(n({},"get"===r&&e&&e.set?{set:e.set}:{}),"set"===r&&e&&e.get?{get:e.get}:{}),r?{}:{writable:!0}),((o={})[r||"value"]=t,o.configurable=!0,o.enumerable=!0,o))}(c,s,u);return v.get&&v.set&&v.get.__ngMocks&&v.set.__ngMocks&&v.set.__ngMocksSet((function(e){return v.get.__ngMocksGet(e)})),Object.defineProperty(e,t,v),s}},2004:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=r(1763),u=r(5974),f=i(r(8073)),c=["canActivate","canActivateChild","canDeactivate","canMatch","canLoad"],d=function(e,t){return Array.isArray(e[t])?function(e){var t,r,n=[];try{for(var a=o(e),i=a.next();!i.done;i=a.next()){var c=i.value;!f.default.isProvidedDef(c)&&f.default.isExcludedDef(l.NG_MOCKS_GUARDS)||(n.push(c),(0,u.isNgDef)(c)||f.default.touches.add(c))}}catch(e){t={error:e}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}return n}(e[t]):e[t]},s=function(e,t){var r,i,v;if(f.default.cacheDeclarations.has(e))return f.default.cacheDeclarations.get(e);if("object"!=typeof e)return e;if(t.has(e))return e;var p=!1;return Array.isArray(e)?(r=a(function(e,t,r){var n,a,i=[],l=!1;e.set(t,i);try{for(var u=o(t),c=u.next();!c.done;c=u.next()){var d=c.value;f.default.isExcludedDef(d)?l=l||!0:(i.push(r(d,e)),l=l||i[i.length-1]!==d)}}catch(e){n={error:e}}finally{try{c&&!c.done&&(a=u.return)&&a.call(u)}finally{if(n)throw n.error}}return[l,i]}(t,e,s),2),p=r[0],v=r[1]):e&&(i=a(function(e,t,r){var a,i,s,v,p,h,y,_={},g=!1;e.set(t,_);try{for(var b=o(Object.keys(t)),m=b.next();!m.done;m=b.next()){var M=m.value;f.default.isExcludedDef(t[M])?g=g||!0:(_[M]=r(t[M],e),g=g||_[M]!==t[M])}}catch(e){a={error:e}}finally{try{m&&!m.done&&(i=b.return)&&i.call(b)}finally{if(a)throw a.error}}try{for(var k=o(c),w=k.next();!w.done;w=k.next()){var O=w.value,x=d(_,O);x&&_[O].length!==x.length&&(g=g||!0,_=n(n({},_),((p={})[O]=x,p)))}}catch(e){s={error:e}}finally{try{w&&!w.done&&(v=k.return)&&v.call(k)}finally{if(s)throw s.error}}if("object"==typeof _.resolve&&_.resolve){var j={},D=!1;try{for(var S=o(Object.keys(_.resolve)),P=S.next();!P.done;P=S.next()){M=P.value;var C=_.resolve[M];f.default.isProvidedDef(C)||!f.default.isExcludedDef(l.NG_MOCKS_RESOLVERS)?(j[M]=C,(0,u.isNgDef)(C)||f.default.touches.add(C)):D=D||!0}}catch(e){h={error:e}}finally{try{P&&!P.done&&(y=S.return)&&y.call(S)}finally{if(h)throw h.error}}D&&(g=g||!0,_=n(n({},_),{resolve:j}))}return[g,_]}(t,e,s),2),p=i[0],v=i[1]),p?(Object.setPrototypeOf(v,Object.getPrototypeOf(e)),v):e};t.default=function(e){var t=new Map,r=s(e,t);return t.clear(),r}},3663:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=r(6456),l=r(1763),u=a(r(7285)),f=a(r(6297)),c=r(4152),d=a(r(8073)),s=a(r(445)),v=a(r(2415)),p=function(e,t,r){var n=!1,a=!e;return t&&e&&!a&&(a=function(e,t){for(var r,n,a=[],i=2;i=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=a(r(3295)),l=a(r(6297)),u=r(4152),f=a(r(8073)),c=a(r(5006)),d=a(r(5020)),s=a(r(9465)),v=r(5779),p=i.default.neverMockProvidedFunction,h=i.default.neverMockToken,y=[[function(e){return"boolean"==typeof e},!1],[function(e){return"number"==typeof e},0],[function(e){return"string"==typeof e},""],[function(e){return null===e},null]],_=function(e,t,r){var a,i;return t===e?r?(0,s.default)(e,(function(){})):void 0:e.multi?void(null===(a=f.default.config.get("ngMocksMulti"))||void 0===a||a.add(t)):(-1!==Object.keys(e).indexOf("useValue")?i=function(e,t){return(0,s.default)(t,(function(){return e.useValue&&"object"==typeof e.useValue?(0,v.MockService)(e.useValue):function(e){var t,r;try{for(var a=n(y),i=a.next();!i.done;i=a.next()){var l=o(i.value,2),u=l[0],f=l[1];if(u(e))return f}}catch(e){t={error:e}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}}(e.useValue)}))}(e,t):-1!==Object.keys(e).indexOf("useExisting")?i=e:-1!==Object.keys(e).indexOf("useClass")?i=function(e,t){return f.default.builtProviders.has(e.useClass)&&f.default.builtProviders.get(e.useClass)===e.useClass?e:(0,s.default)(t,(function(){return(0,v.MockService)(e.useClass)}))}(e,t):-1!==Object.keys(e).indexOf("useFactory")&&(i=(0,s.default)(t,(function(){return{}}))),i)};t.default=function(e,t){void 0===t&&(t=!1);var r=(0,l.default)(e);if("mock"===f.default.getResolution(r));else{if(function(e){return"function"==typeof e&&-1!==p.indexOf(e.name)}(r))return e;if(function(e){return(0,u.isNgInjectionToken)(e)&&-1!==h.indexOf(e.toString())}(r))return}var o=f.default.flags.has("cacheProvider")?f.default.cacheProviders:void 0;return r===e&&o&&o.has(r)?o.get(r):function(e,t,r){var o;return"function"==typeof t&&(o=function(e,t){return(0,s.default)(t,(function(){var r=(0,v.MockService)(t);return t!==e&&-1!==Object.keys(e).indexOf("useClass")&&function(e,t){var r,o,a=Object.getOwnPropertyNames(e),i=(0,v.MockService)(t);try{for(var l=n(Object.getOwnPropertyNames(i)),u=l.next();!u.done;u=l.next()){var f=u.value;if(-1===a.indexOf(f)){var s=(0,d.default)(i,f);(0,c.default)(e,f,s)}}}catch(e){r={error:e}}finally{try{u&&!u.done&&(o=l.return)&&o.call(l)}finally{if(r)throw r.error}}}(r,e.useClass),r}))}(e,t)),t===e&&o&&r&&r.set(t,o),o}(e,r,o)||_(e,r,t)}},5779:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.MockService=function(e){for(var t=[],r=1;r0&&"string"==typeof t[0]?t[0]:t[1],o=t.length>0&&t[0]&&"object"==typeof t[0]?t[0]:void 0,a=new Map,i=v(a,e,n,o);return a.clear(),i};var i=a(r(2970)),l=a(r(8195)),u=a(r(96)),f=a(r(2956)),c=a(r(402)),d=a(r(445)),s=[[u.default,function(e,t){var r=d.default.createMockFromPrototype(t.prototype);return e.set(t,r),r}],[f.default,function(e,t,r){var n=d.default.mockFunction("func:".concat(r||(0,i.default)(t)));return e.set(t,n()),n}],[function(e){return Array.isArray(e)},function(){return[]}],[c.default,function(e,t,r,o){var a,i,l=d.default.createMockFromPrototype(t.constructor.prototype);e.set(t,l);try{for(var u=n(Object.keys(t)),f=u.next();!f.done;f=u.next()){var c=f.value,s=o(e,t[c],"".concat(r||"instance",".").concat(c));void 0!==s&&(l[c]=s)}}catch(e){a={error:e}}finally{try{f&&!f.done&&(i=u.return)&&i.call(u)}finally{if(a)throw a.error}}return Object.setPrototypeOf(l,Object.getPrototypeOf(t)),l}]],v=function(e,t,r,a){void 0===r&&(r="");var i=function(e,t,r,a){var i,l,u;try{for(var f=n(s),c=f.next();!c.done;c=f.next()){var d=o(c.value,2),v=d[0],p=d[1];if(v(t))return null!==(u=e.get(t))&&void 0!==u?u:p(e,t,r,a)}}catch(e){i={error:e}}finally{try{c&&!c.done&&(l=f.return)&&l.call(f)}finally{if(i)throw i.error}}}(e,t,r,v);return a&&(0,l.default)(i,a),i}},534:function(e,t){Object.defineProperty(t,"__esModule",{value:!0})},9715:function(e,t,r){var n=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=o(r(2023)),i=r(6456),l=o(r(7285)),u=o(r(6297)),f=r(1433),c=o(r(445)),d=o(r(7112)),s=o(r(3309)),v=function(e,t,r,n){var o=function(e,t){var r=(0,u.default)(t);return a.default.NG_VALIDATORS&&r===a.default.NG_VALIDATORS?(0,s.default)(r,(function(){return new f.MockValidatorProxy(e)})):a.default.NG_ASYNC_VALIDATORS&&r===a.default.NG_ASYNC_VALIDATORS?(0,s.default)(r,(function(){return new f.MockAsyncValidatorProxy(e)})):a.default.NG_VALUE_ACCESSOR&&r===a.default.NG_VALUE_ACCESSOR?(0,s.default)(r,(function(){return new f.MockControlValueAccessorProxy(e)})):void 0}(t,r);if(o)return o;var i=function(e,t,r){var n=(0,u.default)(r);if(n!==a.default.NgControl&&n!==a.default.FormControlDirective)return r!==n&&(0,l.default)(r.useExisting)===e?(0,d.default)(n,t):void 0}(e,t,r);return i||c.default.resolveProvider(r,n)};t.default=function(e,t,r,o){var l,f,c,d=[];try{for(var s=n((0,i.flatten)(r||[])),p=s.next();!p.done;p=s.next()){var h=p.value;(0,u.default)(h)===a.default.NG_VALUE_ACCESSOR&&(c=!1);var y=v(e,t,h,o);y&&d.push(y)}}catch(e){l={error:e}}finally{try{p&&!p.done&&(f=s.return)&&f.call(s)}finally{if(l)throw l.error}}return{providers:d,setControlValueAccessor:c}}},6847:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},a=this&&this.__values||function(e){var t="function"==typeof Symbol&&Symbol.iterator,r=t&&e[t],n=0;if(r)return r.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var l=i(r(5551)),u=i(r(5756)),f=i(r(615)),c=i(r(5555)),d=i(r(8385)),s=i(r(8073)),v=i(r(224)),p=i(r(445)),h=i(r(9715)),y=i(r(7112));t.default=function(e,t,r,i){var _,g,b,m,M=s.default.config.has("mockNgDefResolver");M||s.default.config.set("mockNgDefResolver",new l.default);var k=n({},i);if(void 0!==r.exportAs&&(k.exportAs=r.exportAs),void 0!==r.selector&&(k.selector=r.selector),void 0!==r.standalone&&(k.standalone=r.standalone),r.standalone&&r.imports){var w=o((0,v.default)({imports:r.imports,skipExports:!0}),2)[1].imports;(null==w?void 0:w.length)&&(k.imports=w)}if(r.hostDirectives){var O=o((0,v.default)({hostDirectives:r.hostDirectives,skipExports:!0}),2)[1].hostDirectives;(null==O?void 0:O.length)&&(k.hostDirectives=O)}var x=(0,h.default)(e,t,r.providers||[],s.default.config.get("mockNgDefResolver")),j=x.setControlValueAccessor,D=x.providers;D.push((0,y.default)(e,t)),k.providers=D;var S=(0,h.default)(e,t,r.viewProviders||[],s.default.config.get("mockNgDefResolver")).providers;S.length>0&&(k.viewProviders=S);var P=function(e,t,r){return{config:s.default.config.get(e),outputs:t.outputs,queryScanKeys:[],setControlValueAccessor:r}}(e,r,null!=j?j:-1!==p.default.extractMethodsFromPrototype(e.prototype).indexOf("writeValue"));(0,f.default)(t,e,P),r.queries&&(0,u.default)(t,r.inputs,Object.keys(r.queries)),(0,c.default)(t,r.outputs),P.queryScanKeys=(0,d.default)(t,r.queries),P.hostBindings=[];try{for(var C=a(r.hostBindings||[]),N=C.next();!N.done;N=C.next()){var T=o(N.value,1)[0];-1===P.hostBindings.indexOf(T)&&P.hostBindings.push(T)}}catch(e){_={error:e}}finally{try{N&&!N.done&&(g=C.return)&&g.call(C)}finally{if(_)throw _.error}}P.hostListeners=[];try{for(var E=a(r.hostListeners||[]),A=E.next();!A.done;A=E.next())T=o(A.value,1)[0],-1===P.hostListeners.indexOf(T)&&P.hostListeners.push(T)}catch(e){b={error:e}}finally{try{A&&!A.done&&(m=E.return)&&m.call(E)}finally{if(b)throw b.error}}return M||s.default.config.delete("mockNgDefResolver"),k}},6932:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(6456),a=n(r(6804)),i=r(6763),l=n(r(8073)),u=n(r(5937));t.default=function(e,t,r,n,f,c){if((0,a.default)(e,r),(0,i.isMockNgDef)(e,t))return e;if(l.default.flags.has(n)&&l.default.cacheDeclarations.has(e))return(0,u.default)(e);var d=l.default.config.has("ngMocksDepsResolution");d||l.default.config.set("ngMocksDepsResolution",new Map);var s=(0,o.extendClass)(f);return c(e,s),l.default.flags.has(n)&&l.default.cacheDeclarations.set(e,s),d||l.default.config.delete("ngMocksDepsResolution"),s}},7610:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(6739),a=n(r(8073));t.default=function(e,t){var r,n=(0,o.getSourceOfMock)(e),i=null!==(r=a.default.configInstance.get(n))&&void 0!==r?r:{__set:!0};i.exported||(i.exported=new Set),t&&i.exported.add((0,o.getSourceOfMock)(t)),i.__set&&(i.__set=void 0,a.default.configInstance.set(n,i))}},5937:function(e,t,r){var n=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var o=r(1763),a=n(r(8073)),i=n(r(5687));t.default=function(e){var t;try{t=(0,i.default)().debugElement.injector.get(o.NG_MOCKS).get(e)}catch(e){}return t||(t=a.default.cacheDeclarations.get(e)),e.__ngMocksResolutions&&a.default.config.has("mockNgDefResolver")&&a.default.config.get("mockNgDefResolver").merge(e.__ngMocksResolutions),t}},7112:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){return{provide:e,useExisting:t}}},3309:function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){return{multi:!0,provide:e,useFactory:t}}},4673:function(e,t,r){var n=this&&this.__assign||function(){return n=Object.assign||function(e){for(var t,r=1,n=arguments.length;r=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},a=this&&this.__read||function(e,t){var r="function"==typeof Symbol&&e[Symbol.iterator];if(!r)return e;var n,o,a=r.call(e),i=[];try{for(;(void 0===t||t-- >0)&&!(n=a.next()).done;)i.push(n.value)}catch(e){o={error:e}}finally{try{n&&!n.done&&(r=a.return)&&r.call(a)}finally{if(o)throw o.error}}return i},i=this&&this.__spreadArray||function(e,t,r){if(r||2===arguments.length)for(var n,o=0,a=t.length;o{t.d(o,{A:()=>r});const r={flags:["cacheModule","cacheComponent","cacheDirective","cacheProvider","correctModuleExports"],mockRenderCacheSize:25,neverMockModule:["ApplicationModule","CommonModule","BrowserModule","_ApplicationModule","_CommonModule","_BrowserModule"],neverMockProvidedFunction:["DomRendererFactory2","EventManager","Injector","RendererFactory2","Sanitizer","DomSanitizer","DomSanitizerImpl","ApplicationInitStatus","ApplicationRef","Compiler","IterableDiffers","KeyValueDiffers","_DomRendererFactory2","_EventManager","_Injector","_Sanitizer","_DomSanitizer","_DomSanitizerImpl","_ApplicationInitStatus","_ApplicationRef","_Compiler","_IterableDiffers","_KeyValueDiffers"],neverMockToken:["InjectionToken Set Injector scope.","InjectionToken EventManagerPlugins","InjectionToken HammerGestureConfig","InjectionToken AppId","InjectionToken DefaultCurrencyCode","InjectionToken LocaleId","InjectionToken SCHEDULER_TOKEN"],onMockBuilderMissingDependency:"throw",onMockInstanceRestoreNeed:"warn",onTestBedFlushNeed:"warn",dependencies:["declarations","hostDirectives","entryComponents","bootstrap","providers","viewProviders","imports","exports"]}},174:(e,o,t)=>{t.d(o,{A:()=>n});var r=t(932);const n=(e,o,t,n=!1)=>{r.A.definePropertyDescriptor(e,o,{configurable:!0,enumerable:n,value:t,writable:!0})}},456:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Ah:()=>getInjection,Bq:()=>flatten,He:()=>extendClass,LG:()=>mapValues,Nn:()=>mapEntries,by:()=>extractDependency,d4:()=>mapKeys,d5:()=>getTestBedInjection});var _angular_core_testing__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(957),_core_define_property__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(174),_core_reflect_parameters_resolve__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(749),_func_get_global__WEBPACK_IMPORTED_MODULE_4__=__webpack_require__(102),_func_get_name__WEBPACK_IMPORTED_MODULE_5__=__webpack_require__(970),_ng_mocks_universe__WEBPACK_IMPORTED_MODULE_3__=__webpack_require__(73);const getTestBedInjection=e=>{try{return getInjection(e)}catch(e){return}},getInjection=e=>{const o=(0,_angular_core_testing__WEBPACK_IMPORTED_MODULE_0__.getTestBed)();return o.inject?o.inject(e):o.get(e)},flatten=(e,o=[])=>{if(Array.isArray(e))for(const t of e)flatten(t,o);else if(null!==e&&"object"==typeof e&&Array.isArray(e.ɵproviders))for(const t of e.ɵproviders)flatten(t,o);else o.push(e);return o},mapKeys=e=>{const o=[];return e.forEach(((e,t)=>o.push(t))),o},mapValues=(e,o)=>{const t=[];return o?e.forEach((e=>{o.add(e)})):e.forEach((e=>{t.push(e)})),t},mapEntries=(e,o)=>{const t=[];return o?e.forEach(((e,t)=>o.set(t,e))):e.forEach(((e,o)=>t.push([o,e]))),t},extractDependencyArray=(e,o)=>{for(const t of e){const e=t&&"object"==typeof t?t.ngMetadataName:void 0;"Optional"!==e&&"SkipSelf"!==e&&"Self"!==e&&o.add(t)}},extractDependency=(e,o)=>{if(o)for(const t of e)Array.isArray(t)?extractDependencyArray(t,o):o.add(t)},extendClassicClass=base=>{let child;const index=_ng_mocks_universe__WEBPACK_IMPORTED_MODULE_3__.A.index(),glb=(0,_func_get_global__WEBPACK_IMPORTED_MODULE_4__.A)();glb.ngMocksParent=base;try{eval(`\n var glb = typeof window === 'undefined' ? global : window;\n class MockMiddleware${index} extends glb.ngMocksParent {};\n glb.ngMocksResult = MockMiddleware${index};\n `),child=glb.ngMocksResult}catch(e){class o extends glb.ngMocksParent{}child=o}finally{glb.ngMocksResult=void 0,glb.ngMocksParent=void 0}return(0,_core_define_property__WEBPACK_IMPORTED_MODULE_1__.A)(child.prototype,`__ngMocks_index_${index}`,void 0,!1),child},extendClass=e=>{const o=extendClassicClass(e);(0,_core_define_property__WEBPACK_IMPORTED_MODULE_1__.A)(o,"name",`MockMiddleware${(0,_func_get_name__WEBPACK_IMPORTED_MODULE_5__.A)(e)}`,!0);const t=(0,_core_reflect_parameters_resolve__WEBPACK_IMPORTED_MODULE_2__.A)(e);return t.length>0&&(0,_core_define_property__WEBPACK_IMPORTED_MODULE_1__.A)(o,"parameters",[...t]),o}},749:(e,o,t)=>{t.d(o,{A:()=>n});var r=t(673);const n=e=>{var o;return null!==(o=(0,r.A)(e).parameters)&&void 0!==o?o:[]}},763:(e,o,t)=>{t.d(o,{C3:()=>i,Em:()=>s,So:()=>c,ZG:()=>_,en:()=>n,gG:()=>l,rO:()=>a});var r=t(614);const n=new r.InjectionToken("NG_MOCKS");n.__ngMocksSkip=!0;const s=new r.InjectionToken("NG_MOCKS_TOUCHES");s.__ngMocksSkip=!0;const c=new r.InjectionToken("NG_MOCKS_OVERRIDES");c.__ngMocksSkip=!0;const _=new r.InjectionToken("NG_MOCKS_GUARDS");_.__ngMocksSkip=!0;const i=new r.InjectionToken("NG_MOCKS_RESOLVERS");i.__ngMocksSkip=!0;const a=new r.InjectionToken("NG_MOCKS_INTERCEPTORS");a.__ngMocksSkip=!0;const l=new r.InjectionToken("NG_MOCKS_ROOT_PROVIDERS");l.__ngMocksSkip=!0},439:(e,o,t)=>{function r({name:e,alias:o,required:t},r=!1){return t?{name:e,alias:o,required:t}:o&&e!==o?r?o:`${e}:${o}`:r?"":e}t.d(o,{A:()=>r})},184:(e,o,t)=>{function r(e){if("string"==typeof e){const[o,t]=e.split(":").map((e=>e.trim()));return o!==t&&t?{name:o,alias:t}:{name:o}}return e}t.d(o,{A:()=>r})},285:(e,o,t)=>{t.d(o,{A:()=>r});const r=e=>"function"==typeof e&&e.__forward_ref__?e():e},102:(e,o,t)=>{t.d(o,{A:()=>r});const r=()=>"undefined"==typeof window?t.g:window},970:(e,o,t)=>{t.d(o,{A:()=>n});const r=new RegExp("[^0-9a-z]+","mgi"),n=e=>{let o;return"function"==typeof e&&e.name?o=e.name:"function"==typeof e?o="arrowFunction":"object"==typeof e&&e&&"InjectionToken"===e.ngMetadataName?o=e._desc:"object"==typeof e&&e&&"function"==typeof e.constructor&&(o=e.constructor.name),o||(o="unknown"),o.replace(r,"_")}},297:(e,o,t)=>{t.d(o,{A:()=>n});var r=t(659);const n=e=>e&&"object"==typeof e&&e.provide?e.provide:(0,r.h)(e)?e.ngModule:e&&"object"==typeof e&&e.directive?e.directive:e},218:(e,o,t)=>{t.d(o,{p:()=>p});var r=t(152),n=t(673);const s=(e,o)=>{const{decorators:t}=(0,n.A)(e);if(0===t.length)return!1;let r=1;if("Injectable"===o&&-1!==t.indexOf("Injectable"))return!0;for(;"Injectable"===t[t.length-r];)r+=1;return t[t.length-r]===o},c=(e,o)=>(!o||"m"===o)&&s(e,"NgModule"),_=(e,o)=>(!o||"c"===o)&&s(e,"Component"),i=(e,o)=>(!o||"d"===o)&&s(e,"Directive"),a=(e,o)=>(!o||"p"===o)&&s(e,"Pipe"),l=(e,o)=>(!o||"i"===o)&&s(e,"Injectable");function p(e,o){if("t"===o)return(0,r.S)(e);if("function"!=typeof e)return!1;const t=c(e,o),n=_(e,o),s=i(e,o),p=a(e,o),u=l(e,o);return t||n||s||p||u}},152:(e,o,t)=>{t.d(o,{S:()=>r});const r=e=>e&&"object"==typeof e&&"InjectionToken"===e.ngMetadataName},659:(e,o,t)=>{t.d(o,{h:()=>r});const r=e=>e&&"object"==typeof e&&"function"==typeof e.ngModule},73:(e,o,t)=>{t.d(o,{A:()=>p});var r=t(295),n=t(102),s=t(970);const c=e=>()=>(_.global.has(e)||_.global.set(e,new Map),_.global.get(e));(0,n.A)().ngMocksUniverse=(0,n.A)().ngMocksUniverse||{};const _=(0,n.A)().ngMocksUniverse;_.builtDeclarations=new Map,_.builtProviders=new Map,_.cacheDeclarations=new Map,_.cacheProviders=new Map,_.config=new Map,_.configInstance=new Map,_.flags=new Set(r.A.flags),_.global=new Map,_.touches=new Set,_.global.set("flags",{onMockBuilderMissingDependency:r.A.onMockBuilderMissingDependency,onMockInstanceRestoreNeed:r.A.onMockInstanceRestoreNeed,onTestBedFlushNeed:r.A.onTestBedFlushNeed}),_.getOverrides=c("overrides"),_.getDefaults=c("defaults"),_.getConfigMock=c("configMock");const i=e=>{{const o=_.getDefaults().get(e);if(o)return o}{const o="function"==typeof e?_.getDefaults().get(`@${(0,s.A)(e)}`):void 0;if(o)return o}return[]};_.getResolution=e=>{const o=_.config.get("ngMocksDepsResolution");if(null==o?void 0:o.has(e))return o.get(e);const[t]=i(e);return t},_.getBuildDeclaration=e=>{if(_.builtDeclarations.has(e))return _.builtDeclarations.get(e);const[o,t]=i(e);return"exclude"===o?null:o&&"keep"!==o?"replace"===o?t:void 0:e},_.hasBuildDeclaration=e=>{if(_.builtDeclarations.has(e))return void 0!==_.builtDeclarations.get(e);const[o]=i(e);return!!o&&"mock"!==o};const a=e=>_.hasBuildDeclaration(e),l=e=>_.getBuildDeclaration(e);_.isExcludedDef=e=>{const o=_.getResolution(e);return(!o||"exclude"===o)&&a(e)&&null===l(e)},_.isProvidedDef=e=>a(e)&&null!==l(e),_.getDefaults().set("@StoreDevtoolsModule",["exclude"]),_.indexValue=0,_.index=()=>_.indexValue++;const p=_},589:(e,o,t)=>{t.d(o,{A:()=>n});var r=t(20);const n=(e,o,t,n)=>{var s;const c=null!==(s=(0,r.A)(e,o))&&void 0!==s?s:{};if(!n&&c.set&&c.set.__ngMocksProxy)return c.set(t),t;const _={configurable:!0,enumerable:!0};return"get"===n&&c.set?_.set=c.set:"set"===n&&c.get&&(_.get=c.get),n?_[n]=t:(_.writable=!0,_.value=t),Object.defineProperty(e,o,_),t}},195:(e,o,t)=>{t.d(o,{A:()=>_});var r=t(331),n=t(794),s=t(20),c=t(932);const _=(e,o,t)=>{if("string"==typeof o)return c.A.mock(e,o,t);let _=e,i=o;const a=["__zone_symbol__unconfigurables"];"function"==typeof o&&(_=c.A.createClone(o),i=e,a.push(...Object.getOwnPropertyNames(_)));const l=[...(0,r.A)(i),...(0,n.A)(i)];for(const e of l){const o=-1===a.indexOf(e)?(0,s.A)(i,e):void 0;o&&Object.prototype.hasOwnProperty.call(o,"value")&&void 0===o.value||c.A.definePropertyDescriptor(_,e,o)}return _}},760:(e,o,t)=>{t.d(o,{A:()=>s});var r=t(73),n=t(589);const s=e=>{const o=[],t=r.A.configInstance.get(e);if(null==t?void 0:t.overloads)for(const[e,r,s]of t.overloads)e?o.push((o=>{(0,n.A)(o,e,r,s)})):o.push(r);return o}},365:(e,o,t)=>{t.d(o,{A:()=>_});var r=t(6),n=t(331),s=t(794),c=t(20);const _=(e,o,t,_)=>{const i=function(...r){return(_||e).apply(o===this?t:this,r)};for(const o of[...(0,n.A)(e),...(0,s.A)(e)]){const t=(0,c.A)(e,o);(0,r.A)(i,o,t)}return i}},6:(e,o,t)=>{t.d(o,{A:()=>n});var r=t(20);const n=(e,o,t)=>{if(!t||!e)return!1;if(Object.defineProperty){const n=(0,r.A)(e,o);if(!1===(null==n?void 0:n.configurable))return!1;Object.defineProperty(e,o,Object.assign(Object.assign(Object.assign({},t),{configurable:!0}),void 0===t.get&&void 0===t.set||!1===t.writable?{writable:!0}:{}))}else e[o]=t.value;return!0}},331:(e,o,t)=>{t.d(o,{A:()=>_});var r=t(970);const n=["sanitize","bypassSecurityTrustHtml","bypassSecurityTrustStyle","bypassSecurityTrustScript","bypassSecurityTrustUrl","bypassSecurityTrustResourceUrl"],s={DomSanitizer:n,Sanitizer:n},c=e=>{var o;const t=Object.getOwnPropertyNames(e);for(const n of null!==(o=s[(0,r.A)(e)])&&void 0!==o?o:[])t.push(n);return t},_=e=>{const o=[];let t=e;for(;t&&null!==Object.getPrototypeOf(t);){for(const e of c(t)){if("constructor"===e)continue;const r=Object.getOwnPropertyDescriptor(t,e);r&&(r.get||r.set)||-1!==o.indexOf(e)||o.push(e)}t=Object.getPrototypeOf(t)}return o}},794:(e,o,t)=>{t.d(o,{A:()=>r});const r=e=>{const o=[];let t=e;for(;t&&null!==Object.getPrototypeOf(t);){for(const e of Object.getOwnPropertyNames(t)){if("constructor"===e)continue;const r=Object.getOwnPropertyDescriptor(t,e);r&&(r.get||r.set)&&-1===o.indexOf(e)&&o.push(e)}t=Object.getPrototypeOf(t)}return o}},20:(e,o,t)=>{t.d(o,{A:()=>r});const r=(e,o)=>{let t=e;for(;t&&null!==Object.getPrototypeOf(t);){const e=Object.getOwnPropertyDescriptor(t,o);if(e)return e;t=Object.getPrototypeOf(t)}}},932:(e,o,t)=>{t.d(o,{A:()=>A,O:()=>M});var r=t(102),n=t(365),s=t(174),c=t(970),_=t(6),i=t(331),a=t(794),l=t(20);const p=(e,o=!1)=>{const t=p.customMockFunction&&!o?p.customMockFunction(e):e=>(n&&n(e),r);let r,n;return(0,s.A)(t,"__ngMocks",!0),(0,s.A)(t,"__ngMocksSet",(e=>n=e)),(0,s.A)(t,"__ngMocksGet",(e=>r=e)),t},u=p;var d=t(763),f=t(218),g=t(73);const k=["canActivate","canActivateChild","canDeactivate","canMatch","canLoad"],m=(e,o)=>Array.isArray(e[o])?(e=>{const o=[];for(const t of e)!g.A.isProvidedDef(t)&&g.A.isExcludedDef(d.ZG)||(o.push(t),(0,f.p)(t)||g.A.touches.add(t));return o})(e[o]):e[o],h=(e,o)=>{if(g.A.cacheDeclarations.has(e))return g.A.cacheDeclarations.get(e);if("object"!=typeof e)return e;if(o.has(e))return e;let t,r=!1;return Array.isArray(e)?[r,t]=((e,o,t)=>{const r=[];let n=!1;e.set(o,r);for(const s of o)g.A.isExcludedDef(s)?n=n||!0:(r.push(t(s,e)),n=n||r[r.length-1]!==s);return[n,r]})(o,e,h):e&&([r,t]=((e,o,t)=>{let r={},n=!1;e.set(o,r);for(const s of Object.keys(o))g.A.isExcludedDef(o[s])?n=n||!0:(r[s]=t(o[s],e),n=n||r[s]!==o[s]);for(const e of k){const o=m(r,e);o&&r[e].length!==o.length&&(n=n||!0,r=Object.assign(Object.assign({},r),{[e]:o}))}if("object"==typeof r.resolve&&r.resolve){const e={};let o=!1;for(const t of Object.keys(r.resolve)){const n=r.resolve[t];g.A.isProvidedDef(n)||!g.A.isExcludedDef(d.C3)?(e[t]=n,(0,f.p)(n)||g.A.touches.add(n)):o=o||!0}o&&(n=n||!0,r=Object.assign(Object.assign({},r),{resolve:e}))}return[n,r]})(o,e,h)),r?(Object.setPrototypeOf(t,Object.getPrototypeOf(e)),t):e};var v=t(663),b=t(465);(0,r.A)().ngMockshelperMockService=(0,r.A)().ngMockshelperMockService||{mockFunction:u,registerMockFunction:e=>{(0,r.A)().ngMockshelperMockService.mockFunction.customMockFunction=e},createClone:n.A,createMockFromPrototype:e=>{const o=(0,c.A)(e),t={};(0,s.A)(t,"__ngMocks",!0);const r=A.extractMethodsFromPrototype(e);for(const e of r)A.mock(t,e,o);const n=A.extractPropertiesFromPrototype(e);for(const e of n)A.mock(t,e,"get",o),A.mock(t,e,"set",o);return Object.setPrototypeOf(t,e),t},definePropertyDescriptor:_.A,extractMethodsFromPrototype:i.A,extractPropertiesFromPrototype:a.A,extractPropertyDescriptor:l.A,mock:(e,o,...t)=>{const{accessType:r,mockName:n}=(e=>{let o,t;return e.length>0&&"get"!==e[0]&&"set"!==e[0]?t=e[0]:e.length>0&&("get"===e[0]||"set"===e[0])&&(o=e[0],t=e[1]),{accessType:o,mockName:t}})(t),s=Object.getOwnPropertyDescriptor(e,o);if(s&&s[r||"value"])return s[r||"value"];const _=((e,o,t,r)=>`${null!=o?o:"function"==typeof t.prototype?t.prototype.name:(0,c.A)(t)}.${e}${null!=r?r:""}`)(o,n,e,r),i=A.mockFunction(_,!!r),a=((e,o,t)=>Object.assign(Object.assign(Object.assign(Object.assign({},"get"===t&&e&&e.set?{set:e.set}:{}),"set"===t&&e&&e.get?{get:e.get}:{}),t?{}:{writable:!0}),{[t||"value"]:o,configurable:!0,enumerable:!0}))(s,i,r);return a.get&&a.set&&a.get.__ngMocks&&a.set.__ngMocks&&a.set.__ngMocksSet((e=>a.get.__ngMocksGet(e))),Object.defineProperty(e,o,a),i},replaceWithMocks:e=>{const o=new Map,t=h(e,o);return o.clear(),t},resolveProvider:v.A,useFactory:b.A};const A=(0,r.A)().ngMockshelperMockService;function M(e){(0,r.A)().ngMockshelperMockService.registerMockFunction(e)}},663:(e,o,t)=>{t.d(o,{A:()=>u});var r=t(456),n=t(763),s=t(285),c=t(297),_=t(152),i=t(73),a=t(932),l=t(415);const p=(e,o,t)=>{let r=!1,n=!e;return o&&e&&!n&&(n=((e,o,...t)=>{for(const r of t)if(e[r]!==o[r])return!0;return!1})(o,e,"provide","useValue","useClass","useExisting","useFactory","deps")),(o===t&&e!==o||o!==t&&n)&&(r=!0),!r},u=(e,o,t)=>{const{provide:u,multi:d,change:f}=((e,o)=>{const t=(0,c.A)(e);return{change:()=>{o&&o()},multi:e!==t&&!!e.multi,provide:t}})(e,t);if(((e,o)=>null===i.A.builtProviders.get(o)||(o!==e&&e.deps&&(0,r.by)(e.deps,i.A.config.get("ngMocksDeps")),((e,o)=>{if(((e,o)=>i.A.builtProviders.has(n.rO)&&null===i.A.builtProviders.get(n.rO)&&(0,_.S)(o)&&"InjectionToken HTTP_INTERCEPTORS"===o.toString()&&o!==e)(e,o)){if(e.useFactory||e.useValue)return!0;const o=(0,s.A)(e.useExisting)||e.useClass;if(!i.A.builtProviders.has(o)||null===i.A.builtProviders.get(o))return!0}return!1})(e,o)))(e,u))return f();if(((e,o)=>{var t;return!(!e||"object"!=typeof e||!e.useExisting||!e.useExisting.mockOf&&(i.A.getResolution(o)&&!(null===(t=i.A.config.get(o))||void 0===t?void 0:t.__internal)||"keep"!==i.A.getResolution((0,s.A)(e.useExisting))))})(e,u))return i.A.touches.add(u),e;if(o.has(u))return((e,o)=>{let t=o;const r=i.A.builtProviders.get(e);return r&&(t=r),"function"==typeof t&&(t={provide:e,useClass:t}),t})(u,o.get(u));const g=((e,o,t)=>{var r;let n=((e,o)=>{if(i.A.builtProviders.has(o)){const t=i.A.builtProviders.get(o);return t===o?e:t}})(e,o);return!n&&i.A.flags.has("skipMock")&&"mock"!==i.A.getResolution(o)&&(null===(r=i.A.config.get("ngMocksDepsSkip"))||void 0===r||r.add(o),n=e),n||(n=(0,l.A)(e)),n=((e,o,t)=>{if(o!==e&&t&&t.useValue){const e=a.A.replaceWithMocks(t.useValue);return e===t.useValue?t:Object.assign(Object.assign({},t),{useValue:e})}return t})(e,o,n),p(n,e,o)||t(),n&&i.A.touches.add(o),n})(e,u,f);return d&&"object"==typeof g?Object.assign(Object.assign({},g),{multi:d}):g}},465:(e,o,t)=>{t.d(o,{A:()=>p});var r=t(614),n=t(456),s=t(152),c=t(73),_=t(195),i=t(760),a=t(839);const l=e=>(0,s.S)(e)||"string"==typeof e,p=(e,o,t)=>({deps:[r.Injector],provide:e,useFactory:r=>{const s=o?o():(0,a.K)(e),p=c.A.getOverrides().get(e),u=p?(0,n.LG)(p):[];return t&&u.push(t),u.push(...(0,i.A)(e)),((e,o,t,r,n)=>{let s=o;for(const o of t){const t=o(s,r);l(e)?s=t:o!==n?t&&(s=(0,_.A)(s,t)):s=t}return s})(e,s,u,r,t)}})},415:(e,o,t)=>{t.d(o,{A:()=>g});var r=t(295),n=t(297),s=t(152),c=t(73),_=t(6),i=t(20),a=t(465),l=t(839);const{neverMockProvidedFunction:p,neverMockToken:u}=r.A,d=[[e=>"boolean"==typeof e,!1],[e=>"number"==typeof e,0],[e=>"string"==typeof e,""],[e=>null===e,null]],f=(e,o,t)=>{var r;if(o===e)return t?(0,a.A)(e,(()=>{})):void 0;if(e.multi)return void(null===(r=c.A.config.get("ngMocksMulti"))||void 0===r||r.add(o));let n;return-1!==Object.keys(e).indexOf("useValue")?n=((e,o)=>(0,a.A)(o,(()=>e.useValue&&"object"==typeof e.useValue?(0,l.K)(e.useValue):(e=>{for(const[o,t]of d)if(o(e))return t})(e.useValue))))(e,o):-1!==Object.keys(e).indexOf("useExisting")?n=e:-1!==Object.keys(e).indexOf("useClass")?n=((e,o)=>c.A.builtProviders.has(e.useClass)&&c.A.builtProviders.get(e.useClass)===e.useClass?e:(0,a.A)(o,(()=>(0,l.K)(e.useClass))))(e,o):-1!==Object.keys(e).indexOf("useFactory")&&(n=(0,a.A)(o,(()=>({})))),n},g=(e,o=!1)=>{const t=(0,n.A)(e);if("mock"===c.A.getResolution(t));else{if((e=>"function"==typeof e&&-1!==p.indexOf(e.name))(t))return e;if((e=>(0,s.S)(e)&&-1!==u.indexOf(e.toString()))(t))return}const r=c.A.flags.has("cacheProvider")?c.A.cacheProviders:void 0;return t===e&&r&&r.has(t)?r.get(t):((e,o,t)=>{let r;return"function"==typeof o&&(r=((e,o)=>(0,a.A)(o,(()=>{const t=(0,l.K)(o);return o!==e&&-1!==Object.keys(e).indexOf("useClass")&&((e,o)=>{const t=Object.getOwnPropertyNames(e),r=(0,l.K)(o);for(const o of Object.getOwnPropertyNames(r)){if(-1!==t.indexOf(o))continue;const n=(0,i.A)(r,o);(0,_.A)(e,o,n)}})(t,e.useClass),t})))(e,o)),o===e&&r&&t&&t.set(o,r),r})(e,t,r)||f(e,t,o)}},839:(e,o,t)=>{t.d(o,{K:()=>a});var r=t(970),n=t(195);const s=e=>{if("function"!=typeof e)return!1;if(!e.prototype)return!0;if((e=>!!(e.ɵprov||e.__annotations__||e.__parameters__||e.parameters))(e))return!1;const o=e.toString();if(null!==o.match(/^class\b/))return!1;const t=o.match(/^function\s+([^\s(]+)\(/);return null===t||!((e,o,t)=>{if(null!==e.match(/^class/))return!0;if(Object.keys(t.prototype).length>0)return!0;const r=e.codePointAt(0);if(r&&r>=65&&r<=90&&null!==o.match(/\bthis\./gm))return!0;const n=new RegExp(`\\(this,\\s*${e}\\)`,"mg");return null!==o.match(n)})(t[1],o,e)};var c=t(932);const _=[[e=>"function"==typeof e&&!s(e),(e,o)=>{const t=c.A.createMockFromPrototype(o.prototype);return e.set(o,t),t}],[s,(e,o,t)=>{const n=c.A.mockFunction(`func:${t||(0,r.A)(o)}`);return e.set(o,n()),n}],[e=>Array.isArray(e),()=>[]],[e=>null!==e&&"object"==typeof e&&"InjectionToken"!==e.ngMetadataName&&"object"==typeof Object.getPrototypeOf(e),(e,o,t,r)=>{const n=c.A.createMockFromPrototype(o.constructor.prototype);e.set(o,n);for(const s of Object.keys(o)){const c=r(e,o[s],`${t||"instance"}.${s}`);void 0!==c&&(n[s]=c)}return Object.setPrototypeOf(n,Object.getPrototypeOf(o)),n}]],i=(e,o,t="",r)=>{const s=((e,o,t,r)=>{var n;for(const[s,c]of _)if(s(o))return null!==(n=e.get(o))&&void 0!==n?n:c(e,o,t,r)})(e,o,t,i);return r&&(0,n.A)(s,r),s};function a(e,...o){const t=o.length>0&&"string"==typeof o[0]?o[0]:o[1],r=o.length>0&&o[0]&&"object"==typeof o[0]?o[0]:void 0,n=new Map,s=i(n,e,t,r);return n.clear(),s}},673:(e,o,t)=>{t.d(o,{A:()=>x});var r=t(614),n=t(174),s=t(439),c=t(184);const _=(e,o)=>{const t=e.indexOf(o);-1!==t&&e.splice(t,1),"Injectable"!==o&&"Pipe"!==o&&"Directive"!==o&&"Component"!==o&&"NgModule"!==o||e.push(o)},i=e=>{const o=[];for(const t of Object.keys(e))o.push(t);return o},a=e=>(o,t,r,n)=>{var _;const{alias:i,required:a}=(0,c.A)({name:t,alias:null!==(_=r.alias)&&void 0!==_?_:r.bindingPropertyName,required:r.required}),l=(0,s.A)({name:t,alias:i,required:a});let p=!0;for(const o of n[e]){if(o===l){p=!1;break}const{name:e,alias:r,required:n}=(0,c.A)(o);if(e===t&&r===i&&n===a){p=!1;break}}p&&n[e].unshift(l)},l=a("inputs"),p=a("outputs"),u=e=>(o,t,r,n)=>{n.queries[t]||(n.queries[t]=Object.assign(Object.assign({isViewQuery:e,ngMetadataName:o,selector:r.selector},void 0===r.read?{}:{read:r.read}),void 0===r.static?{}:{static:r.static}))},d=u(!1),f=u(!0),g=e=>(o,t,r,n)=>{n.queries[t]||(n.queries[t]=Object.assign(Object.assign(Object.assign({isViewQuery:e,ngMetadataName:o,selector:r.selector},void 0===r.descendants?{}:{descendants:r.descendants}),void 0===r.emitDistinctChangesOnly?{}:{emitDistinctChangesOnly:r.emitDistinctChangesOnly}),void 0===r.read?{}:{read:r.read}))},k={ContentChild:d,ContentChildren:g(!1),HostBinding:(e,o,t,r)=>{const n=`[${t.hostPropertyName||o}]`;r.host[n]||(r.host[n]=o),r.hostBindings.push([o,t.hostPropertyName||o,...t.args?[t.args]:[]])},HostListener:(e,o,t,r)=>{const n=`(${t.eventName||o})`;r.host[n]||(r.host[n]=`${o}($event)`),r.hostListeners.push([o,t.eventName||o,...t.args?[t.args]:[]])},Input:l,Output:p,ViewChild:f,ViewChildren:g(!0)},m=e=>{const o=a(e);return(e,t,r,n)=>{var s;const{alias:c,required:_}=void 0===(null===(s=r.args)||void 0===s?void 0:s[0])?{}:"string"==typeof r.args[0]?{alias:r.args[0]}:r.args[0];o(e,t,{alias:c,required:_,bindingPropertyName:c},n)}},h=m("inputs"),v=m("outputs"),b=e=>(o,t,r,n)=>{n.queries[t]||(n.queries[t]=Object.assign({isViewQuery:e,ngMetadataName:o,selector:r.args[0]},r.args[1]))},A=b(!1),M=b(!0),y={ContentChild:A,ContentChildren:A,HostBinding:(e,o,t,r)=>{var n;const s=`[${(null===(n=t.args)||void 0===n?void 0:n[0])||o}]`;r.host[s]||(r.host[s]=o),r.hostBindings.push([o,...t.args||[]])},HostListener:(e,o,t,r)=>{var n;const s=`(${(null===(n=t.args)||void 0===n?void 0:n[0])||o})`;r.host[s]||(r.host[s]=`${o}($event)`),r.hostListeners.push([o,...t.args||[]])},Input:h,Output:v,ViewChild:M,ViewChildren:M},w=(e,o)=>{if(e){e.inputs=e.inputs||[];for(const t of o.inputs)-1===e.inputs.indexOf(t)&&e.inputs.push(t);e.outputs=e.outputs||[];for(const t of o.outputs)-1===e.outputs.indexOf(t)&&e.outputs.push(t);e.queries=Object.assign(Object.assign({},e.queries||[]),o.queries),e.hostBindings=o.hostBindings,e.hostListeners=o.hostListeners}},O=new r["ɵReflectionCapabilities"],C=e=>{if("function"!=typeof e&&"object"!=typeof e)return{};if(Object.prototype.hasOwnProperty.call(e,"__ngMocksParsed"))return e.__ngMocksDeclarations;const o=Object.getPrototypeOf(e),t=o?C(o):{},r=(e=>({host:e.host?Object.assign({},e.host):{},hostBindings:e.hostBindings?[...e.hostBindings]:[],hostListeners:e.hostListeners?[...e.hostListeners]:[],attributes:e.attributes?[...e.attributes]:[],inputs:e.inputs?[...e.inputs]:[],outputs:e.outputs?[...e.outputs]:[],propDecorators:e.propDecorators?Object.assign({},e.propDecorators):{},queries:e.queries?Object.assign({},e.queries):{},decorators:e.decorators?[...e.decorators]:[]}))(t);return(0,n.A)(e,"__ngMocksParsed",!0),((e,o)=>{if(Object.prototype.hasOwnProperty.call(e,"__parameters__")&&e.__parameters__)for(const t of e.__parameters__)for(const e of t||[])"Attribute"===e.ngMetadataName&&-1===o.attributes.indexOf(e.attributeName)&&o.attributes.push(e.attributeName)})(e,r),((e,o)=>{if(Object.prototype.hasOwnProperty.call(e,"__annotations__")&&e.__annotations__)for(const t of e.__annotations__){const e=null==t?void 0:t.ngMetadataName;e&&(o[e]=Object.assign(Object.assign({},t),{attributes:o.attributes}),_(o.decorators,e))}})(e,r),((e,o)=>{var t,r;if(Object.prototype.hasOwnProperty.call(e,"decorators")&&e.decorators)for(const n of e.decorators){const e=null===(r=null===(t=null==n?void 0:n.type)||void 0===t?void 0:t.prototype)||void 0===r?void 0:r.ngMetadataName;e&&(o[e]=n.args?Object.assign({},n.args[0]):{},_(o.decorators,e))}})(e,r),((e,o)=>{var t,r,n;if(Object.prototype.hasOwnProperty.call(e,"propDecorators")&&e.propDecorators)for(const s of i(e.propDecorators)){o.propDecorators[s]=[...o.propDecorators[s]||[],...e.propDecorators[s]];for(const c of e.propDecorators[s]){const e=null===(r=null===(t=null==c?void 0:c.type)||void 0===t?void 0:t.prototype)||void 0===r?void 0:r.ngMetadataName;e&&(null===(n=y[e])||void 0===n||n.call(y,e,s,c,o))}}})(e,r),((e,o)=>{var t;if(Object.prototype.hasOwnProperty.call(e,"__prop__metadata__")&&e.__prop__metadata__)for(const r of i(e.__prop__metadata__)){const n=e.__prop__metadata__[r];for(const e of n){const n=null==e?void 0:e.ngMetadataName;n&&(null===(t=k[n])||void 0===t||t.call(k,n,r,e,o))}}})(e,r),w(r.Directive,r),w(r.Component,r),(0,n.A)(e,"__ngMocksDeclarations",Object.assign(Object.assign(Object.assign({},t),r),{parameters:O.parameters(e)})),e.__ngMocksDeclarations},x=C},614:(e,o,t)=>{e.exports=(e=>{var o={};return t.d(o,e),o})({ChangeDetectorRef:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ChangeDetectorRef,Component:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Component,ComponentFactoryResolver:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ComponentFactoryResolver,ContentChild:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ContentChild,ContentChildren:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ContentChildren,DebugElement:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.DebugElement,Directive:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Directive,ElementRef:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ElementRef,EventEmitter:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.EventEmitter,InjectionToken:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.InjectionToken,Injector:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Injector,Input:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Input,NgModule:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.NgModule,Optional:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Optional,Output:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Output,Pipe:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Pipe,QueryList:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.QueryList,Self:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Self,TemplateRef:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.TemplateRef,ViewChild:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ViewChild,ViewChildren:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ViewChildren,ViewContainerRef:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ViewContainerRef,ɵReflectionCapabilities:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__["ɵReflectionCapabilities"]})},957:(e,o,t)=>{e.exports=(e=>{var o={};return t.d(o,e),o})({TestBed:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_testing_89899de6__.TestBed,getTestBed:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_testing_89899de6__.getTestBed})}},__webpack_module_cache__={};function __webpack_require__(e){var o=__webpack_module_cache__[e];if(void 0!==o)return o.exports;var t=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](t,t.exports,__webpack_require__),t.exports}__webpack_require__.d=(e,o)=>{for(var t in o)__webpack_require__.o(o,t)&&!__webpack_require__.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:o[t]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__={};__webpack_require__.d(__webpack_exports__,{rX:()=>types_namespaceObject.IMockBuilder,HA:()=>types_namespaceObject.IMockBuilderConfig,Wn:()=>types_namespaceObject.IMockBuilderConfigAll,Me:()=>types_namespaceObject.IMockBuilderConfigComponent,I7:()=>types_namespaceObject.IMockBuilderConfigDirective,tv:()=>types_namespaceObject.IMockBuilderConfigModule,OG:()=>types_namespaceObject.IMockBuilderExtended,sF:()=>types_namespaceObject.IMockBuilderProvider,me:()=>types_namespaceObject.IMockBuilderResult,bk:()=>LegacyControlValueAccessor,JT:()=>Mock,_V:()=>MockBuilder,Am:()=>MockComponent,$u:()=>MockComponents,D2:()=>mock_control_value_accessor_namespaceObject.MockControlValueAccessor,dw:()=>MockDeclaration,uV:()=>MockDeclarations,Cc:()=>MockDirective,nr:()=>MockDirectives,Wm:()=>MockInstance,BN:()=>MockModule,ZJ:()=>MockPipe,yI:()=>MockPipes,Qo:()=>MockProvider,dD:()=>MockProviders,Ty:()=>MockRender,P0:()=>MockRenderFactory,mB:()=>MockReset,KH:()=>mock_service.K,b6:()=>mock_control_value_accessor_namespaceObject.MockValidator,Je:()=>mock_component_types_namespaceObject.MockedComponent,T4:()=>mock_directive_types_namespaceObject.MockedDirective,qZ:()=>mock_module_types_namespaceObject.MockedModule,cm:()=>mock_pipe_types_namespaceObject.MockedPipe,en:()=>core_tokens.en,ZG:()=>core_tokens.ZG,rO:()=>core_tokens.rO,So:()=>core_tokens.So,C3:()=>core_tokens.C3,gG:()=>core_tokens.gG,Em:()=>core_tokens.Em,Ah:()=>core_helpers.Ah,xz:()=>getMockedNgDefOf,VK:()=>getSourceOfMock,d5:()=>core_helpers.d5,IA:()=>isMockControlValueAccessor,Bt:()=>isMockNgDef,AW:()=>isMockOf,lt:()=>isMockValidator,Fk:()=>isMockedNgDefOf,pA:()=>func_is_ng_def.p,SM:()=>func_is_ng_injection_token.S,H5:()=>ngMocks});var mock_control_value_accessor_namespaceObject={};__webpack_require__.r(mock_control_value_accessor_namespaceObject),__webpack_require__.d(mock_control_value_accessor_namespaceObject,{b:()=>LegacyControlValueAccessor});var types_namespaceObject={};__webpack_require__.r(types_namespaceObject);var mock_module_types_namespaceObject={};__webpack_require__.r(mock_module_types_namespaceObject);var mock_component_types_namespaceObject={};__webpack_require__.r(mock_component_types_namespaceObject);var mock_directive_types_namespaceObject={};__webpack_require__.r(mock_directive_types_namespaceObject);var mock_pipe_types_namespaceObject={};__webpack_require__.r(mock_pipe_types_namespaceObject);var ng_mocks_universe=__webpack_require__(73),_a,_b;const stackRoot={id:{},level:"root"},stack=ng_mocks_universe.A.global.get("reporter-stack")||[Object.assign({},stackRoot)];ng_mocks_universe.A.global.set("reporter-stack",stack);const current=()=>stack[stack.length-1],listenersPush=null!==(_a=ng_mocks_universe.A.global.get("reporter-stack-push"))&&void 0!==_a?_a:[];ng_mocks_universe.A.global.set("reporter-stack-push",listenersPush);const listenersPop=null!==(_b=ng_mocks_universe.A.global.get("reporter-stack-pop"))&&void 0!==_b?_b:[];ng_mocks_universe.A.global.set("reporter-stack-pop",listenersPop);const stackPush=()=>{const e={};ng_mocks_universe.A.global.set("reporter-stack-id",e);const o={id:e,level:"runtime"};stack.push(o);for(const e of listenersPush)e(o,stack)},stackPop=()=>{const e=stack.pop();if(0===stack.length&&stack.push("root"===(null==e?void 0:e.level)?e:Object.assign({},stackRoot)),e&&"root"!==e.level)for(const o of listenersPop)o(e,stack);ng_mocks_universe.A.global.set("reporter-stack-id",stack[stack.length-1].id)},subscribePush=e=>{listenersPush.indexOf(e)&&listenersPush.push(e),stack.length>0&&e(stack[stack.length-1],stack)},subscribePop=e=>{-1===listenersPop.indexOf(e)&&listenersPop.push(e)},unsubscribePush=e=>{const o=listenersPush.indexOf(e);-1!==o&&listenersPush.splice(o,1)},unsubscribePop=e=>{const o=listenersPop.indexOf(e);-1!==o&&listenersPop.splice(o,1)},ng_mocks_stack={current,stackPop,stackPush,subscribePop,subscribePush,unsubscribePop,unsubscribePush};var core_=__webpack_require__(614),testing_=__webpack_require__(957),core_helpers=__webpack_require__(456),core_tokens=__webpack_require__(763);const func_extract_tokens=e=>{let o,t,r;for(const n of(0,core_helpers.Bq)(e||[]))"object"==typeof n&&(n.provide===core_tokens.en&&(o=n.useValue),n.provide===core_tokens.So&&(t=n.useValue),n.provide===core_tokens.Em&&(r=n.useValue));return{mocks:o,overrides:t,touches:r}};var core_define_property=__webpack_require__(174),collect_declarations=__webpack_require__(673),func_is_ng_injection_token=__webpack_require__(152);const getNgType=e=>{if("string"==typeof e)return;if((0,func_is_ng_injection_token.S)(e))return"Injectable";const{decorators:o}=(0,collect_declarations.A)(e);for(let e=o.length-1;e>=0;e-=1)if("Injectable"!==o[e])return o[e];return o.length>0?"Injectable":void 0};function isStandalone(e){const o=getNgType(e);return!(!o||"Injectable"===o)&&!0===(0,collect_declarations.A)(e)[o].standalone}var helper_extract_property_descriptor=__webpack_require__(20);const core_def_stack=class{constructor(){this.stack=[],this.push()}push(){this.stack.push(new Map)}pop(){var e;return null!==(e=this.stack.pop())&&void 0!==e?e:new Map}has(e){for(let o=this.stack.length-1;o>=0;o-=1)if(this.stack[o].has(e))return!0;return!1}get(e){for(let o=this.stack.length-1;o>=0;o-=1)if(this.stack[o].has(e))return this.stack[o].get(e)}set(e,o){for(let t=this.stack.length-1;t>=0;t-=1)this.stack[t].set(e,o);return this}merge(e){for(const[o,t]of(0,core_helpers.Nn)(e))this.set(o,t);return this}};var func_get_name=__webpack_require__(970),func_is_ng_def=__webpack_require__(218),func_is_ng_module_def_with_providers=__webpack_require__(659),core_config=__webpack_require__(295);class MockBuilderStash{constructor(){this.data={}}backup(){this.data={builtDeclarations:ng_mocks_universe.A.builtDeclarations,builtProviders:ng_mocks_universe.A.builtProviders,cacheDeclarations:ng_mocks_universe.A.cacheDeclarations,cacheProviders:ng_mocks_universe.A.cacheProviders,config:ng_mocks_universe.A.config,configInstance:ng_mocks_universe.A.configInstance,flags:ng_mocks_universe.A.flags,touches:ng_mocks_universe.A.touches},ng_mocks_universe.A.builtDeclarations=new Map,ng_mocks_universe.A.builtProviders=new Map,ng_mocks_universe.A.cacheDeclarations=new Map,ng_mocks_universe.A.cacheProviders=new Map,ng_mocks_universe.A.config=new Map,ng_mocks_universe.A.configInstance=new Map,ng_mocks_universe.A.flags=new Set(core_config.A.flags),ng_mocks_universe.A.touches=new Set}restore(){for(const e of Object.keys(this.data))ng_mocks_universe.A[e]=this.data[e]}}const core_reflect_provided_in=e=>{var o,t,r;if(e&&("object"==typeof e||"function"==typeof e))return null!==(t=null===(o=e.ɵprov)||void 0===o?void 0:o.providedIn)&&void 0!==t?t:null===(r=e.ngInjectableDef)||void 0===r?void 0:r.providedIn};var func_get_type=__webpack_require__(297),helper_resolve_provider=__webpack_require__(663);const add_requested_providers=(e,{providerDef:o,mockDef:t},r)=>{for(const t of(0,core_helpers.LG)(o))e.providers.push(t);for(const o of(0,core_helpers.Bq)(e.providers)){const e=(0,func_get_type.A)(o);ng_mocks_universe.A.touches.add(e),e!==o&&o.deps&&(0,core_helpers.by)(o.deps,ng_mocks_universe.A.config.get("ngMocksDeps"))}for(const o of(0,core_helpers.LG)(t))ng_mocks_universe.A.touches.has(o)||"root"!==core_reflect_provided_in(o)||(e.providers.push((0,helper_resolve_provider.A)(o,r)),ng_mocks_universe.A.touches.add(o))},apply_platform_modules=()=>{const e=(0,testing_.getTestBed)();if(e.ngModule)for(const o of(0,core_helpers.Bq)(e.ngModule))ng_mocks_universe.A.touches.add((0,func_get_type.A)(o))},error_empty_def=e=>{if(!e)throw new Error(["undefined / null has been passed into ng-mocks as a declaration / provider.","Please ensure that the current test file has correct imports:","imported files exist and imported declarations have been exported in the file."].join(" "))},func_is_jest_mock=e=>!(!e||"function"!=typeof e&&"object"!=typeof e||!(e._isMockFunction&&e.mockName&&e.__annotations__)),error_jest_mock=e=>{if(func_is_jest_mock(e))throw new Error([`ng-mocks got ${(0,func_get_name.A)(e)} which has been already mocked by jest.mock().`,"It is not possible to produce correct mocks for it, because jest.mock() removes Angular decorators.",`To fix this, please avoid jest.mock() on the file which exports ${(0,func_get_name.A)(e)} or add jest.dontMock() on it.`,"The same should be done for all related dependencies."].join(" "))},error_missing_decorators=e=>{throw new Error([`${(0,func_get_name.A)(e)} declaration has been passed into ng-mocks without Angular decorators.`,"Therefore, it cannot be properly handled.","Highly likely,","undefined"==typeof jest?"":"jest.mock() has been used on its file, or","ng-mocks is imported in production code, or got a class without Angular decoration.","Otherwise, please create an issue on github: https://github.com/help-me-mom/ng-mocks/issues/new?title=False%20positive%20ng-mocks%20not%20in%20JIT.","Thank you in advance for support."].join(" "))},core_reflect_body_catch=e=>o=>{error_empty_def(o);try{return e(o)}catch(e){error_jest_mock(o),error_missing_decorators(o)}},core_reflect_directive_resolve=e=>core_reflect_body_catch((e=>{const o=(0,collect_declarations.A)(e);if(o.Component)return o.Component;if(o.Directive)return o.Directive;throw new Error("Cannot resolve declarations")}))(e),core_reflect_module_resolve=e=>core_reflect_body_catch((e=>{const o=(0,collect_declarations.A)(e);if(o.NgModule)return o.NgModule;throw new Error("Cannot resolve declarations")}))(e),core_reflect_meta=e=>(0,func_is_ng_def.p)(e,"c")||(0,func_is_ng_def.p)(e,"d")?core_reflect_directive_resolve(e):(0,func_is_ng_def.p)(e,"m")?core_reflect_module_resolve(e):void 0;function getSourceOfMock(e){return"function"==typeof e&&e.mockOf?e.mockOf:e}const mark_exported=(e,o)=>{var t;const r=getSourceOfMock(e),n=null!==(t=ng_mocks_universe.A.configInstance.get(r))&&void 0!==t?t:{__set:!0};n.exported||(n.exported=new Set),o&&n.exported.add(getSourceOfMock(o)),n.__set&&(n.__set=void 0,ng_mocks_universe.A.configInstance.set(r,n))};var x=e=>{var o={};return __webpack_require__.d(o,e),o},y=e=>()=>e;const forms_namespaceObject=x({AbstractControl:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.AbstractControl,DefaultValueAccessor:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.DefaultValueAccessor,FormControl:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.FormControl,FormControlDirective:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.FormControlDirective,NG_ASYNC_VALIDATORS:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.NG_ASYNC_VALIDATORS,NG_VALIDATORS:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.NG_VALIDATORS,NG_VALUE_ACCESSOR:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.NG_VALUE_ACCESSOR,NgControl:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.NgControl,NgModel:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.NgModel}),AbstractControl=forms_namespaceObject.AbstractControl,DefaultValueAccessor=forms_namespaceObject.DefaultValueAccessor,FormControl=forms_namespaceObject.FormControl,FormControlDirective=forms_namespaceObject.FormControlDirective,NG_ASYNC_VALIDATORS=forms_namespaceObject.NG_ASYNC_VALIDATORS,NG_VALIDATORS=forms_namespaceObject.NG_VALIDATORS,NG_VALUE_ACCESSOR=forms_namespaceObject.NG_VALUE_ACCESSOR,NgControl=forms_namespaceObject.NgControl,NgModel=forms_namespaceObject.NgModel,core_form={AbstractControl,DefaultValueAccessor,FormControl,FormControlDirective,NG_ASYNC_VALIDATORS,NG_VALIDATORS,NG_VALUE_ACCESSOR,NgControl,NgModel},func_is_mock=e=>e&&"object"==typeof e&&!!e.__ngMocks;var mock_helper_stub=__webpack_require__(195),mock_instance_apply=__webpack_require__(760),helper_mock_service=__webpack_require__(932),func_directive_io_parse=__webpack_require__(184);const applyProxy=(e,o,t,r)=>{if(e.instance&&r&&(e.instance[r]=t),e.instance&&e.instance[o])return e.instance[o](t)};class MockControlValueAccessorProxy{constructor(e){this.target=e}registerOnChange(e){applyProxy(this,"registerOnChange",e,"__simulateChange")}registerOnTouched(e){applyProxy(this,"registerOnTouched",e,"__simulateTouch")}setDisabledState(e){applyProxy(this,"setDisabledState",e)}writeValue(e){applyProxy(this,"writeValue",e)}}class MockValidatorProxy{constructor(e){this.target=e}registerOnValidatorChange(e){applyProxy(this,"registerOnValidatorChange",e,"__simulateValidatorChange")}validate(e){return this.instance&&this.instance.validate?this.instance.validate(e):null}}class MockAsyncValidatorProxy{constructor(e){this.target=e}registerOnValidatorChange(e){applyProxy(this,"registerOnValidatorChange",e,"__simulateValidatorChange")}validate(e){if(this.instance&&this.instance.validate){const o=this.instance.validate(e);return void 0===o?Promise.resolve(null):o}return Promise.resolve(null)}}const setValueAccessor=(e,o)=>{if(o&&!o.valueAccessor&&e.__ngMocksConfig.setControlValueAccessor)try{o.valueAccessor=new MockControlValueAccessorProxy(e.__ngMocksCtor)}catch(e){}},installValueAccessor=(e,o)=>{e.valueAccessor.instance||e.valueAccessor.target!==o.__ngMocksCtor||(e.valueAccessor.instance=o,helper_mock_service.A.mock(o,"registerOnChange"),helper_mock_service.A.mock(o,"registerOnTouched"),helper_mock_service.A.mock(o,"setDisabledState"),helper_mock_service.A.mock(o,"writeValue"),o.__ngMocksConfig.isControlValueAccessor=!0)},installValidator=(e,o)=>{for(const t of e)t.instance||t.target!==o.__ngMocksCtor||(t.instance=o,helper_mock_service.A.mock(o,"registerOnValidatorChange"),helper_mock_service.A.mock(o,"validate"),o.__ngMocksConfig.isValidator=!0)},applyNgValueAccessor=(e,o)=>{setValueAccessor(e,o);try{o&&(installValueAccessor(o,e),installValidator(o._rawValidators,e),installValidator(o._rawAsyncValidators,e))}catch(e){}},applyOutputs=e=>{const o=[];for(const t of e.__ngMocksConfig.outputs||[])o.push((0,func_directive_io_parse.A)(t).name);for(const t of o)e[t]||Object.getOwnPropertyDescriptor(e,t)||(e[t]=new core_.EventEmitter)},applyPrototype=(e,o)=>{for(const t of[...helper_mock_service.A.extractMethodsFromPrototype(o),...helper_mock_service.A.extractPropertiesFromPrototype(o)]){const r=helper_mock_service.A.extractPropertyDescriptor(o,t);helper_mock_service.A.definePropertyDescriptor(e,t,r)}},applyMethods=(e,o)=>{for(const t of helper_mock_service.A.extractMethodsFromPrototype(o))e[t]||Object.getOwnPropertyDescriptor(e,t)||helper_mock_service.A.mock(e,t)},applyProps=(e,o)=>{for(const t of helper_mock_service.A.extractPropertiesFromPrototype(o))e[t]||Object.getOwnPropertyDescriptor(e,t)||(helper_mock_service.A.mock(e,t,"get"),helper_mock_service.A.mock(e,t,"set"))},applyOverrides=(e,o,t)=>{const r=ng_mocks_universe.A.getOverrides().get(o),n=r?(0,core_helpers.LG)(r):[];e.__ngMocksConfig.init&&n.push(e.__ngMocksConfig.init),n.push(...(0,mock_instance_apply.A)(o));for(const o of n){const r=o(e,t);r&&(0,mock_helper_stub.A)(e,r)}};class Mock{constructor(e=null,o=null){const t=this.constructor.mockOf;(0,core_define_property.A)(this,"__ngMocks",!0),(0,core_define_property.A)(this,"__ngMocksInjector",e),(0,core_define_property.A)(this,"__ngMocksCtor",this.constructor);for(const e of this.__ngMocksConfig.queryScanKeys||[])(0,core_define_property.A)(this,`__ngMocksVcr_${e}`,void 0);for(const e of this.__ngMocksConfig.hostBindings||[])helper_mock_service.A.mock(this,e,"get"),helper_mock_service.A.mock(this,e,"set");for(const e of this.__ngMocksConfig.hostListeners||[])helper_mock_service.A.mock(this,e);func_is_mock(this)&&(applyNgValueAccessor(this,o),applyOutputs(this),applyPrototype(this,Object.getPrototypeOf(this)),applyMethods(this,t.prototype),applyProps(this,t.prototype)),Object.setPrototypeOf(this,t.prototype),applyOverrides(this,t,null!=e?e:void 0)}}(0,core_define_property.A)(Mock,"parameters",[[core_.Injector,new core_.Optional],[core_form.NgControl||(()=>{}),new core_.Optional,new core_.Self]]);class LegacyControlValueAccessor extends Mock{__simulateChange(){}__simulateTouch(){}__simulateValidatorChange(){}}var func_directive_io_build=__webpack_require__(439);const decorate_inputs=(e,o,t)=>{if(o)for(const r of o){const{name:o,alias:n,required:s}=(0,func_directive_io_parse.A)(r);t&&-1!==t.indexOf(o)||(0,core_.Input)((0,func_directive_io_build.A)({name:o,alias:n,required:s},!0))(e.prototype,o)}},decorate_mock=(e,o,t={})=>{(0,core_define_property.A)(e,"mockOf",o),(0,core_define_property.A)(e,"nameConstructor",(0,func_get_name.A)(e)),(0,core_define_property.A)(e,"name",`MockOf${(0,func_get_name.A)(o)}`,!0);const r=ng_mocks_universe.A.getConfigMock().has(o)?Object.assign(Object.assign({},t),{config:Object.assign(Object.assign({},ng_mocks_universe.A.getConfigMock().get(o)),t.config)}):t;(0,core_define_property.A)(e.prototype,"__ngMocksConfig",r)},decorate_outputs=(e,o)=>{if(o)for(const t of o){const{name:o,alias:r,required:n}=(0,func_directive_io_parse.A)(t);(0,core_.Output)((0,func_directive_io_build.A)({name:o,alias:r,required:n},!0))(e.prototype,o)}},map={ContentChild:core_.ContentChild,ContentChildren:core_.ContentChildren,ViewChild:core_.ViewChild,ViewChildren:core_.ViewChildren},isInternalKey=e=>0===e.indexOf("__mock"),cloneVcrQuery=e=>Object.assign(Object.assign({},e),{ngMetadataName:e.ngMetadataName,read:core_.ViewContainerRef}),generateFinalQueries=e=>{const o=[],t=[];for(const r of Object.keys(e)){const n=e[r];o.push([r,n]),n.isViewQuery||isInternalKey(r)||(t.push(r),o.push([`__ngMocksVcr_${r}`,cloneVcrQuery(n)]))}return[o,t]},decorate_queries=(e,o)=>{if(!o)return[];const[t,r]=generateFinalQueries(o);for(const[o,r]of t)r.ngMetadataName&&(0,map[r.ngMetadataName])(r.selector,r)(e.prototype,o);return r};var func_extract_forward_ref=__webpack_require__(285);const to_existing_provider=(e,o)=>({provide:e,useExisting:o}),to_factory_provider=(e,o)=>({multi:!0,provide:e,useFactory:o}),processTokens=(e,o)=>{const t=(0,func_get_type.A)(o);return core_form.NG_VALIDATORS&&t===core_form.NG_VALIDATORS?to_factory_provider(t,(()=>new MockValidatorProxy(e))):core_form.NG_ASYNC_VALIDATORS&&t===core_form.NG_ASYNC_VALIDATORS?to_factory_provider(t,(()=>new MockAsyncValidatorProxy(e))):core_form.NG_VALUE_ACCESSOR&&t===core_form.NG_VALUE_ACCESSOR?to_factory_provider(t,(()=>new MockControlValueAccessorProxy(e))):void 0},processOwnUseExisting=(e,o,t)=>{const r=(0,func_get_type.A)(t);if(r!==core_form.NgControl&&r!==core_form.FormControlDirective)return t!==r&&(0,func_extract_forward_ref.A)(t.useExisting)===e?to_existing_provider(r,o):void 0},processProvider=(e,o,t,r)=>{const n=processTokens(o,t);if(n)return n;return processOwnUseExisting(e,o,t)||helper_mock_service.A.resolveProvider(t,r)},clone_providers=(e,o,t,r)=>{const n=[];let s;for(const c of(0,core_helpers.Bq)(t||[])){(0,func_get_type.A)(c)===core_form.NG_VALUE_ACCESSOR&&(s=!1);const t=processProvider(e,o,c,r);t&&n.push(t)}return{providers:n,setControlValueAccessor:s}},buildConfig=(e,o,t)=>({config:ng_mocks_universe.A.config.get(e),outputs:o.outputs,queryScanKeys:[],setControlValueAccessor:t}),decorate_declaration=(e,o,t,r)=>{const n=ng_mocks_universe.A.config.has("mockNgDefResolver");n||ng_mocks_universe.A.config.set("mockNgDefResolver",new core_def_stack);const s=Object.assign({},r);if(void 0!==t.exportAs&&(s.exportAs=t.exportAs),void 0!==t.selector&&(s.selector=t.selector),void 0!==t.standalone&&(s.standalone=t.standalone),t.standalone&&t.imports){const[,{imports:e}]=mock_ng_def({imports:t.imports,skipExports:!0});(null==e?void 0:e.length)&&(s.imports=e)}if(t.hostDirectives){const[,{hostDirectives:e}]=mock_ng_def({hostDirectives:t.hostDirectives,skipExports:!0});(null==e?void 0:e.length)&&(s.hostDirectives=e)}const{setControlValueAccessor:c,providers:_}=clone_providers(e,o,t.providers||[],ng_mocks_universe.A.config.get("mockNgDefResolver"));_.push(to_existing_provider(e,o)),s.providers=_;const{providers:i}=clone_providers(e,o,t.viewProviders||[],ng_mocks_universe.A.config.get("mockNgDefResolver"));i.length>0&&(s.viewProviders=i);const a=buildConfig(e,t,null!=c?c:-1!==helper_mock_service.A.extractMethodsFromPrototype(e.prototype).indexOf("writeValue"));decorate_mock(o,e,a),t.queries&&decorate_inputs(o,t.inputs,Object.keys(t.queries)),decorate_outputs(o,t.outputs),a.queryScanKeys=decorate_queries(o,t.queries),a.hostBindings=[];for(const[e]of t.hostBindings||[])-1===a.hostBindings.indexOf(e)&&a.hostBindings.push(e);a.hostListeners=[];for(const[e]of t.hostListeners||[])-1===a.hostListeners.indexOf(e)&&a.hostListeners.push(e);return n||ng_mocks_universe.A.config.delete("mockNgDefResolver"),s},getType=e=>(0,func_is_ng_def.p)(e,"p")?"pipe":(0,func_is_ng_def.p)(e,"d")?"directive":(0,func_is_ng_def.p)(e,"c")?"component":(0,func_is_ng_def.p)(e,"m")?"module":(0,func_is_ng_def.p)(e,"i")?"service":(0,func_is_ng_def.p)(e,"t")?"token":"",func_import_exists=(e,o)=>{if(null==e)throw new Error(`null / undefined has been passed into ${o}. Please check that its import is correct.`);if("MockPipe"===o&&(0,func_is_ng_def.p)(e,"p"))return;if("MockDirective"===o&&(0,func_is_ng_def.p)(e,"d"))return;if("MockComponent"===o&&(0,func_is_ng_def.p)(e,"c"))return;if("MockModule"===o&&(0,func_is_ng_def.p)(e,"m"))return;const t=getType(e);if(t&&"MockPipe"===o)throw new Error(`${o} accepts pipes, whereas ${(0,func_get_name.A)(e)} is a ${t}.`);if(t&&"MockDirective"===o)throw new Error(`${o} accepts directives, whereas ${(0,func_get_name.A)(e)} is a ${t}.`);if(t&&"MockComponent"===o)throw new Error(`${o} accepts components, whereas ${(0,func_get_name.A)(e)} is a ${t}.`);if(t&&"MockModule"===o)throw new Error(`${o} accepts modules, whereas ${(0,func_get_name.A)(e)} is a ${t}.`)};function isMockNgDef(e,o){return!!e.mockOf&&(!o||(0,func_is_ng_def.p)(e.mockOf,o))}const func_get_last_fixture=()=>{const e=(0,testing_.getTestBed)()._activeFixtures;return e[e.length-1]},return_cached_mock=e=>{let o;try{o=func_get_last_fixture().debugElement.injector.get(core_tokens.en).get(e)}catch(e){}return o||(o=ng_mocks_universe.A.cacheDeclarations.get(e)),e.__ngMocksResolutions&&ng_mocks_universe.A.config.has("mockNgDefResolver")&&ng_mocks_universe.A.config.get("mockNgDefResolver").merge(e.__ngMocksResolutions),o},get_mock=(e,o,t,r,n,s)=>{if(func_import_exists(e,t),isMockNgDef(e,o))return e;if(ng_mocks_universe.A.flags.has(r)&&ng_mocks_universe.A.cacheDeclarations.has(e))return return_cached_mock(e);const c=ng_mocks_universe.A.config.has("ngMocksDepsResolution");c||ng_mocks_universe.A.config.set("ngMocksDepsResolution",new Map);const _=(0,core_helpers.He)(n);return s(e,_),ng_mocks_universe.A.flags.has(r)&&ng_mocks_universe.A.cacheDeclarations.set(e,_),c||ng_mocks_universe.A.config.delete("ngMocksDepsResolution"),_},vcrArgs={read:core_.ViewContainerRef,static:!1},trArgs={read:core_.TemplateRef,static:!1},viewChildTemplate=(e,o)=>`
`,isTemplateRefQuery=e=>!(e.isViewQuery||e.read&&e.read!==core_.TemplateRef||"string"!=typeof e.selector&&!e.read),generate_template=e=>{const o=[""];if(!e)return o.join("");for(const t of Object.keys(e)){const r=e[t];if(0!==t.indexOf("__mock")&&isTemplateRefQuery(r)){if("string"==typeof r.selector){const t=r.selector.replace(new RegExp("\\W","mg"),"_");e[`__vcrIf_key_${t}`]=new core_.ViewChild(`ngIf_key_${t}`,vcrArgs),e[`__trIf_key_${t}`]=new core_.ViewChild(`ngIf_key_${t}`,trArgs),e[`__mockView_key_${t}`]=new core_.ViewChild(`key_${t}`,vcrArgs),e[`__mockTpl_key_${t}`]=r,o.push(viewChildTemplate(t,"key"))}e[`__vcrIf_prop_${t}`]=new core_.ViewChild(`ngIf_prop_${t}`,vcrArgs),e[`__trIf_prop_${t}`]=new core_.ViewChild(`ngIf_prop_${t}`,trArgs),e[`__mockView_prop_${t}`]=new core_.ViewChild(`prop_${t}`,vcrArgs),o.push(viewChildTemplate(t,"prop"))}}return o.join("")},get_key=e=>{if("string"==typeof e)return["key",`__mockTpl_key_${e}`,e,void 0];const[o,...t]=e;return["prop",o,o,t.length>0?t:void 0]},mixRenderPrepareVcr=(e,o,t,r)=>{const n=e[`__vcrIf_${o}_${t}`],s=e[`__trIf_${o}_${t}`];return n&&s&&!e[`ngMocksRender_${o}_${t}`]&&(e[`ngMocksRender_${o}_${t}`]=n.createEmbeddedView(s,{}),r.detectChanges()),e[`__mockView_${o}_${t}`]},mixRenderReorderViews=(e,o,t)=>{for(const e of o.splice(t+1))e.destroy();let r=0;for(const t of o)t&&(e.move(t,r),r+=1)},mixRenderApplyContext=(e,o)=>{for(const o of Object.keys(e.context))e.context[o]=void 0;for(const t of Object.keys(o))e.context[t]=o[t];e.markForCheck()},mixRenderHandleViews=(e,o,t,r,n,s)=>{let c=-1;for(const o of t)if(c+=1,r[c]=r[c]||void 0,(!n||-1!==n.indexOf(c))&&o){if(!(o instanceof core_.TemplateRef))throw new Error("Cannot find TemplateRef");r[c]||(r[c]=e.createEmbeddedView(o,{})),mixRenderApplyContext(r[c],s)}return o.detectChanges(),c},mixRender=(e,o)=>{(0,core_define_property.A)(e,"__render",((t,r,n)=>{const[s,c,_,i]=get_key(t),a=mixRenderPrepareVcr(e,s,_,o);if(!a)return;const l=e[c],p=l instanceof core_.QueryList?l.toArray():[l],u=e[`ngMocksRender_${s}_${_}_views`]||[],d=mixRenderHandleViews(a,o,p,u,i,Object.assign(Object.assign({},n),{$implicit:r}));mixRenderReorderViews(a,u,d),e[`ngMocksRender_${s}_${_}_views`]=u,o.detectChanges()}))},mixHideHandler=(e,o,t,r)=>{const n=e[`ngMocksRender_${o}_${t}_views`];let s=-1;for(const e of n)s+=1,r&&-1===r.indexOf(s)||!e||(e.destroy(),n[s]=void 0)},mixHide=(e,o)=>{(0,core_define_property.A)(e,"__hide",(t=>{const[r,,n,s]=get_key(t);e[`ngMocksRender_${r}_${n}`]&&(mixHideHandler(e,r,n,s),s||(e[`ngMocksRender_${r}_${n}`].destroy(),e[`ngMocksRender_${r}_${n}`]=void 0),o.detectChanges())}))};class ComponentMockBase extends LegacyControlValueAccessor{constructor(e,o,t){super(e,o),func_is_mock(this)&&(mixRender(this,t),mixHide(this,t))}ngAfterViewInit(){const e=this.__ngMocksConfig.config;if(!this.__rendered&&e&&e.render){for(const o of Object.keys(e.render)){const{$implicit:t,variables:r}=!0===e.render[o]?{$implicit:void 0,variables:{}}:e.render[o];this.__render(o,t,r)}this.__rendered=!0}}}(0,core_define_property.A)(ComponentMockBase,"parameters",[[core_.Injector],[core_form.NgControl||(()=>{}),new core_.Optional,new core_.Self],[core_.ChangeDetectorRef]]);const decorateClass=(e,o)=>{const t=core_reflect_directive_resolve(e);(0,core_.Component)(decorate_declaration(e,o,t,{template:generate_template(t.queries)}))(o)};function MockComponents(...e){return e.map(MockComponent)}function MockComponent(e){return get_mock(e,"c","MockComponent","cacheComponent",ComponentMockBase,decorateClass)}class DirectiveMockBase extends LegacyControlValueAccessor{constructor(e,o,t,r,n=null,s=null){super(e,o),this.__ngMocksInstall(r,t,n,s)}ngOnInit(){const e=this.__ngMocksConfig.config;if(null==e?void 0:e.render){const{$implicit:o,variables:t}=!0===e.render?{$implicit:void 0,variables:{}}:e.render;this.__render(o,t)}}__ngMocksInstall(e,o,t,r){(0,core_define_property.A)(this,"__element",t),(0,core_define_property.A)(this,"__template",r),(0,core_define_property.A)(this,"__viewContainer",e),(0,core_define_property.A)(this,"__vcr",e),(0,core_define_property.A)(this,"__cdr",o),(0,core_define_property.A)(this,"__isStructural",r&&e),(0,core_define_property.A)(this,"__render",((t,n)=>{e&&r&&(e.clear(),e.createEmbeddedView(r,Object.assign(Object.assign({},n),{$implicit:t})),o.detectChanges())}))}}(0,core_define_property.A)(DirectiveMockBase,"parameters",[[core_.Injector],[core_form.NgControl||(()=>{}),new core_.Optional,new core_.Self],[core_.ChangeDetectorRef],[core_.ViewContainerRef],[core_.ElementRef,new core_.Optional,new core_.Self],[core_.TemplateRef,new core_.Optional,new core_.Self]]);const mock_directive_decorateClass=(e,o)=>{const t=core_reflect_directive_resolve(e),r=decorate_declaration(e,o,t,{});(0,core_.Directive)(r)(o)};function MockDirectives(...e){return e.map(MockDirective)}function MockDirective(e){return get_mock(e,"d","MockDirective","cacheDirective",DirectiveMockBase,mock_directive_decorateClass)}const core_reflect_pipe_resolve=e=>core_reflect_body_catch((e=>{const o=(0,collect_declarations.A)(e);if(o.Pipe)return o.Pipe;throw new Error("Cannot resolve declarations")}))(e);function MockPipes(...e){return e.map((e=>MockPipe(e,void 0)))}const getMockClass=(e,o)=>{var t;const r=ng_mocks_universe.A.config.get(e),n=null!=o?o:null===(t=null==r?void 0:r.defValue)||void 0===t?void 0:t.transform,s=(0,core_helpers.He)(Mock);return(0,core_.Pipe)(core_reflect_pipe_resolve(e))(s),decorate_mock(s,e,{init:e=>{n&&(e.transform=n),e.transform||helper_mock_service.A.mock(e,"transform",`${(0,func_get_name.A)(e)}.transform`)},transform:n}),s};function MockPipe(e,o){if(func_import_exists(e,"MockPipe"),isMockNgDef(e,"p"))return e;if(ng_mocks_universe.A.flags.has("cachePipe")&&ng_mocks_universe.A.cacheDeclarations.has(e))return return_cached_mock(e);const t=getMockClass(e,o);return ng_mocks_universe.A.flags.has("cachePipe")&&ng_mocks_universe.A.cacheDeclarations.set(e,t),t}const flagMock=e=>"mock"===e&&ng_mocks_universe.A.flags.has("skipMock"),flagKeep=e=>"keep"===e&&!ng_mocks_universe.A.flags.has("skipMock"),flagReplace=e=>"replace"===e&&!ng_mocks_universe.A.flags.has("skipMock"),flagNever=e=>-1!==core_config.A.neverMockModule.indexOf((0,func_get_name.A)(e))&&!ng_mocks_universe.A.flags.has("skipMock"),preProcessFlags=e=>{let o=!1,t=!0;ng_mocks_universe.A.flags.has("hasRootModule")?t=!1:ng_mocks_universe.A.flags.add("hasRootModule");const r=ng_mocks_universe.A.getResolution(e);return flagMock(r)&&(o=!0,ng_mocks_universe.A.flags.delete("skipMock")),flagNever(e)&&(o=!0,ng_mocks_universe.A.flags.add("skipMock")),t||!flagKeep(r)&&!flagReplace(r)||(o=!0,ng_mocks_universe.A.flags.add("skipMock")),{isRootModule:t,toggleSkipMockFlag:o}},postProcessFlags=({isRootModule:e,toggleSkipMockFlag:o})=>{o&&ng_mocks_universe.A.flags.has("skipMock")?ng_mocks_universe.A.flags.delete("skipMock"):o&&!ng_mocks_universe.A.flags.has("skipMock")&&ng_mocks_universe.A.flags.add("skipMock"),e&&ng_mocks_universe.A.flags.delete("hasRootModule")},extractModuleAndProviders=e=>{let o,t;return(0,func_is_ng_module_def_with_providers.h)(e)?(o=e.ngModule,e.providers&&(t=e.providers)):o=e,{ngModule:o,ngModuleProviders:t}},getExistingMockModule=(e,o)=>{var t;if(isMockNgDef(e,"m"))return e;if(ng_mocks_universe.A.flags.has("cacheModule")&&ng_mocks_universe.A.cacheDeclarations.has(e))return return_cached_mock(e);if(!o&&"mock"!==(null===(t=ng_mocks_universe.A.config.get("ngMocksDepsResolution"))||void 0===t?void 0:t.get(e))&&ng_mocks_universe.A.hasBuildDeclaration(e)){const o=ng_mocks_universe.A.getBuildDeclaration(e);if((0,func_is_ng_def.p)(o,"m")&&o!==e)return o}},detectMockModule=(e,o)=>{const[t,r,n]=o?[!1]:mock_ng_def(core_reflect_module_resolve(e),e);if(n&&(0,core_define_property.A)(e,"__ngMocksResolutions",n),t){const o=ng_mocks_universe.A.flags.has("skipMock")?e:Mock,t=(0,core_helpers.He)(o);return(0,core_.NgModule)(r)(t),decorate_mock(t,e),t}return o||e},getMockProviders=e=>{if(e){const[o,t]=mock_ng_def({providers:e,skipExports:!0});return o?t.providers:e}},generateReturn=(e,o,t,r,n)=>r===o&&n===t?e:(0,func_is_ng_module_def_with_providers.h)(e)?Object.assign({ngModule:r},n?{providers:n}:{}):r;function MockModule(e){var o;func_import_exists(e,"MockModule");const{ngModule:t,ngModuleProviders:r}=extractModuleAndProviders(e),n=preProcessFlags(t);try{const s=detectMockModule(t,getExistingMockModule(t,n.isRootModule));ng_mocks_universe.A.flags.has("cacheModule")&&ng_mocks_universe.A.cacheDeclarations.set(t,s),ng_mocks_universe.A.flags.has("skipMock")&&(null===(o=ng_mocks_universe.A.config.get("ngMocksDepsSkip"))||void 0===o||o.add(s));const c=getMockProviders(r);return generateReturn(e,t,r,s,c)}finally{postProcessFlags(n)}}const processDefMap=[["c",MockComponent],["d",MockDirective],["p",MockPipe]],processDef=e=>{if((0,func_is_ng_def.p)(e,"m")||(0,func_is_ng_module_def_with_providers.h)(e))return MockModule(e);if(ng_mocks_universe.A.hasBuildDeclaration(e))return ng_mocks_universe.A.getBuildDeclaration(e);if(ng_mocks_universe.A.flags.has("skipMock")&&"mock"!==ng_mocks_universe.A.getResolution(e))return e;for(const[o,t]of processDefMap)if((0,func_is_ng_def.p)(e,o))return t(e)},createResolveProvider=(e,o)=>t=>helper_mock_service.A.resolveProvider(t,e,o),createResolveWithProviders=(e,o)=>(0,func_is_ng_module_def_with_providers.h)(o)&&(0,func_is_ng_module_def_with_providers.h)(e),createResolveExisting=(e,o,t)=>{const r=o.get(e);return e!==r&&t(),r},createResolveExcluded=(e,o,t)=>{o.set(e,void 0),t()},createResolve=(e,o)=>t=>{var r;if(e.has(t))return createResolveExisting(t,e,o);const n=(0,func_get_type.A)(t);if(ng_mocks_universe.A.isExcludedDef(n))return createResolveExcluded(t,e,o);ng_mocks_universe.A.touches.add(n);const s=processDef(t);return createResolveWithProviders(t,s)&&e.set(t.ngModule,s.ngModule),ng_mocks_universe.A.flags.has("skipMock")&&(null===(r=ng_mocks_universe.A.config.get("ngMocksDepsSkip"))||void 0===r||r.add(s)),e.set(t,s),o(s!==t),s},create_resolvers=(e,o)=>({resolve:createResolve(o,e),resolveProvider:createResolveProvider(o,e)}),mark_providers=e=>{for(const o of(0,core_helpers.Bq)(null!=e?e:[])){const e=(0,func_get_type.A)(o);mark_exported(e)}},flatToExisting=(e,o)=>(0,core_helpers.Bq)(e).map(o).filter((e=>!!e)),configureProcessMetaKeys=(e,o)=>[["declarations",e],["hostDirectives",o=>{const t=(0,func_get_type.A)(o),r=e(t);return r===t?o:o==t?r:Object.assign(Object.assign({},o),{directive:r})}],["imports",e],["entryComponents",e],["bootstrap",e],["providers",o],["viewProviders",o],["exports",e],["schemas",e=>e]],processMeta=(e,o,t)=>{var r;const n={},s=configureProcessMetaKeys(o,t),c=ng_mocks_universe.A.flags.has("cachePipe");c||ng_mocks_universe.A.flags.add("cachePipe");for(const[o,t]of s)(null===(r=e[o])||void 0===r?void 0:r.length)&&(n[o]=flatToExisting(e[o],t));return e.skipMarkProviders||(mark_providers(n.providers),mark_providers(n.viewProviders)),c||ng_mocks_universe.A.flags.delete("cachePipe"),n},resolveDefForExport=(e,o,t,r)=>{const n=ng_mocks_universe.A.config.get(r)||{},s=(0,func_get_type.A)(e),c=o(s);if(!c)return;const _=ng_mocks_universe.A.config.get(s);return(null==_?void 0:_.export)&&r&&!n.export&&ng_mocks_universe.A.config.set(r,Object.assign(Object.assign({},n),{export:!0})),!t||n.exportAll||(null==_?void 0:_.export)?(mark_exported(s,r),c):void 0},skipAddExports=(e,o)=>!e||!!o.exports&&-1!==o.exports.indexOf(e),addExports=(e,o,t,r,n)=>{const s=ng_mocks_universe.A.flags.has("skipMock")||ng_mocks_universe.A.flags.has("correctModuleExports");for(const c of(0,core_helpers.Bq)([t.imports||[],t.declarations||[]])){const t=resolveDefForExport(c,e,s,n);skipAddExports(t,r)||(o(),r.exports=r.exports||[],r.exports.push(t))}},mock_ng_def=(e,o)=>{const t=ng_mocks_universe.A.config.has("mockNgDefResolver");t||ng_mocks_universe.A.config.set("mockNgDefResolver",new core_def_stack),ng_mocks_universe.A.config.get("mockNgDefResolver").push();let r=!ng_mocks_universe.A.flags.has("skipMock");const n=(e=!0)=>{r=r||e},{resolve:s,resolveProvider:c}=create_resolvers(n,ng_mocks_universe.A.config.get("mockNgDefResolver")),_=processMeta(e,s,c);e.skipExports||addExports(s,n,e,_,o);for(const e of o&&_.exports?(0,core_helpers.Bq)(_.exports):[])mark_exported(e,o);const i=ng_mocks_universe.A.config.get("mockNgDefResolver").pop();return t||ng_mocks_universe.A.config.delete("mockNgDefResolver"),[r,_,i]},get_override_def=e=>{if(!e)return;const o=ng_mocks_universe.A.flags.has("skipMock");o||ng_mocks_universe.A.flags.add("skipMock");const[t,r]=mock_ng_def(e);return o||ng_mocks_universe.A.flags.delete("skipMock"),t?r:void 0},skip_override=(e,o,t,r)=>!!ng_mocks_universe.A.cacheDeclarations.has(r)||!(!e.has(t)||r!==o.get(t)),create_ng_mocks_overrides_token=(e,o)=>{const t=new Map;for(const r of(0,core_helpers.LG)(ng_mocks_universe.A.touches)){const n=r,s=ng_mocks_universe.A.getBuildDeclaration(n)||n;if(skip_override(e,o,n,s))continue;const c=core_reflect_meta(s),_=get_override_def(c);if(!_)continue;const i={};for(const e of Object.keys(_))i[e]=c[e];t.set(s,[{set:_},{set:i}])}return{provide:core_tokens.So,useValue:t}},create_ng_mocks_token=()=>{const e=new Map;for(const[o,t]of[...(0,core_helpers.Nn)(ng_mocks_universe.A.builtProviders),...(0,core_helpers.Nn)(ng_mocks_universe.A.builtDeclarations),...(0,core_helpers.Nn)(ng_mocks_universe.A.cacheDeclarations),...(0,core_helpers.Nn)(ng_mocks_universe.A.cacheProviders)])e.has(o)||e.set(o,t);return{provide:core_tokens.en,useValue:e}},create_ng_mocks_touches_token=()=>{const e=new Set;for(const o of(0,core_helpers.LG)(ng_mocks_universe.A.touches)){const t=o;let r=ng_mocks_universe.A.getBuildDeclaration(t);void 0===r&&(r=t),e.add(t),e.add(r)}return{provide:core_tokens.Em,useValue:e}};var helper_create_clone=__webpack_require__(365);class EntryComponentsModule{constructor(e,o){if(!o)return;const t=o.resolveComponentFactory;o.resolveComponentFactory=(0,helper_create_clone.A)(t,void 0,void 0,((r,...n)=>{var s;return t.apply(o,[null!==(s=e.get(r))&&void 0!==s?s:r,...n])}))}}(0,core_define_property.A)(EntryComponentsModule,"parameters",[[core_tokens.en],[core_.ComponentFactoryResolver,new core_.Optional]]);class IvyModule{}(0,core_.NgModule)()(IvyModule);const handle_entry_components=e=>{const o=[];for(const t of e.declarations)(0,func_is_ng_def.p)(t,"c")&&o.push(t);const t=(0,core_helpers.He)(EntryComponentsModule);(0,core_.NgModule)({entryComponents:IvyModule.ɵmod?[]:o})(t),e.imports.push(t)};var helper_use_factory=__webpack_require__(465),core_reflect_parameters_resolve=__webpack_require__(749),common_x=e=>{var o={};return __webpack_require__.d(o,e),o},common_y=e=>()=>e;const common_namespaceObject=common_x({DOCUMENT:()=>__WEBPACK_EXTERNAL_MODULE__angular_common_d12e0fe1__.DOCUMENT}),skipResolution=e=>{const o=ng_mocks_universe.A.getResolution(e);return"keep"===o||"exclude"===o||"mock"!==o&&void 0},skipSystem=e=>{if(!e||e===common_namespaceObject.DOCUMENT||ng_mocks_universe.A.touches.has(e))return!0;const o=skipResolution(e);return void 0!==o?o:"function"==typeof e&&-1!==core_config.A.neverMockProvidedFunction.indexOf(e.name)||!(!(0,func_is_ng_injection_token.S)(e)||-1===core_config.A.neverMockToken.indexOf(e.toString()))},skip_dep=e=>{if(skipSystem(e))return!0;const o=core_reflect_provided_in(e);return!("function"!=typeof e||o&&"platform"!==o)},add_def_to_root_provider_parameters=(e,o,t)=>{skip_dep(t)||!o.has(core_tokens.gG)&&ng_mocks_universe.A.config.get("ngMocksDepsSkip").has(t)||e.add(t)},check_root_provider_dependency=(e,o,t)=>{"function"==typeof e&&-1===t.indexOf(e)&&(t.push(e),o.push(e))},extract_dep=e=>{if(!e)return;let o;for(const t of e)t&&"object"==typeof t&&t.token&&(o=t.token),o||!t||"object"==typeof t&&t.ngMetadataName||(o=t);return(0,func_extract_forward_ref.A)(o)},get_root_providers_data=()=>{const e=[(0,core_helpers.LG)(ng_mocks_universe.A.config.get("ngMocksDepsSkip")),(0,core_helpers.LG)(ng_mocks_universe.A.config.get("ngMocksDeps")),(0,core_helpers.LG)(ng_mocks_universe.A.touches)];return{buckets:e,touched:[].concat(...e)}},handle_provided_in_dependency=e=>{if(ng_mocks_universe.A.touches.has(e))return;const o=core_reflect_provided_in(e);o&&ng_mocks_universe.A.config.get("ngMocksDepsSkip").has(o)&&ng_mocks_universe.A.config.get("ngMocksDepsSkip").add(e)},skip_root_provider_dependency=e=>!!skip_dep(e)||ng_mocks_universe.A.config.get("ngMocksDepsSkip").has(e),get_root_provider_parameters=e=>{const o=new Set,{buckets:t,touched:r}=get_root_providers_data();for(const n of t)for(const t of n){add_def_to_root_provider_parameters(o,e,t);for(const s of(0,core_reflect_parameters_resolve.A)(t)){const c=extract_dep(s);handle_provided_in_dependency(c),skip_root_provider_dependency(c)||(check_root_provider_dependency(c,r,n),e.has(core_tokens.gG)||!ng_mocks_universe.A.config.get("ngMocksDepsSkip").has(t)?o.add(c):ng_mocks_universe.A.config.get("ngMocksDepsSkip").add(c))}}return o},handle_root_providers=(e,{keepDef:o,mockDef:t},r)=>{const n=o.has(core_tokens.gG)?new Set:get_root_provider_parameters(t);if(n.size>0)for(const o of(0,core_helpers.LG)(n)){const t=(0,helper_resolve_provider.A)(o,r);if(t)e.providers.push(t);else if((0,func_is_ng_injection_token.S)(o)){const t=ng_mocks_universe.A.config.has("ngMocksMulti")&&ng_mocks_universe.A.config.get("ngMocksMulti").has(o);e.providers.push((0,helper_use_factory.A)(o,(()=>t?[]:void 0)))}}},init_module=(e,o)=>{var t;const r=null!==(t=ng_mocks_universe.A.config.get("mockNgDefResolver").get(e))&&void 0!==t?t:ng_mocks_universe.A.getBuildDeclaration(e),n=o.has(e)?o.get(e):void 0;return n?{ngModule:r,providers:n}:r},skipDef=e=>ng_mocks_universe.A.touches.has(e)||(0,func_is_ng_def.p)(e)||(0,func_is_ng_injection_token.S)(e)||"string"==typeof e,handleDef=({imports:e,declarations:o,providers:t},r,n)=>{skipDef(r)||error_jest_mock(r);let s=!1;if((0,func_is_ng_def.p)(r,"m")){const o=init_module(r,n);if(e.push(o),s=!0,"object"==typeof o&&o.providers)for(const e of(0,core_helpers.Bq)(o.providers))ng_mocks_universe.A.touches.add((0,func_get_type.A)(e))}if(((0,func_is_ng_def.p)(r,"c")||(0,func_is_ng_def.p)(r,"d")||(0,func_is_ng_def.p)(r,"p"))&&((isStandalone(r)?e:o).push(ng_mocks_universe.A.getBuildDeclaration(r)),s=!0),(0,func_is_ng_def.p)(r,"i")||!(0,func_is_ng_def.p)(r)){const e=ng_mocks_universe.A.builtProviders.get(r);e&&"string"!=typeof e&&!1===(0,func_is_ng_def.p)(e,"t")&&(t.push(e),s=!0)}s&&(mark_exported(r),ng_mocks_universe.A.touches.add(r))},isExportedOnRoot=(e,o,t)=>{const r=o.get(e),n=t.get(e)||{};if((0,func_is_ng_def.p)(e,"m")&&n.onRoot)return e;if(!(null==r?void 0:r.exported))return e;for(const e of(0,core_helpers.LG)(r.exported)){const r=isExportedOnRoot(e,o,t);if(r)return r}},moveModulesUp=(e,o)=>{const t=(0,func_is_ng_def.p)(e,"m"),r=(0,func_is_ng_def.p)(o,"m");return t&&r?0:t?-1:r?1:0},init_ng_modules=({configDefault:e,keepDef:o,mockDef:t,replaceDef:r},n)=>{const s={imports:[],declarations:[],providers:[]},c=[],_=[],i=[...(0,core_helpers.LG)(t),...(0,core_helpers.LG)(o),...(0,core_helpers.LG)(r)];i.sort(moveModulesUp);for(const o of i){const t=(0,func_is_ng_def.p)(o,"m")&&n.has(o)?o:isExportedOnRoot(o,ng_mocks_universe.A.configInstance,ng_mocks_universe.A.config);if(!t||-1!==c.indexOf(t))continue;const r=ng_mocks_universe.A.config.get(t)||{__set:!0};c.push(t),r.onRoot=r.onRoot||!r.dependency,r.__set&&(r.__set=void 0,ng_mocks_universe.A.config.set(t,r)),(0,func_is_ng_def.p)(t,"m")&&r.onRoot?handleDef(s,t,n):r.dependency||!r.export||!(0,func_is_ng_def.p)(t,"i")&&(0,func_is_ng_def.p)(t)?!r.dependency&&r.export?handleDef(s,t,n):ng_mocks_universe.A.touches.has(t)||r.dependency?!r.dependency||!e.dependency||"root"===core_reflect_provided_in(t)||"object"==typeof t&&t.__ngMocksSkip||_.push(t):handleDef(s,t,n):(handleDef(s,t,n),mark_providers([t]))}const a=ng_mocks_universe.A.global.get("flags");for(const e of _){if(ng_mocks_universe.A.touches.has(e))continue;const o=[`MockBuilder has found a missing dependency: ${(0,func_get_name.A)(e)}.`,"It means no module provides it.",'Please, use the "export" flag if you want to add it explicitly.',"https://ng-mocks.sudo.eu/api/MockBuilder#export-flag"].join(" ");if("warn"===a.onMockBuilderMissingDependency)console.warn(o);else if("throw"===a.onMockBuilderMissingDependency)throw new Error(o)}return s},funcExtractDeps=(e,o,t=!1)=>{const r=(0,collect_declarations.A)(e),n=getNgType(e);if(!n||"Injectable"===n)return o;const s=r[n];for(const e of core_config.A.dependencies)if(s[e])for(const r of(0,core_helpers.Bq)(s[e])){const e=(0,func_get_type.A)(r);o.has(e)||(o.add(e),t&&funcExtractDeps(e,o))}return o},init_exclude_def=e=>{const o=ng_mocks_universe.A.builtDeclarations,t=ng_mocks_universe.A.builtProviders,r=ng_mocks_universe.A.config.get("ngMocksDepsResolution");for(const n of(0,core_helpers.LG)(e))o.set(n,null),t.set(n,null),r.set(n,"exclude")},init_keep_def=(e,o)=>{const t=new Set,r=ng_mocks_universe.A.builtDeclarations,n=ng_mocks_universe.A.builtProviders,s=ng_mocks_universe.A.config.get("ngMocksDepsResolution");for(const c of(0,core_helpers.LG)(e))r.set(c,c),n.set(c,c),s.set(c,"keep"),o.get(c).shallow&&funcExtractDeps(c,t);return t};var mock_provider=__webpack_require__(415);const createInstance=(e,o,t)=>t.precise?o:(0,mock_helper_stub.A)(e,o),try_mock_provider=(e,o)=>{if((0,func_is_ng_def.p)(e,"i")&&o.has(e)){const t=ng_mocks_universe.A.config.get(e),r=o.get(e);ng_mocks_universe.A.builtProviders.set(e,(0,helper_use_factory.A)(e,void 0,(e=>createInstance(e,r,t))))}else(0,func_is_ng_def.p)(e,"i")&&ng_mocks_universe.A.builtProviders.set(e,(0,mock_provider.A)(e,!0));if(!(0,func_is_ng_def.p)(e)&&o.has(e)){const t=o.get(e);ng_mocks_universe.A.builtProviders.set(e,(0,helper_use_factory.A)(e,void 0,(()=>t)))}else(0,func_is_ng_def.p)(e)||ng_mocks_universe.A.builtProviders.set(e,(0,mock_provider.A)(e,!0))},init_mock_declarations=(e,o)=>{const t=ng_mocks_universe.A.builtDeclarations,r=ng_mocks_universe.A.config.get("ngMocksDepsResolution");for(const n of(0,core_helpers.LG)(e)){const e=!ng_mocks_universe.A.touches.has(n);r.set(n,"mock"),t.set(n,void 0),try_mock_provider(n,o),e&&ng_mocks_universe.A.touches.delete(n)}},try_mock_declaration=e=>{void 0===ng_mocks_universe.A.builtDeclarations.get(e)&&((0,func_is_ng_def.p)(e,"c")&&ng_mocks_universe.A.builtDeclarations.set(e,MockComponent(e)),(0,func_is_ng_def.p)(e,"d")&&ng_mocks_universe.A.builtDeclarations.set(e,MockDirective(e)),(0,func_is_ng_def.p)(e,"p")&&ng_mocks_universe.A.builtDeclarations.set(e,MockPipe(e)))},init_modules=(e,o,t,r)=>{var n,s,c,_,i;const a=new Map;for(const l of[...(0,core_helpers.LG)(e),...(0,core_helpers.LG)(o),...(0,core_helpers.LG)(t)]){const e=(0,collect_declarations.A)(l),t=[...null!==(n=r.get(l))&&void 0!==n?n:[],...null!==(c=null===(s=e.Component)||void 0===s?void 0:s.providers)&&void 0!==c?c:[],...null!==(i=null===(_=e.Directive)||void 0===_?void 0:_.providers)&&void 0!==i?i:[]],p=!ng_mocks_universe.A.touches.has(l);o.has(l)||ng_mocks_universe.A.flags.add("skipMock");const u=(0,func_is_ng_def.p)(l,"m");if(t.length>0){const[,e]=mock_ng_def({providers:t,skipMarkProviders:!u,skipExports:!0});a.set(l,e.providers)}u&&ng_mocks_universe.A.builtDeclarations.set(l,MockModule(l)),ng_mocks_universe.A.flags.delete("skipMock"),p&&ng_mocks_universe.A.touches.delete(l)}for(const e of(0,core_helpers.LG)(o))try_mock_declaration(e);return a},init_replace_def=(e,o)=>{const t=ng_mocks_universe.A.builtDeclarations,r=ng_mocks_universe.A.config.get("ngMocksDepsResolution");for(const n of(0,core_helpers.LG)(e))t.set(n,o.get(n)),r.set(n,"replace")},init_universe=({configDef:e,defProviders:o,defValue:t,excludeDef:r,keepDef:n,mockDef:s,replaceDef:c})=>{ng_mocks_universe.A.flags.add("cachePipe"),ng_mocks_universe.A.config.set("ngMocksMulti",new Set),ng_mocks_universe.A.config.set("ngMocksDeps",new Set),ng_mocks_universe.A.config.set("ngMocksDepsSkip",new Set),ng_mocks_universe.A.config.set("ngMocksDepsResolution",new Map);const _=init_keep_def(n,e);for(const e of(0,core_helpers.LG)(_))ng_mocks_universe.A.touches.add(e);for(const e of(0,core_helpers.LG)(n))_.add(e),funcExtractDeps(e,_,!0);for(const e of(0,core_helpers.LG)(s))_.add(e),funcExtractDeps(e,_,!0);for(const e of(0,core_helpers.LG)(c))_.add(e),funcExtractDeps(e,_,!0);for(const o of(0,core_helpers.LG)(_)){if(e.has(o))continue;const _=ng_mocks_universe.A.getResolution(o);"replace"===_?(c.add(o),t.set(o,ng_mocks_universe.A.getBuildDeclaration(o))):"keep"===_?n.add(o):"exclude"===_?r.add(o):("mock"===_||ng_mocks_universe.A.touches.has(o))&&s.add(o),e.set(o,ng_mocks_universe.A.touches.has(o)?{dependency:!0,__internal:!0}:{})}for(const[o,r]of(0,core_helpers.Nn)(e))ng_mocks_universe.A.config.set(o,Object.assign(Object.assign(Object.assign({},ng_mocks_universe.A.getConfigMock().get(o)),r),{defValue:t.get(o)}));return init_replace_def(c,t),init_exclude_def(r),init_mock_declarations(s,t),init_modules(n,s,c,o)},parse_mock_arguments=(e,o,t,r)=>{let n=e===o?r:o,s=null!=t?t:o!==r&&"object"==typeof o?o:void 0;return(0,func_is_ng_def.p)(e,"p")&&"function"==typeof o&&o!==e&&!(0,func_is_ng_def.p)(o,"p")?(n={transform:o},s=t):!(0,func_is_ng_def.p)(e,"i")&&(0,func_is_ng_def.p)(e)||(s=t),n=n===s?r:n,{config:s,mock:n}},parse_provider=e=>{const o=(0,func_get_type.A)(e);return{multi:o!==e&&e.multi,provide:o}};var __awaiter=function(e,o,t,r){return new(t||(t=Promise))((function(n,s){function c(e){try{i(r.next(e))}catch(e){s(e)}}function _(e){try{i(r.throw(e))}catch(e){s(e)}}function i(e){var o;e.done?n(e.value):(o=e.value,o instanceof t?o:new t((function(e){e(o)}))).then(c,_)}i((r=r.apply(e,o||[])).next())}))};const normaliseModule=e=>(0,func_is_ng_module_def_with_providers.h)(e)?{def:e.ngModule,providers:e.providers}:{def:e,providers:void 0},generateProviderValue=(e,o,t)=>t?[...Array.isArray(o)?o:[],e]:e,defaultMock={};class MockBuilderPromise{constructor(e){this.configDefault=e,this.beforeCC=new Set,this.configDef=new Map,this.defProviders=new Map,this.defValue=new Map,this.excludeDef=new Set,this.keepDef=new Set,this.mockDef=new Set,this.providerDef=new Map,this.replaceDef=new Set,this.stash=new MockBuilderStash,"undefined"!=typeof Symbol&&(this[Symbol.toStringTag]="Promise")}beforeCompileComponents(e){return this.beforeCC.add(e),this}build(){this.stash.backup();const e=new core_def_stack;ng_mocks_universe.A.config.set("mockNgDefResolver",e),ng_mocks_universe.A.flags.add("hasRootModule");try{const o=this.combineParams(),t=init_ng_modules(o,init_universe(o));return add_requested_providers(t,o,e),handle_root_providers(t,o,e),handle_entry_components(t),apply_platform_modules(),t.providers.push(create_ng_mocks_token(),create_ng_mocks_touches_token(),create_ng_mocks_overrides_token(this.replaceDef,this.defValue),MockBuilder),t}finally{ng_mocks_universe.A.flags.delete("hasRootModule"),ng_mocks_universe.A.config.delete("mockNgDefResolver"),this.stash.restore()}}catch(e){return __awaiter(this,void 0,void 0,(function*(){return this.then().catch(e)}))}exclude(e){return this.wipe(e),this.excludeDef.add(e),this.setConfigDef(e),this}finally(e){return __awaiter(this,void 0,void 0,(function*(){return this.then().finally(e)}))}keep(e,o){const{def:t,providers:r}=normaliseModule(e),n=this.keepDef.has(t)?this.defProviders.get(t):[];return this.wipe(t),this.keepDef.add(t),r&&this.defProviders.set(t,[...n||[],...r]),this.setConfigDef(t,o),this}mock(e,o=defaultMock,t){const{def:r,providers:n}=normaliseModule(e),{config:s,mock:c}=parse_mock_arguments(r,o,t,defaultMock);if((0,func_is_ng_def.p)(c)&&(0,func_is_ng_def.p)(e)&&!(0,func_is_ng_def.p)(e,"t"))throw new Error([`MockBuilder.mock(${(0,func_get_name.A)(e)}) received a class when its shape is expected.`,"Please try ngMocks.defaultMock instead."].join(" "));const _=this.mockDef.has(r)?this.defProviders.get(r):[];return this.wipe(r),this.mockDef.add(r),n&&this.defProviders.set(r,[..._||[],...n]),this.setDefValue(r,c),this.setConfigDef(r,s),this}provide(e){for(const o of(0,core_helpers.Bq)(e)){const{provide:e,multi:t}=parse_provider(o),r=this.providerDef.has(e)?this.providerDef.get(e):[];this.providerDef.set(e,generateProviderValue(o,r,t))}return this}replace(e,o,t){if(!(0,func_is_ng_def.p)(o)||!(0,func_is_ng_def.p)(e)||(0,func_is_ng_def.p)(o,"i")||(0,func_is_ng_def.p)(e,"i"))throw new Error("Cannot replace the declaration, both have to be a Module, a Component, a Directive or a Pipe, for Providers use `.mock` or `.provide`");return this.wipe(e),this.replaceDef.add(e),this.defValue.set(e,o),this.setConfigDef(e,t),this}then(e,o){return __awaiter(this,void 0,void 0,(function*(){const t=new Promise((e=>{const o=testing_.TestBed.configureTestingModule(this.build());for(const e of(0,core_helpers.LG)(this.beforeCC))e(o);o.compileComponents().then((()=>{e({testBed:o})}))}));return t.then(e,o)}))}combineParams(){return{configDef:this.configDef,configDefault:this.configDefault,defProviders:this.defProviders,defValue:this.defValue,excludeDef:this.excludeDef,keepDef:this.keepDef,mockDef:this.mockDef,providerDef:this.providerDef,replaceDef:this.replaceDef}}setConfigDef(e,o){!o&&this.configDef.has(e)||this.configDef.set(e,null!=o?o:this.configDefault)}setDefValue(e,o){o===defaultMock?this.defValue.delete(e):this.defValue.set(e,o)}wipe(e){this.defProviders.delete(e),this.defValue.delete(e),this.excludeDef.delete(e),this.keepDef.delete(e),this.mockDef.delete(e),this.providerDef.delete(e),this.replaceDef.delete(e)}}const objectsDiffer=(e,o)=>{const t=Object.keys(e),r=Object.keys(o);if(t.length!==r.length)return!0;for(const r of t)if(e[r]!==o[r])return!0;return!1},equal_variables=(e,o)=>e===o||!(e&&!o||!e&&o)&&!objectsDiffer(e,o),equal_render_defs=(e,o)=>e===o||("boolean"!=typeof e&&"boolean"!=typeof o||e===o)&&e.$implicit===o.$implicit&&equal_variables(e.variables,o.variables),equal_render_configs_objectsDiffer=(e,o)=>{if(Object.keys(e).length!==Object.keys(o).length)return!0;for(const t of Object.keys(e))if(!equal_render_defs(e[t],o[t]))return!0;return!1},equal_render_configs=(e,o)=>!(!equal_render_defs(o,e)||"object"==typeof o&&"object"==typeof e&&equal_render_configs_objectsDiffer(o,e)),are_equal_config_params=(e,o)=>o===e||o.dependency===e.dependency&&o.export===e.export&&o.exportAll===e.exportAll&&!!equal_render_configs(e.render,o.render),are_equal_maps=(e,o,t=((e,o)=>e===o))=>{if(!o||o.size!==e.size)return!1;for(const r of(0,core_helpers.d4)(e)){if(!o.has(r))return!1;if(!t(o.get(r),e.get(r)))return!1}return!0},areEqualProviderDefs=(e,o,...t)=>{for(const r of t)if(o&&e&&o[r]&&e[r]&&o[r]===e[r])return!0;return o===e},are_equal_providers=(e,o)=>{if(Array.isArray(e)!==Array.isArray(o))return!1;const[t,r]=[(0,core_helpers.Bq)(e),(0,core_helpers.Bq)(o)];if(t.length!==r.length)return!1;for(let e=0;e{if(!o||o.size!==e.size)return!1;for(const t of(0,core_helpers.LG)(e))if(!o.has(t))return!1;return!0},get_empty_config=()=>({beforeCC:new Set,configDef:new Map,defProviders:new Map,defValue:new Map,excludeDef:new Set,keepDef:new Set,mockDef:new Set,providerDef:new Map,replaceDef:new Set}),required_metadata=e=>Object.assign(Object.assign({},e),{declarations:[...e.declarations||[]],imports:[...e.imports||[]],providers:[...e.providers||[]]});var mock_builder_performance_awaiter=function(e,o,t,r){return new(t||(t=Promise))((function(n,s){function c(e){try{i(r.next(e))}catch(e){s(e)}}function _(e){try{i(r.throw(e))}catch(e){s(e)}}function i(e){var o;e.done?n(e.value):(o=e.value,o instanceof t?o:new t((function(e){e(o)}))).then(c,_)}i((r=r.apply(e,o||[])).next())}))};class MockBuilderPerformance extends MockBuilderPromise{build(){const e=ng_mocks_universe.A.global;if(e.has("builder:module")&&e.has("builder:config")&&this.equalsTo(e.get("builder:config")))return required_metadata(e.get("builder:module"));e.has("builder:module")&&e.delete(e.get("builder:module"));const o=this.cloneConfig(),t=super.build();return e.set("builder:config",o),e.set("builder:module",t),required_metadata(t)}then(e,o){const t=Object.create(null,{then:{get:()=>super.then}});return mock_builder_performance_awaiter(this,void 0,void 0,(function*(){const r=ng_mocks_universe.A.global;if(r.has("bullet")&&r.has("builder:module")&&r.has("builder:config")&&this.equalsTo(r.get("builder:config")))return r.get(r.get("builder:module")).then(e,o);r.has("bullet")&&r.has("bullet:reset")&&(console.warn("ngMocks.faster has zero effect due to changes in testing module between runs"),r.delete("bullet"),testing_.TestBed.resetTestingModule(),r.set("bullet",!0));const n=t.then.call(this,e,o);return r.set(r.get("builder:module"),n),n}))}cloneConfig(){const e=get_empty_config();return(0,core_helpers.LG)(this.beforeCC,e.beforeCC),(0,core_helpers.LG)(this.excludeDef,e.excludeDef),(0,core_helpers.LG)(this.keepDef,e.keepDef),(0,core_helpers.LG)(this.mockDef,e.mockDef),(0,core_helpers.LG)(this.replaceDef,e.replaceDef),(0,core_helpers.Nn)(this.configDef,e.configDef),(0,core_helpers.Nn)(this.defProviders,e.defProviders),(0,core_helpers.Nn)(this.defValue,e.defValue),(0,core_helpers.Nn)(this.providerDef,e.providerDef),e}equalsTo(e){for(const o of["beforeCC","keepDef","replaceDef","excludeDef","mockDef"])if(!are_equal_sets(this[o],e[o]))return!1;for(const o of["defValue"])if(!are_equal_maps(this[o],e[o]))return!1;for(const o of["providerDef","defProviders"])if(!are_equal_maps(this[o],e[o],are_equal_providers))return!1;return are_equal_maps(this.configDef,e.configDef,are_equal_config_params)}}function MockBuilder(...e){const[o,t]=e,r=new MockBuilderPerformance(e.length<2?{export:!0}:{dependency:!0}),n=ng_mocks_universe.A.config.get("MockBuilderExtensions");for(const e of n?(0,core_helpers.d4)(n):[]){if((0,helper_extract_property_descriptor.A)(r,e))throw new Error(`MockBuilder.${e} is a base method and cannot be customized, please use a different name.`);(0,core_define_property.A)(r,e,((...o)=>(n.get(e)(r,o),r)))}if(o)for(const e of(0,core_helpers.Bq)(o))r.keep(e,{export:!0,shallow:isStandalone(e)});if(t)for(const e of(0,core_helpers.Bq)(t))r.mock(e,e,{export:!0,exportAll:!0});return r}function mockBuilderExtend(e,o){var t;const r=null!==(t=ng_mocks_universe.A.config.get("MockBuilderExtensions"))&&void 0!==t?t:new Map;o?(r.set(e,o),ng_mocks_universe.A.config.set("MockBuilderExtensions",r)):r.delete(e)}!function(e){e.extend=function(e,o){mockBuilderExtend(e,o)}}(MockBuilder||(MockBuilder={}));const is_debug_node=e=>!!(null==e?void 0:e.nativeElement)||!!(null==e?void 0:e.nativeNode),func_parse_find_args_name=e=>"string"==typeof e?e:"function"==typeof e?e.name:(0,func_is_ng_def.p)(e,"t")?e._desc:Array.isArray(e)?e[0]:e?"":"",is_fixture=e=>!!e&&"object"==typeof e&&void 0!==e.debugElement,findDebugElement=e=>is_fixture(e)?findDebugElement(e.debugElement):e&&e.injector&&e.query?e:void 0,func_parse_find_args=(e,o)=>{var t;let r,n,s=o;return 3===e.length?(r=findDebugElement(e[0]),n=e[1],s=e[2]):1===e.length?(r=findDebugElement(func_get_last_fixture()),[n]=e):e[0]?(r=findDebugElement(e[0]),r?n=e[1]:(r=findDebugElement(func_get_last_fixture()),[n,s]=e)):n=e[1],n=null!==(t=findDebugElement(n))&&void 0!==t?t:n,[r,n,s]};var platform_browser_x=e=>{var o={};return __webpack_require__.d(o,e),o},platform_browser_y=e=>()=>e;const platform_browser_namespaceObject=platform_browser_x({By:()=>__WEBPACK_EXTERNAL_MODULE__angular_platform_browser_bc6fa964__.By}),func_parse_find_term=e=>Array.isArray(e)?platform_browser_namespaceObject.By.css(1===e.length?`[${e[0]}]`:`[${e[0]}="${e[1]}"]`):"string"==typeof e?platform_browser_namespaceObject.By.css(e):platform_browser_namespaceObject.By.directive(getSourceOfMock(e)),defaultNotFoundValue={},mock_helper_find=(...e)=>{const[o,t,r]=func_parse_find_args(e,defaultNotFoundValue),n=is_debug_node(t)?t:null==o?void 0:o.query(func_parse_find_term(t));if(n)return n;if(r!==defaultNotFoundValue)return r;throw new Error(`Cannot find an element via ngMocks.find(${func_parse_find_args_name(t)})`)},detect_text_node=e=>"#text"===e.nativeNode.nodeName,el_def_compare=(e,o)=>!(!e||!o)&&e===o,el_def_get_node=e=>detect_text_node(e)?void 0:e.injector._tNode||e.injector.elDef||void 0,defaultInjector={},core_injector=(e,o=defaultInjector)=>{if(o===defaultInjector)return(0,core_helpers.d5)(e);try{return o.get(e)}catch(e){return}},getVcr=(e,o)=>{if(e!==o&&"#comment"===o.nativeNode.nodeName)return core_injector(core_.ViewContainerRef,o.injector)},getScanViewRefRootNodes=(e,o)=>{const t=getVcr(e,o);if(!t)return[];const r=[];for(let e=0;e{var o;let t,r;for(const n of(null===(o=e.parent)||void 0===o?void 0:o.childNodes)||[])for(const[o,s]of getScanViewRefRootNodes(e,n))s===e.nativeNode&&(void 0===r||o{var o,t,r,n;return(null===(o=e.injector._tNode)||void 0===o?void 0:o.parent)||(null===(t=e.injector.elDef)||void 0===t?void 0:t.parent)||scanViewRef(e)||(null===(r=e.parent)||void 0===r?void 0:r.injector._tNode)||(null===(n=e.parent)||void 0===n?void 0:n.injector.elDef)||void 0},nested_check_children=e=>{var o,t;const r=el_def_get_node(e);if(!r||detect_text_node(e))return[];const n=void 0!==e.childNodes,s=[];for(const t of e.childNodes||(null===(o=e.parent)||void 0===o?void 0:o.childNodes)||[]){const e=el_def_get_parent(t);(n||el_def_compare(r,e))&&(e&&!el_def_compare(r,e)||s.push(t))}if("BODY"===(null===(t=e.parent)||void 0===t?void 0:t.name)){const o=e.parent.childNodes;let t=o.length,r=0;for(let n=o.length-1;n>=0;n-=1){const s=o[n];if("#comment"===s.nativeNode.nodeName)r=n;else if(s.nativeNode===e.nativeNode){t=n+1;break}}for(let e=t;e{var t;if(o)return o;const r=el_def_get_parent(e),n=e.parent?el_def_get_node(e.parent):void 0;if(e.parent&&el_def_compare(r,n))return e.parent;for(const o of(null===(t=e.parent)||void 0===t?void 0:t.childNodes)||[]){const e=el_def_get_node(o);if(el_def_compare(r,e))return o}},nested_check_parent=detectParent,nestedCheck=(e,o,t,r=!1)=>{if(!e)return!1;if(!r&&detect_text_node(e))return!1;if(t(e,nested_check_parent(e,o)))return!0;for(const o of nested_check_children(e))if(nestedCheck(o,e,t,r))return!0;return!1},nested_check=nestedCheck,mock_helper_crawl=(e,o,t=!1)=>{const r=mock_helper_find(func_get_last_fixture(),e,void 0);nested_check(r,void 0,o,t)},isSelector=e=>("string"==typeof e||Array.isArray(e)&&"string"==typeof e[0]||is_fixture(e)||is_debug_node(e),!0),mock_helper_func_parse_find_args=(e,o,t)=>{let r,n,s=t;return 3===e.length?[r,n,s]=e:1===e.length?(r=func_get_last_fixture(),[n]=e):o(e[1])&&isSelector(e[0])?[r,n]=e:(r=func_get_last_fixture(),[n,s]=e),[r,n,s]},detect_attribute_in_selectors=(e,o)=>{for(const t of e){const e=t.match(/\[([^=\]]+)/g);if(e)for(const t of e)if(t===`[${o}`)return!0}return!1},getMeta=e=>{try{return core_reflect_directive_resolve(e)}catch(e){return}},func_parse_provider_tokens_directives=(e,o)=>{if(e)try{const t=(0,func_get_type.A)(o),r=core_injector(t,e.injector);return getMeta(r.constructor)}catch(e){return}},func_get_public_provider_keys=e=>e.injector.elDef?Object.keys(e.injector.elDef.element.publicProviders):[],func_parse_inputs_and_requires_attributes=(e,o)=>{const t=e.injector.elDef.element.publicProviders[o],r=t.provider.value;if(!r)return[[],[],0];const n=func_parse_provider_tokens_directives(e,r),s=t.bindings.map((e=>e.nonMinifiedName||e.name));return[(null==n?void 0:n.inputs)||[],s,t.nodeIndex]},collectSelectors=e=>{const o=[];for(const t of e.providerTokens){const r=func_parse_provider_tokens_directives(e,t);(null==r?void 0:r.selector)&&-1===o.indexOf(r.selector)&&o.push(r.selector)}return o},collectAttributesClassic=e=>{const o=[];for(const t of func_get_public_provider_keys(e)){const[r,n]=func_parse_inputs_and_requires_attributes(e,t);for(const e of r){const{name:t,alias:r}=(0,func_directive_io_parse.A)(e),s=r||t;-1!==n.indexOf(t)&&-1===o.indexOf(s)&&o.push(s)}}return o},collectAttributesIvy=e=>{var o,t;const r=[],n=(null===(o=e.injector._tNode)||void 0===o?void 0:o.attrs)||[];let s=2;for(let o=0;o[collectSelectors(e),[...collectAttributesClassic(e),...collectAttributesIvy(e)]],crawl_by_attribute=e=>o=>{const[t,r]=detect_selectors_from_node(o);return-1!==r.indexOf(e)||!!detect_attribute_in_selectors(t,e)},detectInClassic=(e,o,t)=>{for(const r of func_get_public_provider_keys(e)){const[n,s,c]=func_parse_inputs_and_requires_attributes(e,r);for(const r of n){const{name:n,alias:_}=(0,func_directive_io_parse.A)(r);if(o===(_||n)&&-1!==s.indexOf(n)&&t===e.injector.view.nodes[c].instance[n])return!0}}return!1},detectInIvy=(e,o,t)=>{var r,n,s;const c=(null===(r=e.injector._tNode)||void 0===r?void 0:r.attrs)||[];let _=2;for(let r=0;rt=>!!detectInIvy(t,e,o)||detectInClassic(t,e,o),crawl_by_declaration=e=>{const o=getSourceOfMock(e);return e=>!!e&&-1!==e.providerTokens.indexOf(o)&&void 0!==core_injector(o,e.injector)},crawl_by_id=e=>o=>!!o.references[e],regExp=new RegExp("\\[.*?\\]","g"),detect_tag_name_in_selectors=(e,o)=>{for(const t of e){const e=t.replace(regExp,"").split(",");for(const t of e)if(t.trim()===o)return!0}return!1},crawl_by_tag_name=e=>o=>{const[t]=detect_selectors_from_node(o);return detect_tag_name_in_selectors(t,e)},isCrawlByAttribute=e=>Array.isArray(e)&&1===e.length&&"string"==typeof e[0],isCrawlByAttributeValue=e=>Array.isArray(e)&&2===e.length&&"string"==typeof e[0],isCrawlById=e=>"string"==typeof e&&0===e.indexOf("#")&&e.length>1,isCrawlByTagName=e=>"string"==typeof e&&0!==e.indexOf("#")&&e.length>0,isCrawlByDeclaration=e=>"function"==typeof e,detect_crawler=e=>{if(isCrawlByAttribute(e))return crawl_by_attribute(e[0]);if(isCrawlByAttributeValue(e))return crawl_by_attribute_value(e[0],e[1]);if(isCrawlById(e))return crawl_by_id(e.slice(1));if(isCrawlByTagName(e))return crawl_by_tag_name(e);if(isCrawlByDeclaration(e))return crawl_by_declaration(e);throw new Error("Unknown selector")},func_is_valid_reveal_selector=e=>"string"==typeof e||!(!Array.isArray(e)||"string"!=typeof e[0])||"function"==typeof e,mock_helper_reveal_defaultNotFoundValue={},mock_helper_reveal=(...e)=>{const[o,t,r]=mock_helper_func_parse_find_args(e,func_is_valid_reveal_selector,mock_helper_reveal_defaultNotFoundValue),n=mock_helper_find(func_get_last_fixture(),o,void 0),s=detect_crawler(t);let c;if(mock_helper_crawl(n,(e=>!(e===n||detect_text_node(e)||!s(e)||(c=e,0)))),c)return c;if(r!==mock_helper_reveal_defaultNotFoundValue)return r;throw new Error(`Cannot find a DebugElement via ngMocks.reveal(${func_parse_find_args_name(t)})`)},mock_helper_reveal_all=(...e)=>{const[o,t]=mock_helper_func_parse_find_args(e,func_is_valid_reveal_selector),r=mock_helper_find(func_get_last_fixture(),o,void 0),n=detect_crawler(t),s=[];return mock_helper_crawl(r,(e=>{e!==r&&!detect_text_node(e)&&n(e)&&s.push(e)})),s},isMockControlValueAccessor=e=>!!func_is_mock(e)&&!!e.__ngMocksConfig.isControlValueAccessor;var helper_define_property_descriptor=__webpack_require__(6),helper_extract_methods_from_prototype=__webpack_require__(331);const is_html_element=e=>!!e&&"object"==typeof e&&void 0!==e.innerHTML,preventBubble=["focus","blur","load","unload","change","reset","scroll"],customEvent=(e,o)=>{const t=Object.assign({bubbles:!1,cancelable:!1},o),r=document.createEvent("CustomEvent");return r.initCustomEvent(e,t.bubbles,t.cancelable,null),r},eventCtor="function"==typeof Event?(e,o)=>new CustomEvent(e,o):customEvent,keyMap={alt:{altKey:!0,code:"AltLeft",key:"Alt",location:1,which:18},arrowdown:{code:"ArrowDown",key:"ArrowDown",location:0,which:40},arrowleft:{code:"ArrowLeft",key:"ArrowLeft",location:0,which:37},arrowright:{code:"ArrowRight",key:"ArrowRight",location:0,which:39},arrowup:{code:"ArrowUp",key:"ArrowUp",location:0,which:38},backspace:{code:"Backspace",key:"Backspace",location:0,which:8},control:{code:"ControlLeft",ctrlKey:!0,key:"Control",location:1,which:17},enter:{code:"Enter",key:"Enter",location:0,which:13},esc:{code:"Escape",key:"Escape",location:0,which:27},meta:{code:"MetaLeft",key:"Meta",location:1,metaKey:!0,which:91},shift:{code:"ShiftLeft",key:"Shift",location:1,shiftKey:!0,which:16},space:{code:"Space",key:" ",location:0,which:32},tab:{code:"Tab",key:"Tab",location:0,which:9}};for(let e=1;e<=12;e+=1)keyMap[`f${e}`]={code:`F${e}`,key:`F${e}`,location:0,which:e+111};const getCode=e=>{const o=e.codePointAt(0);return o&&o>=97&&o<=122||o&&o>=65&&o<=90?`Key${e.toUpperCase()}`:o&&o>=48&&o<=57?`Digit${e}`:"Unknown"},applyPayload=(e,o)=>{const t={};for(const e of o?o.split("."):[]){let o=keyMap[e];if(o||1!==e.length||(o={code:getCode(e),key:e}),!o)throw new Error(`Unknown event part ${e}`);(0,mock_helper_stub.A)(t,o)}o&&(0,mock_helper_stub.A)(e,t)},mock_helper_event=(e,o,t)=>{const r=e.indexOf("."),[n,s]=-1===r?[e]:[e.slice(0,Math.max(0,r)),e.slice(r+1)],c=eventCtor(n,Object.assign({bubbles:-1===preventBubble.indexOf(e),cancelable:!0},o));return applyPayload(c,s),t&&(0,mock_helper_stub.A)(c,t),c},mock_helper_trigger_preventBubble=["focus","blur","load","unload","change","reset","scroll"],toEventObj=e=>"string"==typeof e?mock_helper_event(e,{bubbles:-1===mock_helper_trigger_preventBubble.indexOf(e),cancelable:!0}):e,getNativeElement=e=>is_debug_node(e)||is_fixture(e)?e.nativeElement:is_html_element(e)?e:void 0,mock_helper_trigger=(e,o,t)=>{const r=is_html_element(e)?e:mock_helper_find(func_get_last_fixture(),e,void 0),n=getNativeElement(r);if(!n)throw new Error(`Cannot trigger ${"string"==typeof o?o:o.type} event undefined element`);if(n.disabled)return;const s=toEventObj(o);s.target||(0,mock_helper_stub.A)(s,{target:n}),t&&(0,mock_helper_stub.A)(s,t),n.dispatchEvent(s)};var mock_helper_stub_member=__webpack_require__(589);const message=["Cannot find ControlValueAccessor on the element.","If it is a mock input with [formControlName],","you need either to avoid mocking ReactiveFormsModule","or to avoid accessing the control in such a way,","because this tests ReactiveFormsModule instead of own implementation."].join(" "),func_get_vca=e=>{const o=core_form&&core_injector(core_form.NgControl,e.injector),t=null==o?void 0:o.valueAccessor;if(t)return t;const r=core_form&&core_injector(core_form.FormControlDirective,e.injector);if(null==r?void 0:r.form)return r.form;const n=core_form&&core_injector(core_form.NgModel,e.injector);if(n)return n;throw new Error(message)},triggerInput=(e,o)=>{mock_helper_trigger(e,"focus");const t=Object.getOwnPropertyDescriptor(e.nativeElement,"value");(0,mock_helper_stub_member.A)(e.nativeElement,"value",o),mock_helper_trigger(e,"input"),mock_helper_trigger(e,"change"),t&&((0,helper_define_property_descriptor.A)(e.nativeElement,"value",t),e.nativeElement.value=o),mock_helper_trigger(e,"blur")},handleKnown=(e,o)=>core_form&&e instanceof core_form.AbstractControl?(e.setValue(o),!0):core_form&&e instanceof core_form.NgModel?(e.update.emit(o),!0):!!isMockControlValueAccessor(e.instance)&&(e.instance.__simulateChange(o),!0),hasListener=e=>e.listeners.some((e=>"input"===e.name||"change"===e.name)),keys=["onChange","onChangeCallback","onChangeCb","onChangeClb","onChangeFn","_onChange","_onChangeCallback","_onChangeCb","_onChangeClb","_onChangeFn","changeFn","_changeFn","onModelChange","cvaOnChange","cvaOnChangeCallback","cvaOnChangeCb","cvaOnChangeClb","cvaOnChangeFn","_cvaOnChange","_cvaOnChangeCallback","_cvaOnChangeCb","_cvaOnChangeClb","_cvaOnChangeFn"],mock_helper_change=(e,o,t)=>{const r=mock_helper_find(func_get_last_fixture(),e,void 0);if(!r)throw new Error(`Cannot find an element via ngMocks.change(${func_parse_find_args_name(e)})`);const n=func_get_vca(r);if(handleKnown(n,o)||hasListener(r))return void triggerInput(r,o);for(const e of t?[t]:keys)if("function"==typeof n[e])return n.writeValue(o),void n[e](o);const s=(0,helper_extract_methods_from_prototype.A)(n);throw new Error(["Unsupported type of ControlValueAccessor,",`please ensure it has '${t||"onChange"}' method.`,"If it is a 3rd-party library, please provide the correct name of the method in the 'methodName' parameter.","Possible Names: "+s.join(", ")+"."].join(" "))},triggerTouch=e=>{mock_helper_trigger(e,"focus"),mock_helper_trigger(e,"blur")},mock_helper_touch_handleKnown=e=>core_form&&e instanceof core_form.AbstractControl?(e.markAsTouched(),!0):!!isMockControlValueAccessor(e.instance)&&(e.instance.__simulateTouch(),!0),mock_helper_touch_hasListener=e=>e.listeners.some((e=>"focus"===e.name||"blur"===e.name)),mock_helper_touch_keys=["onTouched","onTouchedCallback","onTouchedCb","onTouchedClb","onTouchedFn","_onTouched","_onTouchedCallback","_onTouchedCb","_onTouchedClb","_onTouchedFn","markAsTouched","_markAsTouched","onModelTouched","cvaOnTouch","cvaOnTouchCallback","cvaOnTouchCb","cvaOnTouchClb","cvaOnTouchFn","_cvaOnTouch","_cvaOnTouchCallback","_cvaOnTouchCb","_cvaOnTouchClb","_cvaOnTouchFn"],mock_helper_touch=(e,o)=>{const t=mock_helper_find(func_get_last_fixture(),e,void 0);if(!t)throw new Error(`Cannot find an element via ngMocks.touch(${func_parse_find_args_name(e)})`);const r=func_get_vca(t);if(mock_helper_touch_handleKnown(r)||mock_helper_touch_hasListener(t))return void triggerTouch(t);for(const e of o?[o]:mock_helper_touch_keys)if("function"==typeof r[e])return void r[e]();const n=(0,helper_extract_methods_from_prototype.A)(r);throw new Error(["Unsupported type of ControlValueAccessor,",`please ensure it has '${o||"onTouched"}' method.`,"If it is a 3rd-party library, please provide the correct name of the method in the 'methodName' parameter.","Possible Names: "+n.join(", ")+"."].join(" "))},mock_helper_click=(e,o)=>{mock_helper_trigger(e,"click",o)},mock_helper_find_all=(...e)=>{const[o,t]=func_parse_find_args(e);return is_debug_node(t)?[t]:(null==o?void 0:o.queryAll(func_parse_find_term(t)))||[]},getParentWithInjector=e=>{let o=e;for(;"NullInjector"===(null==o?void 0:o.injector.constructor.name);)o=o.parent;if(o)return o.injector},func_get_from_node_injector=(e,o,t)=>{if(!o.injector||"NullInjector"===o.injector.constructor.name)return;const r=getParentWithInjector(o.parent),n=r?core_injector(t,r):void 0,s=core_injector(t,o.injector);n!==s&&((0,func_is_ng_def.p)(t,"t")&&void 0!==s||void 0!==s&&-1===e.indexOf(s))&&e.push(s)},func_get_from_node_element=e=>{var o;return"#text"===(null===(o=e.nativeNode)||void 0===o?void 0:o.nodeName)&&e.parent?e.parent:e},detectGatherFlag=(e,o,t)=>!!(o&&o.nativeNode&&"#comment"===o.nativeNode.nodeName&&Array.isArray(t)&&t[0]===o.nativeNode)||!Array.isArray(t)&&(o&&t.nodeName?"#comment"===t.nodeName?t===o.nativeNode:"#text"===t.nodeName&&t.parentNode===o.nativeNode:e),isNotObject=e=>!e||"object"!=typeof e,shouldBeScanned=(e,o)=>-1===e.indexOf(o)&&Array.isArray(o),scan=({result:e,el:o,nodes:t,normalize:r,proto:n},s,c=[])=>{c.push(t);let _=s,i=t.length;t.length>1&&t[1]&&"object"==typeof t[1]&&t[1].bindingStartIndex&&(i=t[1].bindingStartIndex);for(let s=0;s{if("object"==typeof e[1]&&e[20]===o)return e;for(let t=21;t{var o;let t=e,r=null===(o=t.nativeNode)||void 0===o?void 0:o.__ngContext__;for(;void 0===r&&t.parent;)t=t.parent,r=t.nativeNode.__ngContext__;if("number"!=typeof r)return r;const n=t.injector._lView;return Array.isArray(n)?detectContextByIndex(n,r):void 0},contextToNodes=e=>Array.isArray(e)?e:null==e?void 0:e.lView,func_get_from_node_ivy=(e,o,t)=>{if(!o||o._debugContext)return;const r=func_get_from_node_element(o);func_get_from_node_scan({el:r,nodes:contextToNodes(detectContext(o))||[],normalize:e=>e,proto:t,result:e},!0)},normalize=e=>{if(!e||"object"!=typeof e)return e;for(const o of["renderElement","renderText","instance"])if(e[o])return e[o];return null},func_get_from_node_standard=(e,o,t)=>{if(!o||!o._debugContext)return;const r=func_get_from_node_element(o);func_get_from_node_scan({el:r,nodes:o._debugContext.view.nodes,normalize,proto:t,result:e},!0)},func_get_from_node=(e,o,t)=>(func_get_from_node_injector(e,o,t),(0,func_is_ng_def.p)(t,"t")||"string"==typeof t||(func_get_from_node_standard(e,o,t),func_get_from_node_ivy(e,o,t)),e),func_is_valid_find_instance_selector=e=>"function"==typeof e||(0,func_is_ng_def.p)(e,"t"),mock_helper_find_instance_defaultNotFoundValue={},mock_helper_find_instance=(...e)=>{const[o,t,r]=mock_helper_func_parse_find_args(e,func_is_valid_find_instance_selector,mock_helper_find_instance_defaultNotFoundValue);if("function"!=typeof t&&!(0,func_is_ng_def.p)(t,"t")&&"string"!=typeof t)throw new Error("Only classes or tokens are accepted");const n=getSourceOfMock(t),s=[],c=func_get_last_fixture();if(c)mock_helper_crawl(mock_helper_find(c,o,void 0),((e,o)=>(func_get_from_node(s,e,n),0===s.length&&o&&"#comment"===o.nativeNode.nodeName&&func_get_from_node(s,o,n),s.length>0)),!0);else try{s.push((0,core_helpers.Ah)(n))}catch(e){if(!e||"object"!=typeof e||void 0===e.ngTempTokenPath)throw e}if(s.length>0)return s[0];if(r!==mock_helper_find_instance_defaultNotFoundValue)return r;throw new Error(`Cannot find an instance via ngMocks.findInstance(${func_parse_find_args_name(t)})`)},mock_helper_find_instances=(...e)=>{const[o,t]=mock_helper_func_parse_find_args(e,func_is_valid_find_instance_selector);if("function"!=typeof t&&!(0,func_is_ng_def.p)(t,"t")&&"string"!=typeof t)throw new Error("Only classes or tokens are accepted");const r=getSourceOfMock(t),n=[],s=[],c=func_get_last_fixture();if(c){const e=mock_helper_find_all(c,o,void 0);for(const o of e)mock_helper_crawl(o,((e,o)=>{-1===s.indexOf(e)&&(func_get_from_node(n,e,r),s.push(e)),o&&"#comment"===o.nativeNode.nodeName&&-1===s.indexOf(o)&&(func_get_from_node(n,o,r),s.push(o))}),!0)}else try{n.push((0,core_helpers.Ah)(r))}catch(e){}return n},handle_array=(e,o)=>e(o.map((o=>e(o,!0))).join("")),format_handler=e=>(o,t=!1)=>{const r=(o,n=!1)=>{if(Array.isArray(o))return handle_array(r,o);if(is_fixture(o))return r(o.debugElement,t);const s=e(r,o,n);return void 0!==s?s:is_debug_node(o)&&"#comment"===o.nativeNode.nodeName?r(nested_check_children(o),!0):is_debug_node(o)?r(o.nativeNode,n):""};return Array.isArray(o)?o.map((e=>r(e,t))):r(o,t)},handle_text=e=>{var o,t;return null!==(t=null!==(o=e.nodeValue)&&void 0!==o?o:e.textContent)&&void 0!==t?t:e.wholeText},is_text=e=>!!e&&"object"==typeof e&&"#text"===e.nodeName,normalizeValue=e=>e?e.replace(new RegExp("\\s+","mg")," ").replace(new RegExp("\x3c!--(.|\\n|\\r)*?--\x3e|\x3c!--(.|\\n|\\r)*","mg"),"").replace(new RegExp("\\s+","mg")," ").replace(new RegExp(">\\s+<","mg"),"><").replace(new RegExp('"\\s+>',"mg"),'">'):"",normalizeText=e=>e.replace(new RegExp("&","mg"),"&").replace(new RegExp('"',"mg"),""").replace(new RegExp("<","mg"),"<").replace(new RegExp(">","mg"),">").replace(new RegExp("'","mg"),"'"),getElementValue=(e,o)=>o?e.outerHTML:e.innerHTML,handlePrimitives=(e,o,t)=>{if("string"==typeof o||void 0===o){const e=normalizeValue(o);return t?e:e.trim()}return is_html_element(o)?e(getElementValue(o,t)):is_text(o)?handlePrimitives(e,normalizeText(handle_text(o)),t):void 0},mock_helper_format_html=format_handler(handlePrimitives),mock_helper_format_text_normalizeValue=e=>e?e.replace(new RegExp("\\s+","mg")," "):"",mock_helper_format_text_getElementValue=(e,o)=>{var t;const r=null!==(t=e.textContent)&&void 0!==t?t:"";return o?r:r.trim()},mock_helper_format_text_handlePrimitives=(e,o,t)=>{if("string"==typeof o||void 0===o){const e=mock_helper_format_text_normalizeValue(o);return t?e:e.trim()}return is_html_element(o)?e(mock_helper_format_text_getElementValue(o,t)):is_text(o)?mock_helper_format_text_handlePrimitives(e,handle_text(o),t):void 0},mock_helper_format_text=format_handler(mock_helper_format_text_handlePrimitives),calls=[],mock_helper_auto_spy=e=>{"reset"===e?calls.pop():calls.push(e);const o=calls[calls.length-1];return"jasmine"===o?(0,helper_mock_service.O)((e=>jasmine.createSpy(e))):"jest"===o?(0,helper_mock_service.O)((e=>jest.fn().mockName(e))):o&&"default"!==o&&"reset"!==o?(0,helper_mock_service.O)(o):(0,helper_mock_service.O)()},mock_helper_console=(e,o)=>(...t)=>{const r=[];beforeEach((()=>{for(const o of e)-1===t.indexOf(o)&&t.push(o);for(const e of t)(0,core_define_property.A)(console,`__ngMocksBackup_${e}`,console[`__ngMocksBackup_${e}`]||[]),console[`__ngMocksBackup_${e}`].push(console[e]),r.push(e),console[e]=o(e)})),afterEach((()=>{for(const e of r)console[e]=console[`__ngMocksBackup_${e}`].pop();r.splice(0,r.length)}))},factory=e=>helper_mock_service.A.mockFunction(`console.${e}`),mock_helper_console_ignore=mock_helper_console(["log"],factory),mock_helper_console_throw_factory=e=>(...o)=>{const t=new Error(o.join(" "));throw(0,core_define_property.A)(t,"ngMocksConsoleCatch",e),t},mock_helper_console_throw=mock_helper_console(["warn","error"],mock_helper_console_throw_factory),mock_helper_default_config=(e,o)=>{const t=ng_mocks_universe.A.getConfigMock();for(const r of(0,core_helpers.Bq)(e))o?t.set(r,o):t.delete(r)},mock_helper_default_mock=(e,o)=>{const t=ng_mocks_universe.A.getOverrides();for(const r of(0,core_helpers.Bq)(e))if(o){const e=t.has(r)?t.get(r):new Set;e.add(o),t.set(r,e)}else t.delete(r)},hooks=ng_mocks_universe.A.global.get("faster-hooks")||{after:[],before:[]};ng_mocks_universe.A.global.set("faster-hooks",hooks);const configureTestingModule=(e,o)=>t=>{if(testing_.TestBed.ngMocksFasterLock)return e.call(o,t);ng_mocks_universe.A.global.set("bullet:customized",!0);let r=e;for(const e of hooks.before)r=e(r,o);try{return(0,core_define_property.A)(testing_.TestBed,"ngMocksFasterLock",!0),r.call(o,t)}finally{(0,core_define_property.A)(testing_.TestBed,"ngMocksFasterLock",void 0)}},resetTestingModule=(e,o)=>()=>{if(testing_.TestBed.ngMocksFasterLock)return e.call(o);if(ng_mocks_universe.A.global.has("bullet"))return ng_mocks_universe.A.global.has("bullet:customized")&&ng_mocks_universe.A.global.set("bullet:reset",!0),o;ng_mocks_universe.A.global.delete("bullet:customized"),ng_mocks_universe.A.global.delete("bullet:reset");let t=e;for(const e of hooks.after)t=e(t,o);try{return(0,core_define_property.A)(testing_.TestBed,"ngMocksFasterLock",!0),t.call(o)}finally{(0,core_define_property.A)(testing_.TestBed,"ngMocksFasterLock",void 0)}},mock_helper_faster_install=()=>{testing_.TestBed.ngMocksFasterInstalled||(testing_.TestBed.configureTestingModule=configureTestingModule(testing_.TestBed.configureTestingModule,testing_.TestBed),testing_.TestBed.resetTestingModule=resetTestingModule(testing_.TestBed.resetTestingModule,testing_.TestBed),(0,core_define_property.A)(testing_.TestBed,"ngMocksFasterInstalled",!0));const e=(0,testing_.getTestBed)();return e.ngMocksFasterInstalled||(e.configureTestingModule=configureTestingModule(e.configureTestingModule,e),e.resetTestingModule=resetTestingModule(e.resetTestingModule,e),(0,core_define_property.A)(e,"ngMocksFasterInstalled",!0)),hooks},mock_helper_flush_test_bed=()=>{const e=(0,testing_.getTestBed)();e._instantiated=!1,e._moduleFactory=void 0,e._testModuleRef=null},resetFixtures=e=>{const o=(0,testing_.getTestBed)()._activeFixtures||[];let t=0;for(let r=o.length-1;r>=0;r-=1)o[r].ngMocksStackId&&o[r].ngMocksStackId!==e?t+=1:(o[r].ngMocksStackId=void 0,o[r].destroy(),o.splice(r,1));0===t&&mock_helper_flush_test_bed()},idAdd=e=>{var o;const t=null!==(o=ng_mocks_universe.A.global.get("bullet:stack"))&&void 0!==o?o:[];t.push(e),ng_mocks_universe.A.global.set("bullet:stack",t),ng_mocks_universe.A.global.set("bullet:stack:id",e)},idRemove=e=>{const o=ng_mocks_universe.A.global.get("bullet:stack");o.splice(o.indexOf(e),1),o.length>0?ng_mocks_universe.A.global.set("bullet:stack:id",o[o.length-1]):ng_mocks_universe.A.global.delete("bullet:stack:id"),resetFixtures(e)},mock_helper_faster=()=>{mock_helper_faster_install();const e={},o={};beforeAll((()=>{ng_mocks_universe.A.global.has("bullet:customized")&&testing_.TestBed.resetTestingModule(),ng_mocks_universe.A.global.set("bullet",!0),idAdd(e)})),beforeEach((()=>{idAdd(o)})),afterEach((()=>{idRemove(o)})),afterAll((()=>{idRemove(e),ng_mocks_universe.A.global.delete("bullet"),ng_mocks_universe.A.global.has("bullet:reset")&&testing_.TestBed.resetTestingModule()}))},mock_helper_get_defaultNotFoundValue={},parseArgs=e=>({el:e[0],notFoundValue:3===e.length?e[2]:mock_helper_get_defaultNotFoundValue,sel:e[1]}),mock_helper_get=(...e)=>{if(1===e.length)try{return testing_.TestBed.inject?testing_.TestBed.inject(e[0]):testing_.TestBed.get(e[0])}catch(o){if(!o||"object"!=typeof o||void 0===o.ngTempTokenPath)throw o;throw new Error(`Cannot find an instance via ngMocks.get(${func_parse_find_args_name(e[0])})`)}const{el:o,sel:t,notFoundValue:r}=parseArgs(e),n=mock_helper_find(func_get_last_fixture(),o,void 0),s=getSourceOfMock(t);if(n){const e=func_get_from_node([],n,s);if(e.length>0)return e[0]}if(n){const e=nested_check_parent(n,void 0);if(e&&"#comment"===e.nativeNode.nodeName){const o=func_get_from_node([],e,s);if(o.length>0)return o[0]}}if(r!==mock_helper_get_defaultNotFoundValue)return r;throw new Error(`Cannot find ${(0,func_get_name.A)(t)} instance via ngMocks.get`)},iterator=(e,o,t=new Set)=>{const r=(0,collect_declarations.A)(e);for(const e of r.decorators)for(const n of core_config.A.dependencies)if(r[e][n])for(const s of(0,core_helpers.Bq)(r[e][n])){const e=(0,func_get_type.A)(s);e&&!t.has(e)&&(t.add(e),o(e),iterator(e,o,t))}},func_iterate_declaration=iterator,func_global_prepare=()=>{var e;ng_mocks_universe.A.cacheDeclarations.clear(),null===(e=ng_mocks_universe.A.config.get("ngMocksDepsSkip"))||void 0===e||e.clear()},action=e=>{ng_mocks_universe.A.getDefaults().set(e,["exclude"])},mock_helper_global_exclude=(e,o=!1)=>{func_global_prepare(),action(e),o&&func_iterate_declaration(e,action)},mock_helper_global_keep_action=e=>{ng_mocks_universe.A.getDefaults().set(e,["keep"])},mock_helper_global_keep=(e,o=!1)=>{func_global_prepare(),mock_helper_global_keep_action(e),o&&func_iterate_declaration(e,mock_helper_global_keep_action)},mock_helper_global_mock_action=e=>{ng_mocks_universe.A.getDefaults().set(e,["mock"])},mock_helper_global_mock=(e,o=!1)=>{func_global_prepare(),mock_helper_global_mock_action(e),o&&func_iterate_declaration(e,mock_helper_global_mock_action)},mock_helper_global_replace=(e,o)=>{let t=!0;if(((0,func_is_ng_def.p)(e,"m")&&(0,func_is_ng_def.p)(o,"m")||(0,func_is_ng_def.p)(e,"c")&&(0,func_is_ng_def.p)(o,"c")||(0,func_is_ng_def.p)(e,"d")&&(0,func_is_ng_def.p)(o,"d")||(0,func_is_ng_def.p)(e,"p")&&(0,func_is_ng_def.p)(o,"p"))&&(t=!1),t)throw new Error("Cannot replace the declaration, both have to be a Module, a Component, a Directive or a Pipe");func_global_prepare(),ng_mocks_universe.A.getDefaults().set(e,["replace",o])},mock_helper_global_wipe_action=e=>{ng_mocks_universe.A.getDefaults().delete(e),mock_helper_default_mock(e)},mock_helper_global_wipe=(e,o=!1)=>{func_global_prepare(),mock_helper_global_wipe_action(e),o&&func_iterate_declaration(e,mock_helper_global_wipe_action)},mock_helper_guts_skipDef=(e,o,t)=>!!o.has(e)||(o.add(e),t.has(e)),createMetaHandler=(e,o,t,r,n)=>{const s=e.get(o)||o;(0,func_is_ng_def.p)(s,"m")?t.push(s):(0,func_is_ng_def.p)(s,"c")||(0,func_is_ng_def.p)(s,"d")?r.push(s):(0,func_is_ng_def.p)(s,"p")?(r.push(s),n.push(s)):(0,func_is_ng_injection_token.S)(s)||n.push(s)},createMeta=({keep:e,skip:o,optional:t,exclude:r,imports:n,declarations:s,providers:c})=>{for(const _ of e)o.has(_)||r.has(_)||t.has(_)||createMetaHandler(t,_,n,s,c);return{declarations:s,imports:n,providers:c}},typeMap=[["m","module"],["c","component"],["d","directive"],["p","pipe"]],mock_helper_guts_getType=(e,o)=>{if((0,func_is_ng_module_def_with_providers.h)(e))return"module-with-providers";for(const[t,r]of typeMap)if((0,func_is_ng_def.p)(e,t))return"m"===t&&o.has(e)?`${r}-keep`:r;return""},handleModuleWithProviders=(e,o)=>{e.skip.has(o.ngModule)||(e.skip.add(o.ngModule),e.exclude.has(o.ngModule)||e.imports.push(e.keep.has(o.ngModule)?o:MockModule(o)))},handleDeclaration=(e,o,t,r)=>{mock_helper_guts_skipDef(o,e.skip,e.exclude)||r.push(e.keep.has(o)?o:t(o))},handleDestructuring=(e,o,t)=>{if(mock_helper_guts_skipDef(o,e.skip,e.exclude))return;const r=core_reflect_module_resolve(o);for(const o of(0,core_helpers.Bq)([r.declarations,r.imports]))t(e,o);for(const o of r.providers?(0,core_helpers.Bq)(r.providers):[])resolveProvider(e,o)},resolveProvider=({skip:e,keep:o,providers:t,exclude:r},n)=>{const s=(0,func_get_type.A)(n);if(e.add(s),r.has(s))return;const c=o.has(s)?n:(0,mock_provider.A)(n);c&&t.push(c)},resolveMap={component:MockComponent,directive:MockDirective,pipe:MockPipe},resolveHandler=(e,o,t,r)=>{"module-with-providers"===o?handleModuleWithProviders(e,t):"module-keep"===o||"module"===o&&r?handleDeclaration(e,t,MockModule,e.imports):"module"===o?handleDestructuring(e,t,resolve):resolveMap[o]?handleDeclaration(e,t,resolveMap[o],e.declarations):resolveProvider(e,t)},resolve=(e,o,t=!0)=>{if(!o)return;const r=mock_helper_guts_getType(o,e.keep);let n;if("module-with-providers"!==r){const t=e.optional.get(o);t&&t!==o&&(n=t,e.keep.add(n))}n||(n=o),resolveHandler(e,r,n,t)},generateDataWithUniverse=(e,o,t,r)=>{for(const n of(0,core_helpers.d4)(ng_mocks_universe.A.getDefaults())){const s=ng_mocks_universe.A.getBuildDeclaration(n);e.has(n)||o.has(n)||t.has(n)||(r.set(n,s),null===s?t.add(n):void 0===s?o.add(n):n===s&&e.add(n))}},generateData=(e,o,t)=>{const r=new Set((0,core_helpers.Bq)(e||[])),n=new Set((0,core_helpers.Bq)(o||[])),s=new Set((0,core_helpers.Bq)(t||[])),c=new Map;return generateDataWithUniverse(r,n,s,c),{declarations:[],exclude:s,imports:[],keep:r,mock:n,optional:c,providers:[],skip:new Set}},mock_helper_guts=(e,o=null,t=null)=>{const r=generateData(e,o,t),n=new Map;ng_mocks_universe.A.config.set("ngMocksDepsResolution",n);for(const e of(0,core_helpers.LG)(r.keep))n.set(e,"keep");for(const e of(0,core_helpers.LG)(r.exclude))n.set(e,"exclude");ng_mocks_universe.A.config.set("mockNgDefResolver",new core_def_stack);for(const e of(0,core_helpers.LG)(r.mock))n.set(e,"mock"),r.optional.has(e)||resolve(r,e,!1);const s=createMeta(r);return ng_mocks_universe.A.config.delete("mockNgDefResolver"),ng_mocks_universe.A.config.delete("ngMocksDepsResolution"),s},mock_helper_attributes_defaultNotFoundValue={},mock_helper_attributes_parseArgs=e=>[e[0],e[1],3===e.length?e[2]:mock_helper_attributes_defaultNotFoundValue],attrMatches=(e,o)=>{const{name:t,alias:r=""}=(0,func_directive_io_parse.A)(e);if(!r&&t===o||r&&r===o)return t},detectAttribute=(e,o,t)=>{for(const r of(null==e?void 0:e.providerTokens)||[]){const n=func_parse_provider_tokens_directives(e,r);if(n)for(const s of n[o]||[]){const o=attrMatches(s,t);if(o)return mock_helper_get(e,r)[o]}}throw new Error("Not found")},mock_helper_attributes=(e,o,...t)=>{const[r,n,s]=mock_helper_attributes_parseArgs(t);try{return detectAttribute(mock_helper_find(func_get_last_fixture(),r,void 0),o,n)}catch(e){}if(s!==mock_helper_attributes_defaultNotFoundValue)return s;throw new Error(`Cannot find ${n} ${e} via ngMocks.${e}`)},mock_helper_input=(...e)=>mock_helper_attributes("input","inputs",...e),mock_helper_output=(...e)=>mock_helper_attributes("output","outputs",...e),mock_helper_reset=()=>{ng_mocks_universe.A.builtDeclarations=new Map,ng_mocks_universe.A.builtProviders=new Map,ng_mocks_universe.A.cacheDeclarations=new Map,ng_mocks_universe.A.cacheProviders=new Map,ng_mocks_universe.A.config=new Map,ng_mocks_universe.A.configInstance=new Map,ng_mocks_universe.A.flags=new Set(core_config.A.flags),ng_mocks_universe.A.touches=new Set},getValVcr=e=>{const o=[];for(const t of e.__ngMocksConfig.queryScanKeys||[]){const r=e[t],n=e[`__ngMocksVcr_${t}`],s=r instanceof core_.QueryList?r.toArray():[r],c=n instanceof core_.QueryList?n.toArray():[n];for(let e=0;e!!e.__template&&!!e.__vcr&&o(e.__template)&&t(e.__vcr,e.__template),isRightTemplate=(e,o,t)=>!!e&&o instanceof core_.TemplateRef&&t(o),findDeep=(e,o,t)=>{if(!func_is_mock(e))throw new Error("Only instances of mock declarations are accepted");if(handleDirective(e,o,t))return!0;for(const[r,n]of getValVcr(e)){if(func_is_mock(r)&&findDeep(r,o,t))return!0;if(isRightTemplate(n,r,o))return t(n,r)}return!1},func_find_deep=findDeep,func_parse_template=e=>{if(e instanceof core_.TemplateRef)return e;if(func_is_mock(e)&&e.__template)return e.__template;const o=(null==e?void 0:e.nativeNode)&&e.injector;if(o){const e=core_injector(core_.TemplateRef,o);if(e)return e}const t=new Error("Unknown template has been passed, only TemplateRef or a mock structural directive are supported");throw t.param=e,t},mock_helper_hide=(e,o)=>{const t=o?func_parse_template(o):void 0;let r=!1;if(func_find_deep(e,(e=>!t||e.elementRef.nativeElement===t.elementRef.nativeElement),(e=>(e.clear(),r=!0,!1))),!r)throw new Error("Cannot find path to the TemplateRef")},mock_helper_render=(e,o,t,r)=>{const n=func_parse_template(o);if(!func_find_deep(e,(e=>e.elementRef.nativeElement===n.elementRef.nativeElement),((e,o)=>{const n=Object.assign(Object.assign({},r),{$implicit:t});return e.clear(),e.createEmbeddedView(o,n).detectChanges(),!0})))throw new Error("Cannot find path to the TemplateRef")},template_ref_detect_crawler=e=>{if("string"==typeof e)return crawl_by_id(e);if(Array.isArray(e)&&1===e.length&&"string"==typeof e[0])return crawl_by_attribute(e[0]);if(Array.isArray(e)&&2===e.length&&"string"==typeof e[0])return crawl_by_attribute_value(e[0],e[1]);if("function"==typeof e)return crawl_by_declaration(e);throw new Error("Unknown selector")},detect_template_ref=(e,o,t=0)=>r=>{try{const t=!detect_text_node(r)&&o(r)?core_injector(core_.TemplateRef,r.injector):void 0;t&&e.push(t)}catch(e){}return!!t&&e.length===t},func_is_valid_template_ref_selector=e=>"string"==typeof e||!(!Array.isArray(e)||"string"!=typeof e[0])||"function"==typeof e,mock_helper_find_template_ref_defaultNotFoundValue={},mock_helper_find_template_ref=(...e)=>{const[o,t,r]=mock_helper_func_parse_find_args(e,func_is_valid_template_ref_selector,mock_helper_find_template_ref_defaultNotFoundValue),n=[],s=template_ref_detect_crawler(t);if(nested_check(mock_helper_find(func_get_last_fixture(),o,void 0),void 0,detect_template_ref(n,s,1)),n.length>0)return n[0];if(r!==mock_helper_find_template_ref_defaultNotFoundValue)return r;throw new Error(`Cannot find a TemplateRef via ngMocks.findTemplateRef(${func_parse_find_args_name(t)})`)},mock_helper_find_template_refs=(...e)=>{const[o,t]=mock_helper_func_parse_find_args(e,func_is_valid_template_ref_selector),r=[],n=template_ref_detect_crawler(t);return nested_check(mock_helper_find(func_get_last_fixture(),o,void 0),void 0,detect_template_ref(r,n)),r},flagNames=["onMockBuilderMissingDependency","onMockInstanceRestoreNeed","onTestBedFlushNeed"],mock_helper_object={autoSpy:mock_helper_auto_spy,change:mock_helper_change,click:mock_helper_click,config:e=>{const o=ng_mocks_universe.A.global.get("flags");for(const t of flagNames)null===e[t]?o[t]=core_config.A[t]:void 0!==e[t]&&(o[t]=e[t]);null===e.mockRenderCacheSize?ng_mocks_universe.A.global.delete("mockRenderCacheSize"):void 0!==e.mockRenderCacheSize&&ng_mocks_universe.A.global.set("mockRenderCacheSize",e.mockRenderCacheSize)},crawl:mock_helper_crawl,defaultConfig:mock_helper_default_config,defaultMock:mock_helper_default_mock,event:mock_helper_event,faster:mock_helper_faster,find:mock_helper_find,findAll:mock_helper_find_all,findInstance:mock_helper_find_instance,findInstances:mock_helper_find_instances,findTemplateRef:mock_helper_find_template_ref,findTemplateRefs:mock_helper_find_template_refs,flushTestBed:mock_helper_flush_test_bed,formatHtml:mock_helper_format_html,formatText:mock_helper_format_text,get:mock_helper_get,globalExclude:mock_helper_global_exclude,globalKeep:mock_helper_global_keep,globalMock:mock_helper_global_mock,globalReplace:mock_helper_global_replace,globalWipe:mock_helper_global_wipe,guts:mock_helper_guts,hide:mock_helper_hide,ignoreOnConsole:mock_helper_console_ignore,input:mock_helper_input,output:mock_helper_output,render:mock_helper_render,reset:mock_helper_reset,reveal:mock_helper_reveal,revealAll:mock_helper_reveal_all,stub:mock_helper_stub.A,stubMember:mock_helper_stub_member.A,throwOnConsole:mock_helper_console_throw,touch:mock_helper_touch,trigger:mock_helper_trigger},ngMocks=mock_helper_object;var mock_service=__webpack_require__(839);const defaultValue={};function MockProviders(...e){return e.map((e=>MockProvider(e,defaultValue)))}function MockProvider(e,o=defaultValue,t,r={}){func_import_exists(e,"MockProvider");const{deps:n,multi:s}="boolean"==typeof r?{deps:void 0,multi:r}:Array.isArray(r)?{deps:r,multi:void 0}:r;return t?{provide:e,[t]:o,deps:n,multi:s}:(0,helper_use_factory.A)(e,(()=>(0,mock_service.K)(e)),(e=>o===defaultValue?e:e?(0,mock_helper_stub.A)(e,o):o))}const applyOverride=(e,o)=>{(0,func_is_ng_def.p)(e,"c")?testing_.TestBed.overrideComponent(e,o):(0,func_is_ng_def.p)(e,"d")?testing_.TestBed.overrideDirective(e,o):(0,func_is_ng_def.p)(e,"m")&&testing_.TestBed.overrideModule(e,o),((0,func_is_ng_def.p)(e,"t")||(0,func_is_ng_def.p)(e,"i"))&&testing_.TestBed.overrideProvider(e,o)},ng_mocks_global_overrides_applyOverrides=e=>{for(const[o,[t,r]]of(0,core_helpers.Nn)(e))testing_.TestBed.ngMocksOverrides.set(o,Object.assign(Object.assign({},r),{override:t})),applyOverride(o,t)},applyNgMocksOverrides=e=>{var o;if(null===(o=e.ngMocksOverrides)||void 0===o?void 0:o.size){ngMocks.flushTestBed();for(const[o,t]of(0,core_helpers.Nn)(e.ngMocksOverrides))applyOverride(o,t)}e.ngMocksOverrides=void 0},initTestBed=()=>{testing_.TestBed.ngMocksSelectors||(0,core_define_property.A)(testing_.TestBed,"ngMocksSelectors",new Map),testing_.TestBed.ngMocksOverrides||(0,core_define_property.A)(testing_.TestBed,"ngMocksOverrides",new Map)},generateTouches=(e,o)=>{for(const t of core_config.A.dependencies)for(const r of e[t]?(0,core_helpers.Bq)(e[t]):[]){const e=(0,func_get_type.A)(r);if((0,func_is_ng_module_def_with_providers.h)(r)&&generateTouches(r,o),!o.has(e)&&(o.add(e),"function"==typeof e)){if(!Object.prototype.hasOwnProperty.call(e,"__ngMocksTouches")){const o=new Set,t=core_reflect_meta(e);(0,core_define_property.A)(e,"__ngMocksTouches",o,!1),t&&generateTouches(t,o)}(0,core_helpers.LG)(e.__ngMocksTouches,o)}}},defineTouches=(e,o,t)=>{var r;let n=t;return!n&&ng_mocks_universe.A.getDefaults().size>0&&(n=func_extract_tokens(e._providers||(null===(r=e._compiler)||void 0===r?void 0:r.providers)).touches,n||(n=new Set,o.providers=o.providers||[],o.providers.push({provide:core_tokens.Em,useValue:n})),generateTouches(o,n)),n},applyPlatformOverrideDef=e=>{const o=(0,func_get_type.A)(e);if(testing_.TestBed.ngMocksOverrides.has(o))return;const t=core_reflect_module_resolve(o),r=get_override_def(t);r&&(testing_.TestBed.ngMocksOverrides.set(o,{set:t}),testing_.TestBed.overrideModule(o,{set:r}))},applyPlatformOverridesBasedOnProvidedIn=(e,o)=>{const t=core_reflect_provided_in(e);t&&("string"==typeof t||o.has(t))&&(testing_.TestBed.ngMocksOverrides.set(e,{}),testing_.TestBed.overrideProvider(e,MockProvider(e)))},applyPlatformOverridesBasedOnDefaults=e=>{for(const[o,[t]]of(0,core_helpers.Nn)(ng_mocks_universe.A.getDefaults()))"mock"===t&&((0,func_is_ng_def.p)(o,"i")||(0,func_is_ng_def.p)(o,"t"))&&(e.has(o)||testing_.TestBed.ngMocksOverrides.has(o)||applyPlatformOverridesBasedOnProvidedIn(o,e))},applyPlatformOverrides=(e,o)=>{if(testing_.TestBed.ngMocksOverrides){const t=ng_mocks_universe.A.touches;ng_mocks_universe.A.touches=o;for(const o of(0,core_helpers.Bq)(e.ngModule||[]))applyPlatformOverrideDef(o);applyPlatformOverridesBasedOnDefaults(o),ng_mocks_universe.A.touches=t}},ng_mocks_global_overrides_configureTestingModule=(e,o)=>t=>{var r,n;initTestBed();const s=!("object"!=typeof t||!t||t.providers&&-1!==t.providers.indexOf(MockBuilder));let c=0;const _=[];for(const e of s?["imports","declarations"]:[])for(const o of(0,core_helpers.Bq)(t[e]))o&&(_.push([(0,func_is_ng_module_def_with_providers.h)(o)?{ngModule:getSourceOfMock(o.ngModule),providers:o.providers}:getSourceOfMock(o),(0,func_is_ng_module_def_with_providers.h)(o)?o.ngModule:o,isMockNgDef((0,func_get_type.A)(o))]),c|=_[_.length-1][2]?2:1);let i=3===c?void 0:t;if(!i){let e=MockBuilder(core_tokens.gG);for(const[o,t,n]of _){const s=null===(r=t.prototype.__ngMocksConfig)||void 0===r?void 0:r.transform,c={export:!(0,func_is_ng_def.p)(o,"m"),exportAll:!1,onRoot:!0};e=n&&s?e.mock(o,s,c):n?e.mock(o,c):e.keep(o,c)}i=e.build(),i=Object.assign(Object.assign(Object.assign({},t),i),{providers:[...null!==(n=t.providers)&&void 0!==n?n:[],...i.providers]})}const a=(0,testing_.getTestBed)(),l=func_extract_tokens(i.providers),{mocks:p,overrides:u}=l,d=defineTouches(a,i,l.touches);return p&&ngMocks.flushTestBed(),u&&ng_mocks_global_overrides_applyOverrides(u),!d||a._instantiated||a._testModuleRef||applyPlatformOverrides(a,d),e.call(o,i)},ng_mocks_global_overrides_resetTestingModule=(e,o)=>()=>(ng_mocks_universe.A.global.delete("builder:config"),ng_mocks_universe.A.global.delete("builder:module"),testing_.TestBed.ngMocksSelectors=void 0,applyNgMocksOverrides(testing_.TestBed),e.call(o)),patchVcrInstance=e=>{if(!core_.ViewContainerRef.ngMocksOverridesPatched&&((0,core_define_property.A)(core_.ViewContainerRef,"ngMocksOverridesPatched",!0),e.createComponent)){const o=e.createComponent,t=(0,helper_create_clone.A)(o,void 0,void 0,(function(e,...t){var r;const n=core_injector(core_tokens.en,this.injector);return o.apply(this,[null!==(r=null==n?void 0:n.get(e))&&void 0!==r?r:e,...t])}));(0,core_define_property.A)(e.constructor.prototype,"createComponent",t,!0),(0,core_define_property.A)(e,"createComponent",t,!0)}},createComponent=(e,o)=>t=>{const r=e.call(o,t);try{const e=r.debugElement.injector.get(core_.ViewContainerRef);patchVcrInstance(e)}catch(e){}return r},viewContainerInstall=()=>{const e=core_.ViewContainerRef;if(!e.ngMocksOverridesInstalled){const o=e.__NG_ELEMENT_ID__;o&&(0,core_define_property.A)(e,"__NG_ELEMENT_ID__",(0,helper_create_clone.A)(o,void 0,void 0,((...e)=>{const t=o.apply(o,e);return patchVcrInstance(t),t})),!0),(0,core_define_property.A)(testing_.TestBed,"createComponent",createComponent(testing_.TestBed.createComponent,testing_.TestBed)),(0,core_define_property.A)(core_.ViewContainerRef,"ngMocksOverridesInstalled",!0)}},installInjector=e=>{if(e.constructor.prototype.__ngMocksInjector||!e.constructor.prototype.get)return e;(0,core_define_property.A)(e.constructor.prototype,"__ngMocksInjector",!0);const o=e.constructor.prototype.get;return e.constructor.prototype.get=(0,helper_create_clone.A)(o,void 0,void 0,(function(e,...t){const r=o.call(this,e,...t);return r&&"object"==typeof r&&"function"==typeof r.constructor&&"string"==typeof r.constructor.name&&"Injector"===r.constructor.name.slice(-8)&&installInjector(r),r})),e},install=()=>{if(!testing_.TestBed.ngMocksOverridesInstalled){const e=mock_helper_faster_install();viewContainerInstall(),-1===e.before.indexOf(ng_mocks_global_overrides_configureTestingModule)&&e.before.push(ng_mocks_global_overrides_configureTestingModule),-1===e.after.indexOf(ng_mocks_global_overrides_resetTestingModule)&&e.after.push(ng_mocks_global_overrides_resetTestingModule),(0,core_define_property.A)(testing_.TestBed,"ngMocksOverridesInstalled",!0);const o=core_.Injector.create;core_.Injector.create=(0,helper_create_clone.A)(o,void 0,void 0,((...e)=>installInjector(o.apply(core_.Injector,e))));try{core_.Injector.create({length:0,providers:[]})}catch(e){}}};function isMockedNgDefOf(e,o,t){return"function"==typeof e&&e.mockOf===o&&(!t||(0,func_is_ng_def.p)(e,t))}install();const getMock=(e,o,t)=>{if(t&&!t.has(o))throw new Error(`There is no mock for ${(0,func_get_name.A)(o)}`);let r=t?t.get(o):void 0;return r===o&&(r=void 0),r||o===e?!r&&ng_mocks_universe.A.cacheDeclarations.has(o)&&(r=ng_mocks_universe.A.cacheDeclarations.get(o)):r=e,r};function getMockedNgDefOf(e,o){var t;const r=null!==(t=e.mockOf)&&void 0!==t?t:e,n=core_injector(core_tokens.en),s=getMock(e,r,n);if(s&&!o)return s;if(s&&o&&isMockedNgDefOf(s,r,o))return s;throw new Error(`There is no mock for ${(0,func_get_name.A)(r)}`)}function isMockOf(e,o,t){return func_is_mock(e)&&e.constructor===o&&(t?(0,func_is_ng_def.p)(e.constructor,t):(0,func_is_ng_def.p)(e.constructor))}const isMockValidator=e=>!!func_is_mock(e)&&!!e.__ngMocksConfig.isValidator,mock_instance_forgot_reset=e=>{const o=[];for(;e.length>0;){const[t,r]=e.pop()||[];r===ng_mocks_universe.A.configInstance.get(t)&&o.push("function"==typeof t?(0,func_get_name.A)(t):t)}if(o.length>0){const e=ng_mocks_universe.A.global.get("flags"),t=[`MockInstance: side effects have been detected (${o.join(", ")}).`,"Forgot to add MockInstance.scope() or to call MockInstance.restore()?"].join(" ");if("warn"===e.onMockInstanceRestoreNeed)console.warn(t);else if("throw"===e.onMockInstanceRestoreNeed)throw new Error(t)}};let currentStack;ng_mocks_stack.subscribePush((e=>{currentStack=e})),ng_mocks_stack.subscribePop(((e,o)=>{for(const o of e.mockInstance||[])if(ng_mocks_universe.A.configInstance.has(o)){const e=ng_mocks_universe.A.configInstance.get(o);e.overloads.pop(),ng_mocks_universe.A.configInstance.set(o,Object.assign({},e))}currentStack=o[o.length-1]}));const parseMockInstanceArgs=e=>{const o={};return"string"==typeof e[0]?(o.key=e[0],o.value=e[1],o.accessor=e[2]):(o.value=e[0],o.value&&"object"==typeof o.value&&(o.value=o.value.init)),o},checkReset=[];let checkCollect=!1;"undefined"!=typeof beforeEach&&(beforeEach((()=>checkCollect=!0)),beforeEach((()=>mock_instance_forgot_reset(checkReset))),afterEach((()=>checkCollect=!1)));const mockInstanceConfig=(e,o,t,r)=>{var n;const s=ng_mocks_universe.A.configInstance.has(e)?ng_mocks_universe.A.configInstance.get(e):{},c=s.overloads||[];c.push([o,t,r]),s.overloads=c,ng_mocks_universe.A.configInstance.set(e,Object.assign({},s));const _=null!==(n=currentStack.mockInstance)&&void 0!==n?n:[];return _.push(e),currentStack.mockInstance=_,checkCollect&&checkReset.push([e,ng_mocks_universe.A.configInstance.get(e),currentStack]),t};function MockInstance(e,...o){if(func_import_exists(e,"MockInstance"),o.length>0){const{key:t,value:r,accessor:n}=parseMockInstanceArgs(o);return mockInstanceConfig(e,t,r,n)}const t=ng_mocks_universe.A.configInstance.get(e)||{};ng_mocks_universe.A.configInstance.set(e,Object.assign(Object.assign({},t),{overloads:[]}));for(let o=checkReset.length-1;o>=0;o-=1)checkReset[o][0]===e&&checkReset[o][2]===currentStack&&checkReset.splice(o,1)}function MockReset(){ng_mocks_universe.A.configInstance.clear()}function MockDeclarations(...e){return e.map(MockDeclaration)}function MockDeclaration(e){if((0,func_is_ng_def.p)(e,"p"))return MockPipe(e);if((0,func_is_ng_def.p)(e,"c"))return MockComponent(e);if((0,func_is_ng_def.p)(e,"d"))return MockDirective(e);throw error_jest_mock(e),new Error(["MockDeclaration does not know how to mock","function"==typeof e?(0,func_get_name.A)(e):e].join(" "))}!function(e){e.remember=function(){ng_mocks_stack.stackPush()},e.restore=function(){ng_mocks_stack.stackPop()},e.scope=function(o="case"){"all"!==o&&"suite"!==o||(beforeAll(e.remember),afterAll(e.restore)),"all"!==o&&"case"!==o||(beforeEach(e.remember),afterEach(e.restore))}}(MockInstance||(MockInstance={}));const generateTemplateAttrWrap=(e,o)=>"i"===o?`[${e}]`:`(${e})`,generateTemplateAttrWithParams=(e,o)=>{let t=` ${generateTemplateAttrWrap(e,o)}="`;return t+="i"===o?e:`__ngMocksOutput('${e}', $event)`,t+='"',t},generateTemplateAttr=(e,o,t)=>{if(!e&&"o"===t)return"";let r="";const n=null!=e?e:o;for(const e of o){const{name:o,alias:s}=(0,func_directive_io_parse.A)(e);r+=-1===n.indexOf(s||o)?"":generateTemplateAttrWithParams(s||o,t)}return r},func_generate_template=(e,{selector:o,bindings:t,inputs:r,outputs:n})=>{let s="";return"string"==typeof e?s=e:(0,func_is_ng_def.p)(e,"p")&&t&&-1!==t.indexOf("$implicit")?s=`{{ $implicit | ${core_reflect_pipe_resolve(e).name} }}`:o&&(s+=`<${o}`,s+=generateTemplateAttr(t,r,"i"),s+=generateTemplateAttr(t,n,"o"),s+=`>`),s},generateWrapperOutput=e=>(o,t)=>"function"==typeof e[o]?e[o](t):e[o]&&"object"==typeof e[o]&&"function"==typeof e[o].emit?e[o].emit(t):e[o]&&"object"==typeof e[o]&&"function"==typeof e[o].next?e[o].next(t):void(e[o]=t),generateWrapperComponent=({bindings:e,options:o,inputs:t})=>{class r{constructor(){(0,core_define_property.A)(this,"__ngMocksOutput",generateWrapperOutput(this));let o=0;if((0,helper_define_property_descriptor.A)(this,"__ngContext__",{get:()=>o,set:e=>o=e,enumerable:!1}),!e)for(const e of t||[]){let o=null;(0,helper_define_property_descriptor.A)(this,e,{get:()=>o,set:e=>o=e})}}}return(0,core_define_property.A)(r.prototype,`__ngMocks_index_${ng_mocks_universe.A.index()}`,void 0,!1),(0,core_.Component)(o)(r),r},generateWrapperDirective=({selector:e,options:o})=>{class t{}return(0,core_.Directive)({selector:e,providers:o.providers})(t),t},getCache=()=>{var e;const o=null!==(e=ng_mocks_universe.A.config.get("MockRenderCaches"))&&void 0!==e?e:[];return 0===o.length&&ng_mocks_universe.A.config.set("MockRenderCaches",o),o},checkCache=(e,o)=>{for(const t of e){if(t.cacheKey.length!==o.length)continue;let e=!0;for(let r=0;r{var n,s,c;const _=getCache(),i=[e,...null!=t?t:[null],...null!==(n=r.providers)&&void 0!==n?n:[null],...null!==(s=r.viewProviders)&&void 0!==s?s:[null]];let a=checkCache(_,i);if(a)return a;const l=o.inputs?[...o.inputs]:[],p=o.outputs?[...o.outputs]:[];if(o.hostDirectives)for(const e of o.hostDirectives)"object"==typeof e&&e.directive&&(e.inputs&&l.push(...e.inputs),e.outputs&&p.push(...e.outputs));const u=func_generate_template(e,{selector:o.selector,inputs:l,outputs:p,bindings:t}),d={providers:r.providers,selector:"mock-render",template:u,viewProviders:r.viewProviders};if(a=generateWrapperComponent(Object.assign(Object.assign({},o),{bindings:t,options:d})),(0,core_define_property.A)(a,"cacheKey",i),(0,core_define_property.A)(a,"tpl",u),o.selector&&d.providers){const e=generateWrapperDirective(Object.assign(Object.assign({},o),{bindings:t,options:d}));(0,core_define_property.A)(a,"providers",e)}return _.unshift(a),_.splice(null!==(c=ng_mocks_universe.A.global.get("mockRenderCacheSize"))&&void 0!==c?c:core_config.A.mockRenderCacheSize),a},createPropertyGet=(e,o,t)=>{const r=()=>{if("function"==typeof t[e]){if(o[`__ngMocks_${e}__origin`]!==t[e]){const r=helper_mock_service.A.createClone(t[e],o,t);(0,core_define_property.A)(o,`__ngMocks_${e}`,r),(0,core_define_property.A)(o,`__ngMocks_${e}__origin`,t[e])}return o[`__ngMocks_${e}`]}return t[e]};return(0,core_define_property.A)(r,"__ngMocksProxy",!0),r},createPropertySet=(e,o,t)=>{const r=r=>{o[`__ngMocks_${e}`]&&(o[`__ngMocks_${e}`]=void 0),o[`__ngMocks_${e}__origin`]&&(o[`__ngMocks_${e}__origin`]=void 0),t[e]=r};return(0,core_define_property.A)(r,"__ngMocksProxy",!0),r},extractAllKeys=e=>[...helper_mock_service.A.extractPropertiesFromPrototype(Object.getPrototypeOf(e)),...helper_mock_service.A.extractMethodsFromPrototype(Object.getPrototypeOf(e)),...Object.keys(e)],extractOwnKeys=e=>[...Object.getOwnPropertyNames(e),...Object.keys(e)],func_install_prop_reader=(e,o,t,r=!1)=>{if(!o)return;(0,core_define_property.A)(e,"__ngMocks__source",o);const n=extractOwnKeys(e),s=[...extractAllKeys(o),...t];for(const t of s)(r||-1===n.indexOf(t))&&((0,helper_define_property_descriptor.A)(e,t,{get:createPropertyGet(t,e,o),set:createPropertySet(t,e,o)}),n.push(t))},registerTemplateMiddleware=(e,o)=>{const t=(0,core_helpers.He)(e),r={provide:e,useExisting:t};o.providers=[...o.providers||[],r];let n={};try{const t=testing_.TestBed.ngMocksOverrides,{override:s}=t.get(e);n=Object.assign({},s.set),n.providers=n.providers?[...n.providers,r]:o.providers}catch(e){}const s=!0===o.__ngMocksStandalone;((0,func_is_ng_def.p)(e,"c")?core_.Component:core_.Directive)(Object.assign(Object.assign(Object.assign({},o),n),s?{standalone:s}:{}))(t),testing_.TestBed.configureTestingModule({[s?"imports":"declarations"]:[t]})},func_reflect_template=e=>{var o;if(!(0,func_is_ng_def.p)(e,"c")&&!(0,func_is_ng_def.p)(e,"d"))return{};const t=core_reflect_directive_resolve(e),r={};for(const e of Object.keys(t))"standalone"!==e?r[e]=t[e]:(0,core_define_property.A)(r,"__ngMocksStandalone",!!t[e]);return r.selector&&/[\s,[\]]/.test(r.selector)&&(r.selector=""),r.selector||(r.selector=(null===(o=testing_.TestBed.ngMocksSelectors)||void 0===o?void 0:o.get(e))||"",r.selector||(r.selector=`ng-mocks-${e.name}`,registerTemplateMiddleware(e,r),testing_.TestBed.ngMocksSelectors&&testing_.TestBed.ngMocksSelectors.set(e,r.selector))),r},renderDeclaration=(e,o,t)=>{e.point=e.debugElement.children[0]&&"#text"!==e.debugElement.children[0].nativeElement.nodeName&&"#comment"!==e.debugElement.children[0].nativeElement.nodeName?e.debugElement.children[0]:e.debugElement,(0,func_is_ng_def.p)(o,"d")?(0,helper_define_property_descriptor.A)(e.point,"componentInstance",{get:()=>ngMocks.get(e.point,o)}):(0,func_is_ng_def.p)(o,"p")&&(0,helper_define_property_descriptor.A)(e.point,"componentInstance",{get:()=>ngMocks.findInstance(e.point,o)}),tryWhen(!t,(()=>func_install_prop_reader(e.componentInstance,e.point.componentInstance,[])))},renderInjection=(e,o,t)=>{let r;try{r=(0,core_helpers.Ah)(o)}catch(e){if((0,func_is_ng_def.p)(o,"p"))throw new Error([`Cannot render ${(0,func_get_name.A)(o)}.`,"Did you forget to set $implicit param, or add the pipe to providers?","https://ng-mocks.sudo.eu/guides/pipe"].join(" "));throw e}t&&ngMocks.stub(r,t),e.point=(0,mock_service.K)(core_.DebugElement,{childNodes:[],children:[],componentInstance:r,nativeElement:(0,mock_service.K)(HTMLElement)}),func_install_prop_reader(e.componentInstance,e.point.componentInstance,[],!0)},tryWhen=(e,o)=>{if(e)try{o()}catch(e){}},fixtureMessage=["Forgot to flush TestBed?","MockRender cannot be used without a reset after TestBed.get / TestBed.inject / TestBed.createComponent and another MockRender in the same test.","If you want to mock a service before rendering, consider usage of MockRenderFactory or MockInstance.","To flush TestBed, add a call of ngMocks.flushTestBed() before the call of MockRender, or pass `reset: true` to MockRender options."].join(" "),handleFixtureError=e=>{const o=new Error(fixtureMessage);throw(0,core_define_property.A)(o,"parent",e),o},flushTestBed=e=>{const o=ng_mocks_universe.A.global.get("flags"),t=(0,testing_.getTestBed)();e.reset||!t._instantiated&&!t._testModuleRef?ngMocks.flushTestBed():"throw"!==o.onTestBedFlushNeed&&(t._instantiated||t._testModuleRef)&&("warn"===o.onTestBedFlushNeed&&console.warn(fixtureMessage),ngMocks.flushTestBed())},generateFactoryInstall=(e,o)=>()=>{var t;const r=(0,testing_.getTestBed)(),n=(null===(t=r._compiler)||void 0===t?void 0:t.declarations)||r.declarations||r._declarations;if(!n||-1===n.indexOf(e)){flushTestBed(o);try{const o=[];e.providers&&o.push(e.providers),o.push(e),testing_.TestBed.configureTestingModule({declarations:o})}catch(e){handleFixtureError(e)}}},generateFactory=(e,o,t,r)=>{const n=(r,s)=>{n.configureTestBed();const c=testing_.TestBed.createComponent(e);return func_install_prop_reader(c.componentInstance,null!=r?r:{},null!=o?o:[]),(0,core_define_property.A)(c,"ngMocksStackId",ng_mocks_universe.A.global.get("bullet:stack:id")),(void 0===s||s)&&c.detectChanges(),"string"==typeof t||(0,func_is_ng_def.p)(t,"c")||(0,func_is_ng_def.p)(t,"d")||e.tpl&&(0,func_is_ng_def.p)(t,"p")?renderDeclaration(c,t,r):renderInjection(c,t,r),c};return n.declaration=e,n.bindings=o,n.configureTestBed=generateFactoryInstall(e,r),n};function MockRenderFactory(e,o,t={}){func_import_exists(e,"MockRender");const r="string"==typeof e||(0,func_is_ng_def.p)(e,"t")?{}:func_reflect_template(e),n=func_create_wrapper(e,r,o,t),s=generateFactory(n,o,e,t);return"root"!==ng_mocks_stack.current().level&&!1!==t.configureTestBed&&s.configureTestBed(),s}function MockRender(e,o,t=!0){const r=0===arguments.length?"":e,n=o&&"object"==typeof o?Object.keys(o):o,s="boolean"==typeof t?{detectChanges:t}:Object.assign({},t);return MockRenderFactory(r,n,s)(o,s.detectChanges)}var __webpack_exports__IMockBuilder=__webpack_exports__.rX,__webpack_exports__IMockBuilderConfig=__webpack_exports__.HA,__webpack_exports__IMockBuilderConfigAll=__webpack_exports__.Wn,__webpack_exports__IMockBuilderConfigComponent=__webpack_exports__.Me,__webpack_exports__IMockBuilderConfigDirective=__webpack_exports__.I7,__webpack_exports__IMockBuilderConfigModule=__webpack_exports__.tv,__webpack_exports__IMockBuilderExtended=__webpack_exports__.OG,__webpack_exports__IMockBuilderProvider=__webpack_exports__.sF,__webpack_exports__IMockBuilderResult=__webpack_exports__.me,__webpack_exports__LegacyControlValueAccessor=__webpack_exports__.bk,__webpack_exports__Mock=__webpack_exports__.JT,__webpack_exports__MockBuilder=__webpack_exports__._V,__webpack_exports__MockComponent=__webpack_exports__.Am,__webpack_exports__MockComponents=__webpack_exports__.$u,__webpack_exports__MockControlValueAccessor=__webpack_exports__.D2,__webpack_exports__MockDeclaration=__webpack_exports__.dw,__webpack_exports__MockDeclarations=__webpack_exports__.uV,__webpack_exports__MockDirective=__webpack_exports__.Cc,__webpack_exports__MockDirectives=__webpack_exports__.nr,__webpack_exports__MockInstance=__webpack_exports__.Wm,__webpack_exports__MockModule=__webpack_exports__.BN,__webpack_exports__MockPipe=__webpack_exports__.ZJ,__webpack_exports__MockPipes=__webpack_exports__.yI,__webpack_exports__MockProvider=__webpack_exports__.Qo,__webpack_exports__MockProviders=__webpack_exports__.dD,__webpack_exports__MockRender=__webpack_exports__.Ty,__webpack_exports__MockRenderFactory=__webpack_exports__.P0,__webpack_exports__MockReset=__webpack_exports__.mB,__webpack_exports__MockService=__webpack_exports__.KH,__webpack_exports__MockValidator=__webpack_exports__.b6,__webpack_exports__MockedComponent=__webpack_exports__.Je,__webpack_exports__MockedDirective=__webpack_exports__.T4,__webpack_exports__MockedModule=__webpack_exports__.qZ,__webpack_exports__MockedPipe=__webpack_exports__.cm,__webpack_exports__NG_MOCKS=__webpack_exports__.en,__webpack_exports__NG_MOCKS_GUARDS=__webpack_exports__.ZG,__webpack_exports__NG_MOCKS_INTERCEPTORS=__webpack_exports__.rO,__webpack_exports__NG_MOCKS_OVERRIDES=__webpack_exports__.So,__webpack_exports__NG_MOCKS_RESOLVERS=__webpack_exports__.C3,__webpack_exports__NG_MOCKS_ROOT_PROVIDERS=__webpack_exports__.gG,__webpack_exports__NG_MOCKS_TOUCHES=__webpack_exports__.Em,__webpack_exports__getInjection=__webpack_exports__.Ah,__webpack_exports__getMockedNgDefOf=__webpack_exports__.xz,__webpack_exports__getSourceOfMock=__webpack_exports__.VK,__webpack_exports__getTestBedInjection=__webpack_exports__.d5,__webpack_exports__isMockControlValueAccessor=__webpack_exports__.IA,__webpack_exports__isMockNgDef=__webpack_exports__.Bt,__webpack_exports__isMockOf=__webpack_exports__.AW,__webpack_exports__isMockValidator=__webpack_exports__.lt,__webpack_exports__isMockedNgDefOf=__webpack_exports__.Fk,__webpack_exports__isNgDef=__webpack_exports__.pA,__webpack_exports__isNgInjectionToken=__webpack_exports__.SM,__webpack_exports__ngMocks=__webpack_exports__.H5;export{__webpack_exports__IMockBuilder as IMockBuilder,__webpack_exports__IMockBuilderConfig as IMockBuilderConfig,__webpack_exports__IMockBuilderConfigAll as IMockBuilderConfigAll,__webpack_exports__IMockBuilderConfigComponent as IMockBuilderConfigComponent,__webpack_exports__IMockBuilderConfigDirective as IMockBuilderConfigDirective,__webpack_exports__IMockBuilderConfigModule as IMockBuilderConfigModule,__webpack_exports__IMockBuilderExtended as IMockBuilderExtended,__webpack_exports__IMockBuilderProvider as IMockBuilderProvider,__webpack_exports__IMockBuilderResult as IMockBuilderResult,__webpack_exports__LegacyControlValueAccessor as LegacyControlValueAccessor,__webpack_exports__Mock as Mock,__webpack_exports__MockBuilder as MockBuilder,__webpack_exports__MockComponent as MockComponent,__webpack_exports__MockComponents as MockComponents,__webpack_exports__MockControlValueAccessor as MockControlValueAccessor,__webpack_exports__MockDeclaration as MockDeclaration,__webpack_exports__MockDeclarations as MockDeclarations,__webpack_exports__MockDirective as MockDirective,__webpack_exports__MockDirectives as MockDirectives,__webpack_exports__MockInstance as MockInstance,__webpack_exports__MockModule as MockModule,__webpack_exports__MockPipe as MockPipe,__webpack_exports__MockPipes as MockPipes,__webpack_exports__MockProvider as MockProvider,__webpack_exports__MockProviders as MockProviders,__webpack_exports__MockRender as MockRender,__webpack_exports__MockRenderFactory as MockRenderFactory,__webpack_exports__MockReset as MockReset,__webpack_exports__MockService as MockService,__webpack_exports__MockValidator as MockValidator,__webpack_exports__MockedComponent as MockedComponent,__webpack_exports__MockedDirective as MockedDirective,__webpack_exports__MockedModule as MockedModule,__webpack_exports__MockedPipe as MockedPipe,__webpack_exports__NG_MOCKS as NG_MOCKS,__webpack_exports__NG_MOCKS_GUARDS as NG_MOCKS_GUARDS,__webpack_exports__NG_MOCKS_INTERCEPTORS as NG_MOCKS_INTERCEPTORS,__webpack_exports__NG_MOCKS_OVERRIDES as NG_MOCKS_OVERRIDES,__webpack_exports__NG_MOCKS_RESOLVERS as NG_MOCKS_RESOLVERS,__webpack_exports__NG_MOCKS_ROOT_PROVIDERS as NG_MOCKS_ROOT_PROVIDERS,__webpack_exports__NG_MOCKS_TOUCHES as NG_MOCKS_TOUCHES,__webpack_exports__getInjection as getInjection,__webpack_exports__getMockedNgDefOf as getMockedNgDefOf,__webpack_exports__getSourceOfMock as getSourceOfMock,__webpack_exports__getTestBedInjection as getTestBedInjection,__webpack_exports__isMockControlValueAccessor as isMockControlValueAccessor,__webpack_exports__isMockNgDef as isMockNgDef,__webpack_exports__isMockOf as isMockOf,__webpack_exports__isMockValidator as isMockValidator,__webpack_exports__isMockedNgDefOf as isMockedNgDefOf,__webpack_exports__isNgDef as isNgDef,__webpack_exports__isNgInjectionToken as isNgInjectionToken,__webpack_exports__ngMocks as ngMocks}; ++import*as __WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__ from"@angular/core";import*as __WEBPACK_EXTERNAL_MODULE__angular_core_testing_89899de6__ from"@angular/core/testing";import*as __WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__ from"@angular/forms";import*as __WEBPACK_EXTERNAL_MODULE__angular_common_d12e0fe1__ from"@angular/common";import*as __WEBPACK_EXTERNAL_MODULE__angular_platform_browser_bc6fa964__ from"@angular/platform-browser";var __webpack_modules__={295:(e,o,t)=>{t.d(o,{A:()=>r});const r={flags:["cacheModule","cacheComponent","cacheDirective","cacheProvider","correctModuleExports"],mockRenderCacheSize:25,neverMockModule:["ApplicationModule","CommonModule","BrowserModule","_ApplicationModule","_CommonModule","_BrowserModule"],neverMockProvidedFunction:["DomRendererFactory2","EventManager","Injector","RendererFactory2","Sanitizer","DomSanitizer","DomSanitizerImpl","ApplicationInitStatus","ApplicationRef","Compiler","IterableDiffers","KeyValueDiffers","_DomRendererFactory2","_EventManager","_Injector","_Sanitizer","_DomSanitizer","_DomSanitizerImpl","_ApplicationInitStatus","_ApplicationRef","_Compiler","_IterableDiffers","_KeyValueDiffers"],neverMockToken:["InjectionToken Set Injector scope.","InjectionToken EventManagerPlugins","InjectionToken HammerGestureConfig","InjectionToken AppId","InjectionToken DefaultCurrencyCode","InjectionToken LocaleId","InjectionToken SCHEDULER_TOKEN"],onMockBuilderMissingDependency:"throw",onMockInstanceRestoreNeed:"warn",onTestBedFlushNeed:"warn",dependencies:["declarations","hostDirectives","entryComponents","bootstrap","providers","viewProviders","imports","exports"]}},174:(e,o,t)=>{t.d(o,{A:()=>n});var r=t(932);const n=(e,o,t,n=!1)=>{r.A.definePropertyDescriptor(e,o,{configurable:!0,enumerable:n,value:t,writable:!0})}},456:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{Ah:()=>getInjection,Bq:()=>flatten,He:()=>extendClass,LG:()=>mapValues,Nn:()=>mapEntries,by:()=>extractDependency,d4:()=>mapKeys,d5:()=>getTestBedInjection});var _angular_core_testing__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(957),_core_define_property__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(174),_core_reflect_parameters_resolve__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(749),_func_get_global__WEBPACK_IMPORTED_MODULE_4__=__webpack_require__(102),_func_get_name__WEBPACK_IMPORTED_MODULE_5__=__webpack_require__(970),_ng_mocks_universe__WEBPACK_IMPORTED_MODULE_3__=__webpack_require__(73);const getTestBedInjection=e=>{try{return getInjection(e)}catch(e){return}},getInjection=e=>{const o=(0,_angular_core_testing__WEBPACK_IMPORTED_MODULE_0__.getTestBed)();return o.inject?o.inject(e):o.get(e)},flatten=(e,o=[])=>{if(Array.isArray(e))for(const t of e)flatten(t,o);else if(null!==e&&"object"==typeof e&&Array.isArray(e.ɵproviders))for(const t of e.ɵproviders)flatten(t,o);else o.push(e);return o},mapKeys=e=>{const o=[];return e.forEach(((e,t)=>o.push(t))),o},mapValues=(e,o)=>{const t=[];return o?e.forEach((e=>{o.add(e)})):e.forEach((e=>{t.push(e)})),t},mapEntries=(e,o)=>{const t=[];return o?e.forEach(((e,t)=>o.set(t,e))):e.forEach(((e,o)=>t.push([o,e]))),t},extractDependencyArray=(e,o)=>{for(const t of e){const e=t&&"object"==typeof t?t.ngMetadataName:void 0;"Optional"!==e&&"SkipSelf"!==e&&"Self"!==e&&o.add(t)}},extractDependency=(e,o)=>{if(o)for(const t of e)Array.isArray(t)?extractDependencyArray(t,o):o.add(t)},extendClassicClass=base=>{let child;const index=_ng_mocks_universe__WEBPACK_IMPORTED_MODULE_3__.A.index(),glb=(0,_func_get_global__WEBPACK_IMPORTED_MODULE_4__.A)();glb.ngMocksParent=base;try{eval(`\n var glb = typeof window === 'undefined' ? global : window;\n class MockMiddleware${index} extends glb.ngMocksParent {};\n glb.ngMocksResult = MockMiddleware${index};\n `),child=glb.ngMocksResult}catch(e){class o extends glb.ngMocksParent{}child=o}finally{glb.ngMocksResult=void 0,glb.ngMocksParent=void 0}return(0,_core_define_property__WEBPACK_IMPORTED_MODULE_1__.A)(child.prototype,`__ngMocks_index_${index}`,void 0,!1),child},extendClass=e=>{const o=extendClassicClass(e);(0,_core_define_property__WEBPACK_IMPORTED_MODULE_1__.A)(o,"name",`MockMiddleware${(0,_func_get_name__WEBPACK_IMPORTED_MODULE_5__.A)(e)}`,!0);const t=(0,_core_reflect_parameters_resolve__WEBPACK_IMPORTED_MODULE_2__.A)(e);return t.length>0&&(0,_core_define_property__WEBPACK_IMPORTED_MODULE_1__.A)(o,"parameters",[...t]),o}},749:(e,o,t)=>{t.d(o,{A:()=>n});var r=t(673);const n=e=>{var o;return null!==(o=(0,r.A)(e).parameters)&&void 0!==o?o:[]}},763:(e,o,t)=>{t.d(o,{C3:()=>i,Em:()=>s,So:()=>c,ZG:()=>_,en:()=>n,gG:()=>l,rO:()=>a});var r=t(614);const n=new r.InjectionToken("NG_MOCKS");n.__ngMocksSkip=!0;const s=new r.InjectionToken("NG_MOCKS_TOUCHES");s.__ngMocksSkip=!0;const c=new r.InjectionToken("NG_MOCKS_OVERRIDES");c.__ngMocksSkip=!0;const _=new r.InjectionToken("NG_MOCKS_GUARDS");_.__ngMocksSkip=!0;const i=new r.InjectionToken("NG_MOCKS_RESOLVERS");i.__ngMocksSkip=!0;const a=new r.InjectionToken("NG_MOCKS_INTERCEPTORS");a.__ngMocksSkip=!0;const l=new r.InjectionToken("NG_MOCKS_ROOT_PROVIDERS");l.__ngMocksSkip=!0},439:(e,o,t)=>{function r({name:e,alias:o,required:t},r=!1){return t?{name:e,alias:o,required:t}:o&&e!==o?r?o:`${e}:${o}`:r?"":e}t.d(o,{A:()=>r})},184:(e,o,t)=>{function r(e){if("string"==typeof e){const[o,t]=e.split(":").map((e=>e.trim()));return o!==t&&t?{name:o,alias:t}:{name:o}}return e}t.d(o,{A:()=>r})},285:(e,o,t)=>{t.d(o,{A:()=>r});const r=e=>"function"==typeof e&&e.__forward_ref__?e():e},102:(e,o,t)=>{t.d(o,{A:()=>r});const r=()=>"undefined"==typeof window?t.g:window},970:(e,o,t)=>{t.d(o,{A:()=>n});const r=new RegExp("[^0-9a-z]+","mgi"),n=e=>{let o;return"function"==typeof e&&e.name?o=e.name:"function"==typeof e?o="arrowFunction":"object"==typeof e&&e&&"InjectionToken"===e.ngMetadataName?o=e._desc:"object"==typeof e&&e&&"function"==typeof e.constructor&&(o=e.constructor.name),o||(o="unknown"),o.replace(r,"_")}},297:(e,o,t)=>{t.d(o,{A:()=>n});var r=t(659);const n=e=>e&&"object"==typeof e&&e.provide?e.provide:(0,r.h)(e)?e.ngModule:e&&"object"==typeof e&&e.directive?e.directive:e},218:(e,o,t)=>{t.d(o,{p:()=>p});var r=t(152),n=t(673);const s=(e,o)=>{const{decorators:t}=(0,n.A)(e);if(0===t.length)return!1;let r=1;if("Injectable"===o&&-1!==t.indexOf("Injectable"))return!0;for(;"Injectable"===t[t.length-r];)r+=1;return t[t.length-r]===o},c=(e,o)=>(!o||"m"===o)&&s(e,"NgModule"),_=(e,o)=>(!o||"c"===o)&&s(e,"Component"),i=(e,o)=>(!o||"d"===o)&&s(e,"Directive"),a=(e,o)=>(!o||"p"===o)&&s(e,"Pipe"),l=(e,o)=>(!o||"i"===o)&&s(e,"Injectable");function p(e,o){if("t"===o)return(0,r.S)(e);if("function"!=typeof e)return!1;const t=c(e,o),n=_(e,o),s=i(e,o),p=a(e,o),u=l(e,o);return t||n||s||p||u}},152:(e,o,t)=>{t.d(o,{S:()=>r});const r=e=>e&&"object"==typeof e&&"InjectionToken"===e.ngMetadataName},659:(e,o,t)=>{t.d(o,{h:()=>r});const r=e=>e&&"object"==typeof e&&"function"==typeof e.ngModule},73:(e,o,t)=>{t.d(o,{A:()=>p});var r=t(295),n=t(102),s=t(970);const c=e=>()=>(_.global.has(e)||_.global.set(e,new Map),_.global.get(e));(0,n.A)().ngMocksUniverse=(0,n.A)().ngMocksUniverse||{};const _=(0,n.A)().ngMocksUniverse;_.builtDeclarations=new Map,_.builtProviders=new Map,_.cacheDeclarations=new Map,_.cacheProviders=new Map,_.config=new Map,_.configInstance=new Map,_.flags=new Set(r.A.flags),_.global=new Map,_.touches=new Set,_.global.set("flags",{onMockBuilderMissingDependency:r.A.onMockBuilderMissingDependency,onMockInstanceRestoreNeed:r.A.onMockInstanceRestoreNeed,onTestBedFlushNeed:r.A.onTestBedFlushNeed}),_.getOverrides=c("overrides"),_.getDefaults=c("defaults"),_.getConfigMock=c("configMock");const i=e=>{{const o=_.getDefaults().get(e);if(o)return o}{const o="function"==typeof e?_.getDefaults().get(`@${(0,s.A)(e)}`):void 0;if(o)return o}return[]};_.getResolution=e=>{const o=_.config.get("ngMocksDepsResolution");if(null==o?void 0:o.has(e))return o.get(e);const[t]=i(e);return t},_.getBuildDeclaration=e=>{if(_.builtDeclarations.has(e))return _.builtDeclarations.get(e);const[o,t]=i(e);return"exclude"===o?null:o&&"keep"!==o?"replace"===o?t:void 0:e},_.hasBuildDeclaration=e=>{if(_.builtDeclarations.has(e))return void 0!==_.builtDeclarations.get(e);const[o]=i(e);return!!o&&"mock"!==o};const a=e=>_.hasBuildDeclaration(e),l=e=>_.getBuildDeclaration(e);_.isExcludedDef=e=>{const o=_.getResolution(e);return(!o||"exclude"===o)&&a(e)&&null===l(e)},_.isProvidedDef=e=>a(e)&&null!==l(e),_.getDefaults().set("@StoreDevtoolsModule",["exclude"]),_.indexValue=0,_.index=()=>_.indexValue++;const p=_},589:(e,o,t)=>{t.d(o,{A:()=>n});var r=t(20);const n=(e,o,t,n)=>{var s;const c=null!==(s=(0,r.A)(e,o))&&void 0!==s?s:{};if(!n&&c.set&&c.set.__ngMocksProxy)return c.set(t),t;const _={configurable:!0,enumerable:!0};return"get"===n&&c.set?_.set=c.set:"set"===n&&c.get&&(_.get=c.get),n?_[n]=t:(_.writable=!0,_.value=t),Object.defineProperty(e,o,_),t}},195:(e,o,t)=>{t.d(o,{A:()=>_});var r=t(331),n=t(794),s=t(20),c=t(932);const _=(e,o,t)=>{if("string"==typeof o)return c.A.mock(e,o,t);let _=e,i=o;const a=["__zone_symbol__unconfigurables"];"function"==typeof o&&(_=c.A.createClone(o),i=e,a.push(...Object.getOwnPropertyNames(_)));const l=[...(0,r.A)(i),...(0,n.A)(i)];for(const e of l){const o=-1===a.indexOf(e)?(0,s.A)(i,e):void 0;o&&Object.prototype.hasOwnProperty.call(o,"value")&&void 0===o.value||c.A.definePropertyDescriptor(_,e,o)}return _}},760:(e,o,t)=>{t.d(o,{A:()=>s});var r=t(73),n=t(589);const s=e=>{const o=[],t=r.A.configInstance.get(e);if(null==t?void 0:t.overloads)for(const[e,r,s]of t.overloads)e?o.push((o=>{(0,n.A)(o,e,r,s)})):o.push(r);return o}},365:(e,o,t)=>{t.d(o,{A:()=>_});var r=t(6),n=t(331),s=t(794),c=t(20);const _=(e,o,t,_)=>{const i=function(...r){return(_||e).apply(o===this?t:this,r)};for(const o of[...(0,n.A)(e),...(0,s.A)(e)]){const t=(0,c.A)(e,o);(0,r.A)(i,o,t)}return i}},6:(e,o,t)=>{t.d(o,{A:()=>n});var r=t(20);const n=(e,o,t)=>{if(!t||!e)return!1;if(Object.defineProperty){const n=(0,r.A)(e,o);if(!1===(null==n?void 0:n.configurable))return!1;Object.defineProperty(e,o,Object.assign(Object.assign(Object.assign({},t),{configurable:!0}),void 0===t.get&&void 0===t.set||!1===t.writable?{writable:!0}:{}))}else e[o]=t.value;return!0}},331:(e,o,t)=>{t.d(o,{A:()=>_});var r=t(970);const n=["sanitize","bypassSecurityTrustHtml","bypassSecurityTrustStyle","bypassSecurityTrustScript","bypassSecurityTrustUrl","bypassSecurityTrustResourceUrl"],s={DomSanitizer:n,Sanitizer:n},c=e=>{var o;const t=Object.getOwnPropertyNames(e);for(const n of null!==(o=s[(0,r.A)(e)])&&void 0!==o?o:[])t.push(n);return t},_=e=>{const o=[];let t=e;for(;t&&null!==Object.getPrototypeOf(t);){for(const e of c(t)){if("constructor"===e)continue;const r=Object.getOwnPropertyDescriptor(t,e);r&&(r.get||r.set)||-1!==o.indexOf(e)||o.push(e)}t=Object.getPrototypeOf(t)}return o}},794:(e,o,t)=>{t.d(o,{A:()=>r});const r=e=>{const o=[];let t=e;for(;t&&null!==Object.getPrototypeOf(t);){for(const e of Object.getOwnPropertyNames(t)){if("constructor"===e)continue;const r=Object.getOwnPropertyDescriptor(t,e);r&&(r.get||r.set)&&-1===o.indexOf(e)&&o.push(e)}t=Object.getPrototypeOf(t)}return o}},20:(e,o,t)=>{t.d(o,{A:()=>r});const r=(e,o)=>{let t=e;for(;t&&null!==Object.getPrototypeOf(t);){const e=Object.getOwnPropertyDescriptor(t,o);if(e)return e;t=Object.getPrototypeOf(t)}}},932:(e,o,t)=>{t.d(o,{A:()=>A,O:()=>M});var r=t(102),n=t(365),s=t(174),c=t(970),_=t(6),i=t(331),a=t(794),l=t(20);const p=(e,o=!1)=>{const t=p.customMockFunction&&!o?p.customMockFunction(e):e=>(n&&n(e),r);let r,n;return(0,s.A)(t,"__ngMocks",!0),(0,s.A)(t,"__ngMocksSet",(e=>n=e)),(0,s.A)(t,"__ngMocksGet",(e=>r=e)),t},u=p;var d=t(763),f=t(218),g=t(73);const k=["canActivate","canActivateChild","canDeactivate","canMatch","canLoad"],m=(e,o)=>Array.isArray(e[o])?(e=>{const o=[];for(const t of e)!g.A.isProvidedDef(t)&&g.A.isExcludedDef(d.ZG)||(o.push(t),(0,f.p)(t)||g.A.touches.add(t));return o})(e[o]):e[o],h=(e,o)=>{if(g.A.cacheDeclarations.has(e))return g.A.cacheDeclarations.get(e);if("object"!=typeof e)return e;if(o.has(e))return e;let t,r=!1;return Array.isArray(e)?[r,t]=((e,o,t)=>{const r=[];let n=!1;e.set(o,r);for(const s of o)g.A.isExcludedDef(s)?n=n||!0:(r.push(t(s,e)),n=n||r[r.length-1]!==s);return[n,r]})(o,e,h):e&&([r,t]=((e,o,t)=>{let r={},n=!1;e.set(o,r);for(const s of Object.keys(o))g.A.isExcludedDef(o[s])?n=n||!0:(r[s]=t(o[s],e),n=n||r[s]!==o[s]);for(const e of k){const o=m(r,e);o&&r[e].length!==o.length&&(n=n||!0,r=Object.assign(Object.assign({},r),{[e]:o}))}if("object"==typeof r.resolve&&r.resolve){const e={};let o=!1;for(const t of Object.keys(r.resolve)){const n=r.resolve[t];g.A.isProvidedDef(n)||!g.A.isExcludedDef(d.C3)?(e[t]=n,(0,f.p)(n)||g.A.touches.add(n)):o=o||!0}o&&(n=n||!0,r=Object.assign(Object.assign({},r),{resolve:e}))}return[n,r]})(o,e,h)),r?(Object.setPrototypeOf(t,Object.getPrototypeOf(e)),t):e};var v=t(663),b=t(465);(0,r.A)().ngMockshelperMockService=(0,r.A)().ngMockshelperMockService||{mockFunction:u,registerMockFunction:e=>{(0,r.A)().ngMockshelperMockService.mockFunction.customMockFunction=e},createClone:n.A,createMockFromPrototype:e=>{const o=(0,c.A)(e),t={};(0,s.A)(t,"__ngMocks",!0);const r=A.extractMethodsFromPrototype(e);for(const e of r)A.mock(t,e,o);const n=A.extractPropertiesFromPrototype(e);for(const e of n)A.mock(t,e,"get",o),A.mock(t,e,"set",o);return Object.setPrototypeOf(t,e),t},definePropertyDescriptor:_.A,extractMethodsFromPrototype:i.A,extractPropertiesFromPrototype:a.A,extractPropertyDescriptor:l.A,mock:(e,o,...t)=>{const{accessType:r,mockName:n}=(e=>{let o,t;return e.length>0&&"get"!==e[0]&&"set"!==e[0]?t=e[0]:e.length>0&&("get"===e[0]||"set"===e[0])&&(o=e[0],t=e[1]),{accessType:o,mockName:t}})(t),s=Object.getOwnPropertyDescriptor(e,o);if(s&&s[r||"value"])return s[r||"value"];const _=((e,o,t,r)=>`${null!=o?o:"function"==typeof t.prototype?t.prototype.name:(0,c.A)(t)}.${e}${null!=r?r:""}`)(o,n,e,r),i=A.mockFunction(_,!!r),a=((e,o,t)=>Object.assign(Object.assign(Object.assign(Object.assign({},"get"===t&&e&&e.set?{set:e.set}:{}),"set"===t&&e&&e.get?{get:e.get}:{}),t?{}:{writable:!0}),{[t||"value"]:o,configurable:!0,enumerable:!0}))(s,i,r);return a.get&&a.set&&a.get.__ngMocks&&a.set.__ngMocks&&a.set.__ngMocksSet((e=>a.get.__ngMocksGet(e))),Object.defineProperty(e,o,a),i},replaceWithMocks:e=>{const o=new Map,t=h(e,o);return o.clear(),t},resolveProvider:v.A,useFactory:b.A};const A=(0,r.A)().ngMockshelperMockService;function M(e){(0,r.A)().ngMockshelperMockService.registerMockFunction(e)}},663:(e,o,t)=>{t.d(o,{A:()=>u});var r=t(456),n=t(763),s=t(285),c=t(297),_=t(152),i=t(73),a=t(932),l=t(415);const p=(e,o,t)=>{let r=!1,n=!e;return o&&e&&!n&&(n=((e,o,...t)=>{for(const r of t)if(e[r]!==o[r])return!0;return!1})(o,e,"provide","useValue","useClass","useExisting","useFactory","deps")),(o===t&&e!==o||o!==t&&n)&&(r=!0),!r},u=(e,o,t)=>{const{provide:u,multi:d,change:f}=((e,o)=>{const t=(0,c.A)(e);return{change:()=>{o&&o()},multi:e!==t&&!!e.multi,provide:t}})(e,t);if(((e,o)=>null===i.A.builtProviders.get(o)||(o!==e&&e.deps&&(0,r.by)(e.deps,i.A.config.get("ngMocksDeps")),((e,o)=>{if(((e,o)=>i.A.builtProviders.has(n.rO)&&null===i.A.builtProviders.get(n.rO)&&(0,_.S)(o)&&"InjectionToken HTTP_INTERCEPTORS"===o.toString()&&o!==e)(e,o)){if(e.useFactory||e.useValue)return!0;const o=(0,s.A)(e.useExisting)||e.useClass;if(!i.A.builtProviders.has(o)||null===i.A.builtProviders.get(o))return!0}return!1})(e,o)))(e,u))return f();if(((e,o)=>{var t;return!(!e||"object"!=typeof e||!e.useExisting||!e.useExisting.mockOf&&(i.A.getResolution(o)&&!(null===(t=i.A.config.get(o))||void 0===t?void 0:t.__internal)||"keep"!==i.A.getResolution((0,s.A)(e.useExisting))))})(e,u))return i.A.touches.add(u),e;if(o.has(u))return((e,o)=>{let t=o;const r=i.A.builtProviders.get(e);return r&&(t=r),"function"==typeof t&&(t={provide:e,useClass:t}),t})(u,o.get(u));const g=((e,o,t)=>{var r;let n=((e,o)=>{if(i.A.builtProviders.has(o)){const t=i.A.builtProviders.get(o);return t===o?e:t}})(e,o);return!n&&i.A.flags.has("skipMock")&&"mock"!==i.A.getResolution(o)&&(null===(r=i.A.config.get("ngMocksDepsSkip"))||void 0===r||r.add(o),n=e),n||(n=(0,l.A)(e)),n=((e,o,t)=>{if(o!==e&&t&&t.useValue){const e=a.A.replaceWithMocks(t.useValue);return e===t.useValue?t:Object.assign(Object.assign({},t),{useValue:e})}return t})(e,o,n),p(n,e,o)||t(),n&&i.A.touches.add(o),n})(e,u,f);return d&&"object"==typeof g?Object.assign(Object.assign({},g),{multi:d}):g}},465:(e,o,t)=>{t.d(o,{A:()=>p});var r=t(614),n=t(456),s=t(152),c=t(73),_=t(195),i=t(760),a=t(839);const l=e=>(0,s.S)(e)||"string"==typeof e,p=(e,o,t)=>({deps:[r.Injector],provide:e,useFactory:r=>{const s=o?o():(0,a.K)(e),p=c.A.getOverrides().get(e),u=p?(0,n.LG)(p):[];return t&&u.push(t),u.push(...(0,i.A)(e)),((e,o,t,r,n)=>{let s=o;for(const o of t){const t=o(s,r);l(e)?s=t:o!==n?t&&(s=(0,_.A)(s,t)):s=t}return s})(e,s,u,r,t)}})},415:(e,o,t)=>{t.d(o,{A:()=>g});var r=t(295),n=t(297),s=t(152),c=t(73),_=t(6),i=t(20),a=t(465),l=t(839);const{neverMockProvidedFunction:p,neverMockToken:u}=r.A,d=[[e=>"boolean"==typeof e,!1],[e=>"number"==typeof e,0],[e=>"string"==typeof e,""],[e=>null===e,null]],f=(e,o,t)=>{var r;if(o===e)return t?(0,a.A)(e,(()=>{})):void 0;if(e.multi)return void(null===(r=c.A.config.get("ngMocksMulti"))||void 0===r||r.add(o));let n;return-1!==Object.keys(e).indexOf("useValue")?n=((e,o)=>(0,a.A)(o,(()=>e.useValue&&"object"==typeof e.useValue?(0,l.K)(e.useValue):(e=>{for(const[o,t]of d)if(o(e))return t})(e.useValue))))(e,o):-1!==Object.keys(e).indexOf("useExisting")?n=e:-1!==Object.keys(e).indexOf("useClass")?n=((e,o)=>c.A.builtProviders.has(e.useClass)&&c.A.builtProviders.get(e.useClass)===e.useClass?e:(0,a.A)(o,(()=>(0,l.K)(e.useClass))))(e,o):-1!==Object.keys(e).indexOf("useFactory")&&(n=(0,a.A)(o,(()=>({})))),n},g=(e,o=!1)=>{const t=(0,n.A)(e);if("mock"===c.A.getResolution(t));else{if((e=>"function"==typeof e&&-1!==p.indexOf(e.name))(t))return e;if((e=>(0,s.S)(e)&&-1!==u.indexOf(e.toString()))(t))return}const r=c.A.flags.has("cacheProvider")?c.A.cacheProviders:void 0;return t===e&&r&&r.has(t)?r.get(t):((e,o,t)=>{let r;return"function"==typeof o&&(r=((e,o)=>(0,a.A)(o,(()=>{const t=(0,l.K)(o);return o!==e&&-1!==Object.keys(e).indexOf("useClass")&&((e,o)=>{const t=Object.getOwnPropertyNames(e),r=(0,l.K)(o);for(const o of Object.getOwnPropertyNames(r)){if(-1!==t.indexOf(o))continue;const n=(0,i.A)(r,o);(0,_.A)(e,o,n)}})(t,e.useClass),t})))(e,o)),o===e&&r&&t&&t.set(o,r),r})(e,t,r)||f(e,t,o)}},839:(e,o,t)=>{t.d(o,{K:()=>a});var r=t(970),n=t(195);const s=e=>{if("function"!=typeof e)return!1;if(!e.prototype)return!0;if((e=>!!(e.ɵprov||e.__annotations__||e.__parameters__||e.parameters))(e))return!1;const o=e.toString();if(null!==o.match(/^class\b/))return!1;const t=o.match(/^function\s+([^\s(]+)\(/);return null===t||!((e,o,t)=>{if(null!==e.match(/^class/))return!0;if(Object.keys(t.prototype).length>0)return!0;const r=e.codePointAt(0);if(r&&r>=65&&r<=90&&null!==o.match(/\bthis\./gm))return!0;const n=new RegExp(`\\(this,\\s*${e}\\)`,"mg");return null!==o.match(n)})(t[1],o,e)};var c=t(932);const _=[[e=>"function"==typeof e&&!s(e),(e,o)=>{const t=c.A.createMockFromPrototype(o.prototype);return e.set(o,t),t}],[s,(e,o,t)=>{const n=c.A.mockFunction(`func:${t||(0,r.A)(o)}`);return e.set(o,n()),n}],[e=>Array.isArray(e),()=>[]],[e=>null!==e&&"object"==typeof e&&"InjectionToken"!==e.ngMetadataName&&"object"==typeof Object.getPrototypeOf(e),(e,o,t,r)=>{const n=c.A.createMockFromPrototype(o.constructor.prototype);e.set(o,n);for(const s of Object.keys(o)){const c=r(e,o[s],`${t||"instance"}.${s}`);void 0!==c&&(n[s]=c)}return Object.setPrototypeOf(n,Object.getPrototypeOf(o)),n}]],i=(e,o,t="",r)=>{const s=((e,o,t,r)=>{var n;for(const[s,c]of _)if(s(o))return null!==(n=e.get(o))&&void 0!==n?n:c(e,o,t,r)})(e,o,t,i);return r&&(0,n.A)(s,r),s};function a(e,...o){const t=o.length>0&&"string"==typeof o[0]?o[0]:o[1],r=o.length>0&&o[0]&&"object"==typeof o[0]?o[0]:void 0,n=new Map,s=i(n,e,t,r);return n.clear(),s}},673:(e,o,t)=>{t.d(o,{A:()=>x});var r=t(614),n=t(174),s=t(439),c=t(184);const _=(e,o)=>{const t=e.indexOf(o);-1!==t&&e.splice(t,1),"Injectable"!==o&&"Pipe"!==o&&"Directive"!==o&&"Component"!==o&&"NgModule"!==o||e.push(o)},i=e=>{const o=[];for(const t of Object.keys(e))o.push(t);return o},a=e=>(o,t,r,n)=>{var _;const{alias:i,required:a}=(0,c.A)({name:t,alias:null!==(_=r.alias)&&void 0!==_?_:r.bindingPropertyName,required:r.required}),l=(0,s.A)({name:t,alias:i,required:a});let p=!0;for(const o of n[e]){if(o===l){p=!1;break}const{name:e,alias:r,required:n}=(0,c.A)(o);if(e===t&&r===i&&n===a){p=!1;break}}p&&n[e].unshift(l)},l=a("inputs"),p=a("outputs"),u=e=>(o,t,r,n)=>{n.queries[t]||(n.queries[t]=Object.assign(Object.assign({isViewQuery:e,ngMetadataName:o,selector:r.selector},void 0===r.read?{}:{read:r.read}),void 0===r.static?{}:{static:r.static}))},d=u(!1),f=u(!0),g=e=>(o,t,r,n)=>{n.queries[t]||(n.queries[t]=Object.assign(Object.assign(Object.assign({isViewQuery:e,ngMetadataName:o,selector:r.selector},void 0===r.descendants?{}:{descendants:r.descendants}),void 0===r.emitDistinctChangesOnly?{}:{emitDistinctChangesOnly:r.emitDistinctChangesOnly}),void 0===r.read?{}:{read:r.read}))},k={ContentChild:d,ContentChildren:g(!1),HostBinding:(e,o,t,r)=>{const n=`[${t.hostPropertyName||o}]`;r.host[n]||(r.host[n]=o),r.hostBindings.push([o,t.hostPropertyName||o,...t.args?[t.args]:[]])},HostListener:(e,o,t,r)=>{const n=`(${t.eventName||o})`;r.host[n]||(r.host[n]=`${o}($event)`),r.hostListeners.push([o,t.eventName||o,...t.args?[t.args]:[]])},Input:l,Output:p,ViewChild:f,ViewChildren:g(!0)},m=e=>{const o=a(e);return(e,t,r,n)=>{var s;const{alias:c,required:_}=void 0===(null===(s=r.args)||void 0===s?void 0:s[0])?{}:"string"==typeof r.args[0]?{alias:r.args[0]}:r.args[0];o(e,t,{alias:c,required:_,bindingPropertyName:c},n)}},h=m("inputs"),v=m("outputs"),b=e=>(o,t,r,n)=>{n.queries[t]||(n.queries[t]=Object.assign({isViewQuery:e,ngMetadataName:o,selector:r.args[0]},r.args[1]))},A=b(!1),M=b(!0),y={ContentChild:A,ContentChildren:A,HostBinding:(e,o,t,r)=>{var n;const s=`[${(null===(n=t.args)||void 0===n?void 0:n[0])||o}]`;r.host[s]||(r.host[s]=o),r.hostBindings.push([o,...t.args||[]])},HostListener:(e,o,t,r)=>{var n;const s=`(${(null===(n=t.args)||void 0===n?void 0:n[0])||o})`;r.host[s]||(r.host[s]=`${o}($event)`),r.hostListeners.push([o,...t.args||[]])},Input:h,Output:v,ViewChild:M,ViewChildren:M},w=(e,o)=>{if(e){e.inputs=e.inputs||[];for(const t of o.inputs)-1===e.inputs.indexOf(t)&&e.inputs.push(t);e.outputs=e.outputs||[];for(const t of o.outputs)-1===e.outputs.indexOf(t)&&e.outputs.push(t);e.queries=Object.assign(Object.assign({},e.queries||[]),o.queries),e.hostBindings=o.hostBindings,e.hostListeners=o.hostListeners}},O=new r["ɵReflectionCapabilities"],C=e=>{if("function"!=typeof e&&"object"!=typeof e)return{};if(Object.prototype.hasOwnProperty.call(e,"__ngMocksParsed"))return e.__ngMocksDeclarations;const o=Object.getPrototypeOf(e),t=o?C(o):{},r=(e=>({host:e.host?Object.assign({},e.host):{},hostBindings:e.hostBindings?[...e.hostBindings]:[],hostListeners:e.hostListeners?[...e.hostListeners]:[],attributes:e.attributes?[...e.attributes]:[],inputs:e.inputs?[...e.inputs]:[],outputs:e.outputs?[...e.outputs]:[],propDecorators:e.propDecorators?Object.assign({},e.propDecorators):{},queries:e.queries?Object.assign({},e.queries):{},decorators:e.decorators?[...e.decorators]:[]}))(t);return(0,n.A)(e,"__ngMocksParsed",!0),((e,o)=>{if(Object.prototype.hasOwnProperty.call(e,"__parameters__")&&e.__parameters__)for(const t of e.__parameters__)for(const e of t||[])"Attribute"===e.ngMetadataName&&-1===o.attributes.indexOf(e.attributeName)&&o.attributes.push(e.attributeName)})(e,r),((e,o)=>{if(Object.prototype.hasOwnProperty.call(e,"__annotations__")&&e.__annotations__)for(const t of e.__annotations__){const e=null==t?void 0:t.ngMetadataName;e&&(o[e]=Object.assign(Object.assign({},t),{attributes:o.attributes}),_(o.decorators,e))}})(e,r),((e,o)=>{var t,r;if(Object.prototype.hasOwnProperty.call(e,"decorators")&&e.decorators)for(const n of e.decorators){const e=null===(r=null===(t=null==n?void 0:n.type)||void 0===t?void 0:t.prototype)||void 0===r?void 0:r.ngMetadataName;e&&(o[e]=n.args?Object.assign({},n.args[0]):{},_(o.decorators,e))}})(e,r),((e,o)=>{var t,r,n;if(Object.prototype.hasOwnProperty.call(e,"propDecorators")&&e.propDecorators)for(const s of i(e.propDecorators)){o.propDecorators[s]=[...o.propDecorators[s]||[],...e.propDecorators[s]];for(const c of e.propDecorators[s]){const e=null===(r=null===(t=null==c?void 0:c.type)||void 0===t?void 0:t.prototype)||void 0===r?void 0:r.ngMetadataName;e&&(null===(n=y[e])||void 0===n||n.call(y,e,s,c,o))}}})(e,r),((e,o)=>{var t;if(Object.prototype.hasOwnProperty.call(e,"__prop__metadata__")&&e.__prop__metadata__)for(const r of i(e.__prop__metadata__)){const n=e.__prop__metadata__[r];for(const e of n){const n=null==e?void 0:e.ngMetadataName;n&&(null===(t=k[n])||void 0===t||t.call(k,n,r,e,o))}}})(e,r),w(r.Directive,r),w(r.Component,r),(0,n.A)(e,"__ngMocksDeclarations",Object.assign(Object.assign(Object.assign({},t),r),{parameters:O.parameters(e)})),e.__ngMocksDeclarations},x=C},614:(e,o,t)=>{e.exports=(e=>{var o={};return t.d(o,e),o})({ChangeDetectorRef:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ChangeDetectorRef,Component:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Component,ComponentFactoryResolver:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ComponentFactoryResolver,ContentChild:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ContentChild,ContentChildren:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ContentChildren,DebugElement:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.DebugElement,Directive:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Directive,ElementRef:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ElementRef,EventEmitter:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.EventEmitter,InjectionToken:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.InjectionToken,Injector:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Injector,Input:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Input,NgModule:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.NgModule,Optional:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Optional,Output:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Output,Pipe:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Pipe,QueryList:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.QueryList,Self:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.Self,TemplateRef:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.TemplateRef,ViewChild:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ViewChild,ViewChildren:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ViewChildren,ViewContainerRef:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__.ViewContainerRef,ɵReflectionCapabilities:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_bcead0df__["ɵReflectionCapabilities"]})},957:(e,o,t)=>{e.exports=(e=>{var o={};return t.d(o,e),o})({TestBed:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_testing_89899de6__.TestBed,getTestBed:()=>__WEBPACK_EXTERNAL_MODULE__angular_core_testing_89899de6__.getTestBed})}},__webpack_module_cache__={};function __webpack_require__(e){var o=__webpack_module_cache__[e];if(void 0!==o)return o.exports;var t=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](t,t.exports,__webpack_require__),t.exports}__webpack_require__.d=(e,o)=>{for(var t in o)__webpack_require__.o(o,t)&&!__webpack_require__.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:o[t]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__={};__webpack_require__.d(__webpack_exports__,{rX:()=>types_namespaceObject.IMockBuilder,HA:()=>types_namespaceObject.IMockBuilderConfig,Wn:()=>types_namespaceObject.IMockBuilderConfigAll,Me:()=>types_namespaceObject.IMockBuilderConfigComponent,I7:()=>types_namespaceObject.IMockBuilderConfigDirective,tv:()=>types_namespaceObject.IMockBuilderConfigModule,OG:()=>types_namespaceObject.IMockBuilderExtended,sF:()=>types_namespaceObject.IMockBuilderProvider,me:()=>types_namespaceObject.IMockBuilderResult,bk:()=>LegacyControlValueAccessor,JT:()=>Mock,_V:()=>MockBuilder,Am:()=>MockComponent,$u:()=>MockComponents,D2:()=>mock_control_value_accessor_namespaceObject.MockControlValueAccessor,dw:()=>MockDeclaration,uV:()=>MockDeclarations,Cc:()=>MockDirective,nr:()=>MockDirectives,Wm:()=>MockInstance,BN:()=>MockModule,ZJ:()=>MockPipe,yI:()=>MockPipes,Qo:()=>MockProvider,dD:()=>MockProviders,Ty:()=>MockRender,P0:()=>MockRenderFactory,mB:()=>MockReset,KH:()=>mock_service.K,b6:()=>mock_control_value_accessor_namespaceObject.MockValidator,Je:()=>mock_component_types_namespaceObject.MockedComponent,T4:()=>mock_directive_types_namespaceObject.MockedDirective,qZ:()=>mock_module_types_namespaceObject.MockedModule,cm:()=>mock_pipe_types_namespaceObject.MockedPipe,en:()=>core_tokens.en,ZG:()=>core_tokens.ZG,rO:()=>core_tokens.rO,So:()=>core_tokens.So,C3:()=>core_tokens.C3,gG:()=>core_tokens.gG,Em:()=>core_tokens.Em,Ah:()=>core_helpers.Ah,xz:()=>getMockedNgDefOf,VK:()=>getSourceOfMock,d5:()=>core_helpers.d5,IA:()=>isMockControlValueAccessor,Bt:()=>isMockNgDef,AW:()=>isMockOf,lt:()=>isMockValidator,Fk:()=>isMockedNgDefOf,pA:()=>func_is_ng_def.p,SM:()=>func_is_ng_injection_token.S,H5:()=>ngMocks});var mock_control_value_accessor_namespaceObject={};__webpack_require__.r(mock_control_value_accessor_namespaceObject),__webpack_require__.d(mock_control_value_accessor_namespaceObject,{b:()=>LegacyControlValueAccessor});var types_namespaceObject={};__webpack_require__.r(types_namespaceObject);var mock_module_types_namespaceObject={};__webpack_require__.r(mock_module_types_namespaceObject);var mock_component_types_namespaceObject={};__webpack_require__.r(mock_component_types_namespaceObject);var mock_directive_types_namespaceObject={};__webpack_require__.r(mock_directive_types_namespaceObject);var mock_pipe_types_namespaceObject={};__webpack_require__.r(mock_pipe_types_namespaceObject);var ng_mocks_universe=__webpack_require__(73),_a,_b;const stackRoot={id:{},level:"root"},stack=ng_mocks_universe.A.global.get("reporter-stack")||[Object.assign({},stackRoot)];ng_mocks_universe.A.global.set("reporter-stack",stack);const current=()=>stack[stack.length-1],listenersPush=null!==(_a=ng_mocks_universe.A.global.get("reporter-stack-push"))&&void 0!==_a?_a:[];ng_mocks_universe.A.global.set("reporter-stack-push",listenersPush);const listenersPop=null!==(_b=ng_mocks_universe.A.global.get("reporter-stack-pop"))&&void 0!==_b?_b:[];ng_mocks_universe.A.global.set("reporter-stack-pop",listenersPop);const stackPush=()=>{const e={};ng_mocks_universe.A.global.set("reporter-stack-id",e);const o={id:e,level:"runtime"};stack.push(o);for(const e of listenersPush)e(o,stack)},stackPop=()=>{const e=stack.pop();if(0===stack.length&&stack.push("root"===(null==e?void 0:e.level)?e:Object.assign({},stackRoot)),e&&"root"!==e.level)for(const o of listenersPop)o(e,stack);ng_mocks_universe.A.global.set("reporter-stack-id",stack[stack.length-1].id)},subscribePush=e=>{listenersPush.indexOf(e)&&listenersPush.push(e),stack.length>0&&e(stack[stack.length-1],stack)},subscribePop=e=>{-1===listenersPop.indexOf(e)&&listenersPop.push(e)},unsubscribePush=e=>{const o=listenersPush.indexOf(e);-1!==o&&listenersPush.splice(o,1)},unsubscribePop=e=>{const o=listenersPop.indexOf(e);-1!==o&&listenersPop.splice(o,1)},ng_mocks_stack={current,stackPop,stackPush,subscribePop,subscribePush,unsubscribePop,unsubscribePush};var core_=__webpack_require__(614),testing_=__webpack_require__(957),core_helpers=__webpack_require__(456),core_tokens=__webpack_require__(763);const func_extract_tokens=e=>{let o,t,r;for(const n of(0,core_helpers.Bq)(e||[]))"object"==typeof n&&(n.provide===core_tokens.en&&(o=n.useValue),n.provide===core_tokens.So&&(t=n.useValue),n.provide===core_tokens.Em&&(r=n.useValue));return{mocks:o,overrides:t,touches:r}};var core_define_property=__webpack_require__(174),collect_declarations=__webpack_require__(673),func_is_ng_injection_token=__webpack_require__(152);const getNgType=e=>{if("string"==typeof e)return;if((0,func_is_ng_injection_token.S)(e))return"Injectable";const{decorators:o}=(0,collect_declarations.A)(e);for(let e=o.length-1;e>=0;e-=1)if("Injectable"!==o[e])return o[e];return o.length>0?"Injectable":void 0};function isStandalone(e){const o=getNgType(e);return"NgModule"!==o}var helper_extract_property_descriptor=__webpack_require__(20);const core_def_stack=class{constructor(){this.stack=[],this.push()}push(){this.stack.push(new Map)}pop(){var e;return null!==(e=this.stack.pop())&&void 0!==e?e:new Map}has(e){for(let o=this.stack.length-1;o>=0;o-=1)if(this.stack[o].has(e))return!0;return!1}get(e){for(let o=this.stack.length-1;o>=0;o-=1)if(this.stack[o].has(e))return this.stack[o].get(e)}set(e,o){for(let t=this.stack.length-1;t>=0;t-=1)this.stack[t].set(e,o);return this}merge(e){for(const[o,t]of(0,core_helpers.Nn)(e))this.set(o,t);return this}};var func_get_name=__webpack_require__(970),func_is_ng_def=__webpack_require__(218),func_is_ng_module_def_with_providers=__webpack_require__(659),core_config=__webpack_require__(295);class MockBuilderStash{constructor(){this.data={}}backup(){this.data={builtDeclarations:ng_mocks_universe.A.builtDeclarations,builtProviders:ng_mocks_universe.A.builtProviders,cacheDeclarations:ng_mocks_universe.A.cacheDeclarations,cacheProviders:ng_mocks_universe.A.cacheProviders,config:ng_mocks_universe.A.config,configInstance:ng_mocks_universe.A.configInstance,flags:ng_mocks_universe.A.flags,touches:ng_mocks_universe.A.touches},ng_mocks_universe.A.builtDeclarations=new Map,ng_mocks_universe.A.builtProviders=new Map,ng_mocks_universe.A.cacheDeclarations=new Map,ng_mocks_universe.A.cacheProviders=new Map,ng_mocks_universe.A.config=new Map,ng_mocks_universe.A.configInstance=new Map,ng_mocks_universe.A.flags=new Set(core_config.A.flags),ng_mocks_universe.A.touches=new Set}restore(){for(const e of Object.keys(this.data))ng_mocks_universe.A[e]=this.data[e]}}const core_reflect_provided_in=e=>{var o,t,r;if(e&&("object"==typeof e||"function"==typeof e))return null!==(t=null===(o=e.ɵprov)||void 0===o?void 0:o.providedIn)&&void 0!==t?t:null===(r=e.ngInjectableDef)||void 0===r?void 0:r.providedIn};var func_get_type=__webpack_require__(297),helper_resolve_provider=__webpack_require__(663);const add_requested_providers=(e,{providerDef:o,mockDef:t},r)=>{for(const t of(0,core_helpers.LG)(o))e.providers.push(t);for(const o of(0,core_helpers.Bq)(e.providers)){const e=(0,func_get_type.A)(o);ng_mocks_universe.A.touches.add(e),e!==o&&o.deps&&(0,core_helpers.by)(o.deps,ng_mocks_universe.A.config.get("ngMocksDeps"))}for(const o of(0,core_helpers.LG)(t))ng_mocks_universe.A.touches.has(o)||"root"!==core_reflect_provided_in(o)||(e.providers.push((0,helper_resolve_provider.A)(o,r)),ng_mocks_universe.A.touches.add(o))},apply_platform_modules=()=>{const e=(0,testing_.getTestBed)();if(e.ngModule)for(const o of(0,core_helpers.Bq)(e.ngModule))ng_mocks_universe.A.touches.add((0,func_get_type.A)(o))},error_empty_def=e=>{if(!e)throw new Error(["undefined / null has been passed into ng-mocks as a declaration / provider.","Please ensure that the current test file has correct imports:","imported files exist and imported declarations have been exported in the file."].join(" "))},func_is_jest_mock=e=>!(!e||"function"!=typeof e&&"object"!=typeof e||!(e._isMockFunction&&e.mockName&&e.__annotations__)),error_jest_mock=e=>{if(func_is_jest_mock(e))throw new Error([`ng-mocks got ${(0,func_get_name.A)(e)} which has been already mocked by jest.mock().`,"It is not possible to produce correct mocks for it, because jest.mock() removes Angular decorators.",`To fix this, please avoid jest.mock() on the file which exports ${(0,func_get_name.A)(e)} or add jest.dontMock() on it.`,"The same should be done for all related dependencies."].join(" "))},error_missing_decorators=e=>{throw new Error([`${(0,func_get_name.A)(e)} declaration has been passed into ng-mocks without Angular decorators.`,"Therefore, it cannot be properly handled.","Highly likely,","undefined"==typeof jest?"":"jest.mock() has been used on its file, or","ng-mocks is imported in production code, or got a class without Angular decoration.","Otherwise, please create an issue on github: https://github.com/help-me-mom/ng-mocks/issues/new?title=False%20positive%20ng-mocks%20not%20in%20JIT.","Thank you in advance for support."].join(" "))},core_reflect_body_catch=e=>o=>{error_empty_def(o);try{return e(o)}catch(e){error_jest_mock(o),error_missing_decorators(o)}},core_reflect_directive_resolve=e=>core_reflect_body_catch((e=>{const o=(0,collect_declarations.A)(e);if(o.Component)return o.Component;if(o.Directive)return o.Directive;throw new Error("Cannot resolve declarations")}))(e),core_reflect_module_resolve=e=>core_reflect_body_catch((e=>{const o=(0,collect_declarations.A)(e);if(o.NgModule)return o.NgModule;throw new Error("Cannot resolve declarations")}))(e),core_reflect_meta=e=>(0,func_is_ng_def.p)(e,"c")||(0,func_is_ng_def.p)(e,"d")?core_reflect_directive_resolve(e):(0,func_is_ng_def.p)(e,"m")?core_reflect_module_resolve(e):void 0;function getSourceOfMock(e){return"function"==typeof e&&e.mockOf?e.mockOf:e}const mark_exported=(e,o)=>{var t;const r=getSourceOfMock(e),n=null!==(t=ng_mocks_universe.A.configInstance.get(r))&&void 0!==t?t:{__set:!0};n.exported||(n.exported=new Set),o&&n.exported.add(getSourceOfMock(o)),n.__set&&(n.__set=void 0,ng_mocks_universe.A.configInstance.set(r,n))};var x=e=>{var o={};return __webpack_require__.d(o,e),o},y=e=>()=>e;const forms_namespaceObject=x({AbstractControl:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.AbstractControl,DefaultValueAccessor:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.DefaultValueAccessor,FormControl:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.FormControl,FormControlDirective:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.FormControlDirective,NG_ASYNC_VALIDATORS:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.NG_ASYNC_VALIDATORS,NG_VALIDATORS:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.NG_VALIDATORS,NG_VALUE_ACCESSOR:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.NG_VALUE_ACCESSOR,NgControl:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.NgControl,NgModel:()=>__WEBPACK_EXTERNAL_MODULE__angular_forms_df10eade__.NgModel}),AbstractControl=forms_namespaceObject.AbstractControl,DefaultValueAccessor=forms_namespaceObject.DefaultValueAccessor,FormControl=forms_namespaceObject.FormControl,FormControlDirective=forms_namespaceObject.FormControlDirective,NG_ASYNC_VALIDATORS=forms_namespaceObject.NG_ASYNC_VALIDATORS,NG_VALIDATORS=forms_namespaceObject.NG_VALIDATORS,NG_VALUE_ACCESSOR=forms_namespaceObject.NG_VALUE_ACCESSOR,NgControl=forms_namespaceObject.NgControl,NgModel=forms_namespaceObject.NgModel,core_form={AbstractControl,DefaultValueAccessor,FormControl,FormControlDirective,NG_ASYNC_VALIDATORS,NG_VALIDATORS,NG_VALUE_ACCESSOR,NgControl,NgModel},func_is_mock=e=>e&&"object"==typeof e&&!!e.__ngMocks;var mock_helper_stub=__webpack_require__(195),mock_instance_apply=__webpack_require__(760),helper_mock_service=__webpack_require__(932),func_directive_io_parse=__webpack_require__(184);const applyProxy=(e,o,t,r)=>{if(e.instance&&r&&(e.instance[r]=t),e.instance&&e.instance[o])return e.instance[o](t)};class MockControlValueAccessorProxy{constructor(e){this.target=e}registerOnChange(e){applyProxy(this,"registerOnChange",e,"__simulateChange")}registerOnTouched(e){applyProxy(this,"registerOnTouched",e,"__simulateTouch")}setDisabledState(e){applyProxy(this,"setDisabledState",e)}writeValue(e){applyProxy(this,"writeValue",e)}}class MockValidatorProxy{constructor(e){this.target=e}registerOnValidatorChange(e){applyProxy(this,"registerOnValidatorChange",e,"__simulateValidatorChange")}validate(e){return this.instance&&this.instance.validate?this.instance.validate(e):null}}class MockAsyncValidatorProxy{constructor(e){this.target=e}registerOnValidatorChange(e){applyProxy(this,"registerOnValidatorChange",e,"__simulateValidatorChange")}validate(e){if(this.instance&&this.instance.validate){const o=this.instance.validate(e);return void 0===o?Promise.resolve(null):o}return Promise.resolve(null)}}const setValueAccessor=(e,o)=>{if(o&&!o.valueAccessor&&e.__ngMocksConfig.setControlValueAccessor)try{o.valueAccessor=new MockControlValueAccessorProxy(e.__ngMocksCtor)}catch(e){}},installValueAccessor=(e,o)=>{e.valueAccessor.instance||e.valueAccessor.target!==o.__ngMocksCtor||(e.valueAccessor.instance=o,helper_mock_service.A.mock(o,"registerOnChange"),helper_mock_service.A.mock(o,"registerOnTouched"),helper_mock_service.A.mock(o,"setDisabledState"),helper_mock_service.A.mock(o,"writeValue"),o.__ngMocksConfig.isControlValueAccessor=!0)},installValidator=(e,o)=>{for(const t of e)t.instance||t.target!==o.__ngMocksCtor||(t.instance=o,helper_mock_service.A.mock(o,"registerOnValidatorChange"),helper_mock_service.A.mock(o,"validate"),o.__ngMocksConfig.isValidator=!0)},applyNgValueAccessor=(e,o)=>{setValueAccessor(e,o);try{o&&(installValueAccessor(o,e),installValidator(o._rawValidators,e),installValidator(o._rawAsyncValidators,e))}catch(e){}},applyOutputs=e=>{const o=[];for(const t of e.__ngMocksConfig.outputs||[])o.push((0,func_directive_io_parse.A)(t).name);for(const t of o)e[t]||Object.getOwnPropertyDescriptor(e,t)||(e[t]=new core_.EventEmitter)},applyPrototype=(e,o)=>{for(const t of[...helper_mock_service.A.extractMethodsFromPrototype(o),...helper_mock_service.A.extractPropertiesFromPrototype(o)]){const r=helper_mock_service.A.extractPropertyDescriptor(o,t);helper_mock_service.A.definePropertyDescriptor(e,t,r)}},applyMethods=(e,o)=>{for(const t of helper_mock_service.A.extractMethodsFromPrototype(o))e[t]||Object.getOwnPropertyDescriptor(e,t)||helper_mock_service.A.mock(e,t)},applyProps=(e,o)=>{for(const t of helper_mock_service.A.extractPropertiesFromPrototype(o))e[t]||Object.getOwnPropertyDescriptor(e,t)||(helper_mock_service.A.mock(e,t,"get"),helper_mock_service.A.mock(e,t,"set"))},applyOverrides=(e,o,t)=>{const r=ng_mocks_universe.A.getOverrides().get(o),n=r?(0,core_helpers.LG)(r):[];e.__ngMocksConfig.init&&n.push(e.__ngMocksConfig.init),n.push(...(0,mock_instance_apply.A)(o));for(const o of n){const r=o(e,t);r&&(0,mock_helper_stub.A)(e,r)}};class Mock{constructor(e=null,o=null){const t=this.constructor.mockOf;(0,core_define_property.A)(this,"__ngMocks",!0),(0,core_define_property.A)(this,"__ngMocksInjector",e),(0,core_define_property.A)(this,"__ngMocksCtor",this.constructor);for(const e of this.__ngMocksConfig.queryScanKeys||[])(0,core_define_property.A)(this,`__ngMocksVcr_${e}`,void 0);for(const e of this.__ngMocksConfig.hostBindings||[])helper_mock_service.A.mock(this,e,"get"),helper_mock_service.A.mock(this,e,"set");for(const e of this.__ngMocksConfig.hostListeners||[])helper_mock_service.A.mock(this,e);func_is_mock(this)&&(applyNgValueAccessor(this,o),applyOutputs(this),applyPrototype(this,Object.getPrototypeOf(this)),applyMethods(this,t.prototype),applyProps(this,t.prototype)),Object.setPrototypeOf(this,t.prototype),applyOverrides(this,t,null!=e?e:void 0)}}(0,core_define_property.A)(Mock,"parameters",[[core_.Injector,new core_.Optional],[core_form.NgControl||(()=>{}),new core_.Optional,new core_.Self]]);class LegacyControlValueAccessor extends Mock{__simulateChange(){}__simulateTouch(){}__simulateValidatorChange(){}}var func_directive_io_build=__webpack_require__(439);const decorate_inputs=(e,o,t)=>{if(o)for(const r of o){const{name:o,alias:n,required:s}=(0,func_directive_io_parse.A)(r);t&&-1!==t.indexOf(o)||(0,core_.Input)((0,func_directive_io_build.A)({name:o,alias:n,required:s},!0))(e.prototype,o)}},decorate_mock=(e,o,t={})=>{(0,core_define_property.A)(e,"mockOf",o),(0,core_define_property.A)(e,"nameConstructor",(0,func_get_name.A)(e)),(0,core_define_property.A)(e,"name",`MockOf${(0,func_get_name.A)(o)}`,!0);const r=ng_mocks_universe.A.getConfigMock().has(o)?Object.assign(Object.assign({},t),{config:Object.assign(Object.assign({},ng_mocks_universe.A.getConfigMock().get(o)),t.config)}):t;(0,core_define_property.A)(e.prototype,"__ngMocksConfig",r)},decorate_outputs=(e,o)=>{if(o)for(const t of o){const{name:o,alias:r,required:n}=(0,func_directive_io_parse.A)(t);(0,core_.Output)((0,func_directive_io_build.A)({name:o,alias:r,required:n},!0))(e.prototype,o)}},map={ContentChild:core_.ContentChild,ContentChildren:core_.ContentChildren,ViewChild:core_.ViewChild,ViewChildren:core_.ViewChildren},isInternalKey=e=>0===e.indexOf("__mock"),cloneVcrQuery=e=>Object.assign(Object.assign({},e),{ngMetadataName:e.ngMetadataName,read:core_.ViewContainerRef}),generateFinalQueries=e=>{const o=[],t=[];for(const r of Object.keys(e)){const n=e[r];o.push([r,n]),n.isViewQuery||isInternalKey(r)||(t.push(r),o.push([`__ngMocksVcr_${r}`,cloneVcrQuery(n)]))}return[o,t]},decorate_queries=(e,o)=>{if(!o)return[];const[t,r]=generateFinalQueries(o);for(const[o,r]of t)r.ngMetadataName&&(0,map[r.ngMetadataName])(r.selector,r)(e.prototype,o);return r};var func_extract_forward_ref=__webpack_require__(285);const to_existing_provider=(e,o)=>({provide:e,useExisting:o}),to_factory_provider=(e,o)=>({multi:!0,provide:e,useFactory:o}),processTokens=(e,o)=>{const t=(0,func_get_type.A)(o);return core_form.NG_VALIDATORS&&t===core_form.NG_VALIDATORS?to_factory_provider(t,(()=>new MockValidatorProxy(e))):core_form.NG_ASYNC_VALIDATORS&&t===core_form.NG_ASYNC_VALIDATORS?to_factory_provider(t,(()=>new MockAsyncValidatorProxy(e))):core_form.NG_VALUE_ACCESSOR&&t===core_form.NG_VALUE_ACCESSOR?to_factory_provider(t,(()=>new MockControlValueAccessorProxy(e))):void 0},processOwnUseExisting=(e,o,t)=>{const r=(0,func_get_type.A)(t);if(r!==core_form.NgControl&&r!==core_form.FormControlDirective)return t!==r&&(0,func_extract_forward_ref.A)(t.useExisting)===e?to_existing_provider(r,o):void 0},processProvider=(e,o,t,r)=>{const n=processTokens(o,t);if(n)return n;return processOwnUseExisting(e,o,t)||helper_mock_service.A.resolveProvider(t,r)},clone_providers=(e,o,t,r)=>{const n=[];let s;for(const c of(0,core_helpers.Bq)(t||[])){(0,func_get_type.A)(c)===core_form.NG_VALUE_ACCESSOR&&(s=!1);const t=processProvider(e,o,c,r);t&&n.push(t)}return{providers:n,setControlValueAccessor:s}},buildConfig=(e,o,t)=>({config:ng_mocks_universe.A.config.get(e),outputs:o.outputs,queryScanKeys:[],setControlValueAccessor:t}),decorate_declaration=(e,o,t,r)=>{const n=ng_mocks_universe.A.config.has("mockNgDefResolver");n||ng_mocks_universe.A.config.set("mockNgDefResolver",new core_def_stack);const s=Object.assign({},r);if(void 0!==t.exportAs&&(s.exportAs=t.exportAs),void 0!==t.selector&&(s.selector=t.selector),void 0!==t.standalone&&(s.standalone=t.standalone),t.standalone&&t.imports){const[,{imports:e}]=mock_ng_def({imports:t.imports,skipExports:!0});(null==e?void 0:e.length)&&(s.imports=e)}if(t.hostDirectives){const[,{hostDirectives:e}]=mock_ng_def({hostDirectives:t.hostDirectives,skipExports:!0});(null==e?void 0:e.length)&&(s.hostDirectives=e)}const{setControlValueAccessor:c,providers:_}=clone_providers(e,o,t.providers||[],ng_mocks_universe.A.config.get("mockNgDefResolver"));_.push(to_existing_provider(e,o)),s.providers=_;const{providers:i}=clone_providers(e,o,t.viewProviders||[],ng_mocks_universe.A.config.get("mockNgDefResolver"));i.length>0&&(s.viewProviders=i);const a=buildConfig(e,t,null!=c?c:-1!==helper_mock_service.A.extractMethodsFromPrototype(e.prototype).indexOf("writeValue"));decorate_mock(o,e,a),t.queries&&decorate_inputs(o,t.inputs,Object.keys(t.queries)),decorate_outputs(o,t.outputs),a.queryScanKeys=decorate_queries(o,t.queries),a.hostBindings=[];for(const[e]of t.hostBindings||[])-1===a.hostBindings.indexOf(e)&&a.hostBindings.push(e);a.hostListeners=[];for(const[e]of t.hostListeners||[])-1===a.hostListeners.indexOf(e)&&a.hostListeners.push(e);return n||ng_mocks_universe.A.config.delete("mockNgDefResolver"),s},getType=e=>(0,func_is_ng_def.p)(e,"p")?"pipe":(0,func_is_ng_def.p)(e,"d")?"directive":(0,func_is_ng_def.p)(e,"c")?"component":(0,func_is_ng_def.p)(e,"m")?"module":(0,func_is_ng_def.p)(e,"i")?"service":(0,func_is_ng_def.p)(e,"t")?"token":"",func_import_exists=(e,o)=>{if(null==e)throw new Error(`null / undefined has been passed into ${o}. Please check that its import is correct.`);if("MockPipe"===o&&(0,func_is_ng_def.p)(e,"p"))return;if("MockDirective"===o&&(0,func_is_ng_def.p)(e,"d"))return;if("MockComponent"===o&&(0,func_is_ng_def.p)(e,"c"))return;if("MockModule"===o&&(0,func_is_ng_def.p)(e,"m"))return;const t=getType(e);if(t&&"MockPipe"===o)throw new Error(`${o} accepts pipes, whereas ${(0,func_get_name.A)(e)} is a ${t}.`);if(t&&"MockDirective"===o)throw new Error(`${o} accepts directives, whereas ${(0,func_get_name.A)(e)} is a ${t}.`);if(t&&"MockComponent"===o)throw new Error(`${o} accepts components, whereas ${(0,func_get_name.A)(e)} is a ${t}.`);if(t&&"MockModule"===o)throw new Error(`${o} accepts modules, whereas ${(0,func_get_name.A)(e)} is a ${t}.`)};function isMockNgDef(e,o){return!!e.mockOf&&(!o||(0,func_is_ng_def.p)(e.mockOf,o))}const func_get_last_fixture=()=>{const e=(0,testing_.getTestBed)()._activeFixtures;return e[e.length-1]},return_cached_mock=e=>{let o;try{o=func_get_last_fixture().debugElement.injector.get(core_tokens.en).get(e)}catch(e){}return o||(o=ng_mocks_universe.A.cacheDeclarations.get(e)),e.__ngMocksResolutions&&ng_mocks_universe.A.config.has("mockNgDefResolver")&&ng_mocks_universe.A.config.get("mockNgDefResolver").merge(e.__ngMocksResolutions),o},get_mock=(e,o,t,r,n,s)=>{if(func_import_exists(e,t),isMockNgDef(e,o))return e;if(ng_mocks_universe.A.flags.has(r)&&ng_mocks_universe.A.cacheDeclarations.has(e))return return_cached_mock(e);const c=ng_mocks_universe.A.config.has("ngMocksDepsResolution");c||ng_mocks_universe.A.config.set("ngMocksDepsResolution",new Map);const _=(0,core_helpers.He)(n);return s(e,_),ng_mocks_universe.A.flags.has(r)&&ng_mocks_universe.A.cacheDeclarations.set(e,_),c||ng_mocks_universe.A.config.delete("ngMocksDepsResolution"),_},vcrArgs={read:core_.ViewContainerRef,static:!1},trArgs={read:core_.TemplateRef,static:!1},viewChildTemplate=(e,o)=>`
`,isTemplateRefQuery=e=>!(e.isViewQuery||e.read&&e.read!==core_.TemplateRef||"string"!=typeof e.selector&&!e.read),generate_template=e=>{const o=[""];if(!e)return o.join("");for(const t of Object.keys(e)){const r=e[t];if(0!==t.indexOf("__mock")&&isTemplateRefQuery(r)){if("string"==typeof r.selector){const t=r.selector.replace(new RegExp("\\W","mg"),"_");e[`__vcrIf_key_${t}`]=new core_.ViewChild(`ngIf_key_${t}`,vcrArgs),e[`__trIf_key_${t}`]=new core_.ViewChild(`ngIf_key_${t}`,trArgs),e[`__mockView_key_${t}`]=new core_.ViewChild(`key_${t}`,vcrArgs),e[`__mockTpl_key_${t}`]=r,o.push(viewChildTemplate(t,"key"))}e[`__vcrIf_prop_${t}`]=new core_.ViewChild(`ngIf_prop_${t}`,vcrArgs),e[`__trIf_prop_${t}`]=new core_.ViewChild(`ngIf_prop_${t}`,trArgs),e[`__mockView_prop_${t}`]=new core_.ViewChild(`prop_${t}`,vcrArgs),o.push(viewChildTemplate(t,"prop"))}}return o.join("")},get_key=e=>{if("string"==typeof e)return["key",`__mockTpl_key_${e}`,e,void 0];const[o,...t]=e;return["prop",o,o,t.length>0?t:void 0]},mixRenderPrepareVcr=(e,o,t,r)=>{const n=e[`__vcrIf_${o}_${t}`],s=e[`__trIf_${o}_${t}`];return n&&s&&!e[`ngMocksRender_${o}_${t}`]&&(e[`ngMocksRender_${o}_${t}`]=n.createEmbeddedView(s,{}),r.detectChanges()),e[`__mockView_${o}_${t}`]},mixRenderReorderViews=(e,o,t)=>{for(const e of o.splice(t+1))e.destroy();let r=0;for(const t of o)t&&(e.move(t,r),r+=1)},mixRenderApplyContext=(e,o)=>{for(const o of Object.keys(e.context))e.context[o]=void 0;for(const t of Object.keys(o))e.context[t]=o[t];e.markForCheck()},mixRenderHandleViews=(e,o,t,r,n,s)=>{let c=-1;for(const o of t)if(c+=1,r[c]=r[c]||void 0,(!n||-1!==n.indexOf(c))&&o){if(!(o instanceof core_.TemplateRef))throw new Error("Cannot find TemplateRef");r[c]||(r[c]=e.createEmbeddedView(o,{})),mixRenderApplyContext(r[c],s)}return o.detectChanges(),c},mixRender=(e,o)=>{(0,core_define_property.A)(e,"__render",((t,r,n)=>{const[s,c,_,i]=get_key(t),a=mixRenderPrepareVcr(e,s,_,o);if(!a)return;const l=e[c],p=l instanceof core_.QueryList?l.toArray():[l],u=e[`ngMocksRender_${s}_${_}_views`]||[],d=mixRenderHandleViews(a,o,p,u,i,Object.assign(Object.assign({},n),{$implicit:r}));mixRenderReorderViews(a,u,d),e[`ngMocksRender_${s}_${_}_views`]=u,o.detectChanges()}))},mixHideHandler=(e,o,t,r)=>{const n=e[`ngMocksRender_${o}_${t}_views`];let s=-1;for(const e of n)s+=1,r&&-1===r.indexOf(s)||!e||(e.destroy(),n[s]=void 0)},mixHide=(e,o)=>{(0,core_define_property.A)(e,"__hide",(t=>{const[r,,n,s]=get_key(t);e[`ngMocksRender_${r}_${n}`]&&(mixHideHandler(e,r,n,s),s||(e[`ngMocksRender_${r}_${n}`].destroy(),e[`ngMocksRender_${r}_${n}`]=void 0),o.detectChanges())}))};class ComponentMockBase extends LegacyControlValueAccessor{constructor(e,o,t){super(e,o),func_is_mock(this)&&(mixRender(this,t),mixHide(this,t))}ngAfterViewInit(){const e=this.__ngMocksConfig.config;if(!this.__rendered&&e&&e.render){for(const o of Object.keys(e.render)){const{$implicit:t,variables:r}=!0===e.render[o]?{$implicit:void 0,variables:{}}:e.render[o];this.__render(o,t,r)}this.__rendered=!0}}}(0,core_define_property.A)(ComponentMockBase,"parameters",[[core_.Injector],[core_form.NgControl||(()=>{}),new core_.Optional,new core_.Self],[core_.ChangeDetectorRef]]);const decorateClass=(e,o)=>{const t=core_reflect_directive_resolve(e);(0,core_.Component)(decorate_declaration(e,o,t,{template:generate_template(t.queries)}))(o)};function MockComponents(...e){return e.map(MockComponent)}function MockComponent(e){return get_mock(e,"c","MockComponent","cacheComponent",ComponentMockBase,decorateClass)}class DirectiveMockBase extends LegacyControlValueAccessor{constructor(e,o,t,r,n=null,s=null){super(e,o),this.__ngMocksInstall(r,t,n,s)}ngOnInit(){const e=this.__ngMocksConfig.config;if(null==e?void 0:e.render){const{$implicit:o,variables:t}=!0===e.render?{$implicit:void 0,variables:{}}:e.render;this.__render(o,t)}}__ngMocksInstall(e,o,t,r){(0,core_define_property.A)(this,"__element",t),(0,core_define_property.A)(this,"__template",r),(0,core_define_property.A)(this,"__viewContainer",e),(0,core_define_property.A)(this,"__vcr",e),(0,core_define_property.A)(this,"__cdr",o),(0,core_define_property.A)(this,"__isStructural",r&&e),(0,core_define_property.A)(this,"__render",((t,n)=>{e&&r&&(e.clear(),e.createEmbeddedView(r,Object.assign(Object.assign({},n),{$implicit:t})),o.detectChanges())}))}}(0,core_define_property.A)(DirectiveMockBase,"parameters",[[core_.Injector],[core_form.NgControl||(()=>{}),new core_.Optional,new core_.Self],[core_.ChangeDetectorRef],[core_.ViewContainerRef],[core_.ElementRef,new core_.Optional,new core_.Self],[core_.TemplateRef,new core_.Optional,new core_.Self]]);const mock_directive_decorateClass=(e,o)=>{const t=core_reflect_directive_resolve(e),r=decorate_declaration(e,o,t,{});(0,core_.Directive)(r)(o)};function MockDirectives(...e){return e.map(MockDirective)}function MockDirective(e){return get_mock(e,"d","MockDirective","cacheDirective",DirectiveMockBase,mock_directive_decorateClass)}const core_reflect_pipe_resolve=e=>core_reflect_body_catch((e=>{const o=(0,collect_declarations.A)(e);if(o.Pipe)return o.Pipe;throw new Error("Cannot resolve declarations")}))(e);function MockPipes(...e){return e.map((e=>MockPipe(e,void 0)))}const getMockClass=(e,o)=>{var t;const r=ng_mocks_universe.A.config.get(e),n=null!=o?o:null===(t=null==r?void 0:r.defValue)||void 0===t?void 0:t.transform,s=(0,core_helpers.He)(Mock);return(0,core_.Pipe)(core_reflect_pipe_resolve(e))(s),decorate_mock(s,e,{init:e=>{n&&(e.transform=n),e.transform||helper_mock_service.A.mock(e,"transform",`${(0,func_get_name.A)(e)}.transform`)},transform:n}),s};function MockPipe(e,o){if(func_import_exists(e,"MockPipe"),isMockNgDef(e,"p"))return e;if(ng_mocks_universe.A.flags.has("cachePipe")&&ng_mocks_universe.A.cacheDeclarations.has(e))return return_cached_mock(e);const t=getMockClass(e,o);return ng_mocks_universe.A.flags.has("cachePipe")&&ng_mocks_universe.A.cacheDeclarations.set(e,t),t}const flagMock=e=>"mock"===e&&ng_mocks_universe.A.flags.has("skipMock"),flagKeep=e=>"keep"===e&&!ng_mocks_universe.A.flags.has("skipMock"),flagReplace=e=>"replace"===e&&!ng_mocks_universe.A.flags.has("skipMock"),flagNever=e=>-1!==core_config.A.neverMockModule.indexOf((0,func_get_name.A)(e))&&!ng_mocks_universe.A.flags.has("skipMock"),preProcessFlags=e=>{let o=!1,t=!0;ng_mocks_universe.A.flags.has("hasRootModule")?t=!1:ng_mocks_universe.A.flags.add("hasRootModule");const r=ng_mocks_universe.A.getResolution(e);return flagMock(r)&&(o=!0,ng_mocks_universe.A.flags.delete("skipMock")),flagNever(e)&&(o=!0,ng_mocks_universe.A.flags.add("skipMock")),t||!flagKeep(r)&&!flagReplace(r)||(o=!0,ng_mocks_universe.A.flags.add("skipMock")),{isRootModule:t,toggleSkipMockFlag:o}},postProcessFlags=({isRootModule:e,toggleSkipMockFlag:o})=>{o&&ng_mocks_universe.A.flags.has("skipMock")?ng_mocks_universe.A.flags.delete("skipMock"):o&&!ng_mocks_universe.A.flags.has("skipMock")&&ng_mocks_universe.A.flags.add("skipMock"),e&&ng_mocks_universe.A.flags.delete("hasRootModule")},extractModuleAndProviders=e=>{let o,t;return(0,func_is_ng_module_def_with_providers.h)(e)?(o=e.ngModule,e.providers&&(t=e.providers)):o=e,{ngModule:o,ngModuleProviders:t}},getExistingMockModule=(e,o)=>{var t;if(isMockNgDef(e,"m"))return e;if(ng_mocks_universe.A.flags.has("cacheModule")&&ng_mocks_universe.A.cacheDeclarations.has(e))return return_cached_mock(e);if(!o&&"mock"!==(null===(t=ng_mocks_universe.A.config.get("ngMocksDepsResolution"))||void 0===t?void 0:t.get(e))&&ng_mocks_universe.A.hasBuildDeclaration(e)){const o=ng_mocks_universe.A.getBuildDeclaration(e);if((0,func_is_ng_def.p)(o,"m")&&o!==e)return o}},detectMockModule=(e,o)=>{const[t,r,n]=o?[!1]:mock_ng_def(core_reflect_module_resolve(e),e);if(n&&(0,core_define_property.A)(e,"__ngMocksResolutions",n),t){const o=ng_mocks_universe.A.flags.has("skipMock")?e:Mock,t=(0,core_helpers.He)(o);return(0,core_.NgModule)(r)(t),decorate_mock(t,e),t}return o||e},getMockProviders=e=>{if(e){const[o,t]=mock_ng_def({providers:e,skipExports:!0});return o?t.providers:e}},generateReturn=(e,o,t,r,n)=>r===o&&n===t?e:(0,func_is_ng_module_def_with_providers.h)(e)?Object.assign({ngModule:r},n?{providers:n}:{}):r;function MockModule(e){var o;func_import_exists(e,"MockModule");const{ngModule:t,ngModuleProviders:r}=extractModuleAndProviders(e),n=preProcessFlags(t);try{const s=detectMockModule(t,getExistingMockModule(t,n.isRootModule));ng_mocks_universe.A.flags.has("cacheModule")&&ng_mocks_universe.A.cacheDeclarations.set(t,s),ng_mocks_universe.A.flags.has("skipMock")&&(null===(o=ng_mocks_universe.A.config.get("ngMocksDepsSkip"))||void 0===o||o.add(s));const c=getMockProviders(r);return generateReturn(e,t,r,s,c)}finally{postProcessFlags(n)}}const processDefMap=[["c",MockComponent],["d",MockDirective],["p",MockPipe]],processDef=e=>{if((0,func_is_ng_def.p)(e,"m")||(0,func_is_ng_module_def_with_providers.h)(e))return MockModule(e);if(ng_mocks_universe.A.hasBuildDeclaration(e))return ng_mocks_universe.A.getBuildDeclaration(e);if(ng_mocks_universe.A.flags.has("skipMock")&&"mock"!==ng_mocks_universe.A.getResolution(e))return e;for(const[o,t]of processDefMap)if((0,func_is_ng_def.p)(e,o))return t(e)},createResolveProvider=(e,o)=>t=>helper_mock_service.A.resolveProvider(t,e,o),createResolveWithProviders=(e,o)=>(0,func_is_ng_module_def_with_providers.h)(o)&&(0,func_is_ng_module_def_with_providers.h)(e),createResolveExisting=(e,o,t)=>{const r=o.get(e);return e!==r&&t(),r},createResolveExcluded=(e,o,t)=>{o.set(e,void 0),t()},createResolve=(e,o)=>t=>{var r;if(e.has(t))return createResolveExisting(t,e,o);const n=(0,func_get_type.A)(t);if(ng_mocks_universe.A.isExcludedDef(n))return createResolveExcluded(t,e,o);ng_mocks_universe.A.touches.add(n);const s=processDef(t);return createResolveWithProviders(t,s)&&e.set(t.ngModule,s.ngModule),ng_mocks_universe.A.flags.has("skipMock")&&(null===(r=ng_mocks_universe.A.config.get("ngMocksDepsSkip"))||void 0===r||r.add(s)),e.set(t,s),o(s!==t),s},create_resolvers=(e,o)=>({resolve:createResolve(o,e),resolveProvider:createResolveProvider(o,e)}),mark_providers=e=>{for(const o of(0,core_helpers.Bq)(null!=e?e:[])){const e=(0,func_get_type.A)(o);mark_exported(e)}},flatToExisting=(e,o)=>(0,core_helpers.Bq)(e).map(o).filter((e=>!!e)),configureProcessMetaKeys=(e,o)=>[["declarations",e],["hostDirectives",o=>{const t=(0,func_get_type.A)(o),r=e(t);return r===t?o:o==t?r:Object.assign(Object.assign({},o),{directive:r})}],["imports",e],["entryComponents",e],["bootstrap",e],["providers",o],["viewProviders",o],["exports",e],["schemas",e=>e]],processMeta=(e,o,t)=>{var r;const n={},s=configureProcessMetaKeys(o,t),c=ng_mocks_universe.A.flags.has("cachePipe");c||ng_mocks_universe.A.flags.add("cachePipe");for(const[o,t]of s)(null===(r=e[o])||void 0===r?void 0:r.length)&&(n[o]=flatToExisting(e[o],t));return e.skipMarkProviders||(mark_providers(n.providers),mark_providers(n.viewProviders)),c||ng_mocks_universe.A.flags.delete("cachePipe"),n},resolveDefForExport=(e,o,t,r)=>{const n=ng_mocks_universe.A.config.get(r)||{},s=(0,func_get_type.A)(e),c=o(s);if(!c)return;const _=ng_mocks_universe.A.config.get(s);return(null==_?void 0:_.export)&&r&&!n.export&&ng_mocks_universe.A.config.set(r,Object.assign(Object.assign({},n),{export:!0})),!t||n.exportAll||(null==_?void 0:_.export)?(mark_exported(s,r),c):void 0},skipAddExports=(e,o)=>!e||!!o.exports&&-1!==o.exports.indexOf(e),addExports=(e,o,t,r,n)=>{const s=ng_mocks_universe.A.flags.has("skipMock")||ng_mocks_universe.A.flags.has("correctModuleExports");for(const c of(0,core_helpers.Bq)([t.imports||[],t.declarations||[]])){const t=resolveDefForExport(c,e,s,n);skipAddExports(t,r)||(o(),r.exports=r.exports||[],r.exports.push(t))}},mock_ng_def=(e,o)=>{const t=ng_mocks_universe.A.config.has("mockNgDefResolver");t||ng_mocks_universe.A.config.set("mockNgDefResolver",new core_def_stack),ng_mocks_universe.A.config.get("mockNgDefResolver").push();let r=!ng_mocks_universe.A.flags.has("skipMock");const n=(e=!0)=>{r=r||e},{resolve:s,resolveProvider:c}=create_resolvers(n,ng_mocks_universe.A.config.get("mockNgDefResolver")),_=processMeta(e,s,c);e.skipExports||addExports(s,n,e,_,o);for(const e of o&&_.exports?(0,core_helpers.Bq)(_.exports):[])mark_exported(e,o);const i=ng_mocks_universe.A.config.get("mockNgDefResolver").pop();return t||ng_mocks_universe.A.config.delete("mockNgDefResolver"),[r,_,i]},get_override_def=e=>{if(!e)return;const o=ng_mocks_universe.A.flags.has("skipMock");o||ng_mocks_universe.A.flags.add("skipMock");const[t,r]=mock_ng_def(e);return o||ng_mocks_universe.A.flags.delete("skipMock"),t?r:void 0},skip_override=(e,o,t,r)=>!!ng_mocks_universe.A.cacheDeclarations.has(r)||!(!e.has(t)||r!==o.get(t)),create_ng_mocks_overrides_token=(e,o)=>{const t=new Map;for(const r of(0,core_helpers.LG)(ng_mocks_universe.A.touches)){const n=r,s=ng_mocks_universe.A.getBuildDeclaration(n)||n;if(skip_override(e,o,n,s))continue;const c=core_reflect_meta(s),_=get_override_def(c);if(!_)continue;const i={};for(const e of Object.keys(_))i[e]=c[e];t.set(s,[{set:_},{set:i}])}return{provide:core_tokens.So,useValue:t}},create_ng_mocks_token=()=>{const e=new Map;for(const[o,t]of[...(0,core_helpers.Nn)(ng_mocks_universe.A.builtProviders),...(0,core_helpers.Nn)(ng_mocks_universe.A.builtDeclarations),...(0,core_helpers.Nn)(ng_mocks_universe.A.cacheDeclarations),...(0,core_helpers.Nn)(ng_mocks_universe.A.cacheProviders)])e.has(o)||e.set(o,t);return{provide:core_tokens.en,useValue:e}},create_ng_mocks_touches_token=()=>{const e=new Set;for(const o of(0,core_helpers.LG)(ng_mocks_universe.A.touches)){const t=o;let r=ng_mocks_universe.A.getBuildDeclaration(t);void 0===r&&(r=t),e.add(t),e.add(r)}return{provide:core_tokens.Em,useValue:e}};var helper_create_clone=__webpack_require__(365);class EntryComponentsModule{constructor(e,o){if(!o)return;const t=o.resolveComponentFactory;o.resolveComponentFactory=(0,helper_create_clone.A)(t,void 0,void 0,((r,...n)=>{var s;return t.apply(o,[null!==(s=e.get(r))&&void 0!==s?s:r,...n])}))}}(0,core_define_property.A)(EntryComponentsModule,"parameters",[[core_tokens.en],[core_.ComponentFactoryResolver,new core_.Optional]]);class IvyModule{}(0,core_.NgModule)()(IvyModule);const handle_entry_components=e=>{const o=[];for(const t of e.declarations)(0,func_is_ng_def.p)(t,"c")&&o.push(t);const t=(0,core_helpers.He)(EntryComponentsModule);(0,core_.NgModule)({entryComponents:IvyModule.ɵmod?[]:o})(t),e.imports.push(t)};var helper_use_factory=__webpack_require__(465),core_reflect_parameters_resolve=__webpack_require__(749),common_x=e=>{var o={};return __webpack_require__.d(o,e),o},common_y=e=>()=>e;const common_namespaceObject=common_x({DOCUMENT:()=>__WEBPACK_EXTERNAL_MODULE__angular_common_d12e0fe1__.DOCUMENT}),skipResolution=e=>{const o=ng_mocks_universe.A.getResolution(e);return"keep"===o||"exclude"===o||"mock"!==o&&void 0},skipSystem=e=>{if(!e||e===common_namespaceObject.DOCUMENT||ng_mocks_universe.A.touches.has(e))return!0;const o=skipResolution(e);return void 0!==o?o:"function"==typeof e&&-1!==core_config.A.neverMockProvidedFunction.indexOf(e.name)||!(!(0,func_is_ng_injection_token.S)(e)||-1===core_config.A.neverMockToken.indexOf(e.toString()))},skip_dep=e=>{if(skipSystem(e))return!0;const o=core_reflect_provided_in(e);return!("function"!=typeof e||o&&"platform"!==o)},add_def_to_root_provider_parameters=(e,o,t)=>{skip_dep(t)||!o.has(core_tokens.gG)&&ng_mocks_universe.A.config.get("ngMocksDepsSkip").has(t)||e.add(t)},check_root_provider_dependency=(e,o,t)=>{"function"==typeof e&&-1===t.indexOf(e)&&(t.push(e),o.push(e))},extract_dep=e=>{if(!e)return;let o;for(const t of e)t&&"object"==typeof t&&t.token&&(o=t.token),o||!t||"object"==typeof t&&t.ngMetadataName||(o=t);return(0,func_extract_forward_ref.A)(o)},get_root_providers_data=()=>{const e=[(0,core_helpers.LG)(ng_mocks_universe.A.config.get("ngMocksDepsSkip")),(0,core_helpers.LG)(ng_mocks_universe.A.config.get("ngMocksDeps")),(0,core_helpers.LG)(ng_mocks_universe.A.touches)];return{buckets:e,touched:[].concat(...e)}},handle_provided_in_dependency=e=>{if(ng_mocks_universe.A.touches.has(e))return;const o=core_reflect_provided_in(e);o&&ng_mocks_universe.A.config.get("ngMocksDepsSkip").has(o)&&ng_mocks_universe.A.config.get("ngMocksDepsSkip").add(e)},skip_root_provider_dependency=e=>!!skip_dep(e)||ng_mocks_universe.A.config.get("ngMocksDepsSkip").has(e),get_root_provider_parameters=e=>{const o=new Set,{buckets:t,touched:r}=get_root_providers_data();for(const n of t)for(const t of n){add_def_to_root_provider_parameters(o,e,t);for(const s of(0,core_reflect_parameters_resolve.A)(t)){const c=extract_dep(s);handle_provided_in_dependency(c),skip_root_provider_dependency(c)||(check_root_provider_dependency(c,r,n),e.has(core_tokens.gG)||!ng_mocks_universe.A.config.get("ngMocksDepsSkip").has(t)?o.add(c):ng_mocks_universe.A.config.get("ngMocksDepsSkip").add(c))}}return o},handle_root_providers=(e,{keepDef:o,mockDef:t},r)=>{const n=o.has(core_tokens.gG)?new Set:get_root_provider_parameters(t);if(n.size>0)for(const o of(0,core_helpers.LG)(n)){const t=(0,helper_resolve_provider.A)(o,r);if(t)e.providers.push(t);else if((0,func_is_ng_injection_token.S)(o)){const t=ng_mocks_universe.A.config.has("ngMocksMulti")&&ng_mocks_universe.A.config.get("ngMocksMulti").has(o);e.providers.push((0,helper_use_factory.A)(o,(()=>t?[]:void 0)))}}},init_module=(e,o)=>{var t;const r=null!==(t=ng_mocks_universe.A.config.get("mockNgDefResolver").get(e))&&void 0!==t?t:ng_mocks_universe.A.getBuildDeclaration(e),n=o.has(e)?o.get(e):void 0;return n?{ngModule:r,providers:n}:r},skipDef=e=>ng_mocks_universe.A.touches.has(e)||(0,func_is_ng_def.p)(e)||(0,func_is_ng_injection_token.S)(e)||"string"==typeof e,handleDef=({imports:e,declarations:o,providers:t},r,n)=>{skipDef(r)||error_jest_mock(r);let s=!1;if((0,func_is_ng_def.p)(r,"m")){const o=init_module(r,n);if(e.push(o),s=!0,"object"==typeof o&&o.providers)for(const e of(0,core_helpers.Bq)(o.providers))ng_mocks_universe.A.touches.add((0,func_get_type.A)(e))}if(((0,func_is_ng_def.p)(r,"c")||(0,func_is_ng_def.p)(r,"d")||(0,func_is_ng_def.p)(r,"p"))&&((isStandalone(r)?e:o).push(ng_mocks_universe.A.getBuildDeclaration(r)),s=!0),(0,func_is_ng_def.p)(r,"i")||!(0,func_is_ng_def.p)(r)){const e=ng_mocks_universe.A.builtProviders.get(r);e&&"string"!=typeof e&&!1===(0,func_is_ng_def.p)(e,"t")&&(t.push(e),s=!0)}s&&(mark_exported(r),ng_mocks_universe.A.touches.add(r))},isExportedOnRoot=(e,o,t)=>{const r=o.get(e),n=t.get(e)||{};if((0,func_is_ng_def.p)(e,"m")&&n.onRoot)return e;if(!(null==r?void 0:r.exported))return e;for(const e of(0,core_helpers.LG)(r.exported)){const r=isExportedOnRoot(e,o,t);if(r)return r}},moveModulesUp=(e,o)=>{const t=(0,func_is_ng_def.p)(e,"m"),r=(0,func_is_ng_def.p)(o,"m");return t&&r?0:t?-1:r?1:0},init_ng_modules=({configDefault:e,keepDef:o,mockDef:t,replaceDef:r},n)=>{const s={imports:[],declarations:[],providers:[]},c=[],_=[],i=[...(0,core_helpers.LG)(t),...(0,core_helpers.LG)(o),...(0,core_helpers.LG)(r)];i.sort(moveModulesUp);for(const o of i){const t=(0,func_is_ng_def.p)(o,"m")&&n.has(o)?o:isExportedOnRoot(o,ng_mocks_universe.A.configInstance,ng_mocks_universe.A.config);if(!t||-1!==c.indexOf(t))continue;const r=ng_mocks_universe.A.config.get(t)||{__set:!0};c.push(t),r.onRoot=r.onRoot||!r.dependency,r.__set&&(r.__set=void 0,ng_mocks_universe.A.config.set(t,r)),(0,func_is_ng_def.p)(t,"m")&&r.onRoot?handleDef(s,t,n):r.dependency||!r.export||!(0,func_is_ng_def.p)(t,"i")&&(0,func_is_ng_def.p)(t)?!r.dependency&&r.export?handleDef(s,t,n):ng_mocks_universe.A.touches.has(t)||r.dependency?!r.dependency||!e.dependency||"root"===core_reflect_provided_in(t)||"object"==typeof t&&t.__ngMocksSkip||_.push(t):handleDef(s,t,n):(handleDef(s,t,n),mark_providers([t]))}const a=ng_mocks_universe.A.global.get("flags");for(const e of _){if(ng_mocks_universe.A.touches.has(e))continue;const o=[`MockBuilder has found a missing dependency: ${(0,func_get_name.A)(e)}.`,"It means no module provides it.",'Please, use the "export" flag if you want to add it explicitly.',"https://ng-mocks.sudo.eu/api/MockBuilder#export-flag"].join(" ");if("warn"===a.onMockBuilderMissingDependency)console.warn(o);else if("throw"===a.onMockBuilderMissingDependency)throw new Error(o)}return s},funcExtractDeps=(e,o,t=!1)=>{const r=(0,collect_declarations.A)(e),n=getNgType(e);if(!n||"Injectable"===n)return o;const s=r[n];for(const e of core_config.A.dependencies)if(s[e])for(const r of(0,core_helpers.Bq)(s[e])){const e=(0,func_get_type.A)(r);o.has(e)||(o.add(e),t&&funcExtractDeps(e,o))}return o},init_exclude_def=e=>{const o=ng_mocks_universe.A.builtDeclarations,t=ng_mocks_universe.A.builtProviders,r=ng_mocks_universe.A.config.get("ngMocksDepsResolution");for(const n of(0,core_helpers.LG)(e))o.set(n,null),t.set(n,null),r.set(n,"exclude")},init_keep_def=(e,o)=>{const t=new Set,r=ng_mocks_universe.A.builtDeclarations,n=ng_mocks_universe.A.builtProviders,s=ng_mocks_universe.A.config.get("ngMocksDepsResolution");for(const c of(0,core_helpers.LG)(e))r.set(c,c),n.set(c,c),s.set(c,"keep"),o.get(c).shallow&&funcExtractDeps(c,t);return t};var mock_provider=__webpack_require__(415);const createInstance=(e,o,t)=>t.precise?o:(0,mock_helper_stub.A)(e,o),try_mock_provider=(e,o)=>{if((0,func_is_ng_def.p)(e,"i")&&o.has(e)){const t=ng_mocks_universe.A.config.get(e),r=o.get(e);ng_mocks_universe.A.builtProviders.set(e,(0,helper_use_factory.A)(e,void 0,(e=>createInstance(e,r,t))))}else(0,func_is_ng_def.p)(e,"i")&&ng_mocks_universe.A.builtProviders.set(e,(0,mock_provider.A)(e,!0));if(!(0,func_is_ng_def.p)(e)&&o.has(e)){const t=o.get(e);ng_mocks_universe.A.builtProviders.set(e,(0,helper_use_factory.A)(e,void 0,(()=>t)))}else(0,func_is_ng_def.p)(e)||ng_mocks_universe.A.builtProviders.set(e,(0,mock_provider.A)(e,!0))},init_mock_declarations=(e,o)=>{const t=ng_mocks_universe.A.builtDeclarations,r=ng_mocks_universe.A.config.get("ngMocksDepsResolution");for(const n of(0,core_helpers.LG)(e)){const e=!ng_mocks_universe.A.touches.has(n);r.set(n,"mock"),t.set(n,void 0),try_mock_provider(n,o),e&&ng_mocks_universe.A.touches.delete(n)}},try_mock_declaration=e=>{void 0===ng_mocks_universe.A.builtDeclarations.get(e)&&((0,func_is_ng_def.p)(e,"c")&&ng_mocks_universe.A.builtDeclarations.set(e,MockComponent(e)),(0,func_is_ng_def.p)(e,"d")&&ng_mocks_universe.A.builtDeclarations.set(e,MockDirective(e)),(0,func_is_ng_def.p)(e,"p")&&ng_mocks_universe.A.builtDeclarations.set(e,MockPipe(e)))},init_modules=(e,o,t,r)=>{var n,s,c,_,i;const a=new Map;for(const l of[...(0,core_helpers.LG)(e),...(0,core_helpers.LG)(o),...(0,core_helpers.LG)(t)]){const e=(0,collect_declarations.A)(l),t=[...null!==(n=r.get(l))&&void 0!==n?n:[],...null!==(c=null===(s=e.Component)||void 0===s?void 0:s.providers)&&void 0!==c?c:[],...null!==(i=null===(_=e.Directive)||void 0===_?void 0:_.providers)&&void 0!==i?i:[]],p=!ng_mocks_universe.A.touches.has(l);o.has(l)||ng_mocks_universe.A.flags.add("skipMock");const u=(0,func_is_ng_def.p)(l,"m");if(t.length>0){const[,e]=mock_ng_def({providers:t,skipMarkProviders:!u,skipExports:!0});a.set(l,e.providers)}u&&ng_mocks_universe.A.builtDeclarations.set(l,MockModule(l)),ng_mocks_universe.A.flags.delete("skipMock"),p&&ng_mocks_universe.A.touches.delete(l)}for(const e of(0,core_helpers.LG)(o))try_mock_declaration(e);return a},init_replace_def=(e,o)=>{const t=ng_mocks_universe.A.builtDeclarations,r=ng_mocks_universe.A.config.get("ngMocksDepsResolution");for(const n of(0,core_helpers.LG)(e))t.set(n,o.get(n)),r.set(n,"replace")},init_universe=({configDef:e,defProviders:o,defValue:t,excludeDef:r,keepDef:n,mockDef:s,replaceDef:c})=>{ng_mocks_universe.A.flags.add("cachePipe"),ng_mocks_universe.A.config.set("ngMocksMulti",new Set),ng_mocks_universe.A.config.set("ngMocksDeps",new Set),ng_mocks_universe.A.config.set("ngMocksDepsSkip",new Set),ng_mocks_universe.A.config.set("ngMocksDepsResolution",new Map);const _=init_keep_def(n,e);for(const e of(0,core_helpers.LG)(_))ng_mocks_universe.A.touches.add(e);for(const e of(0,core_helpers.LG)(n))_.add(e),funcExtractDeps(e,_,!0);for(const e of(0,core_helpers.LG)(s))_.add(e),funcExtractDeps(e,_,!0);for(const e of(0,core_helpers.LG)(c))_.add(e),funcExtractDeps(e,_,!0);for(const o of(0,core_helpers.LG)(_)){if(e.has(o))continue;const _=ng_mocks_universe.A.getResolution(o);"replace"===_?(c.add(o),t.set(o,ng_mocks_universe.A.getBuildDeclaration(o))):"keep"===_?n.add(o):"exclude"===_?r.add(o):("mock"===_||ng_mocks_universe.A.touches.has(o))&&s.add(o),e.set(o,ng_mocks_universe.A.touches.has(o)?{dependency:!0,__internal:!0}:{})}for(const[o,r]of(0,core_helpers.Nn)(e))ng_mocks_universe.A.config.set(o,Object.assign(Object.assign(Object.assign({},ng_mocks_universe.A.getConfigMock().get(o)),r),{defValue:t.get(o)}));return init_replace_def(c,t),init_exclude_def(r),init_mock_declarations(s,t),init_modules(n,s,c,o)},parse_mock_arguments=(e,o,t,r)=>{let n=e===o?r:o,s=null!=t?t:o!==r&&"object"==typeof o?o:void 0;return(0,func_is_ng_def.p)(e,"p")&&"function"==typeof o&&o!==e&&!(0,func_is_ng_def.p)(o,"p")?(n={transform:o},s=t):!(0,func_is_ng_def.p)(e,"i")&&(0,func_is_ng_def.p)(e)||(s=t),n=n===s?r:n,{config:s,mock:n}},parse_provider=e=>{const o=(0,func_get_type.A)(e);return{multi:o!==e&&e.multi,provide:o}};var __awaiter=function(e,o,t,r){return new(t||(t=Promise))((function(n,s){function c(e){try{i(r.next(e))}catch(e){s(e)}}function _(e){try{i(r.throw(e))}catch(e){s(e)}}function i(e){var o;e.done?n(e.value):(o=e.value,o instanceof t?o:new t((function(e){e(o)}))).then(c,_)}i((r=r.apply(e,o||[])).next())}))};const normaliseModule=e=>(0,func_is_ng_module_def_with_providers.h)(e)?{def:e.ngModule,providers:e.providers}:{def:e,providers:void 0},generateProviderValue=(e,o,t)=>t?[...Array.isArray(o)?o:[],e]:e,defaultMock={};class MockBuilderPromise{constructor(e){this.configDefault=e,this.beforeCC=new Set,this.configDef=new Map,this.defProviders=new Map,this.defValue=new Map,this.excludeDef=new Set,this.keepDef=new Set,this.mockDef=new Set,this.providerDef=new Map,this.replaceDef=new Set,this.stash=new MockBuilderStash,"undefined"!=typeof Symbol&&(this[Symbol.toStringTag]="Promise")}beforeCompileComponents(e){return this.beforeCC.add(e),this}build(){this.stash.backup();const e=new core_def_stack;ng_mocks_universe.A.config.set("mockNgDefResolver",e),ng_mocks_universe.A.flags.add("hasRootModule");try{const o=this.combineParams(),t=init_ng_modules(o,init_universe(o));return add_requested_providers(t,o,e),handle_root_providers(t,o,e),handle_entry_components(t),apply_platform_modules(),t.providers.push(create_ng_mocks_token(),create_ng_mocks_touches_token(),create_ng_mocks_overrides_token(this.replaceDef,this.defValue),MockBuilder),t}finally{ng_mocks_universe.A.flags.delete("hasRootModule"),ng_mocks_universe.A.config.delete("mockNgDefResolver"),this.stash.restore()}}catch(e){return __awaiter(this,void 0,void 0,(function*(){return this.then().catch(e)}))}exclude(e){return this.wipe(e),this.excludeDef.add(e),this.setConfigDef(e),this}finally(e){return __awaiter(this,void 0,void 0,(function*(){return this.then().finally(e)}))}keep(e,o){const{def:t,providers:r}=normaliseModule(e),n=this.keepDef.has(t)?this.defProviders.get(t):[];return this.wipe(t),this.keepDef.add(t),r&&this.defProviders.set(t,[...n||[],...r]),this.setConfigDef(t,o),this}mock(e,o=defaultMock,t){const{def:r,providers:n}=normaliseModule(e),{config:s,mock:c}=parse_mock_arguments(r,o,t,defaultMock);if((0,func_is_ng_def.p)(c)&&(0,func_is_ng_def.p)(e)&&!(0,func_is_ng_def.p)(e,"t"))throw new Error([`MockBuilder.mock(${(0,func_get_name.A)(e)}) received a class when its shape is expected.`,"Please try ngMocks.defaultMock instead."].join(" "));const _=this.mockDef.has(r)?this.defProviders.get(r):[];return this.wipe(r),this.mockDef.add(r),n&&this.defProviders.set(r,[..._||[],...n]),this.setDefValue(r,c),this.setConfigDef(r,s),this}provide(e){for(const o of(0,core_helpers.Bq)(e)){const{provide:e,multi:t}=parse_provider(o),r=this.providerDef.has(e)?this.providerDef.get(e):[];this.providerDef.set(e,generateProviderValue(o,r,t))}return this}replace(e,o,t){if(!(0,func_is_ng_def.p)(o)||!(0,func_is_ng_def.p)(e)||(0,func_is_ng_def.p)(o,"i")||(0,func_is_ng_def.p)(e,"i"))throw new Error("Cannot replace the declaration, both have to be a Module, a Component, a Directive or a Pipe, for Providers use `.mock` or `.provide`");return this.wipe(e),this.replaceDef.add(e),this.defValue.set(e,o),this.setConfigDef(e,t),this}then(e,o){return __awaiter(this,void 0,void 0,(function*(){const t=new Promise((e=>{const o=testing_.TestBed.configureTestingModule(this.build());for(const e of(0,core_helpers.LG)(this.beforeCC))e(o);o.compileComponents().then((()=>{e({testBed:o})}))}));return t.then(e,o)}))}combineParams(){return{configDef:this.configDef,configDefault:this.configDefault,defProviders:this.defProviders,defValue:this.defValue,excludeDef:this.excludeDef,keepDef:this.keepDef,mockDef:this.mockDef,providerDef:this.providerDef,replaceDef:this.replaceDef}}setConfigDef(e,o){!o&&this.configDef.has(e)||this.configDef.set(e,null!=o?o:this.configDefault)}setDefValue(e,o){o===defaultMock?this.defValue.delete(e):this.defValue.set(e,o)}wipe(e){this.defProviders.delete(e),this.defValue.delete(e),this.excludeDef.delete(e),this.keepDef.delete(e),this.mockDef.delete(e),this.providerDef.delete(e),this.replaceDef.delete(e)}}const objectsDiffer=(e,o)=>{const t=Object.keys(e),r=Object.keys(o);if(t.length!==r.length)return!0;for(const r of t)if(e[r]!==o[r])return!0;return!1},equal_variables=(e,o)=>e===o||!(e&&!o||!e&&o)&&!objectsDiffer(e,o),equal_render_defs=(e,o)=>e===o||("boolean"!=typeof e&&"boolean"!=typeof o||e===o)&&e.$implicit===o.$implicit&&equal_variables(e.variables,o.variables),equal_render_configs_objectsDiffer=(e,o)=>{if(Object.keys(e).length!==Object.keys(o).length)return!0;for(const t of Object.keys(e))if(!equal_render_defs(e[t],o[t]))return!0;return!1},equal_render_configs=(e,o)=>!(!equal_render_defs(o,e)||"object"==typeof o&&"object"==typeof e&&equal_render_configs_objectsDiffer(o,e)),are_equal_config_params=(e,o)=>o===e||o.dependency===e.dependency&&o.export===e.export&&o.exportAll===e.exportAll&&!!equal_render_configs(e.render,o.render),are_equal_maps=(e,o,t=((e,o)=>e===o))=>{if(!o||o.size!==e.size)return!1;for(const r of(0,core_helpers.d4)(e)){if(!o.has(r))return!1;if(!t(o.get(r),e.get(r)))return!1}return!0},areEqualProviderDefs=(e,o,...t)=>{for(const r of t)if(o&&e&&o[r]&&e[r]&&o[r]===e[r])return!0;return o===e},are_equal_providers=(e,o)=>{if(Array.isArray(e)!==Array.isArray(o))return!1;const[t,r]=[(0,core_helpers.Bq)(e),(0,core_helpers.Bq)(o)];if(t.length!==r.length)return!1;for(let e=0;e{if(!o||o.size!==e.size)return!1;for(const t of(0,core_helpers.LG)(e))if(!o.has(t))return!1;return!0},get_empty_config=()=>({beforeCC:new Set,configDef:new Map,defProviders:new Map,defValue:new Map,excludeDef:new Set,keepDef:new Set,mockDef:new Set,providerDef:new Map,replaceDef:new Set}),required_metadata=e=>Object.assign(Object.assign({},e),{declarations:[...e.declarations||[]],imports:[...e.imports||[]],providers:[...e.providers||[]]});var mock_builder_performance_awaiter=function(e,o,t,r){return new(t||(t=Promise))((function(n,s){function c(e){try{i(r.next(e))}catch(e){s(e)}}function _(e){try{i(r.throw(e))}catch(e){s(e)}}function i(e){var o;e.done?n(e.value):(o=e.value,o instanceof t?o:new t((function(e){e(o)}))).then(c,_)}i((r=r.apply(e,o||[])).next())}))};class MockBuilderPerformance extends MockBuilderPromise{build(){const e=ng_mocks_universe.A.global;if(e.has("builder:module")&&e.has("builder:config")&&this.equalsTo(e.get("builder:config")))return required_metadata(e.get("builder:module"));e.has("builder:module")&&e.delete(e.get("builder:module"));const o=this.cloneConfig(),t=super.build();return e.set("builder:config",o),e.set("builder:module",t),required_metadata(t)}then(e,o){const t=Object.create(null,{then:{get:()=>super.then}});return mock_builder_performance_awaiter(this,void 0,void 0,(function*(){const r=ng_mocks_universe.A.global;if(r.has("bullet")&&r.has("builder:module")&&r.has("builder:config")&&this.equalsTo(r.get("builder:config")))return r.get(r.get("builder:module")).then(e,o);r.has("bullet")&&r.has("bullet:reset")&&(console.warn("ngMocks.faster has zero effect due to changes in testing module between runs"),r.delete("bullet"),testing_.TestBed.resetTestingModule(),r.set("bullet",!0));const n=t.then.call(this,e,o);return r.set(r.get("builder:module"),n),n}))}cloneConfig(){const e=get_empty_config();return(0,core_helpers.LG)(this.beforeCC,e.beforeCC),(0,core_helpers.LG)(this.excludeDef,e.excludeDef),(0,core_helpers.LG)(this.keepDef,e.keepDef),(0,core_helpers.LG)(this.mockDef,e.mockDef),(0,core_helpers.LG)(this.replaceDef,e.replaceDef),(0,core_helpers.Nn)(this.configDef,e.configDef),(0,core_helpers.Nn)(this.defProviders,e.defProviders),(0,core_helpers.Nn)(this.defValue,e.defValue),(0,core_helpers.Nn)(this.providerDef,e.providerDef),e}equalsTo(e){for(const o of["beforeCC","keepDef","replaceDef","excludeDef","mockDef"])if(!are_equal_sets(this[o],e[o]))return!1;for(const o of["defValue"])if(!are_equal_maps(this[o],e[o]))return!1;for(const o of["providerDef","defProviders"])if(!are_equal_maps(this[o],e[o],are_equal_providers))return!1;return are_equal_maps(this.configDef,e.configDef,are_equal_config_params)}}function MockBuilder(...e){const[o,t]=e,r=new MockBuilderPerformance(e.length<2?{export:!0}:{dependency:!0}),n=ng_mocks_universe.A.config.get("MockBuilderExtensions");for(const e of n?(0,core_helpers.d4)(n):[]){if((0,helper_extract_property_descriptor.A)(r,e))throw new Error(`MockBuilder.${e} is a base method and cannot be customized, please use a different name.`);(0,core_define_property.A)(r,e,((...o)=>(n.get(e)(r,o),r)))}if(o)for(const e of(0,core_helpers.Bq)(o))r.keep(e,{export:!0,shallow:isStandalone(e)});if(t)for(const e of(0,core_helpers.Bq)(t))r.mock(e,e,{export:!0,exportAll:!0});return r}function mockBuilderExtend(e,o){var t;const r=null!==(t=ng_mocks_universe.A.config.get("MockBuilderExtensions"))&&void 0!==t?t:new Map;o?(r.set(e,o),ng_mocks_universe.A.config.set("MockBuilderExtensions",r)):r.delete(e)}!function(e){e.extend=function(e,o){mockBuilderExtend(e,o)}}(MockBuilder||(MockBuilder={}));const is_debug_node=e=>!!(null==e?void 0:e.nativeElement)||!!(null==e?void 0:e.nativeNode),func_parse_find_args_name=e=>"string"==typeof e?e:"function"==typeof e?e.name:(0,func_is_ng_def.p)(e,"t")?e._desc:Array.isArray(e)?e[0]:e?"":"",is_fixture=e=>!!e&&"object"==typeof e&&void 0!==e.debugElement,findDebugElement=e=>is_fixture(e)?findDebugElement(e.debugElement):e&&e.injector&&e.query?e:void 0,func_parse_find_args=(e,o)=>{var t;let r,n,s=o;return 3===e.length?(r=findDebugElement(e[0]),n=e[1],s=e[2]):1===e.length?(r=findDebugElement(func_get_last_fixture()),[n]=e):e[0]?(r=findDebugElement(e[0]),r?n=e[1]:(r=findDebugElement(func_get_last_fixture()),[n,s]=e)):n=e[1],n=null!==(t=findDebugElement(n))&&void 0!==t?t:n,[r,n,s]};var platform_browser_x=e=>{var o={};return __webpack_require__.d(o,e),o},platform_browser_y=e=>()=>e;const platform_browser_namespaceObject=platform_browser_x({By:()=>__WEBPACK_EXTERNAL_MODULE__angular_platform_browser_bc6fa964__.By}),func_parse_find_term=e=>Array.isArray(e)?platform_browser_namespaceObject.By.css(1===e.length?`[${e[0]}]`:`[${e[0]}="${e[1]}"]`):"string"==typeof e?platform_browser_namespaceObject.By.css(e):platform_browser_namespaceObject.By.directive(getSourceOfMock(e)),defaultNotFoundValue={},mock_helper_find=(...e)=>{const[o,t,r]=func_parse_find_args(e,defaultNotFoundValue),n=is_debug_node(t)?t:null==o?void 0:o.query(func_parse_find_term(t));if(n)return n;if(r!==defaultNotFoundValue)return r;throw new Error(`Cannot find an element via ngMocks.find(${func_parse_find_args_name(t)})`)},detect_text_node=e=>"#text"===e.nativeNode.nodeName,el_def_compare=(e,o)=>!(!e||!o)&&e===o,el_def_get_node=e=>detect_text_node(e)?void 0:e.injector._tNode||e.injector.elDef||void 0,defaultInjector={},core_injector=(e,o=defaultInjector)=>{if(o===defaultInjector)return(0,core_helpers.d5)(e);try{return o.get(e)}catch(e){return}},getVcr=(e,o)=>{if(e!==o&&"#comment"===o.nativeNode.nodeName)return core_injector(core_.ViewContainerRef,o.injector)},getScanViewRefRootNodes=(e,o)=>{const t=getVcr(e,o);if(!t)return[];const r=[];for(let e=0;e{var o;let t,r;for(const n of(null===(o=e.parent)||void 0===o?void 0:o.childNodes)||[])for(const[o,s]of getScanViewRefRootNodes(e,n))s===e.nativeNode&&(void 0===r||o{var o,t,r,n;return(null===(o=e.injector._tNode)||void 0===o?void 0:o.parent)||(null===(t=e.injector.elDef)||void 0===t?void 0:t.parent)||scanViewRef(e)||(null===(r=e.parent)||void 0===r?void 0:r.injector._tNode)||(null===(n=e.parent)||void 0===n?void 0:n.injector.elDef)||void 0},nested_check_children=e=>{var o,t;const r=el_def_get_node(e);if(!r||detect_text_node(e))return[];const n=void 0!==e.childNodes,s=[];for(const t of e.childNodes||(null===(o=e.parent)||void 0===o?void 0:o.childNodes)||[]){const e=el_def_get_parent(t);(n||el_def_compare(r,e))&&(e&&!el_def_compare(r,e)||s.push(t))}if("BODY"===(null===(t=e.parent)||void 0===t?void 0:t.name)){const o=e.parent.childNodes;let t=o.length,r=0;for(let n=o.length-1;n>=0;n-=1){const s=o[n];if("#comment"===s.nativeNode.nodeName)r=n;else if(s.nativeNode===e.nativeNode){t=n+1;break}}for(let e=t;e{var t;if(o)return o;const r=el_def_get_parent(e),n=e.parent?el_def_get_node(e.parent):void 0;if(e.parent&&el_def_compare(r,n))return e.parent;for(const o of(null===(t=e.parent)||void 0===t?void 0:t.childNodes)||[]){const e=el_def_get_node(o);if(el_def_compare(r,e))return o}},nested_check_parent=detectParent,nestedCheck=(e,o,t,r=!1)=>{if(!e)return!1;if(!r&&detect_text_node(e))return!1;if(t(e,nested_check_parent(e,o)))return!0;for(const o of nested_check_children(e))if(nestedCheck(o,e,t,r))return!0;return!1},nested_check=nestedCheck,mock_helper_crawl=(e,o,t=!1)=>{const r=mock_helper_find(func_get_last_fixture(),e,void 0);nested_check(r,void 0,o,t)},isSelector=e=>("string"==typeof e||Array.isArray(e)&&"string"==typeof e[0]||is_fixture(e)||is_debug_node(e),!0),mock_helper_func_parse_find_args=(e,o,t)=>{let r,n,s=t;return 3===e.length?[r,n,s]=e:1===e.length?(r=func_get_last_fixture(),[n]=e):o(e[1])&&isSelector(e[0])?[r,n]=e:(r=func_get_last_fixture(),[n,s]=e),[r,n,s]},detect_attribute_in_selectors=(e,o)=>{for(const t of e){const e=t.match(/\[([^=\]]+)/g);if(e)for(const t of e)if(t===`[${o}`)return!0}return!1},getMeta=e=>{try{return core_reflect_directive_resolve(e)}catch(e){return}},func_parse_provider_tokens_directives=(e,o)=>{if(e)try{const t=(0,func_get_type.A)(o),r=core_injector(t,e.injector);return getMeta(r.constructor)}catch(e){return}},func_get_public_provider_keys=e=>e.injector.elDef?Object.keys(e.injector.elDef.element.publicProviders):[],func_parse_inputs_and_requires_attributes=(e,o)=>{const t=e.injector.elDef.element.publicProviders[o],r=t.provider.value;if(!r)return[[],[],0];const n=func_parse_provider_tokens_directives(e,r),s=t.bindings.map((e=>e.nonMinifiedName||e.name));return[(null==n?void 0:n.inputs)||[],s,t.nodeIndex]},collectSelectors=e=>{const o=[];for(const t of e.providerTokens){const r=func_parse_provider_tokens_directives(e,t);(null==r?void 0:r.selector)&&-1===o.indexOf(r.selector)&&o.push(r.selector)}return o},collectAttributesClassic=e=>{const o=[];for(const t of func_get_public_provider_keys(e)){const[r,n]=func_parse_inputs_and_requires_attributes(e,t);for(const e of r){const{name:t,alias:r}=(0,func_directive_io_parse.A)(e),s=r||t;-1!==n.indexOf(t)&&-1===o.indexOf(s)&&o.push(s)}}return o},collectAttributesIvy=e=>{var o,t;const r=[],n=(null===(o=e.injector._tNode)||void 0===o?void 0:o.attrs)||[];let s=2;for(let o=0;o[collectSelectors(e),[...collectAttributesClassic(e),...collectAttributesIvy(e)]],crawl_by_attribute=e=>o=>{const[t,r]=detect_selectors_from_node(o);return-1!==r.indexOf(e)||!!detect_attribute_in_selectors(t,e)},detectInClassic=(e,o,t)=>{for(const r of func_get_public_provider_keys(e)){const[n,s,c]=func_parse_inputs_and_requires_attributes(e,r);for(const r of n){const{name:n,alias:_}=(0,func_directive_io_parse.A)(r);if(o===(_||n)&&-1!==s.indexOf(n)&&t===e.injector.view.nodes[c].instance[n])return!0}}return!1},detectInIvy=(e,o,t)=>{var r,n,s;const c=(null===(r=e.injector._tNode)||void 0===r?void 0:r.attrs)||[];let _=2;for(let r=0;rt=>!!detectInIvy(t,e,o)||detectInClassic(t,e,o),crawl_by_declaration=e=>{const o=getSourceOfMock(e);return e=>!!e&&-1!==e.providerTokens.indexOf(o)&&void 0!==core_injector(o,e.injector)},crawl_by_id=e=>o=>!!o.references[e],regExp=new RegExp("\\[.*?\\]","g"),detect_tag_name_in_selectors=(e,o)=>{for(const t of e){const e=t.replace(regExp,"").split(",");for(const t of e)if(t.trim()===o)return!0}return!1},crawl_by_tag_name=e=>o=>{const[t]=detect_selectors_from_node(o);return detect_tag_name_in_selectors(t,e)},isCrawlByAttribute=e=>Array.isArray(e)&&1===e.length&&"string"==typeof e[0],isCrawlByAttributeValue=e=>Array.isArray(e)&&2===e.length&&"string"==typeof e[0],isCrawlById=e=>"string"==typeof e&&0===e.indexOf("#")&&e.length>1,isCrawlByTagName=e=>"string"==typeof e&&0!==e.indexOf("#")&&e.length>0,isCrawlByDeclaration=e=>"function"==typeof e,detect_crawler=e=>{if(isCrawlByAttribute(e))return crawl_by_attribute(e[0]);if(isCrawlByAttributeValue(e))return crawl_by_attribute_value(e[0],e[1]);if(isCrawlById(e))return crawl_by_id(e.slice(1));if(isCrawlByTagName(e))return crawl_by_tag_name(e);if(isCrawlByDeclaration(e))return crawl_by_declaration(e);throw new Error("Unknown selector")},func_is_valid_reveal_selector=e=>"string"==typeof e||!(!Array.isArray(e)||"string"!=typeof e[0])||"function"==typeof e,mock_helper_reveal_defaultNotFoundValue={},mock_helper_reveal=(...e)=>{const[o,t,r]=mock_helper_func_parse_find_args(e,func_is_valid_reveal_selector,mock_helper_reveal_defaultNotFoundValue),n=mock_helper_find(func_get_last_fixture(),o,void 0),s=detect_crawler(t);let c;if(mock_helper_crawl(n,(e=>!(e===n||detect_text_node(e)||!s(e)||(c=e,0)))),c)return c;if(r!==mock_helper_reveal_defaultNotFoundValue)return r;throw new Error(`Cannot find a DebugElement via ngMocks.reveal(${func_parse_find_args_name(t)})`)},mock_helper_reveal_all=(...e)=>{const[o,t]=mock_helper_func_parse_find_args(e,func_is_valid_reveal_selector),r=mock_helper_find(func_get_last_fixture(),o,void 0),n=detect_crawler(t),s=[];return mock_helper_crawl(r,(e=>{e!==r&&!detect_text_node(e)&&n(e)&&s.push(e)})),s},isMockControlValueAccessor=e=>!!func_is_mock(e)&&!!e.__ngMocksConfig.isControlValueAccessor;var helper_define_property_descriptor=__webpack_require__(6),helper_extract_methods_from_prototype=__webpack_require__(331);const is_html_element=e=>!!e&&"object"==typeof e&&void 0!==e.innerHTML,preventBubble=["focus","blur","load","unload","change","reset","scroll"],customEvent=(e,o)=>{const t=Object.assign({bubbles:!1,cancelable:!1},o),r=document.createEvent("CustomEvent");return r.initCustomEvent(e,t.bubbles,t.cancelable,null),r},eventCtor="function"==typeof Event?(e,o)=>new CustomEvent(e,o):customEvent,keyMap={alt:{altKey:!0,code:"AltLeft",key:"Alt",location:1,which:18},arrowdown:{code:"ArrowDown",key:"ArrowDown",location:0,which:40},arrowleft:{code:"ArrowLeft",key:"ArrowLeft",location:0,which:37},arrowright:{code:"ArrowRight",key:"ArrowRight",location:0,which:39},arrowup:{code:"ArrowUp",key:"ArrowUp",location:0,which:38},backspace:{code:"Backspace",key:"Backspace",location:0,which:8},control:{code:"ControlLeft",ctrlKey:!0,key:"Control",location:1,which:17},enter:{code:"Enter",key:"Enter",location:0,which:13},esc:{code:"Escape",key:"Escape",location:0,which:27},meta:{code:"MetaLeft",key:"Meta",location:1,metaKey:!0,which:91},shift:{code:"ShiftLeft",key:"Shift",location:1,shiftKey:!0,which:16},space:{code:"Space",key:" ",location:0,which:32},tab:{code:"Tab",key:"Tab",location:0,which:9}};for(let e=1;e<=12;e+=1)keyMap[`f${e}`]={code:`F${e}`,key:`F${e}`,location:0,which:e+111};const getCode=e=>{const o=e.codePointAt(0);return o&&o>=97&&o<=122||o&&o>=65&&o<=90?`Key${e.toUpperCase()}`:o&&o>=48&&o<=57?`Digit${e}`:"Unknown"},applyPayload=(e,o)=>{const t={};for(const e of o?o.split("."):[]){let o=keyMap[e];if(o||1!==e.length||(o={code:getCode(e),key:e}),!o)throw new Error(`Unknown event part ${e}`);(0,mock_helper_stub.A)(t,o)}o&&(0,mock_helper_stub.A)(e,t)},mock_helper_event=(e,o,t)=>{const r=e.indexOf("."),[n,s]=-1===r?[e]:[e.slice(0,Math.max(0,r)),e.slice(r+1)],c=eventCtor(n,Object.assign({bubbles:-1===preventBubble.indexOf(e),cancelable:!0},o));return applyPayload(c,s),t&&(0,mock_helper_stub.A)(c,t),c},mock_helper_trigger_preventBubble=["focus","blur","load","unload","change","reset","scroll"],toEventObj=e=>"string"==typeof e?mock_helper_event(e,{bubbles:-1===mock_helper_trigger_preventBubble.indexOf(e),cancelable:!0}):e,getNativeElement=e=>is_debug_node(e)||is_fixture(e)?e.nativeElement:is_html_element(e)?e:void 0,mock_helper_trigger=(e,o,t)=>{const r=is_html_element(e)?e:mock_helper_find(func_get_last_fixture(),e,void 0),n=getNativeElement(r);if(!n)throw new Error(`Cannot trigger ${"string"==typeof o?o:o.type} event undefined element`);if(n.disabled)return;const s=toEventObj(o);s.target||(0,mock_helper_stub.A)(s,{target:n}),t&&(0,mock_helper_stub.A)(s,t),n.dispatchEvent(s)};var mock_helper_stub_member=__webpack_require__(589);const message=["Cannot find ControlValueAccessor on the element.","If it is a mock input with [formControlName],","you need either to avoid mocking ReactiveFormsModule","or to avoid accessing the control in such a way,","because this tests ReactiveFormsModule instead of own implementation."].join(" "),func_get_vca=e=>{const o=core_form&&core_injector(core_form.NgControl,e.injector),t=null==o?void 0:o.valueAccessor;if(t)return t;const r=core_form&&core_injector(core_form.FormControlDirective,e.injector);if(null==r?void 0:r.form)return r.form;const n=core_form&&core_injector(core_form.NgModel,e.injector);if(n)return n;throw new Error(message)},triggerInput=(e,o)=>{mock_helper_trigger(e,"focus");const t=Object.getOwnPropertyDescriptor(e.nativeElement,"value");(0,mock_helper_stub_member.A)(e.nativeElement,"value",o),mock_helper_trigger(e,"input"),mock_helper_trigger(e,"change"),t&&((0,helper_define_property_descriptor.A)(e.nativeElement,"value",t),e.nativeElement.value=o),mock_helper_trigger(e,"blur")},handleKnown=(e,o)=>core_form&&e instanceof core_form.AbstractControl?(e.setValue(o),!0):core_form&&e instanceof core_form.NgModel?(e.update.emit(o),!0):!!isMockControlValueAccessor(e.instance)&&(e.instance.__simulateChange(o),!0),hasListener=e=>e.listeners.some((e=>"input"===e.name||"change"===e.name)),keys=["onChange","onChangeCallback","onChangeCb","onChangeClb","onChangeFn","_onChange","_onChangeCallback","_onChangeCb","_onChangeClb","_onChangeFn","changeFn","_changeFn","onModelChange","cvaOnChange","cvaOnChangeCallback","cvaOnChangeCb","cvaOnChangeClb","cvaOnChangeFn","_cvaOnChange","_cvaOnChangeCallback","_cvaOnChangeCb","_cvaOnChangeClb","_cvaOnChangeFn"],mock_helper_change=(e,o,t)=>{const r=mock_helper_find(func_get_last_fixture(),e,void 0);if(!r)throw new Error(`Cannot find an element via ngMocks.change(${func_parse_find_args_name(e)})`);const n=func_get_vca(r);if(handleKnown(n,o)||hasListener(r))return void triggerInput(r,o);for(const e of t?[t]:keys)if("function"==typeof n[e])return n.writeValue(o),void n[e](o);const s=(0,helper_extract_methods_from_prototype.A)(n);throw new Error(["Unsupported type of ControlValueAccessor,",`please ensure it has '${t||"onChange"}' method.`,"If it is a 3rd-party library, please provide the correct name of the method in the 'methodName' parameter.","Possible Names: "+s.join(", ")+"."].join(" "))},triggerTouch=e=>{mock_helper_trigger(e,"focus"),mock_helper_trigger(e,"blur")},mock_helper_touch_handleKnown=e=>core_form&&e instanceof core_form.AbstractControl?(e.markAsTouched(),!0):!!isMockControlValueAccessor(e.instance)&&(e.instance.__simulateTouch(),!0),mock_helper_touch_hasListener=e=>e.listeners.some((e=>"focus"===e.name||"blur"===e.name)),mock_helper_touch_keys=["onTouched","onTouchedCallback","onTouchedCb","onTouchedClb","onTouchedFn","_onTouched","_onTouchedCallback","_onTouchedCb","_onTouchedClb","_onTouchedFn","markAsTouched","_markAsTouched","onModelTouched","cvaOnTouch","cvaOnTouchCallback","cvaOnTouchCb","cvaOnTouchClb","cvaOnTouchFn","_cvaOnTouch","_cvaOnTouchCallback","_cvaOnTouchCb","_cvaOnTouchClb","_cvaOnTouchFn"],mock_helper_touch=(e,o)=>{const t=mock_helper_find(func_get_last_fixture(),e,void 0);if(!t)throw new Error(`Cannot find an element via ngMocks.touch(${func_parse_find_args_name(e)})`);const r=func_get_vca(t);if(mock_helper_touch_handleKnown(r)||mock_helper_touch_hasListener(t))return void triggerTouch(t);for(const e of o?[o]:mock_helper_touch_keys)if("function"==typeof r[e])return void r[e]();const n=(0,helper_extract_methods_from_prototype.A)(r);throw new Error(["Unsupported type of ControlValueAccessor,",`please ensure it has '${o||"onTouched"}' method.`,"If it is a 3rd-party library, please provide the correct name of the method in the 'methodName' parameter.","Possible Names: "+n.join(", ")+"."].join(" "))},mock_helper_click=(e,o)=>{mock_helper_trigger(e,"click",o)},mock_helper_find_all=(...e)=>{const[o,t]=func_parse_find_args(e);return is_debug_node(t)?[t]:(null==o?void 0:o.queryAll(func_parse_find_term(t)))||[]},getParentWithInjector=e=>{let o=e;for(;"NullInjector"===(null==o?void 0:o.injector.constructor.name);)o=o.parent;if(o)return o.injector},func_get_from_node_injector=(e,o,t)=>{if(!o.injector||"NullInjector"===o.injector.constructor.name)return;const r=getParentWithInjector(o.parent),n=r?core_injector(t,r):void 0,s=core_injector(t,o.injector);n!==s&&((0,func_is_ng_def.p)(t,"t")&&void 0!==s||void 0!==s&&-1===e.indexOf(s))&&e.push(s)},func_get_from_node_element=e=>{var o;return"#text"===(null===(o=e.nativeNode)||void 0===o?void 0:o.nodeName)&&e.parent?e.parent:e},detectGatherFlag=(e,o,t)=>!!(o&&o.nativeNode&&"#comment"===o.nativeNode.nodeName&&Array.isArray(t)&&t[0]===o.nativeNode)||!Array.isArray(t)&&(o&&t.nodeName?"#comment"===t.nodeName?t===o.nativeNode:"#text"===t.nodeName&&t.parentNode===o.nativeNode:e),isNotObject=e=>!e||"object"!=typeof e,shouldBeScanned=(e,o)=>-1===e.indexOf(o)&&Array.isArray(o),scan=({result:e,el:o,nodes:t,normalize:r,proto:n},s,c=[])=>{c.push(t);let _=s,i=t.length;t.length>1&&t[1]&&"object"==typeof t[1]&&t[1].bindingStartIndex&&(i=t[1].bindingStartIndex);for(let s=0;s{if("object"==typeof e[1]&&e[20]===o)return e;for(let t=21;t{var o;let t=e,r=null===(o=t.nativeNode)||void 0===o?void 0:o.__ngContext__;for(;void 0===r&&t.parent;)t=t.parent,r=t.nativeNode.__ngContext__;if("number"!=typeof r)return r;const n=t.injector._lView;return Array.isArray(n)?detectContextByIndex(n,r):void 0},contextToNodes=e=>Array.isArray(e)?e:null==e?void 0:e.lView,func_get_from_node_ivy=(e,o,t)=>{if(!o||o._debugContext)return;const r=func_get_from_node_element(o);func_get_from_node_scan({el:r,nodes:contextToNodes(detectContext(o))||[],normalize:e=>e,proto:t,result:e},!0)},normalize=e=>{if(!e||"object"!=typeof e)return e;for(const o of["renderElement","renderText","instance"])if(e[o])return e[o];return null},func_get_from_node_standard=(e,o,t)=>{if(!o||!o._debugContext)return;const r=func_get_from_node_element(o);func_get_from_node_scan({el:r,nodes:o._debugContext.view.nodes,normalize,proto:t,result:e},!0)},func_get_from_node=(e,o,t)=>(func_get_from_node_injector(e,o,t),(0,func_is_ng_def.p)(t,"t")||"string"==typeof t||(func_get_from_node_standard(e,o,t),func_get_from_node_ivy(e,o,t)),e),func_is_valid_find_instance_selector=e=>"function"==typeof e||(0,func_is_ng_def.p)(e,"t"),mock_helper_find_instance_defaultNotFoundValue={},mock_helper_find_instance=(...e)=>{const[o,t,r]=mock_helper_func_parse_find_args(e,func_is_valid_find_instance_selector,mock_helper_find_instance_defaultNotFoundValue);if("function"!=typeof t&&!(0,func_is_ng_def.p)(t,"t")&&"string"!=typeof t)throw new Error("Only classes or tokens are accepted");const n=getSourceOfMock(t),s=[],c=func_get_last_fixture();if(c)mock_helper_crawl(mock_helper_find(c,o,void 0),((e,o)=>(func_get_from_node(s,e,n),0===s.length&&o&&"#comment"===o.nativeNode.nodeName&&func_get_from_node(s,o,n),s.length>0)),!0);else try{s.push((0,core_helpers.Ah)(n))}catch(e){if(!e||"object"!=typeof e||void 0===e.ngTempTokenPath)throw e}if(s.length>0)return s[0];if(r!==mock_helper_find_instance_defaultNotFoundValue)return r;throw new Error(`Cannot find an instance via ngMocks.findInstance(${func_parse_find_args_name(t)})`)},mock_helper_find_instances=(...e)=>{const[o,t]=mock_helper_func_parse_find_args(e,func_is_valid_find_instance_selector);if("function"!=typeof t&&!(0,func_is_ng_def.p)(t,"t")&&"string"!=typeof t)throw new Error("Only classes or tokens are accepted");const r=getSourceOfMock(t),n=[],s=[],c=func_get_last_fixture();if(c){const e=mock_helper_find_all(c,o,void 0);for(const o of e)mock_helper_crawl(o,((e,o)=>{-1===s.indexOf(e)&&(func_get_from_node(n,e,r),s.push(e)),o&&"#comment"===o.nativeNode.nodeName&&-1===s.indexOf(o)&&(func_get_from_node(n,o,r),s.push(o))}),!0)}else try{n.push((0,core_helpers.Ah)(r))}catch(e){}return n},handle_array=(e,o)=>e(o.map((o=>e(o,!0))).join("")),format_handler=e=>(o,t=!1)=>{const r=(o,n=!1)=>{if(Array.isArray(o))return handle_array(r,o);if(is_fixture(o))return r(o.debugElement,t);const s=e(r,o,n);return void 0!==s?s:is_debug_node(o)&&"#comment"===o.nativeNode.nodeName?r(nested_check_children(o),!0):is_debug_node(o)?r(o.nativeNode,n):""};return Array.isArray(o)?o.map((e=>r(e,t))):r(o,t)},handle_text=e=>{var o,t;return null!==(t=null!==(o=e.nodeValue)&&void 0!==o?o:e.textContent)&&void 0!==t?t:e.wholeText},is_text=e=>!!e&&"object"==typeof e&&"#text"===e.nodeName,normalizeValue=e=>e?e.replace(new RegExp("\\s+","mg")," ").replace(new RegExp("\x3c!--(.|\\n|\\r)*?--\x3e|\x3c!--(.|\\n|\\r)*","mg"),"").replace(new RegExp("\\s+","mg")," ").replace(new RegExp(">\\s+<","mg"),"><").replace(new RegExp('"\\s+>',"mg"),'">'):"",normalizeText=e=>e.replace(new RegExp("&","mg"),"&").replace(new RegExp('"',"mg"),""").replace(new RegExp("<","mg"),"<").replace(new RegExp(">","mg"),">").replace(new RegExp("'","mg"),"'"),getElementValue=(e,o)=>o?e.outerHTML:e.innerHTML,handlePrimitives=(e,o,t)=>{if("string"==typeof o||void 0===o){const e=normalizeValue(o);return t?e:e.trim()}return is_html_element(o)?e(getElementValue(o,t)):is_text(o)?handlePrimitives(e,normalizeText(handle_text(o)),t):void 0},mock_helper_format_html=format_handler(handlePrimitives),mock_helper_format_text_normalizeValue=e=>e?e.replace(new RegExp("\\s+","mg")," "):"",mock_helper_format_text_getElementValue=(e,o)=>{var t;const r=null!==(t=e.textContent)&&void 0!==t?t:"";return o?r:r.trim()},mock_helper_format_text_handlePrimitives=(e,o,t)=>{if("string"==typeof o||void 0===o){const e=mock_helper_format_text_normalizeValue(o);return t?e:e.trim()}return is_html_element(o)?e(mock_helper_format_text_getElementValue(o,t)):is_text(o)?mock_helper_format_text_handlePrimitives(e,handle_text(o),t):void 0},mock_helper_format_text=format_handler(mock_helper_format_text_handlePrimitives),calls=[],mock_helper_auto_spy=e=>{"reset"===e?calls.pop():calls.push(e);const o=calls[calls.length-1];return"jasmine"===o?(0,helper_mock_service.O)((e=>jasmine.createSpy(e))):"jest"===o?(0,helper_mock_service.O)((e=>jest.fn().mockName(e))):o&&"default"!==o&&"reset"!==o?(0,helper_mock_service.O)(o):(0,helper_mock_service.O)()},mock_helper_console=(e,o)=>(...t)=>{const r=[];beforeEach((()=>{for(const o of e)-1===t.indexOf(o)&&t.push(o);for(const e of t)(0,core_define_property.A)(console,`__ngMocksBackup_${e}`,console[`__ngMocksBackup_${e}`]||[]),console[`__ngMocksBackup_${e}`].push(console[e]),r.push(e),console[e]=o(e)})),afterEach((()=>{for(const e of r)console[e]=console[`__ngMocksBackup_${e}`].pop();r.splice(0,r.length)}))},factory=e=>helper_mock_service.A.mockFunction(`console.${e}`),mock_helper_console_ignore=mock_helper_console(["log"],factory),mock_helper_console_throw_factory=e=>(...o)=>{const t=new Error(o.join(" "));throw(0,core_define_property.A)(t,"ngMocksConsoleCatch",e),t},mock_helper_console_throw=mock_helper_console(["warn","error"],mock_helper_console_throw_factory),mock_helper_default_config=(e,o)=>{const t=ng_mocks_universe.A.getConfigMock();for(const r of(0,core_helpers.Bq)(e))o?t.set(r,o):t.delete(r)},mock_helper_default_mock=(e,o)=>{const t=ng_mocks_universe.A.getOverrides();for(const r of(0,core_helpers.Bq)(e))if(o){const e=t.has(r)?t.get(r):new Set;e.add(o),t.set(r,e)}else t.delete(r)},hooks=ng_mocks_universe.A.global.get("faster-hooks")||{after:[],before:[]};ng_mocks_universe.A.global.set("faster-hooks",hooks);const configureTestingModule=(e,o)=>t=>{if(testing_.TestBed.ngMocksFasterLock)return e.call(o,t);ng_mocks_universe.A.global.set("bullet:customized",!0);let r=e;for(const e of hooks.before)r=e(r,o);try{return(0,core_define_property.A)(testing_.TestBed,"ngMocksFasterLock",!0),r.call(o,t)}finally{(0,core_define_property.A)(testing_.TestBed,"ngMocksFasterLock",void 0)}},resetTestingModule=(e,o)=>()=>{if(testing_.TestBed.ngMocksFasterLock)return e.call(o);if(ng_mocks_universe.A.global.has("bullet"))return ng_mocks_universe.A.global.has("bullet:customized")&&ng_mocks_universe.A.global.set("bullet:reset",!0),o;ng_mocks_universe.A.global.delete("bullet:customized"),ng_mocks_universe.A.global.delete("bullet:reset");let t=e;for(const e of hooks.after)t=e(t,o);try{return(0,core_define_property.A)(testing_.TestBed,"ngMocksFasterLock",!0),t.call(o)}finally{(0,core_define_property.A)(testing_.TestBed,"ngMocksFasterLock",void 0)}},mock_helper_faster_install=()=>{testing_.TestBed.ngMocksFasterInstalled||(testing_.TestBed.configureTestingModule=configureTestingModule(testing_.TestBed.configureTestingModule,testing_.TestBed),testing_.TestBed.resetTestingModule=resetTestingModule(testing_.TestBed.resetTestingModule,testing_.TestBed),(0,core_define_property.A)(testing_.TestBed,"ngMocksFasterInstalled",!0));const e=(0,testing_.getTestBed)();return e.ngMocksFasterInstalled||(e.configureTestingModule=configureTestingModule(e.configureTestingModule,e),e.resetTestingModule=resetTestingModule(e.resetTestingModule,e),(0,core_define_property.A)(e,"ngMocksFasterInstalled",!0)),hooks},mock_helper_flush_test_bed=()=>{const e=(0,testing_.getTestBed)();e._instantiated=!1,e._moduleFactory=void 0,e._testModuleRef=null},resetFixtures=e=>{const o=(0,testing_.getTestBed)()._activeFixtures||[];let t=0;for(let r=o.length-1;r>=0;r-=1)o[r].ngMocksStackId&&o[r].ngMocksStackId!==e?t+=1:(o[r].ngMocksStackId=void 0,o[r].destroy(),o.splice(r,1));0===t&&mock_helper_flush_test_bed()},idAdd=e=>{var o;const t=null!==(o=ng_mocks_universe.A.global.get("bullet:stack"))&&void 0!==o?o:[];t.push(e),ng_mocks_universe.A.global.set("bullet:stack",t),ng_mocks_universe.A.global.set("bullet:stack:id",e)},idRemove=e=>{const o=ng_mocks_universe.A.global.get("bullet:stack");o.splice(o.indexOf(e),1),o.length>0?ng_mocks_universe.A.global.set("bullet:stack:id",o[o.length-1]):ng_mocks_universe.A.global.delete("bullet:stack:id"),resetFixtures(e)},mock_helper_faster=()=>{mock_helper_faster_install();const e={},o={};beforeAll((()=>{ng_mocks_universe.A.global.has("bullet:customized")&&testing_.TestBed.resetTestingModule(),ng_mocks_universe.A.global.set("bullet",!0),idAdd(e)})),beforeEach((()=>{idAdd(o)})),afterEach((()=>{idRemove(o)})),afterAll((()=>{idRemove(e),ng_mocks_universe.A.global.delete("bullet"),ng_mocks_universe.A.global.has("bullet:reset")&&testing_.TestBed.resetTestingModule()}))},mock_helper_get_defaultNotFoundValue={},parseArgs=e=>({el:e[0],notFoundValue:3===e.length?e[2]:mock_helper_get_defaultNotFoundValue,sel:e[1]}),mock_helper_get=(...e)=>{if(1===e.length)try{return testing_.TestBed.inject?testing_.TestBed.inject(e[0]):testing_.TestBed.get(e[0])}catch(o){if(!o||"object"!=typeof o||void 0===o.ngTempTokenPath)throw o;throw new Error(`Cannot find an instance via ngMocks.get(${func_parse_find_args_name(e[0])})`)}const{el:o,sel:t,notFoundValue:r}=parseArgs(e),n=mock_helper_find(func_get_last_fixture(),o,void 0),s=getSourceOfMock(t);if(n){const e=func_get_from_node([],n,s);if(e.length>0)return e[0]}if(n){const e=nested_check_parent(n,void 0);if(e&&"#comment"===e.nativeNode.nodeName){const o=func_get_from_node([],e,s);if(o.length>0)return o[0]}}if(r!==mock_helper_get_defaultNotFoundValue)return r;throw new Error(`Cannot find ${(0,func_get_name.A)(t)} instance via ngMocks.get`)},iterator=(e,o,t=new Set)=>{const r=(0,collect_declarations.A)(e);for(const e of r.decorators)for(const n of core_config.A.dependencies)if(r[e][n])for(const s of(0,core_helpers.Bq)(r[e][n])){const e=(0,func_get_type.A)(s);e&&!t.has(e)&&(t.add(e),o(e),iterator(e,o,t))}},func_iterate_declaration=iterator,func_global_prepare=()=>{var e;ng_mocks_universe.A.cacheDeclarations.clear(),null===(e=ng_mocks_universe.A.config.get("ngMocksDepsSkip"))||void 0===e||e.clear()},action=e=>{ng_mocks_universe.A.getDefaults().set(e,["exclude"])},mock_helper_global_exclude=(e,o=!1)=>{func_global_prepare(),action(e),o&&func_iterate_declaration(e,action)},mock_helper_global_keep_action=e=>{ng_mocks_universe.A.getDefaults().set(e,["keep"])},mock_helper_global_keep=(e,o=!1)=>{func_global_prepare(),mock_helper_global_keep_action(e),o&&func_iterate_declaration(e,mock_helper_global_keep_action)},mock_helper_global_mock_action=e=>{ng_mocks_universe.A.getDefaults().set(e,["mock"])},mock_helper_global_mock=(e,o=!1)=>{func_global_prepare(),mock_helper_global_mock_action(e),o&&func_iterate_declaration(e,mock_helper_global_mock_action)},mock_helper_global_replace=(e,o)=>{let t=!0;if(((0,func_is_ng_def.p)(e,"m")&&(0,func_is_ng_def.p)(o,"m")||(0,func_is_ng_def.p)(e,"c")&&(0,func_is_ng_def.p)(o,"c")||(0,func_is_ng_def.p)(e,"d")&&(0,func_is_ng_def.p)(o,"d")||(0,func_is_ng_def.p)(e,"p")&&(0,func_is_ng_def.p)(o,"p"))&&(t=!1),t)throw new Error("Cannot replace the declaration, both have to be a Module, a Component, a Directive or a Pipe");func_global_prepare(),ng_mocks_universe.A.getDefaults().set(e,["replace",o])},mock_helper_global_wipe_action=e=>{ng_mocks_universe.A.getDefaults().delete(e),mock_helper_default_mock(e)},mock_helper_global_wipe=(e,o=!1)=>{func_global_prepare(),mock_helper_global_wipe_action(e),o&&func_iterate_declaration(e,mock_helper_global_wipe_action)},mock_helper_guts_skipDef=(e,o,t)=>!!o.has(e)||(o.add(e),t.has(e)),createMetaHandler=(e,o,t,r,n)=>{const s=e.get(o)||o;(0,func_is_ng_def.p)(s,"m")?t.push(s):(0,func_is_ng_def.p)(s,"c")||(0,func_is_ng_def.p)(s,"d")?r.push(s):(0,func_is_ng_def.p)(s,"p")?(r.push(s),n.push(s)):(0,func_is_ng_injection_token.S)(s)||n.push(s)},createMeta=({keep:e,skip:o,optional:t,exclude:r,imports:n,declarations:s,providers:c})=>{for(const _ of e)o.has(_)||r.has(_)||t.has(_)||createMetaHandler(t,_,n,s,c);return{declarations:s,imports:n,providers:c}},typeMap=[["m","module"],["c","component"],["d","directive"],["p","pipe"]],mock_helper_guts_getType=(e,o)=>{if((0,func_is_ng_module_def_with_providers.h)(e))return"module-with-providers";for(const[t,r]of typeMap)if((0,func_is_ng_def.p)(e,t))return"m"===t&&o.has(e)?`${r}-keep`:r;return""},handleModuleWithProviders=(e,o)=>{e.skip.has(o.ngModule)||(e.skip.add(o.ngModule),e.exclude.has(o.ngModule)||e.imports.push(e.keep.has(o.ngModule)?o:MockModule(o)))},handleDeclaration=(e,o,t,r)=>{mock_helper_guts_skipDef(o,e.skip,e.exclude)||r.push(e.keep.has(o)?o:t(o))},handleDestructuring=(e,o,t)=>{if(mock_helper_guts_skipDef(o,e.skip,e.exclude))return;const r=core_reflect_module_resolve(o);for(const o of(0,core_helpers.Bq)([r.declarations,r.imports]))t(e,o);for(const o of r.providers?(0,core_helpers.Bq)(r.providers):[])resolveProvider(e,o)},resolveProvider=({skip:e,keep:o,providers:t,exclude:r},n)=>{const s=(0,func_get_type.A)(n);if(e.add(s),r.has(s))return;const c=o.has(s)?n:(0,mock_provider.A)(n);c&&t.push(c)},resolveMap={component:MockComponent,directive:MockDirective,pipe:MockPipe},resolveHandler=(e,o,t,r)=>{"module-with-providers"===o?handleModuleWithProviders(e,t):"module-keep"===o||"module"===o&&r?handleDeclaration(e,t,MockModule,e.imports):"module"===o?handleDestructuring(e,t,resolve):resolveMap[o]?handleDeclaration(e,t,resolveMap[o],e.declarations):resolveProvider(e,t)},resolve=(e,o,t=!0)=>{if(!o)return;const r=mock_helper_guts_getType(o,e.keep);let n;if("module-with-providers"!==r){const t=e.optional.get(o);t&&t!==o&&(n=t,e.keep.add(n))}n||(n=o),resolveHandler(e,r,n,t)},generateDataWithUniverse=(e,o,t,r)=>{for(const n of(0,core_helpers.d4)(ng_mocks_universe.A.getDefaults())){const s=ng_mocks_universe.A.getBuildDeclaration(n);e.has(n)||o.has(n)||t.has(n)||(r.set(n,s),null===s?t.add(n):void 0===s?o.add(n):n===s&&e.add(n))}},generateData=(e,o,t)=>{const r=new Set((0,core_helpers.Bq)(e||[])),n=new Set((0,core_helpers.Bq)(o||[])),s=new Set((0,core_helpers.Bq)(t||[])),c=new Map;return generateDataWithUniverse(r,n,s,c),{declarations:[],exclude:s,imports:[],keep:r,mock:n,optional:c,providers:[],skip:new Set}},mock_helper_guts=(e,o=null,t=null)=>{const r=generateData(e,o,t),n=new Map;ng_mocks_universe.A.config.set("ngMocksDepsResolution",n);for(const e of(0,core_helpers.LG)(r.keep))n.set(e,"keep");for(const e of(0,core_helpers.LG)(r.exclude))n.set(e,"exclude");ng_mocks_universe.A.config.set("mockNgDefResolver",new core_def_stack);for(const e of(0,core_helpers.LG)(r.mock))n.set(e,"mock"),r.optional.has(e)||resolve(r,e,!1);const s=createMeta(r);return ng_mocks_universe.A.config.delete("mockNgDefResolver"),ng_mocks_universe.A.config.delete("ngMocksDepsResolution"),s},mock_helper_attributes_defaultNotFoundValue={},mock_helper_attributes_parseArgs=e=>[e[0],e[1],3===e.length?e[2]:mock_helper_attributes_defaultNotFoundValue],attrMatches=(e,o)=>{const{name:t,alias:r=""}=(0,func_directive_io_parse.A)(e);if(!r&&t===o||r&&r===o)return t},detectAttribute=(e,o,t)=>{for(const r of(null==e?void 0:e.providerTokens)||[]){const n=func_parse_provider_tokens_directives(e,r);if(n)for(const s of n[o]||[]){const o=attrMatches(s,t);if(o)return mock_helper_get(e,r)[o]}}throw new Error("Not found")},mock_helper_attributes=(e,o,...t)=>{const[r,n,s]=mock_helper_attributes_parseArgs(t);try{return detectAttribute(mock_helper_find(func_get_last_fixture(),r,void 0),o,n)}catch(e){}if(s!==mock_helper_attributes_defaultNotFoundValue)return s;throw new Error(`Cannot find ${n} ${e} via ngMocks.${e}`)},mock_helper_input=(...e)=>mock_helper_attributes("input","inputs",...e),mock_helper_output=(...e)=>mock_helper_attributes("output","outputs",...e),mock_helper_reset=()=>{ng_mocks_universe.A.builtDeclarations=new Map,ng_mocks_universe.A.builtProviders=new Map,ng_mocks_universe.A.cacheDeclarations=new Map,ng_mocks_universe.A.cacheProviders=new Map,ng_mocks_universe.A.config=new Map,ng_mocks_universe.A.configInstance=new Map,ng_mocks_universe.A.flags=new Set(core_config.A.flags),ng_mocks_universe.A.touches=new Set},getValVcr=e=>{const o=[];for(const t of e.__ngMocksConfig.queryScanKeys||[]){const r=e[t],n=e[`__ngMocksVcr_${t}`],s=r instanceof core_.QueryList?r.toArray():[r],c=n instanceof core_.QueryList?n.toArray():[n];for(let e=0;e!!e.__template&&!!e.__vcr&&o(e.__template)&&t(e.__vcr,e.__template),isRightTemplate=(e,o,t)=>!!e&&o instanceof core_.TemplateRef&&t(o),findDeep=(e,o,t)=>{if(!func_is_mock(e))throw new Error("Only instances of mock declarations are accepted");if(handleDirective(e,o,t))return!0;for(const[r,n]of getValVcr(e)){if(func_is_mock(r)&&findDeep(r,o,t))return!0;if(isRightTemplate(n,r,o))return t(n,r)}return!1},func_find_deep=findDeep,func_parse_template=e=>{if(e instanceof core_.TemplateRef)return e;if(func_is_mock(e)&&e.__template)return e.__template;const o=(null==e?void 0:e.nativeNode)&&e.injector;if(o){const e=core_injector(core_.TemplateRef,o);if(e)return e}const t=new Error("Unknown template has been passed, only TemplateRef or a mock structural directive are supported");throw t.param=e,t},mock_helper_hide=(e,o)=>{const t=o?func_parse_template(o):void 0;let r=!1;if(func_find_deep(e,(e=>!t||e.elementRef.nativeElement===t.elementRef.nativeElement),(e=>(e.clear(),r=!0,!1))),!r)throw new Error("Cannot find path to the TemplateRef")},mock_helper_render=(e,o,t,r)=>{const n=func_parse_template(o);if(!func_find_deep(e,(e=>e.elementRef.nativeElement===n.elementRef.nativeElement),((e,o)=>{const n=Object.assign(Object.assign({},r),{$implicit:t});return e.clear(),e.createEmbeddedView(o,n).detectChanges(),!0})))throw new Error("Cannot find path to the TemplateRef")},template_ref_detect_crawler=e=>{if("string"==typeof e)return crawl_by_id(e);if(Array.isArray(e)&&1===e.length&&"string"==typeof e[0])return crawl_by_attribute(e[0]);if(Array.isArray(e)&&2===e.length&&"string"==typeof e[0])return crawl_by_attribute_value(e[0],e[1]);if("function"==typeof e)return crawl_by_declaration(e);throw new Error("Unknown selector")},detect_template_ref=(e,o,t=0)=>r=>{try{const t=!detect_text_node(r)&&o(r)?core_injector(core_.TemplateRef,r.injector):void 0;t&&e.push(t)}catch(e){}return!!t&&e.length===t},func_is_valid_template_ref_selector=e=>"string"==typeof e||!(!Array.isArray(e)||"string"!=typeof e[0])||"function"==typeof e,mock_helper_find_template_ref_defaultNotFoundValue={},mock_helper_find_template_ref=(...e)=>{const[o,t,r]=mock_helper_func_parse_find_args(e,func_is_valid_template_ref_selector,mock_helper_find_template_ref_defaultNotFoundValue),n=[],s=template_ref_detect_crawler(t);if(nested_check(mock_helper_find(func_get_last_fixture(),o,void 0),void 0,detect_template_ref(n,s,1)),n.length>0)return n[0];if(r!==mock_helper_find_template_ref_defaultNotFoundValue)return r;throw new Error(`Cannot find a TemplateRef via ngMocks.findTemplateRef(${func_parse_find_args_name(t)})`)},mock_helper_find_template_refs=(...e)=>{const[o,t]=mock_helper_func_parse_find_args(e,func_is_valid_template_ref_selector),r=[],n=template_ref_detect_crawler(t);return nested_check(mock_helper_find(func_get_last_fixture(),o,void 0),void 0,detect_template_ref(r,n)),r},flagNames=["onMockBuilderMissingDependency","onMockInstanceRestoreNeed","onTestBedFlushNeed"],mock_helper_object={autoSpy:mock_helper_auto_spy,change:mock_helper_change,click:mock_helper_click,config:e=>{const o=ng_mocks_universe.A.global.get("flags");for(const t of flagNames)null===e[t]?o[t]=core_config.A[t]:void 0!==e[t]&&(o[t]=e[t]);null===e.mockRenderCacheSize?ng_mocks_universe.A.global.delete("mockRenderCacheSize"):void 0!==e.mockRenderCacheSize&&ng_mocks_universe.A.global.set("mockRenderCacheSize",e.mockRenderCacheSize)},crawl:mock_helper_crawl,defaultConfig:mock_helper_default_config,defaultMock:mock_helper_default_mock,event:mock_helper_event,faster:mock_helper_faster,find:mock_helper_find,findAll:mock_helper_find_all,findInstance:mock_helper_find_instance,findInstances:mock_helper_find_instances,findTemplateRef:mock_helper_find_template_ref,findTemplateRefs:mock_helper_find_template_refs,flushTestBed:mock_helper_flush_test_bed,formatHtml:mock_helper_format_html,formatText:mock_helper_format_text,get:mock_helper_get,globalExclude:mock_helper_global_exclude,globalKeep:mock_helper_global_keep,globalMock:mock_helper_global_mock,globalReplace:mock_helper_global_replace,globalWipe:mock_helper_global_wipe,guts:mock_helper_guts,hide:mock_helper_hide,ignoreOnConsole:mock_helper_console_ignore,input:mock_helper_input,output:mock_helper_output,render:mock_helper_render,reset:mock_helper_reset,reveal:mock_helper_reveal,revealAll:mock_helper_reveal_all,stub:mock_helper_stub.A,stubMember:mock_helper_stub_member.A,throwOnConsole:mock_helper_console_throw,touch:mock_helper_touch,trigger:mock_helper_trigger},ngMocks=mock_helper_object;var mock_service=__webpack_require__(839);const defaultValue={};function MockProviders(...e){return e.map((e=>MockProvider(e,defaultValue)))}function MockProvider(e,o=defaultValue,t,r={}){func_import_exists(e,"MockProvider");const{deps:n,multi:s}="boolean"==typeof r?{deps:void 0,multi:r}:Array.isArray(r)?{deps:r,multi:void 0}:r;return t?{provide:e,[t]:o,deps:n,multi:s}:(0,helper_use_factory.A)(e,(()=>(0,mock_service.K)(e)),(e=>o===defaultValue?e:e?(0,mock_helper_stub.A)(e,o):o))}const applyOverride=(e,o)=>{(0,func_is_ng_def.p)(e,"c")?testing_.TestBed.overrideComponent(e,o):(0,func_is_ng_def.p)(e,"d")?testing_.TestBed.overrideDirective(e,o):(0,func_is_ng_def.p)(e,"m")&&testing_.TestBed.overrideModule(e,o),((0,func_is_ng_def.p)(e,"t")||(0,func_is_ng_def.p)(e,"i"))&&testing_.TestBed.overrideProvider(e,o)},ng_mocks_global_overrides_applyOverrides=e=>{for(const[o,[t,r]]of(0,core_helpers.Nn)(e))testing_.TestBed.ngMocksOverrides.set(o,Object.assign(Object.assign({},r),{override:t})),applyOverride(o,t)},applyNgMocksOverrides=e=>{var o;if(null===(o=e.ngMocksOverrides)||void 0===o?void 0:o.size){ngMocks.flushTestBed();for(const[o,t]of(0,core_helpers.Nn)(e.ngMocksOverrides))applyOverride(o,t)}e.ngMocksOverrides=void 0},initTestBed=()=>{testing_.TestBed.ngMocksSelectors||(0,core_define_property.A)(testing_.TestBed,"ngMocksSelectors",new Map),testing_.TestBed.ngMocksOverrides||(0,core_define_property.A)(testing_.TestBed,"ngMocksOverrides",new Map)},generateTouches=(e,o)=>{for(const t of core_config.A.dependencies)for(const r of e[t]?(0,core_helpers.Bq)(e[t]):[]){const e=(0,func_get_type.A)(r);if((0,func_is_ng_module_def_with_providers.h)(r)&&generateTouches(r,o),!o.has(e)&&(o.add(e),"function"==typeof e)){if(!Object.prototype.hasOwnProperty.call(e,"__ngMocksTouches")){const o=new Set,t=core_reflect_meta(e);(0,core_define_property.A)(e,"__ngMocksTouches",o,!1),t&&generateTouches(t,o)}(0,core_helpers.LG)(e.__ngMocksTouches,o)}}},defineTouches=(e,o,t)=>{var r;let n=t;return!n&&ng_mocks_universe.A.getDefaults().size>0&&(n=func_extract_tokens(e._providers||(null===(r=e._compiler)||void 0===r?void 0:r.providers)).touches,n||(n=new Set,o.providers=o.providers||[],o.providers.push({provide:core_tokens.Em,useValue:n})),generateTouches(o,n)),n},applyPlatformOverrideDef=e=>{const o=(0,func_get_type.A)(e);if(testing_.TestBed.ngMocksOverrides.has(o))return;const t=core_reflect_module_resolve(o),r=get_override_def(t);r&&(testing_.TestBed.ngMocksOverrides.set(o,{set:t}),testing_.TestBed.overrideModule(o,{set:r}))},applyPlatformOverridesBasedOnProvidedIn=(e,o)=>{const t=core_reflect_provided_in(e);t&&("string"==typeof t||o.has(t))&&(testing_.TestBed.ngMocksOverrides.set(e,{}),testing_.TestBed.overrideProvider(e,MockProvider(e)))},applyPlatformOverridesBasedOnDefaults=e=>{for(const[o,[t]]of(0,core_helpers.Nn)(ng_mocks_universe.A.getDefaults()))"mock"===t&&((0,func_is_ng_def.p)(o,"i")||(0,func_is_ng_def.p)(o,"t"))&&(e.has(o)||testing_.TestBed.ngMocksOverrides.has(o)||applyPlatformOverridesBasedOnProvidedIn(o,e))},applyPlatformOverrides=(e,o)=>{if(testing_.TestBed.ngMocksOverrides){const t=ng_mocks_universe.A.touches;ng_mocks_universe.A.touches=o;for(const o of(0,core_helpers.Bq)(e.ngModule||[]))applyPlatformOverrideDef(o);applyPlatformOverridesBasedOnDefaults(o),ng_mocks_universe.A.touches=t}},ng_mocks_global_overrides_configureTestingModule=(e,o)=>t=>{var r,n;initTestBed();const s=!("object"!=typeof t||!t||t.providers&&-1!==t.providers.indexOf(MockBuilder));let c=0;const _=[];for(const e of s?["imports","declarations"]:[])for(const o of(0,core_helpers.Bq)(t[e]))o&&(_.push([(0,func_is_ng_module_def_with_providers.h)(o)?{ngModule:getSourceOfMock(o.ngModule),providers:o.providers}:getSourceOfMock(o),(0,func_is_ng_module_def_with_providers.h)(o)?o.ngModule:o,isMockNgDef((0,func_get_type.A)(o))]),c|=_[_.length-1][2]?2:1);let i=3===c?void 0:t;if(!i){let e=MockBuilder(core_tokens.gG);for(const[o,t,n]of _){const s=null===(r=t.prototype.__ngMocksConfig)||void 0===r?void 0:r.transform,c={export:!(0,func_is_ng_def.p)(o,"m"),exportAll:!1,onRoot:!0};e=n&&s?e.mock(o,s,c):n?e.mock(o,c):e.keep(o,c)}i=e.build(),i=Object.assign(Object.assign(Object.assign({},t),i),{providers:[...null!==(n=t.providers)&&void 0!==n?n:[],...i.providers]})}const a=(0,testing_.getTestBed)(),l=func_extract_tokens(i.providers),{mocks:p,overrides:u}=l,d=defineTouches(a,i,l.touches);return p&&ngMocks.flushTestBed(),u&&ng_mocks_global_overrides_applyOverrides(u),!d||a._instantiated||a._testModuleRef||applyPlatformOverrides(a,d),e.call(o,i)},ng_mocks_global_overrides_resetTestingModule=(e,o)=>()=>(ng_mocks_universe.A.global.delete("builder:config"),ng_mocks_universe.A.global.delete("builder:module"),testing_.TestBed.ngMocksSelectors=void 0,applyNgMocksOverrides(testing_.TestBed),e.call(o)),patchVcrInstance=e=>{if(!core_.ViewContainerRef.ngMocksOverridesPatched&&((0,core_define_property.A)(core_.ViewContainerRef,"ngMocksOverridesPatched",!0),e.createComponent)){const o=e.createComponent,t=(0,helper_create_clone.A)(o,void 0,void 0,(function(e,...t){var r;const n=core_injector(core_tokens.en,this.injector);return o.apply(this,[null!==(r=null==n?void 0:n.get(e))&&void 0!==r?r:e,...t])}));(0,core_define_property.A)(e.constructor.prototype,"createComponent",t,!0),(0,core_define_property.A)(e,"createComponent",t,!0)}},createComponent=(e,o)=>t=>{const r=e.call(o,t);try{const e=r.debugElement.injector.get(core_.ViewContainerRef);patchVcrInstance(e)}catch(e){}return r},viewContainerInstall=()=>{const e=core_.ViewContainerRef;if(!e.ngMocksOverridesInstalled){const o=e.__NG_ELEMENT_ID__;o&&(0,core_define_property.A)(e,"__NG_ELEMENT_ID__",(0,helper_create_clone.A)(o,void 0,void 0,((...e)=>{const t=o.apply(o,e);return patchVcrInstance(t),t})),!0),(0,core_define_property.A)(testing_.TestBed,"createComponent",createComponent(testing_.TestBed.createComponent,testing_.TestBed)),(0,core_define_property.A)(core_.ViewContainerRef,"ngMocksOverridesInstalled",!0)}},installInjector=e=>{if(e.constructor.prototype.__ngMocksInjector||!e.constructor.prototype.get)return e;(0,core_define_property.A)(e.constructor.prototype,"__ngMocksInjector",!0);const o=e.constructor.prototype.get;return e.constructor.prototype.get=(0,helper_create_clone.A)(o,void 0,void 0,(function(e,...t){const r=o.call(this,e,...t);return r&&"object"==typeof r&&"function"==typeof r.constructor&&"string"==typeof r.constructor.name&&"Injector"===r.constructor.name.slice(-8)&&installInjector(r),r})),e},install=()=>{if(!testing_.TestBed.ngMocksOverridesInstalled){const e=mock_helper_faster_install();viewContainerInstall(),-1===e.before.indexOf(ng_mocks_global_overrides_configureTestingModule)&&e.before.push(ng_mocks_global_overrides_configureTestingModule),-1===e.after.indexOf(ng_mocks_global_overrides_resetTestingModule)&&e.after.push(ng_mocks_global_overrides_resetTestingModule),(0,core_define_property.A)(testing_.TestBed,"ngMocksOverridesInstalled",!0);const o=core_.Injector.create;core_.Injector.create=(0,helper_create_clone.A)(o,void 0,void 0,((...e)=>installInjector(o.apply(core_.Injector,e))));try{core_.Injector.create({length:0,providers:[]})}catch(e){}}};function isMockedNgDefOf(e,o,t){return"function"==typeof e&&e.mockOf===o&&(!t||(0,func_is_ng_def.p)(e,t))}install();const getMock=(e,o,t)=>{if(t&&!t.has(o))throw new Error(`There is no mock for ${(0,func_get_name.A)(o)}`);let r=t?t.get(o):void 0;return r===o&&(r=void 0),r||o===e?!r&&ng_mocks_universe.A.cacheDeclarations.has(o)&&(r=ng_mocks_universe.A.cacheDeclarations.get(o)):r=e,r};function getMockedNgDefOf(e,o){var t;const r=null!==(t=e.mockOf)&&void 0!==t?t:e,n=core_injector(core_tokens.en),s=getMock(e,r,n);if(s&&!o)return s;if(s&&o&&isMockedNgDefOf(s,r,o))return s;throw new Error(`There is no mock for ${(0,func_get_name.A)(r)}`)}function isMockOf(e,o,t){return func_is_mock(e)&&e.constructor===o&&(t?(0,func_is_ng_def.p)(e.constructor,t):(0,func_is_ng_def.p)(e.constructor))}const isMockValidator=e=>!!func_is_mock(e)&&!!e.__ngMocksConfig.isValidator,mock_instance_forgot_reset=e=>{const o=[];for(;e.length>0;){const[t,r]=e.pop()||[];r===ng_mocks_universe.A.configInstance.get(t)&&o.push("function"==typeof t?(0,func_get_name.A)(t):t)}if(o.length>0){const e=ng_mocks_universe.A.global.get("flags"),t=[`MockInstance: side effects have been detected (${o.join(", ")}).`,"Forgot to add MockInstance.scope() or to call MockInstance.restore()?"].join(" ");if("warn"===e.onMockInstanceRestoreNeed)console.warn(t);else if("throw"===e.onMockInstanceRestoreNeed)throw new Error(t)}};let currentStack;ng_mocks_stack.subscribePush((e=>{currentStack=e})),ng_mocks_stack.subscribePop(((e,o)=>{for(const o of e.mockInstance||[])if(ng_mocks_universe.A.configInstance.has(o)){const e=ng_mocks_universe.A.configInstance.get(o);e.overloads.pop(),ng_mocks_universe.A.configInstance.set(o,Object.assign({},e))}currentStack=o[o.length-1]}));const parseMockInstanceArgs=e=>{const o={};return"string"==typeof e[0]?(o.key=e[0],o.value=e[1],o.accessor=e[2]):(o.value=e[0],o.value&&"object"==typeof o.value&&(o.value=o.value.init)),o},checkReset=[];let checkCollect=!1;"undefined"!=typeof beforeEach&&(beforeEach((()=>checkCollect=!0)),beforeEach((()=>mock_instance_forgot_reset(checkReset))),afterEach((()=>checkCollect=!1)));const mockInstanceConfig=(e,o,t,r)=>{var n;const s=ng_mocks_universe.A.configInstance.has(e)?ng_mocks_universe.A.configInstance.get(e):{},c=s.overloads||[];c.push([o,t,r]),s.overloads=c,ng_mocks_universe.A.configInstance.set(e,Object.assign({},s));const _=null!==(n=currentStack.mockInstance)&&void 0!==n?n:[];return _.push(e),currentStack.mockInstance=_,checkCollect&&checkReset.push([e,ng_mocks_universe.A.configInstance.get(e),currentStack]),t};function MockInstance(e,...o){if(func_import_exists(e,"MockInstance"),o.length>0){const{key:t,value:r,accessor:n}=parseMockInstanceArgs(o);return mockInstanceConfig(e,t,r,n)}const t=ng_mocks_universe.A.configInstance.get(e)||{};ng_mocks_universe.A.configInstance.set(e,Object.assign(Object.assign({},t),{overloads:[]}));for(let o=checkReset.length-1;o>=0;o-=1)checkReset[o][0]===e&&checkReset[o][2]===currentStack&&checkReset.splice(o,1)}function MockReset(){ng_mocks_universe.A.configInstance.clear()}function MockDeclarations(...e){return e.map(MockDeclaration)}function MockDeclaration(e){if((0,func_is_ng_def.p)(e,"p"))return MockPipe(e);if((0,func_is_ng_def.p)(e,"c"))return MockComponent(e);if((0,func_is_ng_def.p)(e,"d"))return MockDirective(e);throw error_jest_mock(e),new Error(["MockDeclaration does not know how to mock","function"==typeof e?(0,func_get_name.A)(e):e].join(" "))}!function(e){e.remember=function(){ng_mocks_stack.stackPush()},e.restore=function(){ng_mocks_stack.stackPop()},e.scope=function(o="case"){"all"!==o&&"suite"!==o||(beforeAll(e.remember),afterAll(e.restore)),"all"!==o&&"case"!==o||(beforeEach(e.remember),afterEach(e.restore))}}(MockInstance||(MockInstance={}));const generateTemplateAttrWrap=(e,o)=>"i"===o?`[${e}]`:`(${e})`,generateTemplateAttrWithParams=(e,o)=>{let t=` ${generateTemplateAttrWrap(e,o)}="`;return t+="i"===o?e:`__ngMocksOutput('${e}', $event)`,t+='"',t},generateTemplateAttr=(e,o,t)=>{if(!e&&"o"===t)return"";let r="";const n=null!=e?e:o;for(const e of o){const{name:o,alias:s}=(0,func_directive_io_parse.A)(e);r+=-1===n.indexOf(s||o)?"":generateTemplateAttrWithParams(s||o,t)}return r},func_generate_template=(e,{selector:o,bindings:t,inputs:r,outputs:n})=>{let s="";return"string"==typeof e?s=e:(0,func_is_ng_def.p)(e,"p")&&t&&-1!==t.indexOf("$implicit")?s=`{{ $implicit | ${core_reflect_pipe_resolve(e).name} }}`:o&&(s+=`<${o}`,s+=generateTemplateAttr(t,r,"i"),s+=generateTemplateAttr(t,n,"o"),s+=`>`),s},generateWrapperOutput=e=>(o,t)=>"function"==typeof e[o]?e[o](t):e[o]&&"object"==typeof e[o]&&"function"==typeof e[o].emit?e[o].emit(t):e[o]&&"object"==typeof e[o]&&"function"==typeof e[o].next?e[o].next(t):void(e[o]=t),generateWrapperComponent=({bindings:e,options:o,inputs:t})=>{class r{constructor(){(0,core_define_property.A)(this,"__ngMocksOutput",generateWrapperOutput(this));let o=0;if((0,helper_define_property_descriptor.A)(this,"__ngContext__",{get:()=>o,set:e=>o=e,enumerable:!1}),!e)for(const e of t||[]){let o=null;(0,helper_define_property_descriptor.A)(this,e,{get:()=>o,set:e=>o=e})}}}return(0,core_define_property.A)(r.prototype,`__ngMocks_index_${ng_mocks_universe.A.index()}`,void 0,!1),(0,core_.Component)(o)(r),r},generateWrapperDirective=({selector:e,options:o})=>{class t{}return(0,core_.Directive)({selector:e,providers:o.providers})(t),t},getCache=()=>{var e;const o=null!==(e=ng_mocks_universe.A.config.get("MockRenderCaches"))&&void 0!==e?e:[];return 0===o.length&&ng_mocks_universe.A.config.set("MockRenderCaches",o),o},checkCache=(e,o)=>{for(const t of e){if(t.cacheKey.length!==o.length)continue;let e=!0;for(let r=0;r{var n,s,c;const _=getCache(),i=[e,...null!=t?t:[null],...null!==(n=r.providers)&&void 0!==n?n:[null],...null!==(s=r.viewProviders)&&void 0!==s?s:[null]];let a=checkCache(_,i);if(a)return a;const l=o.inputs?[...o.inputs]:[],p=o.outputs?[...o.outputs]:[];if(o.hostDirectives)for(const e of o.hostDirectives)"object"==typeof e&&e.directive&&(e.inputs&&l.push(...e.inputs),e.outputs&&p.push(...e.outputs));const u=func_generate_template(e,{selector:o.selector,inputs:l,outputs:p,bindings:t}),d={providers:r.providers,selector:"mock-render",template:u,viewProviders:r.viewProviders};if(a=generateWrapperComponent(Object.assign(Object.assign({},o),{bindings:t,options:d})),(0,core_define_property.A)(a,"cacheKey",i),(0,core_define_property.A)(a,"tpl",u),o.selector&&d.providers){const e=generateWrapperDirective(Object.assign(Object.assign({},o),{bindings:t,options:d}));(0,core_define_property.A)(a,"providers",e)}return _.unshift(a),_.splice(null!==(c=ng_mocks_universe.A.global.get("mockRenderCacheSize"))&&void 0!==c?c:core_config.A.mockRenderCacheSize),a},createPropertyGet=(e,o,t)=>{const r=()=>{if("function"==typeof t[e]){if(o[`__ngMocks_${e}__origin`]!==t[e]){const r=helper_mock_service.A.createClone(t[e],o,t);(0,core_define_property.A)(o,`__ngMocks_${e}`,r),(0,core_define_property.A)(o,`__ngMocks_${e}__origin`,t[e])}return o[`__ngMocks_${e}`]}return t[e]};return(0,core_define_property.A)(r,"__ngMocksProxy",!0),r},createPropertySet=(e,o,t)=>{const r=r=>{o[`__ngMocks_${e}`]&&(o[`__ngMocks_${e}`]=void 0),o[`__ngMocks_${e}__origin`]&&(o[`__ngMocks_${e}__origin`]=void 0),t[e]=r};return(0,core_define_property.A)(r,"__ngMocksProxy",!0),r},extractAllKeys=e=>[...helper_mock_service.A.extractPropertiesFromPrototype(Object.getPrototypeOf(e)),...helper_mock_service.A.extractMethodsFromPrototype(Object.getPrototypeOf(e)),...Object.keys(e)],extractOwnKeys=e=>[...Object.getOwnPropertyNames(e),...Object.keys(e)],func_install_prop_reader=(e,o,t,r=!1)=>{if(!o)return;(0,core_define_property.A)(e,"__ngMocks__source",o);const n=extractOwnKeys(e),s=[...extractAllKeys(o),...t];for(const t of s)(r||-1===n.indexOf(t))&&((0,helper_define_property_descriptor.A)(e,t,{get:createPropertyGet(t,e,o),set:createPropertySet(t,e,o)}),n.push(t))},registerTemplateMiddleware=(e,o)=>{const t=(0,core_helpers.He)(e),r={provide:e,useExisting:t};o.providers=[...o.providers||[],r];let n={};try{const t=testing_.TestBed.ngMocksOverrides,{override:s}=t.get(e);n=Object.assign({},s.set),n.providers=n.providers?[...n.providers,r]:o.providers}catch(e){}const s=!0===o.__ngMocksStandalone;((0,func_is_ng_def.p)(e,"c")?core_.Component:core_.Directive)(Object.assign(Object.assign(Object.assign({},o),n),s?{standalone:s}:{}))(t),testing_.TestBed.configureTestingModule({[s?"imports":"declarations"]:[t]})},func_reflect_template=e=>{var o;if(!(0,func_is_ng_def.p)(e,"c")&&!(0,func_is_ng_def.p)(e,"d"))return{};const t=core_reflect_directive_resolve(e),r={};for(const e of Object.keys(t))"standalone"!==e?r[e]=t[e]:(0,core_define_property.A)(r,"__ngMocksStandalone",!!t[e]);return r.selector&&/[\s,[\]]/.test(r.selector)&&(r.selector=""),r.selector||(r.selector=(null===(o=testing_.TestBed.ngMocksSelectors)||void 0===o?void 0:o.get(e))||"",r.selector||(r.selector=`ng-mocks-${e.name}`,registerTemplateMiddleware(e,r),testing_.TestBed.ngMocksSelectors&&testing_.TestBed.ngMocksSelectors.set(e,r.selector))),r},renderDeclaration=(e,o,t)=>{e.point=e.debugElement.children[0]&&"#text"!==e.debugElement.children[0].nativeElement.nodeName&&"#comment"!==e.debugElement.children[0].nativeElement.nodeName?e.debugElement.children[0]:e.debugElement,(0,func_is_ng_def.p)(o,"d")?(0,helper_define_property_descriptor.A)(e.point,"componentInstance",{get:()=>ngMocks.get(e.point,o)}):(0,func_is_ng_def.p)(o,"p")&&(0,helper_define_property_descriptor.A)(e.point,"componentInstance",{get:()=>ngMocks.findInstance(e.point,o)}),tryWhen(!t,(()=>func_install_prop_reader(e.componentInstance,e.point.componentInstance,[])))},renderInjection=(e,o,t)=>{let r;try{r=(0,core_helpers.Ah)(o)}catch(e){if((0,func_is_ng_def.p)(o,"p"))throw new Error([`Cannot render ${(0,func_get_name.A)(o)}.`,"Did you forget to set $implicit param, or add the pipe to providers?","https://ng-mocks.sudo.eu/guides/pipe"].join(" "));throw e}t&&ngMocks.stub(r,t),e.point=(0,mock_service.K)(core_.DebugElement,{childNodes:[],children:[],componentInstance:r,nativeElement:(0,mock_service.K)(HTMLElement)}),func_install_prop_reader(e.componentInstance,e.point.componentInstance,[],!0)},tryWhen=(e,o)=>{if(e)try{o()}catch(e){}},fixtureMessage=["Forgot to flush TestBed?","MockRender cannot be used without a reset after TestBed.get / TestBed.inject / TestBed.createComponent and another MockRender in the same test.","If you want to mock a service before rendering, consider usage of MockRenderFactory or MockInstance.","To flush TestBed, add a call of ngMocks.flushTestBed() before the call of MockRender, or pass `reset: true` to MockRender options."].join(" "),handleFixtureError=e=>{const o=new Error(fixtureMessage);throw(0,core_define_property.A)(o,"parent",e),o},flushTestBed=e=>{const o=ng_mocks_universe.A.global.get("flags"),t=(0,testing_.getTestBed)();e.reset||!t._instantiated&&!t._testModuleRef?ngMocks.flushTestBed():"throw"!==o.onTestBedFlushNeed&&(t._instantiated||t._testModuleRef)&&("warn"===o.onTestBedFlushNeed&&console.warn(fixtureMessage),ngMocks.flushTestBed())},generateFactoryInstall=(e,o)=>()=>{var t;const r=(0,testing_.getTestBed)(),n=(null===(t=r._compiler)||void 0===t?void 0:t.declarations)||r.declarations||r._declarations;if(!n||-1===n.indexOf(e)){flushTestBed(o);try{const o=[];e.providers&&o.push(e.providers),o.push(e),testing_.TestBed.configureTestingModule({declarations:o})}catch(e){handleFixtureError(e)}}},generateFactory=(e,o,t,r)=>{const n=(r,s)=>{n.configureTestBed();const c=testing_.TestBed.createComponent(e);return func_install_prop_reader(c.componentInstance,null!=r?r:{},null!=o?o:[]),(0,core_define_property.A)(c,"ngMocksStackId",ng_mocks_universe.A.global.get("bullet:stack:id")),(void 0===s||s)&&c.detectChanges(),"string"==typeof t||(0,func_is_ng_def.p)(t,"c")||(0,func_is_ng_def.p)(t,"d")||e.tpl&&(0,func_is_ng_def.p)(t,"p")?renderDeclaration(c,t,r):renderInjection(c,t,r),c};return n.declaration=e,n.bindings=o,n.configureTestBed=generateFactoryInstall(e,r),n};function MockRenderFactory(e,o,t={}){func_import_exists(e,"MockRender");const r="string"==typeof e||(0,func_is_ng_def.p)(e,"t")?{}:func_reflect_template(e),n=func_create_wrapper(e,r,o,t),s=generateFactory(n,o,e,t);return"root"!==ng_mocks_stack.current().level&&!1!==t.configureTestBed&&s.configureTestBed(),s}function MockRender(e,o,t=!0){const r=0===arguments.length?"":e,n=o&&"object"==typeof o?Object.keys(o):o,s="boolean"==typeof t?{detectChanges:t}:Object.assign({},t);return MockRenderFactory(r,n,s)(o,s.detectChanges)}var __webpack_exports__IMockBuilder=__webpack_exports__.rX,__webpack_exports__IMockBuilderConfig=__webpack_exports__.HA,__webpack_exports__IMockBuilderConfigAll=__webpack_exports__.Wn,__webpack_exports__IMockBuilderConfigComponent=__webpack_exports__.Me,__webpack_exports__IMockBuilderConfigDirective=__webpack_exports__.I7,__webpack_exports__IMockBuilderConfigModule=__webpack_exports__.tv,__webpack_exports__IMockBuilderExtended=__webpack_exports__.OG,__webpack_exports__IMockBuilderProvider=__webpack_exports__.sF,__webpack_exports__IMockBuilderResult=__webpack_exports__.me,__webpack_exports__LegacyControlValueAccessor=__webpack_exports__.bk,__webpack_exports__Mock=__webpack_exports__.JT,__webpack_exports__MockBuilder=__webpack_exports__._V,__webpack_exports__MockComponent=__webpack_exports__.Am,__webpack_exports__MockComponents=__webpack_exports__.$u,__webpack_exports__MockControlValueAccessor=__webpack_exports__.D2,__webpack_exports__MockDeclaration=__webpack_exports__.dw,__webpack_exports__MockDeclarations=__webpack_exports__.uV,__webpack_exports__MockDirective=__webpack_exports__.Cc,__webpack_exports__MockDirectives=__webpack_exports__.nr,__webpack_exports__MockInstance=__webpack_exports__.Wm,__webpack_exports__MockModule=__webpack_exports__.BN,__webpack_exports__MockPipe=__webpack_exports__.ZJ,__webpack_exports__MockPipes=__webpack_exports__.yI,__webpack_exports__MockProvider=__webpack_exports__.Qo,__webpack_exports__MockProviders=__webpack_exports__.dD,__webpack_exports__MockRender=__webpack_exports__.Ty,__webpack_exports__MockRenderFactory=__webpack_exports__.P0,__webpack_exports__MockReset=__webpack_exports__.mB,__webpack_exports__MockService=__webpack_exports__.KH,__webpack_exports__MockValidator=__webpack_exports__.b6,__webpack_exports__MockedComponent=__webpack_exports__.Je,__webpack_exports__MockedDirective=__webpack_exports__.T4,__webpack_exports__MockedModule=__webpack_exports__.qZ,__webpack_exports__MockedPipe=__webpack_exports__.cm,__webpack_exports__NG_MOCKS=__webpack_exports__.en,__webpack_exports__NG_MOCKS_GUARDS=__webpack_exports__.ZG,__webpack_exports__NG_MOCKS_INTERCEPTORS=__webpack_exports__.rO,__webpack_exports__NG_MOCKS_OVERRIDES=__webpack_exports__.So,__webpack_exports__NG_MOCKS_RESOLVERS=__webpack_exports__.C3,__webpack_exports__NG_MOCKS_ROOT_PROVIDERS=__webpack_exports__.gG,__webpack_exports__NG_MOCKS_TOUCHES=__webpack_exports__.Em,__webpack_exports__getInjection=__webpack_exports__.Ah,__webpack_exports__getMockedNgDefOf=__webpack_exports__.xz,__webpack_exports__getSourceOfMock=__webpack_exports__.VK,__webpack_exports__getTestBedInjection=__webpack_exports__.d5,__webpack_exports__isMockControlValueAccessor=__webpack_exports__.IA,__webpack_exports__isMockNgDef=__webpack_exports__.Bt,__webpack_exports__isMockOf=__webpack_exports__.AW,__webpack_exports__isMockValidator=__webpack_exports__.lt,__webpack_exports__isMockedNgDefOf=__webpack_exports__.Fk,__webpack_exports__isNgDef=__webpack_exports__.pA,__webpack_exports__isNgInjectionToken=__webpack_exports__.SM,__webpack_exports__ngMocks=__webpack_exports__.H5;export{__webpack_exports__IMockBuilder as IMockBuilder,__webpack_exports__IMockBuilderConfig as IMockBuilderConfig,__webpack_exports__IMockBuilderConfigAll as IMockBuilderConfigAll,__webpack_exports__IMockBuilderConfigComponent as IMockBuilderConfigComponent,__webpack_exports__IMockBuilderConfigDirective as IMockBuilderConfigDirective,__webpack_exports__IMockBuilderConfigModule as IMockBuilderConfigModule,__webpack_exports__IMockBuilderExtended as IMockBuilderExtended,__webpack_exports__IMockBuilderProvider as IMockBuilderProvider,__webpack_exports__IMockBuilderResult as IMockBuilderResult,__webpack_exports__LegacyControlValueAccessor as LegacyControlValueAccessor,__webpack_exports__Mock as Mock,__webpack_exports__MockBuilder as MockBuilder,__webpack_exports__MockComponent as MockComponent,__webpack_exports__MockComponents as MockComponents,__webpack_exports__MockControlValueAccessor as MockControlValueAccessor,__webpack_exports__MockDeclaration as MockDeclaration,__webpack_exports__MockDeclarations as MockDeclarations,__webpack_exports__MockDirective as MockDirective,__webpack_exports__MockDirectives as MockDirectives,__webpack_exports__MockInstance as MockInstance,__webpack_exports__MockModule as MockModule,__webpack_exports__MockPipe as MockPipe,__webpack_exports__MockPipes as MockPipes,__webpack_exports__MockProvider as MockProvider,__webpack_exports__MockProviders as MockProviders,__webpack_exports__MockRender as MockRender,__webpack_exports__MockRenderFactory as MockRenderFactory,__webpack_exports__MockReset as MockReset,__webpack_exports__MockService as MockService,__webpack_exports__MockValidator as MockValidator,__webpack_exports__MockedComponent as MockedComponent,__webpack_exports__MockedDirective as MockedDirective,__webpack_exports__MockedModule as MockedModule,__webpack_exports__MockedPipe as MockedPipe,__webpack_exports__NG_MOCKS as NG_MOCKS,__webpack_exports__NG_MOCKS_GUARDS as NG_MOCKS_GUARDS,__webpack_exports__NG_MOCKS_INTERCEPTORS as NG_MOCKS_INTERCEPTORS,__webpack_exports__NG_MOCKS_OVERRIDES as NG_MOCKS_OVERRIDES,__webpack_exports__NG_MOCKS_RESOLVERS as NG_MOCKS_RESOLVERS,__webpack_exports__NG_MOCKS_ROOT_PROVIDERS as NG_MOCKS_ROOT_PROVIDERS,__webpack_exports__NG_MOCKS_TOUCHES as NG_MOCKS_TOUCHES,__webpack_exports__getInjection as getInjection,__webpack_exports__getMockedNgDefOf as getMockedNgDefOf,__webpack_exports__getSourceOfMock as getSourceOfMock,__webpack_exports__getTestBedInjection as getTestBedInjection,__webpack_exports__isMockControlValueAccessor as isMockControlValueAccessor,__webpack_exports__isMockNgDef as isMockNgDef,__webpack_exports__isMockOf as isMockOf,__webpack_exports__isMockValidator as isMockValidator,__webpack_exports__isMockedNgDefOf as isMockedNgDefOf,__webpack_exports__isNgDef as isNgDef,__webpack_exports__isNgInjectionToken as isNgInjectionToken,__webpack_exports__ngMocks as ngMocks}; + //# sourceMappingURL=index.mjs.map diff --git a/proxy.conf.mjs b/proxy.conf.mjs index 9a1ecebc4a3d..53e4497d75ea 100644 --- a/proxy.conf.mjs +++ b/proxy.conf.mjs @@ -2,22 +2,23 @@ export default [ { context: [ - "/api", - "/services", - "/management", - "/swagger-resources", - "/v3/api-docs", - "/h2-console", - "/auth", - "/health", - "/public", - "/.well-known" + "/api/", + "/services/", + "/management/", + "^/management$", + "/swagger-resources/", + "/v3/api-docs/", + "/h2-console/", + "/auth/", + "/health/", + "/public/", + "/.well-known/" ], target: `http://localhost:8080`, secure: false }, { - context: ["/websocket"], + context: ["/websocket/"], target: "ws://127.0.0.1:8080", ws: true } diff --git a/src/main/webapp/app/account/activate/activate.component.ts b/src/main/webapp/app/account/activate/activate.component.ts index a05a908b695d..10ec25c6ad93 100644 --- a/src/main/webapp/app/account/activate/activate.component.ts +++ b/src/main/webapp/app/account/activate/activate.component.ts @@ -9,7 +9,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-activate', templateUrl: './activate.component.html', - standalone: true, imports: [TranslateDirective, RouterLink, ArtemisSharedModule], }) export class ActivateComponent implements OnInit { diff --git a/src/main/webapp/app/account/password-reset/external/external-user-password-reset-modal.component.ts b/src/main/webapp/app/account/password-reset/external/external-user-password-reset-modal.component.ts index d122291f564d..3b5dd7ed9c7c 100644 --- a/src/main/webapp/app/account/password-reset/external/external-user-password-reset-modal.component.ts +++ b/src/main/webapp/app/account/password-reset/external/external-user-password-reset-modal.component.ts @@ -6,7 +6,6 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; @Component({ selector: 'jhi-external-user-password-reset-modal', templateUrl: './external-user-password-reset-modal.component.html', - standalone: true, imports: [TranslateDirective, ArtemisSharedModule], }) export class ExternalUserPasswordResetModalComponent { diff --git a/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.ts b/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.ts index 35cbb5f0483c..a5aeac5c6e03 100644 --- a/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.ts +++ b/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.ts @@ -11,7 +11,6 @@ import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; @Component({ selector: 'jhi-password-reset-finish', templateUrl: './password-reset-finish.component.html', - standalone: true, imports: [TranslateDirective, RouterLink, FormsModule, ReactiveFormsModule, PasswordStrengthBarComponent, ArtemisSharedCommonModule, ArtemisSharedModule], }) export class PasswordResetFinishComponent implements OnInit, AfterViewInit { diff --git a/src/main/webapp/app/account/password-reset/init/password-reset-init.component.ts b/src/main/webapp/app/account/password-reset/init/password-reset-init.component.ts index 3e245c20e2b6..5823df8e2f4e 100644 --- a/src/main/webapp/app/account/password-reset/init/password-reset-init.component.ts +++ b/src/main/webapp/app/account/password-reset/init/password-reset-init.component.ts @@ -15,7 +15,6 @@ import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; @Component({ selector: 'jhi-password-reset-init', templateUrl: './password-reset-init.component.html', - standalone: true, imports: [TranslateDirective, FormsModule, ArtemisSharedCommonModule, ArtemisSharedModule], }) export class PasswordResetInitComponent implements OnInit, AfterViewInit { diff --git a/src/main/webapp/app/account/password/password-strength-bar.component.ts b/src/main/webapp/app/account/password/password-strength-bar.component.ts index d09537aedab9..c3ae5cf17397 100644 --- a/src/main/webapp/app/account/password/password-strength-bar.component.ts +++ b/src/main/webapp/app/account/password/password-strength-bar.component.ts @@ -15,7 +15,6 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; `, styleUrls: ['password-strength-bar.scss'], - standalone: true, imports: [TranslateDirective, ArtemisSharedModule], }) export class PasswordStrengthBarComponent { diff --git a/src/main/webapp/app/account/password/password.component.ts b/src/main/webapp/app/account/password/password.component.ts index b2a600dd97bb..4b614de2e14a 100644 --- a/src/main/webapp/app/account/password/password.component.ts +++ b/src/main/webapp/app/account/password/password.component.ts @@ -12,7 +12,6 @@ import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; @Component({ selector: 'jhi-password', templateUrl: './password.component.html', - standalone: true, imports: [TranslateDirective, FormsModule, ReactiveFormsModule, PasswordStrengthBarComponent, ArtemisSharedCommonModule, ArtemisSharedModule], }) export class PasswordComponent implements OnInit { diff --git a/src/main/webapp/app/account/register/register.component.ts b/src/main/webapp/app/account/register/register.component.ts index 15ea460bfb73..a63fa4ba3901 100644 --- a/src/main/webapp/app/account/register/register.component.ts +++ b/src/main/webapp/app/account/register/register.component.ts @@ -15,7 +15,6 @@ import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; @Component({ selector: 'jhi-register', templateUrl: './register.component.html', - standalone: true, imports: [TranslateDirective, FormsModule, ReactiveFormsModule, PasswordStrengthBarComponent, ArtemisSharedCommonModule, ArtemisSharedModule], }) export class RegisterComponent implements OnInit, AfterViewInit { diff --git a/src/main/webapp/app/account/settings/settings.component.ts b/src/main/webapp/app/account/settings/settings.component.ts index 75e9187aa1bf..a6d8c02835b8 100644 --- a/src/main/webapp/app/account/settings/settings.component.ts +++ b/src/main/webapp/app/account/settings/settings.component.ts @@ -12,7 +12,6 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; @Component({ selector: 'jhi-settings', templateUrl: './settings.component.html', - standalone: true, imports: [TranslateDirective, FormsModule, ReactiveFormsModule, ArtemisSharedCommonModule, ArtemisSharedModule], }) export class SettingsComponent implements OnInit { diff --git a/src/main/webapp/app/admin/admin.module.ts b/src/main/webapp/app/admin/admin.module.ts index 0a236665c96d..c3dff04c1312 100644 --- a/src/main/webapp/app/admin/admin.module.ts +++ b/src/main/webapp/app/admin/admin.module.ts @@ -1,5 +1,6 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; +import { ArtemisFormsModule } from 'app/forms/artemis-forms.module'; import { adminState } from './admin.route'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { FormDateTimePickerModule } from 'app/shared/date-time-picker/date-time-picker.module'; @@ -56,6 +57,7 @@ const ENTITY_STATES = [...adminState]; RouterModule.forChild(ENTITY_STATES), ArtemisSharedModule, FormDateTimePickerModule, + ArtemisFormsModule, NgxDatatableModule, ArtemisDataTableModule, ArtemisChartsModule, @@ -78,8 +80,6 @@ const ENTITY_STATES = [...adminState]; AdminImportStandardizedCompetenciesComponent, BuildAgentSummaryComponent, BuildAgentDetailsComponent, - ], - declarations: [ AuditsComponent, UserManagementComponent, UserManagementDetailComponent, diff --git a/src/main/webapp/app/admin/admin.route.ts b/src/main/webapp/app/admin/admin.route.ts index 992b20b48c2b..10b4e283d310 100644 --- a/src/main/webapp/app/admin/admin.route.ts +++ b/src/main/webapp/app/admin/admin.route.ts @@ -4,23 +4,12 @@ import { userManagementRoute } from 'app/admin/user-management/user-management.r import { systemNotificationManagementRoute } from 'app/admin/system-notification-management/system-notification-management.route'; import { Authority } from 'app/shared/constants/authority.constants'; import { upcomingExamsAndExercisesRoute } from 'app/admin/upcoming-exams-and-exercises/upcoming-exams-and-exercises.route'; -import { AuditsComponent } from 'app/admin/audits/audits.component'; -import { ConfigurationComponent } from 'app/admin/configuration/configuration.component'; -import { AdminFeatureToggleComponent } from 'app/admin/features/admin-feature-toggle.component'; -import { HealthComponent } from 'app/admin/health/health.component'; -import { LogsComponent } from 'app/admin/logs/logs.component'; -import { StatisticsComponent } from 'app/admin/statistics/statistics.component'; -import { DocsComponent } from 'app/admin/docs/docs.component'; + import { organizationMgmtRoute } from 'app/admin/organization-management/organization-management.route'; -import { MetricsComponent } from 'app/admin/metrics/metrics.component'; -import { BuildQueueComponent } from 'app/localci/build-queue/build-queue.component'; + import { LocalCIGuard } from 'app/localci/localci-guard.service'; import { ltiConfigurationRoute } from 'app/admin/lti-configuration/lti-configuration.route'; -import { BuildAgentSummaryComponent } from 'app/localci/build-agents/build-agent-summary/build-agent-summary.component'; -import { StandardizedCompetencyManagementComponent } from 'app/admin/standardized-competencies/standardized-competency-management.component'; -import { BuildAgentDetailsComponent } from 'app/localci/build-agents/build-agent-details/build-agent-details/build-agent-details.component'; -import { AdminImportStandardizedCompetenciesComponent } from 'app/admin/standardized-competencies/import/admin-import-standardized-competencies.component'; -import { CleanupServiceComponent } from 'app/admin/cleanup-service/cleanup-service.component'; + import { PendingChangesGuard } from 'app/shared/guard/pending-changes.guard'; export const adminState: Routes = [ @@ -33,7 +22,7 @@ export const adminState: Routes = [ children: [ { path: 'audits', - component: AuditsComponent, + loadComponent: () => import('app/admin/audits/audits.component').then((m) => m.AuditsComponent), data: { pageTitle: 'audits.title', defaultSort: 'auditEventDate,desc', @@ -41,56 +30,56 @@ export const adminState: Routes = [ }, { path: 'configuration', - component: ConfigurationComponent, + loadComponent: () => import('app/admin/configuration/configuration.component').then((m) => m.ConfigurationComponent), data: { pageTitle: 'configuration.title', }, }, { path: 'feature-toggles', - component: AdminFeatureToggleComponent, + loadComponent: () => import('app/admin/features/admin-feature-toggle.component').then((m) => m.AdminFeatureToggleComponent), data: { pageTitle: 'featureToggles.title', }, }, { path: 'health', - component: HealthComponent, + loadComponent: () => import('app/admin/health/health.component').then((m) => m.HealthComponent), data: { pageTitle: 'health.title', }, }, { path: 'logs', - component: LogsComponent, + loadComponent: () => import('app/admin/logs/logs.component').then((m) => m.LogsComponent), data: { pageTitle: 'logs.title', }, }, { path: 'docs', - component: DocsComponent, + loadComponent: () => import('app/admin/docs/docs.component').then((m) => m.DocsComponent), data: { pageTitle: 'global.menu.admin.apidocs', }, }, { path: 'metrics', - component: MetricsComponent, + loadComponent: () => import('app/admin/metrics/metrics.component').then((m) => m.MetricsComponent), data: { pageTitle: 'metrics.title', }, }, { path: 'user-statistics', - component: StatisticsComponent, + loadComponent: () => import('app/admin/statistics/statistics.component').then((m) => m.StatisticsComponent), data: { pageTitle: 'statistics.title', }, }, { path: 'build-queue', - component: BuildQueueComponent, + loadComponent: () => import('app/localci/build-queue/build-queue.component').then((m) => m.BuildQueueComponent), data: { pageTitle: 'artemisApp.buildQueue.title', }, @@ -98,7 +87,7 @@ export const adminState: Routes = [ }, { path: 'build-agents', - component: BuildAgentSummaryComponent, + loadComponent: () => import('app/localci/build-agents/build-agent-summary/build-agent-summary.component').then((m) => m.BuildAgentSummaryComponent), data: { pageTitle: 'artemisApp.buildAgents.title', }, @@ -106,7 +95,8 @@ export const adminState: Routes = [ }, { path: 'build-agents/details', - component: BuildAgentDetailsComponent, + loadComponent: () => + import('app/localci/build-agents/build-agent-details/build-agent-details/build-agent-details.component').then((m) => m.BuildAgentDetailsComponent), data: { pageTitle: 'artemisApp.buildAgents.title', }, @@ -114,7 +104,8 @@ export const adminState: Routes = [ }, { path: 'standardized-competencies', - component: StandardizedCompetencyManagementComponent, + loadComponent: () => + import('app/admin/standardized-competencies/standardized-competency-management.component').then((m) => m.StandardizedCompetencyManagementComponent), data: { pageTitle: 'artemisApp.standardizedCompetency.title', }, @@ -129,7 +120,10 @@ export const adminState: Routes = [ children: [ { path: 'import', - component: AdminImportStandardizedCompetenciesComponent, + loadComponent: () => + import('app/admin/standardized-competencies/import/admin-import-standardized-competencies.component').then( + (m) => m.AdminImportStandardizedCompetenciesComponent, + ), data: { pageTitle: 'artemisApp.standardizedCompetency.import.title', }, @@ -153,7 +147,7 @@ export const adminState: Routes = [ }, { path: 'cleanup-service', - component: CleanupServiceComponent, + loadComponent: () => import('app/admin/cleanup-service/cleanup-service.component').then((m) => m.CleanupServiceComponent), data: { pageTitle: 'cleanupService.title', }, diff --git a/src/main/webapp/app/admin/audits/audits.component.ts b/src/main/webapp/app/admin/audits/audits.component.ts index 7f98a7fbe09f..9422cfc0176a 100644 --- a/src/main/webapp/app/admin/audits/audits.component.ts +++ b/src/main/webapp/app/admin/audits/audits.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { HttpHeaders, HttpResponse } from '@angular/common/http'; import { DatePipe } from '@angular/common'; import { ActivatedRoute, Router } from '@angular/router'; @@ -8,12 +8,26 @@ import { ITEMS_PER_PAGE } from 'app/shared/constants/pagination.constants'; import { Audit } from './audit.model'; import { AuditsService } from './audits.service'; import { faSort } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ItemCountComponent } from 'app/shared/pagination/item-count.component'; +import { NgbPagination } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; @Component({ selector: 'jhi-audit', templateUrl: './audits.component.html', + imports: [TranslateDirective, FormsModule, SortDirective, SortByDirective, FaIconComponent, ItemCountComponent, NgbPagination, ArtemisDatePipe], }) export class AuditsComponent implements OnInit { + private auditsService = inject(AuditsService); + private activatedRoute = inject(ActivatedRoute); + private datePipe = inject(DatePipe); + private router = inject(Router); + audits?: Audit[]; fromDate = ''; predicate!: string; @@ -31,13 +45,6 @@ export class AuditsComponent implements OnInit { // Icon faSort = faSort; - constructor( - private auditsService: AuditsService, - private activatedRoute: ActivatedRoute, - private datePipe: DatePipe, - private router: Router, - ) {} - ngOnInit(): void { this.toDate = this.today(); this.fromDate = this.previousMonth(); diff --git a/src/main/webapp/app/admin/audits/audits.service.ts b/src/main/webapp/app/admin/audits/audits.service.ts index cfefe048cf85..e72793f459e4 100644 --- a/src/main/webapp/app/admin/audits/audits.service.ts +++ b/src/main/webapp/app/admin/audits/audits.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { createRequestOption } from 'app/shared/util/request.util'; @@ -6,7 +6,7 @@ import { Audit } from 'app/admin/audits/audit.model'; @Injectable({ providedIn: 'root' }) export class AuditsService { - constructor(private http: HttpClient) {} + private http = inject(HttpClient); query(req: any): Observable> { const params: HttpParams = createRequestOption(req); diff --git a/src/main/webapp/app/admin/cleanup-service/cleanup-operation-modal.component.ts b/src/main/webapp/app/admin/cleanup-service/cleanup-operation-modal.component.ts index be398b021798..34d948f59464 100644 --- a/src/main/webapp/app/admin/cleanup-service/cleanup-operation-modal.component.ts +++ b/src/main/webapp/app/admin/cleanup-service/cleanup-operation-modal.component.ts @@ -11,7 +11,6 @@ import { faCheckCircle, faTimes } from '@fortawesome/free-solid-svg-icons'; @Component({ selector: 'jhi-cleanup-operation-modal', templateUrl: './cleanup-operation-modal.component.html', - standalone: true, imports: [TranslateDirective, ArtemisSharedModule], }) export class CleanupOperationModalComponent implements OnInit { diff --git a/src/main/webapp/app/admin/cleanup-service/cleanup-service.component.ts b/src/main/webapp/app/admin/cleanup-service/cleanup-service.component.ts index 00a6965915d5..5a8d663607e6 100644 --- a/src/main/webapp/app/admin/cleanup-service/cleanup-service.component.ts +++ b/src/main/webapp/app/admin/cleanup-service/cleanup-service.component.ts @@ -14,7 +14,6 @@ import { CleanupOperationModalComponent } from 'app/admin/cleanup-service/cleanu @Component({ selector: 'jhi-cleanup-service', templateUrl: './cleanup-service.component.html', - standalone: true, imports: [FormDateTimePickerModule, ArtemisSharedModule, ArtemisSharedComponentModule], }) export class CleanupServiceComponent implements OnInit { diff --git a/src/main/webapp/app/admin/configuration/configuration.component.ts b/src/main/webapp/app/admin/configuration/configuration.component.ts index 9888e69646ac..6beb882fab6d 100644 --- a/src/main/webapp/app/admin/configuration/configuration.component.ts +++ b/src/main/webapp/app/admin/configuration/configuration.component.ts @@ -1,14 +1,23 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ConfigurationService } from './configuration.service'; import { Bean, PropertySource } from './configuration.model'; import { faSort } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { JsonPipe, KeyValuePipe } from '@angular/common'; @Component({ selector: 'jhi-configuration', templateUrl: './configuration.component.html', + imports: [TranslateDirective, FormsModule, SortDirective, SortByDirective, FaIconComponent, JsonPipe, KeyValuePipe], }) export class ConfigurationComponent implements OnInit { + private configurationService = inject(ConfigurationService); + allBeans!: Bean[]; beans: Bean[] = []; beansFilter = ''; @@ -18,8 +27,6 @@ export class ConfigurationComponent implements OnInit { // Icons faSort = faSort; - constructor(private configurationService: ConfigurationService) {} - ngOnInit(): void { this.configurationService.getBeans().subscribe((beans) => { this.allBeans = beans; diff --git a/src/main/webapp/app/admin/configuration/configuration.service.ts b/src/main/webapp/app/admin/configuration/configuration.service.ts index 8705370fbf44..7863392edd10 100644 --- a/src/main/webapp/app/admin/configuration/configuration.service.ts +++ b/src/main/webapp/app/admin/configuration/configuration.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -7,7 +7,7 @@ import { Bean, Beans, ConfigProps, Env, PropertySource } from './configuration.m @Injectable({ providedIn: 'root' }) export class ConfigurationService { - constructor(private http: HttpClient) {} + private http = inject(HttpClient); getBeans(): Observable { return this.http.get('management/configprops').pipe( diff --git a/src/main/webapp/app/admin/features/admin-feature-toggle.component.ts b/src/main/webapp/app/admin/features/admin-feature-toggle.component.ts index 185801509cc9..998b8f4aec19 100644 --- a/src/main/webapp/app/admin/features/admin-feature-toggle.component.ts +++ b/src/main/webapp/app/admin/features/admin-feature-toggle.component.ts @@ -1,6 +1,7 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { FeatureToggle, FeatureToggleService } from 'app/shared/feature-toggle/feature-toggle.service'; import { tap } from 'rxjs/operators'; +import { NgxDatatableModule } from '@siemens/ngx-datatable'; type FeatureToggleState = { index: number; @@ -24,11 +25,12 @@ type FeatureToggleState = { `, + imports: [NgxDatatableModule], }) export class AdminFeatureToggleComponent implements OnInit { - public availableToggles: FeatureToggleState[] = []; + private featureToggleService = inject(FeatureToggleService); - constructor(private featureToggleService: FeatureToggleService) {} + public availableToggles: FeatureToggleState[] = []; ngOnInit(): void { this.featureToggleService diff --git a/src/main/webapp/app/admin/health/health-modal.component.ts b/src/main/webapp/app/admin/health/health-modal.component.ts index 37efaebe3c34..62b69c7e82f2 100644 --- a/src/main/webapp/app/admin/health/health-modal.component.ts +++ b/src/main/webapp/app/admin/health/health-modal.component.ts @@ -1,15 +1,19 @@ -import { Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { HealthDetails, HealthKey } from 'app/admin/health/health.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { KeyValuePipe } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-health-modal', templateUrl: './health-modal.component.html', + imports: [TranslateDirective, KeyValuePipe, ArtemisTranslatePipe], }) export class HealthModalComponent { - health?: { key: HealthKey; value: HealthDetails }; + private activeModal = inject(NgbActiveModal); - constructor(private activeModal: NgbActiveModal) {} + health?: { key: HealthKey; value: HealthDetails }; readableValue(value: any): string { if (this.health?.key === 'diskSpace') { diff --git a/src/main/webapp/app/admin/health/health.component.ts b/src/main/webapp/app/admin/health/health.component.ts index d07c215f787a..f2e3eba43a7a 100644 --- a/src/main/webapp/app/admin/health/health.component.ts +++ b/src/main/webapp/app/admin/health/health.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { HttpErrorResponse } from '@angular/common/http'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; @@ -6,23 +6,27 @@ import { HealthService } from './health.service'; import { HealthModalComponent } from './health-modal.component'; import { Health, HealthDetails, HealthStatus } from 'app/admin/health/health.model'; import { faEye, faSync } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { KeyValuePipe, NgClass } from '@angular/common'; +import { JhiConnectionStatusComponent } from 'app/shared/connection-status/connection-status.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-health', templateUrl: './health.component.html', + imports: [TranslateDirective, FaIconComponent, NgClass, JhiConnectionStatusComponent, KeyValuePipe, ArtemisTranslatePipe], }) export class HealthComponent implements OnInit { + private modalService = inject(NgbModal); + private healthService = inject(HealthService); + health?: Health; // Icons faSync = faSync; faEye = faEye; - constructor( - private modalService: NgbModal, - private healthService: HealthService, - ) {} - ngOnInit() { this.refresh(); } diff --git a/src/main/webapp/app/admin/health/health.service.ts b/src/main/webapp/app/admin/health/health.service.ts index b89c85e3d215..d76710012e46 100644 --- a/src/main/webapp/app/admin/health/health.service.ts +++ b/src/main/webapp/app/admin/health/health.service.ts @@ -1,16 +1,13 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; +import { Health } from 'app/admin/health/health.model'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class HealthService { - separator: string; + private http = inject(HttpClient); - constructor(private http: HttpClient) { - this.separator = '.'; - } - - checkHealth(): Observable { - return this.http.get('management/health'); + checkHealth(): Observable { + return this.http.get('management/health'); } } diff --git a/src/main/webapp/app/admin/legal/legal-document-update-routing.module.ts b/src/main/webapp/app/admin/legal/legal-document-update-routing.module.ts index 3eca238a3e17..5facd71ddbb9 100644 --- a/src/main/webapp/app/admin/legal/legal-document-update-routing.module.ts +++ b/src/main/webapp/app/admin/legal/legal-document-update-routing.module.ts @@ -1,13 +1,12 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { LegalDocumentUpdateComponent } from 'app/admin/legal/legal-document-update.component'; import { Authority } from 'app/shared/constants/authority.constants'; const routes: Routes = [ { path: '', - component: LegalDocumentUpdateComponent, + loadComponent: () => import('app/admin/legal/legal-document-update.component').then((m) => m.LegalDocumentUpdateComponent), data: { authorities: [Authority.ADMIN], }, diff --git a/src/main/webapp/app/admin/legal/legal-document-update.component.ts b/src/main/webapp/app/admin/legal/legal-document-update.component.ts index 63541a0c97dc..53a56df95509 100644 --- a/src/main/webapp/app/admin/legal/legal-document-update.component.ts +++ b/src/main/webapp/app/admin/legal/legal-document-update.component.ts @@ -1,20 +1,31 @@ -import { AfterContentChecked, ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core'; +import { AfterContentChecked, ChangeDetectorRef, Component, OnInit, ViewChild, inject } from '@angular/core'; import { faBan, faCheckCircle, faCircleNotch, faExclamationTriangle, faSave } from '@fortawesome/free-solid-svg-icons'; import { LegalDocumentService } from 'app/shared/service/legal-document.service'; -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbModalRef, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { UnsavedChangesWarningComponent } from 'app/admin/legal/unsaved-changes-warning/unsaved-changes-warning.component'; import { LegalDocument, LegalDocumentLanguage, LegalDocumentType } from 'app/entities/legal-document.model'; import { ActivatedRoute } from '@angular/router'; import { Observable, tap } from 'rxjs'; import { JhiLanguageHelper } from 'app/core/language/language.helper'; import { MarkdownEditorHeight, MarkdownEditorMonacoComponent } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ModePickerComponent } from 'app/exercises/shared/mode-picker/mode-picker.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-privacy-statement-update-component', styleUrls: ['./legal-document-update.component.scss'], templateUrl: './legal-document-update.component.html', + imports: [TranslateDirective, MarkdownEditorMonacoComponent, FaIconComponent, NgbTooltip, ModePickerComponent, ArtemisTranslatePipe], }) export class LegalDocumentUpdateComponent implements OnInit, AfterContentChecked { + private legalDocumentService = inject(LegalDocumentService); + private modalService = inject(NgbModal); + private route = inject(ActivatedRoute); + private languageHelper = inject(JhiLanguageHelper); + private changeDetectorRef = inject(ChangeDetectorRef); + readonly SUPPORTED_LANGUAGES: LegalDocumentLanguage[] = [LegalDocumentLanguage.GERMAN, LegalDocumentLanguage.ENGLISH]; readonly faBan = faBan; readonly faSave = faSave; @@ -41,14 +52,6 @@ export class LegalDocumentUpdateComponent implements OnInit, AfterContentChecked unsavedChangesWarning: NgbModalRef; titleKey: string; - constructor( - private legalDocumentService: LegalDocumentService, - private modalService: NgbModal, - private route: ActivatedRoute, - private languageHelper: JhiLanguageHelper, - private changeDetectorRef: ChangeDetectorRef, - ) {} - ngOnInit() { // Tap the URL to determine, if it's the imprint or the privacy statement // we need the parent URL, because the imprint and privacy statement are children of the admin component and their path is specified there because they are lazy loaded diff --git a/src/main/webapp/app/admin/legal/legal-update.module.ts b/src/main/webapp/app/admin/legal/legal-update.module.ts index 26660839ca8a..460998bbfff6 100644 --- a/src/main/webapp/app/admin/legal/legal-update.module.ts +++ b/src/main/webapp/app/admin/legal/legal-update.module.ts @@ -16,7 +16,7 @@ import { LegalDocumentUnsavedChangesWarningModule } from 'app/admin/legal/unsave ArtemisMarkdownEditorModule, ArtemisModePickerModule, LegalDocumentUnsavedChangesWarningModule, + LegalDocumentUpdateComponent, ], - declarations: [LegalDocumentUpdateComponent], }) export class LegalUpdateModule {} diff --git a/src/main/webapp/app/admin/legal/unsaved-changes-warning/legal-document-unsaved-changes-warning.module.ts b/src/main/webapp/app/admin/legal/unsaved-changes-warning/legal-document-unsaved-changes-warning.module.ts index 23d07213db6d..4bddb4e7a740 100644 --- a/src/main/webapp/app/admin/legal/unsaved-changes-warning/legal-document-unsaved-changes-warning.module.ts +++ b/src/main/webapp/app/admin/legal/unsaved-changes-warning/legal-document-unsaved-changes-warning.module.ts @@ -4,7 +4,6 @@ import { ArtemisSharedComponentModule } from 'app/shared/components/shared-compo import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; @NgModule({ - imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule], - declarations: [UnsavedChangesWarningComponent], + imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule, UnsavedChangesWarningComponent], }) export class LegalDocumentUnsavedChangesWarningModule {} diff --git a/src/main/webapp/app/admin/legal/unsaved-changes-warning/unsaved-changes-warning.component.ts b/src/main/webapp/app/admin/legal/unsaved-changes-warning/unsaved-changes-warning.component.ts index 3314f37adf15..70f31dd4b621 100644 --- a/src/main/webapp/app/admin/legal/unsaved-changes-warning/unsaved-changes-warning.component.ts +++ b/src/main/webapp/app/admin/legal/unsaved-changes-warning/unsaved-changes-warning.component.ts @@ -1,16 +1,20 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ButtonComponent } from 'app/shared/components/button.component'; @Component({ selector: 'jhi-unsaved-changes-warning', templateUrl: './unsaved-changes-warning.component.html', + imports: [FormsModule, TranslateDirective, ButtonComponent], }) export class UnsavedChangesWarningComponent { + private activeModal = inject(NgbActiveModal); + @Input() textMessage: string; - constructor(private activeModal: NgbActiveModal) {} - /** * Closes the modal in which the warning is shown and discards the changes * diff --git a/src/main/webapp/app/admin/logs/logs.component.ts b/src/main/webapp/app/admin/logs/logs.component.ts index 8f24d4fed3fa..17862729e58c 100644 --- a/src/main/webapp/app/admin/logs/logs.component.ts +++ b/src/main/webapp/app/admin/logs/logs.component.ts @@ -1,14 +1,23 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { faSort } from '@fortawesome/free-solid-svg-icons'; import { Level, Log, LoggersResponse } from 'app/admin/logs/log.model'; import { LogsService } from 'app/admin/logs/logs.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgClass, SlicePipe } from '@angular/common'; @Component({ selector: 'jhi-logs', templateUrl: './logs.component.html', styleUrls: ['./logs.component.scss'], + imports: [TranslateDirective, FormsModule, SortDirective, SortByDirective, FaIconComponent, NgClass, SlicePipe], }) export class LogsComponent implements OnInit { + private logsService = inject(LogsService); + loggers?: Log[]; filteredAndOrderedLoggers?: Log[]; filter = ''; @@ -18,8 +27,6 @@ export class LogsComponent implements OnInit { // Icons faSort = faSort; - constructor(private logsService: LogsService) {} - /** * Subscribe to the logsService to retrieve all logs */ diff --git a/src/main/webapp/app/admin/logs/logs.service.ts b/src/main/webapp/app/admin/logs/logs.service.ts index 73b2ddd7635e..65f2cf6f26de 100644 --- a/src/main/webapp/app/admin/logs/logs.service.ts +++ b/src/main/webapp/app/admin/logs/logs.service.ts @@ -1,11 +1,11 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { Level, LoggersResponse } from './log.model'; @Injectable({ providedIn: 'root' }) export class LogsService { - constructor(private http: HttpClient) {} + private http = inject(HttpClient); changeLevel(name: string, configuredLevel: Level): Observable { return this.http.post(`management/loggers/${name}`, { configuredLevel }); diff --git a/src/main/webapp/app/admin/lti-configuration/edit-lti-configuration.component.ts b/src/main/webapp/app/admin/lti-configuration/edit-lti-configuration.component.ts index 6f65f9c87969..f130ccf06b82 100644 --- a/src/main/webapp/app/admin/lti-configuration/edit-lti-configuration.component.ts +++ b/src/main/webapp/app/admin/lti-configuration/edit-lti-configuration.component.ts @@ -2,14 +2,18 @@ import { AlertService } from 'app/core/util/alert.service'; import { Component, OnInit, inject } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { finalize } from 'rxjs'; -import { FormControl, FormGroup } from '@angular/forms'; +import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { faBan, faPlus, faSave } from '@fortawesome/free-solid-svg-icons'; import { LtiPlatformConfiguration } from 'app/admin/lti-configuration/lti-configuration.model'; import { LtiConfigurationService } from 'app/admin/lti-configuration/lti-configuration.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-edit-lti-configuration', templateUrl: './edit-lti-configuration.component.html', + imports: [FormsModule, ReactiveFormsModule, TranslateDirective, HelpIconComponent, FaIconComponent], }) export class EditLtiConfigurationComponent implements OnInit { private route = inject(ActivatedRoute); diff --git a/src/main/webapp/app/admin/lti-configuration/lti-configuration.component.ts b/src/main/webapp/app/admin/lti-configuration/lti-configuration.component.ts index a18fbb8f602c..cf7cbb55d0ea 100644 --- a/src/main/webapp/app/admin/lti-configuration/lti-configuration.component.ts +++ b/src/main/webapp/app/admin/lti-configuration/lti-configuration.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, inject } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { Course } from 'app/entities/course.model'; import { faExclamationTriangle, faPencilAlt, faPlus, faSort, faTrash, faWrench } from '@fortawesome/free-solid-svg-icons'; import { LtiPlatformConfiguration } from 'app/admin/lti-configuration/lti-configuration.model'; @@ -11,10 +11,39 @@ import { AlertService } from 'app/core/util/alert.service'; import { LTI_URLS } from 'app/admin/lti-configuration/lti-configuration.urls'; import { ITEMS_PER_PAGE } from 'app/shared/constants/pagination.constants'; import { combineLatest } from 'rxjs'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbNav, NgbNavContent, NgbNavItem, NgbNavLink, NgbNavLinkBase, NgbNavOutlet, NgbPagination } from '@ng-bootstrap/ng-bootstrap'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { CopyIconButtonComponent } from 'app/shared/components/copy-icon-button/copy-icon-button.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { ItemCountComponent } from 'app/shared/pagination/item-count.component'; @Component({ selector: 'jhi-lti-configuration', templateUrl: './lti-configuration.component.html', + imports: [ + FormsModule, + TranslateDirective, + NgbNav, + NgbNavItem, + NgbNavLink, + NgbNavLinkBase, + NgbNavContent, + HelpIconComponent, + CopyIconButtonComponent, + RouterLink, + FaIconComponent, + SortDirective, + SortByDirective, + DeleteButtonDirective, + ItemCountComponent, + NgbPagination, + NgbNavOutlet, + ], }) export class LtiConfigurationComponent implements OnInit { private router = inject(Router); diff --git a/src/main/webapp/app/admin/lti-configuration/lti-configuration.route.ts b/src/main/webapp/app/admin/lti-configuration/lti-configuration.route.ts index aa663034e8bf..b4d81dd451d5 100644 --- a/src/main/webapp/app/admin/lti-configuration/lti-configuration.route.ts +++ b/src/main/webapp/app/admin/lti-configuration/lti-configuration.route.ts @@ -1,13 +1,12 @@ import { Routes } from '@angular/router'; -import { LtiConfigurationComponent } from 'app/admin/lti-configuration/lti-configuration.component'; -import { EditLtiConfigurationComponent } from 'app/admin/lti-configuration/edit-lti-configuration.component'; + import { Authority } from 'app/shared/constants/authority.constants'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; export const ltiConfigurationRoute: Routes = [ { path: 'lti-configuration', - component: LtiConfigurationComponent, + loadComponent: () => import('app/admin/lti-configuration/lti-configuration.component').then((m) => m.LtiConfigurationComponent), data: { pageTitle: 'global.menu.admin.lti', defaultSort: 'id,desc', @@ -21,7 +20,7 @@ export const ltiConfigurationRoute: Routes = [ children: [ { path: 'new', - component: EditLtiConfigurationComponent, + loadComponent: () => import('app/admin/lti-configuration/edit-lti-configuration.component').then((m) => m.EditLtiConfigurationComponent), data: { authorities: [Authority.ADMIN], pageTitle: 'artemisApp.lti.addOrEditLtiPlatform', @@ -36,7 +35,7 @@ export const ltiConfigurationRoute: Routes = [ children: [ { path: 'edit', - component: EditLtiConfigurationComponent, + loadComponent: () => import('app/admin/lti-configuration/edit-lti-configuration.component').then((m) => m.EditLtiConfigurationComponent), data: { authorities: [Authority.ADMIN], pageTitle: 'artemisApp.lti.addOrEditLtiPlatform', diff --git a/src/main/webapp/app/admin/metrics/blocks/jvm-memory/jvm-memory.component.ts b/src/main/webapp/app/admin/metrics/blocks/jvm-memory/jvm-memory.component.ts index 7c3866f15985..46b8be5cdff0 100644 --- a/src/main/webapp/app/admin/metrics/blocks/jvm-memory/jvm-memory.component.ts +++ b/src/main/webapp/app/admin/metrics/blocks/jvm-memory/jvm-memory.component.ts @@ -9,7 +9,6 @@ import { DecimalPipe, KeyValuePipe } from '@angular/common'; selector: 'jhi-jvm-memory', templateUrl: './jvm-memory.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - standalone: true, imports: [TranslateDirective, NgbProgressbar, DecimalPipe, KeyValuePipe], }) export class JvmMemoryComponent { diff --git a/src/main/webapp/app/admin/metrics/blocks/jvm-threads/jvm-threads.component.ts b/src/main/webapp/app/admin/metrics/blocks/jvm-threads/jvm-threads.component.ts index 9a087bdb855b..824ba0fa519b 100644 --- a/src/main/webapp/app/admin/metrics/blocks/jvm-threads/jvm-threads.component.ts +++ b/src/main/webapp/app/admin/metrics/blocks/jvm-threads/jvm-threads.component.ts @@ -10,7 +10,6 @@ import { DecimalPipe } from '@angular/common'; selector: 'jhi-jvm-threads', templateUrl: './jvm-threads.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - standalone: true, imports: [TranslateDirective, NgbProgressbar, DecimalPipe], }) export class JvmThreadsComponent { diff --git a/src/main/webapp/app/admin/metrics/blocks/metrics-cache/metrics-cache.component.ts b/src/main/webapp/app/admin/metrics/blocks/metrics-cache/metrics-cache.component.ts index 83b5d464abe8..eb5320fcafde 100644 --- a/src/main/webapp/app/admin/metrics/blocks/metrics-cache/metrics-cache.component.ts +++ b/src/main/webapp/app/admin/metrics/blocks/metrics-cache/metrics-cache.component.ts @@ -8,7 +8,6 @@ import { DecimalPipe, KeyValuePipe } from '@angular/common'; selector: 'jhi-metrics-cache', templateUrl: './metrics-cache.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - standalone: true, imports: [TranslateDirective, DecimalPipe, KeyValuePipe], }) export class MetricsCacheComponent { diff --git a/src/main/webapp/app/admin/metrics/blocks/metrics-datasource/metrics-datasource.component.ts b/src/main/webapp/app/admin/metrics/blocks/metrics-datasource/metrics-datasource.component.ts index 7c12eec1f89d..d8ff9cb81260 100644 --- a/src/main/webapp/app/admin/metrics/blocks/metrics-datasource/metrics-datasource.component.ts +++ b/src/main/webapp/app/admin/metrics/blocks/metrics-datasource/metrics-datasource.component.ts @@ -8,7 +8,6 @@ import { DecimalPipe } from '@angular/common'; selector: 'jhi-metrics-datasource', templateUrl: './metrics-datasource.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - standalone: true, imports: [TranslateDirective, DecimalPipe], }) export class MetricsDatasourceComponent { diff --git a/src/main/webapp/app/admin/metrics/blocks/metrics-endpoints-requests/metrics-endpoints-requests.component.ts b/src/main/webapp/app/admin/metrics/blocks/metrics-endpoints-requests/metrics-endpoints-requests.component.ts index d4ac3e797630..85653844f7ec 100644 --- a/src/main/webapp/app/admin/metrics/blocks/metrics-endpoints-requests/metrics-endpoints-requests.component.ts +++ b/src/main/webapp/app/admin/metrics/blocks/metrics-endpoints-requests/metrics-endpoints-requests.component.ts @@ -6,7 +6,6 @@ import { DecimalPipe, KeyValuePipe } from '@angular/common'; selector: 'jhi-metrics-endpoints-requests', templateUrl: './metrics-endpoints-requests.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - standalone: true, imports: [DecimalPipe, KeyValuePipe], }) export class MetricsEndpointsRequestsComponent { diff --git a/src/main/webapp/app/admin/metrics/blocks/metrics-garbagecollector/metrics-garbagecollector.component.ts b/src/main/webapp/app/admin/metrics/blocks/metrics-garbagecollector/metrics-garbagecollector.component.ts index e6482f229533..5fe766c0ba20 100644 --- a/src/main/webapp/app/admin/metrics/blocks/metrics-garbagecollector/metrics-garbagecollector.component.ts +++ b/src/main/webapp/app/admin/metrics/blocks/metrics-garbagecollector/metrics-garbagecollector.component.ts @@ -8,7 +8,6 @@ import { DecimalPipe } from '@angular/common'; selector: 'jhi-metrics-garbagecollector', templateUrl: './metrics-garbagecollector.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - standalone: true, imports: [TranslateDirective, NgbProgressbar, DecimalPipe], }) export class MetricsGarbageCollectorComponent { diff --git a/src/main/webapp/app/admin/metrics/blocks/metrics-modal-threads/metrics-modal-threads.component.ts b/src/main/webapp/app/admin/metrics/blocks/metrics-modal-threads/metrics-modal-threads.component.ts index 202afdafae93..2ef85a0d981a 100644 --- a/src/main/webapp/app/admin/metrics/blocks/metrics-modal-threads/metrics-modal-threads.component.ts +++ b/src/main/webapp/app/admin/metrics/blocks/metrics-modal-threads/metrics-modal-threads.component.ts @@ -1,18 +1,17 @@ +import { NgClass } from '@angular/common'; import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { faCheck } from '@fortawesome/free-solid-svg-icons'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { Thread, ThreadState } from '../../metrics.model'; import { TranslateDirective } from 'app/shared/language/translate.directive'; -import { FaIconComponent } from '@fortawesome/angular-fontawesome'; -import { FormsModule } from '@angular/forms'; -import { NgClass } from '@angular/common'; import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; +import { Thread, ThreadState } from '../../metrics.model'; @Component({ selector: 'jhi-thread-modal', templateUrl: './metrics-modal-threads.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - standalone: true, imports: [TranslateDirective, FaIconComponent, FormsModule, NgClass, ArtemisSharedCommonModule], }) export class MetricsModalThreadsComponent implements OnInit { diff --git a/src/main/webapp/app/admin/metrics/blocks/metrics-request/metrics-request.component.ts b/src/main/webapp/app/admin/metrics/blocks/metrics-request/metrics-request.component.ts index bcb58fcb5775..138fa79ecdca 100644 --- a/src/main/webapp/app/admin/metrics/blocks/metrics-request/metrics-request.component.ts +++ b/src/main/webapp/app/admin/metrics/blocks/metrics-request/metrics-request.component.ts @@ -9,7 +9,6 @@ import { DecimalPipe, KeyValuePipe } from '@angular/common'; selector: 'jhi-metrics-request', templateUrl: './metrics-request.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - standalone: true, imports: [TranslateDirective, NgbProgressbar, DecimalPipe, KeyValuePipe], }) export class MetricsRequestComponent { diff --git a/src/main/webapp/app/admin/metrics/blocks/metrics-system/metrics-system.component.ts b/src/main/webapp/app/admin/metrics/blocks/metrics-system/metrics-system.component.ts index 358eff4855ff..e55208f186d4 100644 --- a/src/main/webapp/app/admin/metrics/blocks/metrics-system/metrics-system.component.ts +++ b/src/main/webapp/app/admin/metrics/blocks/metrics-system/metrics-system.component.ts @@ -7,7 +7,6 @@ import { DatePipe, DecimalPipe } from '@angular/common'; selector: 'jhi-metrics-system', templateUrl: './metrics-system.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - standalone: true, imports: [NgbProgressbar, DecimalPipe, DatePipe], }) export class MetricsSystemComponent { diff --git a/src/main/webapp/app/admin/metrics/metrics.component.ts b/src/main/webapp/app/admin/metrics/metrics.component.ts index 3cbe7f9f4b79..2d0197c67ca8 100644 --- a/src/main/webapp/app/admin/metrics/metrics.component.ts +++ b/src/main/webapp/app/admin/metrics/metrics.component.ts @@ -19,7 +19,6 @@ import { MetricsDatasourceComponent } from './blocks/metrics-datasource/metrics- selector: 'jhi-metrics', templateUrl: './metrics.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - standalone: true, imports: [ TranslateDirective, FaIconComponent, diff --git a/src/main/webapp/app/admin/organization-management/organization-count-dto.model.ts b/src/main/webapp/app/admin/organization-management/organization-count-dto.model.ts index 522200ab572f..a1416ff07c46 100644 --- a/src/main/webapp/app/admin/organization-management/organization-count-dto.model.ts +++ b/src/main/webapp/app/admin/organization-management/organization-count-dto.model.ts @@ -2,6 +2,4 @@ export class OrganizationCountDto { public organizationId: number; public numberOfUsers: number; public numberOfCourses: number; - - constructor() {} } diff --git a/src/main/webapp/app/admin/organization-management/organization-management-detail.component.ts b/src/main/webapp/app/admin/organization-management/organization-management-detail.component.ts index 23f990728773..33b5532f77b7 100644 --- a/src/main/webapp/app/admin/organization-management/organization-management-detail.component.ts +++ b/src/main/webapp/app/admin/organization-management/organization-management-detail.component.ts @@ -1,5 +1,5 @@ -import { Component, OnInit, ViewChild } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { Component, OnInit, ViewChild, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { HttpErrorResponse } from '@angular/common/http'; import { Organization } from 'app/entities/organization.model'; import { OrganizationManagementService } from 'app/admin/organization-management/organization-management.service'; @@ -12,6 +12,10 @@ import { iconsAsHTML } from 'app/utils/icons.utils'; import { UserService } from 'app/core/user/user.service'; import { DataTableComponent } from 'app/shared/data-table/data-table.component'; import { faUserSlash } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgxDatatableModule } from '@siemens/ngx-datatable'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; const cssClasses = { alreadyMember: 'already-member', @@ -21,8 +25,14 @@ const cssClasses = { @Component({ selector: 'jhi-organization-management-detail', templateUrl: './organization-management-detail.component.html', + imports: [TranslateDirective, RouterLink, DataTableComponent, NgxDatatableModule, FaIconComponent, DeleteButtonDirective], }) export class OrganizationManagementDetailComponent implements OnInit { + private organizationService = inject(OrganizationManagementService); + private userService = inject(UserService); + private alertService = inject(AlertService); + private route = inject(ActivatedRoute); + @ViewChild(DataTableComponent) dataTable: DataTableComponent; organization: Organization; @@ -42,13 +52,6 @@ export class OrganizationManagementDetailComponent implements OnInit { // Icons faUserSlash = faUserSlash; - constructor( - private organizationService: OrganizationManagementService, - private userService: UserService, - private alertService: AlertService, - private route: ActivatedRoute, - ) {} - /** * Retrieve the organization from the organization management activated route data subscription * and get the organization based on its id diff --git a/src/main/webapp/app/admin/organization-management/organization-management-resolve.service.ts b/src/main/webapp/app/admin/organization-management/organization-management-resolve.service.ts index 60277e2a3dc0..a9e42b5e99be 100644 --- a/src/main/webapp/app/admin/organization-management/organization-management-resolve.service.ts +++ b/src/main/webapp/app/admin/organization-management/organization-management-resolve.service.ts @@ -1,11 +1,11 @@ import { Organization } from 'app/entities/organization.model'; import { OrganizationManagementService } from 'app/admin/organization-management/organization-management.service'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class OrganizationManagementResolve implements Resolve { - constructor(private organizationManagementService: OrganizationManagementService) {} + private organizationManagementService = inject(OrganizationManagementService); resolve(route: ActivatedRouteSnapshot) { if (route.params['id']) { diff --git a/src/main/webapp/app/admin/organization-management/organization-management-update.component.ts b/src/main/webapp/app/admin/organization-management/organization-management-update.component.ts index 4eace90dca4a..262fb7b30adb 100644 --- a/src/main/webapp/app/admin/organization-management/organization-management-update.component.ts +++ b/src/main/webapp/app/admin/organization-management/organization-management-update.component.ts @@ -1,14 +1,22 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Organization } from 'app/entities/organization.model'; import { OrganizationManagementService } from 'app/admin/organization-management/organization-management.service'; import { faBan, faSave } from '@fortawesome/free-solid-svg-icons'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CustomPatternValidatorDirective } from 'app/shared/validators/custom-pattern-validator.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-organization-management-update', templateUrl: './organization-management-update.component.html', + imports: [FormsModule, TranslateDirective, CustomPatternValidatorDirective, FaIconComponent], }) export class OrganizationManagementUpdateComponent implements OnInit { + private route = inject(ActivatedRoute); + private organizationService = inject(OrganizationManagementService); + organization: Organization; isSaving: boolean; @@ -16,11 +24,6 @@ export class OrganizationManagementUpdateComponent implements OnInit { faSave = faSave; faBan = faBan; - constructor( - private route: ActivatedRoute, - private organizationService: OrganizationManagementService, - ) {} - /** * Enable subscriptions to retrieve the organization based on the activated route on init */ diff --git a/src/main/webapp/app/admin/organization-management/organization-management.component.ts b/src/main/webapp/app/admin/organization-management/organization-management.component.ts index 9711658af330..c6473eebd30d 100644 --- a/src/main/webapp/app/admin/organization-management/organization-management.component.ts +++ b/src/main/webapp/app/admin/organization-management/organization-management.component.ts @@ -1,15 +1,22 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { HttpErrorResponse } from '@angular/common/http'; import { Organization } from 'app/entities/organization.model'; import { OrganizationManagementService } from 'app/admin/organization-management/organization-management.service'; import { Subject } from 'rxjs'; import { faEye, faPlus, faTimes, faWrench } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { RouterLink } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; @Component({ selector: 'jhi-organization-management', templateUrl: './organization-management.component.html', + imports: [TranslateDirective, RouterLink, FaIconComponent, DeleteButtonDirective], }) export class OrganizationManagementComponent implements OnInit { + private organizationService = inject(OrganizationManagementService); + organizations: Organization[]; private dialogErrorSource = new Subject(); @@ -21,8 +28,6 @@ export class OrganizationManagementComponent implements OnInit { faEye = faEye; faWrench = faWrench; - constructor(private organizationService: OrganizationManagementService) {} - ngOnInit(): void { this.organizationService.getOrganizations().subscribe((organizations) => { this.organizations = organizations; diff --git a/src/main/webapp/app/admin/organization-management/organization-management.route.ts b/src/main/webapp/app/admin/organization-management/organization-management.route.ts index 6cedadd30b4c..a2f68870c6fb 100644 --- a/src/main/webapp/app/admin/organization-management/organization-management.route.ts +++ b/src/main/webapp/app/admin/organization-management/organization-management.route.ts @@ -1,13 +1,11 @@ import { Route } from '@angular/router'; -import { OrganizationManagementComponent } from 'app/admin/organization-management/organization-management.component'; -import { OrganizationManagementUpdateComponent } from 'app/admin/organization-management/organization-management-update.component'; -import { OrganizationManagementDetailComponent } from 'app/admin/organization-management/organization-management-detail.component'; + import { OrganizationManagementResolve } from 'app/admin/organization-management/organization-management-resolve.service'; export const organizationMgmtRoute: Route[] = [ { path: 'organization-management', - component: OrganizationManagementComponent, + loadComponent: () => import('app/admin/organization-management/organization-management.component').then((m) => m.OrganizationManagementComponent), data: { pageTitle: 'artemisApp.organizationManagement.title', }, @@ -20,7 +18,7 @@ export const organizationMgmtRoute: Route[] = [ children: [ { path: 'new', - component: OrganizationManagementUpdateComponent, + loadComponent: () => import('app/admin/organization-management/organization-management-update.component').then((m) => m.OrganizationManagementUpdateComponent), resolve: { organization: OrganizationManagementResolve, }, @@ -30,7 +28,7 @@ export const organizationMgmtRoute: Route[] = [ }, { path: ':id', - component: OrganizationManagementDetailComponent, + loadComponent: () => import('app/admin/organization-management/organization-management-detail.component').then((m) => m.OrganizationManagementDetailComponent), resolve: { organization: OrganizationManagementResolve, }, @@ -50,7 +48,8 @@ export const organizationMgmtRoute: Route[] = [ children: [ { path: 'edit', - component: OrganizationManagementUpdateComponent, + loadComponent: () => + import('app/admin/organization-management/organization-management-update.component').then((m) => m.OrganizationManagementUpdateComponent), data: { pageTitle: 'artemisApp.organizationManagement.addOrEditLabel', breadcrumbLabelVariable: 'organization.id', diff --git a/src/main/webapp/app/admin/organization-management/organization-management.service.ts b/src/main/webapp/app/admin/organization-management/organization-management.service.ts index f488abe062b3..7b89d23a5ce1 100644 --- a/src/main/webapp/app/admin/organization-management/organization-management.service.ts +++ b/src/main/webapp/app/admin/organization-management/organization-management.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable, tap } from 'rxjs'; @@ -8,14 +8,12 @@ import { EntityTitleService, EntityType } from 'app/shared/layouts/navbar/entity @Injectable({ providedIn: 'root' }) export class OrganizationManagementService { + private http = inject(HttpClient); + private entityTitleService = inject(EntityTitleService); + public resourceUrl = 'api/organizations'; public adminResourceUrl = 'api/admin/organizations'; - constructor( - private http: HttpClient, - private entityTitleService: EntityTitleService, - ) {} - /** * Send GET request to retrieve all organizations */ diff --git a/src/main/webapp/app/admin/standardized-competencies/import/admin-import-standardized-competencies.component.ts b/src/main/webapp/app/admin/standardized-competencies/import/admin-import-standardized-competencies.component.ts index bd63f1306106..5355c7e853f8 100644 --- a/src/main/webapp/app/admin/standardized-competencies/import/admin-import-standardized-competencies.component.ts +++ b/src/main/webapp/app/admin/standardized-competencies/import/admin-import-standardized-competencies.component.ts @@ -24,6 +24,7 @@ import { ArtemisSharedComponentModule } from 'app/shared/components/shared-compo import { StandardizedCompetencyDetailComponent } from 'app/shared/standardized-competencies/standardized-competency-detail.component'; import { KnowledgeAreaTreeComponent } from 'app/shared/standardized-competencies/knowledge-area-tree.component'; import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; +import { NgbCollapse } from '@ng-bootstrap/ng-bootstrap'; interface ImportCount { knowledgeAreas: number; @@ -32,9 +33,16 @@ interface ImportCount { @Component({ selector: 'jhi-admin-import-standardized-competencies', - standalone: true, templateUrl: './admin-import-standardized-competencies.component.html', - imports: [ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisMarkdownModule, FontAwesomeModule, StandardizedCompetencyDetailComponent, KnowledgeAreaTreeComponent], + imports: [ + ArtemisSharedModule, + ArtemisSharedComponentModule, + ArtemisMarkdownModule, + FontAwesomeModule, + StandardizedCompetencyDetailComponent, + KnowledgeAreaTreeComponent, + NgbCollapse, + ], }) export class AdminImportStandardizedCompetenciesComponent { protected isLoading = false; @@ -60,7 +68,7 @@ export class AdminImportStandardizedCompetenciesComponent { protected readonly importExample = `\`\`\` { "knowledgeAreas": [{ - "title": "Artifical Intelligence", + "title": "Artificial Intelligence", "shortTitle": "AI", "description": "AI is a field in computer science...", //(optional) "competencies": [{ diff --git a/src/main/webapp/app/admin/standardized-competencies/knowledge-area-edit.component.ts b/src/main/webapp/app/admin/standardized-competencies/knowledge-area-edit.component.ts index 935b8ab26609..0ff068bee384 100644 --- a/src/main/webapp/app/admin/standardized-competencies/knowledge-area-edit.component.ts +++ b/src/main/webapp/app/admin/standardized-competencies/knowledge-area-edit.component.ts @@ -1,15 +1,24 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output, inject } from '@angular/core'; import { faBan, faPencil, faPlus, faSave, faTrash } from '@fortawesome/free-solid-svg-icons'; import { KnowledgeArea, KnowledgeAreaDTO, KnowledgeAreaValidators } from 'app/entities/competency/standardized-competency.model'; import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; -import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { Observable } from 'rxjs'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { MarkdownEditorMonacoComponent } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-knowledge-area-edit', templateUrl: './knowledge-area-edit.component.html', + imports: [TranslateDirective, ButtonComponent, DeleteButtonDirective, FaIconComponent, FormsModule, ReactiveFormsModule, MarkdownEditorMonacoComponent, HtmlForMarkdownPipe], }) export class KnowledgeAreaEditComponent { + private formBuilder = inject(FormBuilder); + // values for the knowledge area select @Input() knowledgeAreas: KnowledgeArea[] = []; @Input({ required: true }) set knowledgeArea(knowledgeArea: KnowledgeAreaDTO) { @@ -72,8 +81,6 @@ export class KnowledgeAreaEditComponent { protected readonly ButtonType = ButtonType; protected readonly validators = KnowledgeAreaValidators; - constructor(private formBuilder: FormBuilder) {} - save() { const updatedValues = this.form.getRawValue(); const updatedKnowledgeArea: KnowledgeAreaDTO = { ...this.knowledgeArea, ...updatedValues }; @@ -128,7 +135,7 @@ export class KnowledgeAreaEditComponent { // if the knowledgeArea is new, no validator is needed. if (this.knowledgeArea.id === undefined) { // eslint-disable-next-line @typescript-eslint/no-unused-vars - return (parentIdControl: FormControl) => null; + return (_parentIdControl: FormControl) => null; } return (parentIdControl: FormControl) => { if (parentIdControl.value === undefined) { diff --git a/src/main/webapp/app/admin/standardized-competencies/standardized-competency-edit.component.ts b/src/main/webapp/app/admin/standardized-competencies/standardized-competency-edit.component.ts index 8644cbaacffd..d7fdab0f675b 100644 --- a/src/main/webapp/app/admin/standardized-competencies/standardized-competency-edit.component.ts +++ b/src/main/webapp/app/admin/standardized-competencies/standardized-competency-edit.component.ts @@ -1,16 +1,36 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output, inject } from '@angular/core'; import { faBan, faPencil, faSave, faTrash } from '@fortawesome/free-solid-svg-icons'; import { KnowledgeArea, Source, StandardizedCompetencyDTO, StandardizedCompetencyValidators } from 'app/entities/competency/standardized-competency.model'; import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; -import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { CompetencyTaxonomy } from 'app/entities/competency.model'; import { Observable } from 'rxjs'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { MarkdownEditorMonacoComponent } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { TaxonomySelectComponent } from 'app/course/competencies/taxonomy-select/taxonomy-select.component'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-standardized-competency-edit', templateUrl: './standardized-competency-edit.component.html', + imports: [ + TranslateDirective, + ButtonComponent, + DeleteButtonDirective, + FaIconComponent, + FormsModule, + ReactiveFormsModule, + MarkdownEditorMonacoComponent, + TaxonomySelectComponent, + HtmlForMarkdownPipe, + ], }) export class StandardizedCompetencyEditComponent { + private formBuilder = inject(FormBuilder); + // values for the knowledge area select @Input() knowledgeAreas: KnowledgeArea[] = []; // values for the source select @@ -74,8 +94,6 @@ export class StandardizedCompetencyEditComponent { protected readonly ButtonType = ButtonType; protected readonly validators = StandardizedCompetencyValidators; - constructor(private formBuilder: FormBuilder) {} - save() { const updatedValues = this.form.getRawValue(); const updatedCompetency: StandardizedCompetencyDTO = { ...this.competency, ...updatedValues }; diff --git a/src/main/webapp/app/admin/standardized-competencies/standardized-competency-management.component.ts b/src/main/webapp/app/admin/standardized-competencies/standardized-competency-management.component.ts index d23fe7213f6d..1d98957a1225 100644 --- a/src/main/webapp/app/admin/standardized-competencies/standardized-competency-management.component.ts +++ b/src/main/webapp/app/admin/standardized-competencies/standardized-competency-management.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { faChevronRight, faDownLeftAndUpRightToCenter, faEye, faFileExport, faFileImport, faPlus, faUpRightAndDownLeftFromCenter } from '@fortawesome/free-solid-svg-icons'; import { KnowledgeAreaDTO, @@ -13,7 +13,7 @@ import { AdminStandardizedCompetencyService } from 'app/admin/standardized-compe import { HttpErrorResponse } from '@angular/common/http'; import { AlertService } from 'app/core/util/alert.service'; import { Subject, forkJoin, map } from 'rxjs'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { ConfirmAutofocusModalComponent } from 'app/shared/components/confirm-autofocus-modal.component'; import { getIcon } from 'app/entities/competency.model'; import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; @@ -22,14 +22,44 @@ import { StandardizedCompetencyFilterPageComponent } from 'app/shared/standardiz import { ComponentCanDeactivate } from 'app/shared/guard/can-deactivate.model'; import { StandardizedCompetencyService } from 'app/shared/standardized-competencies/standardized-competency.service'; import { DocumentationType } from 'app/shared/components/documentation-button/documentation-button.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { RouterLink } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { StandardizedCompetencyFilterComponent } from 'app/shared/standardized-competencies/standardized-competency-filter.component'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { KnowledgeAreaTreeComponent } from 'app/shared/standardized-competencies/knowledge-area-tree.component'; +import { StandardizedCompetencyEditComponent } from './standardized-competency-edit.component'; +import { KnowledgeAreaEditComponent } from './knowledge-area-edit.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-standardized-competency-management', templateUrl: './standardized-competency-management.component.html', styleUrls: ['standardized-competency-management.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + TranslateDirective, + DocumentationButtonComponent, + RouterLink, + FaIconComponent, + StandardizedCompetencyFilterComponent, + ButtonComponent, + KnowledgeAreaTreeComponent, + NgbTooltip, + StandardizedCompetencyEditComponent, + KnowledgeAreaEditComponent, + ArtemisTranslatePipe, + ], }) export class StandardizedCompetencyManagementComponent extends StandardizedCompetencyFilterPageComponent implements OnInit, OnDestroy, ComponentCanDeactivate { + private adminStandardizedCompetencyService = inject(AdminStandardizedCompetencyService); + private standardizedCompetencyService = inject(StandardizedCompetencyService); + private alertService = inject(AlertService); + private modalService = inject(NgbModal); + private translateService = inject(TranslateService); + private changeDetectorRef = inject(ChangeDetectorRef); + protected isLoading = false; // true if a competency is getting edited in the detail component protected isEditing = false; @@ -58,17 +88,6 @@ export class StandardizedCompetencyManagementComponent extends StandardizedCompe protected readonly getIcon = getIcon; readonly documentationType: DocumentationType = 'StandardizedCompetencies'; - constructor( - private adminStandardizedCompetencyService: AdminStandardizedCompetencyService, - private standardizedCompetencyService: StandardizedCompetencyService, - private alertService: AlertService, - private modalService: NgbModal, - private translateService: TranslateService, - private changeDetectorRef: ChangeDetectorRef, - ) { - super(); - } - ngOnInit() { this.isLoading = true; const getKnowledgeAreasObservable = this.standardizedCompetencyService.getAllForTreeView(); diff --git a/src/main/webapp/app/admin/statistics/statistics.component.ts b/src/main/webapp/app/admin/statistics/statistics.component.ts index ab7543bc028c..b9a3c2d0962f 100644 --- a/src/main/webapp/app/admin/statistics/statistics.component.ts +++ b/src/main/webapp/app/admin/statistics/statistics.component.ts @@ -1,9 +1,13 @@ import { Component } from '@angular/core'; import { Graphs, SpanType, StatisticsView } from 'app/entities/statistics.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { StatisticsGraphComponent } from 'app/shared/statistics-graph/statistics-graph.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-statistics', templateUrl: './statistics.component.html', + imports: [TranslateDirective, StatisticsGraphComponent, ArtemisTranslatePipe], }) export class StatisticsComponent { // html properties @@ -24,8 +28,6 @@ export class StatisticsComponent { currentSpan: SpanType = SpanType.WEEK; statisticsView: StatisticsView = StatisticsView.ARTEMIS; - constructor() {} - onTabChanged(span: SpanType): void { this.currentSpan = span; } diff --git a/src/main/webapp/app/admin/system-notification-management/system-notification-management-detail.component.ts b/src/main/webapp/app/admin/system-notification-management/system-notification-management-detail.component.ts index 05c64dec18e7..9aa7d3a66f4c 100644 --- a/src/main/webapp/app/admin/system-notification-management/system-notification-management-detail.component.ts +++ b/src/main/webapp/app/admin/system-notification-management/system-notification-management-detail.component.ts @@ -1,24 +1,26 @@ -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { Component, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, Router, RouterLink, RouterOutlet } from '@angular/router'; import { faWrench } from '@fortawesome/free-solid-svg-icons'; import { SystemNotification } from 'app/entities/system-notification.model'; import { SystemNotificationService } from 'app/shared/notification/system-notification/system-notification.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; @Component({ selector: 'jhi-system-notification-management-detail', templateUrl: './system-notification-management-detail.component.html', + imports: [TranslateDirective, RouterLink, FaIconComponent, RouterOutlet, ArtemisDatePipe], }) export class SystemNotificationManagementDetailComponent implements OnInit { + private systemNotificationService = inject(SystemNotificationService); + private route = inject(ActivatedRoute); + private router = inject(Router); + notification: SystemNotification; // Icons faWrench = faWrench; - constructor( - private systemNotificationService: SystemNotificationService, - private route: ActivatedRoute, - private router: Router, - ) {} - /** * Assigns the subscription to system notification service */ diff --git a/src/main/webapp/app/admin/system-notification-management/system-notification-management-resolve.service.ts b/src/main/webapp/app/admin/system-notification-management/system-notification-management-resolve.service.ts index e0741f531f38..37ed2da319b8 100644 --- a/src/main/webapp/app/admin/system-notification-management/system-notification-management-resolve.service.ts +++ b/src/main/webapp/app/admin/system-notification-management/system-notification-management-resolve.service.ts @@ -1,5 +1,5 @@ import { HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { SystemNotification } from 'app/entities/system-notification.model'; import { SystemNotificationService } from 'app/shared/notification/system-notification/system-notification.service'; @@ -7,7 +7,7 @@ import { filter, map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class SystemNotificationManagementResolve implements Resolve { - constructor(private service: SystemNotificationService) {} + private service = inject(SystemNotificationService); /** * Resolves the route and initializes system notification from id route param diff --git a/src/main/webapp/app/admin/system-notification-management/system-notification-management-update.component.ts b/src/main/webapp/app/admin/system-notification-management/system-notification-management-update.component.ts index 75523020fa0d..18ca17c3372c 100644 --- a/src/main/webapp/app/admin/system-notification-management/system-notification-management-update.component.ts +++ b/src/main/webapp/app/admin/system-notification-management/system-notification-management-update.component.ts @@ -1,17 +1,27 @@ -import { Component, OnInit } from '@angular/core'; -import { FormControl, FormGroup, Validators } from '@angular/forms'; +import { Component, OnInit, inject } from '@angular/core'; +import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { faBan, faSave } from '@fortawesome/free-solid-svg-icons'; import { UserService } from 'app/core/user/user.service'; import { SystemNotification, SystemNotificationType } from 'app/entities/system-notification.model'; import dayjs from 'dayjs/esm'; import { AdminSystemNotificationService } from 'app/shared/notification/system-notification/admin-system-notification.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-system-notification-management-update', templateUrl: './system-notification-management-update.component.html', + imports: [FormsModule, ReactiveFormsModule, TranslateDirective, FormDateTimePickerComponent, FaIconComponent, ArtemisTranslatePipe], }) export class SystemNotificationManagementUpdateComponent implements OnInit { + private userService = inject(UserService); + private systemNotificationService = inject(AdminSystemNotificationService); + private route = inject(ActivatedRoute); + private router = inject(Router); + notification: SystemNotification; isSaving: boolean; @@ -26,13 +36,6 @@ export class SystemNotificationManagementUpdateComponent implements OnInit { faSave = faSave; faBan = faBan; - constructor( - private userService: UserService, - private systemNotificationService: AdminSystemNotificationService, - private route: ActivatedRoute, - private router: Router, - ) {} - /** * Loads notification from route data */ diff --git a/src/main/webapp/app/admin/system-notification-management/system-notification-management.component.ts b/src/main/webapp/app/admin/system-notification-management/system-notification-management.component.ts index 89d80d04b471..d6e44743fe9b 100644 --- a/src/main/webapp/app/admin/system-notification-management/system-notification-management.component.ts +++ b/src/main/webapp/app/admin/system-notification-management/system-notification-management.component.ts @@ -1,6 +1,6 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { HttpErrorResponse, HttpHeaders, HttpResponse } from '@angular/common/http'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { Subject, Subscription } from 'rxjs'; import { User } from 'app/core/user/user.model'; import { AccountService } from 'app/core/auth/account.service'; @@ -14,6 +14,14 @@ import { EventManager } from 'app/core/util/event-manager.service'; import { ParseLinks } from 'app/core/util/parse-links.service'; import { faEye, faPlus, faSort, faTimes, faWrench } from '@fortawesome/free-solid-svg-icons'; import { AdminSystemNotificationService } from 'app/shared/notification/system-notification/admin-system-notification.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { ItemCountComponent } from 'app/shared/pagination/item-count.component'; +import { NgbPagination } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; enum NotificationState { SCHEDULED = 'SCHEDULED', @@ -24,8 +32,18 @@ enum NotificationState { @Component({ selector: 'jhi-system-notification-management', templateUrl: './system-notification-management.component.html', + imports: [TranslateDirective, RouterLink, FaIconComponent, SortDirective, SortByDirective, DeleteButtonDirective, ItemCountComponent, NgbPagination, ArtemisDatePipe], }) export class SystemNotificationManagementComponent implements OnInit, OnDestroy { + private systemNotificationService = inject(SystemNotificationService); + private adminSystemNotificationService = inject(AdminSystemNotificationService); + private alertService = inject(AlertService); + private accountService = inject(AccountService); + private parseLinks = inject(ParseLinks); + private activatedRoute = inject(ActivatedRoute); + private router = inject(Router); + private eventManager = inject(EventManager); + readonly SCHEDULED = NotificationState.SCHEDULED; readonly ACTIVE = NotificationState.ACTIVE; readonly EXPIRED = NotificationState.EXPIRED; @@ -55,16 +73,7 @@ export class SystemNotificationManagementComponent implements OnInit, OnDestroy faEye = faEye; faWrench = faWrench; - constructor( - private systemNotificationService: SystemNotificationService, - private adminSystemNotificationService: AdminSystemNotificationService, - private alertService: AlertService, - private accountService: AccountService, - private parseLinks: ParseLinks, - private activatedRoute: ActivatedRoute, - private router: Router, - private eventManager: EventManager, - ) { + constructor() { this.routeData = this.activatedRoute.data.subscribe((data) => { const pagingParams = data['pagingParams']; if (pagingParams) { diff --git a/src/main/webapp/app/admin/system-notification-management/system-notification-management.route.ts b/src/main/webapp/app/admin/system-notification-management/system-notification-management.route.ts index 7a5b01f2d107..09ff2defee8a 100644 --- a/src/main/webapp/app/admin/system-notification-management/system-notification-management.route.ts +++ b/src/main/webapp/app/admin/system-notification-management/system-notification-management.route.ts @@ -1,13 +1,11 @@ import { Route } from '@angular/router'; -import { SystemNotificationManagementUpdateComponent } from 'app/admin/system-notification-management/system-notification-management-update.component'; -import { SystemNotificationManagementComponent } from 'app/admin/system-notification-management/system-notification-management.component'; -import { SystemNotificationManagementDetailComponent } from 'app/admin/system-notification-management/system-notification-management-detail.component'; + import { SystemNotificationManagementResolve } from 'app/admin/system-notification-management/system-notification-management-resolve.service'; export const systemNotificationManagementRoute: Route[] = [ { path: 'system-notification-management', - component: SystemNotificationManagementComponent, + loadComponent: () => import('app/admin/system-notification-management/system-notification-management.component').then((m) => m.SystemNotificationManagementComponent), data: { pageTitle: 'artemisApp.systemNotification.systemNotifications', defaultSort: 'id,asc', @@ -22,14 +20,16 @@ export const systemNotificationManagementRoute: Route[] = [ children: [ { path: 'new', - component: SystemNotificationManagementUpdateComponent, + loadComponent: () => + import('app/admin/system-notification-management/system-notification-management-update.component').then((m) => m.SystemNotificationManagementUpdateComponent), data: { pageTitle: 'global.generic.create', }, }, { path: ':id', - component: SystemNotificationManagementDetailComponent, + loadComponent: () => + import('app/admin/system-notification-management/system-notification-management-detail.component').then((m) => m.SystemNotificationManagementDetailComponent), resolve: { notification: SystemNotificationManagementResolve, }, @@ -50,7 +50,10 @@ export const systemNotificationManagementRoute: Route[] = [ children: [ { path: 'edit', - component: SystemNotificationManagementUpdateComponent, + loadComponent: () => + import('app/admin/system-notification-management/system-notification-management-update.component').then( + (m) => m.SystemNotificationManagementUpdateComponent, + ), data: { pageTitle: 'global.generic.edit', breadcrumbLabelVariable: '', diff --git a/src/main/webapp/app/admin/upcoming-exams-and-exercises/upcoming-exams-and-exercises.component.ts b/src/main/webapp/app/admin/upcoming-exams-and-exercises/upcoming-exams-and-exercises.component.ts index 8855ae1fb047..d1b8ee625bb0 100644 --- a/src/main/webapp/app/admin/upcoming-exams-and-exercises/upcoming-exams-and-exercises.component.ts +++ b/src/main/webapp/app/admin/upcoming-exams-and-exercises/upcoming-exams-and-exercises.component.ts @@ -1,29 +1,31 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { HttpResponse } from '@angular/common/http'; import { EntityArrayResponseType as ExerciseEntityArrayResponseType, ExerciseService } from 'app/exercises/shared/exercise/exercise.service'; import { Exercise } from 'app/entities/exercise.model'; import { SortService } from 'app/shared/service/sort.service'; import { Exam } from 'app/entities/exam/exam.model'; import { ExamManagementService } from 'app/exam/manage/exam-management.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { RouterLink } from '@angular/router'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; @Component({ selector: 'jhi-upcoming-exams-and-exercises', templateUrl: './upcoming-exams-and-exercises.component.html', styles: ['.table {table-layout: fixed}'], + imports: [TranslateDirective, RouterLink, ArtemisDatePipe], }) export class UpcomingExamsAndExercisesComponent implements OnInit { + private exerciseService = inject(ExerciseService); + private examManagementService = inject(ExamManagementService); + private sortService = inject(SortService); + upcomingExercises: Exercise[] = []; upcomingExams: Exam[] = []; predicate: string; reverse: boolean; - constructor( - private exerciseService: ExerciseService, - private examManagementService: ExamManagementService, - private sortService: SortService, - ) {} - ngOnInit(): void { this.exerciseService.getUpcomingExercises().subscribe((res: ExerciseEntityArrayResponseType) => { this.upcomingExercises = res.body ?? []; diff --git a/src/main/webapp/app/admin/user-management/delete-users-button.component.ts b/src/main/webapp/app/admin/user-management/delete-users-button.component.ts index 1a4bfdd17927..1ef962c85b3d 100644 --- a/src/main/webapp/app/admin/user-management/delete-users-button.component.ts +++ b/src/main/webapp/app/admin/user-management/delete-users-button.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Output, WritableSignal, signal } from '@angular/core'; +import { Component, EventEmitter, Output, WritableSignal, inject, signal } from '@angular/core'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { faEraser } from '@fortawesome/free-solid-svg-icons'; import { ArtemisSharedModule } from 'app/shared/shared.module'; @@ -16,12 +16,15 @@ import { ArtemisSharedComponentModule } from 'app/shared/components/shared-compo * that shows a list of the logins of the users which will be deleted. */ @Component({ - standalone: true, selector: 'jhi-delete-users-button', templateUrl: './delete-users-button.component.html', imports: [ArtemisSharedModule, ArtemisSharedComponentModule], }) export class DeleteUsersButtonComponent { + private adminUserService = inject(AdminUserService); + private alertService = inject(AlertService); + private deleteDialogService = inject(DeleteDialogService); + @Output() deletionCompleted = new EventEmitter<{ [key: string]: boolean }>(); users: WritableSignal = signal(undefined); @@ -33,12 +36,6 @@ export class DeleteUsersButtonComponent { faEraser = faEraser; protected readonly ButtonType = ButtonType; - constructor( - private adminUserService: AdminUserService, - private alertService: AlertService, - private deleteDialogService: DeleteDialogService, - ) {} - /** * Load the list of users to user confirmation and delete. */ diff --git a/src/main/webapp/app/admin/user-management/user-management-detail.component.ts b/src/main/webapp/app/admin/user-management/user-management-detail.component.ts index f1393613b9aa..c00a1b42f177 100644 --- a/src/main/webapp/app/admin/user-management/user-management-detail.component.ts +++ b/src/main/webapp/app/admin/user-management/user-management-detail.component.ts @@ -1,19 +1,24 @@ -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { Component, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink, RouterOutlet } from '@angular/router'; import { faWrench } from '@fortawesome/free-solid-svg-icons'; import { User } from 'app/core/user/user.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-user-management-detail', templateUrl: './user-management-detail.component.html', + imports: [TranslateDirective, RouterLink, FaIconComponent, RouterOutlet, ArtemisDatePipe, ArtemisTranslatePipe], }) export class UserManagementDetailComponent implements OnInit { + private route = inject(ActivatedRoute); + user: User; // Icons faWrench = faWrench; - constructor(private route: ActivatedRoute) {} - /** * Retrieve the user from the user management activated route data subscription * and get the user based on the login string diff --git a/src/main/webapp/app/admin/user-management/user-management-resolve.service.ts b/src/main/webapp/app/admin/user-management/user-management-resolve.service.ts index 41e76ccc9a75..a0e4dd9396e2 100644 --- a/src/main/webapp/app/admin/user-management/user-management-resolve.service.ts +++ b/src/main/webapp/app/admin/user-management/user-management-resolve.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { User } from 'app/core/user/user.model'; import { Observable, of } from 'rxjs'; @@ -6,7 +6,7 @@ import { AdminUserService } from 'app/core/user/admin-user.service'; @Injectable({ providedIn: 'root' }) export class UserManagementResolve implements Resolve { - constructor(private adminUserService: AdminUserService) {} + private adminUserService = inject(AdminUserService); /** * Resolve route to find the user before the route is activated diff --git a/src/main/webapp/app/admin/user-management/user-management-update.component.ts b/src/main/webapp/app/admin/user-management/user-management-update.component.ts index 2d7e318f9038..3ccd94670076 100644 --- a/src/main/webapp/app/admin/user-management/user-management-update.component.ts +++ b/src/main/webapp/app/admin/user-management/user-management-update.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { User } from 'app/core/user/user.model'; import { JhiLanguageHelper } from 'app/core/language/language.helper'; @@ -6,26 +6,64 @@ import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; import { OrganizationManagementService } from 'app/admin/organization-management/organization-management.service'; import { OrganizationSelectorComponent } from 'app/shared/organization-selector/organization-selector.component'; import { Organization } from 'app/entities/organization.model'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, USERNAME_MAX_LENGTH, USERNAME_MIN_LENGTH } from 'app/app.constants'; import { faBan, faSave, faTimes } from '@fortawesome/free-solid-svg-icons'; import { COMMA, ENTER, TAB } from '@angular/cdk/keycodes'; -import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; -import { MatChipInputEvent } from '@angular/material/chips'; -import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; +import { FormBuilder, FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; +import { MatChipGrid, MatChipInput, MatChipInputEvent, MatChipRemove, MatChipRow } from '@angular/material/chips'; +import { MatAutocomplete, MatAutocompleteSelectedEvent, MatAutocompleteTrigger } from '@angular/material/autocomplete'; import { AlertService, AlertType } from 'app/core/util/alert.service'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { AdminUserService } from 'app/core/user/admin-user.service'; import { Observable } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; import { CourseAdminService } from 'app/course/manage/course-admin.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { MatFormField } from '@angular/material/form-field'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { MatOption } from '@angular/material/core'; +import { AsyncPipe } from '@angular/common'; +import { FindLanguageFromKeyPipe } from 'app/shared/language/find-language-from-key.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-user-management-update', templateUrl: './user-management-update.component.html', styleUrls: ['./user-management-update.component.scss'], + imports: [ + FormsModule, + ReactiveFormsModule, + TranslateDirective, + NgbTooltip, + HelpIconComponent, + MatFormField, + MatChipGrid, + MatChipRow, + MatChipRemove, + FaIconComponent, + MatAutocompleteTrigger, + MatChipInput, + MatAutocomplete, + MatOption, + AsyncPipe, + FindLanguageFromKeyPipe, + ArtemisTranslatePipe, + ], }) export class UserManagementUpdateComponent implements OnInit { + private languageHelper = inject(JhiLanguageHelper); + private userService = inject(AdminUserService); + private courseAdminService = inject(CourseAdminService); + private route = inject(ActivatedRoute); + private organizationService = inject(OrganizationManagementService); + private modalService = inject(NgbModal); + private navigationUtilService = inject(ArtemisNavigationUtilService); + private alertService = inject(AlertService); + private profileService = inject(ProfileService); + private fb = inject(FormBuilder); + readonly USERNAME_MIN_LENGTH = USERNAME_MIN_LENGTH; readonly USERNAME_MAX_LENGTH = USERNAME_MAX_LENGTH; readonly PASSWORD_MIN_LENGTH = PASSWORD_MIN_LENGTH; @@ -55,19 +93,6 @@ export class UserManagementUpdateComponent implements OnInit { private oldLogin?: string; private isJenkins: boolean; - constructor( - private languageHelper: JhiLanguageHelper, - private userService: AdminUserService, - private courseAdminService: CourseAdminService, - private route: ActivatedRoute, - private organizationService: OrganizationManagementService, - private modalService: NgbModal, - private navigationUtilService: ArtemisNavigationUtilService, - private alertService: AlertService, - private profileService: ProfileService, - private fb: FormBuilder, - ) {} - /** * Enable subscriptions to retrieve the user based on the activated route, all authorities and all languages on init */ diff --git a/src/main/webapp/app/admin/user-management/user-management.component.ts b/src/main/webapp/app/admin/user-management/user-management.component.ts index f7870f5369cf..56e4c06bf76f 100644 --- a/src/main/webapp/app/admin/user-management/user-management.component.ts +++ b/src/main/webapp/app/admin/user-management/user-management.component.ts @@ -1,6 +1,6 @@ -import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; +import { Component, OnDestroy, OnInit, TemplateRef, ViewChild, inject } from '@angular/core'; import { HttpErrorResponse, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { Subject, Subscription, combineLatest } from 'rxjs'; import { onError } from 'app/shared/util/global.utils'; import { User } from 'app/core/user/user.model'; @@ -8,15 +8,28 @@ import { AccountService } from 'app/core/auth/account.service'; import { AlertService } from 'app/core/util/alert.service'; import { SortingOrder } from 'app/shared/table/pageable-table'; import { switchMap, tap } from 'rxjs/operators'; -import { FormControl, FormGroup } from '@angular/forms'; +import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { EventManager } from 'app/core/util/event-manager.service'; import { ASC, DESC, ITEMS_PER_PAGE, SORT } from 'app/shared/constants/pagination.constants'; import { faEye, faFilter, faPlus, faSort, faTimes, faWrench } from '@fortawesome/free-solid-svg-icons'; import { LocalStorageService } from 'ngx-webstorage'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbHighlight, NgbModal, NgbPagination } from '@ng-bootstrap/ng-bootstrap'; import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { AdminUserService } from 'app/core/user/admin-user.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { UsersImportButtonComponent } from 'app/shared/user-import/users-import-button.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { DeleteUsersButtonComponent } from './delete-users-button.component'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { NgClass } from '@angular/common'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { ProfilePictureComponent } from 'app/shared/profile-picture/profile-picture.component'; +import { ItemCountComponent } from 'app/shared/pagination/item-count.component'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export class UserFilter { authorityFilter: Set = new Set(); @@ -86,8 +99,38 @@ type Filter = typeof AuthorityFilter | typeof OriginFilter | typeof StatusFilter selector: 'jhi-user-management', templateUrl: './user-management.component.html', styleUrls: ['./user-management.component.scss'], + imports: [ + TranslateDirective, + UsersImportButtonComponent, + RouterLink, + FaIconComponent, + FormsModule, + ReactiveFormsModule, + DeleteUsersButtonComponent, + DeleteButtonDirective, + NgClass, + SortDirective, + SortByDirective, + ProfilePictureComponent, + NgbHighlight, + ItemCountComponent, + NgbPagination, + HelpIconComponent, + ArtemisDatePipe, + ArtemisTranslatePipe, + ], }) export class UserManagementComponent implements OnInit, OnDestroy { + private adminUserService = inject(AdminUserService); + private alertService = inject(AlertService); + private accountService = inject(AccountService); + private activatedRoute = inject(ActivatedRoute); + private router = inject(Router); + private eventManager = inject(EventManager); + private localStorage = inject(LocalStorageService); + private modalService = inject(NgbModal); + private profileService = inject(ProfileService); + @ViewChild('filterModal') filterModal: TemplateRef; search = new Subject(); @@ -127,18 +170,6 @@ export class UserManagementComponent implements OnInit, OnDestroy { readonly medium = ButtonSize.MEDIUM; readonly ButtonType = ButtonType; - constructor( - private adminUserService: AdminUserService, - private alertService: AlertService, - private accountService: AccountService, - private activatedRoute: ActivatedRoute, - private router: Router, - private eventManager: EventManager, - private localStorage: LocalStorageService, - private modalService: NgbModal, - private profileService: ProfileService, - ) {} - /** * Retrieves the current user and calls the {@link loadAll} and {@link registerChangeInUsers} methods on init */ diff --git a/src/main/webapp/app/admin/user-management/user-management.route.ts b/src/main/webapp/app/admin/user-management/user-management.route.ts index df2178c4a68b..8c0bec4dd6c6 100644 --- a/src/main/webapp/app/admin/user-management/user-management.route.ts +++ b/src/main/webapp/app/admin/user-management/user-management.route.ts @@ -1,13 +1,11 @@ import { Route } from '@angular/router'; -import { UserManagementDetailComponent } from 'app/admin/user-management/user-management-detail.component'; -import { UserManagementComponent } from 'app/admin/user-management/user-management.component'; -import { UserManagementUpdateComponent } from 'app/admin/user-management/user-management-update.component'; + import { UserManagementResolve } from 'app/admin/user-management/user-management-resolve.service'; export const userManagementRoute: Route[] = [ { path: 'user-management', - component: UserManagementComponent, + loadComponent: () => import('app/admin/user-management/user-management.component').then((m) => m.UserManagementComponent), data: { pageTitle: 'artemisApp.userManagement.home.title', defaultSort: 'id,asc', @@ -22,7 +20,7 @@ export const userManagementRoute: Route[] = [ children: [ { path: 'new', - component: UserManagementUpdateComponent, + loadComponent: () => import('app/admin/user-management/user-management-update.component').then((m) => m.UserManagementUpdateComponent), resolve: { user: UserManagementResolve, }, @@ -32,7 +30,7 @@ export const userManagementRoute: Route[] = [ }, { path: ':login', - component: UserManagementDetailComponent, + loadComponent: () => import('app/admin/user-management/user-management-detail.component').then((m) => m.UserManagementDetailComponent), resolve: { user: UserManagementResolve, }, @@ -49,7 +47,7 @@ export const userManagementRoute: Route[] = [ children: [ { path: 'edit', - component: UserManagementUpdateComponent, + loadComponent: () => import('app/admin/user-management/user-management-update.component').then((m) => m.UserManagementUpdateComponent), data: { pageTitle: 'artemisApp.userManagement.home.editLabel', }, diff --git a/src/main/webapp/app/app-routing.module.ts b/src/main/webapp/app/app-routing.module.ts deleted file mode 100644 index 607fb3a3f6b8..000000000000 --- a/src/main/webapp/app/app-routing.module.ts +++ /dev/null @@ -1,198 +0,0 @@ -import { NgModule } from '@angular/core'; -import { RouterModule, Routes } from '@angular/router'; -import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { Authority } from 'app/shared/constants/authority.constants'; -import { navbarRoute } from 'app/shared/layouts/navbar/navbar.route'; -import { errorRoute } from 'app/shared/layouts/error/error.route'; -import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; - -const LAYOUT_ROUTES: Routes = [navbarRoute, ...errorRoute]; - -@NgModule({ - imports: [ - RouterModule.forRoot( - [ - ...LAYOUT_ROUTES, - { - path: '', - loadComponent: () => import('./home/home.component').then((m) => m.HomeComponent), - data: { - pageTitle: 'home.title', - }, - }, - { - path: 'admin', - loadChildren: () => import('./admin/admin.module').then((m) => m.ArtemisAdminModule), - }, - { - path: 'privacy', - loadChildren: () => import('./core/legal/privacy.module').then((m) => m.ArtemisPrivacyModule), - }, - { - path: 'imprint', - loadChildren: () => import('./core/legal/imprint.module').then((m) => m.ArtemisImprintModule), - }, - { - path: 'about', - loadChildren: () => import('./core/about-us/artemis-about-us.module').then((module) => module.ArtemisAboutUsModule), - }, - // ===== TEAM ==== - { - path: 'course-management/:courseId/exercises/:exerciseId/teams', - loadChildren: () => import('./exercises/shared/team/team.module').then((m) => m.ArtemisTeamModule), - }, - { - path: 'courses/:courseId/exercises/:exerciseId/teams', - loadChildren: () => import('./exercises/shared/team/team.module').then((m) => m.ArtemisTeamModule), - }, - // ===== ACCOUNT ==== - { - path: 'account', - children: [ - { - path: 'activate', - pathMatch: 'full', - loadComponent: () => import('./account/activate/activate.component').then((m) => m.ActivateComponent), - data: { - pageTitle: 'activate.title', - }, - }, - { - path: 'password', - pathMatch: 'full', - loadComponent: () => import('./account/password/password.component').then((m) => m.PasswordComponent), - data: { - authorities: [Authority.USER], - pageTitle: 'global.menu.account.password', - }, - canActivate: [UserRouteAccessService], - }, - { - path: 'reset/finish', - pathMatch: 'full', - loadComponent: () => import('./account/password-reset/finish/password-reset-finish.component').then((m) => m.PasswordResetFinishComponent), - data: { - pageTitle: 'global.menu.account.password', - }, - }, - { - path: 'reset/request', - pathMatch: 'full', - loadComponent: () => import('./account/password-reset/init/password-reset-init.component').then((m) => m.PasswordResetInitComponent), - data: { - pageTitle: 'global.menu.account.password', - }, - }, - { - path: 'register', - pathMatch: 'full', - loadComponent: () => import('./account/register/register.component').then((m) => m.RegisterComponent), - data: { - pageTitle: 'register.title', - }, - }, - { - path: 'settings', - pathMatch: 'full', - loadComponent: () => import('./account/settings/settings.component').then((m) => m.SettingsComponent), - data: { - authorities: [Authority.USER], - pageTitle: 'global.menu.account.settings', - }, - canActivate: [UserRouteAccessService], - }, - ], - }, - // ===== COURSE MANAGEMENT ===== - { - path: 'course-management', - loadChildren: () => import('./course/manage/course-management.module').then((m) => m.ArtemisCourseManagementModule), - }, - { - path: 'course-management/:courseId/programming-exercises/:exerciseId/code-editor', - loadChildren: () => import('./exercises/programming/manage/code-editor/code-editor-management.module').then((m) => m.ArtemisCodeEditorManagementModule), - }, - { - path: 'course-management/:courseId/text-exercises/:exerciseId', - loadChildren: () => import('./exercises/text/assess/text-submission-assessment.module').then((m) => m.ArtemisTextSubmissionAssessmentModule), - }, - { - path: 'course-management/:courseId/text-exercises/:exerciseId/example-submissions/:exampleSubmissionId', - loadChildren: () => import('./exercises/text/manage/example-text-submission/example-text-submission.module').then((m) => m.ArtemisExampleTextSubmissionModule), - }, - { - path: 'course-management/:courseId/programming-exercises/:exerciseId', - loadChildren: () => - import('./exercises/programming/manage/programming-exercise-management-routing.module').then((m) => m.ArtemisProgrammingExerciseManagementRoutingModule), - }, - { - path: 'courses', - loadChildren: () => import('./overview/courses.module').then((m) => m.ArtemisCoursesModule), - }, - { - path: 'course-management/:courseId/lectures/:lectureId/attachments/:attachmentId', - pathMatch: 'full', - loadComponent: () => import('./lecture/pdf-preview/pdf-preview.component').then((m) => m.PdfPreviewComponent), - }, - // ===== GRADING SYSTEM ===== - { - path: 'courses/:courseId/grading-system', - loadChildren: () => import('./grading-system/grading-system.module').then((m) => m.GradingSystemModule), - }, - - { - path: 'courses/:courseId/exercises/:exerciseId/problem-statement', - pathMatch: 'full', - loadComponent: () => import('./overview/exercise-details/problem-statement/problem-statement.component').then((m) => m.ProblemStatementComponent), - }, - { - pathMatch: 'full', - path: 'courses/:courseId/exercises/:exerciseId/problem-statement/:participationId', - loadComponent: () => import('./overview/exercise-details/problem-statement/problem-statement.component').then((m) => m.ProblemStatementComponent), - }, - { - path: 'courses/:courseId/exercises/:exerciseId/participations/:participationId/results/:resultId/feedback', - pathMatch: 'full', - loadComponent: () => import('./exercises/shared/feedback/standalone-feedback/standalone-feedback.component').then((m) => m.StandaloneFeedbackComponent), - }, - - // ===== EXAM ===== - { - path: 'course-management/:courseId/exams', - loadChildren: () => import('./exam/manage/exam-management.module').then((m) => m.ArtemisExamManagementModule), - }, - { - path: 'courses/:courseId/exams/:examId/grading-system', - loadChildren: () => import('./grading-system/grading-system.module').then((m) => m.GradingSystemModule), - }, - { - path: 'courses/:courseId/exams/:examId/exercises/:exerciseId/repository', - loadChildren: () => - import('./exercises/programming/participate/programming-repository-routing.module').then((m) => m.ArtemisProgrammingRepositoryRoutingModule), - }, - { - path: 'features', - loadChildren: () => import('./feature-overview/feature-overview.module').then((m) => m.FeatureOverviewModule), - }, - { - path: 'lti', - loadChildren: () => import('./lti/lti.module').then((m) => m.ArtemisLtiModule), - }, - { - path: 'about-iris', - pathMatch: 'full', - loadComponent: () => import('./iris/about-iris/about-iris.component').then((m) => m.AboutIrisComponent), - data: { - pageTitle: 'artemisApp.exerciseChatbot.title', - }, - }, - ], - { enableTracing: false, onSameUrlNavigation: 'reload' }, - ), - ], - exports: [RouterModule], -}) -export class ArtemisAppRoutingModule { - // Ensure the service is initialized before any routing happens - constructor(private _: ArtemisNavigationUtilService) {} -} diff --git a/src/main/webapp/app/shared/layouts/main/main.component.html b/src/main/webapp/app/app.component.html similarity index 100% rename from src/main/webapp/app/shared/layouts/main/main.component.html rename to src/main/webapp/app/app.component.html diff --git a/src/main/webapp/app/shared/layouts/main/main.component.scss b/src/main/webapp/app/app.component.scss similarity index 100% rename from src/main/webapp/app/shared/layouts/main/main.component.scss rename to src/main/webapp/app/app.component.scss diff --git a/src/main/webapp/app/shared/layouts/main/main.component.ts b/src/main/webapp/app/app.component.ts similarity index 76% rename from src/main/webapp/app/shared/layouts/main/main.component.ts rename to src/main/webapp/app/app.component.ts index 299eebd09926..c09f0685cb86 100644 --- a/src/main/webapp/app/shared/layouts/main/main.component.ts +++ b/src/main/webapp/app/app.component.ts @@ -1,32 +1,49 @@ -import { Component, Inject, OnDestroy, OnInit, Renderer2 } from '@angular/core'; -import { ActivatedRouteSnapshot, NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router'; +import { Component, OnDestroy, OnInit, Renderer2, inject } from '@angular/core'; +import { ActivatedRouteSnapshot, NavigationEnd, NavigationError, NavigationStart, Router, RouterOutlet } from '@angular/router'; import { JhiLanguageHelper } from 'app/core/language/language.helper'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { SentryErrorHandler } from 'app/core/sentry/sentry.error-handler'; import { ThemeService } from 'app/core/theme/theme.service'; -import { DOCUMENT } from '@angular/common'; +import { DOCUMENT, NgClass, NgStyle } from '@angular/common'; import { Subscription } from 'rxjs'; import { ExamParticipationService } from 'app/exam/participate/exam-participation.service'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { LtiService } from 'app/shared/service/lti.service'; +import { AlertOverlayComponent } from './shared/alert/alert-overlay.component'; +import { CdkScrollable } from '@angular/cdk/scrolling'; +import { PageRibbonComponent } from './shared/layouts/profiles/page-ribbon.component'; +import { NotificationPopupComponent } from './shared/notification/notification-popup/notification-popup.component'; +import { FooterComponent } from './shared/layouts/footer/footer.component'; @Component({ - selector: 'jhi-main', - templateUrl: './main.component.html', - styleUrls: ['./main.component.scss'], + selector: 'jhi-app', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'], + imports: [AlertOverlayComponent, CdkScrollable, NgClass, NgStyle, PageRibbonComponent, RouterOutlet, NotificationPopupComponent, FooterComponent], }) -export class JhiMainComponent implements OnInit, OnDestroy { +export class AppComponent implements OnInit, OnDestroy { + private jhiLanguageHelper = inject(JhiLanguageHelper); + private router = inject(Router); + private profileService = inject(ProfileService); + private examParticipationService = inject(ExamParticipationService); + private sentryErrorHandler = inject(SentryErrorHandler); + private themeService = inject(ThemeService); + private document = inject(DOCUMENT); + private renderer = inject(Renderer2); + private courseService = inject(CourseManagementService); + private ltiService = inject(LtiService); + + private profileSubscription: Subscription; + private examStartedSubscription: Subscription; + private courseOverviewSubscription: Subscription; + private testRunSubscription: Subscription; + private ltiSubscription: Subscription; /** * If the footer and header should be shown. * Only set to false on specific pages designed for the native Android and iOS applications where the footer and header are not wanted. * The decision on whether to show the skeleton or not for a specific route is defined in shouldShowSkeleton. */ - public showSkeleton = true; - profileSubscription: Subscription; - examStartedSubscription: Subscription; - courseOverviewSubscription: Subscription; - testRunSubscription: Subscription; - ltiSubscription: Subscription; + showSkeleton = true; isProduction = true; isTestServer = false; isExamStarted = false; @@ -34,19 +51,7 @@ export class JhiMainComponent implements OnInit, OnDestroy { isCourseOverview = false; isShownViaLti = false; - constructor( - private jhiLanguageHelper: JhiLanguageHelper, - private router: Router, - private profileService: ProfileService, - private examParticipationService: ExamParticipationService, - private sentryErrorHandler: SentryErrorHandler, - private themeService: ThemeService, - @Inject(DOCUMENT) - private document: Document, - private renderer: Renderer2, - private courseService: CourseManagementService, - private ltiService: LtiService, - ) { + constructor() { this.setupErrorHandling().then(undefined); } diff --git a/src/main/webapp/app/app.config.ts b/src/main/webapp/app/app.config.ts new file mode 100644 index 000000000000..90ee4be97e9f --- /dev/null +++ b/src/main/webapp/app/app.config.ts @@ -0,0 +1,128 @@ +import './polyfills'; +import 'app/shared/util/array.extension'; +import 'app/shared/util/map.extension'; +import 'app/shared/util/string.extension'; +import 'app/core/config/dayjs'; +import { ScrollingModule } from '@angular/cdk/scrolling'; +import { DatePipe } from '@angular/common'; +import { HTTP_INTERCEPTORS, HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; +import { ApplicationConfig, ErrorHandler, LOCALE_ID, importProvidersFrom, inject, provideAppInitializer } from '@angular/core'; +import { BrowserModule, Title } from '@angular/platform-browser'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { Router, RouterModule, provideRouter, withRouterConfig } from '@angular/router'; +import { ServiceWorkerModule } from '@angular/service-worker'; +import { NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap'; +import { MissingTranslationHandler, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import * as Sentry from '@sentry/angular'; +import { TraceService } from '@sentry/angular'; +import routes from 'app/app.routes'; +import { NgbDateDayjsAdapter } from 'app/core/config/datepicker-adapter'; +import { missingTranslationHandler, translatePartialLoader } from 'app/core/config/translation.config'; +import { ArtemisVersionInterceptor, WINDOW_INJECTOR_TOKEN } from 'app/core/interceptor/artemis-version.interceptor'; +import { AuthExpiredInterceptor } from 'app/core/interceptor/auth-expired.interceptor'; +import { BrowserFingerprintInterceptor } from 'app/core/interceptor/browser-fingerprint.interceptor.service'; +import { ErrorHandlerInterceptor } from 'app/core/interceptor/errorhandler.interceptor'; +import { NotificationInterceptor } from 'app/core/interceptor/notification.interceptor'; +import { SentryErrorHandler } from 'app/core/sentry/sentry.error-handler'; +import { GuidedTourModule } from 'app/guided-tour/guided-tour.module'; +import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; +import { LoadingNotificationInterceptor } from 'app/shared/notification/loading-notification/loading-notification.interceptor'; +import { OrionConnectorService } from 'app/shared/orion/orion-connector.service'; +import { ArtemisSharedModule } from 'app/shared/shared.module'; +import { UserSettingsModule } from 'app/shared/user-settings/user-settings.module'; +import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; +import { provideNgxWebstorage, withLocalStorage, withNgxWebstorageConfig, withSessionStorage } from 'ngx-webstorage'; + +export function initOrionConnector(connector: OrionConnectorService) { + return () => OrionConnectorService.initConnector(connector); +} + +export const appConfig: ApplicationConfig = { + providers: [ + importProvidersFrom( + // TODO: we should exclude modules here in the future + ArtemisSharedComponentModule, + ArtemisSharedModule, + BrowserAnimationsModule, + BrowserModule, + GuidedTourModule, + RouterModule, + ScrollingModule, + UserSettingsModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useFactory: translatePartialLoader, + deps: [HttpClient], + }, + missingTranslationHandler: { + provide: MissingTranslationHandler, + useFactory: missingTranslationHandler, + }, + }), + ), + + // TODO: we should add withComponentInputBinding here + // this would set non-route inputs to undefined, which not all components can handle, currently + // see https://angular.dev/api/router/withComponentInputBinding?tab=usage-notes + // provideRouter(routes, withComponentInputBinding(), withRouterConfig({ onSameUrlNavigation: 'reload' })), + provideRouter(routes, withRouterConfig({ onSameUrlNavigation: 'reload' })), + // This enables service worker (PWA) + importProvidersFrom(ServiceWorkerModule.register('ngsw-worker.js', { enabled: true })), + provideHttpClient(withInterceptorsFromDi()), + provideNgxWebstorage(withNgxWebstorageConfig({ prefix: 'jhi', separator: '-' }), withLocalStorage(), withSessionStorage()), + Title, + { provide: LOCALE_ID, useValue: 'en' }, + { provide: NgbDateAdapter, useClass: NgbDateDayjsAdapter }, + { provide: Sentry.TraceService, deps: [Router] }, + { provide: ErrorHandler, useClass: SentryErrorHandler }, + { provide: WINDOW_INJECTOR_TOKEN, useValue: window }, + DatePipe, + provideAppInitializer(() => { + inject(TraceService); + // Ensure the service is initialized before any routing happens + inject(ArtemisNavigationUtilService); + // Required, otherwise Orion will not work at all + initOrionConnector(inject(OrionConnectorService)); + }), + /** + * @description Interceptor declarations: + * Interceptors are located at 'blocks/interceptor/. + * All of them implement the HttpInterceptor interface. + * They can be used to modify API calls or trigger additional function calls. + * Most interceptors will transform the outgoing request before passing it to + * the next interceptor in the chain, by calling next.handle(transformedReq). + * Documentation: https://angular.io/api/common/http/HttpInterceptor + */ + { + provide: HTTP_INTERCEPTORS, + useClass: AuthExpiredInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: ErrorHandlerInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: BrowserFingerprintInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: NotificationInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: LoadingNotificationInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: ArtemisVersionInterceptor, + multi: true, + }, + ], +}; diff --git a/src/main/webapp/app/app.main.ts b/src/main/webapp/app/app.main.ts index 1c2b479d3a8a..cf1c49919310 100644 --- a/src/main/webapp/app/app.main.ts +++ b/src/main/webapp/app/app.main.ts @@ -1,16 +1,42 @@ -import './polyfills'; -import 'app/shared/util/array.extension'; -import 'app/shared/util/map.extension'; -import 'app/shared/util/string.extension'; -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; -import { ProdConfig } from './core/config/prod.config'; -import { ArtemisAppModule } from './app.module'; +import { bootstrapApplication } from '@angular/platform-browser'; +import { appConfig } from 'app/app.config'; import { MonacoConfig } from 'app/core/config/monaco.config'; +import { ProdConfig } from 'app/core/config/prod.config'; +import { JhiLanguageHelper } from 'app/core/language/language.helper'; +import { artemisIconPack } from 'app/icons/icons'; +import { AppComponent } from './app.component'; +import { FaIconLibrary } from '@fortawesome/angular-fontawesome'; +import isMobile from 'ismobilejs-es5'; +import { registerLocaleData } from '@angular/common'; +import locale from '@angular/common/locales/en'; +import dayjs from 'dayjs/esm'; +import { NgbDatepickerConfig, NgbTooltipConfig } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { SessionStorageService } from 'ngx-webstorage'; ProdConfig(); MonacoConfig(); -platformBrowserDynamic() - .bootstrapModule(ArtemisAppModule, { preserveWhitespaces: true }) - .then(() => {}) +bootstrapApplication(AppComponent, appConfig) + .then((app) => { + // TODO: potentially move this code into AppComponent + const library = app.injector.get(FaIconLibrary); + library.addIconPacks(artemisIconPack); + const dpConfig = app.injector.get(NgbDatepickerConfig); + const tooltipConfig = app.injector.get(NgbTooltipConfig); + const translateService = app.injector.get(TranslateService); + const languageHelper = app.injector.get(JhiLanguageHelper); + const sessionStorageService = app.injector.get(SessionStorageService); + + // Perform initialization logic + registerLocaleData(locale); + dpConfig.minDate = { year: dayjs().subtract(100, 'year').year(), month: 1, day: 1 }; + translateService.setDefaultLang('en'); + const languageKey = sessionStorageService.retrieve('locale') || languageHelper.determinePreferredLanguage(); + translateService.use(languageKey); + tooltipConfig.container = 'body'; + if (isMobile(window.navigator.userAgent).any ?? false) { + tooltipConfig.disableTooltip = true; + } + }) .catch((err) => console.error(err)); diff --git a/src/main/webapp/app/app.module.ts b/src/main/webapp/app/app.module.ts deleted file mode 100644 index 1e43beff4fc1..000000000000 --- a/src/main/webapp/app/app.module.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; -import { ServiceWorkerModule } from '@angular/service-worker'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { ArtemisSystemNotificationModule } from 'app/shared/notification/system-notification/system-notification.module'; -import { NavbarComponent } from 'app/shared/layouts/navbar/navbar.component'; -import { NotificationSidebarComponent } from 'app/shared/notification/notification-sidebar/notification-sidebar.component'; -import { PageRibbonComponent } from 'app/shared/layouts/profiles/page-ribbon.component'; -import { ArtemisHeaderExercisePageWithDetailsModule } from 'app/exercises/shared/exercise-headers/exercise-headers.module'; -import { SystemNotificationComponent } from 'app/shared/notification/system-notification/system-notification.component'; -import { ArtemisAppRoutingModule } from 'app/app-routing.module'; -import { JhiMainComponent } from 'app/shared/layouts/main/main.component'; -import { ArtemisSharedModule } from 'app/shared/shared.module'; -import { FooterComponent } from 'app/shared/layouts/footer/footer.component'; -import { ActiveMenuDirective } from 'app/shared/layouts/navbar/active-menu.directive'; -import { ErrorComponent } from 'app/shared/layouts/error/error.component'; -import { ArtemisCoreModule } from 'app/core/core.module'; -import { GuidedTourModule } from 'app/guided-tour/guided-tour.module'; -import { ArtemisComplaintsModule } from 'app/complaints/complaints.module'; -import { OrionOutdatedComponent } from 'app/shared/orion/outdated-plugin-warning/orion-outdated.component'; -import { LoadingNotificationComponent } from 'app/shared/notification/loading-notification/loading-notification.component'; -import { NotificationPopupComponent } from 'app/shared/notification/notification-popup/notification-popup.component'; -import { UserSettingsModule } from 'app/shared/user-settings/user-settings.module'; -import { ThemeSwitchComponent } from 'app/core/theme/theme-switch.component'; -import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; -import { FaIconLibrary } from '@fortawesome/angular-fontawesome'; -import { artemisIconPack } from 'src/main/webapp/content/icons/icons'; -import { ScrollingModule } from '@angular/cdk/scrolling'; - -// NOTE: this module should only include the most important modules for normal users, all course management, admin and account functionality should be lazy loaded if possible -@NgModule({ - imports: [ - BrowserModule, - BrowserAnimationsModule, - // This enables service worker (PWA) - ServiceWorkerModule.register('ngsw-worker.js', { enabled: true }), - ArtemisSharedModule, - ArtemisCoreModule, - ArtemisAppRoutingModule, - GuidedTourModule, - ArtemisSystemNotificationModule, - ArtemisComplaintsModule, - ArtemisHeaderExercisePageWithDetailsModule, - UserSettingsModule, - ThemeSwitchComponent, - ArtemisSharedComponentModule, - ScrollingModule, - ], - declarations: [ - JhiMainComponent, - NavbarComponent, - ErrorComponent, - OrionOutdatedComponent, - PageRibbonComponent, - ActiveMenuDirective, - FooterComponent, - NotificationPopupComponent, - NotificationSidebarComponent, - SystemNotificationComponent, - LoadingNotificationComponent, - ], - bootstrap: [JhiMainComponent], -}) -export class ArtemisAppModule { - constructor(library: FaIconLibrary) { - library.addIconPacks(artemisIconPack); - } -} diff --git a/src/main/webapp/app/app.routes.ts b/src/main/webapp/app/app.routes.ts new file mode 100644 index 000000000000..214a653bf01c --- /dev/null +++ b/src/main/webapp/app/app.routes.ts @@ -0,0 +1,185 @@ +import { Routes } from '@angular/router'; +import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; +import { Authority } from 'app/shared/constants/authority.constants'; +import { navbarRoute } from 'app/shared/layouts/navbar/navbar.route'; +import { errorRoute } from 'app/shared/layouts/error/error.route'; + +const LAYOUT_ROUTES: Routes = [navbarRoute, ...errorRoute]; + +const routes: Routes = [ + ...LAYOUT_ROUTES, + { + path: '', + loadComponent: () => import('./home/home.component').then((m) => m.HomeComponent), + data: { + pageTitle: 'home.title', + }, + }, + { + path: 'admin', + loadChildren: () => import('./admin/admin.module').then((m) => m.ArtemisAdminModule), + }, + { + path: 'privacy', + loadChildren: () => import('./core/legal/privacy.module').then((m) => m.ArtemisPrivacyModule), + }, + { + path: 'imprint', + loadChildren: () => import('./core/legal/imprint.module').then((m) => m.ArtemisImprintModule), + }, + { + path: 'about', + loadChildren: () => import('./core/about-us/artemis-about-us.module').then((module) => module.ArtemisAboutUsModule), + }, + // ===== TEAM ==== + { + path: 'course-management/:courseId/exercises/:exerciseId/teams', + loadChildren: () => import('./exercises/shared/team/team.module').then((m) => m.ArtemisTeamModule), + }, + { + path: 'courses/:courseId/exercises/:exerciseId/teams', + loadChildren: () => import('./exercises/shared/team/team.module').then((m) => m.ArtemisTeamModule), + }, + // ===== ACCOUNT ==== + { + path: 'account', + children: [ + { + path: 'activate', + pathMatch: 'full', + loadComponent: () => import('./account/activate/activate.component').then((m) => m.ActivateComponent), + data: { + pageTitle: 'activate.title', + }, + }, + { + path: 'password', + pathMatch: 'full', + loadComponent: () => import('./account/password/password.component').then((m) => m.PasswordComponent), + data: { + authorities: [Authority.USER], + pageTitle: 'global.menu.account.password', + }, + canActivate: [UserRouteAccessService], + }, + { + path: 'reset/finish', + pathMatch: 'full', + loadComponent: () => import('./account/password-reset/finish/password-reset-finish.component').then((m) => m.PasswordResetFinishComponent), + data: { + pageTitle: 'global.menu.account.password', + }, + }, + { + path: 'reset/request', + pathMatch: 'full', + loadComponent: () => import('./account/password-reset/init/password-reset-init.component').then((m) => m.PasswordResetInitComponent), + data: { + pageTitle: 'global.menu.account.password', + }, + }, + { + path: 'register', + pathMatch: 'full', + loadComponent: () => import('./account/register/register.component').then((m) => m.RegisterComponent), + data: { + pageTitle: 'register.title', + }, + }, + { + path: 'settings', + pathMatch: 'full', + loadComponent: () => import('./account/settings/settings.component').then((m) => m.SettingsComponent), + data: { + authorities: [Authority.USER], + pageTitle: 'global.menu.account.settings', + }, + canActivate: [UserRouteAccessService], + }, + ], + }, + // ===== COURSE MANAGEMENT ===== + { + path: 'course-management', + loadChildren: () => import('./course/manage/course-management.module').then((m) => m.ArtemisCourseManagementModule), + }, + { + path: 'course-management/:courseId/programming-exercises/:exerciseId/code-editor', + loadChildren: () => import('./exercises/programming/manage/code-editor/code-editor-management.module').then((m) => m.ArtemisCodeEditorManagementModule), + }, + { + path: 'course-management/:courseId/text-exercises/:exerciseId', + loadChildren: () => import('./exercises/text/assess/text-submission-assessment.module').then((m) => m.ArtemisTextSubmissionAssessmentModule), + }, + { + path: 'course-management/:courseId/text-exercises/:exerciseId/example-submissions/:exampleSubmissionId', + loadChildren: () => import('./exercises/text/manage/example-text-submission/example-text-submission.module').then((m) => m.ArtemisExampleTextSubmissionModule), + }, + { + path: 'course-management/:courseId/programming-exercises/:exerciseId', + loadChildren: () => + import('./exercises/programming/manage/programming-exercise-management-routing.module').then((m) => m.ArtemisProgrammingExerciseManagementRoutingModule), + }, + { + path: 'courses', + loadChildren: () => import('./overview/courses.module').then((m) => m.ArtemisCoursesModule), + }, + { + path: 'course-management/:courseId/lectures/:lectureId/attachments/:attachmentId', + pathMatch: 'full', + loadComponent: () => import('./lecture/pdf-preview/pdf-preview.component').then((m) => m.PdfPreviewComponent), + }, + // ===== GRADING SYSTEM ===== + { + path: 'courses/:courseId/grading-system', + loadChildren: () => import('./grading-system/grading-system.module').then((m) => m.GradingSystemModule), + }, + + { + path: 'courses/:courseId/exercises/:exerciseId/problem-statement', + pathMatch: 'full', + loadComponent: () => import('./overview/exercise-details/problem-statement/problem-statement.component').then((m) => m.ProblemStatementComponent), + }, + { + pathMatch: 'full', + path: 'courses/:courseId/exercises/:exerciseId/problem-statement/:participationId', + loadComponent: () => import('./overview/exercise-details/problem-statement/problem-statement.component').then((m) => m.ProblemStatementComponent), + }, + { + path: 'courses/:courseId/exercises/:exerciseId/participations/:participationId/results/:resultId/feedback', + pathMatch: 'full', + loadComponent: () => import('./exercises/shared/feedback/standalone-feedback/standalone-feedback.component').then((m) => m.StandaloneFeedbackComponent), + }, + + // ===== EXAM ===== + { + path: 'course-management/:courseId/exams', + loadChildren: () => import('./exam/manage/exam-management.module').then((m) => m.ArtemisExamManagementModule), + }, + { + path: 'courses/:courseId/exams/:examId/grading-system', + loadChildren: () => import('./grading-system/grading-system.module').then((m) => m.GradingSystemModule), + }, + { + path: 'courses/:courseId/exams/:examId/exercises/:exerciseId/repository', + loadChildren: () => import('./exercises/programming/participate/programming-repository-routing.module').then((m) => m.ArtemisProgrammingRepositoryRoutingModule), + }, + { + path: 'features', + loadChildren: () => import('./feature-overview/feature-overview.module').then((m) => m.FeatureOverviewModule), + }, + { + path: 'lti', + loadChildren: () => import('./lti/lti.module').then((m) => m.ArtemisLtiModule), + }, + { + path: 'about-iris', + pathMatch: 'full', + loadComponent: () => import('./iris/about-iris/about-iris.component').then((m) => m.AboutIrisComponent), + data: { + pageTitle: 'artemisApp.exerciseChatbot.title', + }, + }, +]; + +export default routes; diff --git a/src/main/webapp/app/assessment/assessment-complaint-alert/assessment-complaint-alert.component.ts b/src/main/webapp/app/assessment/assessment-complaint-alert/assessment-complaint-alert.component.ts index 96be65f50ded..55c048949f44 100644 --- a/src/main/webapp/app/assessment/assessment-complaint-alert/assessment-complaint-alert.component.ts +++ b/src/main/webapp/app/assessment/assessment-complaint-alert/assessment-complaint-alert.component.ts @@ -1,5 +1,6 @@ import { Component, Input } from '@angular/core'; import { Complaint, ComplaintType } from 'app/entities/complaint.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; /** * This shows an alert, notifying the assessor on possible complaints at the bottom of the page. @@ -8,6 +9,7 @@ import { Complaint, ComplaintType } from 'app/entities/complaint.model'; selector: 'jhi-assessment-complaint-alert', templateUrl: './assessment-complaint-alert.component.html', styleUrls: [], + imports: [TranslateDirective], }) export class AssessmentComplaintAlertComponent { ComplaintType = ComplaintType; diff --git a/src/main/webapp/app/assessment/assessment-header/assessment-header.component.ts b/src/main/webapp/app/assessment/assessment-header/assessment-header.component.ts index 6e6dc93aff16..a3a87c32d514 100644 --- a/src/main/webapp/app/assessment/assessment-header/assessment-header.component.ts +++ b/src/main/webapp/app/assessment/assessment-header/assessment-header.component.ts @@ -1,14 +1,19 @@ -import { Component, EventEmitter, HostListener, Input, Output } from '@angular/core'; +import { Component, EventEmitter, HostListener, Input, Output, inject } from '@angular/core'; import { Result } from 'app/entities/result.model'; import { Exercise, ExerciseType } from 'app/entities/exercise.model'; import { TextAssessmentAnalytics } from 'app/exercises/text/assess/analytics/text-assesment-analytics.service'; import { TextAssessmentEventType } from 'app/entities/text/text-assesment-event.model'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { ComplaintType } from 'app/entities/complaint.model'; import { AssessmentType } from 'app/entities/assessment-type.model'; import { TranslateService } from '@ngx-translate/core'; import { faSave, faSpinner } from '@fortawesome/free-solid-svg-icons'; import { faSquareCaretRight } from '@fortawesome/free-regular-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbAlert, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { AssessmentWarningComponent } from '../assessment-warning/assessment-warning.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; /** * The component is used in the shared assessment layout. @@ -20,8 +25,13 @@ import { faSquareCaretRight } from '@fortawesome/free-regular-svg-icons'; selector: 'jhi-assessment-header', templateUrl: './assessment-header.component.html', styleUrls: ['./assessment-header.component.scss'], + imports: [TranslateDirective, NgbAlert, NgbTooltip, FaIconComponent, RouterLink, AssessmentWarningComponent, ArtemisTranslatePipe], }) export class AssessmentHeaderComponent { + textAssessmentAnalytics = inject(TextAssessmentAnalytics); + protected route = inject(ActivatedRoute); + private translateService = inject(TranslateService); + @Input() isLoading: boolean; @Input() saveBusy: boolean; @Input() submitBusy: boolean; @@ -68,12 +78,8 @@ export class AssessmentHeaderComponent { this.highlightDifferencesChange.emit(this.highlightDifferences); } - constructor( - public textAssessmentAnalytics: TextAssessmentAnalytics, - protected route: ActivatedRoute, - private translateService: TranslateService, - ) { - textAssessmentAnalytics.setComponentRoute(route); + constructor() { + this.textAssessmentAnalytics.setComponentRoute(this.route); } get highlightDifferences() { diff --git a/src/main/webapp/app/assessment/assessment-instructions/assessment-instructions.module.ts b/src/main/webapp/app/assessment/assessment-instructions/assessment-instructions.module.ts index cbd75c22898e..94ccc9b6673c 100644 --- a/src/main/webapp/app/assessment/assessment-instructions/assessment-instructions.module.ts +++ b/src/main/webapp/app/assessment/assessment-instructions/assessment-instructions.module.ts @@ -23,8 +23,6 @@ import { OrionAssessmentInstructionsComponent } from 'app/orion/assessment/orion ArtemisAssessmentSharedModule, ArtemisSharedComponentModule, ArtemisMarkdownModule, - ], - declarations: [ ExpandableSectionComponent, AssessmentInstructionsComponent, OrionAssessmentInstructionsComponent, diff --git a/src/main/webapp/app/assessment/assessment-instructions/assessment-instructions/assessment-instructions.component.html b/src/main/webapp/app/assessment/assessment-instructions/assessment-instructions/assessment-instructions.component.html index 7f1b0410c943..6a46e7df1762 100644 --- a/src/main/webapp/app/assessment/assessment-instructions/assessment-instructions/assessment-instructions.component.html +++ b/src/main/webapp/app/assessment/assessment-instructions/assessment-instructions/assessment-instructions.component.html @@ -12,7 +12,9 @@ } } -

{{ exercise.title }}

+ + +

{{ exercise.title }}

@switch (exercise.type) { @case (ExerciseType.PROGRAMMING) { diff --git a/src/main/webapp/app/assessment/assessment-instructions/assessment-instructions/assessment-instructions.component.ts b/src/main/webapp/app/assessment/assessment-instructions/assessment-instructions/assessment-instructions.component.ts index d854c6f7ad58..846f4a774e8d 100644 --- a/src/main/webapp/app/assessment/assessment-instructions/assessment-instructions/assessment-instructions.component.ts +++ b/src/main/webapp/app/assessment/assessment-instructions/assessment-instructions/assessment-instructions.component.ts @@ -1,4 +1,4 @@ -import { Component, ContentChild, Input, TemplateRef } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { SafeHtml } from '@angular/platform-browser'; import { UMLDiagramType, UMLModel } from '@ls1intum/apollon'; import { ArtemisMarkdownService } from 'app/shared/markdown.service'; @@ -9,12 +9,32 @@ import { FileUploadExercise } from 'app/entities/file-upload-exercise.model'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { GradingCriterion } from 'app/exercises/shared/structured-grading-criterion/grading-criterion.model'; import { ProgrammingExerciseStudentParticipation } from 'app/entities/participation/programming-exercise-student-participation.model'; +import { ExpandableSectionComponent } from '../expandable-section/expandable-section.component'; +import { StructuredGradingInstructionsAssessmentLayoutComponent } from '../../structured-grading-instructions-assessment-layout/structured-grading-instructions-assessment-layout.component'; +import { ProgrammingExerciseInstructionComponent } from 'app/exercises/programming/shared/instructions-render/programming-exercise-instruction.component'; +import { SecureLinkDirective } from 'app/shared/http/secure-link.directive'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ModelingEditorComponent } from 'app/exercises/modeling/shared/modeling-editor.component'; @Component({ selector: 'jhi-assessment-instructions', templateUrl: './assessment-instructions.component.html', + imports: [ + ExpandableSectionComponent, + StructuredGradingInstructionsAssessmentLayoutComponent, + // TODO: the extension point for Orion does not work with Angular 19, we need to find a different solution + // ExtensionPointDirective, + ProgrammingExerciseInstructionComponent, + SecureLinkDirective, + ButtonComponent, + TranslateDirective, + ModelingEditorComponent, + ], }) export class AssessmentInstructionsComponent { + private markdownService = inject(ArtemisMarkdownService); + exercise: Exercise; programmingExercise?: ProgrammingExercise; problemStatement: SafeHtml; @@ -34,9 +54,8 @@ export class AssessmentInstructionsComponent { readonly ExerciseType = ExerciseType; // extension points, see shared/extension-point - @ContentChild('overrideTitle') overrideTitle: TemplateRef; - - constructor(private markdownService: ArtemisMarkdownService) {} + // TODO: the extension point for Orion does not work with Angular 19, we need to find a different solution + // @ContentChild('overrideTitle') overrideTitle: TemplateRef; // eslint-disable-next-line @angular-eslint/no-input-rename @Input('exercise') set exerciseInput(exercise: Exercise) { diff --git a/src/main/webapp/app/assessment/assessment-instructions/collapsable-assessment-instructions/collapsable-assessment-instructions.component.ts b/src/main/webapp/app/assessment/assessment-instructions/collapsable-assessment-instructions/collapsable-assessment-instructions.component.ts index 3d480876a182..6ff4469e71c1 100644 --- a/src/main/webapp/app/assessment/assessment-instructions/collapsable-assessment-instructions/collapsable-assessment-instructions.component.ts +++ b/src/main/webapp/app/assessment/assessment-instructions/collapsable-assessment-instructions/collapsable-assessment-instructions.component.ts @@ -3,11 +3,15 @@ import { faListAlt } from '@fortawesome/free-regular-svg-icons'; import { faChevronLeft, faChevronRight, faGripLinesVertical } from '@fortawesome/free-solid-svg-icons'; import { Exercise } from 'app/entities/exercise.model'; import interact from 'interactjs'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { AssessmentInstructionsComponent } from '../assessment-instructions/assessment-instructions.component'; @Component({ selector: 'jhi-collapsable-assessment-instructions', templateUrl: './collapsable-assessment-instructions.component.html', styleUrls: ['./collapsable-assessment-instructions.scss'], + imports: [FaIconComponent, TranslateDirective, AssessmentInstructionsComponent], }) export class CollapsableAssessmentInstructionsComponent implements AfterViewInit { @Input() isAssessmentTraining = false; diff --git a/src/main/webapp/app/assessment/assessment-instructions/expandable-section/expandable-section.component.ts b/src/main/webapp/app/assessment/assessment-instructions/expandable-section/expandable-section.component.ts index ff8cb7035f0f..8c5a88074148 100644 --- a/src/main/webapp/app/assessment/assessment-instructions/expandable-section/expandable-section.component.ts +++ b/src/main/webapp/app/assessment/assessment-instructions/expandable-section/expandable-section.component.ts @@ -1,12 +1,18 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { faAngleDown, faAngleRight } from '@fortawesome/free-solid-svg-icons'; import { LocalStorageService } from 'ngx-webstorage'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbCollapse } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-expandable-section', templateUrl: './expandable-section.component.html', + imports: [FaIconComponent, NgbCollapse, ArtemisTranslatePipe], }) export class ExpandableSectionComponent implements OnInit { + private localStorageService = inject(LocalStorageService); + @Input() headerKey: string; @Input() hasTranslation = true; @Input() isSubHeader = false; @@ -18,8 +24,6 @@ export class ExpandableSectionComponent implements OnInit { readonly PREFIX = 'collapsed.'; - constructor(private localStorageService: LocalStorageService) {} - ngOnInit(): void { this.isCollapsed = !!this.localStorageService.retrieve(this.storageKey); this.localStorageService.store(this.storageKey, this.isCollapsed); diff --git a/src/main/webapp/app/assessment/assessment-layout/assessment-layout.component.ts b/src/main/webapp/app/assessment/assessment-layout/assessment-layout.component.ts index b68902048248..e82b6597c9f0 100644 --- a/src/main/webapp/app/assessment/assessment-layout/assessment-layout.component.ts +++ b/src/main/webapp/app/assessment/assessment-layout/assessment-layout.component.ts @@ -5,6 +5,10 @@ import { Exercise } from 'app/entities/exercise.model'; import { Submission } from 'app/entities/submission.model'; import { AssessmentAfterComplaint } from 'app/complaints/complaints-for-tutor/complaints-for-tutor.component'; import { AssessmentNote } from 'app/entities/assessment-note.model'; +import { AssessmentHeaderComponent } from '../assessment-header/assessment-header.component'; +import { AssessmentComplaintAlertComponent } from '../assessment-complaint-alert/assessment-complaint-alert.component'; +import { AssessmentNoteComponent } from '../assessment-note/assessment-note.component'; +import { ComplaintsForTutorComponent } from '../../complaints/complaints-for-tutor/complaints-for-tutor.component'; /** * The component provides the basic layout for an assessment page. @@ -16,6 +20,7 @@ import { AssessmentNote } from 'app/entities/assessment-note.model'; selector: 'jhi-assessment-layout', templateUrl: './assessment-layout.component.html', styleUrls: ['./assessment-layout.component.scss'], + imports: [AssessmentHeaderComponent, AssessmentComplaintAlertComponent, AssessmentNoteComponent, ComplaintsForTutorComponent], }) export class AssessmentLayoutComponent { @HostBinding('class.assessment-container') readonly assessmentContainerClass = true; diff --git a/src/main/webapp/app/assessment/assessment-locks/assessment-locks.component.ts b/src/main/webapp/app/assessment/assessment-locks/assessment-locks.component.ts index 78b63339c2ad..b44aeac5ba83 100644 --- a/src/main/webapp/app/assessment/assessment-locks/assessment-locks.component.ts +++ b/src/main/webapp/app/assessment/assessment-locks/assessment-locks.component.ts @@ -1,5 +1,5 @@ -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { Component, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { FileUploadAssessmentService } from 'app/exercises/file-upload/assess/file-upload-assessment.service'; import { TranslateService } from '@ngx-translate/core'; import { Submission, SubmissionExerciseType } from 'app/entities/submission.model'; @@ -14,12 +14,27 @@ import { ProgrammingAssessmentManualResultService } from 'app/exercises/programm import { ExamManagementService } from 'app/exam/manage/exam-management.service'; import { faBan, faFolderOpen } from '@fortawesome/free-solid-svg-icons'; import { combineLatest } from 'rxjs'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-assessment-locks', templateUrl: './assessment-locks.component.html', + imports: [TranslateDirective, FaIconComponent, NgbTooltip, RouterLink, ArtemisDatePipe, ArtemisTranslatePipe], }) export class AssessmentLocksComponent implements OnInit { + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + private modelingAssessmentService = inject(ModelingAssessmentService); + private textAssessmentService = inject(TextAssessmentService); + private fileUploadAssessmentService = inject(FileUploadAssessmentService); + private programmingAssessmentService = inject(ProgrammingAssessmentManualResultService); + private courseService = inject(CourseManagementService); + private examManagementService = inject(ExamManagementService); + readonly ExerciseType = ExerciseType; course: Course; @@ -40,17 +55,8 @@ export class AssessmentLocksComponent implements OnInit { faBan = faBan; faFolderOpen = faFolderOpen; - constructor( - private route: ActivatedRoute, - private alertService: AlertService, - private modelingAssessmentService: ModelingAssessmentService, - private textAssessmentService: TextAssessmentService, - private fileUploadAssessmentService: FileUploadAssessmentService, - private programmingAssessmentService: ProgrammingAssessmentManualResultService, - translateService: TranslateService, - private courseService: CourseManagementService, - private examManagementService: ExamManagementService, - ) { + constructor() { + const translateService = inject(TranslateService); translateService.get('artemisApp.assessment.messages.confirmCancel').subscribe((text) => (this.cancelConfirmationText = text)); } diff --git a/src/main/webapp/app/assessment/assessment-locks/assessment-locks.route.ts b/src/main/webapp/app/assessment/assessment-locks/assessment-locks.route.ts index c2d1221363fa..fa4b9e2319d2 100644 --- a/src/main/webapp/app/assessment/assessment-locks/assessment-locks.route.ts +++ b/src/main/webapp/app/assessment/assessment-locks/assessment-locks.route.ts @@ -1,13 +1,13 @@ import { Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { AssessmentLocksComponent } from './assessment-locks.component'; + import { Authority } from 'app/shared/constants/authority.constants'; import { CourseManagementResolve } from 'app/course/manage/course-management-resolve.service'; export const assessmentLocksRoute: Routes = [ { path: ':courseId/exams/:examId/assessment-locks', - component: AssessmentLocksComponent, + loadComponent: () => import('./assessment-locks.component').then((m) => m.AssessmentLocksComponent), resolve: { course: CourseManagementResolve, }, @@ -19,7 +19,7 @@ export const assessmentLocksRoute: Routes = [ }, { path: ':courseId/assessment-locks', - component: AssessmentLocksComponent, + loadComponent: () => import('./assessment-locks.component').then((m) => m.AssessmentLocksComponent), resolve: { course: CourseManagementResolve, }, diff --git a/src/main/webapp/app/assessment/assessment-note/assessment-note.component.ts b/src/main/webapp/app/assessment/assessment-note/assessment-note.component.ts index f21ad66262cc..e545e745ecfa 100644 --- a/src/main/webapp/app/assessment/assessment-note/assessment-note.component.ts +++ b/src/main/webapp/app/assessment/assessment-note/assessment-note.component.ts @@ -1,10 +1,12 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { AssessmentNote } from 'app/entities/assessment-note.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-assessment-note', templateUrl: './assessment-note.component.html', styleUrls: ['./assessment-note.component.scss'], + imports: [TranslateDirective], }) export class AssessmentNoteComponent { private _assessmentNote: AssessmentNote; diff --git a/src/main/webapp/app/assessment/assessment-shared.module.ts b/src/main/webapp/app/assessment/assessment-shared.module.ts index fe386487df8c..0677f2d0c174 100644 --- a/src/main/webapp/app/assessment/assessment-shared.module.ts +++ b/src/main/webapp/app/assessment/assessment-shared.module.ts @@ -32,8 +32,6 @@ const ENTITY_STATES = [...assessmentLocksRoute]; ArtemisFeedbackModule, FeedbackContentPipe, QuotePipe, - ], - declarations: [ AssessmentHeaderComponent, AssessmentLayoutComponent, AssessmentComplaintAlertComponent, diff --git a/src/main/webapp/app/assessment/assessment-warning/assessment-warning.component.ts b/src/main/webapp/app/assessment/assessment-warning/assessment-warning.component.ts index 42120b935660..96485248a206 100644 --- a/src/main/webapp/app/assessment/assessment-warning/assessment-warning.component.ts +++ b/src/main/webapp/app/assessment/assessment-warning/assessment-warning.component.ts @@ -3,6 +3,8 @@ import dayjs from 'dayjs/esm'; import { Exercise } from 'app/entities/exercise.model'; import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; import { Submission } from 'app/entities/submission.model'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; /** * Displays a warning for instructors on submission page, team page and the assessment page. @@ -26,6 +28,7 @@ import { Submission } from 'app/entities/submission.model'; } `, + imports: [FaIconComponent, TranslateDirective], }) export class AssessmentWarningComponent implements OnChanges { @Input() exercise: Exercise; diff --git a/src/main/webapp/app/assessment/athena.service.ts b/src/main/webapp/app/assessment/athena.service.ts index 436330e568f2..0488997d035d 100644 --- a/src/main/webapp/app/assessment/athena.service.ts +++ b/src/main/webapp/app/assessment/athena.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable, map, of, switchMap } from 'rxjs'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; @@ -13,12 +13,10 @@ import { ModelingSubmission } from 'app/entities/modeling-submission.model'; @Injectable({ providedIn: 'root' }) export class AthenaService { - public resourceUrl = 'api/athena'; + protected http = inject(HttpClient); + private profileService = inject(ProfileService); - constructor( - protected http: HttpClient, - private profileService: ProfileService, - ) {} + public resourceUrl = 'api/athena'; /** * Determine if the Athena service is available based on whether the corresponding profile is active diff --git a/src/main/webapp/app/assessment/structured-grading-instructions-assessment-layout/structured-grading-instructions-assessment-layout.component.ts b/src/main/webapp/app/assessment/structured-grading-instructions-assessment-layout/structured-grading-instructions-assessment-layout.component.ts index 46be8ca706ce..5c2f2e447f45 100644 --- a/src/main/webapp/app/assessment/structured-grading-instructions-assessment-layout/structured-grading-instructions-assessment-layout.component.ts +++ b/src/main/webapp/app/assessment/structured-grading-instructions-assessment-layout/structured-grading-instructions-assessment-layout.component.ts @@ -4,11 +4,17 @@ import { AfterViewInit, Component, Input, OnInit, QueryList, ViewChildren } from import { faCompress, faExpand, faInfoCircle } from '@fortawesome/free-solid-svg-icons'; import { ExpandableSectionComponent } from 'app/assessment/assessment-instructions/expandable-section/expandable-section.component'; import { delay, startWith } from 'rxjs'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-structured-grading-instructions-assessment-layout', templateUrl: './structured-grading-instructions-assessment-layout.component.html', styleUrls: ['./structured-grading-instructions-assessment-layout.component.scss'], + imports: [FaIconComponent, TranslateDirective, ExpandableSectionComponent, NgbTooltip, HelpIconComponent, HtmlForMarkdownPipe], }) export class StructuredGradingInstructionsAssessmentLayoutComponent implements OnInit, AfterViewInit { @Input() public criteria: GradingCriterion[]; diff --git a/src/main/webapp/app/assessment/unreferenced-feedback-detail/assessment-correction-round-badge/assessment-correction-round-badge.component.ts b/src/main/webapp/app/assessment/unreferenced-feedback-detail/assessment-correction-round-badge/assessment-correction-round-badge.component.ts index 63318de8c442..71efaf15d01c 100644 --- a/src/main/webapp/app/assessment/unreferenced-feedback-detail/assessment-correction-round-badge/assessment-correction-round-badge.component.ts +++ b/src/main/webapp/app/assessment/unreferenced-feedback-detail/assessment-correction-round-badge/assessment-correction-round-badge.component.ts @@ -1,10 +1,13 @@ import { Component, Input } from '@angular/core'; import { Feedback } from 'app/entities/feedback.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgStyle } from '@angular/common'; @Component({ selector: 'jhi-assessment-correction-round-badge', templateUrl: './assessment-correction-round-badge.component.html', styleUrls: ['./assessment-correction-round-badge.component.scss'], + imports: [TranslateDirective, NgStyle], }) export class AssessmentCorrectionRoundBadgeComponent { @Input() feedback: Feedback; diff --git a/src/main/webapp/app/assessment/unreferenced-feedback-detail/unreferenced-feedback-detail.component.ts b/src/main/webapp/app/assessment/unreferenced-feedback-detail/unreferenced-feedback-detail.component.ts index 3b4308b752ab..483eebaf28f9 100644 --- a/src/main/webapp/app/assessment/unreferenced-feedback-detail/unreferenced-feedback-detail.component.ts +++ b/src/main/webapp/app/assessment/unreferenced-feedback-detail/unreferenced-feedback-detail.component.ts @@ -5,13 +5,40 @@ import { StructuredGradingCriterionService } from 'app/exercises/shared/structur import { ButtonSize } from 'app/shared/components/button.component'; import { Subject } from 'rxjs'; import { FeedbackService } from 'app/exercises/shared/feedback/feedback.service'; +import { FeedbackSuggestionBadgeComponent } from '../../exercises/shared/feedback/feedback-suggestion-badge/feedback-suggestion-badge.component'; +import { GradingInstructionLinkIconComponent } from 'app/shared/grading-instruction-link-icon/grading-instruction-link-icon.component'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { FaIconComponent, FaLayersComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { AssessmentCorrectionRoundBadgeComponent } from './assessment-correction-round-badge/assessment-correction-round-badge.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { FeedbackContentPipe } from 'app/shared/pipes/feedback-content.pipe'; +import { QuotePipe } from 'app/shared/pipes/quote.pipe'; @Component({ selector: 'jhi-unreferenced-feedback-detail', templateUrl: './unreferenced-feedback-detail.component.html', styleUrls: ['./unreferenced-feedback-detail.component.scss'], + imports: [ + FeedbackSuggestionBadgeComponent, + GradingInstructionLinkIconComponent, + DeleteButtonDirective, + FaIconComponent, + TranslateDirective, + FormsModule, + NgbTooltip, + FaLayersComponent, + AssessmentCorrectionRoundBadgeComponent, + ArtemisTranslatePipe, + FeedbackContentPipe, + QuotePipe, + ], }) export class UnreferencedFeedbackDetailComponent implements OnInit { + structuredGradingCriterionService = inject(StructuredGradingCriterionService); + @Input() public feedback: Feedback; resultId: InputSignal = input.required(); @Input() isSuggestion: boolean; @@ -40,8 +67,6 @@ export class UnreferencedFeedbackDetailComponent implements OnInit { private dialogErrorSource = new Subject(); dialogError$ = this.dialogErrorSource.asObservable(); - constructor(public structuredGradingCriterionService: StructuredGradingCriterionService) {} - ngOnInit() { this.loadLongFeedback(); } diff --git a/src/main/webapp/app/complaints/complaints-for-students/complaints-student-view.component.ts b/src/main/webapp/app/complaints/complaints-for-students/complaints-student-view.component.ts index ed0bef126614..65dca1ca7ad8 100644 --- a/src/main/webapp/app/complaints/complaints-for-students/complaints-student-view.component.ts +++ b/src/main/webapp/app/complaints/complaints-for-students/complaints-student-view.component.ts @@ -25,7 +25,6 @@ import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; selector: 'jhi-complaint-student-view', templateUrl: './complaints-student-view.component.html', styleUrls: ['../complaints.scss'], - standalone: true, imports: [TranslateDirective, FaIconComponent, ComplaintsFormComponent, ComplaintRequestComponent, ComplaintResponseComponent, ArtemisTranslatePipe], }) export class ComplaintsStudentViewComponent implements OnInit { diff --git a/src/main/webapp/app/complaints/complaints-for-tutor/complaints-for-tutor.component.ts b/src/main/webapp/app/complaints/complaints-for-tutor/complaints-for-tutor.component.ts index a98e34d60b17..8478a6080862 100644 --- a/src/main/webapp/app/complaints/complaints-for-tutor/complaints-for-tutor.component.ts +++ b/src/main/webapp/app/complaints/complaints-for-tutor/complaints-for-tutor.component.ts @@ -24,7 +24,6 @@ export type AssessmentAfterComplaint = { complaintResponse: ComplaintResponse; o @Component({ selector: 'jhi-complaints-for-tutor-form', templateUrl: './complaints-for-tutor.component.html', - standalone: true, imports: [TranslateDirective, FormsModule, TextareaModule, ArtemisSharedCommonModule, ArtemisTranslatePipe], }) export class ComplaintsForTutorComponent implements OnInit { diff --git a/src/main/webapp/app/complaints/form/complaints-form.component.ts b/src/main/webapp/app/complaints/form/complaints-form.component.ts index 5d5265a527e1..bcb6725b5fee 100644 --- a/src/main/webapp/app/complaints/form/complaints-form.component.ts +++ b/src/main/webapp/app/complaints/form/complaints-form.component.ts @@ -16,7 +16,6 @@ import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; selector: 'jhi-complaint-form', templateUrl: './complaints-form.component.html', styleUrls: ['../complaints.scss'], - standalone: true, imports: [TranslateDirective, FormsModule, TextareaModule, ArtemisTranslatePipe], }) export class ComplaintsFormComponent implements OnInit { diff --git a/src/main/webapp/app/complaints/list-of-complaints/list-of-complaints.component.ts b/src/main/webapp/app/complaints/list-of-complaints/list-of-complaints.component.ts index a2a3c2197a0b..9f150adfbbe0 100644 --- a/src/main/webapp/app/complaints/list-of-complaints/list-of-complaints.component.ts +++ b/src/main/webapp/app/complaints/list-of-complaints/list-of-complaints.component.ts @@ -24,7 +24,6 @@ import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-complaint-list', templateUrl: './list-of-complaints.component.html', - standalone: true, imports: [TranslateDirective, FormsModule, ArtemisSharedCommonModule, FaIconComponent, NgbTooltip, ArtemisTranslatePipe], }) export class ListOfComplaintsComponent implements OnInit { diff --git a/src/main/webapp/app/complaints/list-of-complaints/list-of-complaints.route.ts b/src/main/webapp/app/complaints/list-of-complaints/list-of-complaints.route.ts index fbce52b1377d..0058ab0a505c 100644 --- a/src/main/webapp/app/complaints/list-of-complaints/list-of-complaints.route.ts +++ b/src/main/webapp/app/complaints/list-of-complaints/list-of-complaints.route.ts @@ -1,6 +1,7 @@ import { Routes } from '@angular/router'; -import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; import { ListOfComplaintsComponent } from 'app/complaints/list-of-complaints/list-of-complaints.component'; +import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; + import { ComplaintType } from 'app/entities/complaint.model'; import { Authority } from 'app/shared/constants/authority.constants'; import { exerciseTypes } from 'app/entities/exercise.model'; @@ -9,7 +10,7 @@ import { CourseManagementResolve } from 'app/course/manage/course-management-res export const listOfComplaintsRoute: Routes = [ { path: ':courseId/complaints', - component: ListOfComplaintsComponent, + loadComponent: () => import('app/complaints/list-of-complaints/list-of-complaints.component').then((m) => m.ListOfComplaintsComponent), resolve: { course: CourseManagementResolve, }, @@ -22,7 +23,7 @@ export const listOfComplaintsRoute: Routes = [ }, { path: ':courseId/exams/:examId/complaints', - component: ListOfComplaintsComponent, + loadComponent: () => import('app/complaints/list-of-complaints/list-of-complaints.component').then((m) => m.ListOfComplaintsComponent), resolve: { course: CourseManagementResolve, }, @@ -47,7 +48,7 @@ export const listOfComplaintsRoute: Routes = [ }), { path: ':courseId/more-feedback-requests', - component: ListOfComplaintsComponent, + loadComponent: () => import('app/complaints/list-of-complaints/list-of-complaints.component').then((m) => m.ListOfComplaintsComponent), resolve: { course: CourseManagementResolve, }, diff --git a/src/main/webapp/app/complaints/request/complaint-request.component.ts b/src/main/webapp/app/complaints/request/complaint-request.component.ts index 61065c172d4e..205cbe7910c1 100644 --- a/src/main/webapp/app/complaints/request/complaint-request.component.ts +++ b/src/main/webapp/app/complaints/request/complaint-request.component.ts @@ -9,7 +9,6 @@ import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-complaint-request', templateUrl: './complaint-request.component.html', - standalone: true, imports: [NgbTooltip, TranslateDirective, FormsModule, ArtemisSharedCommonModule, ArtemisTranslatePipe], }) export class ComplaintRequestComponent { diff --git a/src/main/webapp/app/complaints/response/complaint-response.component.ts b/src/main/webapp/app/complaints/response/complaint-response.component.ts index c2443cf7ea60..159a22226077 100644 --- a/src/main/webapp/app/complaints/response/complaint-response.component.ts +++ b/src/main/webapp/app/complaints/response/complaint-response.component.ts @@ -8,7 +8,6 @@ import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-complaint-response', templateUrl: './complaint-response.component.html', - standalone: true, imports: [NgbTooltip, FormsModule, ArtemisSharedCommonModule, ArtemisTranslatePipe], }) export class ComplaintResponseComponent { diff --git a/src/main/webapp/app/core/about-us/about-us.component.ts b/src/main/webapp/app/core/about-us/about-us.component.ts index 42ba47b5093a..701fb6bc260d 100644 --- a/src/main/webapp/app/core/about-us/about-us.component.ts +++ b/src/main/webapp/app/core/about-us/about-us.component.ts @@ -1,17 +1,24 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { VERSION } from 'app/app.constants'; import { StaticContentService } from 'app/shared/service/static-content.service'; import { AboutUsModel } from 'app/core/about-us/models/about-us-model'; import { ContributorModel } from 'app/core/about-us/models/contributor-model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-about-us', templateUrl: './about-us.component.html', styleUrls: ['./about-us.component.scss'], + imports: [TranslateDirective, ArtemisTranslatePipe], }) export class AboutUsComponent implements OnInit { + private route = inject(ActivatedRoute); + private profileService = inject(ProfileService); + private staticContentService = inject(StaticContentService); + private readonly ISSUE_BASE_URL = 'https://github.com/ls1intum/Artemis/issues/new?projects=ls1intum/1'; readonly BUG_REPORT_URL = `${this.ISSUE_BASE_URL}&labels=bug&template=bug-report.yml`; readonly FEATURE_REQUEST_URL = `${this.ISSUE_BASE_URL}&labels=feature&template=feature-request.yml`; @@ -51,12 +58,6 @@ export class AboutUsComponent implements OnInit { ['openSource', { openSourceUrl: 'https://docs.artemis.cit.tum.de/dev/open-source/' }], ]; - constructor( - private route: ActivatedRoute, - private profileService: ProfileService, - private staticContentService: StaticContentService, - ) {} - /** * On init get the json file from the Artemis server and save it. * On init get the mail data needed for the contact diff --git a/src/main/webapp/app/core/about-us/artemis-about-us.module.ts b/src/main/webapp/app/core/about-us/artemis-about-us.module.ts index 057b2eda4540..f43f418f25f8 100644 --- a/src/main/webapp/app/core/about-us/artemis-about-us.module.ts +++ b/src/main/webapp/app/core/about-us/artemis-about-us.module.ts @@ -1,17 +1,17 @@ import { NgModule } from '@angular/core'; -import { AboutUsComponent } from 'app/core/about-us/about-us.component'; + import { TranslateModule } from '@ngx-translate/core'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; +import { AboutUsComponent } from 'app/core/about-us/about-us.component'; import { ArtemisSharedModule } from 'app/shared/shared.module'; @NgModule({ - declarations: [AboutUsComponent], imports: [ RouterModule.forChild([ { path: '', - component: AboutUsComponent, + loadComponent: () => import('app/core/about-us/about-us.component').then((m) => m.AboutUsComponent), data: { authorities: [], pageTitle: 'overview.aboutUs', @@ -21,6 +21,7 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; TranslateModule, CommonModule, ArtemisSharedModule, + AboutUsComponent, ], }) export class ArtemisAboutUsModule {} diff --git a/src/main/webapp/app/core/core.module.ts b/src/main/webapp/app/core/core.module.ts deleted file mode 100644 index 30c0442557b2..000000000000 --- a/src/main/webapp/app/core/core.module.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { APP_INITIALIZER, ErrorHandler, LOCALE_ID, NgModule } from '@angular/core'; -import { DatePipe, registerLocaleData } from '@angular/common'; -import { HTTP_INTERCEPTORS, HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; -import { Title } from '@angular/platform-browser'; -import { AuthExpiredInterceptor } from 'app/core/interceptor/auth-expired.interceptor'; -import { ErrorHandlerInterceptor } from 'app/core/interceptor/errorhandler.interceptor'; -import { NotificationInterceptor } from 'app/core/interceptor/notification.interceptor'; -import { NgbDateAdapter, NgbDatepickerConfig, NgbTooltipConfig } from '@ng-bootstrap/ng-bootstrap'; -import { SessionStorageService, provideNgxWebstorage, withLocalStorage, withNgxWebstorageConfig, withSessionStorage } from 'ngx-webstorage'; -import locale from '@angular/common/locales/en'; -import { MissingTranslationHandler, TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; -import { SentryErrorHandler } from 'app/core/sentry/sentry.error-handler'; -import { LoadingNotificationInterceptor } from 'app/shared/notification/loading-notification/loading-notification.interceptor'; -import { BrowserFingerprintInterceptor } from 'app/core/interceptor/browser-fingerprint.interceptor.service'; -import { ArtemisVersionInterceptor, WINDOW_INJECTOR_TOKEN } from 'app/core/interceptor/artemis-version.interceptor'; -import { missingTranslationHandler, translatePartialLoader } from './config/translation.config'; -import dayjs from 'dayjs/esm'; -import './config/dayjs'; -import { NgbDateDayjsAdapter } from 'app/core/config/datepicker-adapter'; -import { JhiLanguageHelper } from 'app/core/language/language.helper'; -import { TraceService } from '@sentry/angular'; -import { Router } from '@angular/router'; -import isMobile from 'ismobilejs-es5'; - -@NgModule({ - imports: [ - TranslateModule.forRoot({ - loader: { - provide: TranslateLoader, - useFactory: translatePartialLoader, - deps: [HttpClient], - }, - missingTranslationHandler: { - provide: MissingTranslationHandler, - useFactory: missingTranslationHandler, - }, - }), - ], - providers: [ - provideHttpClient(withInterceptorsFromDi()), - provideNgxWebstorage(withNgxWebstorageConfig({ prefix: 'jhi', separator: '-' }), withLocalStorage(), withSessionStorage()), - Title, - { - provide: LOCALE_ID, - useValue: 'en', - }, - { provide: NgbDateAdapter, useClass: NgbDateDayjsAdapter }, - { provide: TraceService, deps: [Router] }, - { provide: ErrorHandler, useClass: SentryErrorHandler }, - { provide: WINDOW_INJECTOR_TOKEN, useValue: window }, - DatePipe, - { - provide: APP_INITIALIZER, - useFactory: () => () => {}, - deps: [TraceService], - multi: true, - }, - /** - * @description Interceptor declarations: - * Interceptors are located at 'blocks/interceptor/. - * All of them implement the HttpInterceptor interface. - * They can be used to modify API calls or trigger additional function calls. - * Most interceptors will transform the outgoing request before passing it to - * the next interceptor in the chain, by calling next.handle(transformedReq). - * Documentation: https://angular.io/api/common/http/HttpInterceptor - */ - { - provide: HTTP_INTERCEPTORS, - useClass: AuthExpiredInterceptor, - multi: true, - }, - { - provide: HTTP_INTERCEPTORS, - useClass: ErrorHandlerInterceptor, - multi: true, - }, - { - provide: HTTP_INTERCEPTORS, - useClass: BrowserFingerprintInterceptor, - multi: true, - }, - { - provide: HTTP_INTERCEPTORS, - useClass: NotificationInterceptor, - multi: true, - }, - { - provide: HTTP_INTERCEPTORS, - useClass: LoadingNotificationInterceptor, - multi: true, - }, - { - provide: HTTP_INTERCEPTORS, - useClass: ArtemisVersionInterceptor, - multi: true, - }, - ], -}) -export class ArtemisCoreModule { - constructor( - dpConfig: NgbDatepickerConfig, - tooltipConfig: NgbTooltipConfig, - translateService: TranslateService, - languageHelper: JhiLanguageHelper, - sessionStorageService: SessionStorageService, - ) { - registerLocaleData(locale); - dpConfig.minDate = { year: dayjs().subtract(100, 'year').year(), month: 1, day: 1 }; - translateService.setDefaultLang('en'); - const languageKey = sessionStorageService.retrieve('locale') || languageHelper.determinePreferredLanguage(); - translateService.use(languageKey); - tooltipConfig.container = 'body'; - if (isMobile(window.navigator.userAgent).any ?? false) { - tooltipConfig.disableTooltip = true; - } - } -} diff --git a/src/main/webapp/app/core/interceptor/artemis-version.interceptor.ts b/src/main/webapp/app/core/interceptor/artemis-version.interceptor.ts index e68fa487ec2d..d06badde9302 100644 --- a/src/main/webapp/app/core/interceptor/artemis-version.interceptor.ts +++ b/src/main/webapp/app/core/interceptor/artemis-version.interceptor.ts @@ -1,4 +1,4 @@ -import { ApplicationRef, Inject, Injectable, InjectionToken } from '@angular/core'; +import { ApplicationRef, Injectable, InjectionToken, inject } from '@angular/core'; import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http'; import { Observable, concat, interval, of } from 'rxjs'; import { catchError, first, tap, timeout } from 'rxjs/operators'; @@ -11,18 +11,20 @@ export const WINDOW_INJECTOR_TOKEN = new InjectionToken('Window'); @Injectable() export class ArtemisVersionInterceptor implements HttpInterceptor { + private appRef = inject(ApplicationRef); + private updates = inject(SwUpdate); + private serverDateService = inject(ArtemisServerDateService); + private alertService = inject(AlertService); + private injectedWindow = inject(WINDOW_INJECTOR_TOKEN); + // The currently displayed alert private alert: Alert; // Indicates whether we ever saw an outdated state since last reload private hasSeenOutdatedInThisSession = false; - constructor( - private appRef: ApplicationRef, - private updates: SwUpdate, - private serverDateService: ArtemisServerDateService, - private alertService: AlertService, - @Inject(WINDOW_INJECTOR_TOKEN) private injectedWindow: Window, - ) { + constructor() { + const appRef = this.appRef; + // Allow the app to stabilize first, before starting // polling for updates with `interval()`. const appIsStableOrTimeout = appRef.isStable.pipe( diff --git a/src/main/webapp/app/core/interceptor/auth-expired.interceptor.ts b/src/main/webapp/app/core/interceptor/auth-expired.interceptor.ts index 560b79ecfce6..ef73ff1f2bea 100644 --- a/src/main/webapp/app/core/interceptor/auth-expired.interceptor.ts +++ b/src/main/webapp/app/core/interceptor/auth-expired.interceptor.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @@ -9,12 +9,10 @@ import { AccountService } from 'app/core/auth/account.service'; @Injectable() export class AuthExpiredInterceptor implements HttpInterceptor { - constructor( - private loginService: LoginService, - private stateStorageService: StateStorageService, - private router: Router, - private accountService: AccountService, - ) {} + private loginService = inject(LoginService); + private stateStorageService = inject(StateStorageService); + private router = inject(Router); + private accountService = inject(AccountService); /** * Identifies and handles a given HTTP request. If the request's error status is 401, the current user will be logged out. diff --git a/src/main/webapp/app/core/interceptor/browser-fingerprint.interceptor.service.ts b/src/main/webapp/app/core/interceptor/browser-fingerprint.interceptor.service.ts index d51cca4a20d1..6933636e07ea 100644 --- a/src/main/webapp/app/core/interceptor/browser-fingerprint.interceptor.service.ts +++ b/src/main/webapp/app/core/interceptor/browser-fingerprint.interceptor.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; import { Observable } from 'rxjs'; import { BrowserFingerprintService } from 'app/shared/fingerprint/browser-fingerprint.service'; @@ -6,10 +6,14 @@ import { isRequestToArtemisServer } from './interceptor.util'; @Injectable() export class BrowserFingerprintInterceptor implements HttpInterceptor { + private browserFingerprintService = inject(BrowserFingerprintService); + private fingerprint?: string; private instanceIdentifier?: string; - constructor(private browserFingerprintService: BrowserFingerprintService) { + constructor() { + const browserFingerprintService = this.browserFingerprintService; + browserFingerprintService.fingerprint.subscribe((fingerprint) => (this.fingerprint = fingerprint)); browserFingerprintService.instanceIdentifier.subscribe((instanceIdentifier) => (this.instanceIdentifier = instanceIdentifier)); } diff --git a/src/main/webapp/app/core/interceptor/errorhandler.interceptor.ts b/src/main/webapp/app/core/interceptor/errorhandler.interceptor.ts index 6b3b3ce0b9c5..8a3d009fd985 100644 --- a/src/main/webapp/app/core/interceptor/errorhandler.interceptor.ts +++ b/src/main/webapp/app/core/interceptor/errorhandler.interceptor.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @@ -7,10 +7,8 @@ import { AccountService } from 'app/core/auth/account.service'; @Injectable() export class ErrorHandlerInterceptor implements HttpInterceptor { - constructor( - private eventManager: EventManager, - private accountService: AccountService, - ) {} + private eventManager = inject(EventManager); + private accountService = inject(AccountService); /** * Identifies and handles a given HTTP request. If the request's error status is not 401 while the user is not diff --git a/src/main/webapp/app/core/interceptor/notification.interceptor.ts b/src/main/webapp/app/core/interceptor/notification.interceptor.ts index 60cbd80bf09a..e39212e9a8d9 100644 --- a/src/main/webapp/app/core/interceptor/notification.interceptor.ts +++ b/src/main/webapp/app/core/interceptor/notification.interceptor.ts @@ -1,12 +1,12 @@ import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; import { AlertService } from 'app/core/util/alert.service'; @Injectable() export class NotificationInterceptor implements HttpInterceptor { - constructor(private alertService: AlertService) {} + private alertService = inject(AlertService); /** * Identifies and handles a given HTTP request. If the event is a HttpResponse and contains an alert, the alert diff --git a/src/main/webapp/app/core/language/language.helper.ts b/src/main/webapp/app/core/language/language.helper.ts index 60cfe80b69c2..5d5673c77263 100644 --- a/src/main/webapp/app/core/language/language.helper.ts +++ b/src/main/webapp/app/core/language/language.helper.ts @@ -1,4 +1,4 @@ -import { Injectable, Renderer2, RendererFactory2 } from '@angular/core'; +import { Injectable, Renderer2, RendererFactory2, inject } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { ActivatedRouteSnapshot, Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; @@ -11,17 +11,18 @@ import { LocaleConversionService } from 'app/shared/service/locale-conversion.se @Injectable({ providedIn: 'root' }) export class JhiLanguageHelper { + private translateService = inject(TranslateService); + private localeConversionService = inject(LocaleConversionService); + private titleService = inject(Title); + private router = inject(Router); + private sessionStorage = inject(SessionStorageService); + private renderer: Renderer2; private _language: BehaviorSubject; - constructor( - private translateService: TranslateService, - private localeConversionService: LocaleConversionService, - private titleService: Title, - private router: Router, - rootRenderer: RendererFactory2, - private sessionStorage: SessionStorageService, - ) { + constructor() { + const rootRenderer = inject(RendererFactory2); + this._language = new BehaviorSubject(this.translateService.currentLang); this.renderer = rootRenderer.createRenderer(document.querySelector('html'), null); this.init(); diff --git a/src/main/webapp/app/core/legal/data-export/confirmation/data-export-confirmation-dialog.component.ts b/src/main/webapp/app/core/legal/data-export/confirmation/data-export-confirmation-dialog.component.ts index 9887df9239e3..aaa457e0927e 100644 --- a/src/main/webapp/app/core/legal/data-export/confirmation/data-export-confirmation-dialog.component.ts +++ b/src/main/webapp/app/core/legal/data-export/confirmation/data-export-confirmation-dialog.component.ts @@ -1,15 +1,23 @@ -import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; +import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild, inject } from '@angular/core'; import { Observable, Subscription } from 'rxjs'; import { AlertService } from 'app/core/util/alert.service'; -import { NgForm } from '@angular/forms'; +import { FormsModule, NgForm } from '@angular/forms'; import { faBan, faCheck, faSpinner } from '@fortawesome/free-solid-svg-icons'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { TypeAheadUserSearchFieldComponent } from 'app/shared/type-ahead-search-field/type-ahead-user-search-field.component'; +import { ConfirmEntityNameComponent } from 'app/shared/confirm-entity-name/confirm-entity-name.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-data-export-confirmation-dialog', templateUrl: './data-export-confirmation-dialog.component.html', + imports: [FormsModule, TranslateDirective, TypeAheadUserSearchFieldComponent, ConfirmEntityNameComponent, FaIconComponent], }) export class DataExportConfirmationDialogComponent implements OnInit, OnDestroy { + private activeModal = inject(NgbActiveModal); + private alertService = inject(AlertService); + private dialogErrorSubscription: Subscription; dialogError: Observable; @Output() dataExportRequest: EventEmitter; @@ -31,11 +39,6 @@ export class DataExportConfirmationDialogComponent implements OnInit, OnDestroy faSpinner = faSpinner; faCheck = faCheck; - constructor( - private activeModal: NgbActiveModal, - private alertService: AlertService, - ) {} - /** * Life cycle hook called by Angular to indicate that Angular is done creating the component */ diff --git a/src/main/webapp/app/core/legal/data-export/confirmation/data-export-confirmation-dialog.service.ts b/src/main/webapp/app/core/legal/data-export/confirmation/data-export-confirmation-dialog.service.ts index f4d24980e435..ef6f6ea01b2f 100644 --- a/src/main/webapp/app/core/legal/data-export/confirmation/data-export-confirmation-dialog.service.ts +++ b/src/main/webapp/app/core/legal/data-export/confirmation/data-export-confirmation-dialog.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { from } from 'rxjs'; import { AlertService } from 'app/core/util/alert.service'; @@ -7,12 +7,10 @@ import { DataExportConfirmationDialogComponent } from 'app/core/legal/data-expor @Injectable({ providedIn: 'root' }) export class DataExportConfirmationDialogService { - modalRef: NgbModalRef | null; + private modalService = inject(NgbModal); + alertService = inject(AlertService); - constructor( - private modalService: NgbModal, - public alertService: AlertService, - ) {} + modalRef: NgbModalRef | null; /** * Opens data export confirmation dialog diff --git a/src/main/webapp/app/core/legal/data-export/confirmation/data-export-request-button.directive.ts b/src/main/webapp/app/core/legal/data-export/confirmation/data-export-request-button.directive.ts index 9a56872cde64..f2134afd8bb7 100644 --- a/src/main/webapp/app/core/legal/data-export/confirmation/data-export-request-button.directive.ts +++ b/src/main/webapp/app/core/legal/data-export/confirmation/data-export-request-button.directive.ts @@ -1,4 +1,4 @@ -import { Directive, ElementRef, EventEmitter, HostListener, Input, OnInit, Output, Renderer2 } from '@angular/core'; +import { Directive, ElementRef, EventEmitter, HostListener, Input, OnInit, Output, Renderer2, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs'; import { DataExportConfirmationDialogData } from 'app/core/legal/data-export/confirmation/data-export-confirmation-dialog.model'; @@ -6,6 +6,11 @@ import { DataExportConfirmationDialogService } from 'app/core/legal/data-export/ @Directive({ selector: '[jhiDataExportRequestButton]' }) export class DataExportRequestButtonDirective implements OnInit { + private dataExportConfirmationDialogService = inject(DataExportConfirmationDialogService); + private renderer = inject(Renderer2); + private elementRef = inject(ElementRef); + private translateService = inject(TranslateService); + @Input() expectedLogin: string; @Input() dialogError: Observable; @Input() adminDialog = false; @@ -13,13 +18,6 @@ export class DataExportRequestButtonDirective implements OnInit { @Output() dataExportRequestForAnotherUser = new EventEmitter(); private buttonText: HTMLElement; - constructor( - private dataExportConfirmationDialogService: DataExportConfirmationDialogService, - private renderer: Renderer2, - private elementRef: ElementRef, - private translateService: TranslateService, - ) {} - /** * This method appends classes and type property to the button on which directive was used, additionally adds a span tag with delete text. * We can't use component, as Angular would wrap it in its own tag and this will break button grouping that we are using for other buttons. diff --git a/src/main/webapp/app/core/legal/data-export/data-export.component.ts b/src/main/webapp/app/core/legal/data-export/data-export.component.ts index 37b5de87c4e7..d402dc621668 100644 --- a/src/main/webapp/app/core/legal/data-export/data-export.component.ts +++ b/src/main/webapp/app/core/legal/data-export/data-export.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ActionType } from 'app/shared/delete-dialog/delete-dialog.model'; import { Subject } from 'rxjs'; import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; @@ -9,12 +9,23 @@ import { AlertService } from 'app/core/util/alert.service'; import { DataExport, DataExportState } from 'app/entities/data-export.model'; import { ActivatedRoute } from '@angular/router'; import { convertDateFromServer } from 'app/utils/date.utils'; +import { DataExportRequestButtonDirective } from './confirmation/data-export-request-button.directive'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-data-export', templateUrl: './data-export.component.html', + imports: [DataExportRequestButtonDirective, ButtonComponent, TranslateDirective, ArtemisDatePipe, ArtemisTranslatePipe], }) export class DataExportComponent implements OnInit { + private dataExportService = inject(DataExportService); + private accountService = inject(AccountService); + private alertService = inject(AlertService); + private route = inject(ActivatedRoute); + readonly ActionType = ActionType; readonly ButtonSize = ButtonSize; readonly ButtonType = ButtonType; @@ -34,13 +45,6 @@ export class DataExportComponent implements OnInit { dataExport: DataExport = new DataExport(); isAdmin = false; - constructor( - private dataExportService: DataExportService, - private accountService: AccountService, - private alertService: AlertService, - private route: ActivatedRoute, - ) {} - ngOnInit() { this.currentLogin = this.accountService.userIdentity?.login; this.isAdmin = this.accountService.isAdmin(); diff --git a/src/main/webapp/app/core/legal/data-export/data-export.service.ts b/src/main/webapp/app/core/legal/data-export/data-export.service.ts index f7b2ce5a8527..87296c4d7cd5 100644 --- a/src/main/webapp/app/core/legal/data-export/data-export.service.ts +++ b/src/main/webapp/app/core/legal/data-export/data-export.service.ts @@ -1,11 +1,11 @@ import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { DataExport } from 'app/entities/data-export.model'; @Injectable({ providedIn: 'root' }) export class DataExportService { - constructor(private http: HttpClient) {} + private http = inject(HttpClient); requestDataExport(): Observable { return this.http.post(`api/data-exports`, {}); diff --git a/src/main/webapp/app/core/legal/imprint-routing.module.ts b/src/main/webapp/app/core/legal/imprint-routing.module.ts index 08ec21c8f666..9facac88ab95 100644 --- a/src/main/webapp/app/core/legal/imprint-routing.module.ts +++ b/src/main/webapp/app/core/legal/imprint-routing.module.ts @@ -1,8 +1,6 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { ImprintComponent } from 'app/core/legal/imprint.component'; - const routes: Routes = [ { path: '', @@ -10,7 +8,7 @@ const routes: Routes = [ { path: '', pathMatch: 'full', - component: ImprintComponent, + loadComponent: () => import('app/core/legal/imprint.component').then((m) => m.ImprintComponent), data: { authorities: [], pageTitle: 'artemisApp.legal.imprint.title', @@ -18,7 +16,7 @@ const routes: Routes = [ }, { path: ':fragment', - component: ImprintComponent, + loadComponent: () => import('app/core/legal/imprint.component').then((m) => m.ImprintComponent), data: { authorities: [], pageTitle: 'artemisApp.legal.imprint.title', diff --git a/src/main/webapp/app/core/legal/imprint.component.ts b/src/main/webapp/app/core/legal/imprint.component.ts index c7b1ca5e2ff6..d86d46451247 100644 --- a/src/main/webapp/app/core/legal/imprint.component.ts +++ b/src/main/webapp/app/core/legal/imprint.component.ts @@ -1,24 +1,24 @@ -import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core'; +import { AfterViewInit, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Subscription } from 'rxjs'; import { JhiLanguageHelper } from 'app/core/language/language.helper'; import { LegalDocumentLanguage } from 'app/entities/legal-document.model'; import { LegalDocumentService } from 'app/shared/service/legal-document.service'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-imprint', template: `
`, + imports: [HtmlForMarkdownPipe], }) export class ImprintComponent implements AfterViewInit, OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private legalDocumentService = inject(LegalDocumentService); + private languageHelper = inject(JhiLanguageHelper); + imprint?: string; private languageChangeSubscription?: Subscription; - constructor( - private route: ActivatedRoute, - private legalDocumentService: LegalDocumentService, - private languageHelper: JhiLanguageHelper, - ) {} - /** * On init get the Imprint statement file from the Artemis server and set up a subscription to fetch the file again if the language was changed. */ diff --git a/src/main/webapp/app/core/legal/imprint.module.ts b/src/main/webapp/app/core/legal/imprint.module.ts index 867b3209bdbb..d731771c22fd 100644 --- a/src/main/webapp/app/core/legal/imprint.module.ts +++ b/src/main/webapp/app/core/legal/imprint.module.ts @@ -7,7 +7,6 @@ import { ImprintComponent } from 'app/core/legal/imprint.component'; import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; @NgModule({ - declarations: [ImprintComponent], - imports: [CommonModule, ArtemisSharedModule, ImprintRoutingModule, ArtemisMarkdownModule], + imports: [CommonModule, ArtemisSharedModule, ImprintRoutingModule, ArtemisMarkdownModule, ImprintComponent], }) export class ArtemisImprintModule {} diff --git a/src/main/webapp/app/core/legal/privacy-routing.module.ts b/src/main/webapp/app/core/legal/privacy-routing.module.ts index 4ea113f257b1..cae0efb8ebd4 100644 --- a/src/main/webapp/app/core/legal/privacy-routing.module.ts +++ b/src/main/webapp/app/core/legal/privacy-routing.module.ts @@ -1,15 +1,13 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { PrivacyComponent } from 'app/core/legal/privacy.component'; -import { DataExportComponent } from 'app/core/legal/data-export/data-export.component'; import { Authority } from 'app/shared/constants/authority.constants'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; const routes: Routes = [ { path: 'data-exports/:id', - component: DataExportComponent, + loadComponent: () => import('app/core/legal/data-export/data-export.component').then((m) => m.DataExportComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.dataExport.title', @@ -18,7 +16,7 @@ const routes: Routes = [ }, { path: 'data-exports', - component: DataExportComponent, + loadComponent: () => import('app/core/legal/data-export/data-export.component').then((m) => m.DataExportComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.dataExport.title', @@ -31,7 +29,7 @@ const routes: Routes = [ { path: '', pathMatch: 'full', - component: PrivacyComponent, + loadComponent: () => import('app/core/legal/privacy.component').then((m) => m.PrivacyComponent), data: { authorities: [], pageTitle: 'artemisApp.legal.privacyStatement.title', @@ -39,7 +37,7 @@ const routes: Routes = [ }, { path: ':fragment', - component: PrivacyComponent, + loadComponent: () => import('app/core/legal/privacy.component').then((m) => m.PrivacyComponent), data: { authorities: [], pageTitle: 'artemisApp.legal.privacyStatement.title', diff --git a/src/main/webapp/app/core/legal/privacy.component.ts b/src/main/webapp/app/core/legal/privacy.component.ts index 95a9b73eec9c..c7be0da1f787 100644 --- a/src/main/webapp/app/core/legal/privacy.component.ts +++ b/src/main/webapp/app/core/legal/privacy.component.ts @@ -1,10 +1,12 @@ -import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { AfterViewInit, Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { Subscription } from 'rxjs'; import { JhiLanguageHelper } from 'app/core/language/language.helper'; import { AccountService } from 'app/core/auth/account.service'; import { LegalDocumentService } from 'app/shared/service/legal-document.service'; import { LegalDocumentLanguage } from 'app/entities/legal-document.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-privacy', @@ -14,19 +16,18 @@ import { LegalDocumentLanguage } from 'app/entities/legal-document.model'; } `, + imports: [TranslateDirective, RouterLink, HtmlForMarkdownPipe], }) export class PrivacyComponent implements AfterViewInit, OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private legalDocumentService = inject(LegalDocumentService); + private languageHelper = inject(JhiLanguageHelper); + private accountService = inject(AccountService); + privacyStatement?: string; private languageChangeSubscription?: Subscription; isAuthenticated: boolean; - constructor( - private route: ActivatedRoute, - private legalDocumentService: LegalDocumentService, - private languageHelper: JhiLanguageHelper, - private accountService: AccountService, - ) {} - /** * On init get the privacy statement file from the Artemis server and set up a subscription to fetch the file again if the language was changed. */ diff --git a/src/main/webapp/app/core/legal/privacy.module.ts b/src/main/webapp/app/core/legal/privacy.module.ts index 54f04bfe99df..2a7ac518f8c8 100644 --- a/src/main/webapp/app/core/legal/privacy.module.ts +++ b/src/main/webapp/app/core/legal/privacy.module.ts @@ -12,7 +12,17 @@ import { DataExportRequestButtonDirective } from 'app/core/legal/data-export/con import { TypeAheadUserSearchFieldModule } from 'app/shared/type-ahead-search-field/type-ahead-user-search-field.module'; @NgModule({ - declarations: [PrivacyComponent, DataExportComponent, DataExportConfirmationDialogComponent, DataExportRequestButtonDirective], - imports: [CommonModule, ArtemisSharedComponentModule, ArtemisSharedModule, PrivacyRoutingModule, ArtemisMarkdownModule, TypeAheadUserSearchFieldModule], + imports: [ + CommonModule, + ArtemisSharedComponentModule, + ArtemisSharedModule, + PrivacyRoutingModule, + ArtemisMarkdownModule, + TypeAheadUserSearchFieldModule, + PrivacyComponent, + DataExportComponent, + DataExportConfirmationDialogComponent, + DataExportRequestButtonDirective, + ], }) export class ArtemisPrivacyModule {} diff --git a/src/main/webapp/app/core/sentry/sentry.error-handler.ts b/src/main/webapp/app/core/sentry/sentry.error-handler.ts index be90f524d878..da452aee779d 100644 --- a/src/main/webapp/app/core/sentry/sentry.error-handler.ts +++ b/src/main/webapp/app/core/sentry/sentry.error-handler.ts @@ -35,10 +35,6 @@ export class SentryErrorHandler extends ErrorHandler { }); } - constructor() { - super(); - } - /** * Send an HttpError to Sentry. Only if it's not in the range 400-499. * @param error diff --git a/src/main/webapp/app/core/theme/theme-switch.component.ts b/src/main/webapp/app/core/theme/theme-switch.component.ts index 2108bd3a0fb6..29c20a61a52b 100644 --- a/src/main/webapp/app/core/theme/theme-switch.component.ts +++ b/src/main/webapp/app/core/theme/theme-switch.component.ts @@ -20,7 +20,6 @@ import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; styleUrls: ['theme-switch.component.scss'], imports: [TranslateModule, CommonModule, ArtemisSharedModule, NgbModule, FontAwesomeModule], changeDetection: ChangeDetectionStrategy.OnPush, - standalone: true, }) export class ThemeSwitchComponent implements OnInit { protected readonly faSync = faSync; diff --git a/src/main/webapp/app/core/user/admin-user.service.ts b/src/main/webapp/app/core/user/admin-user.service.ts index 73e14d154597..a3d0efd1d496 100644 --- a/src/main/webapp/app/core/user/admin-user.service.ts +++ b/src/main/webapp/app/core/user/admin-user.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; @@ -8,9 +8,9 @@ import { UserFilter } from 'app/admin/user-management/user-management.component' @Injectable({ providedIn: 'root' }) export class AdminUserService { - public resourceUrl = 'api/admin/users'; + private http = inject(HttpClient); - constructor(private http: HttpClient) {} + public resourceUrl = 'api/admin/users'; /** * Create a user on the server. diff --git a/src/main/webapp/app/core/user/user.service.ts b/src/main/webapp/app/core/user/user.service.ts index 7544c8525fe0..63c7fea088b0 100644 --- a/src/main/webapp/app/core/user/user.service.ts +++ b/src/main/webapp/app/core/user/user.service.ts @@ -1,13 +1,13 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { User } from 'app/core/user/user.model'; @Injectable({ providedIn: 'root' }) export class UserService { - public resourceUrl = 'api/users'; + private http = inject(HttpClient); - constructor(private http: HttpClient) {} + public resourceUrl = 'api/users'; /** * Search for a user on the server by login or name. diff --git a/src/main/webapp/app/core/util/alert.service.ts b/src/main/webapp/app/core/util/alert.service.ts index a2052b623c6c..dbc534b0efdb 100644 --- a/src/main/webapp/app/core/util/alert.service.ts +++ b/src/main/webapp/app/core/util/alert.service.ts @@ -1,4 +1,4 @@ -import { Injectable, NgZone, SecurityContext } from '@angular/core'; +import { Injectable, NgZone, SecurityContext, inject } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; import { translationNotFoundMessage } from 'app/core/config/translation.config'; @@ -57,6 +57,10 @@ const DEFAULT_DISMISSIBLE = true; providedIn: 'root', }) export class AlertService { + private sanitizer = inject(DomSanitizer); + private ngZone = inject(NgZone); + private translateService = inject(TranslateService); + private alerts: AlertInternal[] = []; errorListener: Subscription; @@ -64,12 +68,9 @@ export class AlertService { readonly conflictErrorKeysToSkip: string[] = ['cannotRegisterInstructor']; - constructor( - private sanitizer: DomSanitizer, - private ngZone: NgZone, - private translateService: TranslateService, - eventManager: EventManager, - ) { + constructor() { + const eventManager = inject(EventManager); + this.errorListener = eventManager.subscribe('artemisApp.error', (response: EventWithContent | string) => { const errorResponse = (response as EventWithContent).content; this.addErrorAlert(errorResponse.message, errorResponse.translationKey, errorResponse.translationParams); @@ -97,8 +98,8 @@ export class AlertService { entityKey = httpErrorResponse.headers.get(entry); } }); - if (errorHeader && !translateService.instant(errorHeader).startsWith(translationNotFoundMessage)) { - const entityName = translateService.instant('global.menu.entities.' + entityKey); + if (errorHeader && !this.translateService.instant(errorHeader).startsWith(translationNotFoundMessage)) { + const entityName = this.translateService.instant('global.menu.entities.' + entityKey); this.addErrorAlert(errorHeader, errorHeader, { entityName, ...httpErrorResponse.error?.params }); } else if (httpErrorResponse.error && httpErrorResponse.error.fieldErrors) { const fieldErrors = httpErrorResponse.error.fieldErrors; @@ -110,7 +111,7 @@ export class AlertService { } // convert 'something[14].other[4].id' to 'something[].other[].id' so translations can be written to it const convertedField = fieldError.field.replace(/\[\d*\]/g, '[]'); - const fieldName = translateService.instant('artemisApp.' + fieldError.objectName + '.' + convertedField); + const fieldName = this.translateService.instant('artemisApp.' + fieldError.objectName + '.' + convertedField); this.addErrorAlert('Error on field "' + fieldName + '"', 'error.' + fieldError.message, { fieldName }); } } else if (httpErrorResponse.error && httpErrorResponse.error.title) { diff --git a/src/main/webapp/app/course/competencies/competencies-popover/competencies-popover.component.ts b/src/main/webapp/app/course/competencies/competencies-popover/competencies-popover.component.ts index bdc5747b4ed3..2ef00f2d3588 100644 --- a/src/main/webapp/app/course/competencies/competencies-popover/competencies-popover.component.ts +++ b/src/main/webapp/app/course/competencies/competencies-popover/competencies-popover.component.ts @@ -1,12 +1,17 @@ import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; import { faFlag } from '@fortawesome/free-solid-svg-icons'; import { CompetencyLectureUnitLink } from 'app/entities/competency.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { RouterLink } from '@angular/router'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-competencies-popover', templateUrl: './competencies-popover.component.html', styleUrls: ['./competencies-popover.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [TranslateDirective, RouterLink, NgbPopover, FaIconComponent], }) export class CompetenciesPopoverComponent implements OnInit { @Input() @@ -21,8 +26,6 @@ export class CompetenciesPopoverComponent implements OnInit { // Icons faFlag = faFlag; - constructor() {} - ngOnInit(): void { if (this.courseId) { switch (this.navigateTo) { diff --git a/src/main/webapp/app/course/competencies/competency-accordion/competency-accordion.component.ts b/src/main/webapp/app/course/competencies/competency-accordion/competency-accordion.component.ts index 51fd9e4ae16c..0049a4e749ee 100644 --- a/src/main/webapp/app/course/competencies/competency-accordion/competency-accordion.component.ts +++ b/src/main/webapp/app/course/competencies/competency-accordion/competency-accordion.component.ts @@ -1,15 +1,22 @@ -import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, inject } from '@angular/core'; import { faFile, faFilePdf, faList } from '@fortawesome/free-solid-svg-icons'; import { MIN_SCORE_GREEN } from 'app/app.constants'; import { Competency, CompetencyJol, CompetencyProgress, getConfidence, getIcon, getMastery, getProgress } from 'app/entities/competency.model'; import { Course } from 'app/entities/course.model'; -import { Router } from '@angular/router'; +import { Router, RouterLink } from '@angular/router'; import { CompetencyInformation, LectureUnitInformation, StudentMetrics } from 'app/entities/student-metrics.model'; import { round } from 'app/shared/util/utils'; import { Exercise } from 'app/entities/exercise.model'; import dayjs from 'dayjs/esm'; import { LectureUnitType, lectureUnitIcons, lectureUnitTooltips } from 'app/entities/lecture-unit/lectureUnit.model'; import { isStartPracticeAvailable } from 'app/exercises/shared/exercise/exercise.utils'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbProgressbar, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { CompetencyRingsComponent } from '../competency-rings/competency-rings.component'; +import { JudgementOfLearningRatingComponent } from '../judgement-of-learning-rating/judgement-of-learning-rating.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CourseExerciseRowComponent } from 'app/overview/course-exercises/course-exercise-row.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface CompetencyAccordionToggleEvent { opened: boolean; @@ -20,8 +27,21 @@ export interface CompetencyAccordionToggleEvent { selector: 'jhi-competency-accordion', templateUrl: './competency-accordion.component.html', styleUrl: './competency-accordion.component.scss', + imports: [ + FaIconComponent, + NgbTooltip, + NgbProgressbar, + CompetencyRingsComponent, + JudgementOfLearningRatingComponent, + TranslateDirective, + CourseExerciseRowComponent, + RouterLink, + ArtemisTranslatePipe, + ], }) export class CompetencyAccordionComponent implements OnChanges { + private router = inject(Router); + @Input() course: Course | undefined; @Input() competency: CompetencyInformation; @Input() metrics: StudentMetrics; @@ -53,8 +73,6 @@ export class CompetencyAccordionComponent implements OnChanges { protected readonly getMastery = getMastery; protected readonly round = round; - constructor(private router: Router) {} - ngOnChanges(changes: SimpleChanges) { if (changes.openedIndex && this.index !== this.openedIndex) { this.open = false; diff --git a/src/main/webapp/app/course/competencies/competency-card/competency-card.component.ts b/src/main/webapp/app/course/competencies/competency-card/competency-card.component.ts index 462369931d12..6a3293bd12af 100644 --- a/src/main/webapp/app/course/competencies/competency-card/competency-card.component.ts +++ b/src/main/webapp/app/course/competencies/competency-card/competency-card.component.ts @@ -1,14 +1,26 @@ import dayjs from 'dayjs/esm'; -import { Component, input } from '@angular/core'; +import { Component, inject, input } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CompetencyProgress, CourseCompetency, getIcon, getMastery, getProgress } from 'app/entities/competency.model'; +import { RouterLink } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgClass } from '@angular/common'; +import { CompetencyRingsComponent } from '../competency-rings/competency-rings.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { ArtemisTimeAgoPipe } from 'app/shared/pipes/artemis-time-ago.pipe'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-competency-card', templateUrl: './competency-card.component.html', styleUrls: ['../../../overview/course-exercises/course-exercise-row.scss'], + imports: [RouterLink, FaIconComponent, NgbTooltip, TranslateDirective, NgClass, CompetencyRingsComponent, ArtemisTranslatePipe, ArtemisTimeAgoPipe, HtmlForMarkdownPipe], }) export class CompetencyCardComponent { + translateService = inject(TranslateService); + courseId = input(); competency = input(); isPrerequisite = input(); @@ -17,8 +29,6 @@ export class CompetencyCardComponent { protected readonly getIcon = getIcon; - constructor(public translateService: TranslateService) {} - getUserProgress(): CompetencyProgress { const userProgress = this.competency()?.userProgress?.first(); if (userProgress) { diff --git a/src/main/webapp/app/course/competencies/competency-management/competency-management-table.component.ts b/src/main/webapp/app/course/competencies/competency-management/competency-management-table.component.ts index 7d939bdf5c67..a797d97c5883 100644 --- a/src/main/webapp/app/course/competencies/competency-management/competency-management-table.component.ts +++ b/src/main/webapp/app/course/competencies/competency-management/competency-management-table.component.ts @@ -7,7 +7,7 @@ import { filter, map } from 'rxjs/operators'; import { onError } from 'app/shared/util/global.utils'; import { Subject } from 'rxjs'; import { faFileImport, faPencilAlt, faPlus, faTrash } from '@fortawesome/free-solid-svg-icons'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbProgressbar } from '@ng-bootstrap/ng-bootstrap'; import { ImportAllCompetenciesComponent, ImportAllFromCourseResult } from 'app/course/competencies/competency-management/import-all-competencies.component'; import { PrerequisiteService } from 'app/course/competencies/prerequisite.service'; import { ArtemisSharedModule } from 'app/shared/shared.module'; @@ -16,16 +16,16 @@ import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; @Component({ selector: 'jhi-competency-management-table', templateUrl: './competency-management-table.component.html', - standalone: true, - imports: [ArtemisSharedModule, ArtemisMarkdownModule], + imports: [ArtemisSharedModule, ArtemisMarkdownModule, NgbProgressbar], }) export class CompetencyManagementTableComponent implements OnInit, OnDestroy { @Input() courseId: number; @Input() courseCompetencies: CourseCompetency[] = []; - allCompetencies = model.required(); @Input() competencyType: CourseCompetencyType; @Input() standardizedCompetenciesEnabled: boolean; + allCompetencies = model.required(); + @Output() competencyDeleted = new EventEmitter(); service: CompetencyService | PrerequisiteService; diff --git a/src/main/webapp/app/course/competencies/competency-management/competency-management.component.ts b/src/main/webapp/app/course/competencies/competency-management/competency-management.component.ts index c0c3c3936f71..2b80ae142184 100644 --- a/src/main/webapp/app/course/competencies/competency-management/competency-management.component.ts +++ b/src/main/webapp/app/course/competencies/competency-management/competency-management.component.ts @@ -26,7 +26,6 @@ import { toSignal } from '@angular/core/rxjs-interop'; @Component({ selector: 'jhi-competency-management', templateUrl: './competency-management.component.html', - standalone: true, imports: [CompetencyManagementTableComponent, TranslateDirective, FontAwesomeModule, RouterModule, ArtemisSharedComponentModule], }) export class CompetencyManagementComponent implements OnInit { diff --git a/src/main/webapp/app/course/competencies/competency-management/import-all-competencies.component.ts b/src/main/webapp/app/course/competencies/competency-management/import-all-competencies.component.ts index 9774c03a1bbe..ead28d847b8f 100644 --- a/src/main/webapp/app/course/competencies/competency-management/import-all-competencies.component.ts +++ b/src/main/webapp/app/course/competencies/competency-management/import-all-competencies.component.ts @@ -1,13 +1,11 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { Course, CourseForImportDTO } from 'app/entities/course.model'; -import { SortService } from 'app/shared/service/sort.service'; -import { Router } from '@angular/router'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { CourseForImportDTOPagingService } from 'app/course/course-for-import-dto-paging-service'; import { Column, ImportComponent } from 'app/shared/import/import.component'; import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { CourseCompetencyType } from 'app/entities/competency.model'; +import { NgbPagination } from '@ng-bootstrap/ng-bootstrap'; +import { CourseForImportDTOPagingService } from 'app/course/course-for-import-dto-paging-service'; const tableColumns: Column[] = [ { @@ -38,8 +36,7 @@ export type ImportAllFromCourseResult = { @Component({ selector: 'jhi-import-all-competencies', templateUrl: './import-all-competencies.component.html', - standalone: true, - imports: [ArtemisSharedCommonModule, ArtemisSharedComponentModule], + imports: [ArtemisSharedCommonModule, ArtemisSharedComponentModule, NgbPagination], }) export class ImportAllCompetenciesComponent extends ImportComponent { //import relations by default @@ -47,8 +44,9 @@ export class ImportAllCompetenciesComponent extends ImportComponent; @@ -15,10 +12,6 @@ type EntityArrayResponseType = HttpResponse; providedIn: 'root', }) export class CompetencyService extends CourseCompetencyService { - constructor(httpClient: HttpClient, entityTitleService: EntityTitleService, lectureUnitService: LectureUnitService, accountService: AccountService) { - super(httpClient, entityTitleService, lectureUnitService, accountService); - } - getAllForCourse(courseId: number): Observable { return this.httpClient.get(`${this.resourceURL}/courses/${courseId}/competencies`, { observe: 'response' }).pipe( map((res: EntityArrayResponseType) => this.convertArrayResponseDatesFromServer(res)), diff --git a/src/main/webapp/app/course/competencies/components/course-competencies-relation-graph/course-competencies-relation-graph.component.ts b/src/main/webapp/app/course/competencies/components/course-competencies-relation-graph/course-competencies-relation-graph.component.ts index 448d2e4b1d77..1c247e9d1f15 100644 --- a/src/main/webapp/app/course/competencies/components/course-competencies-relation-graph/course-competencies-relation-graph.component.ts +++ b/src/main/webapp/app/course/competencies/components/course-competencies-relation-graph/course-competencies-relation-graph.component.ts @@ -11,7 +11,6 @@ import { CourseCompetencyRelationNodeComponent } from 'app/course/competencies/c @Component({ selector: 'jhi-course-competencies-relation-graph', - standalone: true, imports: [FontAwesomeModule, NgbAccordionModule, NgxGraphModule, ArtemisSharedModule, CourseCompetencyRelationNodeComponent], templateUrl: './course-competencies-relation-graph.component.html', styleUrl: './course-competencies-relation-graph.component.scss', @@ -44,23 +43,20 @@ export class CourseCompetenciesRelationGraphComponent { }); constructor() { - effect( - () => { - return this.nodes.set( - this.courseCompetencies().map( - (courseCompetency): Node => ({ - id: courseCompetency.id!.toString(), - label: courseCompetency.title, - data: { - id: courseCompetency.id, - type: courseCompetency.type, - }, - }), - ), - ); - }, - { allowSignalWrites: true }, - ); + effect(() => { + return this.nodes.set( + this.courseCompetencies().map( + (courseCompetency): Node => ({ + id: courseCompetency.id!.toString(), + label: courseCompetency.title, + data: { + id: courseCompetency.id, + type: courseCompetency.type, + }, + }), + ), + ); + }); } protected selectRelation(relationId: number): void { diff --git a/src/main/webapp/app/course/competencies/components/course-competencies-relation-modal/course-competencies-relation-modal.component.ts b/src/main/webapp/app/course/competencies/components/course-competencies-relation-modal/course-competencies-relation-modal.component.ts index df0547c57a44..ac2a68f7a312 100644 --- a/src/main/webapp/app/course/competencies/components/course-competencies-relation-modal/course-competencies-relation-modal.component.ts +++ b/src/main/webapp/app/course/competencies/components/course-competencies-relation-modal/course-competencies-relation-modal.component.ts @@ -4,15 +4,13 @@ import { CompetencyRelationDTO, CourseCompetency } from 'app/entities/competency import { AlertService } from 'app/core/util/alert.service'; import { onError } from 'app/shared/util/global.utils'; import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; -import { CompetencyGraphComponent } from 'app/course/learning-paths/components/competency-graph/competency-graph.component'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { CourseCompetencyRelationFormComponent } from 'app/course/competencies/components/course-competency-relation-form/course-competency-relation-form.component'; import { CourseCompetenciesRelationGraphComponent } from '../course-competencies-relation-graph/course-competencies-relation-graph.component'; @Component({ selector: 'jhi-course-competencies-relation-modal', - standalone: true, - imports: [ArtemisSharedCommonModule, CompetencyGraphComponent, CourseCompetenciesRelationGraphComponent, CourseCompetencyRelationFormComponent], + imports: [ArtemisSharedCommonModule, CourseCompetenciesRelationGraphComponent, CourseCompetencyRelationFormComponent], templateUrl: './course-competencies-relation-modal.component.html', styleUrl: './course-competencies-relation-modal.component.scss', }) @@ -32,7 +30,7 @@ export class CourseCompetenciesRelationModalComponent { readonly relations = signal([]); constructor() { - effect(() => this.loadRelations(this.courseId()), { allowSignalWrites: true }); + effect(() => this.loadRelations(this.courseId())); } private async loadRelations(courseId: number): Promise { diff --git a/src/main/webapp/app/course/competencies/components/course-competency-explanation-modal/course-competency-explanation-modal.component.ts b/src/main/webapp/app/course/competencies/components/course-competency-explanation-modal/course-competency-explanation-modal.component.ts index 8cd333d439f3..44176e8f570f 100644 --- a/src/main/webapp/app/course/competencies/components/course-competency-explanation-modal/course-competency-explanation-modal.component.ts +++ b/src/main/webapp/app/course/competencies/components/course-competency-explanation-modal/course-competency-explanation-modal.component.ts @@ -2,13 +2,11 @@ import { Component, inject } from '@angular/core'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; import { faXmark } from '@fortawesome/free-solid-svg-icons'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { CompetencyGraphComponent } from 'app/course/learning-paths/components/competency-graph/competency-graph.component'; import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-course-competency-explanation-modal', - standalone: true, - imports: [CompetencyGraphComponent, TranslateDirective, FontAwesomeModule], + imports: [TranslateDirective, FontAwesomeModule], templateUrl: './course-competency-explanation-modal.component.html', styleUrl: './course-competency-explanation-modal.component.scss', }) diff --git a/src/main/webapp/app/course/competencies/components/course-competency-relation-form/course-competency-relation-form.component.ts b/src/main/webapp/app/course/competencies/components/course-competency-relation-form/course-competency-relation-form.component.ts index 7f173f4968a3..9a3fb9df3760 100644 --- a/src/main/webapp/app/course/competencies/components/course-competency-relation-form/course-competency-relation-form.component.ts +++ b/src/main/webapp/app/course/competencies/components/course-competency-relation-form/course-competency-relation-form.component.ts @@ -7,7 +7,6 @@ import { faSpinner } from '@fortawesome/free-solid-svg-icons'; @Component({ selector: 'jhi-course-competency-relation-form', - standalone: true, imports: [ArtemisSharedCommonModule], templateUrl: './course-competency-relation-form.component.html', styleUrl: './course-competency-relation-form.component.scss', @@ -44,7 +43,7 @@ export class CourseCompetencyRelationFormComponent { readonly showCircularDependencyError = computed(() => this.tailCompetencyId() && !this.selectableTailCourseCompetencyIds().includes(this.tailCompetencyId()!)); constructor() { - effect(() => this.selectRelation(this.selectedRelationId()), { allowSignalWrites: true }); + effect(() => this.selectRelation(this.selectedRelationId())); } protected isCourseCompetencySelectable(courseCompetencyId: number): boolean { diff --git a/src/main/webapp/app/course/competencies/components/course-competency-relation-node/course-competency-relation-node.component.ts b/src/main/webapp/app/course/competencies/components/course-competency-relation-node/course-competency-relation-node.component.ts index 48708b6ed23c..97dd903908f7 100644 --- a/src/main/webapp/app/course/competencies/components/course-competency-relation-node/course-competency-relation-node.component.ts +++ b/src/main/webapp/app/course/competencies/components/course-competency-relation-node/course-competency-relation-node.component.ts @@ -9,7 +9,6 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; @Component({ selector: 'jhi-course-competency-relation-node', - standalone: true, imports: [NgClass, TranslateDirective, NgbTooltipModule, ArtemisSharedModule], templateUrl: './course-competency-relation-node.component.html', styleUrl: './course-competency-relation-node.component.scss', diff --git a/src/main/webapp/app/course/competencies/components/import-all-course-competencies-modal/import-all-course-competencies-modal.component.ts b/src/main/webapp/app/course/competencies/components/import-all-course-competencies-modal/import-all-course-competencies-modal.component.ts index 5ef319c926d2..b4f5b880d434 100644 --- a/src/main/webapp/app/course/competencies/components/import-all-course-competencies-modal/import-all-course-competencies-modal.component.ts +++ b/src/main/webapp/app/course/competencies/components/import-all-course-competencies-modal/import-all-course-competencies-modal.component.ts @@ -12,6 +12,7 @@ import { ImportCourseCompetenciesSettingsComponent, } from 'app/course/competencies/components/import-course-competencies-settings/import-course-competencies-settings.component'; import { CourseCompetencyImportOptionsDTO } from 'app/entities/competency.model'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; const tableColumns: Column[] = [ { @@ -35,8 +36,7 @@ export interface ImportAllCourseCompetenciesResult { @Component({ selector: 'jhi-import-all-course-competencies-modal', - standalone: true, - imports: [ArtemisSharedCommonModule, ImportTableComponent, ImportCourseCompetenciesSettingsComponent], + imports: [ArtemisSharedCommonModule, ImportTableComponent, ImportCourseCompetenciesSettingsComponent, FaIconComponent], providers: [ { provide: PagingService, @@ -55,7 +55,7 @@ export class ImportAllCourseCompetenciesModalComponent { readonly courseId = input.required(); readonly disabledIds = computed(() => [+this.courseId()]); - readonly importSettings = signal(new CourseCompetencyImportSettings()); + importSettings = signal(new CourseCompetencyImportSettings()); public selectCourse(course: Course): void { const courseCompetencyImportOptions = { diff --git a/src/main/webapp/app/course/competencies/components/import-course-competencies-settings/import-course-competencies-settings.component.ts b/src/main/webapp/app/course/competencies/components/import-course-competencies-settings/import-course-competencies-settings.component.ts index 18ad7e777499..641b41b90334 100644 --- a/src/main/webapp/app/course/competencies/components/import-course-competencies-settings/import-course-competencies-settings.component.ts +++ b/src/main/webapp/app/course/competencies/components/import-course-competencies-settings/import-course-competencies-settings.component.ts @@ -1,10 +1,10 @@ import { CommonModule } from '@angular/common'; import { Component, computed, model } from '@angular/core'; +import { FormsModule } from '@angular/forms'; import { OwlDateTimeModule, OwlNativeDateTimeModule } from '@danielmoncada/angular-datetime-picker'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; import { faCalendarAlt, faCircleXmark, faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; import { FormDateTimePickerModule } from 'app/shared/date-time-picker/date-time-picker.module'; -import { FormsModule } from 'app/forms/forms.module'; import { ArtemisSharedModule } from 'app/shared/shared.module'; export class CourseCompetencyImportSettings { @@ -17,7 +17,6 @@ export class CourseCompetencyImportSettings { @Component({ selector: 'jhi-import-course-competencies-settings', - standalone: true, imports: [FormDateTimePickerModule, FormsModule, CommonModule, FontAwesomeModule, OwlDateTimeModule, OwlNativeDateTimeModule, ArtemisSharedModule], templateUrl: './import-course-competencies-settings.component.html', styleUrl: './import-course-competencies-settings.component.scss', diff --git a/src/main/webapp/app/course/competencies/course-competency.service.ts b/src/main/webapp/app/course/competencies/course-competency.service.ts index 6e2f4c4046a8..aec314d7516c 100644 --- a/src/main/webapp/app/course/competencies/course-competency.service.ts +++ b/src/main/webapp/app/course/competencies/course-competency.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { @@ -40,14 +40,12 @@ type CompetencyJolMapResponseType = HttpResponse<{ providedIn: 'root', }) export class CourseCompetencyService { - protected resourceURL = 'api'; + protected httpClient = inject(HttpClient); + protected entityTitleService = inject(EntityTitleService); + protected lectureUnitService = inject(LectureUnitService); + protected accountService = inject(AccountService); - constructor( - protected httpClient: HttpClient, - protected entityTitleService: EntityTitleService, - protected lectureUnitService: LectureUnitService, - protected accountService: AccountService, - ) {} + protected resourceURL = 'api'; getForImport(pageable: CompetencyPageableSearch) { const params = this.createCompetencySearchHttpParams(pageable); diff --git a/src/main/webapp/app/course/competencies/create/create-competency.component.ts b/src/main/webapp/app/course/competencies/create/create-competency.component.ts index 267d9016631c..60e33916c93f 100644 --- a/src/main/webapp/app/course/competencies/create/create-competency.component.ts +++ b/src/main/webapp/app/course/competencies/create/create-competency.component.ts @@ -1,12 +1,9 @@ -import { Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { onError } from 'app/shared/util/global.utils'; import { Competency } from 'app/entities/competency.model'; -import { ActivatedRoute, Router } from '@angular/router'; -import { AlertService } from 'app/core/util/alert.service'; import { CompetencyService } from 'app/course/competencies/competency.service'; import { finalize } from 'rxjs/operators'; import { HttpErrorResponse } from '@angular/common/http'; -import { LectureService } from 'app/lecture/lecture.service'; import { CompetencyFormComponent } from 'app/course/competencies/forms/competency/competency-form.component'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; @@ -16,22 +13,12 @@ import { CourseCompetencyFormData } from 'app/course/competencies/forms/course-c @Component({ selector: 'jhi-create-competency', templateUrl: './create-competency.component.html', - styles: [], - standalone: true, imports: [ArtemisSharedModule, CompetencyFormComponent, ArtemisSharedComponentModule], }) export class CreateCompetencyComponent extends CreateCourseCompetencyComponent { - competencyToCreate: Competency = new Competency(); + private competencyService = inject(CompetencyService); - constructor( - activatedRoute: ActivatedRoute, - router: Router, - alertService: AlertService, - lectureService: LectureService, - private competencyService: CompetencyService, - ) { - super(activatedRoute, router, alertService, lectureService); - } + competencyToCreate: Competency = new Competency(); createCompetency(formData: CourseCompetencyFormData) { if (!formData?.title) { diff --git a/src/main/webapp/app/course/competencies/create/create-course-competency.component.ts b/src/main/webapp/app/course/competencies/create/create-course-competency.component.ts index 0f7884c980df..f79e6cb7288e 100644 --- a/src/main/webapp/app/course/competencies/create/create-course-competency.component.ts +++ b/src/main/webapp/app/course/competencies/create/create-course-competency.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { onError } from 'app/shared/util/global.utils'; import { ActivatedRoute, Router } from '@angular/router'; import { AlertService } from 'app/core/util/alert.service'; @@ -8,21 +8,21 @@ import { LectureService } from 'app/lecture/lecture.service'; import { Lecture } from 'app/entities/lecture.model'; import { DocumentationType } from 'app/shared/components/documentation-button/documentation-button.component'; -@Component({ template: '' }) +@Component({ + template: '', +}) export abstract class CreateCourseCompetencyComponent implements OnInit { + protected activatedRoute = inject(ActivatedRoute); + protected router = inject(Router); + protected alertService = inject(AlertService); + protected lectureService = inject(LectureService); + readonly documentationType: DocumentationType = 'Competencies'; isLoading: boolean; courseId: number; lecturesWithLectureUnits: Lecture[] = []; - constructor( - protected activatedRoute: ActivatedRoute, - protected router: Router, - protected alertService: AlertService, - protected lectureService: LectureService, - ) {} - ngOnInit(): void { this.isLoading = true; this.activatedRoute diff --git a/src/main/webapp/app/course/competencies/create/create-prerequisite.component.ts b/src/main/webapp/app/course/competencies/create/create-prerequisite.component.ts index befbdfb3478e..f369a6670ed2 100644 --- a/src/main/webapp/app/course/competencies/create/create-prerequisite.component.ts +++ b/src/main/webapp/app/course/competencies/create/create-prerequisite.component.ts @@ -1,14 +1,11 @@ -import { Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { onError } from 'app/shared/util/global.utils'; -import { ActivatedRoute, Router } from '@angular/router'; -import { AlertService } from 'app/core/util/alert.service'; import { finalize } from 'rxjs/operators'; import { HttpErrorResponse } from '@angular/common/http'; import { Prerequisite } from 'app/entities/prerequisite.model'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { PrerequisiteFormComponent } from 'app/course/competencies/forms/prerequisite/prerequisite-form.component'; import { CreateCourseCompetencyComponent } from 'app/course/competencies/create/create-course-competency.component'; -import { LectureService } from 'app/lecture/lecture.service'; import { PrerequisiteService } from 'app/course/competencies/prerequisite.service'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { CourseCompetencyFormData } from 'app/course/competencies/forms/course-competency-form.component'; @@ -16,21 +13,12 @@ import { CourseCompetencyFormData } from 'app/course/competencies/forms/course-c @Component({ selector: 'jhi-create-prerequisite', templateUrl: './create-prerequisite.component.html', - standalone: true, imports: [ArtemisSharedModule, PrerequisiteFormComponent, ArtemisSharedComponentModule], }) export class CreatePrerequisiteComponent extends CreateCourseCompetencyComponent { - prerequisiteToCreate: Prerequisite = new Prerequisite(); + private prerequisiteService = inject(PrerequisiteService); - constructor( - activatedRoute: ActivatedRoute, - router: Router, - alertService: AlertService, - lectureService: LectureService, - private prerequisiteService: PrerequisiteService, - ) { - super(activatedRoute, router, alertService, lectureService); - } + prerequisiteToCreate: Prerequisite = new Prerequisite(); createPrerequisite(formData: CourseCompetencyFormData) { if (!formData?.title) { diff --git a/src/main/webapp/app/course/competencies/edit/edit-competency.component.ts b/src/main/webapp/app/course/competencies/edit/edit-competency.component.ts index 7ea6f4b22b76..0f3648211cf2 100644 --- a/src/main/webapp/app/course/competencies/edit/edit-competency.component.ts +++ b/src/main/webapp/app/course/competencies/edit/edit-competency.component.ts @@ -1,12 +1,9 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { onError } from 'app/shared/util/global.utils'; import { Competency } from 'app/entities/competency.model'; -import { ActivatedRoute, Router } from '@angular/router'; -import { AlertService } from 'app/core/util/alert.service'; import { finalize, switchMap, take } from 'rxjs/operators'; import { CompetencyService } from 'app/course/competencies/competency.service'; import { HttpErrorResponse } from '@angular/common/http'; -import { LectureService } from 'app/lecture/lecture.service'; import { combineLatest, forkJoin } from 'rxjs'; import { CompetencyFormComponent } from 'app/course/competencies/forms/competency/competency-form.component'; import { ArtemisSharedModule } from 'app/shared/shared.module'; @@ -16,23 +13,14 @@ import { CourseCompetencyFormData } from 'app/course/competencies/forms/course-c @Component({ selector: 'jhi-edit-competency', templateUrl: './edit-competency.component.html', - standalone: true, imports: [ArtemisSharedModule, CompetencyFormComponent], }) export class EditCompetencyComponent extends EditCourseCompetencyComponent implements OnInit { + private competencyService = inject(CompetencyService); + competency: Competency; formData: CourseCompetencyFormData; - constructor( - activatedRoute: ActivatedRoute, - lectureService: LectureService, - router: Router, - alertService: AlertService, - private competencyService: CompetencyService, - ) { - super(activatedRoute, lectureService, router, alertService); - } - ngOnInit(): void { super.ngOnInit(); diff --git a/src/main/webapp/app/course/competencies/edit/edit-course-competency.component.ts b/src/main/webapp/app/course/competencies/edit/edit-course-competency.component.ts index d44a05d3cf25..1d370bd85791 100644 --- a/src/main/webapp/app/course/competencies/edit/edit-course-competency.component.ts +++ b/src/main/webapp/app/course/competencies/edit/edit-course-competency.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { onError } from 'app/shared/util/global.utils'; import { ActivatedRoute, Router } from '@angular/router'; import { AlertService } from 'app/core/util/alert.service'; @@ -8,19 +8,19 @@ import { LectureService } from 'app/lecture/lecture.service'; import { Lecture } from 'app/entities/lecture.model'; import { LectureUnitType } from 'app/entities/lecture-unit/lectureUnit.model'; -@Component({ template: '' }) +@Component({ + template: '', +}) export abstract class EditCourseCompetencyComponent implements OnInit { + protected activatedRoute = inject(ActivatedRoute); + protected lectureService = inject(LectureService); + protected router = inject(Router); + protected alertService = inject(AlertService); + isLoading = false; lecturesWithLectureUnits: Lecture[] = []; courseId: number; - constructor( - protected activatedRoute: ActivatedRoute, - protected lectureService: LectureService, - protected router: Router, - protected alertService: AlertService, - ) {} - ngOnInit(): void { this.isLoading = true; this.activatedRoute.parent?.parent?.paramMap diff --git a/src/main/webapp/app/course/competencies/edit/edit-prerequisite.component.ts b/src/main/webapp/app/course/competencies/edit/edit-prerequisite.component.ts index d11ecd71c7fb..c8cf992c24b5 100644 --- a/src/main/webapp/app/course/competencies/edit/edit-prerequisite.component.ts +++ b/src/main/webapp/app/course/competencies/edit/edit-prerequisite.component.ts @@ -1,10 +1,7 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { onError } from 'app/shared/util/global.utils'; -import { ActivatedRoute, Router } from '@angular/router'; -import { AlertService } from 'app/core/util/alert.service'; import { finalize, switchMap, take } from 'rxjs/operators'; import { HttpErrorResponse } from '@angular/common/http'; -import { LectureService } from 'app/lecture/lecture.service'; import { combineLatest, forkJoin } from 'rxjs'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { EditCourseCompetencyComponent } from 'app/course/competencies/edit/edit-course-competency.component'; @@ -16,23 +13,14 @@ import { CourseCompetencyFormData } from 'app/course/competencies/forms/course-c @Component({ selector: 'jhi-edit-prerequisite', templateUrl: './edit-prerequisite.component.html', - standalone: true, imports: [ArtemisSharedModule, PrerequisiteFormComponent], }) export class EditPrerequisiteComponent extends EditCourseCompetencyComponent implements OnInit { + private prerequisiteService = inject(PrerequisiteService); + prerequisite: Prerequisite; formData: CourseCompetencyFormData; - constructor( - activatedRoute: ActivatedRoute, - lectureService: LectureService, - router: Router, - alertService: AlertService, - private prerequisiteService: PrerequisiteService, - ) { - super(activatedRoute, lectureService, router, alertService); - } - ngOnInit(): void { super.ngOnInit(); diff --git a/src/main/webapp/app/course/competencies/forms/common-course-competency-form.component.ts b/src/main/webapp/app/course/competencies/forms/common-course-competency-form.component.ts index e7c2cadf3ad4..032d89d0b395 100644 --- a/src/main/webapp/app/course/competencies/forms/common-course-competency-form.component.ts +++ b/src/main/webapp/app/course/competencies/forms/common-course-competency-form.component.ts @@ -1,8 +1,7 @@ -import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; -import { FormControl, FormGroup } from '@angular/forms'; +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, inject } from '@angular/core'; +import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; import { Lecture } from 'app/entities/lecture.model'; import { TranslateService } from '@ngx-translate/core'; -import { LectureUnitService } from 'app/lecture/lecture-unit/lecture-unit-management/lectureUnit.service'; import { CompetencyTaxonomy, CourseCompetency, CourseCompetencyValidators, DEFAULT_MASTERY_THRESHOLD } from 'app/entities/competency.model'; import { faQuestionCircle, faTimes } from '@fortawesome/free-solid-svg-icons'; import { CourseCompetencyFormData } from 'app/course/competencies/forms/course-competency-form.component'; @@ -10,49 +9,42 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; import { FormDateTimePickerModule } from 'app/shared/date-time-picker/date-time-picker.module'; import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; -import { FormsModule } from 'app/forms/forms.module'; import { ArtemisCompetenciesModule } from 'app/course/competencies/competency.module'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { merge } from 'rxjs'; import { ArtemisMarkdownEditorModule } from 'app/shared/markdown-editor/markdown-editor.module'; import { DateTimePickerType } from 'app/shared/date-time-picker/date-time-picker.component'; +import { ArtemisFormsModule } from 'app/forms/artemis-forms.module'; @Component({ selector: 'jhi-common-course-competency-form', templateUrl: './common-course-competency-form.component.html', styleUrls: ['./common-course-competency-form.component.scss'], - standalone: true, imports: [ ArtemisSharedModule, FormDateTimePickerModule, ArtemisMarkdownModule, NgbDropdownModule, - FormsModule, + ArtemisFormsModule, + ReactiveFormsModule, ArtemisCompetenciesModule, ArtemisSharedComponentModule, ArtemisMarkdownEditorModule, ], }) export class CommonCourseCompetencyFormComponent implements OnInit, OnChanges { - @Input() - formData: CourseCompetencyFormData; - @Input() - isEditMode = false; - @Input() - isInConnectMode = false; - @Input() - isInSingleLectureMode = false; - @Input() - lecturesOfCourseWithLectureUnits: Lecture[] = []; - @Input() - averageStudentScore?: number; - @Input() - form: FormGroup; - @Input() - courseCompetency: CourseCompetency; + private translateService = inject(TranslateService); - @Output() - onTitleOrDescriptionChange = new EventEmitter(); + @Input() formData: CourseCompetencyFormData; + @Input() isEditMode = false; + @Input() isInConnectMode = false; + @Input() isInSingleLectureMode = false; + @Input() lecturesOfCourseWithLectureUnits: Lecture[] = []; + @Input() averageStudentScore?: number; + @Input() form: FormGroup; + @Input() courseCompetency: CourseCompetency; + + @Output() onTitleOrDescriptionChange = new EventEmitter(); protected readonly competencyValidators = CourseCompetencyValidators; protected readonly DateTimePickerType = DateTimePickerType; @@ -66,11 +58,6 @@ export class CommonCourseCompetencyFormComponent implements OnInit, OnChanges { protected readonly DEFAULT_MASTERY_THRESHOLD = DEFAULT_MASTERY_THRESHOLD; protected readonly competencyTaxonomy = CompetencyTaxonomy; - constructor( - private translateService: TranslateService, - public lectureUnitService: LectureUnitService, - ) {} - get titleControl() { return this.form.get('title'); } @@ -79,14 +66,6 @@ export class CommonCourseCompetencyFormComponent implements OnInit, OnChanges { return this.form.get('description'); } - get softDueDateControl() { - return this.form.get('softDueDate'); - } - - get optionalControl() { - return this.form.get('optional'); - } - get masteryThresholdControl() { return this.form.get('masteryThreshold'); } diff --git a/src/main/webapp/app/course/competencies/forms/competency/competency-form.component.ts b/src/main/webapp/app/course/competencies/forms/competency/competency-form.component.ts index 7468236ef661..f3856ecb1c28 100644 --- a/src/main/webapp/app/course/competencies/forms/competency/competency-form.component.ts +++ b/src/main/webapp/app/course/competencies/forms/competency/competency-form.component.ts @@ -1,23 +1,18 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; -import { FormBuilder } from '@angular/forms'; -import { CompetencyService } from 'app/course/competencies/competency.service'; -import { LectureUnitService } from 'app/lecture/lecture-unit/lecture-unit-management/lectureUnit.service'; import { CourseCompetencyFormComponent, CourseCompetencyFormData } from 'app/course/competencies/forms/course-competency-form.component'; -import { TranslateService } from '@ngx-translate/core'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { CommonCourseCompetencyFormComponent } from 'app/course/competencies/forms/common-course-competency-form.component'; import { Competency } from 'app/entities/competency.model'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; @Component({ selector: 'jhi-competency-form', templateUrl: './competency-form.component.html', styleUrls: ['./competency-form.component.scss'], - standalone: true, - imports: [ArtemisSharedModule, CommonCourseCompetencyFormComponent], + imports: [ArtemisSharedModule, CommonCourseCompetencyFormComponent, FormsModule, ReactiveFormsModule], }) export class CompetencyFormComponent extends CourseCompetencyFormComponent implements OnInit, OnChanges { - @Input() - formData: CourseCompetencyFormData = { + @Input() formData: CourseCompetencyFormData = { id: undefined, title: undefined, description: undefined, @@ -26,15 +21,9 @@ export class CompetencyFormComponent extends CourseCompetencyFormComponent imple masteryThreshold: undefined, optional: false, }; - @Input() - competency: Competency; + @Input() competency: Competency; - @Output() - formSubmitted: EventEmitter = new EventEmitter(); - - constructor(fb: FormBuilder, lectureUnitService: LectureUnitService, competencyService: CompetencyService, translateService: TranslateService) { - super(fb, lectureUnitService, competencyService, translateService); - } + @Output() formSubmitted: EventEmitter = new EventEmitter(); ngOnChanges(): void { this.initializeForm(); diff --git a/src/main/webapp/app/course/competencies/forms/course-competency-form.component.ts b/src/main/webapp/app/course/competencies/forms/course-competency-form.component.ts index ab3a23b96d90..c05e338df3d4 100644 --- a/src/main/webapp/app/course/competencies/forms/course-competency-form.component.ts +++ b/src/main/webapp/app/course/competencies/forms/course-competency-form.component.ts @@ -1,14 +1,12 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output, inject } from '@angular/core'; import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; import { of } from 'rxjs'; import { catchError, delay, map, switchMap } from 'rxjs/operators'; import { Lecture } from 'app/entities/lecture.model'; -import { LectureUnitService } from 'app/lecture/lecture-unit/lecture-unit-management/lectureUnit.service'; import { CompetencyTaxonomy, DEFAULT_MASTERY_THRESHOLD } from 'app/entities/competency.model'; import { faQuestionCircle, faTimes } from '@fortawesome/free-solid-svg-icons'; import dayjs from 'dayjs/esm'; import { CourseCompetencyService } from 'app/course/competencies/course-competency.service'; -import { TranslateService } from '@ngx-translate/core'; /** * Async Validator to make sure that a competency title is unique within a course @@ -49,29 +47,25 @@ export interface CourseCompetencyFormData { masteryThreshold?: number; } -@Component({ template: '' }) +@Component({ + template: '', +}) export abstract class CourseCompetencyFormComponent { abstract formData: CourseCompetencyFormData; - @Input() - isEditMode = false; - @Input() - isInConnectMode = false; - @Input() - isInSingleLectureMode = false; - @Input() - courseId: number; - @Input() - lecturesOfCourseWithLectureUnits: Lecture[] = []; - @Input() - averageStudentScore?: number; - @Input() - hasCancelButton: boolean; - - @Output() - onCancel: EventEmitter = new EventEmitter(); - @Output() - formSubmitted: EventEmitter = new EventEmitter(); + private fb = inject(FormBuilder); + private courseCompetencyService = inject(CourseCompetencyService); + + @Input() isEditMode = false; + @Input() isInConnectMode = false; + @Input() isInSingleLectureMode = false; + @Input() courseId: number; + @Input() lecturesOfCourseWithLectureUnits: Lecture[] = []; + @Input() averageStudentScore?: number; + @Input() hasCancelButton: boolean; + + @Output() onCancel: EventEmitter = new EventEmitter(); + @Output() formSubmitted: EventEmitter = new EventEmitter(); form: FormGroup; @@ -79,13 +73,6 @@ export abstract class CourseCompetencyFormComponent { protected readonly faTimes = faTimes; protected readonly faQuestionCircle = faQuestionCircle; - protected constructor( - protected fb: FormBuilder, - protected lectureUnitService: LectureUnitService, - protected courseCompetencyService: CourseCompetencyService, - protected translateService: TranslateService, - ) {} - get titleControl() { return this.form.get('title'); } diff --git a/src/main/webapp/app/course/competencies/forms/prerequisite/prerequisite-form.component.ts b/src/main/webapp/app/course/competencies/forms/prerequisite/prerequisite-form.component.ts index 9ce65f93af81..c6315147f171 100644 --- a/src/main/webapp/app/course/competencies/forms/prerequisite/prerequisite-form.component.ts +++ b/src/main/webapp/app/course/competencies/forms/prerequisite/prerequisite-form.component.ts @@ -1,24 +1,19 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; -import { FormBuilder } from '@angular/forms'; -import { LectureUnitService } from 'app/lecture/lecture-unit/lecture-unit-management/lectureUnit.service'; import { CourseCompetencyFormComponent, CourseCompetencyFormData } from 'app/course/competencies/forms/course-competency-form.component'; -import { TranslateService } from '@ngx-translate/core'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { CommonCourseCompetencyFormComponent } from 'app/course/competencies/forms/common-course-competency-form.component'; import { CourseCompetencyType } from 'app/entities/competency.model'; -import { PrerequisiteService } from 'app/course/competencies/prerequisite.service'; import { Prerequisite } from 'app/entities/prerequisite.model'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; @Component({ selector: 'jhi-prerequisite-form', templateUrl: './prerequisite-form.component.html', styleUrls: ['./prerequisite-form.component.scss'], - standalone: true, - imports: [ArtemisSharedModule, CommonCourseCompetencyFormComponent], + imports: [ArtemisSharedModule, CommonCourseCompetencyFormComponent, FormsModule, ReactiveFormsModule], }) export class PrerequisiteFormComponent extends CourseCompetencyFormComponent implements OnInit, OnChanges { - @Input() - formData: CourseCompetencyFormData = { + @Input() formData: CourseCompetencyFormData = { id: undefined, title: undefined, description: undefined, @@ -27,18 +22,12 @@ export class PrerequisiteFormComponent extends CourseCompetencyFormComponent imp masteryThreshold: undefined, optional: false, }; - @Input() - prerequisite: Prerequisite; + @Input() prerequisite: Prerequisite; - @Output() - formSubmitted: EventEmitter = new EventEmitter(); + @Output() formSubmitted: EventEmitter = new EventEmitter(); readonly CourseCompetencyType = CourseCompetencyType; - constructor(fb: FormBuilder, lectureUnitService: LectureUnitService, prerequisiteService: PrerequisiteService, translateService: TranslateService) { - super(fb, lectureUnitService, prerequisiteService, translateService); - } - ngOnChanges(): void { this.initializeForm(); if (this.isEditMode && this.formData) { diff --git a/src/main/webapp/app/course/competencies/generate-competencies/competency-recommendation-detail.component.ts b/src/main/webapp/app/course/competencies/generate-competencies/competency-recommendation-detail.component.ts index 5e44f690d966..1a7eac6e42fa 100644 --- a/src/main/webapp/app/course/competencies/generate-competencies/competency-recommendation-detail.component.ts +++ b/src/main/webapp/app/course/competencies/generate-competencies/competency-recommendation-detail.component.ts @@ -2,13 +2,31 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { CourseCompetencyValidators } from 'app/entities/competency.model'; import { faChevronRight, faPencilAlt, faSave, faTrash, faWrench } from '@fortawesome/free-solid-svg-icons'; import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; -import { FormGroup, Validators } from '@angular/forms'; +import { FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { CompetencyFormControlsWithViewed } from 'app/course/competencies/generate-competencies/generate-competencies.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { NgbCollapse } from '@ng-bootstrap/ng-bootstrap'; +import { MarkdownEditorMonacoComponent } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { TaxonomySelectComponent } from '../taxonomy-select/taxonomy-select.component'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-competency-recommendation', templateUrl: './competency-recommendation-detail.component.html', styleUrls: ['competency-recommendation-detail.component.scss'], + imports: [ + FormsModule, + ReactiveFormsModule, + FaIconComponent, + TranslateDirective, + ButtonComponent, + NgbCollapse, + MarkdownEditorMonacoComponent, + TaxonomySelectComponent, + HtmlForMarkdownPipe, + ], }) export class CompetencyRecommendationDetailComponent implements OnInit { @Input({ required: true }) form: FormGroup; diff --git a/src/main/webapp/app/course/competencies/generate-competencies/course-description-form.component.ts b/src/main/webapp/app/course/competencies/generate-competencies/course-description-form.component.ts index a466747c670b..803812f6a915 100644 --- a/src/main/webapp/app/course/competencies/generate-competencies/course-description-form.component.ts +++ b/src/main/webapp/app/course/competencies/generate-competencies/course-description-form.component.ts @@ -1,13 +1,21 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; +import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core'; +import { FormBuilder, FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; import { ButtonType } from 'app/shared/components/button.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { IrisLogoButtonComponent } from 'app/iris/iris-logo-button/iris-logo-button.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-course-description-form', templateUrl: './course-description-form.component.html', + imports: [FormsModule, ReactiveFormsModule, TranslateDirective, FaIconComponent, NgbTooltip, IrisLogoButtonComponent, ArtemisTranslatePipe], }) export class CourseDescriptionFormComponent implements OnInit { + private formBuilder = inject(FormBuilder); + @Input() isLoading = false; @Input() placeholder = ''; @Output() formSubmitted: EventEmitter = new EventEmitter(); @@ -23,8 +31,6 @@ export class CourseDescriptionFormComponent implements OnInit { protected readonly DESCRIPTION_MIN = 100; protected readonly ButtonType = ButtonType; - constructor(private formBuilder: FormBuilder) {} - ngOnInit(): void { this.form = this.formBuilder.group({ courseDescription: [this.placeholder, [Validators.required, Validators.minLength(this.DESCRIPTION_MIN), Validators.maxLength(this.DESCRIPTION_MAX)]], diff --git a/src/main/webapp/app/course/competencies/generate-competencies/generate-competencies.component.ts b/src/main/webapp/app/course/competencies/generate-competencies/generate-competencies.component.ts index 19d3d33b6124..feac299ebb06 100644 --- a/src/main/webapp/app/course/competencies/generate-competencies/generate-competencies.component.ts +++ b/src/main/webapp/app/course/competencies/generate-competencies/generate-competencies.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, ViewChild } from '@angular/core'; +import { Component, OnInit, ViewChild, inject } from '@angular/core'; import { CompetencyService } from 'app/course/competencies/competency.service'; import { AlertService } from 'app/core/util/alert.service'; import { onError } from 'app/shared/util/global.utils'; @@ -6,7 +6,7 @@ import { HttpErrorResponse } from '@angular/common/http'; import { Competency, CompetencyTaxonomy } from 'app/entities/competency.model'; import { ActivatedRoute, Router } from '@angular/router'; import { faBan, faSave, faTimes } from '@fortawesome/free-solid-svg-icons'; -import { FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms'; +import { FormArray, FormBuilder, FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { ButtonType } from 'app/shared/components/button.component'; import { ComponentCanDeactivate } from 'app/shared/guard/can-deactivate.model'; import { ConfirmAutofocusModalComponent } from 'app/shared/components/confirm-autofocus-modal.component'; @@ -49,10 +49,21 @@ type CompetencyGenerationStatusUpdate = { @Component({ selector: 'jhi-generate-competencies', templateUrl: './generate-competencies.component.html', - standalone: true, - imports: [ArtemisSharedCommonModule, ArtemisSharedComponentModule, ArtemisCompetenciesModule], + imports: [ArtemisSharedCommonModule, ArtemisSharedComponentModule, ArtemisCompetenciesModule, FormsModule, ReactiveFormsModule], }) export class GenerateCompetenciesComponent implements OnInit, ComponentCanDeactivate { + private courseManagementService = inject(CourseManagementService); + private courseCompetencyService = inject(CourseCompetencyService); + private competencyService = inject(CompetencyService); + private alertService = inject(AlertService); + private activatedRoute = inject(ActivatedRoute); + private router = inject(Router); + private formBuilder = inject(FormBuilder); + private modalService = inject(NgbModal); + private artemisTranslatePipe = inject(ArtemisTranslatePipe); + private translateService = inject(TranslateService); + private jhiWebsocketService = inject(JhiWebsocketService); + @ViewChild(CourseDescriptionFormComponent) courseDescriptionForm: CourseDescriptionFormComponent; courseId: number; @@ -69,20 +80,6 @@ export class GenerateCompetenciesComponent implements OnInit, ComponentCanDeacti protected readonly ButtonType = ButtonType; readonly documentationType: DocumentationType = 'GenerateCompetencies'; - constructor( - private courseManagementService: CourseManagementService, - private courseCompetencyService: CourseCompetencyService, - private competencyService: CompetencyService, - private alertService: AlertService, - private activatedRoute: ActivatedRoute, - private router: Router, - private formBuilder: FormBuilder, - private modalService: NgbModal, - private artemisTranslatePipe: ArtemisTranslatePipe, - private translateService: TranslateService, - private jhiWebsocketService: JhiWebsocketService, - ) {} - ngOnInit(): void { this.activatedRoute.params.subscribe((params) => { this.courseId = Number(params['courseId']); diff --git a/src/main/webapp/app/course/competencies/import-standardized-competencies/course-import-standardized-competencies.component.ts b/src/main/webapp/app/course/competencies/import-standardized-competencies/course-import-standardized-competencies.component.ts index 7186b318de76..19c516b94442 100644 --- a/src/main/webapp/app/course/competencies/import-standardized-competencies/course-import-standardized-competencies.component.ts +++ b/src/main/webapp/app/course/competencies/import-standardized-competencies/course-import-standardized-competencies.component.ts @@ -1,9 +1,4 @@ -import { ActivatedRoute, Router } from '@angular/router'; -import { Component } from '@angular/core'; -import { AlertService } from 'app/core/util/alert.service'; -import { TranslateService } from '@ngx-translate/core'; -import { SortService } from 'app/shared/service/sort.service'; -import { StandardizedCompetencyService } from 'app/shared/standardized-competencies/standardized-competency.service'; +import { Component, inject } from '@angular/core'; import { CompetencyService } from 'app/course/competencies/competency.service'; import { CourseImportStandardizedCourseCompetenciesComponent } from 'app/course/competencies/import-standardized-competencies/course-import-standardized-course-competencies.component'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; @@ -16,7 +11,6 @@ import { KnowledgeAreaTreeComponent } from 'app/shared/standardized-competencies @Component({ selector: 'jhi-course-import-standardized-competencies', templateUrl: './course-import-standardized-competencies.component.html', - standalone: true, imports: [ ArtemisSharedCommonModule, ArtemisSharedComponentModule, @@ -27,17 +21,7 @@ import { KnowledgeAreaTreeComponent } from 'app/shared/standardized-competencies ], }) export class CourseImportStandardizedCompetenciesComponent extends CourseImportStandardizedCourseCompetenciesComponent { - constructor( - router: Router, - activatedRoute: ActivatedRoute, - standardizedCompetencyService: StandardizedCompetencyService, - alertService: AlertService, - translateService: TranslateService, - sortService: SortService, - private competencyService: CompetencyService, - ) { - super(router, activatedRoute, standardizedCompetencyService, alertService, translateService, sortService); - } + private competencyService = inject(CompetencyService); protected importCompetencies() { super.importCompetencies(this.competencyService); diff --git a/src/main/webapp/app/course/competencies/import-standardized-competencies/course-import-standardized-course-competencies.component.ts b/src/main/webapp/app/course/competencies/import-standardized-competencies/course-import-standardized-course-competencies.component.ts index 63b74465efe7..280cdf5f0f80 100644 --- a/src/main/webapp/app/course/competencies/import-standardized-competencies/course-import-standardized-course-competencies.component.ts +++ b/src/main/webapp/app/course/competencies/import-standardized-competencies/course-import-standardized-course-competencies.component.ts @@ -10,7 +10,7 @@ import { } from 'app/entities/competency/standardized-competency.model'; import { faBan, faDownLeftAndUpRightToCenter, faFileImport, faSort, faTrash, faUpRightAndDownLeftFromCenter } from '@fortawesome/free-solid-svg-icons'; import { ActivatedRoute, Router } from '@angular/router'; -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { onError } from 'app/shared/util/global.utils'; import { forkJoin, map } from 'rxjs'; import { HttpErrorResponse } from '@angular/common/http'; @@ -34,8 +34,17 @@ interface KnowledgeAreaForImport extends KnowledgeAreaForTree { competencies?: StandardizedCompetencyForImport[]; } -@Component({ template: '' }) +@Component({ + template: '', +}) export abstract class CourseImportStandardizedCourseCompetenciesComponent extends StandardizedCompetencyFilterPageComponent implements OnInit, ComponentCanDeactivate { + protected router = inject(Router); + protected activatedRoute = inject(ActivatedRoute); + protected standardizedCompetencyService = inject(StandardizedCompetencyService); + protected alertService = inject(AlertService); + protected translateService = inject(TranslateService); + protected sortService = inject(SortService); + protected selectedCompetencies: StandardizedCompetencyForImport[] = []; protected selectedCompetency?: StandardizedCompetencyForImport; protected sourceString = ''; @@ -57,17 +66,6 @@ export abstract class CourseImportStandardizedCourseCompetenciesComponent extend protected readonly faTrash = faTrash; protected readonly faSort = faSort; - constructor( - protected router: Router, - protected activatedRoute: ActivatedRoute, - protected standardizedCompetencyService: StandardizedCompetencyService, - protected alertService: AlertService, - protected translateService: TranslateService, - protected sortService: SortService, - ) { - super(); - } - ngOnInit(): void { this.isLoading = true; const getKnowledgeAreasObservable = this.standardizedCompetencyService.getAllForTreeView(); diff --git a/src/main/webapp/app/course/competencies/import-standardized-competencies/course-import-standardized-prerequisites.component.ts b/src/main/webapp/app/course/competencies/import-standardized-competencies/course-import-standardized-prerequisites.component.ts index ed3e19ff65cc..cad9f80d38f3 100644 --- a/src/main/webapp/app/course/competencies/import-standardized-competencies/course-import-standardized-prerequisites.component.ts +++ b/src/main/webapp/app/course/competencies/import-standardized-competencies/course-import-standardized-prerequisites.component.ts @@ -1,9 +1,4 @@ -import { ActivatedRoute, Router } from '@angular/router'; -import { Component } from '@angular/core'; -import { AlertService } from 'app/core/util/alert.service'; -import { TranslateService } from '@ngx-translate/core'; -import { SortService } from 'app/shared/service/sort.service'; -import { StandardizedCompetencyService } from 'app/shared/standardized-competencies/standardized-competency.service'; +import { Component, inject } from '@angular/core'; import { PrerequisiteService } from 'app/course/competencies/prerequisite.service'; import { CourseImportStandardizedCourseCompetenciesComponent } from 'app/course/competencies/import-standardized-competencies/course-import-standardized-course-competencies.component'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; @@ -12,11 +7,13 @@ import { StandardizedCompetencyDetailComponent } from 'app/shared/standardized-c import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; import { KnowledgeAreaTreeComponent } from 'app/shared/standardized-competencies/knowledge-area-tree.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; +import { FormsModule } from '@angular/forms'; @Component({ selector: 'jhi-course-import-standardized-prerequisites', templateUrl: './course-import-standardized-prerequisites.component.html', - standalone: true, imports: [ ArtemisSharedCommonModule, ArtemisSharedComponentModule, @@ -24,20 +21,13 @@ import { KnowledgeAreaTreeComponent } from 'app/shared/standardized-competencies StandardizedCompetencyFilterComponent, StandardizedCompetencyDetailComponent, KnowledgeAreaTreeComponent, + FaIconComponent, + FormsModule, + NgbTooltipModule, ], }) export class CourseImportStandardizedPrerequisitesComponent extends CourseImportStandardizedCourseCompetenciesComponent { - constructor( - router: Router, - activatedRoute: ActivatedRoute, - standardizedCompetencyService: StandardizedCompetencyService, - alertService: AlertService, - translateService: TranslateService, - sortService: SortService, - private prerequisiteService: PrerequisiteService, - ) { - super(router, activatedRoute, standardizedCompetencyService, alertService, translateService, sortService); - } + private prerequisiteService = inject(PrerequisiteService); protected importCompetencies() { super.importCompetencies(this.prerequisiteService); diff --git a/src/main/webapp/app/course/competencies/import/competency-search.component.ts b/src/main/webapp/app/course/competencies/import/competency-search.component.ts index 24b924a45c37..b740becc121e 100644 --- a/src/main/webapp/app/course/competencies/import/competency-search.component.ts +++ b/src/main/webapp/app/course/competencies/import/competency-search.component.ts @@ -3,10 +3,16 @@ import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; import { ButtonType } from 'app/shared/components/button.component'; import { getSemesters } from 'app/utils/semester-utils'; import { CourseCompetencyFilter } from 'app/shared/table/pageable-table'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { NgbCollapse } from '@ng-bootstrap/ng-bootstrap'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-competency-search', templateUrl: './competency-search.component.html', + imports: [TranslateDirective, FormsModule, NgbCollapse, ButtonComponent, FaIconComponent], }) export class CompetencySearchComponent { @Input() search: CourseCompetencyFilter; diff --git a/src/main/webapp/app/course/competencies/import/import-competencies-table.component.ts b/src/main/webapp/app/course/competencies/import/import-competencies-table.component.ts index 9b97b7547193..87146057a246 100644 --- a/src/main/webapp/app/course/competencies/import/import-competencies-table.component.ts +++ b/src/main/webapp/app/course/competencies/import/import-competencies-table.component.ts @@ -2,10 +2,18 @@ import { Component, ContentChild, EventEmitter, Input, OnInit, Output, TemplateR import { faSort } from '@fortawesome/free-solid-svg-icons'; import { PageableSearch, SearchResult, SortingOrder } from 'app/shared/table/pageable-table'; import { Competency } from 'app/entities/competency.model'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgTemplateOutlet } from '@angular/common'; +import { NgbPagination } from '@ng-bootstrap/ng-bootstrap'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-import-competencies-table', templateUrl: './import-competencies-table.component.html', + imports: [SortDirective, SortByDirective, FaIconComponent, TranslateDirective, NgTemplateOutlet, NgbPagination, HtmlForMarkdownPipe], }) export class ImportCompetenciesTableComponent implements OnInit { @Input() content: SearchResult; diff --git a/src/main/webapp/app/course/competencies/import/import-competencies.component.ts b/src/main/webapp/app/course/competencies/import/import-competencies.component.ts index a9adf3785ee5..9dd6cf1181b9 100644 --- a/src/main/webapp/app/course/competencies/import/import-competencies.component.ts +++ b/src/main/webapp/app/course/competencies/import/import-competencies.component.ts @@ -11,7 +11,6 @@ import { CourseCompetencyType } from 'app/entities/competency.model'; @Component({ selector: 'jhi-import-competencies', templateUrl: './import-course-competencies.component.html', - standalone: true, imports: [ArtemisSharedCommonModule, ArtemisSharedComponentModule, ArtemisCompetenciesModule], }) export class ImportCompetenciesComponent extends ImportCourseCompetenciesComponent { diff --git a/src/main/webapp/app/course/competencies/import/import-course-competencies.component.ts b/src/main/webapp/app/course/competencies/import/import-course-competencies.component.ts index 0190d71b8b5e..39c377f2e34f 100644 --- a/src/main/webapp/app/course/competencies/import/import-course-competencies.component.ts +++ b/src/main/webapp/app/course/competencies/import/import-course-competencies.component.ts @@ -16,7 +16,9 @@ import { CourseCompetencyService } from 'app/course/competencies/course-competen * An abstract component used to import course competencies. Its concrete implementations are * {@link ImportCompetenciesComponent} and {@link ImportPrerequisitesComponent} */ -@Component({ template: '' }) +@Component({ + template: '', +}) export abstract class ImportCourseCompetenciesComponent implements OnInit, ComponentCanDeactivate { // this attribute has to be set when using the common template (import-course-competencies.component.html) abstract entityType: string; diff --git a/src/main/webapp/app/course/competencies/import/import-prerequisites.component.ts b/src/main/webapp/app/course/competencies/import/import-prerequisites.component.ts index 660c12d399b2..554807741494 100644 --- a/src/main/webapp/app/course/competencies/import/import-prerequisites.component.ts +++ b/src/main/webapp/app/course/competencies/import/import-prerequisites.component.ts @@ -11,7 +11,6 @@ import { CourseCompetencyType } from 'app/entities/competency.model'; @Component({ selector: 'jhi-import-prerequisites', templateUrl: './import-course-competencies.component.html', - standalone: true, imports: [ArtemisSharedCommonModule, ArtemisSharedComponentModule, ArtemisCompetenciesModule], }) export class ImportPrerequisitesComponent extends ImportCourseCompetenciesComponent { diff --git a/src/main/webapp/app/course/competencies/judgement-of-learning-rating/judgement-of-learning-rating.component.ts b/src/main/webapp/app/course/competencies/judgement-of-learning-rating/judgement-of-learning-rating.component.ts index 92fa6f2d63e7..e02ce29d0bb3 100644 --- a/src/main/webapp/app/course/competencies/judgement-of-learning-rating/judgement-of-learning-rating.component.ts +++ b/src/main/webapp/app/course/competencies/judgement-of-learning-rating/judgement-of-learning-rating.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output, inject } from '@angular/core'; import { RatingModule } from 'app/exercises/shared/rating/rating.module'; import { StarRatingComponent } from 'app/exercises/shared/rating/star-rating/star-rating.component'; import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; @@ -8,11 +8,13 @@ import { CourseCompetencyService } from 'app/course/competencies/course-competen @Component({ selector: 'jhi-judgement-of-learning-rating', - standalone: true, imports: [RatingModule, ArtemisSharedCommonModule, ArtemisSharedComponentModule], templateUrl: './judgement-of-learning-rating.component.html', }) export class JudgementOfLearningRatingComponent { + private courseCompetencyService = inject(CourseCompetencyService); + private alertService = inject(AlertService); + @Input() courseId: number | undefined; @Input() competencyId: number; @Input() rating: number | undefined; @@ -20,11 +22,6 @@ export class JudgementOfLearningRatingComponent { @Output() ratingChange = new EventEmitter(); - constructor( - private courseCompetencyService: CourseCompetencyService, - private alertService: AlertService, - ) {} - /** * Handle the event when a new rating is selected. * @param event - starRating component that holds the new rating value diff --git a/src/main/webapp/app/course/competencies/prerequisite.service.ts b/src/main/webapp/app/course/competencies/prerequisite.service.ts index 3554ef546f38..ff75cfc5fa73 100644 --- a/src/main/webapp/app/course/competencies/prerequisite.service.ts +++ b/src/main/webapp/app/course/competencies/prerequisite.service.ts @@ -1,11 +1,8 @@ -import { HttpClient, HttpResponse } from '@angular/common/http'; +import { HttpResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map, tap } from 'rxjs/operators'; import { CompetencyImportResponseDTO, CompetencyWithTailRelationDTO, CourseCompetency, CourseCompetencyImportOptionsDTO } from 'app/entities/competency.model'; -import { EntityTitleService } from 'app/shared/layouts/navbar/entity-title.service'; -import { LectureUnitService } from 'app/lecture/lecture-unit/lecture-unit-management/lectureUnit.service'; -import { AccountService } from 'app/core/auth/account.service'; import { Prerequisite } from 'app/entities/prerequisite.model'; import { CourseCompetencyService } from 'app/course/competencies/course-competency.service'; @@ -16,10 +13,6 @@ type EntityArrayResponseType = HttpResponse; providedIn: 'root', }) export class PrerequisiteService extends CourseCompetencyService { - constructor(httpClient: HttpClient, entityTitleService: EntityTitleService, lectureUnitService: LectureUnitService, accountService: AccountService) { - super(httpClient, entityTitleService, lectureUnitService, accountService); - } - getAllForCourse(courseId: number): Observable { return this.httpClient.get(`${this.resourceURL}/courses/${courseId}/prerequisites`, { observe: 'response' }).pipe( map((res: EntityArrayResponseType) => this.convertArrayResponseDatesFromServer(res)), diff --git a/src/main/webapp/app/course/competencies/taxonomy-select/taxonomy-select.component.ts b/src/main/webapp/app/course/competencies/taxonomy-select/taxonomy-select.component.ts index 653b5993ff6c..2bcb8e5b0467 100644 --- a/src/main/webapp/app/course/competencies/taxonomy-select/taxonomy-select.component.ts +++ b/src/main/webapp/app/course/competencies/taxonomy-select/taxonomy-select.component.ts @@ -1,10 +1,13 @@ import { Component, Input } from '@angular/core'; -import { FormControl } from '@angular/forms'; +import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { CompetencyTaxonomy } from 'app/entities/competency.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { KeyValuePipe } from '@angular/common'; @Component({ selector: 'jhi-taxonomy-select', templateUrl: './taxonomy-select.component.html', + imports: [FormsModule, ReactiveFormsModule, TranslateDirective, KeyValuePipe], }) export class TaxonomySelectComponent { /** diff --git a/src/main/webapp/app/course/course-access-storage.service.ts b/src/main/webapp/app/course/course-access-storage.service.ts index dcbf08e519df..e4a85450c000 100644 --- a/src/main/webapp/app/course/course-access-storage.service.ts +++ b/src/main/webapp/app/course/course-access-storage.service.ts @@ -1,18 +1,18 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { LocalStorageService } from 'ngx-webstorage'; @Injectable({ providedIn: 'root', }) export class CourseAccessStorageService { + private localStorage = inject(LocalStorageService); + public static readonly STORAGE_KEY = 'artemis.courseAccess'; public static readonly STORAGE_KEY_DROPDOWN = 'artemis.courseAccessDropdown'; public static readonly MAX_DISPLAYED_RECENTLY_ACCESSED_COURSES_OVERVIEW = 3; // Maximum number of recently accessed courses displayed in the dropdown, including the current course. The current course will be removed before displaying the dropdown so only 6 - 1 courses will be displayed in the dropdown. public static readonly MAX_DISPLAYED_RECENTLY_ACCESSED_COURSES_DROPDOWN = 6; - constructor(private localStorage: LocalStorageService) {} - onCourseAccessed(courseId: number, storageKey: string, maxAccessedCourses: number): void { const courseAccessMap: { [key: number]: number } = this.localStorage.retrieve(storageKey) || {}; diff --git a/src/main/webapp/app/course/course-for-import-dto-paging-service.ts b/src/main/webapp/app/course/course-for-import-dto-paging-service.ts index 6b311405c5de..c332daaa0128 100644 --- a/src/main/webapp/app/course/course-for-import-dto-paging-service.ts +++ b/src/main/webapp/app/course/course-for-import-dto-paging-service.ts @@ -1,5 +1,5 @@ import { HttpClient, HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { PagingService } from 'app/exercises/shared/manage/paging.service'; import { SearchResult, SearchTermPageableSearch } from 'app/shared/table/pageable-table'; import { Observable } from 'rxjs'; @@ -10,9 +10,11 @@ type EntityResponseType = SearchResult; @Injectable({ providedIn: 'root' }) export class CourseForImportDTOPagingService extends PagingService { + private http = inject(HttpClient); + private readonly RESOURCE_URL = 'api/courses'; - constructor(private http: HttpClient) { + constructor() { super(); } diff --git a/src/main/webapp/app/course/course-scores/course-scores-routing.module.ts b/src/main/webapp/app/course/course-scores/course-scores-routing.module.ts index eb2b5374af44..5f6227f0a7fb 100644 --- a/src/main/webapp/app/course/course-scores/course-scores-routing.module.ts +++ b/src/main/webapp/app/course/course-scores/course-scores-routing.module.ts @@ -1,19 +1,18 @@ import { RouterModule, Routes } from '@angular/router'; -import { CourseScoresComponent } from 'app/course/course-scores/course-scores.component'; + import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; import { NgModule } from '@angular/core'; import { Authority } from 'app/shared/constants/authority.constants'; import { CourseManagementResolve } from 'app/course/manage/course-management-resolve.service'; -import { CourseManagementTabBarComponent } from 'app/course/manage/course-management-tab-bar/course-management-tab-bar.component'; const routes: Routes = [ { path: ':courseId/scores', - component: CourseManagementTabBarComponent, + loadComponent: () => import('app/course/manage/course-management-tab-bar/course-management-tab-bar.component').then((m) => m.CourseManagementTabBarComponent), children: [ { path: '', - component: CourseScoresComponent, + loadComponent: () => import('app/course/course-scores/course-scores.component').then((m) => m.CourseScoresComponent), resolve: { course: CourseManagementResolve, }, diff --git a/src/main/webapp/app/course/course-scores/course-scores.component.ts b/src/main/webapp/app/course/course-scores/course-scores.component.ts index 530e70f9ab0e..29ebd7eebb16 100644 --- a/src/main/webapp/app/course/course-scores/course-scores.component.ts +++ b/src/main/webapp/app/course/course-scores/course-scores.component.ts @@ -1,6 +1,6 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { Subscription, forkJoin, of } from 'rxjs'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import dayjs from 'dayjs/esm'; import { sum } from 'lodash-es'; import { StudentParticipation } from 'app/entities/participation/student-participation.model'; @@ -48,6 +48,15 @@ import { PlagiarismCasesService } from 'app/course/plagiarism-cases/shared/plagi import { GradeStep } from 'app/entities/grade-step.model'; import { PlagiarismCase } from 'app/exercises/shared/plagiarism/types/PlagiarismCase'; import { PlagiarismVerdict } from 'app/exercises/shared/plagiarism/types/PlagiarismVerdict'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ParticipantScoresDistributionComponent } from 'app/shared/participant-scores/participant-scores-distribution/participant-scores-distribution.component'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { NgClass } from '@angular/common'; +import { ExportButtonComponent } from 'app/shared/export/export-button.component'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export enum HighlightType { AVERAGE = 'average', @@ -60,8 +69,31 @@ export enum HighlightType { templateUrl: './course-scores.component.html', styleUrls: ['./course-scores.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + TranslateDirective, + RouterLink, + FaIconComponent, + ParticipantScoresDistributionComponent, + NgbTooltip, + NgClass, + ExportButtonComponent, + SortDirective, + SortByDirective, + ArtemisTranslatePipe, + ], }) export class CourseScoresComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private courseService = inject(CourseManagementService); + private sortService = inject(SortService); + private changeDetector = inject(ChangeDetectorRef); + private languageHelper = inject(JhiLanguageHelper); + private localeConversionService = inject(LocaleConversionService); + private participantScoresService = inject(ParticipantScoresService); + private gradingSystemService = inject(GradingSystemService); + private navigationUtilService = inject(ArtemisNavigationUtilService); + private plagiarismCasesService = inject(PlagiarismCasesService); + private paramSub: Subscription; private languageChangeSubscription?: Subscription; @@ -132,18 +164,7 @@ export class CourseScoresComponent implements OnInit, OnDestroy { faSpinner = faSpinner; faClipboard = faClipboard; - constructor( - private route: ActivatedRoute, - private courseService: CourseManagementService, - private sortService: SortService, - private changeDetector: ChangeDetectorRef, - private languageHelper: JhiLanguageHelper, - private localeConversionService: LocaleConversionService, - private participantScoresService: ParticipantScoresService, - private gradingSystemService: GradingSystemService, - private navigationUtilService: ArtemisNavigationUtilService, - private plagiarismCasesService: PlagiarismCasesService, - ) { + constructor() { this.reverse = false; this.predicate = 'id'; } diff --git a/src/main/webapp/app/course/course-scores/course-scores.module.ts b/src/main/webapp/app/course/course-scores/course-scores.module.ts index 23b0e3417817..3936ab34157d 100644 --- a/src/main/webapp/app/course/course-scores/course-scores.module.ts +++ b/src/main/webapp/app/course/course-scores/course-scores.module.ts @@ -6,7 +6,6 @@ import { ArtemisParticipantScoresModule } from 'app/shared/participant-scores/pa import { ExportModule } from 'app/shared/export/export.module'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisCourseScoresRoutingModule, ArtemisParticipantScoresModule, ExportModule], - declarations: [CourseScoresComponent], + imports: [ArtemisSharedModule, ArtemisCourseScoresRoutingModule, ArtemisParticipantScoresModule, ExportModule, CourseScoresComponent], }) export class ArtemisCourseScoresModule {} diff --git a/src/main/webapp/app/course/dashboards/assessment-dashboard/assessment-dashboard-information.component.ts b/src/main/webapp/app/course/dashboards/assessment-dashboard/assessment-dashboard-information.component.ts index 36819ac62b0f..6020c6a28708 100644 --- a/src/main/webapp/app/course/dashboards/assessment-dashboard/assessment-dashboard-information.component.ts +++ b/src/main/webapp/app/course/dashboards/assessment-dashboard/assessment-dashboard-information.component.ts @@ -37,7 +37,6 @@ export class AssessmentDashboardInformationEntry { selector: 'jhi-assessment-dashboard-information', templateUrl: './assessment-dashboard-information.component.html', styleUrls: ['./assessment-dashboard-information.component.scss'], - standalone: true, imports: [TranslateDirective, PieChartModule, ArtemisSidePanelModule, RouterLink, ArtemisTranslatePipe], }) export class AssessmentDashboardInformationComponent implements OnInit, OnChanges, OnDestroy { diff --git a/src/main/webapp/app/course/dashboards/assessment-dashboard/assessment-dashboard.component.ts b/src/main/webapp/app/course/dashboards/assessment-dashboard/assessment-dashboard.component.ts index 8ada9ad9321b..0678c09f3f34 100644 --- a/src/main/webapp/app/course/dashboards/assessment-dashboard/assessment-dashboard.component.ts +++ b/src/main/webapp/app/course/dashboards/assessment-dashboard/assessment-dashboard.component.ts @@ -39,7 +39,6 @@ import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; templateUrl: './assessment-dashboard.component.html', styleUrls: ['./exam-assessment-buttons/exam-assessment-buttons.component.scss'], providers: [CourseManagementService], - standalone: true, imports: [ ArtemisSharedComponentModule, RouterLink, diff --git a/src/main/webapp/app/course/dashboards/assessment-dashboard/assessment-dashboard.route.ts b/src/main/webapp/app/course/dashboards/assessment-dashboard/assessment-dashboard.route.ts index 178648a1d3b4..bc5742db0660 100644 --- a/src/main/webapp/app/course/dashboards/assessment-dashboard/assessment-dashboard.route.ts +++ b/src/main/webapp/app/course/dashboards/assessment-dashboard/assessment-dashboard.route.ts @@ -1,18 +1,17 @@ import { Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { AssessmentDashboardComponent } from './assessment-dashboard.component'; + import { Authority } from 'app/shared/constants/authority.constants'; import { CourseManagementResolve } from 'app/course/manage/course-management-resolve.service'; -import { CourseManagementTabBarComponent } from 'app/course/manage/course-management-tab-bar/course-management-tab-bar.component'; export const assessmentDashboardRoute: Routes = [ { path: ':courseId/assessment-dashboard', - component: CourseManagementTabBarComponent, + loadComponent: () => import('app/course/manage/course-management-tab-bar/course-management-tab-bar.component').then((m) => m.CourseManagementTabBarComponent), children: [ { path: '', - component: AssessmentDashboardComponent, + loadComponent: () => import('./assessment-dashboard.component').then((m) => m.AssessmentDashboardComponent), resolve: { course: CourseManagementResolve, }, diff --git a/src/main/webapp/app/course/dashboards/assessment-dashboard/exam-assessment-buttons/exam-assessment-buttons.component.ts b/src/main/webapp/app/course/dashboards/assessment-dashboard/exam-assessment-buttons/exam-assessment-buttons.component.ts index de7010811fae..4014718b261b 100644 --- a/src/main/webapp/app/course/dashboards/assessment-dashboard/exam-assessment-buttons/exam-assessment-buttons.component.ts +++ b/src/main/webapp/app/course/dashboards/assessment-dashboard/exam-assessment-buttons/exam-assessment-buttons.component.ts @@ -21,7 +21,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-exam-assessment-buttons', templateUrl: './exam-assessment-buttons.component.html', - standalone: true, imports: [RouterLink, FaIconComponent, TranslateDirective], }) export class ExamAssessmentButtonsComponent implements OnInit { diff --git a/src/main/webapp/app/course/dashboards/due-date-stat.model.ts b/src/main/webapp/app/course/dashboards/due-date-stat.model.ts index bcf244fc9fcb..727c63fcd25a 100644 --- a/src/main/webapp/app/course/dashboards/due-date-stat.model.ts +++ b/src/main/webapp/app/course/dashboards/due-date-stat.model.ts @@ -6,8 +6,6 @@ export class DueDateStat { public inTime = 0; public late = 0; - constructor() {} - /** * Computed property to get the total number of * both properties, inTime and late members. diff --git a/src/main/webapp/app/course/dashboards/stats-for-dashboard.model.ts b/src/main/webapp/app/course/dashboards/stats-for-dashboard.model.ts index 2af8e2ed1c02..e46452e5a0d4 100644 --- a/src/main/webapp/app/course/dashboards/stats-for-dashboard.model.ts +++ b/src/main/webapp/app/course/dashboards/stats-for-dashboard.model.ts @@ -20,8 +20,6 @@ export class StatsForDashboard { public tutorLeaderboardEntries: TutorLeaderboardElement[] = []; - constructor() {} - /** * Correctly initializes a class instance from a typecasted object. * Returns a 'real' class instance that supports all class methods. diff --git a/src/main/webapp/app/course/learning-paths/components/competency-graph-modal/competency-graph-modal.component.ts b/src/main/webapp/app/course/learning-paths/components/competency-graph-modal/competency-graph-modal.component.ts index 28594a2f49d9..0a076f93aa71 100644 --- a/src/main/webapp/app/course/learning-paths/components/competency-graph-modal/competency-graph-modal.component.ts +++ b/src/main/webapp/app/course/learning-paths/components/competency-graph-modal/competency-graph-modal.component.ts @@ -10,7 +10,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-competency-graph-modal', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [FontAwesomeModule, CompetencyGraphComponent, TranslateDirective], templateUrl: './competency-graph-modal.component.html', @@ -29,13 +28,10 @@ export class CompetencyGraphModalComponent { private readonly activeModal: NgbActiveModal = inject(NgbActiveModal); constructor() { - effect( - () => { - const learningPathId = this.learningPathId(); - untracked(() => this.loadCompetencyGraph(learningPathId)); - }, - { allowSignalWrites: true }, - ); + effect(() => { + const learningPathId = this.learningPathId(); + untracked(() => this.loadCompetencyGraph(learningPathId)); + }); } private async loadCompetencyGraph(learningPathId: number): Promise { diff --git a/src/main/webapp/app/course/learning-paths/components/competency-graph/competency-graph.component.ts b/src/main/webapp/app/course/learning-paths/components/competency-graph/competency-graph.component.ts index bf177640eb57..91030c0983cf 100644 --- a/src/main/webapp/app/course/learning-paths/components/competency-graph/competency-graph.component.ts +++ b/src/main/webapp/app/course/learning-paths/components/competency-graph/competency-graph.component.ts @@ -6,7 +6,6 @@ import { CompetencyNodeComponent, SizeUpdate } from 'app/course/learning-paths/c @Component({ selector: 'jhi-competency-graph', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CompetencyNodeComponent, NgxGraphModule], templateUrl: './competency-graph.component.html', @@ -34,7 +33,7 @@ export class CompetencyGraphComponent { readonly zoomToFit$ = new Subject(); constructor() { - effect(() => this.internalCompetencyGraph.set(this.competencyGraph()), { allowSignalWrites: true }); + effect(() => this.internalCompetencyGraph.set(this.competencyGraph())); } setNodeDimension(sizeUpdate: SizeUpdate): void { diff --git a/src/main/webapp/app/course/learning-paths/components/competency-node/competency-node.component.ts b/src/main/webapp/app/course/learning-paths/components/competency-node/competency-node.component.ts index e4d60b32ef47..c4e951137203 100644 --- a/src/main/webapp/app/course/learning-paths/components/competency-node/competency-node.component.ts +++ b/src/main/webapp/app/course/learning-paths/components/competency-node/competency-node.component.ts @@ -12,7 +12,6 @@ export interface SizeUpdate { @Component({ selector: 'jhi-learning-path-competency-node', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgbDropdownModule, FontAwesomeModule, NgbAccordionModule, CommonModule], templateUrl: './competency-node.component.html', diff --git a/src/main/webapp/app/course/learning-paths/components/learning-path-exercise/learning-path-exercise.component.ts b/src/main/webapp/app/course/learning-paths/components/learning-path-exercise/learning-path-exercise.component.ts index 99f230ce1938..028748ebf32f 100644 --- a/src/main/webapp/app/course/learning-paths/components/learning-path-exercise/learning-path-exercise.component.ts +++ b/src/main/webapp/app/course/learning-paths/components/learning-path-exercise/learning-path-exercise.component.ts @@ -4,7 +4,6 @@ import { CourseExerciseDetailsModule } from 'app/overview/exercise-details/cours @Component({ selector: 'jhi-learning-path-exercise', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CourseExerciseDetailsModule], templateUrl: './learning-path-exercise.component.html', diff --git a/src/main/webapp/app/course/learning-paths/components/learning-path-lecture-unit/learning-path-lecture-unit.component.ts b/src/main/webapp/app/course/learning-paths/components/learning-path-lecture-unit/learning-path-lecture-unit.component.ts index 04822ff754d8..a8303af06344 100644 --- a/src/main/webapp/app/course/learning-paths/components/learning-path-lecture-unit/learning-path-lecture-unit.component.ts +++ b/src/main/webapp/app/course/learning-paths/components/learning-path-lecture-unit/learning-path-lecture-unit.component.ts @@ -16,7 +16,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-learning-path-lecture-unit', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [ArtemisLectureUnitsModule, VideoUnitComponent, TextUnitComponent, AttachmentUnitComponent, OnlineUnitComponent, DiscussionSectionComponent, TranslateDirective], templateUrl: './learning-path-lecture-unit.component.html', @@ -37,13 +36,10 @@ export class LearningPathLectureUnitComponent { readonly isCommunicationEnabled = computed(() => isCommunicationEnabled(this.lecture()?.course)); constructor() { - effect( - () => { - const lectureUnitId = this.lectureUnitId(); - untracked(() => this.loadLectureUnit(lectureUnitId)); - }, - { allowSignalWrites: true }, - ); + effect(() => { + const lectureUnitId = this.lectureUnitId(); + untracked(() => this.loadLectureUnit(lectureUnitId)); + }); } async loadLectureUnit(lectureUnitId: number): Promise { diff --git a/src/main/webapp/app/course/learning-paths/components/learning-path-nav-overview-learning-objects/learning-path-nav-overview-learning-objects.component.ts b/src/main/webapp/app/course/learning-paths/components/learning-path-nav-overview-learning-objects/learning-path-nav-overview-learning-objects.component.ts index 21c0fa4c1c32..3ca8225316d4 100644 --- a/src/main/webapp/app/course/learning-paths/components/learning-path-nav-overview-learning-objects/learning-path-nav-overview-learning-objects.component.ts +++ b/src/main/webapp/app/course/learning-paths/components/learning-path-nav-overview-learning-objects/learning-path-nav-overview-learning-objects.component.ts @@ -11,7 +11,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-learning-path-nav-overview-learning-objects', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgbAccordionModule, FontAwesomeModule, CommonModule, TranslateDirective], templateUrl: './learning-path-nav-overview-learning-objects.component.html', @@ -41,12 +40,9 @@ export class LearningPathNavOverviewLearningObjectsComponent { readonly onLearningObjectSelected = output(); constructor() { - effect( - () => { - untracked(() => this.loadLearningObjects()); - }, - { allowSignalWrites: true }, - ); + effect(() => { + untracked(() => this.loadLearningObjects()); + }); } async loadLearningObjects(): Promise { diff --git a/src/main/webapp/app/course/learning-paths/components/learning-path-nav-overview/learning-path-nav-overview.component.ts b/src/main/webapp/app/course/learning-paths/components/learning-path-nav-overview/learning-path-nav-overview.component.ts index 6bf5c49cea7a..746874759930 100644 --- a/src/main/webapp/app/course/learning-paths/components/learning-path-nav-overview/learning-path-nav-overview.component.ts +++ b/src/main/webapp/app/course/learning-paths/components/learning-path-nav-overview/learning-path-nav-overview.component.ts @@ -13,7 +13,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-learning-path-nav-overview', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [FontAwesomeModule, CommonModule, NgbDropdownModule, NgbAccordionModule, LearningPathNavOverviewLearningObjectsComponent, TranslateDirective], templateUrl: './learning-path-nav-overview.component.html', @@ -41,13 +40,10 @@ export class LearningPathNavOverviewComponent { readonly currentCompetencyOnPath = computed(() => this.competencies()?.find((competency) => competency.masteryProgress < 1)); constructor() { - effect( - () => { - const learningPathId = this.learningPathId(); - untracked(() => this.loadCompetencies(learningPathId)); - }, - { allowSignalWrites: true }, - ); + effect(() => { + const learningPathId = this.learningPathId(); + untracked(() => this.loadCompetencies(learningPathId)); + }); } async loadCompetencies(learningPathId: number): Promise { diff --git a/src/main/webapp/app/course/learning-paths/components/learning-path-student-nav/learning-path-student-nav.component.ts b/src/main/webapp/app/course/learning-paths/components/learning-path-student-nav/learning-path-student-nav.component.ts index dd938e28bd80..c04025d5dec8 100644 --- a/src/main/webapp/app/course/learning-paths/components/learning-path-student-nav/learning-path-student-nav.component.ts +++ b/src/main/webapp/app/course/learning-paths/components/learning-path-student-nav/learning-path-student-nav.component.ts @@ -10,7 +10,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-learning-path-student-nav', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, NgbDropdownModule, NgbAccordionModule, FontAwesomeModule, LearningPathNavOverviewComponent, TranslateDirective], templateUrl: './learning-path-student-nav.component.html', @@ -41,13 +40,10 @@ export class LearningPathNavComponent { readonly isDropdownOpen = signal(false); constructor() { - effect( - () => { - const learningPathId = this.learningPathId(); - untracked(() => this.learningPathNavigationService.loadLearningPathNavigation(learningPathId)); - }, - { allowSignalWrites: true }, - ); + effect(() => { + const learningPathId = this.learningPathId(); + untracked(() => this.learningPathNavigationService.loadLearningPathNavigation(learningPathId)); + }); } async selectLearningObject(selectedLearningObject: LearningPathNavigationObjectDTO, isSuccessor: boolean): Promise { diff --git a/src/main/webapp/app/course/learning-paths/components/learning-paths-analytics/learning-paths-analytics.component.ts b/src/main/webapp/app/course/learning-paths/components/learning-paths-analytics/learning-paths-analytics.component.ts index 6c2678d30c5a..c35168f82977 100644 --- a/src/main/webapp/app/course/learning-paths/components/learning-paths-analytics/learning-paths-analytics.component.ts +++ b/src/main/webapp/app/course/learning-paths/components/learning-paths-analytics/learning-paths-analytics.component.ts @@ -9,7 +9,6 @@ import { CommonModule } from '@angular/common'; @Component({ selector: 'jhi-learning-paths-analytics', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CompetencyGraphComponent, TranslateDirective, CommonModule], templateUrl: './learning-paths-analytics.component.html', @@ -29,13 +28,10 @@ export class LearningPathsAnalyticsComponent { readonly valueSelection = signal(CompetencyGraphNodeValueType.AVERAGE_MASTERY_PROGRESS); constructor() { - effect( - () => { - const courseId = this.courseId(); - untracked(() => this.loadInstructionCompetencyGraph(courseId)); - }, - { allowSignalWrites: true }, - ); + effect(() => { + const courseId = this.courseId(); + untracked(() => this.loadInstructionCompetencyGraph(courseId)); + }); } private async loadInstructionCompetencyGraph(courseId: number): Promise { diff --git a/src/main/webapp/app/course/learning-paths/components/learning-paths-configuration/learning-paths-configuration.component.ts b/src/main/webapp/app/course/learning-paths/components/learning-paths-configuration/learning-paths-configuration.component.ts index 6f2d305f54cc..107c7e493a21 100644 --- a/src/main/webapp/app/course/learning-paths/components/learning-paths-configuration/learning-paths-configuration.component.ts +++ b/src/main/webapp/app/course/learning-paths/components/learning-paths-configuration/learning-paths-configuration.component.ts @@ -10,7 +10,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-learning-paths-configuration', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [FontAwesomeModule, ArtemisSharedComponentModule, TranslateDirective], templateUrl: './learning-paths-configuration.component.html', @@ -33,13 +32,10 @@ export class LearningPathsConfigurationComponent { readonly includeAllGradedExercisesEnabled = computed(() => this.learningPathsConfiguration()?.includeAllGradedExercises ?? false); constructor() { - effect( - () => { - const courseId = this.courseId(); - untracked(() => this.loadLearningPathsConfiguration(courseId)); - }, - { allowSignalWrites: true }, - ); + effect(() => { + const courseId = this.courseId(); + untracked(() => this.loadLearningPathsConfiguration(courseId)); + }); } private async loadLearningPathsConfiguration(courseId: number): Promise { diff --git a/src/main/webapp/app/course/learning-paths/components/learning-paths-state/learning-paths-state.component.ts b/src/main/webapp/app/course/learning-paths/components/learning-paths-state/learning-paths-state.component.ts index a8460830ca71..20fbb7a8e094 100644 --- a/src/main/webapp/app/course/learning-paths/components/learning-paths-state/learning-paths-state.component.ts +++ b/src/main/webapp/app/course/learning-paths/components/learning-paths-state/learning-paths-state.component.ts @@ -11,7 +11,6 @@ import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-learning-paths-state', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslateDirective, CommonModule, FontAwesomeModule], templateUrl: './learning-paths-state.component.html', @@ -45,13 +44,10 @@ export class LearningPathsStateComponent { readonly learningPathHealthState = computed(() => this.learningPathHealth()?.status ?? []); constructor() { - effect( - () => { - const courseId = this.courseId(); - untracked(() => this.loadLearningPathHealthState(courseId)); - }, - { allowSignalWrites: true }, - ); + effect(() => { + const courseId = this.courseId(); + untracked(() => this.loadLearningPathHealthState(courseId)); + }); } protected async loadLearningPathHealthState(courseId: number): Promise { diff --git a/src/main/webapp/app/course/learning-paths/components/learning-paths-table/learning-paths-table.component.ts b/src/main/webapp/app/course/learning-paths/components/learning-paths-table/learning-paths-table.component.ts index 4fe183acd1a5..4043a22c2035 100644 --- a/src/main/webapp/app/course/learning-paths/components/learning-paths-table/learning-paths-table.component.ts +++ b/src/main/webapp/app/course/learning-paths/components/learning-paths-table/learning-paths-table.component.ts @@ -21,7 +21,6 @@ enum TableColumn { @Component({ selector: 'jhi-learning-paths-table', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgbPaginationModule, NgbTypeaheadModule, FormsModule, FontAwesomeModule, ArtemisSharedModule], templateUrl: './learning-paths-table.component.html', @@ -51,14 +50,11 @@ export class LearningPathsTableComponent { private readonly debounceLoadLearningPaths = BaseApiHttpService.debounce(this.loadLearningPaths.bind(this), 300); constructor() { - effect( - () => { - // Load learning paths whenever the courseId changes - const courseId = this.courseId(); - untracked(() => this.loadLearningPaths(courseId)); - }, - { allowSignalWrites: true }, - ); + effect(() => { + // Load learning paths whenever the courseId changes + const courseId = this.courseId(); + untracked(() => this.loadLearningPaths(courseId)); + }); } private async loadLearningPaths(courseId: number): Promise { diff --git a/src/main/webapp/app/course/learning-paths/pages/learning-path-instructor-page/learning-path-instructor-page.component.ts b/src/main/webapp/app/course/learning-paths/pages/learning-path-instructor-page/learning-path-instructor-page.component.ts index dcd31ceae3a9..7496f4fdd15c 100644 --- a/src/main/webapp/app/course/learning-paths/pages/learning-path-instructor-page/learning-path-instructor-page.component.ts +++ b/src/main/webapp/app/course/learning-paths/pages/learning-path-instructor-page/learning-path-instructor-page.component.ts @@ -1,7 +1,6 @@ import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, untracked } from '@angular/core'; import { toSignal } from '@angular/core/rxjs-interop'; import { ActivatedRoute } from '@angular/router'; -import { LearningPathsConfigurationComponent } from 'app/course/learning-paths/components/learning-paths-configuration/learning-paths-configuration.component'; import { lastValueFrom, map } from 'rxjs'; import { LearningPathApiService } from 'app/course/learning-paths/services/learning-path-api.service'; import { AlertService } from 'app/core/util/alert.service'; @@ -15,9 +14,8 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-learning-path-instructor-page', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, - imports: [LearningPathsConfigurationComponent, LearningPathsStateComponent, LearningPathsTableComponent, LearningPathsAnalyticsComponent, TranslateDirective], + imports: [LearningPathsStateComponent, LearningPathsTableComponent, LearningPathsAnalyticsComponent, TranslateDirective], templateUrl: './learning-path-instructor-page.component.html', styleUrl: './learning-path-instructor-page.component.scss', }) @@ -34,13 +32,10 @@ export class LearningPathInstructorPageComponent { readonly isLoading = signal(false); constructor() { - effect( - () => { - const courseId = this.courseId(); - untracked(() => this.loadCourse(courseId)); - }, - { allowSignalWrites: true }, - ); + effect(() => { + const courseId = this.courseId(); + untracked(() => this.loadCourse(courseId)); + }); } private async loadCourse(courseId: number): Promise { diff --git a/src/main/webapp/app/course/learning-paths/pages/learning-path-student-page/learning-path-student-page.component.ts b/src/main/webapp/app/course/learning-paths/pages/learning-path-student-page/learning-path-student-page.component.ts index 72c77fbf2d40..bf5f11f1f219 100644 --- a/src/main/webapp/app/course/learning-paths/pages/learning-path-student-page/learning-path-student-page.component.ts +++ b/src/main/webapp/app/course/learning-paths/pages/learning-path-student-page/learning-path-student-page.component.ts @@ -17,7 +17,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; templateUrl: './learning-path-student-page.component.html', styleUrl: './learning-path-student-page.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, - standalone: true, imports: [LearningPathNavComponent, LearningPathLectureUnitComponent, LearningPathExerciseComponent, TranslateDirective], }) export class LearningPathStudentPageComponent { @@ -35,13 +34,10 @@ export class LearningPathStudentPageComponent { readonly isLearningPathNavigationLoading = this.learningPathNavigationService.isLoading; constructor() { - effect( - () => { - const courseId = this.courseId(); - untracked(() => this.loadLearningPath(courseId)); - }, - { allowSignalWrites: true }, - ); + effect(() => { + const courseId = this.courseId(); + untracked(() => this.loadLearningPath(courseId)); + }); } private async loadLearningPath(courseId: number): Promise { diff --git a/src/main/webapp/app/course/manage/course-admin.service.ts b/src/main/webapp/app/course/manage/course-admin.service.ts index 1185c439a8d2..fb28f13466dc 100644 --- a/src/main/webapp/app/course/manage/course-admin.service.ts +++ b/src/main/webapp/app/course/manage/course-admin.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -12,12 +12,10 @@ export type EntityArrayResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class CourseAdminService { - private resourceUrl = 'api/admin/courses'; + private http = inject(HttpClient); + private courseManagementService = inject(CourseManagementService); - constructor( - private http: HttpClient, - private courseManagementService: CourseManagementService, - ) {} + private resourceUrl = 'api/admin/courses'; /** * finds all groups for all courses using a GET request diff --git a/src/main/webapp/app/course/manage/course-exercise-card.component.ts b/src/main/webapp/app/course/manage/course-exercise-card.component.ts index b2fbbff8b5b1..85a1e3842dbd 100644 --- a/src/main/webapp/app/course/manage/course-exercise-card.component.ts +++ b/src/main/webapp/app/course/manage/course-exercise-card.component.ts @@ -1,11 +1,15 @@ import { Component, Input } from '@angular/core'; import { faAngleDown, faAngleRight } from '@fortawesome/free-solid-svg-icons'; import { Course } from 'app/entities/course.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbCollapse } from '@ng-bootstrap/ng-bootstrap'; @Component({ selector: 'jhi-course-exercise-card', templateUrl: './course-exercise-card.component.html', styleUrls: ['./course-exercise-card.component.scss', '../../exercises/quiz/shared/quiz.scss'], + imports: [TranslateDirective, FaIconComponent, NgbCollapse], }) export class CourseExerciseCardComponent { @Input() headingJhiTranslate: string; diff --git a/src/main/webapp/app/course/manage/course-for-dashboard-dto.ts b/src/main/webapp/app/course/manage/course-for-dashboard-dto.ts index 67cc0c6bed68..322557637962 100644 --- a/src/main/webapp/app/course/manage/course-for-dashboard-dto.ts +++ b/src/main/webapp/app/course/manage/course-for-dashboard-dto.ts @@ -13,13 +13,10 @@ export class CourseForDashboardDTO { quizScores: CourseScores; participationResults: ParticipationResultDTO[]; - - constructor() {} } export class ParticipationResultDTO { score?: number; rated?: boolean; participationId: number; - constructor() {} } diff --git a/src/main/webapp/app/course/manage/course-group-membership/course-group-membership.component.ts b/src/main/webapp/app/course/manage/course-group-membership/course-group-membership.component.ts index 0b9626661fa4..4e605fc6d9a1 100644 --- a/src/main/webapp/app/course/manage/course-group-membership/course-group-membership.component.ts +++ b/src/main/webapp/app/course/manage/course-group-membership/course-group-membership.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { Course, CourseGroup, courseGroups } from 'app/entities/course.model'; import { User } from 'app/core/user/user.model'; import { AccountService } from 'app/core/auth/account.service'; @@ -9,12 +9,23 @@ import { CourseManagementService } from 'app/course/manage/course-management.ser import { UserService } from 'app/core/user/user.service'; import { Subscription } from 'rxjs'; import { capitalize } from 'lodash-es'; +import { CourseGroupComponent } from 'app/shared/course-group/course-group.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-course-group-membership', templateUrl: './course-group-membership.component.html', + imports: [CourseGroupComponent, TranslateDirective], }) export class CourseGroupMembershipComponent implements OnInit { + private router = inject(Router); + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + private eventManager = inject(EventManager); + private courseService = inject(CourseManagementService); + private userService = inject(UserService); + private accountService = inject(AccountService); + allCourseGroupUsers: User[] = []; course: Course; courseGroup: CourseGroup; @@ -25,16 +36,6 @@ export class CourseGroupMembershipComponent implements OnInit { readonly capitalize = capitalize; - constructor( - private router: Router, - private route: ActivatedRoute, - private alertService: AlertService, - private eventManager: EventManager, - private courseService: CourseManagementService, - private userService: UserService, - private accountService: AccountService, - ) {} - ngOnInit(): void { this.loadAll(); } diff --git a/src/main/webapp/app/course/manage/course-lti-configuration/course-lti-configuration.component.ts b/src/main/webapp/app/course/manage/course-lti-configuration/course-lti-configuration.component.ts index d91fcf8469b2..cdcc305d2a82 100644 --- a/src/main/webapp/app/course/manage/course-lti-configuration/course-lti-configuration.component.ts +++ b/src/main/webapp/app/course/manage/course-lti-configuration/course-lti-configuration.component.ts @@ -7,17 +7,16 @@ import { Exercise } from 'app/entities/exercise.model'; import { faExclamationTriangle, faSort, faWrench } from '@fortawesome/free-solid-svg-icons'; import { SortService } from 'app/shared/service/sort.service'; import { FormsModule } from '@angular/forms'; -import { TranslateDirective } from '../../../shared/language/translate.directive'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { NgbNav, NgbNavContent, NgbNavItem, NgbNavLink, NgbNavLinkBase, NgbNavOutlet, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; -import { ArtemisSharedComponentModule } from '../../../shared/components/shared-component.module'; -import { ArtemisSharedCommonModule } from '../../../shared/shared-common.module'; -import { ArtemisTranslatePipe } from '../../../shared/pipes/artemis-translate.pipe'; +import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; +import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-course-lti-configuration', templateUrl: './course-lti-configuration.component.html', - standalone: true, imports: [ FormsModule, TranslateDirective, diff --git a/src/main/webapp/app/course/manage/course-lti-configuration/edit-course-lti-configuration.component.ts b/src/main/webapp/app/course/manage/course-lti-configuration/edit-course-lti-configuration.component.ts index 78f46c1f410d..28d581d5e346 100644 --- a/src/main/webapp/app/course/manage/course-lti-configuration/edit-course-lti-configuration.component.ts +++ b/src/main/webapp/app/course/manage/course-lti-configuration/edit-course-lti-configuration.component.ts @@ -1,6 +1,7 @@ import { Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { Course } from 'app/entities/course.model'; +import { HasAnyAuthorityDirective } from 'app/shared/auth/has-any-authority.directive'; import { finalize } from 'rxjs'; import { OnlineCourseConfiguration } from 'app/entities/online-course-configuration.model'; import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; @@ -13,19 +14,18 @@ import { LtiConfigurationService } from 'app/admin/lti-configuration/lti-configu import { ITEMS_PER_PAGE } from 'app/shared/constants/pagination.constants'; import { HttpHeaders, HttpResponse } from '@angular/common/http'; import { combineLatest } from 'rxjs'; -import { TranslateDirective } from '../../../shared/language/translate.directive'; -import { ArtemisSharedComponentModule } from '../../../shared/components/shared-component.module'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { NgbDropdown, NgbDropdownButtonItem, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle, NgbPagination, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { KeyValuePipe } from '@angular/common'; -import { ArtemisTranslatePipe } from '../../../shared/pipes/artemis-translate.pipe'; -import { ArtemisSharedPipesModule } from '../../../shared/pipes/shared-pipes.module'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { ArtemisSharedPipesModule } from 'app/shared/pipes/shared-pipes.module'; @Component({ selector: 'jhi-edit-course-lti-configuration', templateUrl: './edit-course-lti-configuration.component.html', - standalone: true, imports: [ FormsModule, ReactiveFormsModule, @@ -43,6 +43,8 @@ import { ArtemisSharedPipesModule } from '../../../shared/pipes/shared-pipes.mod KeyValuePipe, ArtemisTranslatePipe, ArtemisSharedPipesModule, + // NOTE: this is actually used in the html template, otherwise *jhiHasAnyAuthority would not work + HasAnyAuthorityDirective, ], }) export class EditCourseLtiConfigurationComponent implements OnInit { diff --git a/src/main/webapp/app/course/manage/course-management-detail-view-dto.model.ts b/src/main/webapp/app/course/manage/course-management-detail-view-dto.model.ts index e262f717a7de..4e8983fe099f 100644 --- a/src/main/webapp/app/course/manage/course-management-detail-view-dto.model.ts +++ b/src/main/webapp/app/course/manage/course-management-detail-view-dto.model.ts @@ -28,6 +28,4 @@ export class CourseManagementDetailViewDto { // LLM Stats currentTotalLlmCostInEur: number; - - constructor() {} } diff --git a/src/main/webapp/app/course/manage/course-management-exercises-search.component.ts b/src/main/webapp/app/course/manage/course-management-exercises-search.component.ts index aeb057ef6e2a..bbc433ad8aba 100644 --- a/src/main/webapp/app/course/manage/course-management-exercises-search.component.ts +++ b/src/main/webapp/app/course/manage/course-management-exercises-search.component.ts @@ -1,11 +1,15 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core'; import { ExerciseFilter } from 'app/entities/exercise-filter.model'; import { exerciseTypes } from 'app/entities/exercise.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-course-management-exercises-search', templateUrl: './course-management-exercises-search.component.html', styleUrls: ['./course-management-exercises-search.component.scss'], + imports: [TranslateDirective, FormsModule, ArtemisTranslatePipe], }) export class CourseManagementExercisesSearchComponent implements OnInit { typeOptions: string[]; diff --git a/src/main/webapp/app/course/manage/course-management-exercises.component.html b/src/main/webapp/app/course/manage/course-management-exercises.component.html index 51f7c1ecfb10..176580fff610 100644 --- a/src/main/webapp/app/course/manage/course-management-exercises.component.html +++ b/src/main/webapp/app/course/manage/course-management-exercises.component.html @@ -27,19 +27,32 @@

[hidden]="shouldHideExerciseCard('programming')" [course]="course" > - + + + + + + + + + + + + + + + + + + + + + + + + (filteredExerciseCount)="filteredProgrammingExercisesCount = $event" /> + + + + + + + + (filteredExerciseCount)="filteredQuizExercisesCount = $event" /> + + + + + + + + (filteredExerciseCount)="filteredModelingExercisesCount = $event" /> + + + + + + + + (filteredExerciseCount)="filteredTextExercisesCount = $event" /> + + + + + + + + ; - @ContentChild('overrideProgrammingExerciseCard') overrideProgrammingExerciseCard: TemplateRef; - @ContentChild('overrideNonProgrammingExerciseCard') overrideNonProgrammingExerciseCard: TemplateRef; + // TODO: the extension point for Orion does not work with Angular 19, we need to find a different solution + // @ContentChild('overrideGenerateAndImportButton') overrideGenerateAndImportButton: TemplateRef; + // @ContentChild('overrideProgrammingExerciseCard') overrideProgrammingExerciseCard: TemplateRef; + // @ContentChild('overrideNonProgrammingExerciseCard') overrideNonProgrammingExerciseCard: TemplateRef; private readonly route = inject(ActivatedRoute); diff --git a/src/main/webapp/app/course/manage/course-management-resolve.service.ts b/src/main/webapp/app/course/manage/course-management-resolve.service.ts index 1e789622ccbb..ebebf754ba8f 100644 --- a/src/main/webapp/app/course/manage/course-management-resolve.service.ts +++ b/src/main/webapp/app/course/manage/course-management-resolve.service.ts @@ -1,13 +1,13 @@ import { Course } from 'app/entities/course.model'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { Observable, filter, map, of } from 'rxjs'; import { HttpResponse } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class CourseManagementResolve implements Resolve { - constructor(private service: CourseManagementService) {} + private service = inject(CourseManagementService); /** * Resolves the route by extracting the courseId and returns the course with that Id if it exists diff --git a/src/main/webapp/app/course/manage/course-management-statistics-dto.ts b/src/main/webapp/app/course/manage/course-management-statistics-dto.ts index adc705057731..3aba5cd52140 100644 --- a/src/main/webapp/app/course/manage/course-management-statistics-dto.ts +++ b/src/main/webapp/app/course/manage/course-management-statistics-dto.ts @@ -3,6 +3,4 @@ import { CourseManagementStatisticsModel } from 'app/entities/quiz/course-manage export class CourseManagementStatisticsDTO { averageScoreOfCourse: number; averageScoresOfExercises: CourseManagementStatisticsModel[]; - - constructor() {} } diff --git a/src/main/webapp/app/course/manage/course-management-statistics.component.ts b/src/main/webapp/app/course/manage/course-management-statistics.component.ts index 4b2dbf79b37d..516dc03f2555 100644 --- a/src/main/webapp/app/course/manage/course-management-statistics.component.ts +++ b/src/main/webapp/app/course/manage/course-management-statistics.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Graphs, SpanType, StatisticsView } from 'app/entities/statistics.model'; import { Subscription } from 'rxjs'; @@ -6,13 +6,22 @@ import { StatisticsService } from 'app/shared/statistics-graph/statistics.servic import { CourseManagementStatisticsDTO } from './course-management-statistics-dto'; import { DocumentationType } from 'app/shared/components/documentation-button/documentation-button.component'; import { Course, isCommunicationEnabled } from 'app/entities/course.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { StatisticsAverageScoreGraphComponent } from 'app/shared/statistics-graph/statistics-average-score-graph.component'; +import { StatisticsGraphComponent } from 'app/shared/statistics-graph/statistics-graph.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-course-management-statistics', templateUrl: './course-management-statistics.component.html', styleUrls: ['./course-management-statistics.component.scss'], + imports: [TranslateDirective, DocumentationButtonComponent, StatisticsAverageScoreGraphComponent, StatisticsGraphComponent, ArtemisTranslatePipe], }) export class CourseManagementStatisticsComponent implements OnInit { + private service = inject(StatisticsService); + private route = inject(ActivatedRoute); + readonly documentationType: DocumentationType = 'Statistics'; // html properties SpanType = SpanType; @@ -40,11 +49,6 @@ export class CourseManagementStatisticsComponent implements OnInit { courseStatistics: CourseManagementStatisticsDTO; - constructor( - private service: StatisticsService, - private route: ActivatedRoute, - ) {} - ngOnInit() { this.paramSub = this.route.params.subscribe((params) => { this.courseId = params['courseId']; diff --git a/src/main/webapp/app/course/manage/course-management-tab-bar/course-management-tab-bar.component.ts b/src/main/webapp/app/course/manage/course-management-tab-bar/course-management-tab-bar.component.ts index 8e15c55fbd28..00336be8ba3c 100644 --- a/src/main/webapp/app/course/manage/course-management-tab-bar/course-management-tab-bar.component.ts +++ b/src/main/webapp/app/course/manage/course-management-tab-bar/course-management-tab-bar.component.ts @@ -1,6 +1,7 @@ -import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { AfterViewInit, Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, Router, RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router'; import { HttpErrorResponse } from '@angular/common/http'; +import { HasAnyAuthorityDirective } from 'app/shared/auth/has-any-authority.directive'; import { Observable, Subject, Subscription, map, of } from 'rxjs'; import { Course, isCommunicationEnabled } from 'app/entities/course.model'; import { CourseManagementService } from 'app/course/manage/course-management.service'; @@ -29,20 +30,48 @@ import { } from '@fortawesome/free-solid-svg-icons'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; import { CourseAdminService } from 'app/course/manage/course-admin.service'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { PROFILE_IRIS, PROFILE_LOCALCI, PROFILE_LTI } from 'app/app.constants'; import { CourseAccessStorageService } from 'app/course/course-access-storage.service'; import { scrollToTopOfPage } from 'app/shared/util/utils'; import { ExerciseType } from 'app/entities/exercise.model'; import { EntitySummary } from 'app/shared/delete-dialog/delete-dialog.model'; +import { HeaderCourseComponent } from 'app/overview/header-course.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FeatureToggleLinkDirective } from 'app/shared/feature-toggle/feature-toggle-link.directive'; +import { FeatureToggleHideDirective } from 'app/shared/feature-toggle/feature-toggle-hide.directive'; +import { CourseExamArchiveButtonComponent } from 'app/shared/components/course-exam-archive-button/course-exam-archive-button.component'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; @Component({ selector: 'jhi-course-management-tab-bar', templateUrl: './course-management-tab-bar.component.html', styleUrls: ['./course-management-tab-bar.component.scss'], + imports: [ + HeaderCourseComponent, + RouterLinkActive, + RouterLink, + FaIconComponent, + TranslateDirective, + FeatureToggleLinkDirective, + FeatureToggleHideDirective, + CourseExamArchiveButtonComponent, + DeleteButtonDirective, + RouterOutlet, + // NOTE: this is actually used in the html template, otherwise *jhiHasAnyAuthority would not work + HasAnyAuthorityDirective, + ], }) export class CourseManagementTabBarComponent implements OnInit, OnDestroy, AfterViewInit { + private eventManager = inject(EventManager); + private courseManagementService = inject(CourseManagementService); + private courseAdminService = inject(CourseAdminService); + private route = inject(ActivatedRoute); + private router = inject(Router); + private profileService = inject(ProfileService); + private courseAccessStorageService = inject(CourseAccessStorageService); + readonly FeatureToggle = FeatureToggle; readonly ButtonSize = ButtonSize; @@ -83,17 +112,6 @@ export class CourseManagementTabBarComponent implements OnInit, OnDestroy, After irisEnabled = false; ltiEnabled = false; - constructor( - private eventManager: EventManager, - private courseManagementService: CourseManagementService, - private courseAdminService: CourseAdminService, - private route: ActivatedRoute, - private router: Router, - private modalService: NgbModal, - private profileService: ProfileService, - private courseAccessStorageService: CourseAccessStorageService, - ) {} - /** * On init load the course information and subscribe to listen for changes in course. */ diff --git a/src/main/webapp/app/course/manage/course-management.component.ts b/src/main/webapp/app/course/manage/course-management.component.ts index e6706bd2b2ee..f5970f30cba4 100644 --- a/src/main/webapp/app/course/manage/course-management.component.ts +++ b/src/main/webapp/app/course/manage/course-management.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core'; +import { AfterViewInit, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { Subject, Subscription } from 'rxjs'; import { Course } from 'app/entities/course.model'; @@ -12,14 +12,39 @@ import { EventManager } from 'app/core/util/event-manager.service'; import { faAngleDown, faAngleUp, faPlus } from '@fortawesome/free-solid-svg-icons'; import { DocumentationType } from 'app/shared/components/documentation-button/documentation-button.component'; import { CourseAccessStorageService } from 'app/course/course-access-storage.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { HasAnyAuthorityDirective } from 'app/shared/auth/has-any-authority.directive'; +import { OrionFilterDirective } from 'app/shared/orion/orion-filter.directive'; +import { RouterLink } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { CourseManagementCardComponent } from './overview/course-management-card.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-course', templateUrl: './course-management.component.html', styles: ['.course-table {padding-bottom: 5rem}'], styleUrls: ['./course-management.component.scss'], + imports: [ + TranslateDirective, + DocumentationButtonComponent, + // NOTE: this is actually used in the html template, otherwise *jhiHasAnyAuthority would not work + HasAnyAuthorityDirective, + OrionFilterDirective, + RouterLink, + FaIconComponent, + CourseManagementCardComponent, + ArtemisTranslatePipe, + ], }) export class CourseManagementComponent implements OnInit, OnDestroy, AfterViewInit { + private courseManagementService = inject(CourseManagementService); + private alertService = inject(AlertService); + private eventManager = inject(EventManager); + private guidedTourService = inject(GuidedTourService); + private courseAccessStorageService = inject(CourseAccessStorageService); + showOnlyActive = true; courses: Course[]; @@ -42,14 +67,6 @@ export class CourseManagementComponent implements OnInit, OnDestroy, AfterViewIn faAngleDown = faAngleDown; faAngleUp = faAngleUp; - constructor( - private courseManagementService: CourseManagementService, - private alertService: AlertService, - private eventManager: EventManager, - private guidedTourService: GuidedTourService, - private courseAccessStorageService: CourseAccessStorageService, - ) {} - /** * loads all courses and subscribes to courseListModification */ diff --git a/src/main/webapp/app/course/manage/course-management.module.ts b/src/main/webapp/app/course/manage/course-management.module.ts index 3aeca48c59d3..bf0afc89a1d2 100644 --- a/src/main/webapp/app/course/manage/course-management.module.ts +++ b/src/main/webapp/app/course/manage/course-management.module.ts @@ -49,11 +49,11 @@ import { CourseManagementExercisesSearchComponent } from 'app/course/manage/cour import { LineChartModule, PieChartModule } from '@swimlane/ngx-charts'; import { ArtemisPlagiarismModule } from 'app/exercises/shared/plagiarism/plagiarism.module'; import { ArtemisChartsModule } from 'app/shared/chart/artemis-charts.module'; -import { ImageCropperModule } from 'app/shared/image-cropper/image-cropper.module'; + import { ArtemisFullscreenModule } from 'app/shared/fullscreen/fullscreen.module'; import { ArtemisCourseGroupModule } from 'app/shared/course-group/course-group.module'; import { CourseGroupMembershipComponent } from './course-group-membership/course-group-membership.component'; -import { FeatureToggleModule } from 'app/shared/feature-toggle/feature-toggle.module'; + import { CourseLtiConfigurationComponent } from 'app/course/manage/course-lti-configuration/course-lti-configuration.component'; import { EditCourseLtiConfigurationComponent } from 'app/course/manage/course-lti-configuration/edit-course-lti-configuration.component'; import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'; @@ -75,7 +75,6 @@ import { ComplaintsForTutorComponent } from 'app/complaints/complaints-for-tutor RouterModule.forChild(courseManagementState), FormDateTimePickerModule, ReactiveFormsModule, - ImageCropperModule, OrionModule, MatChipsModule, ArtemisExerciseModule, @@ -112,7 +111,6 @@ import { ComplaintsForTutorComponent } from 'app/complaints/complaints-for-tutor ArtemisPlagiarismModule, ArtemisChartsModule, ArtemisCourseGroupModule, - FeatureToggleModule, ExerciseCategoriesModule, NgbNavModule, ArtemisExerciseCreateButtonsModule, @@ -122,8 +120,6 @@ import { ComplaintsForTutorComponent } from 'app/complaints/complaints-for-tutor ArtemisMarkdownEditorModule, CourseLtiConfigurationComponent, EditCourseLtiConfigurationComponent, - ], - declarations: [ CourseManagementComponent, CourseDetailComponent, CourseUpdateComponent, diff --git a/src/main/webapp/app/course/manage/course-management.route.ts b/src/main/webapp/app/course/manage/course-management.route.ts index 9d00cb7cc48f..cf0b92a77ecc 100644 --- a/src/main/webapp/app/course/manage/course-management.route.ts +++ b/src/main/webapp/app/course/manage/course-management.route.ts @@ -1,46 +1,17 @@ import { Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { CourseManagementComponent } from './course-management.component'; -import { CourseDetailComponent } from './detail/course-detail.component'; -import { CourseUpdateComponent } from './course-update.component'; -import { CourseManagementExercisesComponent } from './course-management-exercises.component'; import { Authority } from 'app/shared/constants/authority.constants'; -import { RatingListComponent } from 'app/exercises/shared/rating/rating-list/rating-list.component'; -import { CompetencyManagementComponent } from 'app/course/competencies/competency-management/competency-management.component'; -import { CreateCompetencyComponent } from 'app/course/competencies/create/create-competency.component'; -import { EditCompetencyComponent } from 'app/course/competencies/edit/edit-competency.component'; -import { GenerateCompetenciesComponent } from 'app/course/competencies/generate-competencies/generate-competencies.component'; -import { CourseManagementStatisticsComponent } from './course-management-statistics.component'; -import { GradingSystemComponent } from 'app/grading-system/grading-system.component'; -import { isOrion } from 'app/shared/orion/orion'; -import { OrionCourseManagementExercisesComponent } from 'app/orion/management/orion-course-management-exercises.component'; import { CourseManagementResolve } from 'app/course/manage/course-management-resolve.service'; -import { CourseGroupMembershipComponent } from 'app/course/manage/course-group-membership/course-group-membership.component'; import { TutorialGroupManagementResolve } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-group-management-resolve.service'; -import { TutorialGroupsChecklistComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-checklist/tutorial-groups-checklist.component'; -import { CreateTutorialGroupsConfigurationComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/create-tutorial-groups-configuration/create-tutorial-groups-configuration.component'; -import { CourseLtiConfigurationComponent } from 'app/course/manage/course-lti-configuration/course-lti-configuration.component'; -import { EditCourseLtiConfigurationComponent } from 'app/course/manage/course-lti-configuration/edit-course-lti-configuration.component'; -import { CourseManagementTabBarComponent } from 'app/course/manage/course-management-tab-bar/course-management-tab-bar.component'; import { PendingChangesGuard } from 'app/shared/guard/pending-changes.guard'; -import { BuildQueueComponent } from 'app/localci/build-queue/build-queue.component'; -import { ImportCompetenciesComponent } from 'app/course/competencies/import/import-competencies.component'; import { LocalCIGuard } from 'app/localci/localci-guard.service'; import { IrisGuard } from 'app/iris/iris-guard.service'; -import { CourseImportStandardizedCompetenciesComponent } from 'app/course/competencies/import-standardized-competencies/course-import-standardized-competencies.component'; -import { ImportPrerequisitesComponent } from 'app/course/competencies/import/import-prerequisites.component'; -import { CreatePrerequisiteComponent } from 'app/course/competencies/create/create-prerequisite.component'; -import { EditPrerequisiteComponent } from 'app/course/competencies/edit/edit-prerequisite.component'; -import { CourseImportStandardizedPrerequisitesComponent } from 'app/course/competencies/import-standardized-competencies/course-import-standardized-prerequisites.component'; -import { LearningPathInstructorPageComponent } from 'app/course/learning-paths/pages/learning-path-instructor-page/learning-path-instructor-page.component'; -import { FaqComponent } from 'app/faq/faq.component'; -import { FaqUpdateComponent } from 'app/faq/faq-update.component'; import { FaqResolve } from 'app/faq/faq.routes'; export const courseManagementState: Routes = [ { path: '', - component: CourseManagementComponent, + loadComponent: () => import('./course-management.component').then((m) => m.CourseManagementComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.course.home.title', @@ -49,7 +20,7 @@ export const courseManagementState: Routes = [ }, { path: 'new', - component: CourseUpdateComponent, + loadComponent: () => import('./course-update.component').then((m) => m.CourseUpdateComponent), data: { authorities: [Authority.ADMIN], pageTitle: 'global.generic.create', @@ -58,11 +29,11 @@ export const courseManagementState: Routes = [ }, { path: '', - component: CourseManagementTabBarComponent, + loadComponent: () => import('app/course/manage/course-management-tab-bar/course-management-tab-bar.component').then((m) => m.CourseManagementTabBarComponent), children: [ { path: ':courseId', - component: CourseDetailComponent, + loadComponent: () => import('./detail/course-detail.component').then((m) => m.CourseDetailComponent), resolve: { course: CourseManagementResolve, }, @@ -74,7 +45,7 @@ export const courseManagementState: Routes = [ }, { path: ':courseId/grading-system', - component: GradingSystemComponent, + loadComponent: () => import('app/grading-system/grading-system.component').then((m) => m.GradingSystemComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.course.gradingSystem', @@ -109,7 +80,10 @@ export const courseManagementState: Routes = [ }, { path: ':courseId/tutorial-groups-checklist', - component: TutorialGroupsChecklistComponent, + loadComponent: () => + import('app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-checklist/tutorial-groups-checklist.component').then( + (m) => m.TutorialGroupsChecklistComponent, + ), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.pages.checklist.title', @@ -118,7 +92,10 @@ export const courseManagementState: Routes = [ }, { path: ':courseId/create-tutorial-groups-configuration', - component: CreateTutorialGroupsConfigurationComponent, + loadComponent: () => + import( + 'app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/create-tutorial-groups-configuration/create-tutorial-groups-configuration.component' + ).then((m) => m.CreateTutorialGroupsConfigurationComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.pages.createTutorialGroupsConfiguration.title', @@ -127,7 +104,7 @@ export const courseManagementState: Routes = [ }, { path: ':courseId/lti-configuration', - component: CourseLtiConfigurationComponent, + loadComponent: () => import('app/course/manage/course-lti-configuration/course-lti-configuration.component').then((m) => m.CourseLtiConfigurationComponent), resolve: { course: CourseManagementResolve, }, @@ -139,7 +116,8 @@ export const courseManagementState: Routes = [ }, { path: ':courseId/lti-configuration/edit', - component: EditCourseLtiConfigurationComponent, + loadComponent: () => + import('app/course/manage/course-lti-configuration/edit-course-lti-configuration.component').then((m) => m.EditCourseLtiConfigurationComponent), resolve: { course: CourseManagementResolve, }, @@ -158,7 +136,7 @@ export const courseManagementState: Routes = [ children: [ { path: 'exercises', - component: !isOrion ? CourseManagementExercisesComponent : OrionCourseManagementExercisesComponent, + loadComponent: () => import('app/orion/management/orion-course-management-exercises.component').then((m) => m.OrionCourseManagementExercisesComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.course.exercises', @@ -167,7 +145,7 @@ export const courseManagementState: Routes = [ }, { path: 'course-statistics', - component: CourseManagementStatisticsComponent, + loadComponent: () => import('./course-management-statistics.component').then((m) => m.CourseManagementStatisticsComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.courseStatistics.statistics', @@ -177,7 +155,7 @@ export const courseManagementState: Routes = [ }, { path: 'edit', - component: CourseUpdateComponent, + loadComponent: () => import('./course-update.component').then((m) => m.CourseUpdateComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.course.home.editLabel', @@ -186,7 +164,7 @@ export const courseManagementState: Routes = [ }, { path: 'groups/:courseGroup', - component: CourseGroupMembershipComponent, + loadComponent: () => import('app/course/manage/course-group-membership/course-group-membership.component').then((m) => m.CourseGroupMembershipComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.userManagement.groups', @@ -195,7 +173,7 @@ export const courseManagementState: Routes = [ }, { path: 'ratings', - component: RatingListComponent, + loadComponent: () => import('app/exercises/shared/rating/rating-list/rating-list.component').then((m) => m.RatingListComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.ratingList.pageTitle', @@ -204,7 +182,7 @@ export const courseManagementState: Routes = [ }, { path: 'competency-management', - component: CompetencyManagementComponent, + loadComponent: () => import('app/course/competencies/competency-management/competency-management.component').then((m) => m.CompetencyManagementComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.competency.manage.title', @@ -220,7 +198,7 @@ export const courseManagementState: Routes = [ children: [ { path: 'create', - component: CreateCompetencyComponent, + loadComponent: () => import('app/course/competencies/create/create-competency.component').then((m) => m.CreateCompetencyComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.competency.create.title', @@ -229,7 +207,7 @@ export const courseManagementState: Routes = [ }, { path: ':competencyId/edit', - component: EditCompetencyComponent, + loadComponent: () => import('app/course/competencies/edit/edit-competency.component').then((m) => m.EditCompetencyComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.competency.editCompetency.title', @@ -238,7 +216,7 @@ export const courseManagementState: Routes = [ }, { path: 'import', - component: ImportCompetenciesComponent, + loadComponent: () => import('app/course/competencies/import/import-competencies.component').then((m) => m.ImportCompetenciesComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.competency.import.title', @@ -248,7 +226,10 @@ export const courseManagementState: Routes = [ }, { path: 'import-standardized', - component: CourseImportStandardizedCompetenciesComponent, + loadComponent: () => + import('app/course/competencies/import-standardized-competencies/course-import-standardized-competencies.component').then( + (m) => m.CourseImportStandardizedCompetenciesComponent, + ), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.competency.import.title', @@ -258,7 +239,8 @@ export const courseManagementState: Routes = [ }, { path: 'generate', - component: GenerateCompetenciesComponent, + loadComponent: () => + import('app/course/competencies/generate-competencies/generate-competencies.component').then((m) => m.GenerateCompetenciesComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.competency.generate.title', @@ -281,7 +263,7 @@ export const courseManagementState: Routes = [ children: [ { path: 'create', - component: CreatePrerequisiteComponent, + loadComponent: () => import('app/course/competencies/create/create-prerequisite.component').then((m) => m.CreatePrerequisiteComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.prerequisite.createPrerequisite.title', @@ -290,7 +272,7 @@ export const courseManagementState: Routes = [ }, { path: ':prerequisiteId/edit', - component: EditPrerequisiteComponent, + loadComponent: () => import('app/course/competencies/edit/edit-prerequisite.component').then((m) => m.EditPrerequisiteComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.prerequisite.editPrerequisite.title', @@ -299,7 +281,7 @@ export const courseManagementState: Routes = [ }, { path: 'import', - component: ImportPrerequisitesComponent, + loadComponent: () => import('app/course/competencies/import/import-prerequisites.component').then((m) => m.ImportPrerequisitesComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.prerequisite.import.title', @@ -309,7 +291,10 @@ export const courseManagementState: Routes = [ }, { path: 'import-standardized', - component: CourseImportStandardizedPrerequisitesComponent, + loadComponent: () => + import('app/course/competencies/import-standardized-competencies/course-import-standardized-prerequisites.component').then( + (m) => m.CourseImportStandardizedPrerequisitesComponent, + ), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.prerequisite.import.title', @@ -321,7 +306,10 @@ export const courseManagementState: Routes = [ }, { path: 'learning-path-management', - component: LearningPathInstructorPageComponent, + loadComponent: () => + import('app/course/learning-paths/pages/learning-path-instructor-page/learning-path-instructor-page.component').then( + (m) => m.LearningPathInstructorPageComponent, + ), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.learningPath.manageLearningPaths.title', @@ -330,7 +318,7 @@ export const courseManagementState: Routes = [ }, { path: 'build-queue', - component: BuildQueueComponent, + loadComponent: () => import('app/localci/build-queue/build-queue.component').then((m) => m.BuildQueueComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.buildQueue.title', @@ -342,7 +330,7 @@ export const courseManagementState: Routes = [ children: [ { path: '', - component: FaqComponent, + loadComponent: () => import('app/faq/faq.component').then((m) => m.FaqComponent), resolve: { course: CourseManagementResolve, }, @@ -361,7 +349,7 @@ export const courseManagementState: Routes = [ children: [ { path: 'new', - component: FaqUpdateComponent, + loadComponent: () => import('app/faq/faq-update.component').then((m) => m.FaqUpdateComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'global.generic.create', @@ -376,7 +364,7 @@ export const courseManagementState: Routes = [ children: [ { path: 'edit', - component: FaqUpdateComponent, + loadComponent: () => import('app/faq/faq-update.component').then((m) => m.FaqUpdateComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'global.generic.edit', diff --git a/src/main/webapp/app/course/manage/course-management.service.ts b/src/main/webapp/app/course/manage/course-management.service.ts index 7aeb99ef0c0b..895d180db81a 100644 --- a/src/main/webapp/app/course/manage/course-management.service.ts +++ b/src/main/webapp/app/course/manage/course-management.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; import { CoursesForDashboardDTO } from 'app/course/manage/courses-for-dashboard-dto'; import { BehaviorSubject, Observable } from 'rxjs'; @@ -36,6 +36,15 @@ export type RoleGroup = 'tutors' | 'students' | 'instructors' | 'editors'; @Injectable({ providedIn: 'root' }) export class CourseManagementService { + private http = inject(HttpClient); + private courseStorageService = inject(CourseStorageService); + private lectureService = inject(LectureService); + private accountService = inject(AccountService); + private entityTitleService = inject(EntityTitleService); + private tutorialGroupsConfigurationService = inject(TutorialGroupsConfigurationService); + private tutorialGroupsService = inject(TutorialGroupsService); + private scoresStorageService = inject(ScoresStorageService); + private resourceUrl = 'api/courses'; private coursesForNotifications: BehaviorSubject = new BehaviorSubject(undefined); @@ -45,17 +54,6 @@ export class CourseManagementService { private courseOverviewSubject = new BehaviorSubject(false); isCourseOverview$ = this.courseOverviewSubject.asObservable(); - constructor( - private http: HttpClient, - private courseStorageService: CourseStorageService, - private lectureService: LectureService, - private accountService: AccountService, - private entityTitleService: EntityTitleService, - private tutorialGroupsConfigurationService: TutorialGroupsConfigurationService, - private tutorialGroupsService: TutorialGroupsService, - private scoresStorageService: ScoresStorageService, - ) {} - /** * updates a course using a PUT request * @param courseId - the id of the course to be updated diff --git a/src/main/webapp/app/course/manage/course-update.component.ts b/src/main/webapp/app/course/manage/course-update.component.ts index 8922497168dd..5fcde16d3efb 100644 --- a/src/main/webapp/app/course/manage/course-update.component.ts +++ b/src/main/webapp/app/course/manage/course-update.component.ts @@ -1,8 +1,9 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms'; +import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, ValidatorFn, Validators } from '@angular/forms'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { AlertService, AlertType } from 'app/core/util/alert.service'; +import { HasAnyAuthorityDirective } from 'app/shared/auth/has-any-authority.directive'; import { Observable, OperatorFunction, Subject, debounceTime, distinctUntilChanged, filter, map, merge, tap } from 'rxjs'; import { regexValidator } from 'app/shared/form/shortname-validator.directive'; import { Course, CourseInformationSharingConfiguration, isCommunicationEnabled, isMessagingEnabled } from 'app/entities/course.model'; @@ -15,12 +16,11 @@ import dayjs from 'dayjs/esm'; import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; import { SHORT_NAME_PATTERN } from 'app/shared/constants/input.constants'; import { Organization } from 'app/entities/organization.model'; -import { NgbModal, NgbTypeahead } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbTooltip, NgbTypeahead } from '@ng-bootstrap/ng-bootstrap'; import { OrganizationManagementService } from 'app/admin/organization-management/organization-management.service'; import { OrganizationSelectorComponent } from 'app/shared/organization-selector/organization-selector.component'; import { faBan, faExclamationTriangle, faPen, faQuestionCircle, faSave, faTimes, faTrash } from '@fortawesome/free-solid-svg-icons'; import { base64StringToBlob } from 'app/utils/blob-util'; -import { ImageCroppedEvent } from 'app/shared/image-cropper/interfaces/image-cropped-event.interface'; import { ProgrammingLanguage } from 'app/entities/programming/programming-exercise.model'; import { CourseAdminService } from 'app/course/manage/course-admin.service'; import { FeatureToggle, FeatureToggleService } from 'app/shared/feature-toggle/feature-toggle.service'; @@ -32,6 +32,16 @@ import { getSemesters } from 'app/utils/semester-utils'; import { ImageCropperModalComponent } from 'app/course/manage/image-cropper-modal.component'; import { scrollToTopOfPage } from 'app/shared/util/utils'; import { CourseStorageService } from 'app/course/manage/course-storage.service'; +import { SecuredImageComponent } from 'app/shared/image/secured-image.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { KeyValuePipe, NgClass, NgStyle, NgTemplateOutlet } from '@angular/common'; +import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { MarkdownEditorMonacoComponent } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { FeatureToggleHideDirective } from 'app/shared/feature-toggle/feature-toggle-hide.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { RemoveKeysPipe } from 'app/shared/pipes/remove-keys.pipe'; const DEFAULT_CUSTOM_GROUP_NAME = 'artemis-dev'; @@ -39,20 +49,58 @@ const DEFAULT_CUSTOM_GROUP_NAME = 'artemis-dev'; selector: 'jhi-course-update', templateUrl: './course-update.component.html', styleUrls: ['./course-update.component.scss'], + imports: [ + FormsModule, + ReactiveFormsModule, + SecuredImageComponent, + FaIconComponent, + TranslateDirective, + NgStyle, + ColorSelectorComponent, + NgClass, + NgbTooltip, + FormDateTimePickerComponent, + HelpIconComponent, + MarkdownEditorMonacoComponent, + FeatureToggleHideDirective, + NgbTypeahead, + NgTemplateOutlet, + KeyValuePipe, + ArtemisTranslatePipe, + RemoveKeysPipe, + // NOTE: this is actually used in the html template, otherwise *jhiHasAnyAuthority would not work + HasAnyAuthorityDirective, + ], }) export class CourseUpdateComponent implements OnInit { + private eventManager = inject(EventManager); + private courseManagementService = inject(CourseManagementService); + private courseAdminService = inject(CourseAdminService); + private activatedRoute = inject(ActivatedRoute); + private fileService = inject(FileService); + private alertService = inject(AlertService); + private profileService = inject(ProfileService); + private organizationService = inject(OrganizationManagementService); + private modalService = inject(NgbModal); + private navigationUtilService = inject(ArtemisNavigationUtilService); + private router = inject(Router); + private featureToggleService = inject(FeatureToggleService); + private accountService = inject(AccountService); + CachingStrategy = CachingStrategy; ProgrammingLanguage = ProgrammingLanguage; + @ViewChild('fileInput', { static: false }) fileInput: ElementRef; + @ViewChild(ColorSelectorComponent, { static: false }) colorSelector: ColorSelectorComponent; @ViewChild('timeZoneInput') tzTypeAhead: NgbTypeahead; + tzFocus$ = new Subject(); tzClick$ = new Subject(); timeZones: string[] = []; originalTimeZone?: string; - @ViewChild('fileInput', { static: false }) fileInput: ElementRef; - @ViewChild(ColorSelectorComponent, { static: false }) colorSelector: ColorSelectorComponent; readonly ARTEMIS_DEFAULT_COLOR = ARTEMIS_DEFAULT_COLOR; + courseForm: FormGroup; course: Course; isSaving: boolean; @@ -79,7 +127,7 @@ export class CourseUpdateComponent implements OnInit { isAthenaEnabled = false; tutorialGroupsFeatureActivated = false; - private courseStorageServivce = inject(CourseStorageService); + private courseStorageService = inject(CourseStorageService); readonly semesters = getSemesters(); @@ -88,25 +136,8 @@ export class CourseUpdateComponent implements OnInit { // Currently set to 65535 as this is the limit of TEXT readonly COMPLAINT_RESPONSE_TEXT_LIMIT = 65535; readonly COMPLAINT_TEXT_LIMIT = 65535; - readonly COURSE_TITLE_LIMIT = 255; - constructor( - private eventManager: EventManager, - private courseManagementService: CourseManagementService, - private courseAdminService: CourseAdminService, - private activatedRoute: ActivatedRoute, - private fileService: FileService, - private alertService: AlertService, - private profileService: ProfileService, - private organizationService: OrganizationManagementService, - private modalService: NgbModal, - private navigationUtilService: ArtemisNavigationUtilService, - private router: Router, - private featureToggleService: FeatureToggleService, - private accountService: AccountService, - ) {} - ngOnInit() { this.timeZones = (Intl as any).supportedValuesOf('timeZone'); this.isSaving = false; @@ -347,7 +378,7 @@ export class CourseUpdateComponent implements OnInit { name: 'courseModification', content: 'Changed a course', }); - this.courseStorageServivce.updateCourse(updatedCourse!); + this.courseStorageService.updateCourse(updatedCourse!); } this.router.navigate(['course-management', updatedCourse?.id?.toString()]); @@ -367,13 +398,6 @@ export class CourseUpdateComponent implements OnInit { element.value = ''; } - /** - * @param event - */ - imageCropped(event: ImageCroppedEvent) { - this.croppedImage = event.base64; - } - /** * Action on unsuccessful course creation or edit * @param error The error for providing feedback diff --git a/src/main/webapp/app/course/manage/courses-for-dashboard-dto.ts b/src/main/webapp/app/course/manage/courses-for-dashboard-dto.ts index 123e334cca33..ad0b6d4a0a01 100644 --- a/src/main/webapp/app/course/manage/courses-for-dashboard-dto.ts +++ b/src/main/webapp/app/course/manage/courses-for-dashboard-dto.ts @@ -4,6 +4,4 @@ import { Exam } from 'app/entities/exam/exam.model'; export class CoursesForDashboardDTO { courses: CourseForDashboardDTO[]; activeExams: Exam[]; - - constructor() {} } diff --git a/src/main/webapp/app/course/manage/detail/course-detail-doughnut-chart.component.ts b/src/main/webapp/app/course/manage/detail/course-detail-doughnut-chart.component.ts index 6e842fdd4309..758fcc072a55 100644 --- a/src/main/webapp/app/course/manage/detail/course-detail-doughnut-chart.component.ts +++ b/src/main/webapp/app/course/manage/detail/course-detail-doughnut-chart.component.ts @@ -1,12 +1,15 @@ -import { Component, Input, OnChanges, OnInit } from '@angular/core'; +import { Component, Input, OnChanges, OnInit, inject } from '@angular/core'; import { roundValueSpecifiedByCourseSettings } from 'app/shared/util/utils'; import { DoughnutChartType } from './course-detail.component'; -import { Router } from '@angular/router'; +import { Router, RouterLink } from '@angular/router'; import { Course } from 'app/entities/course.model'; -import { Color, ScaleType } from '@swimlane/ngx-charts'; +import { Color, PieChartModule, ScaleType } from '@swimlane/ngx-charts'; import { faSpinner } from '@fortawesome/free-solid-svg-icons'; import { NgxChartsSingleSeriesDataEntry } from 'app/shared/chart/ngx-charts-datatypes'; import { GraphColors } from 'app/entities/statistics.model'; +import { NgClass } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; const PIE_CHART_NA_FALLBACK_VALUE = [0, 0, 1]; @@ -14,8 +17,11 @@ const PIE_CHART_NA_FALLBACK_VALUE = [0, 0, 1]; selector: 'jhi-course-detail-doughnut-chart', templateUrl: './course-detail-doughnut-chart.component.html', styleUrls: ['./course-detail-doughnut-chart.component.scss'], + imports: [RouterLink, NgClass, FaIconComponent, PieChartModule, ArtemisTranslatePipe], }) export class CourseDetailDoughnutChartComponent implements OnChanges, OnInit { + private router = inject(Router); + @Input() contentType: DoughnutChartType; @Input() currentPercentage?: number; @Input() currentAbsolute?: number; @@ -31,8 +37,6 @@ export class CourseDetailDoughnutChartComponent implements OnChanges, OnInit { // Icons faSpinner = faSpinner; - constructor(private router: Router) {} - // ngx-charts ngxData: NgxChartsSingleSeriesDataEntry[] = [ { name: 'Done', value: 0 }, diff --git a/src/main/webapp/app/course/manage/detail/course-detail-line-chart.component.ts b/src/main/webapp/app/course/manage/detail/course-detail-line-chart.component.ts index 60c30010f7de..17a273f95704 100644 --- a/src/main/webapp/app/course/manage/detail/course-detail-line-chart.component.ts +++ b/src/main/webapp/app/course/manage/detail/course-detail-line-chart.component.ts @@ -1,8 +1,8 @@ -import { Component, Input, OnChanges } from '@angular/core'; +import { Component, Input, OnChanges, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import dayjs from 'dayjs/esm'; import { CourseManagementService } from '../course-management.service'; -import { Color, ScaleType } from '@swimlane/ngx-charts'; +import { Color, LineChartModule, ScaleType } from '@swimlane/ngx-charts'; import { roundScorePercentSpecifiedByCourseSettings } from 'app/shared/util/utils'; import { Course } from 'app/entities/course.model'; import { faArrowLeft, faArrowRight, faSpinner } from '@fortawesome/free-solid-svg-icons'; @@ -10,6 +10,13 @@ import * as shape from 'd3-shape'; import { GraphColors } from 'app/entities/statistics.model'; import { ActiveStudentsChart } from 'app/shared/chart/active-students-chart'; import { mean } from 'simple-statistics'; +import { RouterLink } from '@angular/router'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export enum SwitchTimeSpanDirection { LEFT, @@ -20,8 +27,12 @@ export enum SwitchTimeSpanDirection { selector: 'jhi-course-detail-line-chart', templateUrl: './course-detail-line-chart.component.html', styleUrls: ['./course-detail-line-chart.component.scss'], + imports: [RouterLink, TranslateDirective, HelpIconComponent, NgbTooltip, FaIconComponent, LineChartModule, ArtemisDatePipe, ArtemisTranslatePipe], }) export class CourseDetailLineChartComponent extends ActiveStudentsChart implements OnChanges { + private service = inject(CourseManagementService); + private translateService = inject(TranslateService); + @Input() course: Course; @Input() @@ -70,10 +81,7 @@ export class CourseDetailLineChartComponent extends ActiveStudentsChart implemen faArrowLeft = faArrowLeft; faArrowRight = faArrowRight; - constructor( - private service: CourseManagementService, - private translateService: TranslateService, - ) { + constructor() { super(); this.translateService.onLangChange.subscribe(() => { this.loadTranslations(); diff --git a/src/main/webapp/app/course/manage/detail/course-detail.component.ts b/src/main/webapp/app/course/manage/detail/course-detail.component.ts index 4b5ecc80b629..b9e4057208cf 100644 --- a/src/main/webapp/app/course/manage/detail/course-detail.component.ts +++ b/src/main/webapp/app/course/manage/detail/course-detail.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { PROFILE_ATHENA, PROFILE_IRIS, PROFILE_LTI } from 'app/app.constants'; @@ -19,6 +19,9 @@ import { DetailOverviewSection, DetailType } from 'app/detail-overview-list/deta import { ArtemisMarkdownService } from 'app/shared/markdown.service'; import { IrisSubSettingsType } from 'app/entities/iris/settings/iris-sub-settings.model'; import { Detail } from 'app/detail-overview-list/detail.model'; +import { CourseDetailDoughnutChartComponent } from './course-detail-doughnut-chart.component'; +import { CourseDetailLineChartComponent } from './course-detail-line-chart.component'; +import { DetailOverviewListComponent } from 'app/detail-overview-list/detail-overview-list.component'; export enum DoughnutChartType { ASSESSMENT = 'ASSESSMENT', @@ -35,8 +38,20 @@ export enum DoughnutChartType { selector: 'jhi-course-detail', templateUrl: './course-detail.component.html', styleUrls: ['./course-detail.component.scss'], + imports: [CourseDetailDoughnutChartComponent, CourseDetailLineChartComponent, DetailOverviewListComponent], }) export class CourseDetailComponent implements OnInit, OnDestroy { + private eventManager = inject(EventManager); + private courseManagementService = inject(CourseManagementService); + private organizationService = inject(OrganizationManagementService); + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + private profileService = inject(ProfileService); + private accountService = inject(AccountService); + private irisSettingsService = inject(IrisSettingsService); + private markdownService = inject(ArtemisMarkdownService); + private featureToggleService = inject(FeatureToggleService); + readonly DoughnutChartType = DoughnutChartType; readonly FeatureToggle = FeatureToggle; @@ -69,19 +84,6 @@ export class CourseDetailComponent implements OnInit, OnDestroy { faChartBar = faChartBar; faClipboard = faClipboard; - constructor( - private eventManager: EventManager, - private courseManagementService: CourseManagementService, - private organizationService: OrganizationManagementService, - private route: ActivatedRoute, - private alertService: AlertService, - private profileService: ProfileService, - private accountService: AccountService, - private irisSettingsService: IrisSettingsService, - private markdownService: ArtemisMarkdownService, - private featureToggleService: FeatureToggleService, - ) {} - /** * On init load the course information and subscribe to listen for changes in courses. */ diff --git a/src/main/webapp/app/course/manage/image-cropper-modal.component.ts b/src/main/webapp/app/course/manage/image-cropper-modal.component.ts index 12944633f6e0..d327a064c8bb 100644 --- a/src/main/webapp/app/course/manage/image-cropper-modal.component.ts +++ b/src/main/webapp/app/course/manage/image-cropper-modal.component.ts @@ -1,20 +1,23 @@ -import { Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { ImageCroppedEvent } from 'app/shared/image-cropper/interfaces/image-cropped-event.interface'; import { OutputFormat } from 'app/shared/image-cropper/interfaces/cropper-options.interface'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ImageCropperComponent } from 'app/shared/image-cropper/component/image-cropper.component'; @Component({ selector: 'jhi-image-cropper-modal', templateUrl: './image-cropper-modal.component.html', + imports: [TranslateDirective, ImageCropperComponent], }) export class ImageCropperModalComponent { + private activeModal = inject(NgbActiveModal); + uploadFile?: File; croppedImage?: string; roundCropper = true; fileFormat: OutputFormat = 'png'; - constructor(private activeModal: NgbActiveModal) {} - /** * Called when an image is cropped. * @param event The event containing the cropped image data. diff --git a/src/main/webapp/app/course/manage/overview/course-management-card.component.ts b/src/main/webapp/app/course/manage/overview/course-management-card.component.ts index 2fd25af861ed..436def467956 100644 --- a/src/main/webapp/app/course/manage/overview/course-management-card.component.ts +++ b/src/main/webapp/app/course/manage/overview/course-management-card.component.ts @@ -25,12 +25,38 @@ import { faUserCheck, } from '@fortawesome/free-solid-svg-icons'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; +import { NgStyle } from '@angular/common'; +import { RouterLink } from '@angular/router'; +import { SecuredImageComponent } from 'app/shared/image/secured-image.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { CourseManagementExerciseRowComponent } from './course-management-exercise-row.component'; +import { CourseManagementOverviewStatisticsComponent } from './course-management-overview-statistics.component'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FeatureToggleLinkDirective } from 'app/shared/feature-toggle/feature-toggle-link.directive'; +import { FeatureToggleHideDirective } from 'app/shared/feature-toggle/feature-toggle-hide.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-course-management-card', templateUrl: './course-management-card.component.html', styleUrls: ['course-management-card.scss'], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + NgStyle, + RouterLink, + SecuredImageComponent, + TranslateDirective, + FaIconComponent, + CourseManagementExerciseRowComponent, + CourseManagementOverviewStatisticsComponent, + NgbTooltip, + FeatureToggleLinkDirective, + FeatureToggleHideDirective, + ArtemisDatePipe, + ArtemisTranslatePipe, + ], }) export class CourseManagementCardComponent implements OnChanges { readonly ARTEMIS_DEFAULT_COLOR = ARTEMIS_DEFAULT_COLOR; diff --git a/src/main/webapp/app/course/manage/overview/course-management-exercise-row.component.ts b/src/main/webapp/app/course/manage/overview/course-management-exercise-row.component.ts index 1a2b62285a3a..c69035905d6a 100644 --- a/src/main/webapp/app/course/manage/overview/course-management-exercise-row.component.ts +++ b/src/main/webapp/app/course/manage/overview/course-management-exercise-row.component.ts @@ -6,6 +6,16 @@ import { Course } from 'app/entities/course.model'; import { roundValueSpecifiedByCourseSettings } from 'app/shared/util/utils'; import { faBook, faExclamationTriangle, faFileSignature, faTable, faTimes, faUsers, faWrench } from '@fortawesome/free-solid-svg-icons'; import { faCalendarAlt } from '@fortawesome/free-regular-svg-icons'; +import { RouterLink } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ExerciseCategoriesComponent } from 'app/shared/exercise-categories/exercise-categories.component'; +import { NgClass } from '@angular/common'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ProgressBarComponent } from 'app/shared/dashboards/tutor-participation-graph/progress-bar/progress-bar.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { ArtemisTimeAgoPipe } from 'app/shared/pipes/artemis-time-ago.pipe'; export enum ExerciseRowType { FUTURE = 'future', @@ -19,6 +29,18 @@ export enum ExerciseRowType { templateUrl: './course-management-exercise-row.component.html', styleUrls: ['course-management-exercise-row.scss'], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + RouterLink, + FaIconComponent, + NgbTooltip, + ExerciseCategoriesComponent, + NgClass, + TranslateDirective, + ProgressBarComponent, + ArtemisDatePipe, + ArtemisTranslatePipe, + ArtemisTimeAgoPipe, + ], }) export class CourseManagementExerciseRowComponent implements OnChanges { @Input() course: Course; @@ -57,8 +79,6 @@ export class CourseManagementExerciseRowComponent implements OnChanges { faExclamationTriangle = faExclamationTriangle; faFileSignature = faFileSignature; - constructor() {} - ngOnChanges() { if (this.details && !this.detailsLoaded) { this.detailsLoaded = true; diff --git a/src/main/webapp/app/course/manage/overview/course-management-overview-exercise-statistics-dto.model.ts b/src/main/webapp/app/course/manage/overview/course-management-overview-exercise-statistics-dto.model.ts index 7780cdcdd19c..3738b17e0e01 100644 --- a/src/main/webapp/app/course/manage/overview/course-management-overview-exercise-statistics-dto.model.ts +++ b/src/main/webapp/app/course/manage/overview/course-management-overview-exercise-statistics-dto.model.ts @@ -9,6 +9,4 @@ export class CourseManagementOverviewExerciseStatisticsDTO { public noOfRatedAssessments?: number; public noOfSubmissionsInTime?: number; public noOfAssessmentsDoneInPercent?: number; - - constructor() {} } diff --git a/src/main/webapp/app/course/manage/overview/course-management-overview-statistics-dto.model.ts b/src/main/webapp/app/course/manage/overview/course-management-overview-statistics-dto.model.ts index 4195209c07e7..7540cf386005 100644 --- a/src/main/webapp/app/course/manage/overview/course-management-overview-statistics-dto.model.ts +++ b/src/main/webapp/app/course/manage/overview/course-management-overview-statistics-dto.model.ts @@ -4,6 +4,4 @@ export class CourseManagementOverviewStatisticsDto { public courseId?: number; public exerciseDTOS: CourseManagementOverviewExerciseStatisticsDTO[]; public activeStudents?: number[]; - - constructor() {} } diff --git a/src/main/webapp/app/course/manage/overview/course-management-overview-statistics.component.ts b/src/main/webapp/app/course/manage/overview/course-management-overview-statistics.component.ts index 1d155291a83b..8fbb9f5b03e4 100644 --- a/src/main/webapp/app/course/manage/overview/course-management-overview-statistics.component.ts +++ b/src/main/webapp/app/course/manage/overview/course-management-overview-statistics.component.ts @@ -1,18 +1,25 @@ -import { Component, Input, OnChanges, OnInit } from '@angular/core'; +import { Component, Input, OnChanges, OnInit, inject } from '@angular/core'; import { GraphColors, Graphs } from 'app/entities/statistics.model'; import { TranslateService } from '@ngx-translate/core'; -import { Color, ScaleType } from '@swimlane/ngx-charts'; +import { Color, LineChartModule, ScaleType } from '@swimlane/ngx-charts'; import { faSpinner } from '@fortawesome/free-solid-svg-icons'; import { Course } from 'app/entities/course.model'; import * as shape from 'd3-shape'; import { ActiveStudentsChart } from 'app/shared/chart/active-students-chart'; +import { RouterLink } from '@angular/router'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; @Component({ selector: 'jhi-course-management-overview-statistics', templateUrl: './course-management-overview-statistics.component.html', styleUrls: ['./course-management-overview-statistics.component.scss', '../detail/course-detail-line-chart.component.scss'], + imports: [RouterLink, TranslateDirective, HelpIconComponent, LineChartModule, ArtemisDatePipe], }) export class CourseManagementOverviewStatisticsComponent extends ActiveStudentsChart implements OnInit, OnChanges { + private translateService = inject(TranslateService); + @Input() amountOfStudentsInCourse: number; @@ -39,7 +46,7 @@ export class CourseManagementOverviewStatisticsComponent extends ActiveStudentsC // Icons faSpinner = faSpinner; - constructor(private translateService: TranslateService) { + constructor() { super(); } diff --git a/src/main/webapp/app/course/plagiarism-cases/instructor-view/detail-view/plagiarism-case-instructor-detail-view.component.ts b/src/main/webapp/app/course/plagiarism-cases/instructor-view/detail-view/plagiarism-case-instructor-detail-view.component.ts index 1b2265a266aa..3249ffdc298c 100644 --- a/src/main/webapp/app/course/plagiarism-cases/instructor-view/detail-view/plagiarism-case-instructor-detail-view.component.ts +++ b/src/main/webapp/app/course/plagiarism-cases/instructor-view/detail-view/plagiarism-case-instructor-detail-view.component.ts @@ -1,7 +1,9 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { PlagiarismCaseReviewComponent } from 'app/course/plagiarism-cases/shared/review/plagiarism-case-review.component'; +import { PlagiarismCaseVerdictComponent } from 'app/course/plagiarism-cases/shared/verdict/plagiarism-case-verdict.component'; import { PlagiarismCase } from 'app/exercises/shared/plagiarism/types/PlagiarismCase'; import { PlagiarismCasesService } from 'app/course/plagiarism-cases/shared/plagiarism-cases.service'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { HttpResponse } from '@angular/common/http'; import { getCourseFromExercise, getExerciseUrlSegment, getIcon } from 'app/entities/exercise.model'; @@ -17,14 +19,63 @@ import { abbreviateString } from 'app/utils/text.utils'; import { AccountService } from 'app/core/auth/account.service'; import { User } from 'app/core/user/user.model'; import dayjs from 'dayjs/esm'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { + NgbDropdown, + NgbDropdownItem, + NgbDropdownMenu, + NgbDropdownToggle, + NgbNav, + NgbNavContent, + NgbNavItem, + NgbNavItemRole, + NgbNavLink, + NgbNavLinkBase, + NgbNavOutlet, +} from '@ng-bootstrap/ng-bootstrap'; +import { PostingThreadComponent } from 'app/shared/metis/posting-thread/posting-thread.component'; +import { PostCreateEditModalComponent } from 'app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-create-edit-modal.component'; +import { ConfirmAutofocusButtonComponent } from 'app/shared/components/confirm-autofocus-button.component'; +import { FormsModule } from '@angular/forms'; @Component({ selector: 'jhi-plagiarism-case-instructor-detail-view', templateUrl: './plagiarism-case-instructor-detail-view.component.html', styleUrls: ['./plagiarism-case-instructor-detail-view.component.scss'], providers: [MetisService], + imports: [ + TranslateDirective, + PlagiarismCaseVerdictComponent, + FaIconComponent, + RouterLink, + NgbDropdown, + NgbDropdownToggle, + NgbDropdownMenu, + NgbDropdownItem, + PostingThreadComponent, + PostCreateEditModalComponent, + NgbNav, + NgbNavItem, + NgbNavItemRole, + NgbNavLink, + NgbNavLinkBase, + NgbNavContent, + ConfirmAutofocusButtonComponent, + FormsModule, + NgbNavOutlet, + PlagiarismCaseReviewComponent, + ], }) export class PlagiarismCaseInstructorDetailViewComponent implements OnInit, OnDestroy { + protected metisService = inject(MetisService); + private plagiarismCasesService = inject(PlagiarismCasesService); + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + private translateService = inject(TranslateService); + private themeService = inject(ThemeService); + private accountService = inject(AccountService); + courseId: number; plagiarismCaseId: number; plagiarismCase: PlagiarismCase; @@ -47,16 +98,6 @@ export class PlagiarismCaseInstructorDetailViewComponent implements OnInit, OnDe private postsSubscription: Subscription; posts: Post[]; - constructor( - protected metisService: MetisService, - private plagiarismCasesService: PlagiarismCasesService, - private route: ActivatedRoute, - private alertService: AlertService, - private translateService: TranslateService, - private themeService: ThemeService, - private accountService: AccountService, - ) {} - ngOnInit(): void { this.courseId = Number(this.route.snapshot.paramMap.get('courseId')); this.plagiarismCaseId = Number(this.route.snapshot.paramMap.get('plagiarismCaseId')); diff --git a/src/main/webapp/app/course/plagiarism-cases/instructor-view/plagiarism-cases-instructor-view.component.ts b/src/main/webapp/app/course/plagiarism-cases/instructor-view/plagiarism-cases-instructor-view.component.ts index efa0d14d147e..3a4137a35740 100644 --- a/src/main/webapp/app/course/plagiarism-cases/instructor-view/plagiarism-cases-instructor-view.component.ts +++ b/src/main/webapp/app/course/plagiarism-cases/instructor-view/plagiarism-cases-instructor-view.component.ts @@ -1,6 +1,6 @@ import { HttpResponse } from '@angular/common/http'; -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { Component, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { PlagiarismCasesService } from 'app/course/plagiarism-cases/shared/plagiarism-cases.service'; import { PlagiarismCase } from 'app/exercises/shared/plagiarism/types/PlagiarismCase'; import { Exercise, getExerciseUrlSegment, getIcon } from 'app/entities/exercise.model'; @@ -8,13 +8,34 @@ import { downloadFile } from 'app/shared/util/download.util'; import { DocumentationType } from 'app/shared/components/documentation-button/documentation-button.component'; import { GroupedPlagiarismCases } from 'app/exercises/shared/plagiarism/types/GroupedPlagiarismCase'; import { AlertService } from 'app/core/util/alert.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ProgressBarComponent } from 'app/shared/dashboards/tutor-participation-graph/progress-bar/progress-bar.component'; +import { PlagiarismCaseVerdictComponent } from '../shared/verdict/plagiarism-case-verdict.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-plagiarism-cases-instructor-view', templateUrl: './plagiarism-cases-instructor-view.component.html', styleUrls: ['./plagiarism-cases-instructor-view.component.scss'], + imports: [ + TranslateDirective, + DocumentationButtonComponent, + FaIconComponent, + RouterLink, + ProgressBarComponent, + PlagiarismCaseVerdictComponent, + ArtemisDatePipe, + ArtemisTranslatePipe, + ], }) export class PlagiarismCasesInstructorViewComponent implements OnInit { + private plagiarismCasesService = inject(PlagiarismCasesService); + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + courseId: number; examId?: number; plagiarismCases: PlagiarismCase[] = []; @@ -28,12 +49,6 @@ export class PlagiarismCasesInstructorViewComponent implements OnInit { readonly getIcon = getIcon; readonly documentationType: DocumentationType = 'PlagiarismChecks'; - constructor( - private plagiarismCasesService: PlagiarismCasesService, - private route: ActivatedRoute, - private alertService: AlertService, - ) {} - ngOnInit(): void { this.courseId = Number(this.route.snapshot.paramMap.get('courseId')); this.examId = Number(this.route.snapshot.paramMap.get('examId')); diff --git a/src/main/webapp/app/course/plagiarism-cases/instructor-view/plagiarism-cases-instructor-view.module.ts b/src/main/webapp/app/course/plagiarism-cases/instructor-view/plagiarism-cases-instructor-view.module.ts index 4c4241f2da8d..014af93d4b6b 100644 --- a/src/main/webapp/app/course/plagiarism-cases/instructor-view/plagiarism-cases-instructor-view.module.ts +++ b/src/main/webapp/app/course/plagiarism-cases/instructor-view/plagiarism-cases-instructor-view.module.ts @@ -1,7 +1,8 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { PlagiarismCasesInstructorViewComponent } from 'app/course/plagiarism-cases/instructor-view/plagiarism-cases-instructor-view.component'; import { PlagiarismCaseInstructorDetailViewComponent } from 'app/course/plagiarism-cases/instructor-view/detail-view/plagiarism-case-instructor-detail-view.component'; +import { PlagiarismCasesInstructorViewComponent } from 'app/course/plagiarism-cases/instructor-view/plagiarism-cases-instructor-view.component'; + import { Authority } from 'app/shared/constants/authority.constants'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; import { ArtemisPlagiarismCasesSharedModule } from 'app/course/plagiarism-cases/shared/plagiarism-cases-shared.module'; @@ -9,7 +10,7 @@ import { ArtemisPlagiarismCasesSharedModule } from 'app/course/plagiarism-cases/ const routes: Routes = [ { path: '', - component: PlagiarismCasesInstructorViewComponent, + loadComponent: () => import('app/course/plagiarism-cases/instructor-view/plagiarism-cases-instructor-view.component').then((m) => m.PlagiarismCasesInstructorViewComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.plagiarism.cases.pageTitle', @@ -18,7 +19,10 @@ const routes: Routes = [ }, { path: ':plagiarismCaseId', - component: PlagiarismCaseInstructorDetailViewComponent, + loadComponent: () => + import('app/course/plagiarism-cases/instructor-view/detail-view/plagiarism-case-instructor-detail-view.component').then( + (m) => m.PlagiarismCaseInstructorDetailViewComponent, + ), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.plagiarism.cases.pageTitle', @@ -28,7 +32,6 @@ const routes: Routes = [ ]; @NgModule({ - imports: [RouterModule.forChild(routes), ArtemisPlagiarismCasesSharedModule], - declarations: [PlagiarismCasesInstructorViewComponent, PlagiarismCaseInstructorDetailViewComponent], + imports: [RouterModule.forChild(routes), ArtemisPlagiarismCasesSharedModule, PlagiarismCasesInstructorViewComponent, PlagiarismCaseInstructorDetailViewComponent], }) export class ArtemisPlagiarismCasesInstructorViewModule {} diff --git a/src/main/webapp/app/course/plagiarism-cases/shared/plagiarism-cases-shared.module.ts b/src/main/webapp/app/course/plagiarism-cases/shared/plagiarism-cases-shared.module.ts index f21a9fc2cd06..c0397b829ac0 100644 --- a/src/main/webapp/app/course/plagiarism-cases/shared/plagiarism-cases-shared.module.ts +++ b/src/main/webapp/app/course/plagiarism-cases/shared/plagiarism-cases-shared.module.ts @@ -8,8 +8,15 @@ import { PlagiarismCaseReviewComponent } from 'app/course/plagiarism-cases/share import { MetisModule } from 'app/shared/metis/metis.module'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisPlagiarismModule, ArtemisTutorParticipationGraphModule, MetisModule], - declarations: [PlagiarismCaseVerdictComponent, PlagiarismCaseReviewComponent], + imports: [ + ArtemisSharedModule, + ArtemisSharedComponentModule, + ArtemisPlagiarismModule, + ArtemisTutorParticipationGraphModule, + MetisModule, + PlagiarismCaseVerdictComponent, + PlagiarismCaseReviewComponent, + ], exports: [ PlagiarismCaseVerdictComponent, PlagiarismCaseReviewComponent, diff --git a/src/main/webapp/app/course/plagiarism-cases/shared/plagiarism-cases.service.ts b/src/main/webapp/app/course/plagiarism-cases/shared/plagiarism-cases.service.ts index e4041a996cf4..c3fea5b08795 100644 --- a/src/main/webapp/app/course/plagiarism-cases/shared/plagiarism-cases.service.ts +++ b/src/main/webapp/app/course/plagiarism-cases/shared/plagiarism-cases.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { PlagiarismCase } from 'app/exercises/shared/plagiarism/types/PlagiarismCase'; @@ -15,11 +15,11 @@ export type Comparison = PlagiarismComparison; @Injectable({ providedIn: 'root' }) export class PlagiarismCasesService { + private http = inject(HttpClient); + private resourceUrl = 'api/courses'; private resourceUrlExercises = 'api/exercises'; - constructor(private http: HttpClient) {} - /* Instructor */ /** diff --git a/src/main/webapp/app/course/plagiarism-cases/shared/plagiarism-results.service.ts b/src/main/webapp/app/course/plagiarism-cases/shared/plagiarism-results.service.ts index 28652db616eb..4626a00ad485 100644 --- a/src/main/webapp/app/course/plagiarism-cases/shared/plagiarism-results.service.ts +++ b/src/main/webapp/app/course/plagiarism-cases/shared/plagiarism-results.service.ts @@ -1,12 +1,12 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class PlagiarismResultsService { - private resourceUrlExercises = 'api/exercises'; + private http = inject(HttpClient); - constructor(private http: HttpClient) {} + private resourceUrlExercises = 'api/exercises'; getNumberOfPlagiarismResultsForExercise(exerciseId: number): Observable { return this.http.get(`${this.resourceUrlExercises}/${exerciseId}/potential-plagiarism-count`); diff --git a/src/main/webapp/app/course/plagiarism-cases/shared/review/plagiarism-case-review.component.ts b/src/main/webapp/app/course/plagiarism-cases/shared/review/plagiarism-case-review.component.ts index a8ed39faa5d0..67037909c24c 100644 --- a/src/main/webapp/app/course/plagiarism-cases/shared/review/plagiarism-case-review.component.ts +++ b/src/main/webapp/app/course/plagiarism-cases/shared/review/plagiarism-case-review.component.ts @@ -1,10 +1,14 @@ import { Component, Input } from '@angular/core'; import { PlagiarismCase } from 'app/exercises/shared/plagiarism/types/PlagiarismCase'; import { Subject } from 'rxjs'; +import { NgbNav, NgbNavContent, NgbNavItem, NgbNavItemRole, NgbNavLink, NgbNavLinkBase, NgbNavOutlet } from '@ng-bootstrap/ng-bootstrap'; +import { PlagiarismSplitViewComponent } from 'app/exercises/shared/plagiarism/plagiarism-split-view/plagiarism-split-view.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-plagiarism-case-review', templateUrl: './plagiarism-case-review.component.html', + imports: [NgbNav, NgbNavItem, NgbNavItemRole, NgbNavLink, NgbNavLinkBase, NgbNavContent, PlagiarismSplitViewComponent, NgbNavOutlet, ArtemisTranslatePipe], }) export class PlagiarismCaseReviewComponent { @Input() plagiarismCase: PlagiarismCase; diff --git a/src/main/webapp/app/course/plagiarism-cases/shared/verdict/plagiarism-case-verdict.component.ts b/src/main/webapp/app/course/plagiarism-cases/shared/verdict/plagiarism-case-verdict.component.ts index f1b404044906..d2d0d1a5c2d6 100644 --- a/src/main/webapp/app/course/plagiarism-cases/shared/verdict/plagiarism-case-verdict.component.ts +++ b/src/main/webapp/app/course/plagiarism-cases/shared/verdict/plagiarism-case-verdict.component.ts @@ -1,10 +1,14 @@ import { Component, Input } from '@angular/core'; import { PlagiarismCase } from 'app/exercises/shared/plagiarism/types/PlagiarismCase'; import { PlagiarismVerdict } from 'app/exercises/shared/plagiarism/types/PlagiarismVerdict'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-plagiarism-case-verdict', templateUrl: './plagiarism-case-verdict.component.html', + imports: [NgbTooltip, ArtemisDatePipe, ArtemisTranslatePipe], }) export class PlagiarismCaseVerdictComponent { @Input() plagiarismCase: PlagiarismCase; diff --git a/src/main/webapp/app/course/plagiarism-cases/student-view/detail-view/plagiarism-case-student-detail-view.component.ts b/src/main/webapp/app/course/plagiarism-cases/student-view/detail-view/plagiarism-case-student-detail-view.component.ts index feb0bf3c8d02..30fe9f16082c 100644 --- a/src/main/webapp/app/course/plagiarism-cases/student-view/detail-view/plagiarism-case-student-detail-view.component.ts +++ b/src/main/webapp/app/course/plagiarism-cases/student-view/detail-view/plagiarism-case-student-detail-view.component.ts @@ -1,7 +1,9 @@ -import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { Component, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; +import { PlagiarismCaseReviewComponent } from 'app/course/plagiarism-cases/shared/review/plagiarism-case-review.component'; +import { PlagiarismCaseVerdictComponent } from 'app/course/plagiarism-cases/shared/verdict/plagiarism-case-verdict.component'; import { PlagiarismCase } from 'app/exercises/shared/plagiarism/types/PlagiarismCase'; import { PlagiarismCasesService } from 'app/course/plagiarism-cases/shared/plagiarism-cases.service'; -import { ActivatedRoute, Params } from '@angular/router'; +import { ActivatedRoute, Params, RouterLink } from '@angular/router'; import { HttpResponse } from '@angular/common/http'; import { getCourseFromExercise, getIcon } from 'app/entities/exercise.model'; import { Subscription, combineLatest } from 'rxjs'; @@ -13,14 +15,23 @@ import { PlagiarismVerdict } from 'app/exercises/shared/plagiarism/types/Plagiar import { PostComponent } from 'app/shared/metis/post/post.component'; import { ButtonType } from 'app/shared/components/button.component'; import dayjs from 'dayjs/esm'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-plagiarism-case-student-detail-view', templateUrl: './plagiarism-case-student-detail-view.component.html', styleUrls: ['./plagiarism-case-student-detail-view.component.scss'], providers: [MetisService], + imports: [TranslateDirective, PlagiarismCaseVerdictComponent, FaIconComponent, RouterLink, PostComponent, ButtonComponent, PlagiarismCaseReviewComponent, ArtemisTranslatePipe], }) export class PlagiarismCaseStudentDetailViewComponent implements OnInit, OnDestroy { + protected metisService = inject(MetisService); + private plagiarismCasesService = inject(PlagiarismCasesService); + private activatedRoute = inject(ActivatedRoute); + @ViewChild('post') postComponent: PostComponent; readonly ButtonType = ButtonType; @@ -44,12 +55,6 @@ export class PlagiarismCaseStudentDetailViewComponent implements OnInit, OnDestr readonly dayjs = dayjs; - constructor( - protected metisService: MetisService, - private plagiarismCasesService: PlagiarismCasesService, - private activatedRoute: ActivatedRoute, - ) {} - ngOnInit(): void { this.paramSubscription = combineLatest({ ancestorParams: this.activatedRoute.parent!.parent!.params, diff --git a/src/main/webapp/app/course/plagiarism-cases/student-view/plagiarism-cases-student-view.module.ts b/src/main/webapp/app/course/plagiarism-cases/student-view/plagiarism-cases-student-view.module.ts index 373e04e0616a..081f4156c14e 100644 --- a/src/main/webapp/app/course/plagiarism-cases/student-view/plagiarism-cases-student-view.module.ts +++ b/src/main/webapp/app/course/plagiarism-cases/student-view/plagiarism-cases-student-view.module.ts @@ -1,6 +1,7 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { PlagiarismCaseStudentDetailViewComponent } from 'app/course/plagiarism-cases/student-view/detail-view/plagiarism-case-student-detail-view.component'; + import { Authority } from 'app/shared/constants/authority.constants'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; import { ArtemisPlagiarismCasesSharedModule } from 'app/course/plagiarism-cases/shared/plagiarism-cases-shared.module'; @@ -8,7 +9,8 @@ import { ArtemisPlagiarismCasesSharedModule } from 'app/course/plagiarism-cases/ const routes: Routes = [ { path: ':plagiarismCaseId', - component: PlagiarismCaseStudentDetailViewComponent, + loadComponent: () => + import('app/course/plagiarism-cases/student-view/detail-view/plagiarism-case-student-detail-view.component').then((m) => m.PlagiarismCaseStudentDetailViewComponent), data: { authorities: [Authority.USER, Authority.ADMIN], pageTitle: 'artemisApp.plagiarism.cases.pageTitle', @@ -18,7 +20,6 @@ const routes: Routes = [ ]; @NgModule({ - imports: [RouterModule.forChild(routes), ArtemisPlagiarismCasesSharedModule], - declarations: [PlagiarismCaseStudentDetailViewComponent], + imports: [RouterModule.forChild(routes), ArtemisPlagiarismCasesSharedModule, PlagiarismCaseStudentDetailViewComponent], }) export class ArtemisPlagiarismCasesStudentViewModule {} diff --git a/src/main/webapp/app/course/tutorial-groups/shared/meeting-pattern.pipe.ts b/src/main/webapp/app/course/tutorial-groups/shared/meeting-pattern.pipe.ts index 2cd9b89c262c..cff6004c3e11 100644 --- a/src/main/webapp/app/course/tutorial-groups/shared/meeting-pattern.pipe.ts +++ b/src/main/webapp/app/course/tutorial-groups/shared/meeting-pattern.pipe.ts @@ -9,13 +9,12 @@ import { RemoveSecondsPipe } from 'app/course/tutorial-groups/shared/remove-seco * Example: 'Every Week, Monday from 14:00 to 15:00' English * Example: 'Jede Woche, Montag von 14:00 bis 15:00' German */ -@Pipe({ - name: 'meetingPattern', -}) +@Pipe({ name: 'meetingPattern' }) export class MeetingPatternPipe implements PipeTransform { removeSecondsPipe = new RemoveSecondsPipe(); constructor(private translateService: TranslateService) {} + /** * Transforms a tutorial group schedule to a translated meeting pattern. * @param schedule The tutorial group schedule to transform. diff --git a/src/main/webapp/app/course/tutorial-groups/shared/remove-seconds.pipe.ts b/src/main/webapp/app/course/tutorial-groups/shared/remove-seconds.pipe.ts index af351b9d516c..5817338b88e0 100644 --- a/src/main/webapp/app/course/tutorial-groups/shared/remove-seconds.pipe.ts +++ b/src/main/webapp/app/course/tutorial-groups/shared/remove-seconds.pipe.ts @@ -3,9 +3,7 @@ import { Pipe, PipeTransform } from '@angular/core'; /** * A pipe that removes the seconds information from a time string in the format '14:00:00'. */ -@Pipe({ - name: 'removeSeconds', -}) +@Pipe({ name: 'removeSeconds' }) export class RemoveSecondsPipe implements PipeTransform { /** * Transforms a time string in the format '14:00:00' to a string without seconds, e.g. '14:00'. diff --git a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-detail/tutorial-group-detail.component.ts b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-detail/tutorial-group-detail.component.ts index 2b3adc91f4e3..97f692fb8d54 100644 --- a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-detail/tutorial-group-detail.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-detail/tutorial-group-detail.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, ContentChild, Input, OnChanges, SimpleChanges, TemplateRef } from '@angular/core'; +import { ChangeDetectorRef, Component, ContentChild, Input, OnChanges, SimpleChanges, TemplateRef, inject } from '@angular/core'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { Course, isMessagingEnabled } from 'app/entities/course.model'; import { SafeHtml } from '@angular/platform-browser'; @@ -9,13 +9,40 @@ import { TranslateService } from '@ngx-translate/core'; import { faCircle, faCircleInfo, faCircleXmark, faPercent, faQuestionCircle, faUserCheck } from '@fortawesome/free-solid-svg-icons'; import dayjs from 'dayjs/esm'; import { SortService } from 'app/shared/service/sort.service'; +import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common'; +import { IconCardComponent } from 'app/shared/icon-card/icon-card.component'; +import { ProfilePictureComponent } from 'app/shared/profile-picture/profile-picture.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { RouterLink } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { TutorialGroupSessionsTableComponent } from '../tutorial-group-sessions-table/tutorial-group-sessions-table.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-tutorial-group-detail', templateUrl: './tutorial-group-detail.component.html', styleUrls: ['./tutorial-group-detail.component.scss'], + imports: [ + NgTemplateOutlet, + IconCardComponent, + ProfilePictureComponent, + TranslateDirective, + RouterLink, + FaIconComponent, + NgbTooltip, + NgClass, + NgStyle, + TutorialGroupSessionsTableComponent, + ArtemisTranslatePipe, + ], }) export class TutorialGroupDetailComponent implements OnChanges { + private artemisMarkdownService = inject(ArtemisMarkdownService); + private changeDetectorRef = inject(ChangeDetectorRef); + private translateService = inject(TranslateService); + private sortService = inject(SortService); + @ContentChild(TemplateRef, { static: true }) header: TemplateRef; @Input() @@ -44,13 +71,6 @@ export class TutorialGroupDetailComponent implements OnChanges { readonly faCircle = faCircle; readonly faCircleXmark = faCircleXmark; - constructor( - private artemisMarkdownService: ArtemisMarkdownService, - private changeDetectorRef: ChangeDetectorRef, - private translateService: TranslateService, - private sortService: SortService, - ) {} - ngOnChanges(changes: SimpleChanges) { for (const propName in changes) { if (changes.hasOwnProperty(propName) && propName === 'tutorialGroup') { diff --git a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-free-days-overview/tutorial-group-free-days-overview.component.ts b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-free-days-overview/tutorial-group-free-days-overview.component.ts index 97226684b4a0..b23b5b89e17a 100644 --- a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-free-days-overview/tutorial-group-free-days-overview.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-free-days-overview/tutorial-group-free-days-overview.component.ts @@ -1,19 +1,24 @@ -import { ChangeDetectionStrategy, Component, DoCheck, Input, IterableDiffer, IterableDiffers, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, Component, DoCheck, Input, IterableDiffer, IterableDiffers, OnInit, inject } from '@angular/core'; import { TutorialGroupFreePeriod } from 'app/entities/tutorial-group/tutorial-group-free-day.model'; import { SortService } from 'app/shared/service/sort.service'; import dayjs from 'dayjs/esm'; +import { SidePanelComponent } from 'app/shared/side-panel/side-panel.component'; +import { NgClass } from '@angular/common'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-tutorial-group-free-days-overview', templateUrl: './tutorial-group-free-days-overview.component.html', styleUrls: ['./tutorial-group-free-days-overview.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [SidePanelComponent, NgClass, TranslateDirective, NgbPopover, ArtemisDatePipe, ArtemisTranslatePipe], }) export class TutorialGroupFreeDaysOverviewComponent implements OnInit, DoCheck { - constructor( - private sortService: SortService, - private iterableDiffers: IterableDiffers, - ) {} + private sortService = inject(SortService); + private iterableDiffers = inject(IterableDiffers); @Input() tutorialGroupFreeDays: TutorialGroupFreePeriod[] = []; diff --git a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-sessions-table/tutorial-group-session-row/tutorial-group-session-row.component.ts b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-sessions-table/tutorial-group-session-row/tutorial-group-session-row.component.ts index 02fe89acac8b..bb28f1a9e113 100644 --- a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-sessions-table/tutorial-group-session-row/tutorial-group-session-row.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-sessions-table/tutorial-group-session-row/tutorial-group-session-row.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostBinding, Input, OnChanges, Output, TemplateRef, ViewEncapsulation } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostBinding, Input, OnChanges, Output, TemplateRef, ViewEncapsulation, inject } from '@angular/core'; import { faUmbrellaBeach } from '@fortawesome/free-solid-svg-icons'; import { TutorialGroupSession, TutorialGroupSessionStatus } from 'app/entities/tutorial-group/tutorial-group-session.model'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; @@ -7,17 +7,28 @@ import { onError } from 'app/shared/util/global.utils'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { AlertService } from 'app/core/util/alert.service'; import { map } from 'rxjs'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgTemplateOutlet } from '@angular/common'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ // this is intended and an attribute selector because otherwise the rendered table breaks - // eslint-disable-next-line @angular-eslint/component-selector selector: '[jhi-session-row]', templateUrl: './tutorial-group-session-row.component.html', styleUrls: ['./tutorial-group-session-row.component.scss'], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, + imports: [NgbPopover, FaIconComponent, FormsModule, TranslateDirective, NgTemplateOutlet, ArtemisDatePipe, ArtemisTranslatePipe], }) export class TutorialGroupSessionRowComponent implements OnChanges { + private changeDetectorRef = inject(ChangeDetectorRef); + private tutorialGroupSessionService = inject(TutorialGroupSessionService); + private alertService = inject(AlertService); + @HostBinding('class') class = 'tutorial-group-session-row'; @Input() @@ -48,12 +59,6 @@ export class TutorialGroupSessionRowComponent implements OnChanges { hasSchedule = false; - constructor( - private changeDetectorRef: ChangeDetectorRef, - private tutorialGroupSessionService: TutorialGroupSessionService, - private alertService: AlertService, - ) {} - ngOnChanges() { if (this.session) { this.isCancelled = this.session.status === TutorialGroupSessionStatus.CANCELLED; diff --git a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-sessions-table/tutorial-group-sessions-table.component.ts b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-sessions-table/tutorial-group-sessions-table.component.ts index f21326185326..f94d5feb4a88 100644 --- a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-sessions-table/tutorial-group-sessions-table.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-sessions-table/tutorial-group-sessions-table.component.ts @@ -10,11 +10,16 @@ import { SimpleChanges, TemplateRef, ViewEncapsulation, + inject, } from '@angular/core'; import { TutorialGroupSession } from 'app/entities/tutorial-group/tutorial-group-session.model'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { SortService } from 'app/shared/service/sort.service'; import dayjs from 'dayjs/esm'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { TutorialGroupSessionRowComponent } from './tutorial-group-session-row/tutorial-group-session-row.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-tutorial-group-sessions-table', @@ -22,8 +27,12 @@ import dayjs from 'dayjs/esm'; styleUrls: ['./tutorial-group-sessions-table.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, + imports: [TranslateDirective, TutorialGroupSessionRowComponent, ArtemisDatePipe, ArtemisTranslatePipe], }) export class TutorialGroupSessionsTableComponent implements OnChanges { + private sortService = inject(SortService); + private changeDetectorRef = inject(ChangeDetectorRef); + @ContentChild(TemplateRef, { static: true }) extraColumn: TemplateRef; @Input() @@ -62,11 +71,6 @@ export class TutorialGroupSessionsTableComponent implements OnChanges { return numberOfColumns; } - constructor( - private sortService: SortService, - private changeDetectorRef: ChangeDetectorRef, - ) {} - ngOnChanges(changes: SimpleChanges) { for (const propName in changes) { if (changes.hasOwnProperty(propName)) { diff --git a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-utilization-indicator/tutorial-group-utilization-indicator.component.ts b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-utilization-indicator/tutorial-group-utilization-indicator.component.ts index e6a34005ba84..00507fe08da5 100644 --- a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-utilization-indicator/tutorial-group-utilization-indicator.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-group-utilization-indicator/tutorial-group-utilization-indicator.component.ts @@ -1,11 +1,14 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; +import { VerticalProgressBarComponent } from 'app/shared/vertical-progress-bar/vertical-progress-bar.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-tutorial-group-utilization-indicator', templateUrl: './tutorial-group-utilization-indicator.component.html', styleUrls: ['./tutorial-group-utilization-indicator.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [VerticalProgressBarComponent, ArtemisTranslatePipe], }) export class TutorialGroupUtilizationIndicatorComponent { readonly Math = Math; diff --git a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-groups-shared.module.ts b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-groups-shared.module.ts index 3c1417c6a2b6..47820f440d42 100644 --- a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-groups-shared.module.ts +++ b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-groups-shared.module.ts @@ -8,7 +8,7 @@ import { TutorialGroupSessionRowComponent } from 'app/course/tutorial-groups/sha import { TutorialGroupFreeDaysOverviewComponent } from './tutorial-group-free-days-overview/tutorial-group-free-days-overview.component'; import { ArtemisSidePanelModule } from 'app/shared/side-panel/side-panel.module'; import { TutorialGroupRowComponent } from './tutorial-groups-table/tutorial-group-row/tutorial-group-row.component'; -import { VerticalProgressBarModule } from 'app/shared/vertical-progress-bar/vertical-progress-bar.module'; + import { TutorialGroupUtilizationIndicatorComponent } from './tutorial-group-utilization-indicator/tutorial-group-utilization-indicator.component'; import { RemoveSecondsPipe } from 'app/course/tutorial-groups/shared/remove-seconds.pipe'; import { MeetingPatternPipe } from 'app/course/tutorial-groups/shared/meeting-pattern.pipe'; @@ -17,8 +17,13 @@ import { IconCardComponent } from 'app/shared/icon-card/icon-card.component'; import { ProfilePictureComponent } from 'app/shared/profile-picture/profile-picture.component'; @NgModule({ - imports: [ArtemisSharedModule, RouterModule, ArtemisSidePanelModule, VerticalProgressBarModule, DetailModule, IconCardComponent, ProfilePictureComponent], - declarations: [ + imports: [ + ArtemisSharedModule, + RouterModule, + ArtemisSidePanelModule, + DetailModule, + IconCardComponent, + ProfilePictureComponent, TutorialGroupsTableComponent, TutorialGroupDetailComponent, TutorialGroupSessionsTableComponent, diff --git a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-groups-table/tutorial-group-row/tutorial-group-row.component.ts b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-groups-table/tutorial-group-row/tutorial-group-row.component.ts index 4c8d5dd58a4d..15c240ac3263 100644 --- a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-groups-table/tutorial-group-row/tutorial-group-row.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-groups-table/tutorial-group-row/tutorial-group-row.component.ts @@ -1,14 +1,21 @@ import { ChangeDetectionStrategy, Component, HostBinding, Input, TemplateRef, ViewEncapsulation } from '@angular/core'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { Course } from 'app/entities/course.model'; +import { RouterLink } from '@angular/router'; +import { TutorialGroupUtilizationIndicatorComponent } from '../../tutorial-group-utilization-indicator/tutorial-group-utilization-indicator.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgTemplateOutlet } from '@angular/common'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { MeetingPatternPipe } from 'app/course/tutorial-groups/shared/meeting-pattern.pipe'; @Component({ - // eslint-disable-next-line @angular-eslint/component-selector selector: '[jhi-tutorial-group-row]', templateUrl: './tutorial-group-row.component.html', styleUrls: ['./tutorial-group-row.component.scss'], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, + imports: [RouterLink, TutorialGroupUtilizationIndicatorComponent, TranslateDirective, NgTemplateOutlet, ArtemisDatePipe, ArtemisTranslatePipe, MeetingPatternPipe], }) export class TutorialGroupRowComponent { readonly Math = Math; diff --git a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-groups-table/tutorial-groups-table.component.ts b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-groups-table/tutorial-groups-table.component.ts index abcec9dd4824..cd667462b5da 100644 --- a/src/main/webapp/app/course/tutorial-groups/shared/tutorial-groups-table/tutorial-groups-table.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/shared/tutorial-groups-table/tutorial-groups-table.component.ts @@ -1,17 +1,30 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, Input, OnChanges, SimpleChanges, TemplateRef } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, Input, OnChanges, SimpleChanges, TemplateRef, inject } from '@angular/core'; import { faQuestionCircle, faSort } from '@fortawesome/free-solid-svg-icons'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { SortService } from 'app/shared/service/sort.service'; import { Course } from 'app/entities/course.model'; import dayjs from 'dayjs/esm'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { RouterLink } from '@angular/router'; +import { TutorialGroupRowComponent } from './tutorial-group-row/tutorial-group-row.component'; +import { NgClass } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-tutorial-groups-table', templateUrl: './tutorial-groups-table.component.html', styleUrls: ['./tutorial-groups-table.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [TranslateDirective, SortDirective, SortByDirective, FaIconComponent, NgbTooltip, RouterLink, TutorialGroupRowComponent, NgClass, ArtemisTranslatePipe], }) export class TutorialGroupsTableComponent implements OnChanges { + private sortService = inject(SortService); + private cdr = inject(ChangeDetectorRef); + @ContentChild(TemplateRef, { static: true }) extraColumn: TemplateRef; @Input() @@ -50,11 +63,6 @@ export class TutorialGroupsTableComponent implements OnChanges { */ mifOfDifferentLanguages = false; - constructor( - private sortService: SortService, - private cdr: ChangeDetectorRef, - ) {} - trackId(index: number, item: TutorialGroup) { return item.id; } diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/registered-students/registered-students.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/registered-students/registered-students.component.ts index eafa6e8710ce..46ceddc68c67 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/registered-students/registered-students.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/registered-students/registered-students.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, inject } from '@angular/core'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { TutorialGroupsService } from 'app/course/tutorial-groups/services/tutorial-groups.service'; import { AlertService } from 'app/core/util/alert.service'; @@ -11,13 +11,24 @@ import { AccountService } from 'app/core/auth/account.service'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { Subject } from 'rxjs'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CourseGroupComponent } from 'app/shared/course-group/course-group.component'; @Component({ selector: 'jhi-registered-students', templateUrl: './registered-students.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [LoadingIndicatorContainerComponent, TranslateDirective, CourseGroupComponent], }) export class RegisteredStudentsComponent implements OnDestroy { + private activeModal = inject(NgbActiveModal); + private tutorialGroupService = inject(TutorialGroupsService); + private alertService = inject(AlertService); + private accountService = inject(AccountService); + private courseService = inject(CourseManagementService); + private cdr = inject(ChangeDetectorRef); + @Input() course: Course; @@ -48,15 +59,6 @@ export class RegisteredStudentsComponent implements OnDestroy { } } - constructor( - private activeModal: NgbActiveModal, - private tutorialGroupService: TutorialGroupsService, - private alertService: AlertService, - private accountService: AccountService, - private courseService: CourseManagementService, - private cdr: ChangeDetectorRef, - ) {} - ngOnDestroy(): void { this.ngUnsubscribe.next(); this.ngUnsubscribe.complete(); diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/create-tutorial-group-free-period/create-tutorial-group-free-period.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/create-tutorial-group-free-period/create-tutorial-group-free-period.component.ts index 11c86fc7af6c..24258f9a6e5f 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/create-tutorial-group-free-period/create-tutorial-group-free-period.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/create-tutorial-group-free-period/create-tutorial-group-free-period.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, Input, OnDestroy } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnDestroy, inject } from '@angular/core'; import { TutorialGroupFreePeriodDTO, TutorialGroupFreePeriodService } from 'app/course/tutorial-groups/services/tutorial-group-free-period.service'; import { TutorialGroupFreePeriodFormData } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/tutorial-free-period-form/tutorial-group-free-period-form.component'; import { finalize, takeUntil } from 'rxjs/operators'; @@ -9,13 +9,21 @@ import { Course } from 'app/entities/course.model'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { Subject } from 'rxjs'; import { captureException } from '@sentry/angular'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { TutorialGroupFreePeriodFormComponent } from '../tutorial-free-period-form/tutorial-group-free-period-form.component'; @Component({ selector: 'jhi-create-tutorial-group-free-day', templateUrl: './create-tutorial-group-free-period.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [LoadingIndicatorContainerComponent, TranslateDirective, TutorialGroupFreePeriodFormComponent], }) export class CreateTutorialGroupFreePeriodComponent implements OnDestroy { + private activeModal = inject(NgbActiveModal); + private tutorialGroupFreePeriodService = inject(TutorialGroupFreePeriodService); + private alertService = inject(AlertService); + ngUnsubscribe = new Subject(); tutorialGroupFreePeriodToCreate: TutorialGroupFreePeriodDTO = new TutorialGroupFreePeriodDTO(); @@ -29,12 +37,6 @@ export class CreateTutorialGroupFreePeriodComponent implements OnDestroy { isInitialized = false; - constructor( - private activeModal: NgbActiveModal, - private tutorialGroupFreePeriodService: TutorialGroupFreePeriodService, - private alertService: AlertService, - ) {} - initialize() { if (!this.tutorialGroupConfigurationId || !this.course) { console.error('Error: Component not fully configured'); diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/edit-tutorial-group-free-period/edit-tutorial-group-free-period.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/edit-tutorial-group-free-period/edit-tutorial-group-free-period.component.ts index 2b345504a615..b9d7fa038e14 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/edit-tutorial-group-free-period/edit-tutorial-group-free-period.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/edit-tutorial-group-free-period/edit-tutorial-group-free-period.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, Input, OnDestroy } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnDestroy, inject } from '@angular/core'; import { TutorialGroupsConfiguration } from 'app/entities/tutorial-group/tutorial-groups-configuration.model'; import { AlertService } from 'app/core/util/alert.service'; import { onError } from 'app/shared/util/global.utils'; @@ -12,13 +12,21 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { takeUntil } from 'rxjs/operators'; import { CreateTutorialGroupFreePeriodComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/create-tutorial-group-free-period/create-tutorial-group-free-period.component'; import { TutorialGroupFreePeriodsManagementComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-periods-management.component'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { TutorialGroupFreePeriodFormComponent } from '../tutorial-free-period-form/tutorial-group-free-period-form.component'; @Component({ selector: 'jhi-edit-tutorial-group-free-period', templateUrl: './edit-tutorial-group-free-period.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [LoadingIndicatorContainerComponent, TranslateDirective, TutorialGroupFreePeriodFormComponent], }) export class EditTutorialGroupFreePeriodComponent implements OnDestroy { + private activeModal = inject(NgbActiveModal); + private tutorialGroupFreePeriodService = inject(TutorialGroupFreePeriodService); + private alertService = inject(AlertService); + isLoading = false; @Input() @@ -34,11 +42,6 @@ export class EditTutorialGroupFreePeriodComponent implements OnDestroy { ngUnsubscribe = new Subject(); formData: TutorialGroupFreePeriodFormData; - constructor( - private activeModal: NgbActiveModal, - private tutorialGroupFreePeriodService: TutorialGroupFreePeriodService, - private alertService: AlertService, - ) {} /** * Initializes the component by setting up the form data based on the tutorial group free period, course, and tutorial groups configuration. diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/tutorial-free-period-form/tutorial-group-free-period-form.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/tutorial-free-period-form/tutorial-group-free-period-form.component.ts index 3bf9198265bd..f6f0aa787520 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/tutorial-free-period-form/tutorial-group-free-period-form.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/tutorial-free-period-form/tutorial-group-free-period-form.component.ts @@ -1,7 +1,12 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output, inject } from '@angular/core'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { faCalendarAlt } from '@fortawesome/free-solid-svg-icons'; -import { OWL_DATE_TIME_FORMATS } from '@danielmoncada/angular-datetime-picker'; +import { OWL_DATE_TIME_FORMATS, OwlDateTimeModule } from '@danielmoncada/angular-datetime-picker'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgClass } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export const MY_NATIVE_FORMATS = { datePickerInput: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }, @@ -34,8 +39,11 @@ export enum TimeFrame { templateUrl: './tutorial-group-free-period-form.component.html', changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: OWL_DATE_TIME_FORMATS, useValue: MY_NATIVE_FORMATS }], + imports: [TranslateDirective, FormsModule, ReactiveFormsModule, OwlDateTimeModule, NgClass, FaIconComponent, ArtemisDatePipe, ArtemisTranslatePipe], }) export class TutorialGroupFreePeriodFormComponent implements OnInit, OnChanges { + private fb = inject(FormBuilder); + @Input() formData: TutorialGroupFreePeriodFormData = { startDate: undefined, @@ -150,8 +158,6 @@ export class TutorialGroupFreePeriodFormComponent implements OnInit, OnChanges { return false; } - constructor(private fb: FormBuilder) {} - ngOnInit(): void { this.initializeForm(); } diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-period-row-buttons/tutorial-group-free-period-row-buttons.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-period-row-buttons/tutorial-group-free-period-row-buttons.component.ts index c841ff877284..9354d920a7fc 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-period-row-buttons/tutorial-group-free-period-row-buttons.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-period-row-buttons/tutorial-group-free-period-row-buttons.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output, inject } from '@angular/core'; import { TutorialGroupFreePeriod } from 'app/entities/tutorial-group/tutorial-group-free-day.model'; import { TutorialGroupFreePeriodService } from 'app/course/tutorial-groups/services/tutorial-group-free-period.service'; import { HttpErrorResponse } from '@angular/common/http'; @@ -9,13 +9,21 @@ import { Course } from 'app/entities/course.model'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { EditTutorialGroupFreePeriodComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/edit-tutorial-group-free-period/edit-tutorial-group-free-period.component'; import { catchError, takeUntil } from 'rxjs/operators'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; @Component({ selector: 'jhi-tutorial-group-free-period-row-buttons', templateUrl: './tutorial-group-free-period-row-buttons.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [FaIconComponent, TranslateDirective, DeleteButtonDirective, ArtemisDatePipe], }) export class TutorialGroupFreePeriodRowButtonsComponent implements OnDestroy { + private tutorialGroupFreePeriodService = inject(TutorialGroupFreePeriodService); + private modalService = inject(NgbModal); + @Input() course: Course; @Input() tutorialGroupConfiguration: TutorialGroupsConfiguration; @Input() tutorialFreePeriod: TutorialGroupFreePeriod; @@ -31,11 +39,6 @@ export class TutorialGroupFreePeriodRowButtonsComponent implements OnDestroy { faUsers = faUsers; faTrash = faTrash; - constructor( - private tutorialGroupFreePeriodService: TutorialGroupFreePeriodService, - private modalService: NgbModal, - ) {} - deleteTutorialFreePeriod = () => { this.tutorialGroupFreePeriodService .delete(this.course.id!, this.tutorialGroupConfiguration.id!, this.tutorialFreePeriod.id!) diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-periods-management.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-periods-management.component.ts index 9dffbe4b5727..a27bb05b3c0d 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-periods-management.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-periods-management.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { onError } from 'app/shared/util/global.utils'; import { TutorialGroupsConfiguration } from 'app/entities/tutorial-group/tutorial-groups-configuration.model'; import { EMPTY, Subject, combineLatest, finalize, from, switchMap, take } from 'rxjs'; @@ -14,14 +14,27 @@ import dayjs from 'dayjs/esm'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { CreateTutorialGroupFreePeriodComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/crud/create-tutorial-group-free-period/create-tutorial-group-free-period.component'; import { catchError, takeUntil } from 'rxjs/operators'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TutorialGroupFreePeriodsTableComponent } from './tutorial-group-free-periods-table/tutorial-group-free-periods-table.component'; @Component({ selector: 'jhi-tutorial-free-periods', templateUrl: './tutorial-group-free-periods-management.component.html', styleUrls: ['./tutorial-group-free-periods-management.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [LoadingIndicatorContainerComponent, TranslateDirective, FaIconComponent, TutorialGroupFreePeriodsTableComponent], }) export class TutorialGroupFreePeriodsManagementComponent implements OnInit, OnDestroy { + private activatedRoute = inject(ActivatedRoute); + private router = inject(Router); + private tutorialGroupsConfigurationService = inject(TutorialGroupsConfigurationService); + private alertService = inject(AlertService); + private sortService = inject(SortService); + private modalService = inject(NgbModal); + private cdr = inject(ChangeDetectorRef); + isLoading = false; tutorialGroupsConfiguration: TutorialGroupsConfiguration; tutorialGroupFreePeriods: TutorialGroupFreePeriod[] = []; @@ -34,16 +47,6 @@ export class TutorialGroupFreePeriodsManagementComponent implements OnInit, OnDe ngUnsubscribe = new Subject(); - constructor( - private activatedRoute: ActivatedRoute, - private router: Router, - private tutorialGroupsConfigurationService: TutorialGroupsConfigurationService, - private alertService: AlertService, - private sortService: SortService, - private modalService: NgbModal, - private cdr: ChangeDetectorRef, - ) {} - ngOnInit(): void { this.loadAll(); } diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-periods-table/tutorial-group-free-periods-table.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-periods-table/tutorial-group-free-periods-table.component.ts index e662adb9bffe..2a70480390fb 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-periods-table/tutorial-group-free-periods-table.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-periods-table/tutorial-group-free-periods-table.component.ts @@ -4,12 +4,18 @@ import { Course } from 'app/entities/course.model'; import { TutorialGroupsConfiguration } from 'app/entities/tutorial-group/tutorial-groups-configuration.model'; import dayjs from 'dayjs/esm'; import { TutorialGroupFreePeriodsManagementComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-periods-management.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgClass } from '@angular/common'; +import { TutorialGroupFreePeriodRowButtonsComponent } from '../tutorial-group-free-period-row-buttons/tutorial-group-free-period-row-buttons.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-tutorial-group-free-periods-table', templateUrl: './tutorial-group-free-periods-table.component.html', styleUrls: ['../tutorial-group-free-periods-management.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [TranslateDirective, NgClass, TutorialGroupFreePeriodRowButtonsComponent, ArtemisDatePipe, ArtemisTranslatePipe], }) export class TutorialGroupFreePeriodsTableComponent { @Input() course: Course; diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-management-resolve.service.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-management-resolve.service.ts index 862c1bfae9b4..55c86c31eaf1 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-management-resolve.service.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-management-resolve.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; import { Course } from 'app/entities/course.model'; import { CourseManagementService } from 'app/course/manage/course-management.service'; @@ -8,10 +8,8 @@ import { tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class TutorialGroupManagementResolve implements Resolve { - constructor( - private service: CourseManagementService, - private router: Router, - ) {} + private service = inject(CourseManagementService); + private router = inject(Router); resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { return this.service.find(route.params['courseId']).pipe( diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/create-tutorial-group-session/create-tutorial-group-session.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/create-tutorial-group-session/create-tutorial-group-session.component.ts index 36158766cdaa..0da7cb2344fc 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/create-tutorial-group-session/create-tutorial-group-session.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/create-tutorial-group-session/create-tutorial-group-session.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, Input, OnDestroy } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnDestroy, inject } from '@angular/core'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { AlertService } from 'app/core/util/alert.service'; import { finalize, takeUntil } from 'rxjs/operators'; @@ -8,13 +8,21 @@ import { TutorialGroupSessionDTO, TutorialGroupSessionService } from 'app/course import { Course } from 'app/entities/course.model'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { Subject } from 'rxjs'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { TutorialGroupSessionFormComponent } from '../tutorial-group-session-form/tutorial-group-session-form.component'; @Component({ selector: 'jhi-create-tutorial-group-session', templateUrl: './create-tutorial-group-session.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [LoadingIndicatorContainerComponent, TranslateDirective, TutorialGroupSessionFormComponent], }) export class CreateTutorialGroupSessionComponent implements OnDestroy { + private activeModal = inject(NgbActiveModal); + private tutorialGroupSessionService = inject(TutorialGroupSessionService); + private alertService = inject(AlertService); + ngUnsubscribe = new Subject(); tutorialGroupSessionToCreate: TutorialGroupSessionDTO = new TutorialGroupSessionDTO(); @@ -28,12 +36,6 @@ export class CreateTutorialGroupSessionComponent implements OnDestroy { isInitialized = false; - constructor( - private activeModal: NgbActiveModal, - private tutorialGroupSessionService: TutorialGroupSessionService, - private alertService: AlertService, - ) {} - initialize() { if (!this.course || !this.tutorialGroup) { console.error('Error: Component not fully configured'); diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/edit-tutorial-group-session/edit-tutorial-group-session.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/edit-tutorial-group-session/edit-tutorial-group-session.component.ts index 974395b1ff47..1f6383bfa8f1 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/edit-tutorial-group-session/edit-tutorial-group-session.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/edit-tutorial-group-session/edit-tutorial-group-session.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, Input, OnDestroy } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnDestroy, inject } from '@angular/core'; import { TutorialGroupSession } from 'app/entities/tutorial-group/tutorial-group-session.model'; import { TutorialGroupSessionFormData } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/tutorial-group-session-form/tutorial-group-session-form.component'; import { AlertService } from 'app/core/util/alert.service'; @@ -9,13 +9,21 @@ import { Course } from 'app/entities/course.model'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { Subject } from 'rxjs'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { TutorialGroupSessionFormComponent } from '../tutorial-group-session-form/tutorial-group-session-form.component'; @Component({ selector: 'jhi-edit-tutorial-group-session', templateUrl: './edit-tutorial-group-session.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [LoadingIndicatorContainerComponent, TranslateDirective, TutorialGroupSessionFormComponent], }) export class EditTutorialGroupSessionComponent implements OnDestroy { + private activeModal = inject(NgbActiveModal); + private tutorialGroupSessionService = inject(TutorialGroupSessionService); + private alertService = inject(AlertService); + ngUnsubscribe = new Subject(); @Input() @@ -32,12 +40,6 @@ export class EditTutorialGroupSessionComponent implements OnDestroy { isInitialized = false; - constructor( - private activeModal: NgbActiveModal, - private tutorialGroupSessionService: TutorialGroupSessionService, - private alertService: AlertService, - ) {} - initialize() { if (!this.tutorialGroupSession || !this.course || !this.tutorialGroup) { console.error('Error: Component not fully configured'); diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/tutorial-group-session-form/tutorial-group-session-form.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/tutorial-group-session-form/tutorial-group-session-form.component.ts index 8a4c7e1ded95..42a87fbf1929 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/tutorial-group-session-form/tutorial-group-session-form.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/tutorial-group-session-form/tutorial-group-session-form.component.ts @@ -1,9 +1,14 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { NgbTimeAdapter } from '@ng-bootstrap/ng-bootstrap'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output, inject } from '@angular/core'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; +import { NgbTimeAdapter, NgbTimepicker } from '@ng-bootstrap/ng-bootstrap'; import { faCalendarAlt } from '@fortawesome/free-solid-svg-icons'; import { NgbTimeStringAdapter } from 'app/course/tutorial-groups/shared/ngbTimeStringAdapter'; import { validTimeRange } from 'app/course/tutorial-groups/shared/timeRangeValidator'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { OwlDateTimeModule } from '@danielmoncada/angular-datetime-picker'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface TutorialGroupSessionFormData { date?: Date; @@ -17,8 +22,11 @@ export interface TutorialGroupSessionFormData { templateUrl: './tutorial-group-session-form.component.html', providers: [{ provide: NgbTimeAdapter, useClass: NgbTimeStringAdapter }], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [TranslateDirective, FormsModule, ReactiveFormsModule, OwlDateTimeModule, FaIconComponent, NgbTimepicker, ArtemisDatePipe, ArtemisTranslatePipe], }) export class TutorialGroupSessionFormComponent implements OnInit, OnChanges { + private fb = inject(FormBuilder); + @Input() formData: TutorialGroupSessionFormData = { date: undefined, @@ -67,8 +75,6 @@ export class TutorialGroupSessionFormComponent implements OnInit, OnChanges { return !this.form.invalid; } - constructor(private fb: FormBuilder) {} - ngOnInit(): void { this.initializeForm(); } diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/cancellation-modal/cancellation-modal.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/cancellation-modal/cancellation-modal.component.ts index 912ecaeb810e..f600c8ba859e 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/cancellation-modal/cancellation-modal.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/cancellation-modal/cancellation-modal.component.ts @@ -1,21 +1,29 @@ -import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { TutorialGroupSession, TutorialGroupSessionStatus } from 'app/entities/tutorial-group/tutorial-group-session.model'; import { onError } from 'app/shared/util/global.utils'; import { TutorialGroupSessionService } from 'app/course/tutorial-groups/services/tutorial-group-session.service'; import { HttpErrorResponse } from '@angular/common/http'; import { AlertService } from 'app/core/util/alert.service'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { Course } from 'app/entities/course.model'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-cancellation-modal', templateUrl: './cancellation-modal.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [FormsModule, ReactiveFormsModule, TranslateDirective, ArtemisTranslatePipe], }) export class CancellationModalComponent implements OnInit, OnDestroy { + activeModal = inject(NgbActiveModal); + private tutorialGroupSessionService = inject(TutorialGroupSessionService); + private alertService = inject(AlertService); + private fb = inject(FormBuilder); + ngUnsubscribe = new Subject(); tutorialGroupSessionStatus = TutorialGroupSessionStatus; @@ -30,13 +38,6 @@ export class CancellationModalComponent implements OnInit, OnDestroy { @Input() tutorialGroupSession: TutorialGroupSession; - constructor( - public activeModal: NgbActiveModal, - private tutorialGroupSessionService: TutorialGroupSessionService, - private alertService: AlertService, - private fb: FormBuilder, - ) {} - ngOnInit(): void { this.initializeForm(); } diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/tutorial-group-session-row-buttons/tutorial-group-session-row-buttons.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/tutorial-group-session-row-buttons/tutorial-group-session-row-buttons.component.ts index 3e037d4c89b6..916f8889b70d 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/tutorial-group-session-row-buttons/tutorial-group-session-row-buttons.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/tutorial-group-session-row-buttons/tutorial-group-session-row-buttons.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output, inject } from '@angular/core'; import { EMPTY, Subject, from } from 'rxjs'; import { faTrash, faUsers, faWrench } from '@fortawesome/free-solid-svg-icons'; import { TutorialGroupSessionService } from 'app/course/tutorial-groups/services/tutorial-group-session.service'; @@ -10,13 +10,22 @@ import { Course } from 'app/entities/course.model'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { EditTutorialGroupSessionComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/edit-tutorial-group-session/edit-tutorial-group-session.component'; import { catchError, takeUntil } from 'rxjs/operators'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-tutorial-group-session-row-buttons', templateUrl: './tutorial-group-session-row-buttons.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [FaIconComponent, TranslateDirective, DeleteButtonDirective, ArtemisDatePipe, ArtemisTranslatePipe], }) export class TutorialGroupSessionRowButtonsComponent implements OnDestroy { + private tutorialGroupSessionService = inject(TutorialGroupSessionService); + private modalService = inject(NgbModal); + ngUnsubscribe = new Subject(); @Input() course: Course; @@ -35,11 +44,6 @@ export class TutorialGroupSessionRowButtonsComponent implements OnDestroy { faUsers = faUsers; faTrash = faTrash; - constructor( - private tutorialGroupSessionService: TutorialGroupSessionService, - private modalService: NgbModal, - ) {} - deleteTutorialGroupSession = () => { this.tutorialGroupSessionService .delete(this.course.id!, this.tutorialGroup.id!, this.tutorialGroupSession.id!) diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/tutorial-group-sessions-management.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/tutorial-group-sessions-management.component.ts index 4dc520b817c9..4cc9264d423c 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/tutorial-group-sessions-management.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/tutorial-group-sessions-management.component.ts @@ -1,6 +1,7 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, ViewEncapsulation } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, ViewEncapsulation, inject } from '@angular/core'; import { TutorialGroupsService } from 'app/course/tutorial-groups/services/tutorial-groups.service'; import { AlertService } from 'app/core/util/alert.service'; +import { TutorialGroupSessionsTableComponent } from 'app/course/tutorial-groups/shared/tutorial-group-sessions-table/tutorial-group-sessions-table.component'; import { EMPTY, Subject, from } from 'rxjs'; import { catchError, finalize, map, takeUntil } from 'rxjs/operators'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; @@ -13,6 +14,12 @@ import { TutorialGroupSession } from 'app/entities/tutorial-group/tutorial-group import { getDayTranslationKey } from 'app/course/tutorial-groups/shared/weekdays'; import { NgbActiveModal, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { CreateTutorialGroupSessionComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/crud/create-tutorial-group-session/create-tutorial-group-session.component'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TutorialGroupSessionRowButtonsComponent } from './tutorial-group-session-row-buttons/tutorial-group-session-row-buttons.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { RemoveSecondsPipe } from 'app/course/tutorial-groups/shared/remove-seconds.pipe'; @Component({ selector: 'jhi-session-management', @@ -20,8 +27,23 @@ import { CreateTutorialGroupSessionComponent } from 'app/course/tutorial-groups/ styleUrls: ['./tutorial-group-sessions-management.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, + imports: [ + LoadingIndicatorContainerComponent, + TranslateDirective, + FaIconComponent, + TutorialGroupSessionsTableComponent, + TutorialGroupSessionRowButtonsComponent, + ArtemisTranslatePipe, + RemoveSecondsPipe, + ], }) export class TutorialGroupSessionsManagementComponent implements OnDestroy { + private tutorialGroupService = inject(TutorialGroupsService); + private alertService = inject(AlertService); + private modalService = inject(NgbModal); + private activeModal = inject(NgbActiveModal); + private cdr = inject(ChangeDetectorRef); + ngUnsubscribe = new Subject(); isLoading = false; @@ -39,14 +61,6 @@ export class TutorialGroupSessionsManagementComponent implements OnDestroy { isInitialized = false; - constructor( - private tutorialGroupService: TutorialGroupsService, - private alertService: AlertService, - private modalService: NgbModal, - private activeModal: NgbActiveModal, - private cdr: ChangeDetectorRef, - ) {} - initialize() { if (!this.tutorialGroupId || !this.course) { console.error('Error: Component not fully configured'); diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-checklist/tutorial-groups-checklist.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-checklist/tutorial-groups-checklist.component.ts index 8f18bbb4a7d4..aa6a810aa7a7 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-checklist/tutorial-groups-checklist.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-checklist/tutorial-groups-checklist.component.ts @@ -1,5 +1,5 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { Course } from 'app/entities/course.model'; import { AlertService } from 'app/core/util/alert.service'; @@ -9,13 +9,24 @@ import { HttpErrorResponse } from '@angular/common/http'; import { faPlus, faWrench } from '@fortawesome/free-solid-svg-icons'; import { TutorialGroupsConfigurationService } from 'app/course/tutorial-groups/services/tutorial-groups-configuration.service'; import { takeUntil } from 'rxjs/operators'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ChecklistCheckComponent } from 'app/shared/components/checklist-check/checklist-check.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-tutorial-groups-checklist', templateUrl: './tutorial-groups-checklist.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [LoadingIndicatorContainerComponent, TranslateDirective, ChecklistCheckComponent, RouterLink, FaIconComponent], }) export class TutorialGroupsChecklistComponent implements OnInit, OnDestroy { + private activatedRoute = inject(ActivatedRoute); + private courseManagementService = inject(CourseManagementService); + private alertService = inject(AlertService); + private tutorialGroupsConfigurationService = inject(TutorialGroupsConfigurationService); + private cdr = inject(ChangeDetectorRef); + isLoading = false; course: Course; isTimeZoneConfigured = false; @@ -25,13 +36,6 @@ export class TutorialGroupsChecklistComponent implements OnInit, OnDestroy { faPlus = faPlus; ngUnsubscribe = new Subject(); - constructor( - private activatedRoute: ActivatedRoute, - private courseManagementService: CourseManagementService, - private alertService: AlertService, - private tutorialGroupsConfigurationService: TutorialGroupsConfigurationService, - private cdr: ChangeDetectorRef, - ) {} get isFullyConfigured(): boolean { return this.isTimeZoneConfigured && this.isTutorialGroupConfigurationCreated; diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/create-tutorial-groups-configuration/create-tutorial-groups-configuration.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/create-tutorial-groups-configuration/create-tutorial-groups-configuration.component.ts index 9686406a47e2..36392e841ab7 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/create-tutorial-groups-configuration/create-tutorial-groups-configuration.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/create-tutorial-groups-configuration/create-tutorial-groups-configuration.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { AlertService } from 'app/core/util/alert.service'; import { ActivatedRoute, Router } from '@angular/router'; import { TutorialGroupsConfiguration } from 'app/entities/tutorial-group/tutorial-groups-configuration.model'; @@ -11,30 +11,31 @@ import { CourseManagementService } from 'app/course/manage/course-management.ser import { Course } from 'app/entities/course.model'; import { Subject } from 'rxjs'; import { CourseStorageService } from 'app/course/manage/course-storage.service'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { TutorialGroupsConfigurationFormComponent } from '../tutorial-groups-configuration-form/tutorial-groups-configuration-form.component'; @Component({ selector: 'jhi-create-tutorial-groups-configuration', templateUrl: './create-tutorial-groups-configuration.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [LoadingIndicatorContainerComponent, TranslateDirective, TutorialGroupsConfigurationFormComponent], }) export class CreateTutorialGroupsConfigurationComponent implements OnInit, OnDestroy { + private activatedRoute = inject(ActivatedRoute); + private router = inject(Router); + private tutorialGroupsConfigurationService = inject(TutorialGroupsConfigurationService); + private courseManagementService = inject(CourseManagementService); + private alertService = inject(AlertService); + private courseStorageService = inject(CourseStorageService); + private cdr = inject(ChangeDetectorRef); + ngUnsubscribe = new Subject(); newTutorialGroupsConfiguration = new TutorialGroupsConfiguration(); isLoading: boolean; course: Course; - constructor( - private activatedRoute: ActivatedRoute, - private router: Router, - private tutorialGroupsConfigurationService: TutorialGroupsConfigurationService, - private courseManagementService: CourseManagementService, - private alertService: AlertService, - private courseStorageService: CourseStorageService, - - private cdr: ChangeDetectorRef, - ) {} - ngOnInit(): void { this.isLoading = true; this.activatedRoute.paramMap diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/edit-tutorial-groups-configuration/edit-tutorial-groups-configuration.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/edit-tutorial-groups-configuration/edit-tutorial-groups-configuration.component.ts index 0998e7060f03..f34a351447d3 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/edit-tutorial-groups-configuration/edit-tutorial-groups-configuration.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/edit-tutorial-groups-configuration/edit-tutorial-groups-configuration.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { TutorialGroupsConfiguration } from 'app/entities/tutorial-group/tutorial-groups-configuration.model'; import { TutorialGroupsConfigurationFormData } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/tutorial-groups-configuration-form/tutorial-groups-configuration-form.component'; import { AlertService } from 'app/core/util/alert.service'; @@ -10,13 +10,24 @@ import { finalize, switchMap, take, takeUntil } from 'rxjs/operators'; import { HttpErrorResponse } from '@angular/common/http'; import { Course } from 'app/entities/course.model'; import { CourseStorageService } from 'app/course/manage/course-storage.service'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { TutorialGroupsConfigurationFormComponent } from '../tutorial-groups-configuration-form/tutorial-groups-configuration-form.component'; @Component({ selector: 'jhi-edit-tutorial-groups-configuration', templateUrl: './edit-tutorial-groups-configuration.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [LoadingIndicatorContainerComponent, TranslateDirective, TutorialGroupsConfigurationFormComponent], }) export class EditTutorialGroupsConfigurationComponent implements OnInit, OnDestroy { + private activatedRoute = inject(ActivatedRoute); + private router = inject(Router); + private tutorialGroupsConfigurationService = inject(TutorialGroupsConfigurationService); + private courseStorageService = inject(CourseStorageService); + private alertService = inject(AlertService); + private cdr = inject(ChangeDetectorRef); + ngUnsubscribe = new Subject(); isLoading = false; @@ -25,16 +36,6 @@ export class EditTutorialGroupsConfigurationComponent implements OnInit, OnDestr course: Course; tutorialGroupConfigurationId: number; - constructor( - private activatedRoute: ActivatedRoute, - private router: Router, - private tutorialGroupsConfigurationService: TutorialGroupsConfigurationService, - private courseStorageService: CourseStorageService, - private alertService: AlertService, - - private cdr: ChangeDetectorRef, - ) {} - ngOnInit(): void { this.isLoading = true; combineLatest([this.activatedRoute.paramMap, this.activatedRoute.data]) diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/tutorial-groups-configuration-form/tutorial-groups-configuration-form.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/tutorial-groups-configuration-form/tutorial-groups-configuration-form.component.ts index 65309727c283..8867bc84534a 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/tutorial-groups-configuration-form/tutorial-groups-configuration-form.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/tutorial-groups-configuration-form/tutorial-groups-configuration-form.component.ts @@ -1,7 +1,11 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output, inject } from '@angular/core'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { faCalendarAlt } from '@fortawesome/free-solid-svg-icons'; import { Course, isMessagingEnabled } from 'app/entities/course.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { OwlDateTimeModule } from '@danielmoncada/angular-datetime-picker'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisDateRangePipe } from 'app/shared/pipes/artemis-date-range.pipe'; export interface TutorialGroupsConfigurationFormData { period?: Date[]; @@ -14,8 +18,11 @@ export interface TutorialGroupsConfigurationFormData { templateUrl: './tutorial-groups-configuration-form.component.html', styleUrls: ['./tutorial-groups-configuration-form.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [FormsModule, ReactiveFormsModule, TranslateDirective, OwlDateTimeModule, FaIconComponent, ArtemisDateRangePipe], }) export class TutorialGroupsConfigurationFormComponent implements OnInit, OnChanges { + private fb = inject(FormBuilder); + @Input() formData: TutorialGroupsConfigurationFormData = { period: undefined, @@ -36,8 +43,6 @@ export class TutorialGroupsConfigurationFormComponent implements OnInit, OnChang form: FormGroup; - constructor(private fb: FormBuilder) {} - get periodControl() { return this.form.get('period'); } diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-management.module.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-management.module.ts index aaeac91ae070..6f952dcbf621 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-management.module.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-management.module.ts @@ -53,8 +53,6 @@ import { ArtemisMarkdownEditorModule } from 'app/shared/markdown-editor/markdown ArtemisSidePanelModule, ArtemisSharedComponentModule, ArtemisMarkdownEditorModule, - ], - declarations: [ TutorialGroupsManagementComponent, TutorialGroupFormComponent, CreateTutorialGroupComponent, diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-management.route.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-management.route.ts index 2b48dcfd4a48..c35051014537 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-management.route.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-management.route.ts @@ -3,18 +3,16 @@ */ import { Authority } from 'app/shared/constants/authority.constants'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { TutorialGroupFreePeriodsManagementComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-periods-management.component'; -import { TutorialGroupManagementDetailComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/detail/tutorial-group-management-detail.component'; -import { TutorialGroupsManagementComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-management.component'; -import { EditTutorialGroupComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/edit-tutorial-group/edit-tutorial-group.component'; -import { CreateTutorialGroupComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/create-tutorial-group/create-tutorial-group.component'; -import { EditTutorialGroupsConfigurationComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/edit-tutorial-groups-configuration/edit-tutorial-groups-configuration.component'; + import { Routes } from '@angular/router'; export const tutorialGroupManagementRoutes: Routes = [ { path: '', - component: TutorialGroupsManagementComponent, + loadComponent: () => + import('app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-management.component').then( + (m) => m.TutorialGroupsManagementComponent, + ), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.pages.tutorialGroupsManagement.title', @@ -23,7 +21,10 @@ export const tutorialGroupManagementRoutes: Routes = [ }, { path: 'configuration', - component: TutorialGroupsManagementComponent, + loadComponent: () => + import('app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-management.component').then( + (m) => m.TutorialGroupsManagementComponent, + ), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], pageTitle: 'artemisApp.pages.tutorialGroupsManagement.title', @@ -32,7 +33,10 @@ export const tutorialGroupManagementRoutes: Routes = [ }, { path: 'configuration/:tutorialGroupsConfigurationId/edit', - component: EditTutorialGroupsConfigurationComponent, + loadComponent: () => + import( + 'app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/edit-tutorial-groups-configuration/edit-tutorial-groups-configuration.component' + ).then((m) => m.EditTutorialGroupsConfigurationComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], pageTitle: 'artemisApp.pages.editTutorialGroupsConfiguration.title', @@ -41,7 +45,10 @@ export const tutorialGroupManagementRoutes: Routes = [ }, { path: 'configuration/:tutorialGroupsConfigurationId/tutorial-free-days', - component: TutorialGroupFreePeriodsManagementComponent, + loadComponent: () => + import( + 'app/course/tutorial-groups/tutorial-groups-management/tutorial-free-periods/tutorial-free-periods-management/tutorial-group-free-periods-management.component' + ).then((m) => m.TutorialGroupFreePeriodsManagementComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], pageTitle: 'artemisApp.pages.tutorialFreePeriodsManagement.title', @@ -50,7 +57,10 @@ export const tutorialGroupManagementRoutes: Routes = [ }, { path: 'create', - component: CreateTutorialGroupComponent, + loadComponent: () => + import('app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/create-tutorial-group/create-tutorial-group.component').then( + (m) => m.CreateTutorialGroupComponent, + ), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], pageTitle: 'artemisApp.pages.createTutorialGroup.title', @@ -59,7 +69,10 @@ export const tutorialGroupManagementRoutes: Routes = [ }, { path: ':tutorialGroupId/edit', - component: EditTutorialGroupComponent, + loadComponent: () => + import('app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/edit-tutorial-group/edit-tutorial-group.component').then( + (m) => m.EditTutorialGroupComponent, + ), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], pageTitle: 'artemisApp.pages.editTutorialGroup.title', @@ -68,7 +81,10 @@ export const tutorialGroupManagementRoutes: Routes = [ }, { path: ':tutorialGroupId', - component: TutorialGroupManagementDetailComponent, + loadComponent: () => + import('app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/detail/tutorial-group-management-detail.component').then( + (m) => m.TutorialGroupManagementDetailComponent, + ), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.pages.tutorialGroupDetail.title', diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/create-tutorial-group/create-tutorial-group.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/create-tutorial-group/create-tutorial-group.component.ts index 8d08d128296f..71d51d5c1247 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/create-tutorial-group/create-tutorial-group.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/create-tutorial-group/create-tutorial-group.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { AlertService } from 'app/core/util/alert.service'; import { ActivatedRoute, Router } from '@angular/router'; import { TutorialGroupsService } from 'app/course/tutorial-groups/services/tutorial-groups.service'; @@ -11,24 +11,27 @@ import { TutorialGroupSchedule } from 'app/entities/tutorial-group/tutorial-grou import dayjs from 'dayjs/esm'; import { Course } from 'app/entities/course.model'; import { Subject } from 'rxjs'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { TutorialGroupFormComponent } from '../tutorial-group-form/tutorial-group-form.component'; @Component({ selector: 'jhi-create-tutorial-group', templateUrl: './create-tutorial-group.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [LoadingIndicatorContainerComponent, TranslateDirective, TutorialGroupFormComponent], }) export class CreateTutorialGroupComponent implements OnInit, OnDestroy { + private activatedRoute = inject(ActivatedRoute); + private router = inject(Router); + private tutorialGroupService = inject(TutorialGroupsService); + private alertService = inject(AlertService); + tutorialGroupToCreate: TutorialGroup = new TutorialGroup(); isLoading: boolean; course: Course; ngUnsubscribe = new Subject(); - constructor( - private activatedRoute: ActivatedRoute, - private router: Router, - private tutorialGroupService: TutorialGroupsService, - private alertService: AlertService, - ) {} ngOnInit(): void { this.activatedRoute.data.pipe(takeUntil(this.ngUnsubscribe)).subscribe(({ course }) => { diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/edit-tutorial-group/edit-tutorial-group.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/edit-tutorial-group/edit-tutorial-group.component.ts index 0d8d24df7b38..2be9e266f3a5 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/edit-tutorial-group/edit-tutorial-group.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/edit-tutorial-group/edit-tutorial-group.component.ts @@ -1,7 +1,7 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; -import { TutorialGroupFormData } from '../tutorial-group-form/tutorial-group-form.component'; +import { TutorialGroupFormComponent, TutorialGroupFormData } from '../tutorial-group-form/tutorial-group-form.component'; import { onError } from 'app/shared/util/global.utils'; import { Subject, combineLatest } from 'rxjs'; import { finalize, switchMap, take, takeUntil } from 'rxjs/operators'; @@ -11,13 +11,22 @@ import { AlertService } from 'app/core/util/alert.service'; import { TutorialGroupSchedule } from 'app/entities/tutorial-group/tutorial-group-schedule.model'; import dayjs from 'dayjs/esm'; import { Course } from 'app/entities/course.model'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-edit-tutorial-group', templateUrl: './edit-tutorial-group.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [LoadingIndicatorContainerComponent, TranslateDirective, TutorialGroupFormComponent], }) export class EditTutorialGroupComponent implements OnInit, OnDestroy { + private activatedRoute = inject(ActivatedRoute); + private router = inject(Router); + private tutorialGroupService = inject(TutorialGroupsService); + private alertService = inject(AlertService); + private cdr = inject(ChangeDetectorRef); + ngUnsubscribe = new Subject(); isLoading = false; @@ -27,14 +36,6 @@ export class EditTutorialGroupComponent implements OnInit, OnDestroy { tutorialGroupId: number; course: Course; - constructor( - private activatedRoute: ActivatedRoute, - private router: Router, - private tutorialGroupService: TutorialGroupsService, - private alertService: AlertService, - private cdr: ChangeDetectorRef, - ) {} - ngOnInit(): void { this.isLoading = true; combineLatest([this.activatedRoute.paramMap, this.activatedRoute.data]) diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/schedule-form/schedule-form.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/schedule-form/schedule-form.component.ts index 31e3b2bcc1c6..f81db6d68366 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/schedule-form/schedule-form.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/schedule-form/schedule-form.component.ts @@ -1,7 +1,7 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, inject } from '@angular/core'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { faCalendarAlt } from '@fortawesome/free-solid-svg-icons'; -import { NgbDateParserFormatter, NgbTimeAdapter } from '@ng-bootstrap/ng-bootstrap'; +import { NgbDateParserFormatter, NgbTimeAdapter, NgbTimepicker } from '@ng-bootstrap/ng-bootstrap'; import { weekDays } from 'app/course/tutorial-groups/shared/weekdays'; import { Course } from 'app/entities/course.model'; import * as _ from 'lodash-es'; @@ -9,6 +9,12 @@ import dayjs from 'dayjs/esm'; import { dayOfWeekZeroSundayToZeroMonday } from 'app/utils/date.utils'; import { NgbTimeStringAdapter } from 'app/course/tutorial-groups/shared/ngbTimeStringAdapter'; import { validTimeRange } from 'app/course/tutorial-groups/shared/timeRangeValidator'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { OwlDateTimeModule } from '@danielmoncada/angular-datetime-picker'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisDateRangePipe } from 'app/shared/pipes/artemis-date-range.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface ScheduleFormData { dayOfWeek?: number; @@ -25,8 +31,13 @@ export interface ScheduleFormData { styleUrls: ['./schedule-form.component.scss'], providers: [{ provide: NgbTimeAdapter, useClass: NgbTimeStringAdapter }], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [FormsModule, ReactiveFormsModule, TranslateDirective, NgbTimepicker, OwlDateTimeModule, FaIconComponent, ArtemisDatePipe, ArtemisDateRangePipe, ArtemisTranslatePipe], }) export class ScheduleFormComponent implements OnInit { + private fb = inject(FormBuilder); + formatter = inject(NgbDateParserFormatter); + cdr = inject(ChangeDetectorRef); + @Input() course: Course; @Input() parentFormGroup: FormGroup; formGroup: FormGroup; @@ -87,12 +98,6 @@ export class ScheduleFormComponent implements OnInit { return sessions; } - constructor( - private fb: FormBuilder, - public formatter: NgbDateParserFormatter, - public cdr: ChangeDetectorRef, - ) {} - ngOnInit(): void { if (this.course.tutorialGroupsConfiguration) { const { tutorialPeriodStartInclusive, tutorialPeriodEndInclusive } = this.course.tutorialGroupsConfiguration; diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/tutorial-group-form.component.html b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/tutorial-group-form.component.html index 881abff7acd5..b3edd62913e1 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/tutorial-group-form.component.html +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/tutorial-group-form.component.html @@ -163,7 +163,7 @@
- +
@if (showScheduledChangedWarning) { diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/tutorial-group-form.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/tutorial-group-form.component.ts index c4d619a8869d..7de8402ba2b0 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/tutorial-group-form.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/tutorial-group-form.component.ts @@ -1,5 +1,5 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; -import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, ViewChild, inject } from '@angular/core'; +import { FormBuilder, FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { Course, CourseGroup } from 'app/entities/course.model'; import { User } from 'app/core/user/user.model'; @@ -16,6 +16,10 @@ import { import { isEqual } from 'lodash-es'; import { TutorialGroupsService } from 'app/course/tutorial-groups/services/tutorial-groups.service'; import { faSave } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { MarkdownEditorMonacoComponent } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface TutorialGroupFormData { title?: string; @@ -40,8 +44,14 @@ export const titleRegex = new RegExp('^[a-zA-Z0-9]{1}[a-zA-Z0-9- ]{0,19}$'); selector: 'jhi-tutorial-group-form', templateUrl: './tutorial-group-form.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [FormsModule, ReactiveFormsModule, TranslateDirective, NgbTypeahead, MarkdownEditorMonacoComponent, ScheduleFormComponent, FaIconComponent, ArtemisTranslatePipe], }) export class TutorialGroupFormComponent implements OnInit, OnChanges, OnDestroy { + private fb = inject(FormBuilder); + private courseManagementService = inject(CourseManagementService); + private tutorialGroupService = inject(TutorialGroupsService); + private alertService = inject(AlertService); + @Input() formData: TutorialGroupFormData = { title: undefined, @@ -89,13 +99,6 @@ export class TutorialGroupFormComponent implements OnInit, OnChanges, OnDestroy ngUnsubscribe = new Subject(); - constructor( - private fb: FormBuilder, - private courseManagementService: CourseManagementService, - private tutorialGroupService: TutorialGroupsService, - private alertService: AlertService, - ) {} - get titleControl() { return this.form.get('title'); } diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/detail/tutorial-group-management-detail.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/detail/tutorial-group-management-detail.component.ts index 010ae59754e1..1c10cda81c6d 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/detail/tutorial-group-management-detail.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/detail/tutorial-group-management-detail.component.ts @@ -1,4 +1,5 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { TutorialGroupDetailComponent } from 'app/course/tutorial-groups/shared/tutorial-group-detail/tutorial-group-detail.component'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { onError } from 'app/shared/util/global.utils'; import { Subject, combineLatest, finalize, switchMap, take } from 'rxjs'; @@ -8,13 +9,22 @@ import { ActivatedRoute, Router } from '@angular/router'; import { HttpErrorResponse } from '@angular/common/http'; import { Course } from 'app/entities/course.model'; import { takeUntil } from 'rxjs/operators'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { TutorialGroupRowButtonsComponent } from '../tutorial-groups-management/tutorial-group-row-buttons/tutorial-group-row-buttons.component'; @Component({ selector: 'jhi-tutorial-group-management-detail', templateUrl: './tutorial-group-management-detail.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [LoadingIndicatorContainerComponent, TutorialGroupDetailComponent, TutorialGroupRowButtonsComponent], }) export class TutorialGroupManagementDetailComponent implements OnInit, OnDestroy { + private activatedRoute = inject(ActivatedRoute); + private router = inject(Router); + private tutorialGroupService = inject(TutorialGroupsService); + private alertService = inject(AlertService); + private cdr = inject(ChangeDetectorRef); + ngUnsubscribe = new Subject(); isLoading = false; @@ -23,14 +33,6 @@ export class TutorialGroupManagementDetailComponent implements OnInit, OnDestroy tutorialGroupId: number; isAtLeastInstructor = false; - constructor( - private activatedRoute: ActivatedRoute, - private router: Router, - private tutorialGroupService: TutorialGroupsService, - private alertService: AlertService, - private cdr: ChangeDetectorRef, - ) {} - ngOnInit(): void { this.isLoading = true; combineLatest([this.activatedRoute.paramMap, this.activatedRoute.data]) diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-group-row-buttons/tutorial-group-row-buttons.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-group-row-buttons/tutorial-group-row-buttons.component.ts index 143e1782d996..49c1724b10b5 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-group-row-buttons/tutorial-group-row-buttons.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-group-row-buttons/tutorial-group-row-buttons.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output, inject } from '@angular/core'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { faCalendarAlt, faTrash, faUsers, faWrench } from '@fortawesome/free-solid-svg-icons'; import { EMPTY, Subject, from } from 'rxjs'; @@ -9,13 +9,21 @@ import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { RegisteredStudentsComponent } from 'app/course/tutorial-groups/tutorial-groups-management/registered-students/registered-students.component'; import { TutorialGroupSessionsManagementComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-group-sessions/tutorial-group-sessions-management/tutorial-group-sessions-management.component'; import { catchError, takeUntil } from 'rxjs/operators'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { RouterLink } from '@angular/router'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; @Component({ selector: 'jhi-tutorial-group-row-buttons', templateUrl: './tutorial-group-row-buttons.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [FaIconComponent, TranslateDirective, RouterLink, DeleteButtonDirective], }) export class TutorialGroupRowButtonsComponent implements OnDestroy { + private tutorialGroupsService = inject(TutorialGroupsService); + private modalService = inject(NgbModal); + ngUnsubscribe = new Subject(); @Input() isAtLeastInstructor = false; @@ -34,10 +42,7 @@ export class TutorialGroupRowButtonsComponent implements OnDestroy { faTrash = faTrash; faCalendar = faCalendarAlt; - public constructor( - private tutorialGroupsService: TutorialGroupsService, - private modalService: NgbModal, - ) {} + public constructor() {} openSessionDialog(event: MouseEvent) { event.stopPropagation(); diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-course-information/tutorial-groups-course-information.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-course-information/tutorial-groups-course-information.component.ts index 18bb6955bd0d..7f9738d0b1ee 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-course-information/tutorial-groups-course-information.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-course-information/tutorial-groups-course-information.component.ts @@ -1,10 +1,14 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; +import { SidePanelComponent } from 'app/shared/side-panel/side-panel.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-tutorial-groups-course-information', templateUrl: './tutorial-groups-course-information.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [SidePanelComponent, TranslateDirective, ArtemisTranslatePipe], }) export class TutorialGroupsCourseInformationComponent { @Input() diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-export-button.component/tutorial-groups-export-button.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-export-button.component/tutorial-groups-export-button.component.ts index e8e5c16d4449..98413ced01f0 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-export-button.component/tutorial-groups-export-button.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-export-button.component/tutorial-groups-export-button.component.ts @@ -1,16 +1,23 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output, TemplateRef, ViewChild } from '@angular/core'; -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output, TemplateRef, ViewChild, inject } from '@angular/core'; +import { NgbDropdownButtonItem, NgbDropdownItem, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { EMPTY, Subject, from } from 'rxjs'; import { catchError, takeUntil } from 'rxjs/operators'; import { TutorialGroupsService } from 'app/course/tutorial-groups/services/tutorial-groups.service'; import { AlertService } from 'app/core/util/alert.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; @Component({ selector: 'jhi-tutorial-groups-export-button', templateUrl: './tutorial-groups-export-button.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [NgbDropdownButtonItem, NgbDropdownItem, TranslateDirective, FormsModule], }) export class TutorialGroupsExportButtonComponent implements OnDestroy { + private modalService = inject(NgbModal); + private tutorialGroupsService = inject(TutorialGroupsService); + private alertService = inject(AlertService); + ngUnsubscribe = new Subject(); @ViewChild('exportDialog') exportDialogRef: TemplateRef; @@ -37,12 +44,6 @@ export class TutorialGroupsExportButtonComponent implements OnDestroy { { value: 'Students', selected: false }, ]; - constructor( - private modalService: NgbModal, - private tutorialGroupsService: TutorialGroupsService, - private alertService: AlertService, - ) {} - openExportDialog(event: MouseEvent) { event.stopPropagation(); const modalRef: NgbModalRef = this.modalService.open(this.exportDialogRef, { diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-import-button/tutorial-groups-import-button.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-import-button/tutorial-groups-import-button.component.ts index c26904bcfccd..72d5cc30d44c 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-import-button/tutorial-groups-import-button.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-import-button/tutorial-groups-import-button.component.ts @@ -1,15 +1,19 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output, TemplateRef, ViewChild } from '@angular/core'; -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output, TemplateRef, ViewChild, inject } from '@angular/core'; +import { NgbDropdownButtonItem, NgbDropdownItem, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { TutorialGroupsRegistrationImportDialogComponent } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-import-dialog/tutorial-groups-registration-import-dialog.component'; import { EMPTY, Subject, from } from 'rxjs'; import { catchError, takeUntil } from 'rxjs/operators'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-tutorial-groups-import-button', templateUrl: './tutorial-groups-import-button.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [NgbDropdownButtonItem, NgbDropdownItem, TranslateDirective], }) export class TutorialGroupsImportButtonComponent implements OnDestroy { + private modalService = inject(NgbModal); + ngUnsubscribe = new Subject(); @ViewChild('warning') @@ -19,8 +23,6 @@ export class TutorialGroupsImportButtonComponent implements OnDestroy { @Output() importFinished: EventEmitter = new EventEmitter(); - constructor(private modalService: NgbModal) {} - openTutorialGroupImportDialog(event: MouseEvent) { event.stopPropagation(); const modalRef: NgbModalRef = this.modalService.open(TutorialGroupsRegistrationImportDialogComponent, { diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-import-dialog/tutorial-groups-registration-import-dialog.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-import-dialog/tutorial-groups-registration-import-dialog.component.ts index 2f48df4e9970..f8aa6f625e7a 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-import-dialog/tutorial-groups-registration-import-dialog.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-import-dialog/tutorial-groups-registration-import-dialog.component.ts @@ -1,4 +1,4 @@ -import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; import { faBan, faCheck, faCircleNotch, faFileImport, faSpinner } from '@fortawesome/free-solid-svg-icons'; import { TutorialGroupRegistrationImportDTO } from 'app/entities/tutorial-group/tutorial-group-import-dto.model'; import { cleanString } from 'app/shared/util/utils'; @@ -9,11 +9,14 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { Subject } from 'rxjs'; import { StudentDTO } from 'app/entities/student-dto.model'; import { HttpResponse } from '@angular/common/http'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; import { titleRegex } from 'app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/tutorial-group-form.component'; import { takeUntil } from 'rxjs/operators'; import { CsvDownloadService } from 'app/shared/util/CsvDownloadService'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; /** * Each row is a object with the structure @@ -42,8 +45,16 @@ type filterValues = 'all' | 'onlyImported' | 'onlyNotImported'; selector: 'jhi-tutorial-groups-import-dialog', templateUrl: './tutorial-groups-registration-import-dialog.component.html', styleUrls: ['./tutorial-groups-registration-import-dialog.component.scss'], + imports: [TranslateDirective, FaIconComponent, FormsModule, ReactiveFormsModule, ArtemisTranslatePipe], }) export class TutorialGroupsRegistrationImportDialogComponent implements OnInit, OnDestroy { + private fb = inject(FormBuilder); + private translateService = inject(TranslateService); + private activeModal = inject(NgbActiveModal); + private alertService = inject(AlertService); + private tutorialGroupService = inject(TutorialGroupsService); + private csvDownloadService = inject(CsvDownloadService); + ngUnsubscribe = new Subject(); @ViewChild('fileInput') fileInput: ElementRef; @@ -92,15 +103,6 @@ export class TutorialGroupsRegistrationImportDialogComponent implements OnInit, faFileImport = faFileImport; selectedFilter: filterValues = 'all'; - constructor( - private fb: FormBuilder, - private translateService: TranslateService, - private activeModal: NgbActiveModal, - private alertService: AlertService, - private tutorialGroupService: TutorialGroupsService, - private csvDownloadService: CsvDownloadService, - ) {} - ngOnDestroy(): void { this.ngUnsubscribe.next(); this.ngUnsubscribe.complete(); diff --git a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-management.component.ts b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-management.component.ts index 932eecba9484..1f6c0f0c3f11 100644 --- a/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-management.component.ts +++ b/src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/tutorial-groups-management/tutorial-groups-management.component.ts @@ -1,6 +1,8 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { TutorialGroupFreeDaysOverviewComponent } from 'app/course/tutorial-groups/shared/tutorial-group-free-days-overview/tutorial-group-free-days-overview.component'; +import { TutorialGroupsTableComponent } from 'app/course/tutorial-groups/shared/tutorial-groups-table/tutorial-groups-table.component'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { TutorialGroupsService } from 'app/course/tutorial-groups/services/tutorial-groups.service'; import { HttpErrorResponse } from '@angular/common/http'; import { Subject, combineLatest, finalize } from 'rxjs'; @@ -12,13 +14,46 @@ import { TutorialGroupFreePeriod } from 'app/entities/tutorial-group/tutorial-gr import { TutorialGroupsConfigurationService } from 'app/course/tutorial-groups/services/tutorial-groups-configuration.service'; import { takeUntil } from 'rxjs/operators'; import { TutorialGroupsConfiguration } from 'app/entities/tutorial-group/tutorial-groups-configuration.model'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { NgbDropdown, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { TutorialGroupsImportButtonComponent } from './tutorial-groups-import-button/tutorial-groups-import-button.component'; +import { TutorialGroupsExportButtonComponent } from './tutorial-groups-export-button.component/tutorial-groups-export-button.component'; +import { TutorialGroupRowButtonsComponent } from './tutorial-group-row-buttons/tutorial-group-row-buttons.component'; +import { TutorialGroupsCourseInformationComponent } from './tutorial-groups-course-information/tutorial-groups-course-information.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-tutorial-groups-management', templateUrl: './tutorial-groups-management.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + LoadingIndicatorContainerComponent, + NgbTooltip, + RouterLink, + FaIconComponent, + TranslateDirective, + NgbDropdown, + NgbDropdownToggle, + NgbDropdownMenu, + NgbDropdownItem, + TutorialGroupsImportButtonComponent, + TutorialGroupsExportButtonComponent, + TutorialGroupsTableComponent, + TutorialGroupRowButtonsComponent, + TutorialGroupsCourseInformationComponent, + TutorialGroupFreeDaysOverviewComponent, + ArtemisTranslatePipe, + ], }) export class TutorialGroupsManagementComponent implements OnInit, OnDestroy { + private tutorialGroupService = inject(TutorialGroupsService); + private activatedRoute = inject(ActivatedRoute); + private alertService = inject(AlertService); + private tutorialGroupsConfigurationService = inject(TutorialGroupsConfigurationService); + private cdr = inject(ChangeDetectorRef); + ngUnsubscribe = new Subject(); courseId: number; @@ -36,15 +71,6 @@ export class TutorialGroupsManagementComponent implements OnInit, OnDestroy { tutorialGroupFreeDays: TutorialGroupFreePeriod[] = []; - constructor( - private tutorialGroupService: TutorialGroupsService, - private router: Router, - private activatedRoute: ActivatedRoute, - private alertService: AlertService, - private tutorialGroupsConfigurationService: TutorialGroupsConfigurationService, - private cdr: ChangeDetectorRef, - ) {} - ngOnInit(): void { this.activatedRoute.data.pipe(takeUntil(this.ngUnsubscribe)).subscribe(({ course }) => { if (course) { diff --git a/src/main/webapp/app/detail-overview-list/components/boolean-detail/boolean-detail.component.ts b/src/main/webapp/app/detail-overview-list/components/boolean-detail/boolean-detail.component.ts index 4f4adffe1461..42c2eab9890b 100644 --- a/src/main/webapp/app/detail-overview-list/components/boolean-detail/boolean-detail.component.ts +++ b/src/main/webapp/app/detail-overview-list/components/boolean-detail/boolean-detail.component.ts @@ -1,13 +1,11 @@ import { Component, Input } from '@angular/core'; import type { BooleanDetail } from 'app/detail-overview-list/detail.model'; -import { NoDataComponent } from 'app/shared/no-data-component'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; @Component({ selector: 'jhi-boolean-detail', templateUrl: 'boolean-detail.component.html', - standalone: true, - imports: [NoDataComponent, ArtemisSharedComponentModule], + imports: [ArtemisSharedComponentModule], }) export class BooleanDetailComponent { @Input() detail: BooleanDetail; diff --git a/src/main/webapp/app/detail-overview-list/components/date-detail/date-detail.component.ts b/src/main/webapp/app/detail-overview-list/components/date-detail/date-detail.component.ts index cddb968cde85..ea6dc8a51126 100644 --- a/src/main/webapp/app/detail-overview-list/components/date-detail/date-detail.component.ts +++ b/src/main/webapp/app/detail-overview-list/components/date-detail/date-detail.component.ts @@ -6,7 +6,6 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; @Component({ selector: 'jhi-date-detail', templateUrl: 'date-detail.component.html', - standalone: true, imports: [NoDataComponent, ArtemisSharedModule], }) export class DateDetailComponent { diff --git a/src/main/webapp/app/detail-overview-list/components/link-detail/link-detail.component.ts b/src/main/webapp/app/detail-overview-list/components/link-detail/link-detail.component.ts index a0367d87c622..84c5faa0e0fd 100644 --- a/src/main/webapp/app/detail-overview-list/components/link-detail/link-detail.component.ts +++ b/src/main/webapp/app/detail-overview-list/components/link-detail/link-detail.component.ts @@ -6,7 +6,6 @@ import { RouterModule } from '@angular/router'; @Component({ selector: 'jhi-link-detail', templateUrl: 'link-detail.component.html', - standalone: true, imports: [NoDataComponent, RouterModule], }) export class LinkDetailComponent { diff --git a/src/main/webapp/app/detail-overview-list/components/programming-auxiliary-repository-buttons-detail/programming-auxiliary-repository-buttons-detail.component.ts b/src/main/webapp/app/detail-overview-list/components/programming-auxiliary-repository-buttons-detail/programming-auxiliary-repository-buttons-detail.component.ts index e44170601ac7..26cb40817d45 100644 --- a/src/main/webapp/app/detail-overview-list/components/programming-auxiliary-repository-buttons-detail/programming-auxiliary-repository-buttons-detail.component.ts +++ b/src/main/webapp/app/detail-overview-list/components/programming-auxiliary-repository-buttons-detail/programming-auxiliary-repository-buttons-detail.component.ts @@ -1,5 +1,4 @@ import { Component, Input } from '@angular/core'; -import { NoDataComponent } from 'app/shared/no-data-component'; import { RouterModule } from '@angular/router'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { ArtemisProgrammingExerciseActionsModule } from 'app/exercises/programming/shared/actions/programming-exercise-actions.module'; @@ -10,8 +9,7 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; @Component({ selector: 'jhi-programming-auxiliary-repository-buttons-detail', templateUrl: 'programming-auxiliary-repository-buttons-detail.component.html', - standalone: true, - imports: [NoDataComponent, RouterModule, ArtemisSharedComponentModule, ArtemisProgrammingExerciseActionsModule, ArtemisSharedModule], + imports: [RouterModule, ArtemisSharedComponentModule, ArtemisProgrammingExerciseActionsModule, ArtemisSharedModule], }) export class ProgrammingAuxiliaryRepositoryButtonsDetailComponent { @Input() detail: ProgrammingAuxiliaryRepositoryButtonsDetail; diff --git a/src/main/webapp/app/detail-overview-list/components/programming-diff-report-detail/programming-diff-report-detail.component.ts b/src/main/webapp/app/detail-overview-list/components/programming-diff-report-detail/programming-diff-report-detail.component.ts index 46999aa24a27..c059cbe34571 100644 --- a/src/main/webapp/app/detail-overview-list/components/programming-diff-report-detail/programming-diff-report-detail.component.ts +++ b/src/main/webapp/app/detail-overview-list/components/programming-diff-report-detail/programming-diff-report-detail.component.ts @@ -13,7 +13,6 @@ import { GitDiffLineStatComponent } from 'app/exercises/programming/git-diff-rep @Component({ selector: 'jhi-programming-diff-report-detail', templateUrl: 'programming-diff-report-detail.component.html', - standalone: true, imports: [ArtemisSharedModule, ArtemisSharedComponentModule, GitDiffLineStatComponent], }) export class ProgrammingDiffReportDetailComponent implements OnDestroy { diff --git a/src/main/webapp/app/detail-overview-list/components/programming-repository-buttons-detail/programming-repository-buttons-detail.component.ts b/src/main/webapp/app/detail-overview-list/components/programming-repository-buttons-detail/programming-repository-buttons-detail.component.ts index 21676685fed1..58528fe13578 100644 --- a/src/main/webapp/app/detail-overview-list/components/programming-repository-buttons-detail/programming-repository-buttons-detail.component.ts +++ b/src/main/webapp/app/detail-overview-list/components/programming-repository-buttons-detail/programming-repository-buttons-detail.component.ts @@ -8,7 +8,6 @@ import { ArtemisProgrammingExerciseActionsModule } from 'app/exercises/programmi @Component({ selector: 'jhi-programming-repository-buttons-detail', templateUrl: 'programming-repository-buttons-detail.component.html', - standalone: true, imports: [NoDataComponent, RouterModule, ArtemisSharedComponentModule, ArtemisProgrammingExerciseActionsModule], }) export class ProgrammingRepositoryButtonsDetailComponent { diff --git a/src/main/webapp/app/detail-overview-list/components/programming-test-status-detail/programming-test-status-detail.component.ts b/src/main/webapp/app/detail-overview-list/components/programming-test-status-detail/programming-test-status-detail.component.ts index 89a43fb9aee3..47667bf81352 100644 --- a/src/main/webapp/app/detail-overview-list/components/programming-test-status-detail/programming-test-status-detail.component.ts +++ b/src/main/webapp/app/detail-overview-list/components/programming-test-status-detail/programming-test-status-detail.component.ts @@ -10,7 +10,6 @@ import { ProgrammingExerciseParticipationType } from 'app/entities/programming/p @Component({ selector: 'jhi-programming-test-status-detail', templateUrl: 'programming-test-status-detail.component.html', - standalone: true, imports: [RouterModule, ArtemisProgrammingExerciseActionsModule, SubmissionResultStatusModule, ArtemisProgrammingExerciseStatusModule, TranslateDirective], }) export class ProgrammingTestStatusDetailComponent { diff --git a/src/main/webapp/app/detail-overview-list/components/text-detail/text-detail.component.ts b/src/main/webapp/app/detail-overview-list/components/text-detail/text-detail.component.ts index a2e56d418816..2e285aedd7f7 100644 --- a/src/main/webapp/app/detail-overview-list/components/text-detail/text-detail.component.ts +++ b/src/main/webapp/app/detail-overview-list/components/text-detail/text-detail.component.ts @@ -5,7 +5,6 @@ import { NoDataComponent } from 'app/shared/no-data-component'; @Component({ selector: 'jhi-text-detail', templateUrl: 'text-detail.component.html', - standalone: true, imports: [NoDataComponent], }) export class TextDetailComponent { diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts index 27eeca162243..f10239706aa0 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts @@ -11,6 +11,19 @@ import { UMLModel } from '@ls1intum/apollon'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { Subscription } from 'rxjs'; import { PROFILE_LOCALVC } from 'app/app.constants'; +import { DetailOverviewNavigationBarComponent } from '../shared/detail-overview-navigation-bar/detail-overview-navigation-bar.component'; +import { HelpIconComponent } from '../shared/components/help-icon.component'; +import { ProgrammingExerciseInstructionComponent } from '../exercises/programming/shared/instructions-render/programming-exercise-instruction.component'; +import { ProgrammingExerciseLifecycleComponent } from '../exercises/programming/shared/lifecycle/programming-exercise-lifecycle.component'; +import { DecimalPipe, NgStyle, NgTemplateOutlet } from '@angular/common'; +import { StructuredGradingInstructionsAssessmentLayoutComponent } from '../assessment/structured-grading-instructions-assessment-layout/structured-grading-instructions-assessment-layout.component'; +import { TranslateDirective } from '../shared/language/translate.directive'; +import { IrisEnabledComponent } from '../iris/settings/shared/iris-enabled.component'; +import { ModelingEditorComponent } from '../exercises/modeling/shared/modeling-editor.component'; +import { ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent } from '../exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component'; +import { ExerciseDetailDirective } from './exercise-detail.directive'; +import { NoDataComponent } from '../shared/no-data-component'; +import { ArtemisTranslatePipe } from '../shared/pipes/artemis-translate.pipe'; export interface DetailOverviewSection { headline: string; @@ -43,6 +56,23 @@ export enum DetailType { templateUrl: './detail-overview-list.component.html', styleUrls: ['./detail-overview-list.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [ + DetailOverviewNavigationBarComponent, + HelpIconComponent, + ProgrammingExerciseInstructionComponent, + ProgrammingExerciseLifecycleComponent, + NgTemplateOutlet, + StructuredGradingInstructionsAssessmentLayoutComponent, + TranslateDirective, + IrisEnabledComponent, + ModelingEditorComponent, + ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent, + NgStyle, + ExerciseDetailDirective, + NoDataComponent, + DecimalPipe, + ArtemisTranslatePipe, + ], }) export class DetailOverviewListComponent implements OnInit, OnDestroy { protected readonly isEmpty = isEmpty; diff --git a/src/main/webapp/app/detail-overview-list/detail.module.ts b/src/main/webapp/app/detail-overview-list/detail.module.ts index c661ae788647..cbc9acfd2aa7 100644 --- a/src/main/webapp/app/detail-overview-list/detail.module.ts +++ b/src/main/webapp/app/detail-overview-list/detail.module.ts @@ -33,8 +33,8 @@ import { NoDataComponent } from 'app/shared/no-data-component'; ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent, ExerciseDetailDirective, NoDataComponent, + DetailOverviewListComponent, ], - declarations: [DetailOverviewListComponent], exports: [DetailOverviewListComponent], }) export class DetailModule {} diff --git a/src/main/webapp/app/detail-overview-list/exercise-detail.directive.ts b/src/main/webapp/app/detail-overview-list/exercise-detail.directive.ts index 2bacb55c076b..f26902a73590 100644 --- a/src/main/webapp/app/detail-overview-list/exercise-detail.directive.ts +++ b/src/main/webapp/app/detail-overview-list/exercise-detail.directive.ts @@ -1,4 +1,4 @@ -import { ComponentRef, Directive, Input, OnDestroy, OnInit, Type, ViewContainerRef } from '@angular/core'; +import { ComponentRef, Directive, Input, OnDestroy, OnInit, Type, ViewContainerRef, inject } from '@angular/core'; import type { Detail, ShownDetail } from 'app/detail-overview-list/detail.model'; import { DetailType } from 'app/detail-overview-list/detail-overview-list.component'; import { TextDetailComponent } from 'app/detail-overview-list/components/text-detail/text-detail.component'; @@ -12,15 +12,14 @@ import { ProgrammingDiffReportDetailComponent } from 'app/detail-overview-list/c @Directive({ selector: '[jhiExerciseDetail]', - standalone: true, }) export class ExerciseDetailDirective implements OnInit, OnDestroy { + viewContainerRef = inject(ViewContainerRef); + @Input() detail: Detail; private componentRef: ComponentRef; - constructor(public viewContainerRef: ViewContainerRef) {} - ngOnInit() { if (!this.isShownDetail()) { return; diff --git a/src/main/webapp/app/entities/bonus.model.ts b/src/main/webapp/app/entities/bonus.model.ts index b40d156545ca..ea7b1cd4a55a 100644 --- a/src/main/webapp/app/entities/bonus.model.ts +++ b/src/main/webapp/app/entities/bonus.model.ts @@ -8,8 +8,6 @@ export class Bonus implements BaseEntity { public weight?: number; public sourceGradingScale?: GradingScale; public bonusToGradingScale?: GradingScale; - - constructor() {} } export enum BonusStrategy { @@ -41,6 +39,4 @@ export class BonusResult { public mostSeverePlagiarismVerdict?: PlagiarismVerdict; public achievedPresentationScore?: number; public presentationScoreThreshold?: number; - - constructor() {} } diff --git a/src/main/webapp/app/entities/competency.model.ts b/src/main/webapp/app/entities/competency.model.ts index c130b3a24a67..f6fa260f7876 100644 --- a/src/main/webapp/app/entities/competency.model.ts +++ b/src/main/webapp/app/entities/competency.model.ts @@ -188,8 +188,6 @@ export class CompetencyProgress { public progress?: number; public confidence?: number; public confidenceReason?: ConfidenceReason; - - constructor() {} } export class CourseCompetencyProgress { @@ -197,8 +195,6 @@ export class CourseCompetencyProgress { numberOfStudents?: number; numberOfMasteredStudents?: number; averageStudentScore?: number; - - constructor() {} } export class CompetencyRelation implements BaseEntity { @@ -242,8 +238,6 @@ export function dtoToCompetencyRelation(competencyRelationDTO: CompetencyRelatio export class CompetencyWithTailRelationDTO { competency?: CourseCompetency; tailRelations?: CompetencyRelationDTO[]; - - constructor() {} } export function getIcon(competencyTaxonomy?: CompetencyTaxonomy): IconProp { diff --git a/src/main/webapp/app/entities/competency/learning-path.model.ts b/src/main/webapp/app/entities/competency/learning-path.model.ts index 576afd4e75a5..e431d8c399eb 100644 --- a/src/main/webapp/app/entities/competency/learning-path.model.ts +++ b/src/main/webapp/app/entities/competency/learning-path.model.ts @@ -11,8 +11,6 @@ export class LearningPath implements BaseEntity { public user?: User; public course?: Course; public competencies?: CourseCompetency[]; - - constructor() {} } export class LearningPathInformationDTO { diff --git a/src/main/webapp/app/entities/complaint-response.model.ts b/src/main/webapp/app/entities/complaint-response.model.ts index 0dca177c0b1f..a2af4ad1d28d 100644 --- a/src/main/webapp/app/entities/complaint-response.model.ts +++ b/src/main/webapp/app/entities/complaint-response.model.ts @@ -14,6 +14,4 @@ export class ComplaintResponse implements BaseEntity { public isCurrentlyLocked?: boolean; // transient property that will be calculated on the server public lockEndDate?: dayjs.Dayjs; - - constructor() {} } diff --git a/src/main/webapp/app/entities/complaint.model.ts b/src/main/webapp/app/entities/complaint.model.ts index e8f4f79a7d18..2d21c7092ed2 100644 --- a/src/main/webapp/app/entities/complaint.model.ts +++ b/src/main/webapp/app/entities/complaint.model.ts @@ -21,6 +21,4 @@ export class Complaint implements BaseEntity { public team?: Team; public complaintType?: ComplaintType; public complaintResponse?: ComplaintResponse; - - constructor() {} } diff --git a/src/main/webapp/app/entities/course.model.ts b/src/main/webapp/app/entities/course.model.ts index f3084853431a..db224001c721 100644 --- a/src/main/webapp/app/entities/course.model.ts +++ b/src/main/webapp/app/entities/course.model.ts @@ -169,8 +169,6 @@ export class CourseForImportDTO { title?: string; shortName?: string; semester?: string; - - constructor() {} } export const enum CourseGroup { diff --git a/src/main/webapp/app/entities/example-submission.model.ts b/src/main/webapp/app/entities/example-submission.model.ts index 75bea8e597bb..d0f05067f8b4 100644 --- a/src/main/webapp/app/entities/example-submission.model.ts +++ b/src/main/webapp/app/entities/example-submission.model.ts @@ -11,8 +11,6 @@ export class ExampleSubmission implements BaseEntity { public submission?: Submission; public tutorParticipations?: TutorParticipation[]; public assessmentExplanation?: string; - - constructor() {} } export enum ExampleSubmissionMode { diff --git a/src/main/webapp/app/entities/lecture.model.ts b/src/main/webapp/app/entities/lecture.model.ts index d213ed53de1d..cfe447f755e9 100644 --- a/src/main/webapp/app/entities/lecture.model.ts +++ b/src/main/webapp/app/entities/lecture.model.ts @@ -23,6 +23,4 @@ export class Lecture implements BaseEntity { isAtLeastEditor?: boolean; isAtLeastInstructor?: boolean; ingested?: IngestionState; - - constructor() {} } diff --git a/src/main/webapp/app/entities/participation/tutor-participation.model.ts b/src/main/webapp/app/entities/participation/tutor-participation.model.ts index 234b49451458..99ce4666014f 100644 --- a/src/main/webapp/app/entities/participation/tutor-participation.model.ts +++ b/src/main/webapp/app/entities/participation/tutor-participation.model.ts @@ -17,6 +17,4 @@ export class TutorParticipation implements BaseEntity { public assessedExercise?: Exercise; public tutor?: User; public trainedExampleSubmissions?: ExampleSubmission[]; - - constructor() {} } diff --git a/src/main/webapp/app/entities/programming-exercise-git-diff-entry.model.ts b/src/main/webapp/app/entities/programming-exercise-git-diff-entry.model.ts index c06f8c7ea50c..2ee6c1d884da 100644 --- a/src/main/webapp/app/entities/programming-exercise-git-diff-entry.model.ts +++ b/src/main/webapp/app/entities/programming-exercise-git-diff-entry.model.ts @@ -9,6 +9,4 @@ export class ProgrammingExerciseGitDiffEntry implements BaseEntity { public startLine?: number; public previousLineCount?: number; public lineCount?: number; - - constructor() {} } diff --git a/src/main/webapp/app/entities/programming-exercise-git-diff-report.model.ts b/src/main/webapp/app/entities/programming-exercise-git-diff-report.model.ts index d688911d1ccd..ecce60142a47 100644 --- a/src/main/webapp/app/entities/programming-exercise-git-diff-report.model.ts +++ b/src/main/webapp/app/entities/programming-exercise-git-diff-report.model.ts @@ -13,6 +13,4 @@ export class ProgrammingExerciseGitDiffReport implements BaseEntity { public participationIdForRightCommit?: number; public templateRepositoryCommitHash?: string; public solutionRepositoryCommitHash?: string; - - constructor() {} } diff --git a/src/main/webapp/app/entities/quiz/course-management-statistics-model.ts b/src/main/webapp/app/entities/quiz/course-management-statistics-model.ts index 2d4a583c1837..154b4aa6e8ef 100644 --- a/src/main/webapp/app/entities/quiz/course-management-statistics-model.ts +++ b/src/main/webapp/app/entities/quiz/course-management-statistics-model.ts @@ -9,6 +9,4 @@ export class CourseManagementStatisticsModel { public averageScore: number; public exerciseType: ExerciseType; public categories?: ExerciseCategory[]; - - constructor() {} } diff --git a/src/main/webapp/app/entities/quiz/quiz-statistic-counter.model.ts b/src/main/webapp/app/entities/quiz/quiz-statistic-counter.model.ts index 4b2e0baa0475..1b9d0eae7060 100644 --- a/src/main/webapp/app/entities/quiz/quiz-statistic-counter.model.ts +++ b/src/main/webapp/app/entities/quiz/quiz-statistic-counter.model.ts @@ -4,6 +4,4 @@ export class QuizStatisticCounter implements BaseEntity { public id?: number; public ratedCounter?: number; public unRatedCounter?: number; - - constructor() {} } diff --git a/src/main/webapp/app/entities/tutorial-group/tutorial-group-registration.model.ts b/src/main/webapp/app/entities/tutorial-group/tutorial-group-registration.model.ts index 0ff00c9f2b8a..393964bb8341 100644 --- a/src/main/webapp/app/entities/tutorial-group/tutorial-group-registration.model.ts +++ b/src/main/webapp/app/entities/tutorial-group/tutorial-group-registration.model.ts @@ -12,6 +12,4 @@ export class TutorialGroupRegistration implements BaseEntity { public student?: User; public tutorialGroup?: TutorialGroup; public type?: TutorialGroupRegistrationType; - - constructor() {} } diff --git a/src/main/webapp/app/exam/exam-scores/exam-score-dtos.model.ts b/src/main/webapp/app/exam/exam-scores/exam-score-dtos.model.ts index a11b03282410..5afc37f0cbcc 100644 --- a/src/main/webapp/app/exam/exam-scores/exam-score-dtos.model.ts +++ b/src/main/webapp/app/exam/exam-scores/exam-score-dtos.model.ts @@ -12,8 +12,6 @@ export class ExamScoreDTO { public hasSecondCorrectionAndStarted: boolean; public exerciseGroups: ExerciseGroup[]; public studentResults: StudentResult[]; - - constructor() {} } export class ExerciseGroup { @@ -22,8 +20,6 @@ export class ExerciseGroup { public maxPoints: number; public numberOfParticipants: number; public containedExercises: ExerciseInfo[]; - - constructor() {} } export class ExerciseInfo { @@ -32,8 +28,6 @@ export class ExerciseInfo { public maxPoints: number; public numberOfParticipants: number; public exerciseType: string; - - constructor() {} } export class StudentResult { @@ -52,8 +46,6 @@ export class StudentResult { public gradeWithBonus?: BonusResult; public exerciseGroupIdToExerciseResult: { [key: number]: ExerciseResult }; public mostSeverePlagiarismVerdict?: PlagiarismVerdict; - - constructor() {} } export class StudentExamWithGradeDTO { @@ -72,8 +64,6 @@ export class ExerciseResult { public achievedScore?: number; public achievedPoints?: number; public hasNonEmptySubmission: boolean; - - constructor() {} } export class AggregatedExamResult { @@ -164,8 +154,6 @@ export class AggregatedExamResult { public standardGradeDeviationTotalInFirstCorrection?: number; public standardGradeDeviationNonEmptyInFirstCorrection?: number; public standardGradeDeviationSubmittedAndNonEmptyInFirstCorrection?: number; - - constructor() {} } export class AggregatedExerciseGroupResult { diff --git a/src/main/webapp/app/exam/exam-scores/exam-scores-average-scores-graph.component.ts b/src/main/webapp/app/exam/exam-scores/exam-scores-average-scores-graph.component.ts index a76a05026816..822cd14cc06b 100644 --- a/src/main/webapp/app/exam/exam-scores/exam-scores-average-scores-graph.component.ts +++ b/src/main/webapp/app/exam/exam-scores/exam-scores-average-scores-graph.component.ts @@ -1,6 +1,4 @@ import { Component, OnInit, inject, input } from '@angular/core'; -import { StatisticsService } from 'app/shared/statistics-graph/statistics.service'; -import { TranslateService } from '@ngx-translate/core'; import { GraphColors } from 'app/entities/statistics.model'; import { AggregatedExerciseGroupResult } from 'app/exam/exam-scores/exam-score-dtos.model'; import { LocaleConversionService } from 'app/shared/service/locale-conversion.service'; @@ -20,14 +18,11 @@ type NameToValueMap = { [name: string]: any }; @Component({ selector: 'jhi-exam-scores-average-scores-graph', templateUrl: './exam-scores-average-scores-graph.component.html', - standalone: true, imports: [TranslateDirective, BarChartModule, ArtemisSharedCommonModule], }) export class ExamScoresAverageScoresGraphComponent implements OnInit { private navigationUtilService = inject(ArtemisNavigationUtilService); private activatedRoute = inject(ActivatedRoute); - private service = inject(StatisticsService); - private translateService = inject(TranslateService); private localeConversionService = inject(LocaleConversionService); averageScores = input.required(); diff --git a/src/main/webapp/app/exam/exam-scores/exam-scores.component.ts b/src/main/webapp/app/exam/exam-scores/exam-scores.component.ts index 97bb7fb19d39..8a92155a2700 100644 --- a/src/main/webapp/app/exam/exam-scores/exam-scores.component.ts +++ b/src/main/webapp/app/exam/exam-scores/exam-scores.component.ts @@ -75,7 +75,6 @@ export enum MedianType { templateUrl: './exam-scores.component.html', changeDetection: ChangeDetectionStrategy.OnPush, styleUrls: ['./exam-scores.component.scss', '../../shared/chart/vertical-bar-chart.scss'], - standalone: true, imports: [RouterLink, ArtemisSharedComponentModule, ArtemisSharedCommonModule, ExamScoresAverageScoresGraphComponent, ArtemisParticipantScoresModule, ExportModule], }) export class ExamScoresComponent implements OnInit, OnDestroy { diff --git a/src/main/webapp/app/exam/exam-scores/exam-scores.route.ts b/src/main/webapp/app/exam/exam-scores/exam-scores.route.ts index c0b815477e42..ac35ee9c1370 100644 --- a/src/main/webapp/app/exam/exam-scores/exam-scores.route.ts +++ b/src/main/webapp/app/exam/exam-scores/exam-scores.route.ts @@ -1,12 +1,12 @@ import { Route, Routes } from '@angular/router'; -import { ExamScoresComponent } from 'app/exam/exam-scores/exam-scores.component'; + import { Authority } from 'app/shared/constants/authority.constants'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; export const examScoresRoute: Route[] = [ { path: ':examId/scores', - component: ExamScoresComponent, + loadComponent: () => import('app/exam/exam-scores/exam-scores.component').then((m) => m.ExamScoresComponent), }, ]; diff --git a/src/main/webapp/app/exam/manage/exam-exercise-update.service.ts b/src/main/webapp/app/exam/manage/exam-exercise-update.service.ts index 79b53329ac10..ec9530e1735e 100644 --- a/src/main/webapp/app/exam/manage/exam-exercise-update.service.ts +++ b/src/main/webapp/app/exam/manage/exam-exercise-update.service.ts @@ -14,8 +14,6 @@ export class ExamExerciseUpdateService { private examExerciseIdForNavigationSource = new BehaviorSubject(-1); currentExerciseIdForNavigation = this.examExerciseIdForNavigationSource.asObservable(); - constructor() {} - navigateToExamExercise(exerciseId: number) { this.examExerciseIdForNavigationSource.next(exerciseId); } diff --git a/src/main/webapp/app/exam/manage/exam-management-resolve.service.ts b/src/main/webapp/app/exam/manage/exam-management-resolve.service.ts index e33354d96359..525e29e024c3 100644 --- a/src/main/webapp/app/exam/manage/exam-management-resolve.service.ts +++ b/src/main/webapp/app/exam/manage/exam-management-resolve.service.ts @@ -3,7 +3,7 @@ import { Exam } from 'app/entities/exam/exam.model'; import { ExamManagementService } from 'app/exam/manage/exam-management.service'; import { ExerciseGroup } from 'app/entities/exercise-group.model'; import { ExerciseGroupService } from 'app/exam/manage/exercise-groups/exercise-group.service'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { Observable, filter, map, of } from 'rxjs'; import { HttpResponse } from '@angular/common/http'; @@ -14,7 +14,7 @@ import { catchError } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class CourseResolve implements Resolve { - constructor(private courseManagementService: CourseManagementService) {} + private courseManagementService = inject(CourseManagementService); resolve(route: ActivatedRouteSnapshot): Observable { const courseId = route.params['courseId']; @@ -32,7 +32,7 @@ export class CourseResolve implements Resolve { @Injectable({ providedIn: 'root' }) export class ExamResolve implements Resolve { - constructor(private examManagementService: ExamManagementService) {} + private examManagementService = inject(ExamManagementService); /** * Resolves the route by extracting the examId and returns the exam with that id if it exists @@ -64,7 +64,7 @@ export class ExamResolve implements Resolve { @Injectable({ providedIn: 'root' }) export class ExerciseGroupResolve implements Resolve { - constructor(private exerciseGroupService: ExerciseGroupService) {} + private exerciseGroupService = inject(ExerciseGroupService); /** * Resolves the route by extracting the exerciseGroupId and returns the exercise group with that id if it exists @@ -87,7 +87,7 @@ export class ExerciseGroupResolve implements Resolve { @Injectable({ providedIn: 'root' }) export class StudentExamResolve implements Resolve { - constructor(private studentExamService: StudentExamService) {} + private studentExamService = inject(StudentExamService); /** * Resolves the route by extracting the studentExamId and returns the student exam with that id if it exists diff --git a/src/main/webapp/app/exam/manage/exam-management.component.ts b/src/main/webapp/app/exam/manage/exam-management.component.ts index bd55ca990c1c..0bec4752d1c2 100644 --- a/src/main/webapp/app/exam/manage/exam-management.component.ts +++ b/src/main/webapp/app/exam/manage/exam-management.component.ts @@ -1,6 +1,6 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { Subject, Subscription } from 'rxjs'; import { ExamManagementService } from 'app/exam/manage/exam-management.service'; import { Exam } from 'app/entities/exam/exam.model'; @@ -17,13 +17,30 @@ import { faClipboard, faEye, faFileImport, faListAlt, faPlus, faSort, faThList, import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { ExamImportComponent } from 'app/exam/manage/exams/exam-import/exam-import.component'; import { DocumentationType } from 'app/shared/components/documentation-button/documentation-button.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { ExamStatusComponent } from './exam-status.component'; @Component({ selector: 'jhi-exam-management', templateUrl: './exam-management.component.html', styleUrls: ['./exam-management.component.scss'], + imports: [TranslateDirective, DocumentationButtonComponent, FaIconComponent, RouterLink, SortDirective, SortByDirective, ExamStatusComponent], }) export class ExamManagementComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private courseService = inject(CourseManagementService); + private examManagementService = inject(ExamManagementService); + private eventManager = inject(EventManager); + private accountService = inject(AccountService); + private alertService = inject(AlertService); + private sortService = inject(SortService); + private modalService = inject(NgbModal); + private router = inject(Router); + readonly documentationType: DocumentationType = 'Exams'; course: Course; @@ -47,17 +64,7 @@ export class ExamManagementComponent implements OnInit, OnDestroy { faClipboard = faClipboard; faThList = faThList; - constructor( - private route: ActivatedRoute, - private courseService: CourseManagementService, - private examManagementService: ExamManagementService, - private eventManager: EventManager, - private accountService: AccountService, - private alertService: AlertService, - private sortService: SortService, - private modalService: NgbModal, - private router: Router, - ) { + constructor() { this.predicate = 'id'; this.ascending = true; } diff --git a/src/main/webapp/app/exam/manage/exam-management.module.ts b/src/main/webapp/app/exam/manage/exam-management.module.ts index d3e3677195d2..1422935400c5 100644 --- a/src/main/webapp/app/exam/manage/exam-management.module.ts +++ b/src/main/webapp/app/exam/manage/exam-management.module.ts @@ -48,7 +48,7 @@ import { ArtemisExamModePickerModule } from 'app/exam/manage/exams/exam-mode-pic import { ExamImportComponent } from 'app/exam/manage/exams/exam-import/exam-import.component'; import { ArtemisHeaderExercisePageWithDetailsModule } from 'app/exercises/shared/exercise-headers/exercise-headers.module'; import { ExamExerciseImportComponent } from 'app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component'; -import { FeatureToggleModule } from 'app/shared/feature-toggle/feature-toggle.module'; + import { BonusComponent } from 'app/grading-system/bonus/bonus.component'; import { ArtemisModePickerModule } from 'app/exercises/shared/mode-picker/mode-picker.module'; import { StudentExamTimelineComponent } from './student-exams/student-exam-timeline/student-exam-timeline.component'; @@ -99,7 +99,6 @@ const ENTITY_STATES = [...examManagementState, ...examScoresState]; ArtemisExamModePickerModule, ArtemisHeaderExercisePageWithDetailsModule, BarChartModule, - FeatureToggleModule, ArtemisModePickerModule, StudentsUploadImagesModule, TitleChannelNameModule, @@ -113,8 +112,6 @@ const ENTITY_STATES = [...examManagementState, ...examScoresState]; SafeHtmlPipe, GradeStepBoundsPipe, BonusComponent, - ], - declarations: [ ExamManagementComponent, ExamUpdateComponent, ExamDetailComponent, diff --git a/src/main/webapp/app/exam/manage/exam-management.route.ts b/src/main/webapp/app/exam/manage/exam-management.route.ts index 16f0a8e2a5ca..6b8cd746e9ae 100644 --- a/src/main/webapp/app/exam/manage/exam-management.route.ts +++ b/src/main/webapp/app/exam/manage/exam-management.route.ts @@ -1,76 +1,36 @@ import { Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { ExamManagementComponent } from 'app/exam/manage/exam-management.component'; -import { ExamUpdateComponent } from 'app/exam/manage/exams/exam-update.component'; -import { ExamDetailComponent } from 'app/exam/manage/exams/exam-detail.component'; -import { ExerciseGroupsComponent } from 'app/exam/manage/exercise-groups/exercise-groups.component'; -import { ExerciseGroupUpdateComponent } from 'app/exam/manage/exercise-groups/exercise-group-update.component'; -import { ExamStudentsComponent } from 'app/exam/manage/students/exam-students.component'; -import { StudentExamsComponent } from 'app/exam/manage/student-exams/student-exams.component'; -import { StudentExamDetailComponent } from 'app/exam/manage/student-exams/student-exam-detail.component'; -import { ExamStudentsAttendanceCheckComponent } from 'app/exam/manage/students/verify-attendance-check/exam-students-attendance-check.component'; -import { TextExerciseUpdateComponent } from 'app/exercises/text/manage/text-exercise/text-exercise-update.component'; + import { TextExerciseResolver } from 'app/exercises/text/manage/text-exercise/text-exercise.route'; -import { FileUploadExerciseUpdateComponent } from 'app/exercises/file-upload/manage/file-upload-exercise-update.component'; -import { QuizExerciseUpdateComponent } from 'app/exercises/quiz/manage/quiz-exercise-update.component'; -import { ProgrammingExerciseUpdateComponent } from 'app/exercises/programming/manage/update/programming-exercise-update.component'; + import { ProgrammingExerciseResolve } from 'app/exercises/programming/manage/programming-exercise-management-routing.module'; -import { ModelingExerciseUpdateComponent } from 'app/exercises/modeling/manage/modeling-exercise-update.component'; -import { StudentExamSummaryComponent } from 'app/exam/manage/student-exams/student-exam-summary.component'; -import { AssessmentDashboardComponent } from 'app/course/dashboards/assessment-dashboard/assessment-dashboard.component'; -import { TestRunManagementComponent } from 'app/exam/manage/test-runs/test-run-management.component'; -import { ExamParticipationComponent } from 'app/exam/participate/exam-participation.component'; + import { PendingChangesGuard } from 'app/shared/guard/pending-changes.guard'; import { Authority } from 'app/shared/constants/authority.constants'; import { ExerciseAssessmentDashboardComponent } from 'app/exercises/shared/dashboards/tutor/exercise-assessment-dashboard.component'; import { ParticipationSubmissionComponent } from 'app/exercises/shared/participation-submission/participation-submission.component'; -import { FileUploadAssessmentComponent } from 'app/exercises/file-upload/assess/file-upload-assessment.component'; + import { ParticipationComponent } from 'app/exercises/shared/participation/participation.component'; import { ExerciseScoresComponent } from 'app/exercises/shared/exercise-scores/exercise-scores.component'; -import { ModelingAssessmentEditorComponent } from 'app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.component'; + import { CodeEditorTutorAssessmentContainerComponent } from 'app/exercises/programming/assess/code-editor-tutor-assessment-container.component'; import { exerciseTypes } from 'app/entities/exercise.model'; -import { FileUploadExerciseDetailComponent } from 'app/exercises/file-upload/manage/file-upload-exercise-detail.component'; -import { ModelingExerciseDetailComponent } from 'app/exercises/modeling/manage/modeling-exercise-detail.component'; -import { ProgrammingExerciseDetailComponent } from 'app/exercises/programming/manage/programming-exercise-detail.component'; -import { TextExerciseDetailComponent } from 'app/exercises/text/manage/text-exercise/text-exercise-detail.component'; -import { PlagiarismInspectorComponent } from 'app/exercises/shared/plagiarism/plagiarism-inspector/plagiarism-inspector.component'; -import { GradingSystemComponent } from 'app/grading-system/grading-system.component'; -import { ExampleSubmissionsComponent } from 'app/exercises/shared/example-submission/example-submissions.component'; -import { GradingKeyOverviewComponent } from 'app/grading-system/grading-key-overview/grading-key-overview.component'; + import { ExerciseStatisticsComponent } from 'app/exercises/shared/statistics/exercise-statistics.component'; -import { ProgrammingExerciseConfigureGradingComponent } from 'app/exercises/programming/manage/grading/programming-exercise-configure-grading.component'; -import { ExampleModelingSubmissionComponent } from 'app/exercises/modeling/manage/example-modeling/example-modeling-submission.component'; -import { QuizParticipationComponent } from 'app/exercises/quiz/participate/quiz-participation.component'; -import { QuizReEvaluateComponent } from 'app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate.component'; -import { QuizPointStatisticComponent } from 'app/exercises/quiz/manage/statistics/quiz-point-statistic/quiz-point-statistic.component'; -import { QuizStatisticComponent } from 'app/exercises/quiz/manage/statistics/quiz-statistic/quiz-statistic.component'; -import { MultipleChoiceQuestionStatisticComponent } from 'app/exercises/quiz/manage/statistics/multiple-choice-question-statistic/multiple-choice-question-statistic.component'; -import { DragAndDropQuestionStatisticComponent } from 'app/exercises/quiz/manage/statistics/drag-and-drop-question-statistic/drag-and-drop-question-statistic.component'; -import { ShortAnswerQuestionStatisticComponent } from 'app/exercises/quiz/manage/statistics/short-answer-question-statistic/short-answer-question-statistic.component'; + import { OrionExerciseAssessmentDashboardComponent } from 'app/orion/assessment/orion-exercise-assessment-dashboard.component'; import { OrionTutorAssessmentComponent } from 'app/orion/assessment/orion-tutor-assessment.component'; import { isOrion } from 'app/shared/orion/orion'; import { FileUploadExerciseManagementResolve } from 'app/exercises/file-upload/manage/file-upload-exercise-management-resolve.service'; import { ModelingExerciseResolver } from 'app/exercises/modeling/manage/modeling-exercise-resolver.service'; import { CourseResolve, ExamResolve, ExerciseGroupResolve, StudentExamResolve } from 'app/exam/manage/exam-management-resolve.service'; -import { BonusComponent } from 'app/grading-system/bonus/bonus.component'; -import { SuspiciousBehaviorComponent } from 'app/exam/manage/suspicious-behavior/suspicious-behavior.component'; -import { SuspiciousSessionsOverviewComponent } from 'app/exam/manage/suspicious-behavior/suspicious-sessions-overview/suspicious-sessions-overview.component'; -import { StudentExamTimelineComponent } from 'app/exam/manage/student-exams/student-exam-timeline/student-exam-timeline.component'; -import { QuizPoolComponent } from 'app/exercises/quiz/manage/quiz-pool.component'; -import { BuildPlanEditorComponent } from 'app/exercises/programming/manage/build-plan-editor.component'; -import { QuizExerciseDetailComponent } from 'app/exercises/quiz/manage/quiz-exercise-detail.component'; -import { RepositoryViewComponent } from 'app/localvc/repository-view/repository-view.component'; + import { LocalVCGuard } from 'app/localvc/localvc-guard.service'; -import { CommitHistoryComponent } from 'app/localvc/commit-history/commit-history.component'; -import { CommitDetailsViewComponent } from 'app/localvc/commit-details-view/commit-details-view.component'; -import { VcsRepositoryAccessLogViewComponent } from 'app/localvc/vcs-repository-access-log-view/vcs-repository-access-log-view.component'; export const examManagementRoute: Routes = [ { path: '', - component: ExamManagementComponent, + loadComponent: () => import('app/exam/manage/exam-management.component').then((m) => m.ExamManagementComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.examManagement.title', @@ -79,7 +39,7 @@ export const examManagementRoute: Routes = [ }, { path: 'new', - component: ExamUpdateComponent, + loadComponent: () => import('app/exam/manage/exams/exam-update.component').then((m) => m.ExamUpdateComponent), resolve: { exam: ExamResolve, course: CourseResolve, @@ -92,7 +52,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/edit', - component: ExamUpdateComponent, + loadComponent: () => import('app/exam/manage/exams/exam-update.component').then((m) => m.ExamUpdateComponent), resolve: { exam: ExamResolve, course: CourseResolve, @@ -105,7 +65,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId', - component: ExamDetailComponent, + loadComponent: () => import('app/exam/manage/exams/exam-detail.component').then((m) => m.ExamDetailComponent), resolve: { exam: ExamResolve, }, @@ -121,7 +81,7 @@ export const examManagementRoute: Routes = [ // Exam Import { path: 'import/:examId', - component: ExamUpdateComponent, + loadComponent: () => import('app/exam/manage/exams/exam-update.component').then((m) => m.ExamUpdateComponent), resolve: { exam: ExamResolve, course: CourseResolve, @@ -137,7 +97,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups', - component: ExerciseGroupsComponent, + loadComponent: () => import('app/exam/manage/exercise-groups/exercise-groups.component').then((m) => m.ExerciseGroupsComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.examManagement.title', @@ -146,7 +106,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/new', - component: ExerciseGroupUpdateComponent, + loadComponent: () => import('app/exam/manage/exercise-groups/exercise-group-update.component').then((m) => m.ExerciseGroupUpdateComponent), resolve: { exam: ExamResolve, exerciseGroup: ExerciseGroupResolve, @@ -159,7 +119,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/edit', - component: ExerciseGroupUpdateComponent, + loadComponent: () => import('app/exam/manage/exercise-groups/exercise-group-update.component').then((m) => m.ExerciseGroupUpdateComponent), resolve: { exam: ExamResolve, exerciseGroup: ExerciseGroupResolve, @@ -176,7 +136,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/students', - component: ExamStudentsComponent, + loadComponent: () => import('app/exam/manage/students/exam-students.component').then((m) => m.ExamStudentsComponent), resolve: { exam: ExamResolve, }, @@ -191,7 +151,8 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/students/verify-attendance', - component: ExamStudentsAttendanceCheckComponent, + loadComponent: () => + import('app/exam/manage/students/verify-attendance-check/exam-students-attendance-check.component').then((m) => m.ExamStudentsAttendanceCheckComponent), resolve: { exam: ExamResolve, }, @@ -203,7 +164,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/student-exams', - component: StudentExamsComponent, + loadComponent: () => import('app/exam/manage/student-exams/student-exams.component').then((m) => m.StudentExamsComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.examManagement.title', @@ -212,7 +173,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/grading-system', - component: GradingSystemComponent, + loadComponent: () => import('app/grading-system/grading-system.component').then((m) => m.GradingSystemComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.examManagement.gradingSystem', @@ -222,7 +183,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/bonus', - component: BonusComponent, + loadComponent: () => import('app/grading-system/bonus/bonus.component').then((m) => m.BonusComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.bonus.title', @@ -231,7 +192,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/suspicious-behavior', - component: SuspiciousBehaviorComponent, + loadComponent: () => import('app/exam/manage/suspicious-behavior/suspicious-behavior.component').then((m) => m.SuspiciousBehaviorComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], pageTitle: 'artemisApp.examManagement.suspiciousBehavior.title', @@ -240,7 +201,8 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/suspicious-behavior/suspicious-sessions', - component: SuspiciousSessionsOverviewComponent, + loadComponent: () => + import('app/exam/manage/suspicious-behavior/suspicious-sessions-overview/suspicious-sessions-overview.component').then((m) => m.SuspiciousSessionsOverviewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], pageTitle: 'artemisApp.examManagement.suspiciousBehavior.suspiciousSessions.title', @@ -249,7 +211,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/test-runs', - component: TestRunManagementComponent, + loadComponent: () => import('app/exam/manage/test-runs/test-run-management.component').then((m) => m.TestRunManagementComponent), resolve: { exam: ExamResolve, }, @@ -261,7 +223,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/test-runs/assess', - component: AssessmentDashboardComponent, + loadComponent: () => import('app/course/dashboards/assessment-dashboard/assessment-dashboard.component').then((m) => m.AssessmentDashboardComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.TA], pageTitle: 'artemisApp.examManagement.assessmentDashboard', @@ -270,7 +232,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/test-runs/:studentExamId', - component: StudentExamDetailComponent, + loadComponent: () => import('app/exam/manage/student-exams/student-exam-detail.component').then((m) => m.StudentExamDetailComponent), resolve: { studentExam: StudentExamResolve, }, @@ -282,7 +244,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/student-exams/:studentExamId', - component: StudentExamDetailComponent, + loadComponent: () => import('app/exam/manage/student-exams/student-exam-detail.component').then((m) => m.StudentExamDetailComponent), resolve: { studentExam: StudentExamResolve, }, @@ -294,7 +256,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/student-exams/:studentExamId/summary', - component: StudentExamSummaryComponent, + loadComponent: () => import('app/exam/manage/student-exams/student-exam-summary.component').then((m) => m.StudentExamSummaryComponent), resolve: { studentExam: StudentExamResolve, }, @@ -306,7 +268,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/student-exams/:studentExamId/summary/exercises/:exerciseId/repository/:participationId', - component: RepositoryViewComponent, + loadComponent: () => import('app/localvc/repository-view/repository-view.component').then((m) => m.RepositoryViewComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.repository.title', @@ -315,7 +277,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/student-exams/:studentExamId/summary/exercises/:exerciseId/repository/:participationId/commit-history', - component: CommitHistoryComponent, + loadComponent: () => import('app/localvc/commit-history/commit-history.component').then((m) => m.CommitHistoryComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.repository.commitHistory.title', @@ -324,7 +286,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/student-exams/:studentExamId/summary/exercises/:exerciseId/repository/:participationId/commit-history/:commitHash', - component: CommitDetailsViewComponent, + loadComponent: () => import('app/localvc/commit-details-view/commit-details-view.component').then((m) => m.CommitDetailsViewComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.repository.commitHistory.commitDetails.title', @@ -333,7 +295,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/student-exams/:studentExamId/exam-timeline', - component: StudentExamTimelineComponent, + loadComponent: () => import('app/exam/manage/student-exams/student-exam-timeline/student-exam-timeline.component').then((m) => m.StudentExamTimelineComponent), resolve: { studentExam: StudentExamResolve, }, @@ -345,7 +307,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/student-exams/:studentExamId/summary/overview/grading-key', - component: GradingKeyOverviewComponent, + loadComponent: () => import('app/grading-system/grading-key-overview/grading-key-overview.component').then((m) => m.GradingKeyOverviewComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.examManagement.title', @@ -354,7 +316,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/student-exams/:studentExamId/summary/overview/bonus-grading-key', - component: GradingKeyOverviewComponent, + loadComponent: () => import('app/grading-system/grading-key-overview/grading-key-overview.component').then((m) => m.GradingKeyOverviewComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.examManagement.title', @@ -364,7 +326,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/test-runs/:testRunId/conduction', - component: ExamParticipationComponent, + loadComponent: () => import('app/exam/participate/exam-participation.component').then((m) => m.ExamParticipationComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.exam.title', @@ -374,7 +336,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/test-runs/:studentExamId/summary', - component: StudentExamSummaryComponent, + loadComponent: () => import('app/exam/manage/student-exams/student-exam-summary.component').then((m) => m.StudentExamSummaryComponent), resolve: { studentExam: StudentExamResolve, }, @@ -387,7 +349,7 @@ export const examManagementRoute: Routes = [ // Create Modeling Exercise { path: ':examId/exercise-groups/:exerciseGroupId/modeling-exercises/new', - component: ModelingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/modeling/manage/modeling-exercise-update.component').then((m) => m.ModelingExerciseUpdateComponent), resolve: { modelingExercise: ModelingExerciseResolver, }, @@ -400,7 +362,7 @@ export const examManagementRoute: Routes = [ // Import Modeling Exercise { path: ':examId/exercise-groups/:exerciseGroupId/modeling-exercises/import/:exerciseId', - component: ModelingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/modeling/manage/modeling-exercise-update.component').then((m) => m.ModelingExerciseUpdateComponent), resolve: { modelingExercise: ModelingExerciseResolver, }, @@ -413,7 +375,7 @@ export const examManagementRoute: Routes = [ // Edit Modeling Exercise { path: ':examId/exercise-groups/:exerciseGroupId/modeling-exercises/:exerciseId/edit', - component: ModelingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/modeling/manage/modeling-exercise-update.component').then((m) => m.ModelingExerciseUpdateComponent), resolve: { modelingExercise: ModelingExerciseResolver, }, @@ -426,7 +388,7 @@ export const examManagementRoute: Routes = [ // Create Text Exercise { path: ':examId/exercise-groups/:exerciseGroupId/text-exercises/new', - component: TextExerciseUpdateComponent, + loadComponent: () => import('app/exercises/text/manage/text-exercise/text-exercise-update.component').then((m) => m.TextExerciseUpdateComponent), resolve: { textExercise: TextExerciseResolver, }, @@ -439,7 +401,7 @@ export const examManagementRoute: Routes = [ // Import Text Exercise { path: ':examId/exercise-groups/:exerciseGroupId/text-exercises/import/:exerciseId', - component: TextExerciseUpdateComponent, + loadComponent: () => import('app/exercises/text/manage/text-exercise/text-exercise-update.component').then((m) => m.TextExerciseUpdateComponent), resolve: { textExercise: TextExerciseResolver, }, @@ -452,7 +414,7 @@ export const examManagementRoute: Routes = [ // Edit Text Exercise { path: ':examId/exercise-groups/:exerciseGroupId/text-exercises/:exerciseId/edit', - component: TextExerciseUpdateComponent, + loadComponent: () => import('app/exercises/text/manage/text-exercise/text-exercise-update.component').then((m) => m.TextExerciseUpdateComponent), resolve: { textExercise: TextExerciseResolver, }, @@ -465,7 +427,7 @@ export const examManagementRoute: Routes = [ // Create File Upload Exercise { path: ':examId/exercise-groups/:exerciseGroupId/file-upload-exercises/new', - component: FileUploadExerciseUpdateComponent, + loadComponent: () => import('app/exercises/file-upload/manage/file-upload-exercise-update.component').then((m) => m.FileUploadExerciseUpdateComponent), resolve: { fileUploadExercise: FileUploadExerciseManagementResolve, }, @@ -478,7 +440,7 @@ export const examManagementRoute: Routes = [ // Edit File Upload Exercise { path: ':examId/exercise-groups/:exerciseGroupId/file-upload-exercises/:exerciseId/edit', - component: FileUploadExerciseUpdateComponent, + loadComponent: () => import('app/exercises/file-upload/manage/file-upload-exercise-update.component').then((m) => m.FileUploadExerciseUpdateComponent), resolve: { fileUploadExercise: FileUploadExerciseManagementResolve, }, @@ -491,7 +453,7 @@ export const examManagementRoute: Routes = [ // Quiz Pool Configuration { path: ':examId/quiz-pool', - component: QuizPoolComponent, + loadComponent: () => import('app/exercises/quiz/manage/quiz-pool.component').then((m) => m.QuizPoolComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -501,7 +463,7 @@ export const examManagementRoute: Routes = [ // Import File Upload Exercise { path: ':examId/exercise-groups/:exerciseGroupId/file-upload-exercises/import/:exerciseId', - component: FileUploadExerciseUpdateComponent, + loadComponent: () => import('app/exercises/file-upload/manage/file-upload-exercise-update.component').then((m) => m.FileUploadExerciseUpdateComponent), resolve: { fileUploadExercise: FileUploadExerciseManagementResolve, }, @@ -514,7 +476,7 @@ export const examManagementRoute: Routes = [ // Create Quiz Exercise { path: ':examId/exercise-groups/:exerciseGroupId/quiz-exercises/new', - component: QuizExerciseUpdateComponent, + loadComponent: () => import('app/exercises/quiz/manage/quiz-exercise-update.component').then((m) => m.QuizExerciseUpdateComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -524,7 +486,7 @@ export const examManagementRoute: Routes = [ // Import Quiz Exercise { path: ':examId/exercise-groups/:exerciseGroupId/quiz-exercises/import/:exerciseId', - component: QuizExerciseUpdateComponent, + loadComponent: () => import('app/exercises/quiz/manage/quiz-exercise-update.component').then((m) => m.QuizExerciseUpdateComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -534,7 +496,7 @@ export const examManagementRoute: Routes = [ // Edit Quiz Exercise { path: ':examId/exercise-groups/:exerciseGroupId/quiz-exercises/:exerciseId/edit', - component: QuizExerciseUpdateComponent, + loadComponent: () => import('app/exercises/quiz/manage/quiz-exercise-update.component').then((m) => m.QuizExerciseUpdateComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -544,7 +506,7 @@ export const examManagementRoute: Routes = [ // Create Programming Exercise { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/new', - component: ProgrammingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/programming/manage/update/programming-exercise-update.component').then((m) => m.ProgrammingExerciseUpdateComponent), resolve: { programmingExercise: ProgrammingExerciseResolve, }, @@ -557,7 +519,7 @@ export const examManagementRoute: Routes = [ // Import programming exercise { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/import/:exerciseId', - component: ProgrammingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/programming/manage/update/programming-exercise-update.component').then((m) => m.ProgrammingExerciseUpdateComponent), resolve: { programmingExercise: ProgrammingExerciseResolve, }, @@ -570,7 +532,7 @@ export const examManagementRoute: Routes = [ // Import programming exercise from file { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/import-from-file', - component: ProgrammingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/programming/manage/update/programming-exercise-update.component').then((m) => m.ProgrammingExerciseUpdateComponent), resolve: { programmingExercise: ProgrammingExerciseResolve, }, @@ -583,7 +545,7 @@ export const examManagementRoute: Routes = [ // Edit Programming Exercise { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/edit', - component: ProgrammingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/programming/manage/update/programming-exercise-update.component').then((m) => m.ProgrammingExerciseUpdateComponent), resolve: { programmingExercise: ProgrammingExerciseResolve, }, @@ -595,7 +557,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/text-exercises/:exerciseId', - component: TextExerciseDetailComponent, + loadComponent: () => import('app/exercises/text/manage/text-exercise/text-exercise-detail.component').then((m) => m.TextExerciseDetailComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.textExercise.home.title', @@ -604,7 +566,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/file-upload-exercises/:exerciseId', - component: FileUploadExerciseDetailComponent, + loadComponent: () => import('app/exercises/file-upload/manage/file-upload-exercise-detail.component').then((m) => m.FileUploadExerciseDetailComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.fileUploadExercise.home.title', @@ -613,7 +575,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/modeling-exercises/:exerciseId', - component: ModelingExerciseDetailComponent, + loadComponent: () => import('app/exercises/modeling/manage/modeling-exercise-detail.component').then((m) => m.ModelingExerciseDetailComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.modelingExercise.home.title', @@ -622,7 +584,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId', - component: ProgrammingExerciseDetailComponent, + loadComponent: () => import('app/exercises/programming/manage/programming-exercise-detail.component').then((m) => m.ProgrammingExerciseDetailComponent), resolve: { programmingExercise: ProgrammingExerciseResolve, }, @@ -634,7 +596,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/repository/:repositoryType', - component: RepositoryViewComponent, + loadComponent: () => import('app/localvc/repository-view/repository-view.component').then((m) => m.RepositoryViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.repository.title', @@ -643,7 +605,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/repository/:repositoryType/vcs-access-log', - component: VcsRepositoryAccessLogViewComponent, + loadComponent: () => import('app/localvc/vcs-repository-access-log-view/vcs-repository-access-log-view.component').then((m) => m.VcsRepositoryAccessLogViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], pageTitle: 'artemisApp.repository.title', @@ -652,7 +614,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/repository/:repositoryType/repo/:repositoryId', - component: RepositoryViewComponent, + loadComponent: () => import('app/localvc/repository-view/repository-view.component').then((m) => m.RepositoryViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.repository.title', @@ -661,7 +623,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/repository/:repositoryType/commit-history', - component: CommitHistoryComponent, + loadComponent: () => import('app/localvc/commit-history/commit-history.component').then((m) => m.CommitHistoryComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.repository.title', @@ -670,7 +632,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/repository/:repositoryType/commit-history/:commitHash', - component: CommitDetailsViewComponent, + loadComponent: () => import('app/localvc/commit-details-view/commit-details-view.component').then((m) => m.CommitDetailsViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.repository.title', @@ -679,7 +641,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/participations/:participationId/repository', - component: RepositoryViewComponent, + loadComponent: () => import('app/localvc/repository-view/repository-view.component').then((m) => m.RepositoryViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.repository.title', @@ -688,7 +650,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/participations/:participationId/repository/vcs-access-log', - component: VcsRepositoryAccessLogViewComponent, + loadComponent: () => import('app/localvc/vcs-repository-access-log-view/vcs-repository-access-log-view.component').then((m) => m.VcsRepositoryAccessLogViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], pageTitle: 'artemisApp.repository.title', @@ -697,7 +659,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/participations/:participationId/repository/commit-history', - component: CommitHistoryComponent, + loadComponent: () => import('app/localvc/commit-history/commit-history.component').then((m) => m.CommitHistoryComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.repository.title', @@ -706,7 +668,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/participations/:participationId/repository/commit-history/:commitHash', - component: CommitDetailsViewComponent, + loadComponent: () => import('app/localvc/commit-details-view/commit-details-view.component').then((m) => m.CommitDetailsViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.repository.title', @@ -715,7 +677,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/quiz-exercises/:exerciseId', - component: QuizExerciseDetailComponent, + loadComponent: () => import('app/exercises/quiz/manage/quiz-exercise-detail.component').then((m) => m.QuizExerciseDetailComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -724,7 +686,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/modeling-exercises/:exerciseId/plagiarism', - component: PlagiarismInspectorComponent, + loadComponent: () => import('app/exercises/shared/plagiarism/plagiarism-inspector/plagiarism-inspector.component').then((m) => m.PlagiarismInspectorComponent), resolve: { exercise: ModelingExerciseResolver, }, @@ -736,7 +698,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/text-exercises/:exerciseId/plagiarism', - component: PlagiarismInspectorComponent, + loadComponent: () => import('app/exercises/shared/plagiarism/plagiarism-inspector/plagiarism-inspector.component').then((m) => m.PlagiarismInspectorComponent), resolve: { exercise: TextExerciseResolver, }, @@ -748,7 +710,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/plagiarism', - component: PlagiarismInspectorComponent, + loadComponent: () => import('app/exercises/shared/plagiarism/plagiarism-inspector/plagiarism-inspector.component').then((m) => m.PlagiarismInspectorComponent), resolve: { exercise: ProgrammingExerciseResolve, }, @@ -760,7 +722,8 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/grading/:tab', - component: ProgrammingExerciseConfigureGradingComponent, + loadComponent: () => + import('app/exercises/programming/manage/grading/programming-exercise-configure-grading.component').then((m) => m.ProgrammingExerciseConfigureGradingComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.programmingExercise.home.title', @@ -769,7 +732,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/programming-exercises/:exerciseId/edit-build-plan', - component: BuildPlanEditorComponent, + loadComponent: () => import('app/exercises/programming/manage/build-plan-editor.component').then((m) => m.BuildPlanEditorComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.programmingExercise.buildPlanEditor', @@ -778,7 +741,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/quiz-exercises/:exerciseId/preview', - component: QuizParticipationComponent, + loadComponent: () => import('app/exercises/quiz/participate/quiz-participation.component').then((m) => m.QuizParticipationComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -788,7 +751,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/quiz-exercises/:exerciseId/solution', - component: QuizParticipationComponent, + loadComponent: () => import('app/exercises/quiz/participate/quiz-participation.component').then((m) => m.QuizParticipationComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -798,7 +761,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/quiz-exercises/:exerciseId/re-evaluate', - component: QuizReEvaluateComponent, + loadComponent: () => import('app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate.component').then((m) => m.QuizReEvaluateComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -807,7 +770,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/quiz-exercises/:exerciseId/quiz-point-statistic', - component: QuizPointStatisticComponent, + loadComponent: () => import('app/exercises/quiz/manage/statistics/quiz-point-statistic/quiz-point-statistic.component').then((m) => m.QuizPointStatisticComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.course.home.title', @@ -816,7 +779,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/quiz-exercises/:exerciseId/quiz-statistic', - component: QuizStatisticComponent, + loadComponent: () => import('app/exercises/quiz/manage/statistics/quiz-statistic/quiz-statistic.component').then((m) => m.QuizStatisticComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.course.home.title', @@ -825,7 +788,10 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/quiz-exercises/:exerciseId/mc-question-statistic/:questionId', - component: MultipleChoiceQuestionStatisticComponent, + loadComponent: () => + import('app/exercises/quiz/manage/statistics/multiple-choice-question-statistic/multiple-choice-question-statistic.component').then( + (m) => m.MultipleChoiceQuestionStatisticComponent, + ), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.course.home.title', @@ -834,7 +800,10 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/quiz-exercises/:exerciseId/dnd-question-statistic/:questionId', - component: DragAndDropQuestionStatisticComponent, + loadComponent: () => + import('app/exercises/quiz/manage/statistics/drag-and-drop-question-statistic/drag-and-drop-question-statistic.component').then( + (m) => m.DragAndDropQuestionStatisticComponent, + ), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.course.home.title', @@ -843,7 +812,10 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/quiz-exercises/:exerciseId/sa-question-statistic/:questionId', - component: ShortAnswerQuestionStatisticComponent, + loadComponent: () => + import('app/exercises/quiz/manage/statistics/short-answer-question-statistic/short-answer-question-statistic.component').then( + (m) => m.ShortAnswerQuestionStatisticComponent, + ), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.course.home.title', @@ -852,7 +824,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/assessment-dashboard', - component: AssessmentDashboardComponent, + loadComponent: () => import('app/course/dashboards/assessment-dashboard/assessment-dashboard.component').then((m) => m.AssessmentDashboardComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.examManagement.assessmentDashboard', @@ -923,7 +895,7 @@ export const examManagementRoute: Routes = [ }), { path: ':examId/exercise-groups/:exerciseGroupId/text-exercises/:exerciseId/example-submissions', - component: ExampleSubmissionsComponent, + loadComponent: () => import('app/exercises/shared/example-submission/example-submissions.component').then((m) => m.ExampleSubmissionsComponent), resolve: { exercise: TextExerciseResolver, }, @@ -947,7 +919,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/modeling-exercises/:exerciseId/example-submissions', - component: ExampleSubmissionsComponent, + loadComponent: () => import('app/exercises/shared/example-submission/example-submissions.component').then((m) => m.ExampleSubmissionsComponent), resolve: { exercise: ModelingExerciseResolver, }, @@ -959,7 +931,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/modeling-exercises/:exerciseId/example-submissions/:exampleSubmissionId', - component: ExampleModelingSubmissionComponent, + loadComponent: () => import('app/exercises/modeling/manage/example-modeling/example-modeling-submission.component').then((m) => m.ExampleModelingSubmissionComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.exampleSubmission.home.editor', @@ -968,7 +940,8 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/modeling-exercises/:exerciseId/submissions/:submissionId/assessment', - component: ModelingAssessmentEditorComponent, + loadComponent: () => + import('app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.component').then((m) => m.ModelingAssessmentEditorComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.apollonDiagram.detail.title', @@ -995,7 +968,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/file-upload-exercises/:exerciseId/submissions/:submissionId/assessment', - component: FileUploadAssessmentComponent, + loadComponent: () => import('app/exercises/file-upload/assess/file-upload-assessment.component').then((m) => m.FileUploadAssessmentComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.fileUploadExercise.home.title', @@ -1004,7 +977,7 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/file-upload-exercises/:exerciseId/submissions/:submissionId/assessments/:resultId', - component: FileUploadAssessmentComponent, + loadComponent: () => import('app/exercises/file-upload/assess/file-upload-assessment.component').then((m) => m.FileUploadAssessmentComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.fileUploadExercise.home.title', @@ -1013,7 +986,8 @@ export const examManagementRoute: Routes = [ }, { path: ':examId/exercise-groups/:exerciseGroupId/modeling-exercises/:exerciseId/submissions/:submissionId/assessments/:resultId', - component: ModelingAssessmentEditorComponent, + loadComponent: () => + import('app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.component').then((m) => m.ModelingAssessmentEditorComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], usePathForBreadcrumbs: true, diff --git a/src/main/webapp/app/exam/manage/exam-management.service.ts b/src/main/webapp/app/exam/manage/exam-management.service.ts index 24425d3a530e..3617e77917db 100644 --- a/src/main/webapp/app/exam/manage/exam-management.service.ts +++ b/src/main/webapp/app/exam/manage/exam-management.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ExamUserDTO } from 'app/entities/exam/exam-user-dto.model'; import { ExamUserAttendanceCheckDTO } from 'app/entities/exam/exam-users-attendance-check-dto.model'; import { filter, map, tap } from 'rxjs/operators'; @@ -28,15 +28,13 @@ type EntityArrayResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class ExamManagementService { + private http = inject(HttpClient); + private accountService = inject(AccountService); + private entityTitleService = inject(EntityTitleService); + public resourceUrl = 'api/courses'; public adminResourceUrl = 'api/admin/courses'; - constructor( - private http: HttpClient, - private accountService: AccountService, - private entityTitleService: EntityTitleService, - ) {} - /** * Create an exam on the server using a POST request. * @param courseId The course id. diff --git a/src/main/webapp/app/exam/manage/exam-status.component.ts b/src/main/webapp/app/exam/manage/exam-status.component.ts index fafa2f201137..f19f79041368 100644 --- a/src/main/webapp/app/exam/manage/exam-status.component.ts +++ b/src/main/webapp/app/exam/manage/exam-status.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, OnChanges, OnDestroy, OnInit, inject } from '@angular/core'; import { faArrowRight, faCheckCircle, faCircleExclamation, faDotCircle, faTimes, faTimesCircle } from '@fortawesome/free-solid-svg-icons'; import { Exam } from 'app/entities/exam/exam.model'; import { ExamChecklistService } from 'app/exam/manage/exams/exam-checklist-component/exam-checklist.service'; @@ -7,6 +7,12 @@ import dayjs from 'dayjs/esm'; import { round } from 'app/shared/util/utils'; import { Course } from 'app/entities/course.model'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; +import { NgClass } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { ArtemisDurationFromSecondsPipe } from 'app/shared/pipes/artemis-duration-from-seconds.pipe'; export enum ExamReviewState { UNSET = 'unset', @@ -26,8 +32,12 @@ export enum ExamConductionState { selector: 'jhi-exam-status', templateUrl: './exam-status.component.html', styleUrls: ['./exam-status.component.scss'], + imports: [NgClass, FaIconComponent, TranslateDirective, ArtemisDatePipe, ArtemisTranslatePipe, ArtemisDurationFromSecondsPipe], }) export class ExamStatusComponent implements OnChanges, OnInit, OnDestroy { + private examChecklistService = inject(ExamChecklistService); + private websocketService = inject(JhiWebsocketService); + @Input() public exam: Exam; @Input() @@ -68,11 +78,6 @@ export class ExamStatusComponent implements OnChanges, OnInit, OnDestroy { faDotCircle = faDotCircle; faCircleExclamation = faCircleExclamation; - constructor( - private examChecklistService: ExamChecklistService, - private websocketService: JhiWebsocketService, - ) {} - ngOnInit() { const submittedTopic = this.examChecklistService.getSubmittedTopic(this.exam); this.websocketService.subscribe(submittedTopic); diff --git a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-announcement-dialog/exam-live-announcement-create-button.component.ts b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-announcement-dialog/exam-live-announcement-create-button.component.ts index 826a85b0a83d..8433bcbc1f59 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-announcement-dialog/exam-live-announcement-create-button.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-announcement-dialog/exam-live-announcement-create-button.component.ts @@ -1,5 +1,5 @@ import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { faBullhorn } from '@fortawesome/free-solid-svg-icons'; import dayjs from 'dayjs/esm'; import { Subscription, from } from 'rxjs'; @@ -7,12 +7,18 @@ import { Subscription, from } from 'rxjs'; import { Exam } from 'app/entities/exam/exam.model'; import { AlertService } from 'app/core/util/alert.service'; import { ExamLiveAnnouncementCreateModalComponent } from 'app/exam/manage/exams/exam-checklist-component/exam-announcement-dialog/exam-live-announcement-create-modal.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-exam-live-announcement-create-button', templateUrl: './exam-live-announcement-create-button.component.html', + imports: [FaIconComponent, TranslateDirective], }) export class ExamLiveAnnouncementCreateButtonComponent implements OnInit, OnDestroy { + private modalService = inject(NgbModal); + alertService = inject(AlertService); + @Input() exam: Exam; faBullhorn = faBullhorn; @@ -22,11 +28,6 @@ export class ExamLiveAnnouncementCreateButtonComponent implements OnInit, OnDest private timeoutRef: any; private subscription: Subscription; - constructor( - private modalService: NgbModal, - public alertService: AlertService, - ) {} - ngOnInit() { this.checkAnnouncementCreationAllowed(); } diff --git a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-announcement-dialog/exam-live-announcement-create-modal.component.ts b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-announcement-dialog/exam-live-announcement-create-modal.component.ts index 371492f0bcfc..55f5b643f701 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-announcement-dialog/exam-live-announcement-create-modal.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-announcement-dialog/exam-live-announcement-create-modal.component.ts @@ -1,10 +1,11 @@ -import { Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { SafeHtml } from '@angular/platform-browser'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { ExamManagementService } from 'app/exam/manage/exam-management.service'; import { ExamLiveEventType, ExamWideAnnouncementEvent } from 'app/exam/participate/exam-participation-live-events.service'; import { faCheckCircle, faSpinner } from '@fortawesome/free-solid-svg-icons'; import { AccountService } from 'app/core/auth/account.service'; +import { ExamLiveEventComponent } from 'app/exam/shared/events/exam-live-event.component'; import dayjs from 'dayjs/esm'; import { BoldAction } from 'app/shared/monaco-editor/model/actions/bold.action'; import { ItalicAction } from 'app/shared/monaco-editor/model/actions/italic.action'; @@ -12,13 +13,22 @@ import { UnderlineAction } from 'app/shared/monaco-editor/model/actions/underlin import { CodeAction } from 'app/shared/monaco-editor/model/actions/code.action'; import { CodeBlockAction } from 'app/shared/monaco-editor/model/actions/code-block.action'; import { OrderedListAction } from 'app/shared/monaco-editor/model/actions/ordered-list.action'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { MarkdownEditorMonacoComponent } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-exam-live-announcement-create-modal', templateUrl: './exam-live-announcement-create-modal.component.html', styleUrls: ['./exam-live-announcement-create-modal.component.scss'], + imports: [FormsModule, TranslateDirective, MarkdownEditorMonacoComponent, ExamLiveEventComponent, FaIconComponent], }) export class ExamLiveAnnouncementCreateModalComponent { + private activeModal = inject(NgbActiveModal); + private examManagementService = inject(ExamManagementService); + private accountService = inject(AccountService); + actions = [new BoldAction(), new ItalicAction(), new UnderlineAction(), new CodeAction(), new CodeBlockAction(), new OrderedListAction(), new OrderedListAction()]; courseId: number; @@ -35,12 +45,6 @@ export class ExamLiveAnnouncementCreateModalComponent { faSpinner = faSpinner; faCheckCircle = faCheckCircle; - constructor( - private activeModal: NgbActiveModal, - private examManagementService: ExamManagementService, - private accountService: AccountService, - ) {} - submitAnnouncement() { this.status = 'submitting'; this.examManagementService.createAnnouncement(this.courseId, this.examId, this.textContent).subscribe({ diff --git a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-checklist-exercisegroup-table/exam-checklist-exercisegroup-table.component.ts b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-checklist-exercisegroup-table/exam-checklist-exercisegroup-table.component.ts index fcbd6ec73144..5b5bf049f4e6 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-checklist-exercisegroup-table/exam-checklist-exercisegroup-table.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-checklist-exercisegroup-table/exam-checklist-exercisegroup-table.component.ts @@ -3,11 +3,17 @@ import { ExerciseGroup } from 'app/entities/exercise-group.model'; import { ExerciseType, getIcon, getIconTooltip } from 'app/entities/exercise.model'; import { ExerciseGroupVariantColumn } from 'app/entities/exercise-group-variant-column.model'; import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NoDataComponent } from 'app/shared/no-data-component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-exam-checklist-exercisegroup-table', templateUrl: './exam-checklist-exercisegroup-table.component.html', styleUrls: ['./exam-checklist-exercisegroup-table.component.scss'], + imports: [TranslateDirective, NgbTooltip, FaIconComponent, NoDataComponent, ArtemisTranslatePipe], }) export class ExamChecklistExerciseGroupTableComponent implements OnChanges { @Input() quizExamMaxPoints: number; diff --git a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-checklist.component.ts b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-checklist.component.ts index f873b396b058..88e6412574a4 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-checklist.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-checklist.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, OnChanges, OnDestroy, OnInit, inject } from '@angular/core'; import { Exam } from 'app/entities/exam/exam.model'; import { ExamChecklist } from 'app/entities/exam/exam-checklist.model'; import { faChartBar, faEye, faListAlt, faThList, faUser, faWrench } from '@fortawesome/free-solid-svg-icons'; @@ -11,12 +11,40 @@ import dayjs from 'dayjs/esm'; import { StudentExamService } from 'app/exam/manage/student-exams/student-exam.service'; import { Subject, Subscription } from 'rxjs'; import { captureException } from '@sentry/angular'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ChecklistCheckComponent } from 'app/shared/components/checklist-check/checklist-check.component'; +import { ExamChecklistExerciseGroupTableComponent } from './exam-checklist-exercisegroup-table/exam-checklist-exercisegroup-table.component'; +import { RouterLink } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ProgressBarComponent } from 'app/shared/dashboards/tutor-participation-graph/progress-bar/progress-bar.component'; +import { ExamEditWorkingTimeComponent } from './exam-edit-workingtime-dialog/exam-edit-working-time.component'; +import { ExamLiveAnnouncementCreateButtonComponent } from './exam-announcement-dialog/exam-live-announcement-create-button.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-exam-checklist', templateUrl: './exam-checklist.component.html', + imports: [ + TranslateDirective, + ChecklistCheckComponent, + ExamChecklistExerciseGroupTableComponent, + RouterLink, + FaIconComponent, + ProgressBarComponent, + ExamEditWorkingTimeComponent, + ExamLiveAnnouncementCreateButtonComponent, + ArtemisDatePipe, + ArtemisTranslatePipe, + ], }) export class ExamChecklistComponent implements OnChanges, OnInit, OnDestroy { + private examChecklistService = inject(ExamChecklistService); + private websocketService = inject(JhiWebsocketService); + private examManagementService = inject(ExamManagementService); + private alertService = inject(AlertService); + private studentExamService = inject(StudentExamService); + @Input() exam: Exam; @Input() getExamRoutesByIdentifier: any; private longestWorkingTimeSub: Subscription | null = null; @@ -54,14 +82,6 @@ export class ExamChecklistComponent implements OnChanges, OnInit, OnDestroy { private dialogErrorSource = new Subject(); dialogError$ = this.dialogErrorSource.asObservable(); - constructor( - private examChecklistService: ExamChecklistService, - private websocketService: JhiWebsocketService, - private examManagementService: ExamManagementService, - private alertService: AlertService, - private studentExamService: StudentExamService, - ) {} - ngOnInit() { const submittedTopic = this.examChecklistService.getSubmittedTopic(this.exam); this.websocketService.subscribe(submittedTopic); diff --git a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-checklist.service.ts b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-checklist.service.ts index ac6133a43d76..b71d5b8d3c58 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-checklist.service.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-checklist.service.ts @@ -1,5 +1,5 @@ import { HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ExamChecklist } from 'app/entities/exam/exam-checklist.model'; import { Exam } from 'app/entities/exam/exam.model'; import { ExamManagementService } from 'app/exam/manage/exam-management.service'; @@ -8,7 +8,7 @@ import { filter, map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class ExamChecklistService { - constructor(private examService: ExamManagementService) {} + private examService = inject(ExamManagementService); /** * indicates whether all student exams are generated diff --git a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-edit-workingtime-dialog/exam-edit-working-time-dialog.component.ts b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-edit-workingtime-dialog/exam-edit-working-time-dialog.component.ts index a1bb4e17c565..2c010341ab59 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-edit-workingtime-dialog/exam-edit-working-time-dialog.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-edit-workingtime-dialog/exam-edit-working-time-dialog.component.ts @@ -1,17 +1,27 @@ import { HttpResponse } from '@angular/common/http'; -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { faBan, faCheck, faSpinner } from '@fortawesome/free-solid-svg-icons'; import { Exam } from 'app/entities/exam/exam.model'; import { ExamManagementService } from 'app/exam/manage/exam-management.service'; import { examWorkingTime } from 'app/exam/participate/exam.utils'; +import { FormsModule } from '@angular/forms'; +import { WorkingTimeChangeComponent } from 'app/exam/shared/working-time-change/working-time-change.component'; +import { WorkingTimeControlComponent } from 'app/exam/shared/working-time-control/working-time-control.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ConfirmEntityNameComponent } from 'app/shared/confirm-entity-name/confirm-entity-name.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-edit-working-time-dialog', templateUrl: './exam-edit-working-time-dialog.component.html', + imports: [FormsModule, TranslateDirective, WorkingTimeControlComponent, WorkingTimeChangeComponent, ConfirmEntityNameComponent, FaIconComponent], }) export class ExamEditWorkingTimeDialogComponent { + private activeModal = inject(NgbActiveModal); + private examManagementService = inject(ExamManagementService); + @Input() exam: Exam; @Output() examChange = new EventEmitter(); @@ -32,11 +42,6 @@ export class ExamEditWorkingTimeDialogComponent { return this.oldWorkingTime ? this.oldWorkingTime + this.workingTimeSeconds : undefined; } - constructor( - private activeModal: NgbActiveModal, - private examManagementService: ExamManagementService, - ) {} - clear(): void { this.activeModal.close(); } diff --git a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-edit-workingtime-dialog/exam-edit-working-time.component.ts b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-edit-workingtime-dialog/exam-edit-working-time.component.ts index 4024634666c9..fa54b2b2c421 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-edit-workingtime-dialog/exam-edit-working-time.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-checklist-component/exam-edit-workingtime-dialog/exam-edit-working-time.component.ts @@ -1,5 +1,5 @@ import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; -import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, inject } from '@angular/core'; import { faHourglassHalf } from '@fortawesome/free-solid-svg-icons'; import dayjs from 'dayjs/esm'; import { Subscription, from } from 'rxjs'; @@ -7,12 +7,18 @@ import { Subscription, from } from 'rxjs'; import { Exam } from 'app/entities/exam/exam.model'; import { AlertService } from 'app/core/util/alert.service'; import { ExamEditWorkingTimeDialogComponent } from './exam-edit-working-time-dialog.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-exam-edit-working-time', templateUrl: './exam-edit-working-time.component.html', + imports: [FaIconComponent, TranslateDirective], }) export class ExamEditWorkingTimeComponent implements OnInit, OnDestroy { + private modalService = inject(NgbModal); + alertService = inject(AlertService); + @Input() exam: Exam; @Output() examChange = new EventEmitter(); @@ -23,11 +29,6 @@ export class ExamEditWorkingTimeComponent implements OnInit, OnDestroy { private timeoutRef: any; private subscription: Subscription; - constructor( - private modalService: NgbModal, - public alertService: AlertService, - ) {} - ngOnInit() { this.checkWorkingTimeChangeAllowed(); } diff --git a/src/main/webapp/app/exam/manage/exams/exam-detail.component.ts b/src/main/webapp/app/exam/manage/exams/exam-detail.component.ts index c0f4130e83c1..cbf58cbb97b2 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-detail.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-detail.component.ts @@ -1,5 +1,5 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { SafeHtml } from '@angular/platform-browser'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { Observable, Subject, map } from 'rxjs'; @@ -18,12 +18,28 @@ import { DetailOverviewSection, DetailType } from 'app/detail-overview-list/deta import { ArtemisDurationFromSecondsPipe } from 'app/shared/pipes/artemis-duration-from-seconds.pipe'; import { scrollToTopOfPage } from 'app/shared/util/utils'; import { ExerciseType } from 'app/entities/exercise.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { CourseExamArchiveButtonComponent } from 'app/shared/components/course-exam-archive-button/course-exam-archive-button.component'; +import { ExamChecklistComponent } from './exam-checklist-component/exam-checklist.component'; +import { DetailOverviewListComponent } from 'app/detail-overview-list/detail-overview-list.component'; @Component({ selector: 'jhi-exam-detail', templateUrl: './exam-detail.component.html', + imports: [TranslateDirective, RouterLink, FaIconComponent, DeleteButtonDirective, CourseExamArchiveButtonComponent, ExamChecklistComponent, DetailOverviewListComponent], }) export class ExamDetailComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private artemisMarkdown = inject(ArtemisMarkdownService); + private accountService = inject(AccountService); + private examManagementService = inject(ExamManagementService); + private router = inject(Router); + private alertService = inject(AlertService); + private gradingSystemService = inject(GradingSystemService); + private artemisDurationFromSecondsPipe = inject(ArtemisDurationFromSecondsPipe); + exam: Exam; formattedStartText?: SafeHtml; formattedConfirmationStartText?: SafeHtml; @@ -53,17 +69,6 @@ export class ExamDetailComponent implements OnInit, OnDestroy { examDetailSections: DetailOverviewSection[]; - constructor( - private route: ActivatedRoute, - private artemisMarkdown: ArtemisMarkdownService, - private accountService: AccountService, - private examManagementService: ExamManagementService, - private router: Router, - private alertService: AlertService, - private gradingSystemService: GradingSystemService, - private artemisDurationFromSecondsPipe: ArtemisDurationFromSecondsPipe, - ) {} - /** * Initialize the exam */ diff --git a/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts b/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts index 9739343cb687..02cf547cfff6 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts @@ -4,11 +4,18 @@ import { faCheckDouble, faFont } from '@fortawesome/free-solid-svg-icons'; import { Exercise, ExerciseType, getIcon } from 'app/entities/exercise.model'; import { ExerciseGroup } from 'app/entities/exercise-group.model'; import { EXERCISE_TITLE_NAME_REGEX, SHORT_NAME_PATTERN } from 'app/shared/constants/input.constants'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { FormsModule } from '@angular/forms'; +import { NgClass } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { DifficultyBadgeComponent } from 'app/exercises/shared/exercise-headers/difficulty-badge.component'; @Component({ selector: 'jhi-exam-exercise-import', templateUrl: './exam-exercise-import.component.html', styleUrls: ['./exam-exercise-import.component.scss'], + imports: [TranslateDirective, HelpIconComponent, FormsModule, NgClass, FaIconComponent, DifficultyBadgeComponent], }) export class ExamExerciseImportComponent implements OnInit { @Input() exam: Exam; @@ -41,8 +48,6 @@ export class ExamExerciseImportComponent implements OnInit { getExerciseIcon = getIcon; - constructor() {} - ngOnInit(): void { this.initializeSelectedExercisesAndContainsProgrammingExercisesMaps(); // If the exam is imported into the same course, the title + shortName of Programming Exercises must be changed diff --git a/src/main/webapp/app/exam/manage/exams/exam-import/exam-import-paging.service.ts b/src/main/webapp/app/exam/manage/exams/exam-import/exam-import-paging.service.ts index ca9bcbf3f1fc..6ab2aabd2d7f 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-import/exam-import-paging.service.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-import/exam-import-paging.service.ts @@ -1,5 +1,5 @@ import { HttpClient, HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { Exam } from 'app/entities/exam/exam.model'; import { PagingService } from 'app/exercises/shared/manage/paging.service'; import { SearchResult, SearchTermPageableSearch } from 'app/shared/table/pageable-table'; @@ -10,9 +10,11 @@ type EntityResponseType = SearchResult; @Injectable({ providedIn: 'root' }) export class ExamImportPagingService extends PagingService { + private http = inject(HttpClient); + private static readonly RESOURCE_URL = 'api/exams'; - constructor(private http: HttpClient) { + constructor() { super(); } diff --git a/src/main/webapp/app/exam/manage/exams/exam-import/exam-import.component.ts b/src/main/webapp/app/exam/manage/exams/exam-import/exam-import.component.ts index f97c8c3d537b..d813eac2dd2b 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-import/exam-import.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-import/exam-import.component.ts @@ -1,22 +1,30 @@ import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; -import { Component, Input, ViewChild } from '@angular/core'; -import { Router } from '@angular/router'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { Component, Input, ViewChild, inject } from '@angular/core'; import { AlertService } from 'app/core/util/alert.service'; import { Exam } from 'app/entities/exam/exam.model'; import { ExerciseGroup } from 'app/entities/exercise-group.model'; import { ExamManagementService } from 'app/exam/manage/exam-management.service'; import { ExamExerciseImportComponent } from 'app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component'; -import { ExamImportPagingService } from 'app/exam/manage/exams/exam-import/exam-import-paging.service'; import { ImportComponent } from 'app/shared/import/import.component'; -import { SortService } from 'app/shared/service/sort.service'; import { onError } from 'app/shared/util/global.utils'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbHighlight, NgbPagination } from '@ng-bootstrap/ng-bootstrap'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { ExamImportPagingService } from 'app/exam/manage/exams/exam-import/exam-import-paging.service'; @Component({ selector: 'jhi-exam-import', templateUrl: './exam-import.component.html', + imports: [FormsModule, TranslateDirective, SortDirective, SortByDirective, FaIconComponent, NgbHighlight, ButtonComponent, NgbPagination, ExamExerciseImportComponent], }) export class ExamImportComponent extends ImportComponent { + private examManagementService = inject(ExamManagementService); + private alertService = inject(AlertService); + // boolean to indicate, if the import modal should include the exerciseGroup selection subsequently. @Input() subsequentExerciseGroupSelection: boolean; // Values to specify the target of the exercise group import @@ -30,15 +38,9 @@ export class ExamImportComponent extends ImportComponent { isImportingExercises = false; isImportInSameCourse = false; - constructor( - router: Router, - sortService: SortService, - activeModal: NgbActiveModal, - pagingService: ExamImportPagingService, - private examManagementService: ExamManagementService, - private alertService: AlertService, - ) { - super(router, sortService, activeModal, pagingService); + constructor() { + const pagingService = inject(ExamImportPagingService); + super(pagingService); } /** diff --git a/src/main/webapp/app/exam/manage/exams/exam-mode-picker/exam-mode-picker.component.ts b/src/main/webapp/app/exam/manage/exams/exam-mode-picker/exam-mode-picker.component.ts index c022b55ec428..d3e4a19ee370 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-mode-picker/exam-mode-picker.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-mode-picker/exam-mode-picker.component.ts @@ -1,10 +1,13 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { Exam } from 'app/entities/exam/exam.model'; +import { NgClass } from '@angular/common'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-exam-mode-picker', templateUrl: './exam-mode-picker.component.html', styleUrls: ['./exam-mode-picker.component.scss'], + imports: [NgClass, TranslateDirective], }) export class ExamModePickerComponent { @Input() exam: Exam; diff --git a/src/main/webapp/app/exam/manage/exams/exam-mode-picker/exam-mode-picker.module.ts b/src/main/webapp/app/exam/manage/exams/exam-mode-picker/exam-mode-picker.module.ts index 4fbbcc666a8c..50ab25c83469 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-mode-picker/exam-mode-picker.module.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-mode-picker/exam-mode-picker.module.ts @@ -4,8 +4,7 @@ import { ExamModePickerComponent } from 'app/exam/manage/exams/exam-mode-picker/ import { ArtemisSharedModule } from 'app/shared/shared.module'; @NgModule({ - imports: [ArtemisSharedModule], - declarations: [ExamModePickerComponent], + imports: [ArtemisSharedModule, ExamModePickerComponent], exports: [ExamModePickerComponent], }) export class ArtemisExamModePickerModule {} diff --git a/src/main/webapp/app/exam/manage/exams/exam-update.component.ts b/src/main/webapp/app/exam/manage/exams/exam-update.component.ts index 610798664c76..548d37ab5a33 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-update.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-update.component.ts @@ -1,10 +1,11 @@ +import { WorkingTimeChangeComponent } from 'app/exam/shared/working-time-change/working-time-change.component'; import dayjs from 'dayjs/esm'; import { omit } from 'lodash-es'; import { combineLatest, takeWhile } from 'rxjs'; import { map } from 'rxjs/operators'; -import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; +import { Component, OnDestroy, OnInit, TemplateRef, ViewChild, inject } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { faBan, faExclamationTriangle, faSave } from '@fortawesome/free-solid-svg-icons'; import { Exam } from 'app/entities/exam/exam.model'; import { ExamManagementService } from 'app/exam/manage/exam-management.service'; @@ -18,12 +19,48 @@ import { DocumentationType } from 'app/shared/components/documentation-button/do import { ConfirmAutofocusModalComponent } from 'app/shared/components/confirm-autofocus-modal.component'; import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; import { examWorkingTime, normalWorkingTime } from 'app/exam/participate/exam.utils'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { TitleChannelNameComponent } from 'app/shared/form/title-channel-name/title-channel-name.component'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { ExamModePickerComponent } from './exam-mode-picker/exam-mode-picker.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component'; +import { CustomMinDirective } from 'app/shared/validators/custom-min-validator.directive'; +import { CustomMaxDirective } from 'app/shared/validators/custom-max-validator.directive'; +import { MarkdownEditorMonacoComponent } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; @Component({ selector: 'jhi-exam-update', templateUrl: './exam-update.component.html', + imports: [ + FormsModule, + TranslateDirective, + DocumentationButtonComponent, + TitleChannelNameComponent, + HelpIconComponent, + ExamModePickerComponent, + NgbTooltip, + FaIconComponent, + WorkingTimeChangeComponent, + FormDateTimePickerComponent, + CustomMinDirective, + CustomMaxDirective, + ExamExerciseImportComponent, + MarkdownEditorMonacoComponent, + ArtemisTranslatePipe, + ], }) export class ExamUpdateComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private examManagementService = inject(ExamManagementService); + private alertService = inject(AlertService); + private navigationUtilService = inject(ArtemisNavigationUtilService); + private modalService = inject(NgbModal); + private router = inject(Router); + private artemisTranslatePipe = inject(ArtemisTranslatePipe); + protected readonly faSave = faSave; protected readonly faBan = faBan; protected readonly faExclamationTriangle = faExclamationTriangle; @@ -46,16 +83,6 @@ export class ExamUpdateComponent implements OnInit, OnDestroy { @ViewChild('workingTimeConfirmationContent') public workingTimeConfirmationContent: TemplateRef; - constructor( - private route: ActivatedRoute, - private examManagementService: ExamManagementService, - private alertService: AlertService, - private navigationUtilService: ArtemisNavigationUtilService, - private modalService: NgbModal, - private router: Router, - private artemisTranslatePipe: ArtemisTranslatePipe, - ) {} - ngOnInit(): void { combineLatest([this.route.url, this.route.data]) .pipe(takeWhile(() => this.componentActive)) diff --git a/src/main/webapp/app/exam/manage/exercise-groups/exercise-group-update.component.ts b/src/main/webapp/app/exam/manage/exercise-groups/exercise-group-update.component.ts index 7acfb1fac6a6..d4a951a34a1f 100644 --- a/src/main/webapp/app/exam/manage/exercise-groups/exercise-group-update.component.ts +++ b/src/main/webapp/app/exam/manage/exercise-groups/exercise-group-update.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { AlertService } from 'app/core/util/alert.service'; @@ -8,12 +8,22 @@ import { ExerciseGroupService } from 'app/exam/manage/exercise-groups/exercise-g import { Exam } from 'app/entities/exam/exam.model'; import { onError } from 'app/shared/util/global.utils'; import { faBan, faSave } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { NgbAlert } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-exercise-group-update', templateUrl: './exercise-group-update.component.html', + imports: [TranslateDirective, FormsModule, NgbAlert, FaIconComponent], }) export class ExerciseGroupUpdateComponent implements OnInit { + private route = inject(ActivatedRoute); + private router = inject(Router); + private exerciseGroupService = inject(ExerciseGroupService); + private alertService = inject(AlertService); + readonly alertType = 'info'; courseId: number; exam: Exam; @@ -23,13 +33,6 @@ export class ExerciseGroupUpdateComponent implements OnInit { faBan = faBan; faSave = faSave; - constructor( - private route: ActivatedRoute, - private router: Router, - private exerciseGroupService: ExerciseGroupService, - private alertService: AlertService, - ) {} - /** * Initialize the courseId and exerciseGroup */ diff --git a/src/main/webapp/app/exam/manage/exercise-groups/exercise-group.service.ts b/src/main/webapp/app/exam/manage/exercise-groups/exercise-group.service.ts index 2481ccc98dbd..6d749e09796e 100644 --- a/src/main/webapp/app/exam/manage/exercise-groups/exercise-group.service.ts +++ b/src/main/webapp/app/exam/manage/exercise-groups/exercise-group.service.ts @@ -1,5 +1,4 @@ -import { Injectable } from '@angular/core'; -import { Router } from '@angular/router'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { ExerciseGroup } from 'app/entities/exercise-group.model'; @@ -9,12 +8,9 @@ type EntityArrayResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class ExerciseGroupService { - public resourceUrl = 'api/courses'; + private http = inject(HttpClient); - constructor( - private router: Router, - private http: HttpClient, - ) {} + public resourceUrl = 'api/courses'; /** * Create an exercise group on the server using a POST request. diff --git a/src/main/webapp/app/exam/manage/exercise-groups/exercise-groups.component.ts b/src/main/webapp/app/exam/manage/exercise-groups/exercise-groups.component.ts index 8fcac15d391b..63a43da95f72 100644 --- a/src/main/webapp/app/exam/manage/exercise-groups/exercise-groups.component.ts +++ b/src/main/webapp/app/exam/manage/exercise-groups/exercise-groups.component.ts @@ -1,5 +1,5 @@ -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { Component, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { Subject, forkJoin, of } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { ExerciseGroupService } from 'app/exam/manage/exercise-groups/exercise-group.service'; @@ -13,7 +13,6 @@ import { Course } from 'app/entities/course.model'; import { Exam } from 'app/entities/exam/exam.model'; import dayjs from 'dayjs/esm'; import { ExerciseService } from 'app/exercises/shared/exercise/exercise.service'; -import { ProgrammingExerciseParticipationType } from 'app/entities/programming/programming-exercise-participation.model'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { AlertService } from 'app/core/util/alert.service'; import { EventManager } from 'app/core/util/event-manager.service'; @@ -34,14 +33,48 @@ import { ExamImportComponent } from 'app/exam/manage/exams/exam-import/exam-impo import { ExerciseImportWrapperComponent } from 'app/exercises/shared/import/exercise-import-wrapper/exercise-import-wrapper.component'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { PROFILE_LOCALCI, PROFILE_LOCALVC } from 'app/app.constants'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { ProgrammingExerciseGroupCellComponent } from './programming-exercise-cell/programming-exercise-group-cell.component'; +import { QuizExerciseGroupCellComponent } from './quiz-exercise-cell/quiz-exercise-group-cell.component'; +import { ModelingExerciseGroupCellComponent } from './modeling-exercise-cell/modeling-exercise-group-cell.component'; +import { FileUploadExerciseGroupCellComponent } from './file-upload-exercise-cell/file-upload-exercise-group-cell.component'; +import { ExamExerciseRowButtonsComponent } from 'app/exercises/shared/exam-exercise-row-buttons/exam-exercise-row-buttons.component'; +import { LowerCasePipe } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-exercise-groups', templateUrl: './exercise-groups.component.html', styleUrls: ['./exercise-groups.component.scss'], + imports: [ + TranslateDirective, + FaIconComponent, + RouterLink, + HelpIconComponent, + DeleteButtonDirective, + ProgrammingExerciseGroupCellComponent, + QuizExerciseGroupCellComponent, + ModelingExerciseGroupCellComponent, + FileUploadExerciseGroupCellComponent, + ExamExerciseRowButtonsComponent, + LowerCasePipe, + ArtemisTranslatePipe, + ], }) export class ExerciseGroupsComponent implements OnInit { - participationType = ProgrammingExerciseParticipationType; + private route = inject(ActivatedRoute); + private exerciseGroupService = inject(ExerciseGroupService); + exerciseService = inject(ExerciseService); + private examManagementService = inject(ExamManagementService); + private eventManager = inject(EventManager); + private alertService = inject(AlertService); + private modalService = inject(NgbModal); + private router = inject(Router); + private profileService = inject(ProfileService); + courseId: number; course: Course; examId: number; @@ -69,18 +102,6 @@ export class ExerciseGroupsComponent implements OnInit { faAngleDown = faAngleDown; faFileImport = faFileImport; - constructor( - private route: ActivatedRoute, - private exerciseGroupService: ExerciseGroupService, - public exerciseService: ExerciseService, - private examManagementService: ExamManagementService, - private eventManager: EventManager, - private alertService: AlertService, - private modalService: NgbModal, - private router: Router, - private profileService: ProfileService, - ) {} - /** * Initialize the courseId and examId. Get all exercise groups for the exam. Setup dictionary for exercise groups which contain programming exercises. * See {@link setupExerciseGroupToExerciseTypesDict}. diff --git a/src/main/webapp/app/exam/manage/exercise-groups/modeling-exercise-cell/modeling-exercise-group-cell.component.ts b/src/main/webapp/app/exam/manage/exercise-groups/modeling-exercise-cell/modeling-exercise-group-cell.component.ts index 53966e6022df..327e5e041320 100644 --- a/src/main/webapp/app/exam/manage/exercise-groups/modeling-exercise-cell/modeling-exercise-group-cell.component.ts +++ b/src/main/webapp/app/exam/manage/exercise-groups/modeling-exercise-cell/modeling-exercise-group-cell.component.ts @@ -1,11 +1,13 @@ import { Component, Input } from '@angular/core'; import { Exercise, ExerciseType } from 'app/entities/exercise.model'; import { ModelingExercise } from 'app/entities/modeling-exercise.model'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-modeling-exercise-group-cell', templateUrl: './modeling-exercise-group-cell.component.html', styles: [':host{display: contents}'], + imports: [ArtemisTranslatePipe], }) export class ModelingExerciseGroupCellComponent { exerciseType = ExerciseType; diff --git a/src/main/webapp/app/exam/manage/exercise-groups/programming-exercise-cell/programming-exercise-group-cell.component.ts b/src/main/webapp/app/exam/manage/exercise-groups/programming-exercise-cell/programming-exercise-group-cell.component.ts index a171fc11d30e..95128f04f992 100644 --- a/src/main/webapp/app/exam/manage/exercise-groups/programming-exercise-cell/programming-exercise-group-cell.component.ts +++ b/src/main/webapp/app/exam/manage/exercise-groups/programming-exercise-cell/programming-exercise-group-cell.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { HttpResponse } from '@angular/common/http'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { ProgrammingExerciseParticipationType } from 'app/entities/programming/programming-exercise-participation.model'; @@ -10,13 +10,22 @@ import { downloadZipFileFromResponse } from 'app/shared/util/download.util'; import { AlertService } from 'app/core/util/alert.service'; import { faDownload } from '@fortawesome/free-solid-svg-icons'; import { PROFILE_LOCALVC, PROFILE_THEIA } from 'app/app.constants'; +import { RouterLink } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ProgrammingExerciseInstructorStatusComponent } from 'app/exercises/programming/manage/status/programming-exercise-instructor-status.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-programming-exercise-group-cell', templateUrl: './programming-exercise-group-cell.component.html', styles: [':host{display: contents}'], + imports: [RouterLink, FaIconComponent, ProgrammingExerciseInstructorStatusComponent, TranslateDirective], }) export class ProgrammingExerciseGroupCellComponent implements OnInit { + private profileService = inject(ProfileService); + private programmingExerciseService = inject(ProgrammingExerciseService); + private alertService = inject(AlertService); + participationType = ProgrammingExerciseParticipationType; programmingExercise: ProgrammingExercise; @@ -40,12 +49,6 @@ export class ProgrammingExerciseGroupCellComponent implements OnInit { faDownload = faDownload; - constructor( - private profileService: ProfileService, - private programmingExerciseService: ProgrammingExerciseService, - private alertService: AlertService, - ) {} - ngOnInit(): void { this.profileService.getProfileInfo().subscribe((profileInfo) => { this.localVCEnabled = profileInfo.activeProfiles.includes(PROFILE_LOCALVC); diff --git a/src/main/webapp/app/exam/manage/student-exams/student-exam-detail-table-row/student-exam-detail-table-row.component.ts b/src/main/webapp/app/exam/manage/student-exams/student-exam-detail-table-row/student-exam-detail-table-row.component.ts index fd2f3fe264ca..8bdaacb89d04 100644 --- a/src/main/webapp/app/exam/manage/student-exams/student-exam-detail-table-row/student-exam-detail-table-row.component.ts +++ b/src/main/webapp/app/exam/manage/student-exams/student-exam-detail-table-row/student-exam-detail-table-row.component.ts @@ -7,12 +7,16 @@ import { Course } from 'app/entities/course.model'; import { Result } from 'app/entities/result.model'; import { StudentExam } from 'app/entities/student-exam.model'; import { faFolderOpen } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { RouterLink } from '@angular/router'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ - /* eslint-disable-next-line @angular-eslint/component-selector */ selector: '[jhi-student-exam-detail-table-row]', templateUrl: './student-exam-detail-table-row.component.html', providers: [], + imports: [FaIconComponent, TranslateDirective, RouterLink, ArtemisTranslatePipe], }) export class StudentExamDetailTableRowComponent implements OnChanges { @Input() exercise: Exercise; diff --git a/src/main/webapp/app/exam/manage/student-exams/student-exam-detail.component.html b/src/main/webapp/app/exam/manage/student-exams/student-exam-detail.component.html index 7b825a7471e5..790a185740b4 100644 --- a/src/main/webapp/app/exam/manage/student-exams/student-exam-detail.component.html +++ b/src/main/webapp/app/exam/manage/student-exams/student-exam-detail.component.html @@ -70,7 +70,7 @@
: - +
}
diff --git a/src/main/webapp/app/exam/manage/student-exams/student-exam-detail.component.ts b/src/main/webapp/app/exam/manage/student-exams/student-exam-detail.component.ts index 8d8a79acccfb..1adc225e67ce 100644 --- a/src/main/webapp/app/exam/manage/student-exams/student-exam-detail.component.ts +++ b/src/main/webapp/app/exam/manage/student-exams/student-exam-detail.component.ts @@ -1,25 +1,50 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { StudentExam } from 'app/entities/student-exam.model'; import { StudentExamService } from 'app/exam/manage/student-exams/student-exam.service'; import { Course } from 'app/entities/course.model'; import { User } from 'app/core/user/user.model'; import { AlertService } from 'app/core/util/alert.service'; +import { TestExamWorkingTimeComponent } from 'app/exam/shared/testExam-workingTime/test-exam-working-time.component'; +import { WorkingTimeControlComponent } from 'app/exam/shared/working-time-control/working-time-control.component'; import dayjs from 'dayjs/esm'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { getLatestSubmissionResult, setLatestSubmissionResult } from 'app/entities/submission.model'; import { GradeType } from 'app/entities/grading-scale.model'; import { faSave } from '@fortawesome/free-solid-svg-icons'; import { Exercise } from 'app/entities/exercise.model'; import { StudentExamWithGradeDTO } from 'app/exam/exam-scores/exam-score-dtos.model'; import { combineLatest, takeWhile } from 'rxjs'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { StudentExamDetailTableRowComponent } from './student-exam-detail-table-row/student-exam-detail-table-row.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-student-exam-detail', templateUrl: './student-exam-detail.component.html', styleUrls: ['./student-exam-detail.component.scss'], + imports: [ + TranslateDirective, + FormsModule, + WorkingTimeControlComponent, + FaIconComponent, + TestExamWorkingTimeComponent, + NgbTooltip, + RouterLink, + StudentExamDetailTableRowComponent, + ArtemisDatePipe, + ArtemisTranslatePipe, + ], }) export class StudentExamDetailComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private studentExamService = inject(StudentExamService); + private alertService = inject(AlertService); + private modalService = inject(NgbModal); + examId: number; courseId: number; studentExam: StudentExam; @@ -47,13 +72,6 @@ export class StudentExamDetailComponent implements OnInit, OnDestroy { private componentActive = true; - constructor( - private route: ActivatedRoute, - private studentExamService: StudentExamService, - private alertService: AlertService, - private modalService: NgbModal, - ) {} - /** * Initialize the courseId and studentExam */ diff --git a/src/main/webapp/app/exam/manage/student-exams/student-exam-status/student-exam-status.component.ts b/src/main/webapp/app/exam/manage/student-exams/student-exam-status/student-exam-status.component.ts index 2793d9ec48c5..1ed4390a80d3 100644 --- a/src/main/webapp/app/exam/manage/student-exams/student-exam-status/student-exam-status.component.ts +++ b/src/main/webapp/app/exam/manage/student-exams/student-exam-status/student-exam-status.component.ts @@ -1,5 +1,9 @@ import { Component, Input } from '@angular/core'; import { faCheckCircle, faExclamationTriangle, faInfoCircle } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; /** * Status indicator for student exams @@ -8,6 +12,7 @@ import { faCheckCircle, faExclamationTriangle, faInfoCircle } from '@fortawesome @Component({ selector: 'jhi-student-exam-status', templateUrl: `./student-exam-status.component.html`, + imports: [FaIconComponent, TranslateDirective, NgbTooltip, ArtemisTranslatePipe], }) export class StudentExamStatusComponent { @Input() hasStudentsWithoutExam: boolean; diff --git a/src/main/webapp/app/exam/manage/student-exams/student-exam-summary.component.ts b/src/main/webapp/app/exam/manage/student-exams/student-exam-summary.component.ts index f6b73dac9994..db06641c336f 100644 --- a/src/main/webapp/app/exam/manage/student-exams/student-exam-summary.component.ts +++ b/src/main/webapp/app/exam/manage/student-exams/student-exam-summary.component.ts @@ -1,15 +1,17 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { StudentExam } from 'app/entities/student-exam.model'; +import { ExamResultSummaryComponent } from '../../participate/summary/exam-result-summary.component'; @Component({ selector: 'jhi-student-exam-summary', template: '', + imports: [ExamResultSummaryComponent], }) export class StudentExamSummaryComponent implements OnInit { - studentExam: StudentExam; + private route = inject(ActivatedRoute); - constructor(private route: ActivatedRoute) {} + studentExam: StudentExam; /** * Initialize the studentExam diff --git a/src/main/webapp/app/exam/manage/student-exams/student-exam-timeline/programming-exam-diff/programming-exercise-exam-diff.component.ts b/src/main/webapp/app/exam/manage/student-exams/student-exam-timeline/programming-exam-diff/programming-exercise-exam-diff.component.ts index c3979797994f..e7c8c01f3003 100644 --- a/src/main/webapp/app/exam/manage/student-exams/student-exam-timeline/programming-exam-diff/programming-exercise-exam-diff.component.ts +++ b/src/main/webapp/app/exam/manage/student-exams/student-exam-timeline/programming-exam-diff/programming-exercise-exam-diff.component.ts @@ -1,27 +1,37 @@ -import { ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output, signal } from '@angular/core'; +import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, inject, signal } from '@angular/core'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { ProgrammingSubmission } from 'app/entities/programming/programming-submission.model'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; import { ButtonSize } from 'app/shared/components/button.component'; import { GitDiffReportModalComponent } from 'app/exercises/programming/git-diff-report/git-diff-report-modal.component'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; -import { Exercise, IncludedInOverallScore } from 'app/entities/exercise.model'; +import { IncludedInOverallScore } from 'app/entities/exercise.model'; import { ExamSubmissionComponent } from 'app/exam/participate/exercises/exam-submission.component'; -import { Submission } from 'app/entities/submission.model'; import { ProgrammingExerciseStudentParticipation } from 'app/entities/participation/programming-exercise-student-participation.model'; import { faCodeCompare } from '@fortawesome/free-solid-svg-icons'; import { ProgrammingExerciseGitDiffReport } from 'app/entities/programming-exercise-git-diff-report.model'; import { ExamPageComponent } from 'app/exam/participate/exercises/exam-page.component'; import { Observable, Subject, Subscription, debounceTime, take } from 'rxjs'; import { CachedRepositoryFilesService } from 'app/exercises/programming/manage/services/cached-repository-files.service'; +import { IncludedInScoreBadgeComponent } from 'app/exercises/shared/exercise-headers/included-in-score-badge.component'; +import { CommitsInfoComponent } from 'app/exercises/programming/shared/commits-info/commits-info.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { GitDiffLineStatComponent } from 'app/exercises/programming/git-diff-report/git-diff-line-stat.component'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-programming-exam-diff', templateUrl: './programming-exercise-exam-diff.component.html', providers: [{ provide: ExamSubmissionComponent, useExisting: ProgrammingExerciseExamDiffComponent }], + imports: [IncludedInScoreBadgeComponent, CommitsInfoComponent, TranslateDirective, GitDiffLineStatComponent, NgbTooltip, ButtonComponent, ArtemisTranslatePipe], }) export class ProgrammingExerciseExamDiffComponent extends ExamPageComponent implements OnInit, OnDestroy { + private programmingExerciseService = inject(ProgrammingExerciseService); + private modalService = inject(NgbModal); + private cachedRepositoryFilesService = inject(CachedRepositoryFilesService); + @Input() exercise: ProgrammingExercise; @Input() previousSubmission: ProgrammingSubmission | undefined; @Input() currentSubmission: ProgrammingSubmission; @@ -30,6 +40,7 @@ export class ProgrammingExerciseExamDiffComponent extends ExamPageComponent impl @Input() cachedDiffReports: Map = new Map(); @Output() cachedDiffReportsChange = new EventEmitter>(); @Input() exerciseIdSubject: Subject = new Subject(); + isLoadingDiffReport: boolean; addedLineCount: number; removedLineCount: number; @@ -42,15 +53,6 @@ export class ProgrammingExerciseExamDiffComponent extends ExamPageComponent impl readonly faCodeCompare = faCodeCompare; readonly IncludedInOverallScore = IncludedInOverallScore; - constructor( - protected changeDetectorReference: ChangeDetectorRef, - private programmingExerciseService: ProgrammingExerciseService, - private modalService: NgbModal, - private cachedRepositoryFilesService: CachedRepositoryFilesService, - ) { - super(changeDetectorReference); - } - ngOnInit() { // we subscribe to the exercise id because this allows us to avoid reloading the diff report every time the user switches between submission timestamps this.exerciseIdSubscription = this.exerciseIdSubject.pipe(debounceTime(200)).subscribe(() => { @@ -132,14 +134,6 @@ export class ProgrammingExerciseExamDiffComponent extends ExamPageComponent impl }); } - getSubmission(): Submission | undefined { - return this.currentSubmission; - } - - getExercise(): Exercise { - return this.exercise; - } - private calculateMapKey() { return JSON.stringify([this.previousSubmission?.id, this.currentSubmission.id!]); } diff --git a/src/main/webapp/app/exam/manage/student-exams/student-exam-timeline/student-exam-timeline.component.ts b/src/main/webapp/app/exam/manage/student-exams/student-exam-timeline/student-exam-timeline.component.ts index ac7f501a52d5..4b8a63f9dd8c 100644 --- a/src/main/webapp/app/exam/manage/student-exams/student-exam-timeline/student-exam-timeline.component.ts +++ b/src/main/webapp/app/exam/manage/student-exams/student-exam-timeline/student-exam-timeline.component.ts @@ -1,10 +1,13 @@ -import { AfterViewInit, ChangeDetectorRef, Component, OnDestroy, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core'; +import { AfterViewInit, ChangeDetectorRef, Component, OnDestroy, OnInit, QueryList, ViewChild, ViewChildren, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { StudentExam } from 'app/entities/student-exam.model'; import { Exercise, ExerciseType } from 'app/entities/exercise.model'; import { ExamPage } from 'app/entities/exam/exam-page.model'; import { ExamSubmissionComponent } from 'app/exam/participate/exercises/exam-submission.component'; import { ExamNavigationBarComponent } from 'app/exam/participate/exam-navigation-bar/exam-navigation-bar.component'; +import { ModelingExamSubmissionComponent } from 'app/exam/participate/exercises/modeling/modeling-exam-submission.component'; +import { QuizExamSubmissionComponent } from 'app/exam/participate/exercises/quiz/quiz-exam-submission.component'; +import { TextExamSubmissionComponent } from 'app/exam/participate/exercises/text/text-exam-submission.component'; import { SubmissionService } from 'app/exercises/shared/submission/submission.service'; import dayjs from 'dayjs/esm'; import { SubmissionVersion } from 'app/entities/submission-version.model'; @@ -15,16 +18,35 @@ import { FileUploadSubmission } from 'app/entities/file-upload-submission.model' import { FileUploadExamSubmissionComponent } from 'app/exam/participate/exercises/file-upload/file-upload-exam-submission.component'; import { SubmissionVersionService } from 'app/exercises/shared/submission-version/submission-version.service'; import { ProgrammingExerciseExamDiffComponent } from 'app/exam/manage/student-exams/student-exam-timeline/programming-exam-diff/programming-exercise-exam-diff.component'; -import { ProgrammingExerciseParticipationService } from 'app/exercises/programming/manage/services/programming-exercise-participation.service'; import { ExamPageComponent } from 'app/exam/participate/exercises/exam-page.component'; import { ProgrammingExerciseGitDiffReport } from 'app/entities/programming-exercise-git-diff-report.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { MatSlider, MatSliderThumb } from '@angular/material/slider'; +import { FormsModule } from '@angular/forms'; @Component({ selector: 'jhi-student-exam-timeline', templateUrl: './student-exam-timeline.component.html', styleUrls: ['./student-exam-timeline.component.scss'], + imports: [ + TranslateDirective, + MatSlider, + MatSliderThumb, + FormsModule, + ExamNavigationBarComponent, + QuizExamSubmissionComponent, + FileUploadExamSubmissionComponent, + TextExamSubmissionComponent, + ModelingExamSubmissionComponent, + ProgrammingExerciseExamDiffComponent, + ], }) export class StudentExamTimelineComponent implements OnInit, AfterViewInit, OnDestroy { + private activatedRoute = inject(ActivatedRoute); + private submissionService = inject(SubmissionService); + private submissionVersionService = inject(SubmissionVersionService); + private cdr = inject(ChangeDetectorRef); + readonly ExerciseType = ExerciseType; readonly SubmissionVersion = SubmissionVersion; @@ -52,14 +74,6 @@ export class StudentExamTimelineComponent implements OnInit, AfterViewInit, OnDe private activatedRouteSubscription: Subscription; - constructor( - private activatedRoute: ActivatedRoute, - private submissionService: SubmissionService, - private submissionVersionService: SubmissionVersionService, - private programmingExerciseParticipationService: ProgrammingExerciseParticipationService, - private cdr: ChangeDetectorRef, - ) {} - ngOnInit(): void { this.activatedRouteSubscription = this.activatedRoute.data.subscribe(({ studentExam: studentExamWithGrade }) => { this.studentExam = studentExamWithGrade.studentExam; diff --git a/src/main/webapp/app/exam/manage/student-exams/student-exam.service.ts b/src/main/webapp/app/exam/manage/student-exams/student-exam.service.ts index 8d2196806de9..6a10d4325a96 100644 --- a/src/main/webapp/app/exam/manage/student-exams/student-exam.service.ts +++ b/src/main/webapp/app/exam/manage/student-exams/student-exam.service.ts @@ -1,5 +1,4 @@ -import { Injectable } from '@angular/core'; -import { Router } from '@angular/router'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable, map, tap } from 'rxjs'; import { StudentExam } from 'app/entities/student-exam.model'; @@ -11,13 +10,10 @@ type EntityArrayResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class StudentExamService { - public resourceUrl = 'api/courses'; + private http = inject(HttpClient); + private accountService = inject(AccountService); - constructor( - private router: Router, - private http: HttpClient, - private accountService: AccountService, - ) {} + public resourceUrl = 'api/courses'; /** * Find a student exam on the server using a GET request. diff --git a/src/main/webapp/app/exam/manage/student-exams/student-exams.component.html b/src/main/webapp/app/exam/manage/student-exams/student-exams.component.html index 5b85ae4215cd..9b670704024e 100644 --- a/src/main/webapp/app/exam/manage/student-exams/student-exams.component.html +++ b/src/main/webapp/app/exam/manage/student-exams/student-exams.component.html @@ -162,7 +162,7 @@

@if (isTestExam) { - + } @if (!isTestExam) { diff --git a/src/main/webapp/app/exam/manage/student-exams/student-exams.component.ts b/src/main/webapp/app/exam/manage/student-exams/student-exams.component.ts index f10fc54ecf2a..e1f30113fd9b 100644 --- a/src/main/webapp/app/exam/manage/student-exams/student-exams.component.ts +++ b/src/main/webapp/app/exam/manage/student-exams/student-exams.component.ts @@ -1,7 +1,9 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink } from '@angular/router'; +import { NgbModal, NgbProgressbar } from '@ng-bootstrap/ng-bootstrap'; import { StudentExamService } from 'app/exam/manage/student-exams/student-exam.service'; +import { StudentExamWorkingTimeComponent } from 'app/exam/shared/student-exam-working-time/student-exam-working-time.component'; +import { TestExamWorkingTimeComponent } from 'app/exam/shared/testExam-workingTime/test-exam-working-time.component'; import { Subscription } from 'rxjs'; import { tap } from 'rxjs/operators'; import { StudentExam } from 'app/entities/student-exam.model'; @@ -21,6 +23,12 @@ import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; import { convertDateFromServer } from 'app/utils/date.utils'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { PROFILE_LOCALVC } from 'app/app.constants'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { StudentExamStatusComponent } from './student-exam-status/student-exam-status.component'; +import { DataTableComponent } from 'app/shared/data-table/data-table.component'; +import { NgxDatatableModule } from '@siemens/ngx-datatable'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; const getWebsocketChannel = (examId: number) => `/topic/exams/${examId}/exercise-start-status`; @@ -35,8 +43,32 @@ export type ExamExerciseStartPreparationStatus = { @Component({ selector: 'jhi-student-exams', templateUrl: './student-exams.component.html', + imports: [ + TranslateDirective, + FaIconComponent, + StudentExamStatusComponent, + NgbProgressbar, + DataTableComponent, + NgxDatatableModule, + RouterLink, + TestExamWorkingTimeComponent, + StudentExamWorkingTimeComponent, + ArtemisDatePipe, + ArtemisTranslatePipe, + ], }) export class StudentExamsComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private examManagementService = inject(ExamManagementService); + private studentExamService = inject(StudentExamService); + private courseService = inject(CourseManagementService); + private alertService = inject(AlertService); + private modalService = inject(NgbModal); + private accountService = inject(AccountService); + private artemisTranslatePipe = inject(ArtemisTranslatePipe); + private websocketService = inject(JhiWebsocketService); + private profileService = inject(ProfileService); + courseId: number; examId: number; studentExams: StudentExam[] = []; @@ -63,19 +95,6 @@ export class StudentExamsComponent implements OnInit, OnDestroy { // Icons faExclamationTriangle = faExclamationTriangle; - constructor( - private route: ActivatedRoute, - private examManagementService: ExamManagementService, - private studentExamService: StudentExamService, - private courseService: CourseManagementService, - private alertService: AlertService, - private modalService: NgbModal, - private accountService: AccountService, - private artemisTranslatePipe: ArtemisTranslatePipe, - private websocketService: JhiWebsocketService, - private profileService: ProfileService, - ) {} - /** * Initialize the courseId and examId */ diff --git a/src/main/webapp/app/exam/manage/students/exam-students.component.ts b/src/main/webapp/app/exam/manage/students/exam-students.component.ts index ccc0f9e42671..1d5ea4f81858 100644 --- a/src/main/webapp/app/exam/manage/students/exam-students.component.ts +++ b/src/main/webapp/app/exam/manage/students/exam-students.component.ts @@ -1,8 +1,8 @@ -import { Component, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; +import { Component, OnDestroy, OnInit, ViewChild, ViewEncapsulation, inject } from '@angular/core'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { ExamUser } from 'app/entities/exam/exam-user.model'; import { Observable, Subject, Subscription, of } from 'rxjs'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { User } from 'app/core/user/user.model'; import { ActionType } from 'app/shared/delete-dialog/delete-dialog.model'; import { catchError, map, switchMap, tap } from 'rxjs/operators'; @@ -14,10 +14,16 @@ import { ExamManagementService } from 'app/exam/manage/exam-management.service'; import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; import { AccountService } from 'app/core/auth/account.service'; import { AlertService } from 'app/core/util/alert.service'; -import { EventManager } from 'app/core/util/event-manager.service'; import { faCheck, faInfoCircle, faPlus, faTimes, faUpload, faUserSlash, faUserTimes } from '@fortawesome/free-solid-svg-icons'; import dayjs from 'dayjs/esm'; import { StudentExamService } from 'app/exam/manage/student-exams/student-exam.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { UsersImportButtonComponent } from 'app/shared/user-import/users-import-button.component'; +import { StudentsUploadImagesButtonComponent } from './upload-images/students-upload-images-button.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { NgxDatatableModule } from '@siemens/ngx-datatable'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; const cssClasses = { alreadyRegistered: 'already-registered', @@ -29,8 +35,26 @@ const cssClasses = { templateUrl: './exam-students.component.html', styleUrls: ['./exam-students.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [ + TranslateDirective, + UsersImportButtonComponent, + StudentsUploadImagesButtonComponent, + FaIconComponent, + RouterLink, + DeleteButtonDirective, + DataTableComponent, + NgxDatatableModule, + ArtemisTranslatePipe, + ], }) export class ExamStudentsComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + private examManagementService = inject(ExamManagementService); + private userService = inject(UserService); + private accountService = inject(AccountService); + private studentExamService = inject(StudentExamService); + @ViewChild(DataTableComponent) dataTable: DataTableComponent; readonly ButtonType = ButtonType; @@ -67,16 +91,6 @@ export class ExamStudentsComponent implements OnInit, OnDestroy { faUpload = faUpload; faCheck = faCheck; faTimes = faTimes; - constructor( - private router: Router, - private route: ActivatedRoute, - private alertService: AlertService, - private eventManager: EventManager, - private examManagementService: ExamManagementService, - private userService: UserService, - private accountService: AccountService, - private studentExamService: StudentExamService, - ) {} ngOnInit() { this.isLoading = true; diff --git a/src/main/webapp/app/exam/manage/students/upload-images/students-upload-images-button.component.ts b/src/main/webapp/app/exam/manage/students/upload-images/students-upload-images-button.component.ts index 16b03fe9bbcd..a3d42089b84f 100644 --- a/src/main/webapp/app/exam/manage/students/upload-images/students-upload-images-button.component.ts +++ b/src/main/webapp/app/exam/manage/students/upload-images/students-upload-images-button.component.ts @@ -1,9 +1,10 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output, inject } from '@angular/core'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { StudentsUploadImagesDialogComponent } from 'app/exam/manage/students/upload-images/students-upload-images-dialog.component'; import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; import { Exam } from 'app/entities/exam/exam.model'; import { faPlus, faUpload } from '@fortawesome/free-solid-svg-icons'; +import { ButtonComponent } from 'app/shared/components/button.component'; @Component({ selector: 'jhi-student-upload-images-button', @@ -16,8 +17,11 @@ import { faPlus, faUpload } from '@fortawesome/free-solid-svg-icons'; (onClick)="openUploadImagesDialog($event)" /> `, + imports: [ButtonComponent], }) export class StudentsUploadImagesButtonComponent { + private modalService = inject(NgbModal); + ButtonType = ButtonType; ButtonSize = ButtonSize; @@ -31,8 +35,6 @@ export class StudentsUploadImagesButtonComponent { faPlus = faPlus; faUpload = faUpload; - constructor(private modalService: NgbModal) {} - /** * Open up upload dialog for exam users image upload * @param {Event} event - Mouse Event which invoked the opening diff --git a/src/main/webapp/app/exam/manage/students/upload-images/students-upload-images-dialog.component.ts b/src/main/webapp/app/exam/manage/students/upload-images/students-upload-images-dialog.component.ts index f94e4b9f836c..08cd57979d45 100644 --- a/src/main/webapp/app/exam/manage/students/upload-images/students-upload-images-dialog.component.ts +++ b/src/main/webapp/app/exam/manage/students/upload-images/students-upload-images-dialog.component.ts @@ -1,5 +1,5 @@ -import { Component, Input, OnDestroy, ViewChild, ViewEncapsulation } from '@angular/core'; -import { NgForm } from '@angular/forms'; +import { Component, Input, OnDestroy, ViewChild, ViewEncapsulation, inject } from '@angular/core'; +import { FormsModule, NgForm } from '@angular/forms'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { AlertService } from 'app/core/util/alert.service'; import { HttpErrorResponse } from '@angular/common/http'; @@ -9,6 +9,11 @@ import { Exam } from 'app/entities/exam/exam.model'; import { ExamManagementService } from 'app/exam/manage/exam-management.service'; import { faArrowRight, faBan, faCheck, faCircleNotch, faSpinner, faUpload } from '@fortawesome/free-solid-svg-icons'; import { onError } from 'app/shared/util/global.utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgClass } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; class NotFoundExamUserType { numberOfUsersNotFound: number; @@ -19,8 +24,13 @@ class NotFoundExamUserType { selector: 'jhi-student-upload-images-dialog', templateUrl: './students-upload-images-dialog.component.html', encapsulation: ViewEncapsulation.None, + imports: [FormsModule, TranslateDirective, HelpIconComponent, FaIconComponent, NgClass, ArtemisTranslatePipe], }) export class StudentsUploadImagesDialogComponent implements OnDestroy { + private activeModal = inject(NgbActiveModal); + private alertService = inject(AlertService); + private examManagementService = inject(ExamManagementService); + readonly ActionType = ActionType; @ViewChild('importForm', { static: false }) importForm: NgForm; @@ -44,12 +54,6 @@ export class StudentsUploadImagesDialogComponent implements OnDestroy { faUpload = faUpload; faArrowRight = faArrowRight; - constructor( - private activeModal: NgbActiveModal, - private alertService: AlertService, - private examManagementService: ExamManagementService, - ) {} - ngOnDestroy(): void { this.dialogErrorSource.unsubscribe(); } diff --git a/src/main/webapp/app/exam/manage/students/upload-images/students-upload-images.module.ts b/src/main/webapp/app/exam/manage/students/upload-images/students-upload-images.module.ts index 59a8f087f2ff..cbad103c8eef 100644 --- a/src/main/webapp/app/exam/manage/students/upload-images/students-upload-images.module.ts +++ b/src/main/webapp/app/exam/manage/students/upload-images/students-upload-images.module.ts @@ -5,8 +5,7 @@ import { ArtemisSharedComponentModule } from 'app/shared/components/shared-compo import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; @NgModule({ - imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule], - declarations: [StudentsUploadImagesDialogComponent, StudentsUploadImagesButtonComponent], + imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule, StudentsUploadImagesDialogComponent, StudentsUploadImagesButtonComponent], exports: [StudentsUploadImagesDialogComponent, StudentsUploadImagesButtonComponent], }) export class StudentsUploadImagesModule {} diff --git a/src/main/webapp/app/exam/manage/students/verify-attendance-check/exam-students-attendance-check.component.ts b/src/main/webapp/app/exam/manage/students/verify-attendance-check/exam-students-attendance-check.component.ts index e8cfdfa14426..519614190490 100644 --- a/src/main/webapp/app/exam/manage/students/verify-attendance-check/exam-students-attendance-check.component.ts +++ b/src/main/webapp/app/exam/manage/students/verify-attendance-check/exam-students-attendance-check.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { Component, OnDestroy, OnInit, ViewEncapsulation, inject } from '@angular/core'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { ExamUserAttendanceCheckDTO } from 'app/entities/exam/exam-users-attendance-check-dto.model'; import { SortService } from 'app/shared/service/sort.service'; @@ -14,13 +14,27 @@ import { AlertService } from 'app/core/util/alert.service'; import { EventManager } from 'app/core/util/event-manager.service'; import { faCheck, faInfoCircle, faPlus, faSort, faTimes, faUpload, faUserSlash, faXmark } from '@fortawesome/free-solid-svg-icons'; import dayjs from 'dayjs/esm'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; @Component({ selector: 'jhi-exam-students-attendance-check', templateUrl: './exam-students-attendance-check.component.html', encapsulation: ViewEncapsulation.None, + imports: [TranslateDirective, FaIconComponent, SortDirective, SortByDirective], }) export class ExamStudentsAttendanceCheckComponent implements OnInit, OnDestroy { + private router = inject(Router); + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + private eventManager = inject(EventManager); + private examManagementService = inject(ExamManagementService); + private userService = inject(UserService); + private accountService = inject(AccountService); + private sortService = inject(SortService); + readonly ButtonType = ButtonType; readonly ButtonSize = ButtonSize; readonly ActionType = ActionType; @@ -57,17 +71,6 @@ export class ExamStudentsAttendanceCheckComponent implements OnInit, OnDestroy { faXmark = faXmark; faSort = faSort; - constructor( - private router: Router, - private route: ActivatedRoute, - private alertService: AlertService, - private eventManager: EventManager, - private examManagementService: ExamManagementService, - private userService: UserService, - private accountService: AccountService, - private sortService: SortService, - ) {} - ngOnInit() { this.isLoading = true; this.courseId = Number(this.route.snapshot.paramMap.get('courseId')); diff --git a/src/main/webapp/app/exam/manage/suspicious-behavior/plagiarism-cases-overview/plagiarism-cases-overview.component.ts b/src/main/webapp/app/exam/manage/suspicious-behavior/plagiarism-cases-overview/plagiarism-cases-overview.component.ts index 5f9d2c05a2bd..45d0b248c0bf 100644 --- a/src/main/webapp/app/exam/manage/suspicious-behavior/plagiarism-cases-overview/plagiarism-cases-overview.component.ts +++ b/src/main/webapp/app/exam/manage/suspicious-behavior/plagiarism-cases-overview/plagiarism-cases-overview.component.ts @@ -6,7 +6,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-plagiarism-cases-overview', templateUrl: './plagiarism-cases-overview.component.html', - standalone: true, imports: [TranslateDirective], }) export class PlagiarismCasesOverviewComponent { diff --git a/src/main/webapp/app/exam/manage/suspicious-behavior/suspicious-behavior.component.ts b/src/main/webapp/app/exam/manage/suspicious-behavior/suspicious-behavior.component.ts index 0fc847d95581..2fe3406fe655 100644 --- a/src/main/webapp/app/exam/manage/suspicious-behavior/suspicious-behavior.component.ts +++ b/src/main/webapp/app/exam/manage/suspicious-behavior/suspicious-behavior.component.ts @@ -16,7 +16,6 @@ import { FormsModule } from '@angular/forms'; @Component({ selector: 'jhi-suspicious-behavior', templateUrl: './suspicious-behavior.component.html', - standalone: true, imports: [FormsModule, TranslateDirective, ArtemisTranslatePipe, ArtemisSharedComponentModule, PlagiarismCasesOverviewComponent], }) export class SuspiciousBehaviorComponent implements OnInit { diff --git a/src/main/webapp/app/exam/manage/suspicious-behavior/suspicious-sessions-overview/suspicious-sessions-overview.component.ts b/src/main/webapp/app/exam/manage/suspicious-behavior/suspicious-sessions-overview/suspicious-sessions-overview.component.ts index 0626bb6d8911..fa02409b274d 100644 --- a/src/main/webapp/app/exam/manage/suspicious-behavior/suspicious-sessions-overview/suspicious-sessions-overview.component.ts +++ b/src/main/webapp/app/exam/manage/suspicious-behavior/suspicious-sessions-overview/suspicious-sessions-overview.component.ts @@ -9,7 +9,6 @@ import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; selector: 'jhi-suspicious-sessions-overview', templateUrl: './suspicious-sessions-overview.component.html', styleUrls: ['./suspicious-sessions-overview.component.scss'], - standalone: true, imports: [SuspiciousSessionsComponent, TranslateDirective, ArtemisTranslatePipe], }) export class SuspiciousSessionsOverviewComponent implements OnInit { diff --git a/src/main/webapp/app/exam/manage/suspicious-behavior/suspicious-sessions/suspicious-sessions.component.ts b/src/main/webapp/app/exam/manage/suspicious-behavior/suspicious-sessions/suspicious-sessions.component.ts index 7e153d9faaad..8cbbe3c92b89 100644 --- a/src/main/webapp/app/exam/manage/suspicious-behavior/suspicious-sessions/suspicious-sessions.component.ts +++ b/src/main/webapp/app/exam/manage/suspicious-behavior/suspicious-sessions/suspicious-sessions.component.ts @@ -5,11 +5,9 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; @Component({ // this is intended and an attribute selector because otherwise the rendered table breaks - // eslint-disable-next-line @angular-eslint/component-selector selector: '[jhi-suspicious-sessions]', templateUrl: './suspicious-sessions.component.html', styleUrls: ['./suspicious-sessions.component.scss'], - standalone: true, imports: [ArtemisSharedModule], }) export class SuspiciousSessionsComponent implements OnInit { diff --git a/src/main/webapp/app/exam/manage/test-runs/create-test-run-modal.component.ts b/src/main/webapp/app/exam/manage/test-runs/create-test-run-modal.component.ts index a43fa4a9e41c..29e5e47640a0 100644 --- a/src/main/webapp/app/exam/manage/test-runs/create-test-run-modal.component.ts +++ b/src/main/webapp/app/exam/manage/test-runs/create-test-run-modal.component.ts @@ -1,28 +1,28 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { StudentExam } from 'app/entities/student-exam.model'; import { Exam } from 'app/entities/exam/exam.model'; import { Exercise } from 'app/entities/exercise.model'; import { ExerciseGroup } from 'app/entities/exercise-group.model'; -import { FormControl, FormGroup, Validators } from '@angular/forms'; +import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { ArtemisDurationFromSecondsPipe } from 'app/shared/pipes/artemis-duration-from-seconds.pipe'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-create-test-run-modal', templateUrl: './create-test-run-modal.component.html', providers: [ArtemisDurationFromSecondsPipe], styles: ['.table tr.active td { background-color:#3e8acc; color: white; }'], + imports: [TranslateDirective, FormsModule, ReactiveFormsModule], }) export class CreateTestRunModalComponent implements OnInit { + private activeModal = inject(NgbActiveModal); + private artemisDurationFromSecondsPipe = inject(ArtemisDurationFromSecondsPipe); + exam: Exam; workingTimeForm: FormGroup; testRunConfiguration: { [id: number]: Exercise } = {}; - constructor( - private activeModal: NgbActiveModal, - private artemisDurationFromSecondsPipe: ArtemisDurationFromSecondsPipe, - ) {} - ngOnInit(): void { this.initWorkingTimeForm(); this.ignoreEmptyExerciseGroups(); diff --git a/src/main/webapp/app/exam/manage/test-runs/test-run-management.component.html b/src/main/webapp/app/exam/manage/test-runs/test-run-management.component.html index 988dcfa83074..6f4971128eac 100644 --- a/src/main/webapp/app/exam/manage/test-runs/test-run-management.component.html +++ b/src/main/webapp/app/exam/manage/test-runs/test-run-management.component.html @@ -113,7 +113,7 @@

{{ exam? } diff --git a/src/main/webapp/app/exam/manage/test-runs/test-run-management.component.ts b/src/main/webapp/app/exam/manage/test-runs/test-run-management.component.ts index 06d0196d6ba9..0492d8d6ac18 100644 --- a/src/main/webapp/app/exam/manage/test-runs/test-run-management.component.ts +++ b/src/main/webapp/app/exam/manage/test-runs/test-run-management.component.ts @@ -1,12 +1,12 @@ -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { Component, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { Course } from 'app/entities/course.model'; import { StudentExam } from 'app/entities/student-exam.model'; import { SortService } from 'app/shared/service/sort.service'; import { Exam } from 'app/entities/exam/exam.model'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { AlertService } from 'app/core/util/alert.service'; -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbModalRef, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { CreateTestRunModalComponent } from 'app/exam/manage/test-runs/create-test-run-modal.component'; import { ExamManagementService } from 'app/exam/manage/exam-management.service'; import { AccountService } from 'app/core/auth/account.service'; @@ -14,12 +14,39 @@ import { Subject } from 'rxjs'; import { User } from 'app/core/user/user.model'; import { onError } from 'app/shared/util/global.utils'; import { faSort, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { ArtemisDurationFromSecondsPipe } from 'app/shared/pipes/artemis-duration-from-seconds.pipe'; @Component({ selector: 'jhi-test-run-management', templateUrl: './test-run-management.component.html', + imports: [ + TranslateDirective, + NgbTooltip, + RouterLink, + SortDirective, + SortByDirective, + FaIconComponent, + DeleteButtonDirective, + ArtemisDatePipe, + ArtemisTranslatePipe, + ArtemisDurationFromSecondsPipe, + ], }) export class TestRunManagementComponent implements OnInit { + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + private examManagementService = inject(ExamManagementService); + private accountService = inject(AccountService); + private sortService = inject(SortService); + private modalService = inject(NgbModal); + course: Course; exam: Exam; isLoading: boolean; @@ -35,14 +62,7 @@ export class TestRunManagementComponent implements OnInit { faSort = faSort; faTimes = faTimes; - constructor( - private route: ActivatedRoute, - private alertService: AlertService, - private examManagementService: ExamManagementService, - private accountService: AccountService, - private sortService: SortService, - private modalService: NgbModal, - ) { + constructor() { this.predicate = 'id'; this.ascending = true; } diff --git a/src/main/webapp/app/exam/manage/test-runs/test-run-ribbon.component.ts b/src/main/webapp/app/exam/manage/test-runs/test-run-ribbon.component.ts index c2d0b5f5e366..c14f8155ae79 100644 --- a/src/main/webapp/app/exam/manage/test-runs/test-run-ribbon.component.ts +++ b/src/main/webapp/app/exam/manage/test-runs/test-run-ribbon.component.ts @@ -1,4 +1,5 @@ import { Component } from '@angular/core'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-test-run-ribbon', @@ -10,5 +11,6 @@ import { Component } from '@angular/core';

`, styleUrls: ['../../../shared/layouts/profiles/page-ribbon.scss'], + imports: [TranslateDirective], }) export class TestRunRibbonComponent {} diff --git a/src/main/webapp/app/exam/participate/events/exam-live-events-button.component.ts b/src/main/webapp/app/exam/participate/events/exam-live-events-button.component.ts index 8659685258a2..91a0fcf88fa8 100644 --- a/src/main/webapp/app/exam/participate/events/exam-live-events-button.component.ts +++ b/src/main/webapp/app/exam/participate/events/exam-live-events-button.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit, ViewEncapsulation, inject } from '@angular/core'; import { faBullhorn } from '@fortawesome/free-solid-svg-icons'; import { AlertService } from 'app/core/util/alert.service'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; @@ -6,6 +6,7 @@ import { Subscription, from } from 'rxjs'; import { ExamLiveEvent, ExamLiveEventType, ExamParticipationLiveEventsService } from 'app/exam/participate/exam-participation-live-events.service'; import { ExamLiveEventsOverlayComponent } from 'app/exam/participate/events/exam-live-events-overlay.component'; import dayjs from 'dayjs/esm'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; export const USER_DISPLAY_RELEVANT_EVENTS = [ ExamLiveEventType.EXAM_WIDE_ANNOUNCEMENT, @@ -20,8 +21,13 @@ export const USER_DISPLAY_RELEVANT_EVENTS_REOPEN = [ExamLiveEventType.EXAM_WIDE_ templateUrl: './exam-live-events-button.component.html', styleUrls: ['./exam-live-events-button.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [FaIconComponent], }) export class ExamLiveEventsButtonComponent implements OnInit, OnDestroy { + private alertService = inject(AlertService); + private modalService = inject(NgbModal); + private liveEventsService = inject(ExamParticipationLiveEventsService); + private modalRef?: NgbModalRef; private liveEventsSubscription?: Subscription; private allEventsSubscription?: Subscription; @@ -31,12 +37,6 @@ export class ExamLiveEventsButtonComponent implements OnInit, OnDestroy { // Icons faBullhorn = faBullhorn; - constructor( - private alertService: AlertService, - private modalService: NgbModal, - private liveEventsService: ExamParticipationLiveEventsService, - ) {} - ngOnInit(): void { this.allEventsSubscription = this.liveEventsService.observeAllEvents(USER_DISPLAY_RELEVANT_EVENTS_REOPEN).subscribe((events: ExamLiveEvent[]) => { // do not count the problem statements events that are made before the start of the exam diff --git a/src/main/webapp/app/exam/participate/events/exam-live-events-overlay.component.ts b/src/main/webapp/app/exam/participate/events/exam-live-events-overlay.component.ts index cf24ccb614e4..b1c1e7f99c1c 100644 --- a/src/main/webapp/app/exam/participate/events/exam-live-events-overlay.component.ts +++ b/src/main/webapp/app/exam/participate/events/exam-live-events-overlay.component.ts @@ -1,18 +1,26 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { faCheck } from '@fortawesome/free-solid-svg-icons'; +import { ExamLiveEventComponent } from 'app/exam/shared/events/exam-live-event.component'; import { Subscription } from 'rxjs'; import { ExamLiveEvent, ExamLiveEventType, ExamParticipationLiveEventsService, ProblemStatementUpdateEvent } from 'app/exam/participate/exam-participation-live-events.service'; import { USER_DISPLAY_RELEVANT_EVENTS, USER_DISPLAY_RELEVANT_EVENTS_REOPEN } from 'app/exam/participate/events/exam-live-events-button.component'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { ExamExerciseUpdateService } from 'app/exam/manage/exam-exercise-update.service'; import dayjs from 'dayjs/esm'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-exam-live-events-overlay', templateUrl: './exam-live-events-overlay.component.html', styleUrls: ['./exam-live-events-overlay.component.scss'], + imports: [ExamLiveEventComponent, FaIconComponent, TranslateDirective], }) export class ExamLiveEventsOverlayComponent implements OnInit, OnDestroy { + private liveEventsService = inject(ExamParticipationLiveEventsService); + private activeModal = inject(NgbActiveModal); + private examExerciseUpdateService = inject(ExamExerciseUpdateService); + private allLiveEventsSubscription?: Subscription; private newLiveEventsSubscription?: Subscription; @@ -26,12 +34,6 @@ export class ExamLiveEventsOverlayComponent implements OnInit, OnDestroy { protected readonly ExamLiveEventType = ExamLiveEventType; - constructor( - private liveEventsService: ExamParticipationLiveEventsService, - private activeModal: NgbActiveModal, - private examExerciseUpdateService: ExamExerciseUpdateService, - ) {} - ngOnDestroy(): void { this.allLiveEventsSubscription?.unsubscribe(); this.newLiveEventsSubscription?.unsubscribe(); diff --git a/src/main/webapp/app/exam/participate/events/exam-live-events.module.ts b/src/main/webapp/app/exam/participate/events/exam-live-events.module.ts index ef1a24e8e765..cc805d9c46f0 100644 --- a/src/main/webapp/app/exam/participate/events/exam-live-events.module.ts +++ b/src/main/webapp/app/exam/participate/events/exam-live-events.module.ts @@ -7,8 +7,7 @@ import { ExamLiveEventsOverlayComponent } from 'app/exam/participate/events/exam import { ArtemisExamSharedModule } from 'app/exam/shared/exam-shared.module'; @NgModule({ - declarations: [ExamLiveEventsButtonComponent, ExamLiveEventsOverlayComponent], - imports: [CommonModule, ArtemisSharedCommonModule, ArtemisExamTimerModule, ArtemisExamSharedModule], + imports: [CommonModule, ArtemisSharedCommonModule, ArtemisExamTimerModule, ArtemisExamSharedModule, ExamLiveEventsButtonComponent, ExamLiveEventsOverlayComponent], exports: [ExamLiveEventsButtonComponent, ExamLiveEventsOverlayComponent], }) export class ArtemisExamLiveEventsModule {} diff --git a/src/main/webapp/app/exam/participate/exam-bar/exam-bar.component.ts b/src/main/webapp/app/exam/participate/exam-bar/exam-bar.component.ts index daf2532e3b15..e4c0b2afacf5 100644 --- a/src/main/webapp/app/exam/participate/exam-bar/exam-bar.component.ts +++ b/src/main/webapp/app/exam/participate/exam-bar/exam-bar.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnInit, Output, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; import { ArtemisExamTimerModule } from 'app/exam/participate/timer/exam-timer.module'; @@ -12,12 +12,13 @@ import { StudentExam } from 'app/entities/student-exam.model'; @Component({ selector: 'jhi-exam-bar', - standalone: true, imports: [CommonModule, ArtemisSharedCommonModule, ArtemisExamTimerModule, ArtemisExamLiveEventsModule], templateUrl: './exam-bar.component.html', styleUrl: './exam-bar.component.scss', }) export class ExamBarComponent implements AfterViewInit, OnInit { + private elementRef = inject(ElementRef); + @Output() onExamHandInEarly = new EventEmitter(); @Output() examAboutToEnd = new EventEmitter(); @Output() heightChange = new EventEmitter(); @@ -41,8 +42,6 @@ export class ExamBarComponent implements AfterViewInit, OnInit { examTitle: string; exercises: Exercise[] = []; - constructor(private elementRef: ElementRef) {} - ngOnInit(): void { this.examTitle = this.exam.title ?? ''; this.exercises = this.studentExam.exercises ?? []; diff --git a/src/main/webapp/app/exam/participate/exam-cover/exam-participation-cover.component.ts b/src/main/webapp/app/exam/participate/exam-cover/exam-participation-cover.component.ts index 090588335574..56084ed83e0c 100644 --- a/src/main/webapp/app/exam/participate/exam-cover/exam-participation-cover.component.ts +++ b/src/main/webapp/app/exam/participate/exam-cover/exam-participation-cover.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, inject } from '@angular/core'; import { SafeHtml } from '@angular/platform-browser'; import { ArtemisMarkdownService } from 'app/shared/markdown.service'; import { CourseManagementService } from 'app/course/manage/course-management.service'; @@ -14,13 +14,29 @@ import { EXAM_START_WAIT_TIME_MINUTES } from 'app/app.constants'; import { UI_RELOAD_TIME } from 'app/shared/constants/exercise-exam-constants'; import { faArrowLeft, faCircleExclamation, faDoorClosed, faSpinner } from '@fortawesome/free-solid-svg-icons'; import { Subscription } from 'rxjs'; +import { NgClass } from '@angular/common'; +import { ExamLiveEventsButtonComponent } from '../events/exam-live-events-button.component'; +import { ExamStartInformationComponent } from '../exam-start-information/exam-start-information.component'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-exam-participation-cover', templateUrl: './exam-participation-cover.component.html', styleUrls: ['./exam-participation-cover.scss'], + imports: [NgClass, ExamLiveEventsButtonComponent, ExamStartInformationComponent, FormsModule, TranslateDirective, FaIconComponent, ArtemisDatePipe, ArtemisTranslatePipe], }) export class ExamParticipationCoverComponent implements OnChanges, OnDestroy, OnInit { + private courseService = inject(CourseManagementService); + private artemisMarkdown = inject(ArtemisMarkdownService); + private translateService = inject(TranslateService); + private accountService = inject(AccountService); + private examParticipationService = inject(ExamParticipationService); + private serverDateService = inject(ArtemisServerDateService); + /** * if startView is set to true: startText and confirmationStartText will be displayed * if startView is set to false: endText and confirmationEndText will be displayed @@ -65,15 +81,6 @@ export class ExamParticipationCoverComponent implements OnChanges, OnDestroy, On faCircleExclamation = faCircleExclamation; faDoorClosed = faDoorClosed; - constructor( - private courseService: CourseManagementService, - private artemisMarkdown: ArtemisMarkdownService, - private translateService: TranslateService, - private accountService: AccountService, - private examParticipationService: ExamParticipationService, - private serverDateService: ArtemisServerDateService, - ) {} - ngOnInit(): void { this.isAttendanceChecked = this.exam.testExam || !this.exam.examWithAttendanceCheck || this.attendanceChecked; } diff --git a/src/main/webapp/app/exam/participate/exam-navigation-bar/exam-navigation-bar.component.ts b/src/main/webapp/app/exam/participate/exam-navigation-bar/exam-navigation-bar.component.ts index 800285feeda1..28aab3a490b3 100644 --- a/src/main/webapp/app/exam/participate/exam-navigation-bar/exam-navigation-bar.component.ts +++ b/src/main/webapp/app/exam/participate/exam-navigation-bar/exam-navigation-bar.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { AfterViewInit, Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core'; import { Exercise, ExerciseType } from 'app/entities/exercise.model'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { LayoutService } from 'app/shared/breakpoints/layout.service'; @@ -17,13 +17,27 @@ import { faBars, faCheck, faEdit } from '@fortawesome/free-solid-svg-icons'; import { ProgrammingSubmission } from 'app/entities/programming/programming-submission.model'; import { SubmissionVersion } from 'app/entities/submission-version.model'; import { FileUploadSubmission } from 'app/entities/file-upload-submission.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ExamLiveEventsButtonComponent } from '../events/exam-live-events-button.component'; +import { NgClass } from '@angular/common'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ExamTimerComponent } from '../timer/exam-timer.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-exam-navigation-bar', templateUrl: './exam-navigation-bar.component.html', styleUrls: ['./exam-navigation-bar.component.scss'], + imports: [TranslateDirective, ExamLiveEventsButtonComponent, NgClass, NgbTooltip, FaIconComponent, ExamTimerComponent, ArtemisTranslatePipe], }) export class ExamNavigationBarComponent implements OnInit, AfterViewInit { + private layoutService = inject(LayoutService); + private examParticipationService = inject(ExamParticipationService); + private examExerciseUpdateService = inject(ExamExerciseUpdateService); + private repositoryService = inject(CodeEditorRepositoryService); + private conflictService = inject(CodeEditorConflictStateService); + @Input() exercises: Exercise[] = []; @Input() exerciseIndex = 0; @Input() endDate: dayjs.Dayjs; @@ -51,14 +65,6 @@ export class ExamNavigationBarComponent implements OnInit, AfterViewInit { // Icons faBars = faBars; - constructor( - private layoutService: LayoutService, - private examParticipationService: ExamParticipationService, - private examExerciseUpdateService: ExamExerciseUpdateService, - private repositoryService: CodeEditorRepositoryService, - private conflictService: CodeEditorConflictStateService, - ) {} - ngOnInit(): void { if (!this.examTimeLineView) { this.subscriptionToLiveExamExerciseUpdates = this.examExerciseUpdateService.currentExerciseIdForNavigation.subscribe((exerciseIdToNavigateTo) => { diff --git a/src/main/webapp/app/exam/participate/exam-navigation-bar/exam-navigation-bar.module.ts b/src/main/webapp/app/exam/participate/exam-navigation-bar/exam-navigation-bar.module.ts index 1dedc313ae2e..e56eeac54ab9 100644 --- a/src/main/webapp/app/exam/participate/exam-navigation-bar/exam-navigation-bar.module.ts +++ b/src/main/webapp/app/exam/participate/exam-navigation-bar/exam-navigation-bar.module.ts @@ -6,8 +6,7 @@ import { ArtemisExamTimerModule } from 'app/exam/participate/timer/exam-timer.mo import { ArtemisExamLiveEventsModule } from 'app/exam/participate/events/exam-live-events.module'; @NgModule({ - declarations: [ExamNavigationBarComponent], - imports: [CommonModule, ArtemisSharedCommonModule, ArtemisExamTimerModule, ArtemisExamLiveEventsModule], + imports: [CommonModule, ArtemisSharedCommonModule, ArtemisExamTimerModule, ArtemisExamLiveEventsModule, ExamNavigationBarComponent], exports: [ExamNavigationBarComponent], }) export class ArtemisExamNavigationBarModule {} diff --git a/src/main/webapp/app/exam/participate/exam-navigation-sidebar/exam-navigation-sidebar.component.ts b/src/main/webapp/app/exam/participate/exam-navigation-sidebar/exam-navigation-sidebar.component.ts index 93bcecfa27ae..d6cb7fd64c3d 100644 --- a/src/main/webapp/app/exam/participate/exam-navigation-sidebar/exam-navigation-sidebar.component.ts +++ b/src/main/webapp/app/exam/participate/exam-navigation-sidebar/exam-navigation-sidebar.component.ts @@ -1,7 +1,6 @@ -import { Component, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, HostListener, Input, OnDestroy, OnInit, Output, inject } from '@angular/core'; import { ArtemisSidebarModule } from 'app/shared/sidebar/sidebar.module'; import { ArtemisSharedModule } from 'app/shared/shared.module'; -import { SidebarCardDirective } from 'app/shared/sidebar/sidebar-card.directive'; import { Subscription } from 'rxjs'; import { SidebarEventService } from 'app/shared/sidebar/sidebar-event.service'; import { SidebarData } from 'app/types/sidebar'; @@ -20,8 +19,8 @@ import { CommitState, DomainChange, DomainType } from 'app/exercises/programming import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { faChevronRight, faFileLines, faHourglassHalf } from '@fortawesome/free-solid-svg-icons'; -import { facSaveSuccess, facSaveWarning } from '../../../../content/icons/icons'; import { getIconTooltip } from 'app/entities/exercise.model'; +import { facSaveSuccess, facSaveWarning } from 'app/icons/icons'; export enum ExerciseButtonStatus { Synced = 'synced', @@ -31,12 +30,18 @@ export enum ExerciseButtonStatus { @Component({ selector: 'jhi-exam-navigation-sidebar', - standalone: true, - imports: [ArtemisSidebarModule, ArtemisSharedModule, SidebarCardDirective], + imports: [ArtemisSidebarModule, ArtemisSharedModule], templateUrl: './exam-navigation-sidebar.component.html', styleUrl: './exam-navigation-sidebar.component.scss', }) export class ExamNavigationSidebarComponent implements OnDestroy, OnInit { + private profileService = inject(ProfileService); + private sidebarEventService = inject(SidebarEventService); + private examParticipationService = inject(ExamParticipationService); + private examExerciseUpdateService = inject(ExamExerciseUpdateService); + private repositoryService = inject(CodeEditorRepositoryService); + private conflictService = inject(CodeEditorConflictStateService); + @Input() sidebarData: SidebarData; @Input() exercises: Exercise[] = []; @Input() exerciseIndex = 0; @@ -61,7 +66,6 @@ export class ExamNavigationSidebarComponent implements OnDestroy, OnInit { icon: IconProp; readonly faFileLines = faFileLines; readonly faChevronRight = faChevronRight; - readonly ExerciseButtonStatus = ExerciseButtonStatus; profileSubscription?: Subscription; isProduction = true; @@ -70,15 +74,6 @@ export class ExamNavigationSidebarComponent implements OnDestroy, OnInit { exerciseId: string; numberOfSavedExercises: number = 0; - constructor( - private profileService: ProfileService, - private sidebarEventService: SidebarEventService, - private examParticipationService: ExamParticipationService, - private examExerciseUpdateService: ExamExerciseUpdateService, - private repositoryService: CodeEditorRepositoryService, - private conflictService: CodeEditorConflictStateService, - ) {} - ngOnInit(): void { this.profileSubscription = this.profileService.getProfileInfo()?.subscribe((profileInfo) => { this.isProduction = profileInfo?.inProduction; @@ -92,6 +87,7 @@ export class ExamNavigationSidebarComponent implements OnDestroy, OnInit { }); } + // TODO: avoid duplicated code const isInitialSession = this.examSessions && this.examSessions.length > 0 && this.examSessions[0].initialSession; if (isInitialSession || isInitialSession == undefined) { return; @@ -134,9 +130,9 @@ export class ExamNavigationSidebarComponent implements OnDestroy, OnInit { } /** - * @param overviewPage: user wants to switch to the overview page - * @param exerciseIndex: index of the exercise to switch to, if it should not be used, you can pass -1 - * @param forceSave: true if forceSave shall be used. + * @param overviewPage user wants to switch to the overview page + * @param exerciseIndex index of the exercise to switch to, if it should not be used, you can pass -1 + * @param forceSave true if forceSave shall be used. * @param submission the submission to be viewed, used in the exam timeline */ changePage(overviewPage: boolean, exerciseIndex: number, forceSave?: boolean, submission?: SubmissionVersion | ProgrammingSubmission | FileUploadSubmission): void { diff --git a/src/main/webapp/app/exam/participate/exam-participation-live-events.service.ts b/src/main/webapp/app/exam/participate/exam-participation-live-events.service.ts index 63e5c7cf0ec8..1058fb8fbbba 100644 --- a/src/main/webapp/app/exam/participate/exam-participation-live-events.service.ts +++ b/src/main/webapp/app/exam/participate/exam-participation-live-events.service.ts @@ -1,5 +1,5 @@ import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ConnectionState, JhiWebsocketService } from 'app/core/websocket/websocket.service'; import { ExamParticipationService } from 'app/exam/participate/exam-participation.service'; import dayjs from 'dayjs/esm'; @@ -54,6 +54,11 @@ export type ProblemStatementUpdateEvent = ExamLiveEvent & { @Injectable({ providedIn: 'root' }) export class ExamParticipationLiveEventsService { + private websocketService = inject(JhiWebsocketService); + private examParticipationService = inject(ExamParticipationService); + private localStorageService = inject(LocalStorageService); + private httpClient = inject(HttpClient); + private courseId?: number; private examId?: number; private studentExamId?: number; @@ -74,12 +79,7 @@ export class ExamParticipationLiveEventsService { // Subject that emits all events when the array of events changes private allEventsSubject = new BehaviorSubject([]); - constructor( - private websocketService: JhiWebsocketService, - private examParticipationService: ExamParticipationService, - private localStorageService: LocalStorageService, - private httpClient: HttpClient, - ) { + constructor() { this.clearOldAcknowledgement(); // Listen to updates of the connection state; if we reconnect, we should fetch the list of events diff --git a/src/main/webapp/app/exam/participate/exam-participation.component.ts b/src/main/webapp/app/exam/participate/exam-participation.component.ts index 7871ce88d681..c4b8c658aff2 100644 --- a/src/main/webapp/app/exam/participate/exam-participation.component.ts +++ b/src/main/webapp/app/exam/participate/exam-participation.component.ts @@ -1,5 +1,5 @@ -import { Component, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { Component, OnDestroy, OnInit, QueryList, ViewChildren, inject } from '@angular/core'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; import { ExamParticipationService } from 'app/exam/participate/exam-participation.service'; import { StudentExam } from 'app/entities/student-exam.model'; @@ -45,6 +45,22 @@ import { import { ExamExerciseUpdateService } from 'app/exam/manage/exam-exercise-update.service'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { SidebarCardElement, SidebarData } from 'app/types/sidebar'; +import { TestRunRibbonComponent } from '../manage/test-runs/test-run-ribbon.component'; +import { ExamParticipationCoverComponent } from './exam-cover/exam-participation-cover.component'; +import { AsyncPipe, NgClass } from '@angular/common'; +import { ExamBarComponent } from './exam-bar/exam-bar.component'; +import { ExamNavigationSidebarComponent } from './exam-navigation-sidebar/exam-navigation-sidebar.component'; +import { ExamExerciseOverviewPageComponent } from './exercises/exercise-overview-page/exam-exercise-overview-page.component'; +import { QuizExamSubmissionComponent } from './exercises/quiz/quiz-exam-submission.component'; +import { FileUploadExamSubmissionComponent } from './exercises/file-upload/file-upload-exam-submission.component'; +import { TextExamSubmissionComponent } from './exercises/text/text-exam-submission.component'; +import { ModelingExamSubmissionComponent } from './exercises/modeling/modeling-exam-submission.component'; +import { ProgrammingExamSubmissionComponent } from './exercises/programming/programming-exam-submission.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { JhiConnectionStatusComponent } from 'app/shared/connection-status/connection-status.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ExamResultSummaryComponent } from './summary/exam-result-summary.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; type GenerateParticipationStatus = 'generating' | 'failed' | 'success'; @@ -52,8 +68,46 @@ type GenerateParticipationStatus = 'generating' | 'failed' | 'success'; selector: 'jhi-exam-participation', templateUrl: './exam-participation.component.html', styleUrls: ['./exam-participation.scss'], + imports: [ + TestRunRibbonComponent, + ExamParticipationCoverComponent, + NgClass, + ExamBarComponent, + ExamNavigationSidebarComponent, + ExamExerciseOverviewPageComponent, + QuizExamSubmissionComponent, + FileUploadExamSubmissionComponent, + TextExamSubmissionComponent, + ModelingExamSubmissionComponent, + ProgrammingExamSubmissionComponent, + TranslateDirective, + JhiConnectionStatusComponent, + FaIconComponent, + ExamResultSummaryComponent, + RouterLink, + AsyncPipe, + ArtemisTranslatePipe, + ], }) export class ExamParticipationComponent implements OnInit, OnDestroy, ComponentCanDeactivate { + private websocketService = inject(JhiWebsocketService); + private route = inject(ActivatedRoute); + private router = inject(Router); + private examParticipationService = inject(ExamParticipationService); + private modelingSubmissionService = inject(ModelingSubmissionService); + private programmingSubmissionService = inject(ProgrammingSubmissionService); + private textSubmissionService = inject(TextSubmissionService); + private serverDateService = inject(ArtemisServerDateService); + private translateService = inject(TranslateService); + private alertService = inject(AlertService); + private courseExerciseService = inject(CourseExerciseService); + private liveEventsService = inject(ExamParticipationLiveEventsService); + private courseService = inject(CourseManagementService); + private courseStorageService = inject(CourseStorageService); + private examExerciseUpdateService = inject(ExamExerciseUpdateService); + private examManagementService = inject(ExamManagementService); + private profileService = inject(ProfileService); + @ViewChildren(ExamSubmissionComponent) currentPageComponents: QueryList; @@ -145,25 +199,7 @@ export class ExamParticipationComponent implements OnInit, OnDestroy, ComponentC // Icons faGraduationCap = faGraduationCap; - constructor( - private websocketService: JhiWebsocketService, - private route: ActivatedRoute, - private router: Router, - private examParticipationService: ExamParticipationService, - private modelingSubmissionService: ModelingSubmissionService, - private programmingSubmissionService: ProgrammingSubmissionService, - private textSubmissionService: TextSubmissionService, - private serverDateService: ArtemisServerDateService, - private translateService: TranslateService, - private alertService: AlertService, - private courseExerciseService: CourseExerciseService, - private liveEventsService: ExamParticipationLiveEventsService, - private courseService: CourseManagementService, - private courseStorageService: CourseStorageService, - private examExerciseUpdateService: ExamExerciseUpdateService, - private examManagementService: ExamManagementService, - private profileService: ProfileService, - ) { + constructor() { // show only one synchronization error every 5s this.errorSubscription = this.synchronizationAlert.pipe(throttleTime(5000)).subscribe(() => { this.alertService.error('artemisApp.examParticipation.saveSubmissionError'); diff --git a/src/main/webapp/app/exam/participate/exam-participation.module.ts b/src/main/webapp/app/exam/participate/exam-participation.module.ts index 2aac8a643f4f..2ba50e3dd5d1 100644 --- a/src/main/webapp/app/exam/participate/exam-participation.module.ts +++ b/src/main/webapp/app/exam/participate/exam-participation.module.ts @@ -64,7 +64,9 @@ const ENTITY_STATES = [...examParticipationState]; ArtemisSidebarModule, ExamNavigationSidebarComponent, ExamBarComponent, + ExamParticipationComponent, + ExamParticipationCoverComponent, + ExamExerciseOverviewPageComponent, ], - declarations: [ExamParticipationComponent, ExamParticipationCoverComponent, ExamExerciseOverviewPageComponent], }) export class ArtemisExamParticipationModule {} diff --git a/src/main/webapp/app/exam/participate/exam-participation.route.ts b/src/main/webapp/app/exam/participate/exam-participation.route.ts index a104b0ad964e..dfced7d039e0 100644 --- a/src/main/webapp/app/exam/participate/exam-participation.route.ts +++ b/src/main/webapp/app/exam/participate/exam-participation.route.ts @@ -1,15 +1,13 @@ import { Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { ExamParticipationComponent } from 'app/exam/participate/exam-participation.component'; + import { PendingChangesGuard } from 'app/shared/guard/pending-changes.guard'; import { Authority } from 'app/shared/constants/authority.constants'; -import { GradingKeyOverviewComponent } from 'app/grading-system/grading-key-overview/grading-key-overview.component'; -import { ExampleSolutionComponent } from 'app/exercises/shared/example-solution/example-solution.component'; export const examParticipationRoute: Routes = [ { path: '', - component: ExamParticipationComponent, + loadComponent: () => import('app/exam/participate/exam-participation.component').then((m) => m.ExamParticipationComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.exam.title', @@ -18,7 +16,7 @@ export const examParticipationRoute: Routes = [ }, { path: 'overview/grading-key', - component: GradingKeyOverviewComponent, + loadComponent: () => import('app/grading-system/grading-key-overview/grading-key-overview.component').then((m) => m.GradingKeyOverviewComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.exam.title', @@ -27,7 +25,7 @@ export const examParticipationRoute: Routes = [ }, { path: 'overview/bonus-grading-key', - component: GradingKeyOverviewComponent, + loadComponent: () => import('app/grading-system/grading-key-overview/grading-key-overview.component').then((m) => m.GradingKeyOverviewComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.exam.title', @@ -37,7 +35,7 @@ export const examParticipationRoute: Routes = [ }, { path: 'test-exam/:studentExamId', - component: ExamParticipationComponent, + loadComponent: () => import('app/exam/participate/exam-participation.component').then((m) => m.ExamParticipationComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.exam.title', @@ -47,7 +45,7 @@ export const examParticipationRoute: Routes = [ }, { path: 'exercises/:exerciseId/example-solution', - component: ExampleSolutionComponent, + loadComponent: () => import('app/exercises/shared/example-solution/example-solution.component').then((m) => m.ExampleSolutionComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.exam.title', diff --git a/src/main/webapp/app/exam/participate/exam-participation.service.ts b/src/main/webapp/app/exam/participate/exam-participation.service.ts index 5e125f6b1288..4add2a0fd022 100644 --- a/src/main/webapp/app/exam/participate/exam-participation.service.ts +++ b/src/main/webapp/app/exam/participate/exam-participation.service.ts @@ -1,5 +1,5 @@ import { HttpClient, HttpErrorResponse, HttpParams, HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { faLightbulb } from '@fortawesome/free-solid-svg-icons'; import { captureException } from '@sentry/angular'; import { Exam } from 'app/entities/exam/exam.model'; @@ -22,6 +22,10 @@ export type ButtonTooltipType = 'submitted' | 'submittedSubmissionLimitReached' @Injectable({ providedIn: 'root' }) export class ExamParticipationService { + private httpClient = inject(HttpClient); + private localStorageService = inject(LocalStorageService); + private sessionStorage = inject(SessionStorageService); + public currentlyLoadedStudentExam = new Subject(); private examIsStartedSubject = new BehaviorSubject(false); @@ -37,12 +41,6 @@ export class ExamParticipationService { return `api/courses/${courseId}/exams/${examId}`; } - constructor( - private httpClient: HttpClient, - private localStorageService: LocalStorageService, - private sessionStorage: SessionStorageService, - ) {} - private static getLocalStorageKeyForStudentExam(courseId: number, examId: number): string { const prefix = 'artemis_student_exam'; return `${prefix}_${courseId}_${examId}`; diff --git a/src/main/webapp/app/exam/participate/exam-start-information/exam-start-information.component.ts b/src/main/webapp/app/exam/participate/exam-start-information/exam-start-information.component.ts index 3f02da6bab2b..6e56677edc85 100644 --- a/src/main/webapp/app/exam/participate/exam-start-information/exam-start-information.component.ts +++ b/src/main/webapp/app/exam/participate/exam-start-information/exam-start-information.component.ts @@ -10,7 +10,6 @@ import { SafeHtml } from '@angular/platform-browser'; @Component({ selector: 'jhi-exam-start-information', - standalone: true, imports: [ArtemisSharedModule, ArtemisSharedComponentModule, InformationBoxComponent, ArtemisExamSharedModule], templateUrl: './exam-start-information.component.html', }) diff --git a/src/main/webapp/app/exam/participate/exercises/exam-exercise-update-highlighter/exam-exercise-update-highlighter.component.ts b/src/main/webapp/app/exam/participate/exercises/exam-exercise-update-highlighter/exam-exercise-update-highlighter.component.ts index e841254ef587..35ad5bd48745 100644 --- a/src/main/webapp/app/exam/participate/exercises/exam-exercise-update-highlighter/exam-exercise-update-highlighter.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/exam-exercise-update-highlighter/exam-exercise-update-highlighter.component.ts @@ -1,16 +1,20 @@ -import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, inject } from '@angular/core'; import { Subscription } from 'rxjs'; import { ExamExerciseUpdateService } from 'app/exam/manage/exam-exercise-update.service'; import { Exercise, ExerciseType } from 'app/entities/exercise.model'; import { htmlForMarkdown } from 'app/shared/util/markdown.conversion.util'; import diff from 'html-diff-ts'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-exam-exercise-update-highlighter', templateUrl: './exam-exercise-update-highlighter.component.html', styleUrls: ['./exam-exercise-update-highlighter.component.scss'], + imports: [ArtemisTranslatePipe], }) export class ExamExerciseUpdateHighlighterComponent implements OnInit, OnDestroy { + private examExerciseUpdateService = inject(ExamExerciseUpdateService); + subscriptionToLiveExamExerciseUpdates: Subscription; themeSubscription: Subscription; updatedProblemStatementHTML: string; @@ -23,8 +27,6 @@ export class ExamExerciseUpdateHighlighterComponent implements OnInit, OnDestroy @Output() problemStatementUpdateEvent: EventEmitter = new EventEmitter(); - constructor(private examExerciseUpdateService: ExamExerciseUpdateService) {} - ngOnInit(): void { this.subscriptionToLiveExamExerciseUpdates = this.examExerciseUpdateService.currentExerciseIdAndProblemStatement.subscribe((update) => { if (update) { diff --git a/src/main/webapp/app/exam/participate/exercises/exam-exercise-update-highlighter/exam-exercise-update-highlighter.module.ts b/src/main/webapp/app/exam/participate/exercises/exam-exercise-update-highlighter/exam-exercise-update-highlighter.module.ts index 30e5255744b1..e915682f2001 100644 --- a/src/main/webapp/app/exam/participate/exercises/exam-exercise-update-highlighter/exam-exercise-update-highlighter.module.ts +++ b/src/main/webapp/app/exam/participate/exercises/exam-exercise-update-highlighter/exam-exercise-update-highlighter.module.ts @@ -3,8 +3,7 @@ import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; import { ExamExerciseUpdateHighlighterComponent } from 'app/exam/participate/exercises/exam-exercise-update-highlighter/exam-exercise-update-highlighter.component'; @NgModule({ - declarations: [ExamExerciseUpdateHighlighterComponent], - imports: [ArtemisSharedCommonModule], + imports: [ArtemisSharedCommonModule, ExamExerciseUpdateHighlighterComponent], exports: [ExamExerciseUpdateHighlighterComponent], }) export class ExamExerciseUpdateHighlighterModule {} diff --git a/src/main/webapp/app/exam/participate/exercises/exam-page.component.ts b/src/main/webapp/app/exam/participate/exercises/exam-page.component.ts index d587462715b6..cf2130c6236a 100644 --- a/src/main/webapp/app/exam/participate/exercises/exam-page.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/exam-page.component.ts @@ -1,8 +1,8 @@ -import { ChangeDetectorRef, Directive } from '@angular/core'; +import { ChangeDetectorRef, Directive, inject } from '@angular/core'; @Directive() export abstract class ExamPageComponent { - protected constructor(protected changeDetectorReference: ChangeDetectorRef) {} + protected changeDetectorReference = inject(ChangeDetectorRef); /** * Should be called when the component becomes active / visible. It activates Angular's change detection for this component. diff --git a/src/main/webapp/app/exam/participate/exercises/exam-submission-components.module.ts b/src/main/webapp/app/exam/participate/exercises/exam-submission-components.module.ts index 72fb6667e806..9d374e6f90b0 100644 --- a/src/main/webapp/app/exam/participate/exercises/exam-submission-components.module.ts +++ b/src/main/webapp/app/exam/participate/exercises/exam-submission-components.module.ts @@ -21,13 +21,6 @@ import { ArtemisProgrammingSubmissionPolicyStatusModule } from 'app/exercises/pr import { ExerciseSaveButtonComponent } from './exercise-save-button/exercise-save-button.component'; @NgModule({ - declarations: [ - FileUploadExamSubmissionComponent, - QuizExamSubmissionComponent, - ProgrammingExamSubmissionComponent, - TextExamSubmissionComponent, - ModelingExamSubmissionComponent, - ], imports: [ CommonModule, ArtemisSharedModule, @@ -44,6 +37,11 @@ import { ExerciseSaveButtonComponent } from './exercise-save-button/exercise-sav ArtemisProgrammingSubmissionPolicyStatusModule, ExamExerciseUpdateHighlighterModule, ExerciseSaveButtonComponent, + FileUploadExamSubmissionComponent, + QuizExamSubmissionComponent, + ProgrammingExamSubmissionComponent, + TextExamSubmissionComponent, + ModelingExamSubmissionComponent, ], exports: [FileUploadExamSubmissionComponent, QuizExamSubmissionComponent, ProgrammingExamSubmissionComponent, TextExamSubmissionComponent, ModelingExamSubmissionComponent], }) diff --git a/src/main/webapp/app/exam/participate/exercises/exercise-overview-page/exam-exercise-overview-page.component.ts b/src/main/webapp/app/exam/participate/exercises/exercise-overview-page/exam-exercise-overview-page.component.ts index 483891aba2c1..3d6d75aaca8b 100644 --- a/src/main/webapp/app/exam/participate/exercises/exercise-overview-page/exam-exercise-overview-page.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/exercise-overview-page/exam-exercise-overview-page.component.ts @@ -1,35 +1,36 @@ -import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, inject } from '@angular/core'; import { Exercise, ExerciseType, getIcon, getIconTooltip } from 'app/entities/exercise.model'; import { ExamPageComponent } from 'app/exam/participate/exercises/exam-page.component'; import { StudentExam } from 'app/entities/student-exam.model'; import { ExamExerciseOverviewItem } from 'app/entities/exam/exam-exercise-overview-item.model'; import { ButtonTooltipType, ExamParticipationService } from 'app/exam/participate/exam-participation.service'; import { faHourglassHalf } from '@fortawesome/free-solid-svg-icons'; -import { facSaveSuccess, facSaveWarning } from '../../../../../content/icons/icons'; import { ExerciseButtonStatus } from 'app/exam/participate/exam-navigation-sidebar/exam-navigation-sidebar.component'; +import { facSaveSuccess, facSaveWarning } from 'app/icons/icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { NgClass } from '@angular/common'; +import { UpdatingResultComponent } from 'app/exercises/shared/result/updating-result.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-exam-exercise-overview-page', templateUrl: './exam-exercise-overview-page.component.html', styleUrls: ['./exam-exercise-overview-page.scss', '../../exam-navigation-sidebar/exam-navigation-sidebar.component.scss'], + imports: [TranslateDirective, FaIconComponent, NgbTooltip, NgClass, UpdatingResultComponent, ArtemisTranslatePipe], }) export class ExamExerciseOverviewPageComponent extends ExamPageComponent implements OnInit, OnChanges { + private examParticipationService = inject(ExamParticipationService); + @Input() studentExam: StudentExam; @Output() onPageChanged = new EventEmitter<{ overViewChange: boolean; exercise: Exercise; forceSave: boolean }>(); getIcon = getIcon; getIconTooltip = getIconTooltip; - readonly ExerciseButtonStatus = ExerciseButtonStatus; showResultWidth = 10; examExerciseOverviewItems: ExamExerciseOverviewItem[] = []; - constructor( - protected changeDetectorReference: ChangeDetectorRef, - private examParticipationService: ExamParticipationService, - ) { - super(changeDetectorReference); - } - ngOnInit() { this.studentExam.exercises?.forEach((exercise) => { const item = new ExamExerciseOverviewItem(); diff --git a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts index 01e627a6941f..74fb67154b1e 100644 --- a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts @@ -1,7 +1,7 @@ import { Component, input, output } from '@angular/core'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { faFloppyDisk } from '@fortawesome/free-solid-svg-icons'; -import { facSaveSuccess } from '../../../../../content/icons/icons'; +import { facSaveSuccess } from 'app/icons/icons'; import { Submission } from 'app/entities/submission.model'; import { TranslateDirective } from 'app/shared/language/translate.directive'; @@ -9,7 +9,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; selector: 'jhi-exercise-save-button', templateUrl: './exercise-save-button.component.html', styleUrls: ['./exercise-save-button.component.scss'], - standalone: true, imports: [FaIconComponent, TranslateDirective], }) export class ExerciseSaveButtonComponent { diff --git a/src/main/webapp/app/exam/participate/exercises/file-upload/file-upload-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/file-upload/file-upload-exam-submission.component.ts index cec4402861c4..3f16c4b89c92 100644 --- a/src/main/webapp/app/exam/participate/exercises/file-upload/file-upload-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/file-upload/file-upload-exam-submission.component.ts @@ -1,16 +1,12 @@ -import { ChangeDetectorRef, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; -import { Location } from '@angular/common'; +import { Component, ElementRef, Input, OnInit, ViewChild, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; -import { ActivatedRoute } from '@angular/router'; import { AlertService } from 'app/core/util/alert.service'; import dayjs from 'dayjs/esm'; import { StudentParticipation } from 'app/entities/participation/student-participation.model'; import { FileUploadSubmissionService } from 'app/exercises/file-upload/participate/file-upload-submission.service'; -import { FileUploaderService } from 'app/shared/http/file-uploader.service'; import { MAX_SUBMISSION_FILE_SIZE } from 'app/shared/constants/input.constants'; import { FileUploadExercise } from 'app/entities/file-upload-exercise.model'; import { FileService } from 'app/shared/http/file.service'; -import { ResultService } from 'app/exercises/shared/result/result.service'; import { FileUploadSubmission } from 'app/entities/file-upload-submission.model'; import { ButtonType } from 'app/shared/components/button.component'; import { Result } from 'app/entities/result.model'; @@ -20,22 +16,40 @@ import { Submission } from 'app/entities/submission.model'; import { faListAlt } from '@fortawesome/free-regular-svg-icons'; import { SubmissionVersion } from 'app/entities/submission-version.model'; import { htmlForMarkdown } from 'app/shared/util/markdown.conversion.util'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { IncludedInScoreBadgeComponent } from 'app/exercises/shared/exercise-headers/included-in-score-badge.component'; +import { ResizeableContainerComponent } from 'app/shared/resizeable-container/resizeable-container.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ExamExerciseUpdateHighlighterComponent } from '../exam-exercise-update-highlighter/exam-exercise-update-highlighter.component'; +import { UpperCasePipe } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-file-upload-submission-exam', templateUrl: './file-upload-exam-submission.component.html', providers: [{ provide: ExamSubmissionComponent, useExisting: FileUploadExamSubmissionComponent }], - // change deactivation must be triggered manually + imports: [ + TranslateDirective, + IncludedInScoreBadgeComponent, + ResizeableContainerComponent, + FaIconComponent, + ExamExerciseUpdateHighlighterComponent, + UpperCasePipe, + ArtemisTranslatePipe, + ], }) export class FileUploadExamSubmissionComponent extends ExamSubmissionComponent implements OnInit { + private fileUploadSubmissionService = inject(FileUploadSubmissionService); + private alertService = inject(AlertService); + private translateService = inject(TranslateService); + private fileService = inject(FileService); + exerciseType = ExerciseType.FILE_UPLOAD; @ViewChild('fileInput', { static: false }) fileInput: ElementRef; - @Input() - studentSubmission: FileUploadSubmission; - @Input() - exercise: FileUploadExercise; + @Input() studentSubmission: FileUploadSubmission; + @Input() exercise: FileUploadExercise; problemStatementHtml: string; submittedFileName: string; @@ -52,20 +66,6 @@ export class FileUploadExamSubmissionComponent extends ExamSubmissionComponent i // Icons farListAlt = faListAlt; - constructor( - private route: ActivatedRoute, - private fileUploadSubmissionService: FileUploadSubmissionService, - private fileUploaderService: FileUploaderService, - private resultService: ResultService, - private alertService: AlertService, - private location: Location, - private translateService: TranslateService, - private fileService: FileService, - changeDetectorReference: ChangeDetectorRef, - ) { - super(changeDetectorReference); - } - /** * Initializes data for file upload editor */ diff --git a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts index d16f4d56ff6d..fb5f8c062970 100644 --- a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, ViewChild, input, output } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnInit, ViewChild, input, output } from '@angular/core'; import { UMLModel } from '@ls1intum/apollon'; import dayjs from 'dayjs/esm'; import { ModelingSubmission } from 'app/entities/modeling-submission.model'; @@ -10,6 +10,14 @@ import { Exercise, ExerciseType, IncludedInOverallScore } from 'app/entities/exe import { faListAlt } from '@fortawesome/free-regular-svg-icons'; import { SubmissionVersion } from 'app/entities/submission-version.model'; import { htmlForMarkdown } from 'app/shared/util/markdown.conversion.util'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { IncludedInScoreBadgeComponent } from 'app/exercises/shared/exercise-headers/included-in-score-badge.component'; +import { ExerciseSaveButtonComponent } from '../exercise-save-button/exercise-save-button.component'; +import { ResizeableContainerComponent } from 'app/shared/resizeable-container/resizeable-container.component'; +import { FullscreenComponent } from 'app/shared/fullscreen/fullscreen.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ExamExerciseUpdateHighlighterComponent } from '../exam-exercise-update-highlighter/exam-exercise-update-highlighter.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-modeling-submission-exam', @@ -18,20 +26,28 @@ import { htmlForMarkdown } from 'app/shared/util/markdown.conversion.util'; styleUrls: ['./modeling-exam-submission.component.scss'], // change deactivation must be triggered manually changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + TranslateDirective, + IncludedInScoreBadgeComponent, + ExerciseSaveButtonComponent, + ResizeableContainerComponent, + FullscreenComponent, + ModelingEditorComponent, + FaIconComponent, + ExamExerciseUpdateHighlighterComponent, + ArtemisTranslatePipe, + ], }) export class ModelingExamSubmissionComponent extends ExamSubmissionComponent implements OnInit { exerciseType = ExerciseType.MODELING; - @ViewChild(ModelingEditorComponent, { static: false }) - modelingEditor: ModelingEditorComponent; + @ViewChild(ModelingEditorComponent, { static: false }) modelingEditor: ModelingEditorComponent; // IMPORTANT: this reference must be contained in this.studentParticipation.submissions[0] otherwise the parent component will not be able to react to changes - @Input() - studentSubmission: ModelingSubmission; + @Input() studentSubmission: ModelingSubmission; problemStatementHtml: string; - @Input() - exercise: ModelingExercise; + @Input() exercise: ModelingExercise; umlModel: UMLModel; // input model for Apollon+ // explicitly needed to track if submission.isSynced is changed, otherwise component @@ -46,10 +62,6 @@ export class ModelingExamSubmissionComponent extends ExamSubmissionComponent imp // Icons protected readonly faListAlt = faListAlt; - constructor(changeDetectorReference: ChangeDetectorRef) { - super(changeDetectorReference); - } - ngOnInit(): void { // show submission answers in UI this.problemStatementHtml = htmlForMarkdown(this.exercise?.problemStatement); @@ -122,7 +134,7 @@ export class ModelingExamSubmissionComponent extends ExamSubmissionComponent imp } // eslint-disable-next-line @typescript-eslint/no-unused-vars - modelChanged(model: UMLModel) { + modelChanged(_model: UMLModel) { this.studentSubmission.isSynced = false; } diff --git a/src/main/webapp/app/exam/participate/exercises/programming/programming-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/programming/programming-exam-submission.component.ts index 7b18cda9e20a..713bbda62778 100644 --- a/src/main/webapp/app/exam/participate/exercises/programming/programming-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/programming/programming-exam-submission.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, Input, OnChanges, OnInit, ViewChild } from '@angular/core'; +import { Component, Input, OnChanges, OnInit, ViewChild, inject } from '@angular/core'; import { Submission } from 'app/entities/submission.model'; import { ExamSubmissionComponent } from 'app/exam/participate/exercises/exam-submission.component'; import { ProgrammingExerciseStudentParticipation } from 'app/entities/participation/programming-exercise-student-participation.model'; @@ -19,6 +19,13 @@ import { CodeEditorRepositoryService, } from 'app/exercises/programming/shared/code-editor/service/code-editor-repository.service'; import { SubmissionVersion } from 'app/entities/submission-version.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { IncludedInScoreBadgeComponent } from 'app/exercises/shared/exercise-headers/included-in-score-badge.component'; +import { ProgrammingSubmissionPolicyStatusComponent } from 'app/exercises/programming/participate/programming-submission-policy-status'; +import { ExerciseDetailsStudentActionsComponent } from 'app/overview/exercise-details/exercise-details-student-actions.component'; +import { CodeEditorRepositoryIsLockedComponent } from 'app/exercises/programming/shared/code-editor/layout/code-editor-repository-is-locked.component'; +import { UpdatingResultComponent } from 'app/exercises/shared/result/updating-result.component'; +import { ProgrammingExerciseStudentTriggerBuildButtonComponent } from 'app/exercises/programming/shared/actions/programming-exercise-student-trigger-build-button.component'; @Component({ selector: 'jhi-programming-submission-exam', @@ -32,20 +39,30 @@ import { SubmissionVersion } from 'app/entities/submission-version.model'; CodeEditorRepositoryService, ], styleUrls: ['./programming-exam-submission.component.scss'], + imports: [ + TranslateDirective, + IncludedInScoreBadgeComponent, + CodeEditorContainerComponent, + ProgrammingSubmissionPolicyStatusComponent, + ExerciseDetailsStudentActionsComponent, + CodeEditorRepositoryIsLockedComponent, + UpdatingResultComponent, + ProgrammingExerciseStudentTriggerBuildButtonComponent, + ProgrammingExerciseInstructionComponent, + ], }) export class ProgrammingExamSubmissionComponent extends ExamSubmissionComponent implements OnChanges, OnInit { + private domainService = inject(DomainService); + exerciseType = ExerciseType.PROGRAMMING; @ViewChild(CodeEditorContainerComponent, { static: false }) codeEditorContainer: CodeEditorContainerComponent; @ViewChild(ProgrammingExerciseInstructionComponent, { static: false }) instructions: ProgrammingExerciseInstructionComponent; // IMPORTANT: this reference must be activeExercise.studentParticipation[0] otherwise the parent component will not be able to react to change - @Input() - studentParticipation: ProgrammingExerciseStudentParticipation; - @Input() - exercise: ProgrammingExercise; - @Input() - courseId: number; + @Input() studentParticipation: ProgrammingExerciseStudentParticipation; + @Input() exercise: ProgrammingExercise; + @Input() courseId: number; showEditorInstructions = true; hasSubmittedOnce = false; @@ -75,13 +92,6 @@ export class ProgrammingExamSubmissionComponent extends ExamSubmissionComponent readonly ButtonType = ButtonType; readonly ButtonSize = ButtonSize; - constructor( - private domainService: DomainService, - changeDetectorReference: ChangeDetectorRef, - ) { - super(changeDetectorReference); - } - /** * On init set up the route param subscription. * Will load the participation according to participation Id with the latest result and result details. diff --git a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts index 26aa88a762d5..deff24ba6ecc 100644 --- a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, Input, OnInit, QueryList, ViewChildren, output } from '@angular/core'; +import { Component, Input, OnInit, QueryList, ViewChildren, inject, output } from '@angular/core'; import { Exercise, ExerciseType, IncludedInOverallScore } from 'app/entities/exercise.model'; import { AbstractQuizSubmission } from 'app/entities/quiz/abstract-quiz-exam-submission.model'; import { AnswerOption } from 'app/entities/quiz/answer-option.model'; @@ -20,14 +20,33 @@ import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; import { ArtemisQuizService } from 'app/shared/quiz/quiz.service'; import { cloneDeep } from 'lodash-es'; import * as smoothscroll from 'smoothscroll-polyfill'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { IncludedInScoreBadgeComponent } from 'app/exercises/shared/exercise-headers/included-in-score-badge.component'; +import { ExerciseSaveButtonComponent } from '../exercise-save-button/exercise-save-button.component'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { NgClass } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-quiz-submission-exam', templateUrl: './quiz-exam-submission.component.html', providers: [{ provide: ExamSubmissionComponent, useExisting: QuizExamSubmissionComponent }], styleUrls: ['./quiz-exam-submission.component.scss'], + imports: [ + TranslateDirective, + IncludedInScoreBadgeComponent, + ExerciseSaveButtonComponent, + NgbTooltip, + NgClass, + MultipleChoiceQuestionComponent, + DragAndDropQuestionComponent, + ShortAnswerQuestionComponent, + ArtemisTranslatePipe, + ], }) export class QuizExamSubmissionComponent extends ExamSubmissionComponent implements OnInit { + private quizService = inject(ArtemisQuizService); + exerciseType = ExerciseType.QUIZ; // make constants available to html for comparison @@ -38,14 +57,9 @@ export class QuizExamSubmissionComponent extends ExamSubmissionComponent impleme readonly ButtonType = ButtonType; readonly IncludedInOverallScore = IncludedInOverallScore; - @ViewChildren(MultipleChoiceQuestionComponent) - mcQuestionComponents: QueryList; - - @ViewChildren(DragAndDropQuestionComponent) - dndQuestionComponents: QueryList; - - @ViewChildren(ShortAnswerQuestionComponent) - shortAnswerQuestionComponents: QueryList; + @ViewChildren(MultipleChoiceQuestionComponent) mcQuestionComponents: QueryList; + @ViewChildren(DragAndDropQuestionComponent) dndQuestionComponents: QueryList; + @ViewChildren(ShortAnswerQuestionComponent) shortAnswerQuestionComponents: QueryList; // IMPORTANT: this reference must be contained in this.studentParticipation.submissions[0] otherwise the parent component will not be able to react to changes @Input() studentSubmission: AbstractQuizSubmission; @@ -59,15 +73,8 @@ export class QuizExamSubmissionComponent extends ExamSubmissionComponent impleme dragAndDropMappings = new Map(); shortAnswerSubmittedTexts = new Map(); - constructor( - private quizService: ArtemisQuizService, - changeDetectorReference: ChangeDetectorRef, - ) { - super(changeDetectorReference); - smoothscroll.polyfill(); - } - ngOnInit(): void { + smoothscroll.polyfill(); this.initQuiz(); this.updateViewFromSubmission(); } diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts index cb2dc3c0fd51..145b29c4cc2e 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, Input, OnInit, output } from '@angular/core'; +import { Component, Input, OnInit, inject, output } from '@angular/core'; import { TextEditorService } from 'app/exercises/text/participate/text-editor.service'; import { Subject } from 'rxjs'; import { TextSubmission } from 'app/entities/text/text-submission.model'; @@ -10,21 +10,40 @@ import { faListAlt } from '@fortawesome/free-solid-svg-icons'; import { MAX_SUBMISSION_TEXT_LENGTH } from 'app/shared/constants/input.constants'; import { SubmissionVersion } from 'app/entities/submission-version.model'; import { htmlForMarkdown } from 'app/shared/util/markdown.conversion.util'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { IncludedInScoreBadgeComponent } from 'app/exercises/shared/exercise-headers/included-in-score-badge.component'; +import { ExerciseSaveButtonComponent } from '../exercise-save-button/exercise-save-button.component'; +import { ResizeableContainerComponent } from 'app/shared/resizeable-container/resizeable-container.component'; +import { FormsModule } from '@angular/forms'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ExamExerciseUpdateHighlighterComponent } from '../exam-exercise-update-highlighter/exam-exercise-update-highlighter.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-text-editor-exam', templateUrl: './text-exam-submission.component.html', providers: [{ provide: ExamSubmissionComponent, useExisting: TextExamSubmissionComponent }], styleUrls: ['./text-exam-submission.component.scss'], + imports: [ + TranslateDirective, + IncludedInScoreBadgeComponent, + ExerciseSaveButtonComponent, + ResizeableContainerComponent, + FormsModule, + FaIconComponent, + ExamExerciseUpdateHighlighterComponent, + ArtemisTranslatePipe, + ], }) export class TextExamSubmissionComponent extends ExamSubmissionComponent implements OnInit { + private textService = inject(TextEditorService); + private stringCountService = inject(StringCountService); + exerciseType = ExerciseType.TEXT; // IMPORTANT: this reference must be contained in this.studentParticipation.submissions[0] otherwise the parent component will not be able to react to changes - @Input() - studentSubmission: TextSubmission; - @Input() - exercise: Exercise; + @Input() studentSubmission: TextSubmission; + @Input() exercise: Exercise; saveCurrentExercise = output(); @@ -39,14 +58,6 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme // Icons protected readonly faListAlt = faListAlt; - constructor( - private textService: TextEditorService, - private stringCountService: StringCountService, - changeDetectorReference: ChangeDetectorRef, - ) { - super(changeDetectorReference); - } - ngOnInit(): void { // show submission answers in UI this.problemStatementHtml = htmlForMarkdown(this.exercise?.problemStatement); diff --git a/src/main/webapp/app/exam/participate/general-information/exam-general-information.component.html b/src/main/webapp/app/exam/participate/general-information/exam-general-information.component.html index d6b4a6cd2c74..ec867ce353cd 100644 --- a/src/main/webapp/app/exam/participate/general-information/exam-general-information.component.html +++ b/src/main/webapp/app/exam/participate/general-information/exam-general-information.component.html @@ -119,7 +119,7 @@

+ } diff --git a/src/main/webapp/app/exam/participate/general-information/exam-general-information.component.ts b/src/main/webapp/app/exam/participate/general-information/exam-general-information.component.ts index 89dc3774bf64..bc540a923b88 100644 --- a/src/main/webapp/app/exam/participate/general-information/exam-general-information.component.ts +++ b/src/main/webapp/app/exam/participate/general-information/exam-general-information.component.ts @@ -2,12 +2,19 @@ import { Component, Input, OnChanges } from '@angular/core'; import { StudentExam } from 'app/entities/student-exam.model'; import { Exam } from 'app/entities/exam/exam.model'; import { endTime, examWorkingTime, getAdditionalWorkingTime, isExamOverMultipleDays } from 'app/exam/participate/exam.utils'; +import { StudentExamWorkingTimeComponent } from 'app/exam/shared/student-exam-working-time/student-exam-working-time.component'; +import { TestExamWorkingTimeComponent } from 'app/exam/shared/testExam-workingTime/test-exam-working-time.component'; import dayjs from 'dayjs/esm'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { ArtemisDurationFromSecondsPipe } from 'app/shared/pipes/artemis-duration-from-seconds.pipe'; @Component({ selector: 'jhi-exam-general-information', styleUrls: ['./exam-general-information.component.scss'], templateUrl: './exam-general-information.component.html', + imports: [TranslateDirective, StudentExamWorkingTimeComponent, TestExamWorkingTimeComponent, ArtemisDatePipe, ArtemisTranslatePipe, ArtemisDurationFromSecondsPipe], }) export class ExamGeneralInformationComponent implements OnChanges { @Input() exam: Exam; diff --git a/src/main/webapp/app/exam/participate/summary/collapsible-card.component.ts b/src/main/webapp/app/exam/participate/summary/collapsible-card.component.ts index 8fd6833375fe..6d1eeceb1933 100644 --- a/src/main/webapp/app/exam/participate/summary/collapsible-card.component.ts +++ b/src/main/webapp/app/exam/participate/summary/collapsible-card.component.ts @@ -1,10 +1,13 @@ import { Component, Input } from '@angular/core'; import { faAngleRight } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbCollapse } from '@ng-bootstrap/ng-bootstrap'; @Component({ selector: 'jhi-collapsible-card', templateUrl: './collapsible-card.component.html', styleUrls: ['../../../course/manage/course-exercise-card.component.scss', '../../../exercises/quiz/shared/quiz.scss', 'exam-result-summary.component.scss'], + imports: [FaIconComponent, NgbCollapse], }) export class CollapsibleCardComponent { @Input() isCardContentCollapsed: boolean; diff --git a/src/main/webapp/app/exam/participate/summary/exam-result-summary.component.ts b/src/main/webapp/app/exam/participate/summary/exam-result-summary.component.ts index dc3af180c411..e025f65567e7 100644 --- a/src/main/webapp/app/exam/participate/summary/exam-result-summary.component.ts +++ b/src/main/webapp/app/exam/participate/summary/exam-result-summary.component.ts @@ -1,8 +1,8 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { StudentExam } from 'app/entities/student-exam.model'; import { Exercise, ExerciseType, IncludedInOverallScore, getIcon } from 'app/entities/exercise.model'; import dayjs from 'dayjs/esm'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { ArtemisServerDateService } from 'app/shared/server-date.service'; import { Exam } from 'app/entities/exam/exam.model'; import { AssessmentType } from 'app/entities/assessment-type.model'; @@ -25,6 +25,23 @@ import { AlertService } from 'app/core/util/alert.service'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { isExamResultPublished } from 'app/exam/participate/exam.utils'; import { Course } from 'app/entities/course.model'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ExamGeneralInformationComponent } from '../general-information/exam-general-information.component'; +import { ExamResultOverviewComponent } from './result-overview/exam-result-overview.component'; +import { CollapsibleCardComponent } from './collapsible-card.component'; +import { ExamResultSummaryExerciseCardHeaderComponent } from './exercises/header/exam-result-summary-exercise-card-header.component'; +import { NgClass } from '@angular/common'; +import { ProgrammingExerciseExampleSolutionRepoDownloadComponent } from 'app/exercises/programming/shared/actions/programming-exercise-example-solution-repo-download.component'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ExampleSolutionComponent } from 'app/exercises/shared/example-solution/example-solution.component'; +import { TextExamSummaryComponent } from './exercises/text-exam-summary/text-exam-summary.component'; +import { ModelingExamSummaryComponent } from './exercises/modeling-exam-summary/modeling-exam-summary.component'; +import { QuizExamSummaryComponent } from './exercises/quiz-exam-summary/quiz-exam-summary.component'; +import { FileUploadExamSummaryComponent } from './exercises/file-upload-exam-summary/file-upload-exam-summary.component'; +import { ComplaintsStudentViewComponent } from 'app/complaints/complaints-for-students/complaints-student-view.component'; +import { ProgrammingExamSummaryComponent } from './exercises/programming-exam-summary/programming-exam-summary.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export type ResultSummaryExerciseInfo = { icon: IconProp; @@ -50,8 +67,35 @@ type StateBeforeResetting = { selector: 'jhi-exam-participation-summary', templateUrl: './exam-result-summary.component.html', styleUrls: ['../../../course/manage/course-exercise-card.component.scss', '../../../exercises/quiz/shared/quiz.scss', 'exam-result-summary.component.scss'], + imports: [ + FaIconComponent, + TranslateDirective, + ExamGeneralInformationComponent, + ExamResultOverviewComponent, + CollapsibleCardComponent, + ExamResultSummaryExerciseCardHeaderComponent, + NgClass, + RouterLink, + ProgrammingExerciseExampleSolutionRepoDownloadComponent, + NgbTooltip, + ExampleSolutionComponent, + TextExamSummaryComponent, + ModelingExamSummaryComponent, + QuizExamSummaryComponent, + FileUploadExamSummaryComponent, + ComplaintsStudentViewComponent, + ProgrammingExamSummaryComponent, + ArtemisTranslatePipe, + ], }) export class ExamResultSummaryComponent implements OnInit { + private route = inject(ActivatedRoute); + private serverDateService = inject(ArtemisServerDateService); + private themeService = inject(ThemeService); + private examParticipationService = inject(ExamParticipationService); + private plagiarismCasesService = inject(PlagiarismCasesService); + private alertService = inject(AlertService); + // make constants available to html for comparison readonly TEXT = ExerciseType.TEXT; readonly QUIZ = ExerciseType.QUIZ; @@ -132,15 +176,6 @@ export class ExamResultSummaryComponent implements OnInit { */ expandProblemStatement = false; - constructor( - private route: ActivatedRoute, - private serverDateService: ArtemisServerDateService, - private themeService: ThemeService, - private examParticipationService: ExamParticipationService, - private plagiarismCasesService: PlagiarismCasesService, - private alertService: AlertService, - ) {} - /** * Initialise the courseId from the current url */ diff --git a/src/main/webapp/app/exam/participate/summary/exam-result-summary.module.ts b/src/main/webapp/app/exam/participate/summary/exam-result-summary.module.ts index e3dada84b5e5..6ee8ac047277 100644 --- a/src/main/webapp/app/exam/participate/summary/exam-result-summary.module.ts +++ b/src/main/webapp/app/exam/participate/summary/exam-result-summary.module.ts @@ -57,8 +57,6 @@ import { NoDataComponent } from 'app/shared/no-data-component'; ArtemisFileUploadParticipationModule, ArtemisFeedbackModule, NoDataComponent, - ], - declarations: [ ExamResultSummaryComponent, ProgrammingExamSummaryComponent, ModelingExamSummaryComponent, diff --git a/src/main/webapp/app/exam/participate/summary/exercises/file-upload-exam-summary/file-upload-exam-summary.component.ts b/src/main/webapp/app/exam/participate/summary/exercises/file-upload-exam-summary/file-upload-exam-summary.component.ts index 0137462b144c..608f6e292c44 100644 --- a/src/main/webapp/app/exam/participate/summary/exercises/file-upload-exam-summary/file-upload-exam-summary.component.ts +++ b/src/main/webapp/app/exam/participate/summary/exercises/file-upload-exam-summary/file-upload-exam-summary.component.ts @@ -1,17 +1,16 @@ import { Component, Input } from '@angular/core'; import { FileUploadSubmission } from 'app/entities/file-upload-submission.model'; import { Exercise } from 'app/entities/exercise.model'; +import { FileUploadSubmissionComponent } from 'app/exercises/file-upload/participate/file-upload-submission.component'; @Component({ selector: 'jhi-file-upload-exam-summary', templateUrl: './file-upload-exam-summary.component.html', + imports: [FileUploadSubmissionComponent], }) export class FileUploadExamSummaryComponent { @Input() submission: FileUploadSubmission; - @Input() exercise: Exercise; - - @Input() expandProblemStatement?: boolean = false; - - @Input() isAfterResultsArePublished?: boolean = false; + @Input() expandProblemStatement = false; + @Input() isAfterResultsArePublished = false; } diff --git a/src/main/webapp/app/exam/participate/summary/exercises/header/exam-result-summary-exercise-card-header.component.ts b/src/main/webapp/app/exam/participate/summary/exercises/header/exam-result-summary-exercise-card-header.component.ts index 9002b2cdfe30..185360ff0a15 100644 --- a/src/main/webapp/app/exam/participate/summary/exercises/header/exam-result-summary-exercise-card-header.component.ts +++ b/src/main/webapp/app/exam/participate/summary/exercises/header/exam-result-summary-exercise-card-header.component.ts @@ -2,10 +2,15 @@ import { Component, Input } from '@angular/core'; import { Exercise } from 'app/entities/exercise.model'; import { ResultSummaryExerciseInfo } from 'app/exam/participate/summary/exam-result-summary.component'; import { SubmissionType } from 'app/entities/submission.model'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgClass } from '@angular/common'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-result-summary-exercise-card-header', templateUrl: './exam-result-summary-exercise-card-header.component.html', + imports: [FaIconComponent, NgClass, TranslateDirective, ArtemisTranslatePipe], }) export class ExamResultSummaryExerciseCardHeaderComponent { @Input() index: number; diff --git a/src/main/webapp/app/exam/participate/summary/exercises/modeling-exam-summary/modeling-exam-summary.component.ts b/src/main/webapp/app/exam/participate/summary/exercises/modeling-exam-summary/modeling-exam-summary.component.ts index b8cafb1dda8b..e582e40860b1 100644 --- a/src/main/webapp/app/exam/participate/summary/exercises/modeling-exam-summary/modeling-exam-summary.component.ts +++ b/src/main/webapp/app/exam/participate/summary/exercises/modeling-exam-summary/modeling-exam-summary.component.ts @@ -1,15 +1,17 @@ import { Component, Input } from '@angular/core'; import { ModelingSubmission } from 'app/entities/modeling-submission.model'; import { ModelingExercise } from 'app/entities/modeling-exercise.model'; +import { ModelingSubmissionComponent } from 'app/exercises/modeling/participate/modeling-submission.component'; @Component({ selector: 'jhi-modeling-exam-summary', templateUrl: './modeling-exam-summary.component.html', + imports: [ModelingSubmissionComponent], }) export class ModelingExamSummaryComponent { @Input() exercise: ModelingExercise; @Input() submission: ModelingSubmission; - @Input() isPrinting?: boolean = false; - @Input() expandProblemStatement?: boolean = false; - @Input() isAfterResultsArePublished?: boolean = false; + @Input() isPrinting = false; + @Input() expandProblemStatement = false; + @Input() isAfterResultsArePublished = false; } diff --git a/src/main/webapp/app/exam/participate/summary/exercises/programming-exam-summary/programming-exam-summary.component.ts b/src/main/webapp/app/exam/participate/summary/exercises/programming-exam-summary/programming-exam-summary.component.ts index 5ffdffc38018..6f0fcf20e189 100644 --- a/src/main/webapp/app/exam/participate/summary/exercises/programming-exam-summary/programming-exam-summary.component.ts +++ b/src/main/webapp/app/exam/participate/summary/exercises/programming-exam-summary/programming-exam-summary.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit, Optional } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { ProgrammingExerciseStudentParticipation } from 'app/entities/participation/programming-exercise-student-participation.model'; import { ProgrammingSubmission } from 'app/entities/programming/programming-submission.model'; @@ -12,15 +12,26 @@ import { ExerciseCacheService } from 'app/exercises/shared/exercise/exercise-cac import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { Result } from 'app/entities/result.model'; import { createCommitUrl } from 'app/exercises/programming/shared/utils/programming-exercise.utils'; -import { faCodeBranch } from '@fortawesome/free-solid-svg-icons'; import { Router } from '@angular/router'; import { PROFILE_LOCALVC } from 'app/app.constants'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CodeButtonComponent } from 'app/shared/components/code-button/code-button.component'; +import { FeedbackComponent } from 'app/exercises/shared/feedback/feedback.component'; +import { ProgrammingExerciseInstructionComponent } from 'app/exercises/programming/shared/instructions-render/programming-exercise-instruction.component'; +import { ComplaintsStudentViewComponent } from 'app/complaints/complaints-for-students/complaints-student-view.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-programming-exam-summary', templateUrl: './programming-exam-summary.component.html', + imports: [TranslateDirective, CodeButtonComponent, FeedbackComponent, ProgrammingExerciseInstructionComponent, ComplaintsStudentViewComponent, ArtemisTranslatePipe], }) export class ProgrammingExamSummaryComponent implements OnInit { + private exerciseService = inject(ExerciseService); + private exerciseCacheService = inject(ExerciseCacheService, { optional: true }); + private profileService = inject(ProfileService); + private router = inject(Router); + @Input() exercise: ProgrammingExercise; @Input() participation: ProgrammingExerciseStudentParticipation; @@ -53,18 +64,10 @@ export class ProgrammingExamSummaryComponent implements OnInit { commitUrl: string | undefined; commitHash: string | undefined; - faCodeBranch = faCodeBranch; routerLink: string; localVCEnabled = false; - constructor( - private exerciseService: ExerciseService, - @Optional() private exerciseCacheService: ExerciseCacheService, - private profileService: ProfileService, - private router: Router, - ) {} - ngOnInit() { this.routerLink = this.router.url; this.result = this.participation.results?.[0]; diff --git a/src/main/webapp/app/exam/participate/summary/exercises/quiz-exam-summary/quiz-exam-summary.component.ts b/src/main/webapp/app/exam/participate/summary/exercises/quiz-exam-summary/quiz-exam-summary.component.ts index 217925a8e230..1a549c38fc75 100644 --- a/src/main/webapp/app/exam/participate/summary/exercises/quiz-exam-summary/quiz-exam-summary.component.ts +++ b/src/main/webapp/app/exam/participate/summary/exercises/quiz-exam-summary/quiz-exam-summary.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnChanges } from '@angular/core'; +import { Component, Input, OnChanges, inject } from '@angular/core'; import dayjs from 'dayjs/esm'; import { QuizQuestionType } from 'app/entities/quiz/quiz-question.model'; import { QuizSubmission } from 'app/entities/quiz/quiz-submission.model'; @@ -8,18 +8,24 @@ import { ShortAnswerSubmittedText } from 'app/entities/quiz/short-answer-submitt import { MultipleChoiceSubmittedAnswer } from 'app/entities/quiz/multiple-choice-submitted-answer.model'; import { DragAndDropSubmittedAnswer } from 'app/entities/quiz/drag-and-drop-submitted-answer.model'; import { ShortAnswerSubmittedAnswer } from 'app/entities/quiz/short-answer-submitted-answer.model'; -import { QuizExerciseService } from 'app/exercises/quiz/manage/quiz-exercise.service'; import { Exam } from 'app/entities/exam/exam.model'; import { ArtemisServerDateService } from 'app/shared/server-date.service'; import { Result } from 'app/entities/result.model'; import { roundValueSpecifiedByCourseSettings } from 'app/shared/util/utils'; import { QuizParticipation } from 'app/entities/quiz/quiz-participation.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { MultipleChoiceQuestionComponent } from 'app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-question.component'; +import { DragAndDropQuestionComponent } from 'app/exercises/quiz/shared/questions/drag-and-drop-question/drag-and-drop-question.component'; +import { ShortAnswerQuestionComponent } from 'app/exercises/quiz/shared/questions/short-answer-question/short-answer-question.component'; @Component({ selector: 'jhi-quiz-exam-summary', templateUrl: './quiz-exam-summary.component.html', + imports: [TranslateDirective, MultipleChoiceQuestionComponent, DragAndDropQuestionComponent, ShortAnswerQuestionComponent], }) export class QuizExamSummaryComponent implements OnChanges { + private serverDateService = inject(ArtemisServerDateService); + readonly DRAG_AND_DROP = QuizQuestionType.DRAG_AND_DROP; readonly MULTIPLE_CHOICE = QuizQuestionType.MULTIPLE_CHOICE; readonly SHORT_ANSWER = QuizQuestionType.SHORT_ANSWER; @@ -28,25 +34,13 @@ export class QuizExamSummaryComponent implements OnChanges { dragAndDropMappings = new Map(); shortAnswerSubmittedTexts = new Map(); - @Input() - quizParticipation: QuizParticipation; - - @Input() - submission: QuizSubmission; - - @Input() - resultsPublished: boolean; - - @Input() - exam: Exam; + @Input() quizParticipation: QuizParticipation; + @Input() submission: QuizSubmission; + @Input() resultsPublished: boolean; + @Input() exam: Exam; result?: Result; - constructor( - private exerciseService: QuizExerciseService, - private serverDateService: ArtemisServerDateService, - ) {} - ngOnChanges(): void { this.updateViewFromSubmission(); if (this.quizParticipation.studentParticipations) { diff --git a/src/main/webapp/app/exam/participate/summary/exercises/text-exam-summary/text-exam-summary.component.ts b/src/main/webapp/app/exam/participate/summary/exercises/text-exam-summary/text-exam-summary.component.ts index a1dcf5c9de34..b5ab25b05217 100644 --- a/src/main/webapp/app/exam/participate/summary/exercises/text-exam-summary/text-exam-summary.component.ts +++ b/src/main/webapp/app/exam/participate/summary/exercises/text-exam-summary/text-exam-summary.component.ts @@ -1,10 +1,12 @@ import { Component, Input } from '@angular/core'; import { TextSubmission } from 'app/entities/text/text-submission.model'; import { Exercise } from 'app/entities/exercise.model'; +import { TextEditorComponent } from 'app/exercises/text/participate/text-editor.component'; @Component({ selector: 'jhi-text-exam-summary', templateUrl: './text-exam-summary.component.html', + imports: [TextEditorComponent], }) export class TextExamSummaryComponent { @Input() exercise: Exercise; diff --git a/src/main/webapp/app/exam/participate/summary/result-overview/exam-result-overview.component.ts b/src/main/webapp/app/exam/participate/summary/result-overview/exam-result-overview.component.ts index 86b3ae75d78a..45f6c12b84d0 100644 --- a/src/main/webapp/app/exam/participate/summary/result-overview/exam-result-overview.component.ts +++ b/src/main/webapp/app/exam/participate/summary/result-overview/exam-result-overview.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, Input, OnChanges, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, Input, OnChanges, OnInit, inject } from '@angular/core'; import { IncludedInOverallScore } from 'app/entities/exercise.model'; import { ArtemisServerDateService } from 'app/shared/server-date.service'; import { ExerciseService } from 'app/exercises/shared/exercise/exercise.service'; @@ -11,6 +11,13 @@ import { roundScorePercentSpecifiedByCourseSettings } from 'app/shared/util/util import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { captureException } from '@sentry/angular'; import { isExamResultPublished } from 'app/exam/participate/exam.utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CollapsibleCardComponent } from '../collapsible-card.component'; +import { NgClass } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NoDataComponent } from 'app/shared/no-data-component'; +import { GradingKeyTableComponent } from 'app/grading-system/grading-key-overview/grading-key/grading-key-table.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; type ExerciseInfo = { icon: IconProp; @@ -24,8 +31,13 @@ type ResultOverviewSection = 'grading-table' | 'grading-key' | 'bonus-grading-ke selector: 'jhi-exam-result-overview', styleUrls: ['./exam-result-overview.component.scss'], templateUrl: './exam-result-overview.component.html', + imports: [TranslateDirective, CollapsibleCardComponent, NgClass, FaIconComponent, NoDataComponent, GradingKeyTableComponent, ArtemisTranslatePipe], }) export class ExamResultOverviewComponent implements OnInit, OnChanges { + private serverDateService = inject(ArtemisServerDateService); + exerciseService = inject(ExerciseService); + private changeDetector = inject(ChangeDetectorRef); + readonly IncludedInOverallScore = IncludedInOverallScore; readonly BonusStrategy = BonusStrategy; @@ -69,12 +81,6 @@ export class ExamResultOverviewComponent implements OnInit, OnChanges { 'bonus-grading-key': true, }; - constructor( - private serverDateService: ArtemisServerDateService, - public exerciseService: ExerciseService, - private changeDetector: ChangeDetectorRef, - ) {} - ngOnInit() { if (this.areResultsPublished()) { this.setExamGrade(); @@ -220,14 +226,6 @@ export class ExamResultOverviewComponent implements OnInit, OnChanges { return false; } - toggleGradingKey(): void { - this.isGradingKeyCollapsed = !this.isGradingKeyCollapsed; - } - - toggleBonusGradingKey(): void { - this.isBonusGradingKeyCollapsed = !this.isBonusGradingKeyCollapsed; - } - toggleCollapse(resultOverviewSection: ResultOverviewSection) { return () => (this.isCollapsed[resultOverviewSection] = !this.isCollapsed[resultOverviewSection]); } diff --git a/src/main/webapp/app/exam/participate/timer/exam-timer.component.ts b/src/main/webapp/app/exam/participate/timer/exam-timer.component.ts index 0df96822e1aa..1a5a53cf4d95 100644 --- a/src/main/webapp/app/exam/participate/timer/exam-timer.component.ts +++ b/src/main/webapp/app/exam/participate/timer/exam-timer.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, HostBinding, Input, OnDestroy, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, HostBinding, Input, OnDestroy, OnInit, Output, inject } from '@angular/core'; import { Observable, Subject, timer } from 'rxjs'; import { distinctUntilChanged, first, map, takeUntil } from 'rxjs/operators'; import dayjs from 'dayjs/esm'; @@ -6,13 +6,18 @@ import { ArtemisServerDateService } from 'app/shared/server-date.service'; import { cloneDeep } from 'lodash-es'; import { ArtemisDurationFromSecondsPipe } from 'app/shared/pipes/artemis-duration-from-seconds.pipe'; import { round } from 'app/shared/util/utils'; +import { AsyncPipe } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-exam-timer', templateUrl: './exam-timer.component.html', styleUrls: ['./exam-timer.scss'], + imports: [AsyncPipe, ArtemisTranslatePipe], }) export class ExamTimerComponent implements OnInit, OnDestroy { + private serverDateService = inject(ArtemisServerDateService); + @HostBinding('class.row') readonly row = true; @Input() @@ -39,7 +44,7 @@ export class ExamTimerComponent implements OnInit, OnDestroy { timePipe: ArtemisDurationFromSecondsPipe = new ArtemisDurationFromSecondsPipe(); - constructor(private serverDateService: ArtemisServerDateService) { + constructor() { this.timer .pipe( map((timeLeft: plugin.Duration) => timeLeft.asSeconds()), diff --git a/src/main/webapp/app/exam/participate/timer/exam-timer.module.ts b/src/main/webapp/app/exam/participate/timer/exam-timer.module.ts index b04ff5ab7a30..94c53564d044 100644 --- a/src/main/webapp/app/exam/participate/timer/exam-timer.module.ts +++ b/src/main/webapp/app/exam/participate/timer/exam-timer.module.ts @@ -4,8 +4,7 @@ import { ExamTimerComponent } from 'app/exam/participate/timer/exam-timer.compon import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; @NgModule({ - declarations: [ExamTimerComponent], - imports: [CommonModule, ArtemisSharedCommonModule], + imports: [CommonModule, ArtemisSharedCommonModule, ExamTimerComponent], exports: [ExamTimerComponent], }) export class ArtemisExamTimerModule {} diff --git a/src/main/webapp/app/exam/shared/events/exam-live-event.component.ts b/src/main/webapp/app/exam/shared/events/exam-live-event.component.ts index ae2422c4f91f..4d6e4417f2a2 100644 --- a/src/main/webapp/app/exam/shared/events/exam-live-event.component.ts +++ b/src/main/webapp/app/exam/shared/events/exam-live-event.component.ts @@ -8,11 +8,19 @@ import { ProblemStatementUpdateEvent, WorkingTimeUpdateEvent, } from 'app/exam/participate/exam-participation-live-events.service'; +import { NgClass } from '@angular/common'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { WorkingTimeChangeComponent } from '../working-time-change/working-time-change.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-exam-live-event', templateUrl: './exam-live-event.component.html', styleUrls: ['./exam-live-event.component.scss'], + imports: [NgClass, TranslateDirective, FaIconComponent, WorkingTimeChangeComponent, ArtemisDatePipe, ArtemisTranslatePipe, HtmlForMarkdownPipe], }) export class ExamLiveEventComponent { @Input() diff --git a/src/main/webapp/app/exam/shared/exam-shared.module.ts b/src/main/webapp/app/exam/shared/exam-shared.module.ts index 9b4db9b8f43b..68d31244d222 100644 --- a/src/main/webapp/app/exam/shared/exam-shared.module.ts +++ b/src/main/webapp/app/exam/shared/exam-shared.module.ts @@ -1,15 +1,22 @@ import { NgModule } from '@angular/core'; import { StudentExamWorkingTimeComponent } from 'app/exam/shared/student-exam-working-time/student-exam-working-time.component'; import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; -import { TestexamWorkingTimeComponent } from 'app/exam/shared/testExam-workingTime/testexam-working-time.component'; +import { TestExamWorkingTimeComponent } from 'app/exam/shared/testExam-workingTime/test-exam-working-time.component'; import { WorkingTimeControlComponent } from 'app/exam/shared/working-time-control/working-time-control.component'; import { ExamLiveEventComponent } from 'app/exam/shared/events/exam-live-event.component'; import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; import { WorkingTimeChangeComponent } from 'app/exam/shared/working-time-change/working-time-change.component'; @NgModule({ - imports: [ArtemisSharedCommonModule, ArtemisMarkdownModule], - declarations: [StudentExamWorkingTimeComponent, TestexamWorkingTimeComponent, WorkingTimeControlComponent, WorkingTimeChangeComponent, ExamLiveEventComponent], - exports: [StudentExamWorkingTimeComponent, TestexamWorkingTimeComponent, WorkingTimeControlComponent, WorkingTimeChangeComponent, ExamLiveEventComponent], + imports: [ + ArtemisSharedCommonModule, + ArtemisMarkdownModule, + StudentExamWorkingTimeComponent, + TestExamWorkingTimeComponent, + WorkingTimeControlComponent, + WorkingTimeChangeComponent, + ExamLiveEventComponent, + ], + exports: [StudentExamWorkingTimeComponent, TestExamWorkingTimeComponent, WorkingTimeControlComponent, WorkingTimeChangeComponent, ExamLiveEventComponent], }) export class ArtemisExamSharedModule {} diff --git a/src/main/webapp/app/exam/shared/student-exam-working-time/student-exam-working-time.component.ts b/src/main/webapp/app/exam/shared/student-exam-working-time/student-exam-working-time.component.ts index e32a0ae2afb2..e9e086cb872b 100644 --- a/src/main/webapp/app/exam/shared/student-exam-working-time/student-exam-working-time.component.ts +++ b/src/main/webapp/app/exam/shared/student-exam-working-time/student-exam-working-time.component.ts @@ -1,11 +1,13 @@ import { Component, Input, OnInit } from '@angular/core'; import { StudentExam } from 'app/entities/student-exam.model'; import { getRelativeWorkingTimeExtension } from 'app/exam/participate/exam.utils'; +import { ArtemisDurationFromSecondsPipe } from 'app/shared/pipes/artemis-duration-from-seconds.pipe'; @Component({ selector: 'jhi-student-exam-working-time', templateUrl: './student-exam-working-time.component.html', providers: [], + imports: [ArtemisDurationFromSecondsPipe], }) export class StudentExamWorkingTimeComponent implements OnInit { @Input() studentExam: StudentExam; diff --git a/src/main/webapp/app/exam/shared/testExam-workingTime/testexam-working-time.component.html b/src/main/webapp/app/exam/shared/testExam-workingTime/test-exam-working-time.component.html similarity index 100% rename from src/main/webapp/app/exam/shared/testExam-workingTime/testexam-working-time.component.html rename to src/main/webapp/app/exam/shared/testExam-workingTime/test-exam-working-time.component.html diff --git a/src/main/webapp/app/exam/shared/testExam-workingTime/testexam-working-time.component.ts b/src/main/webapp/app/exam/shared/testExam-workingTime/test-exam-working-time.component.ts similarity index 81% rename from src/main/webapp/app/exam/shared/testExam-workingTime/testexam-working-time.component.ts rename to src/main/webapp/app/exam/shared/testExam-workingTime/test-exam-working-time.component.ts index 0de8831f3fbe..e7b8bca26088 100644 --- a/src/main/webapp/app/exam/shared/testExam-workingTime/testexam-working-time.component.ts +++ b/src/main/webapp/app/exam/shared/testExam-workingTime/test-exam-working-time.component.ts @@ -2,13 +2,15 @@ import { Component, Input, OnInit } from '@angular/core'; import { StudentExam } from 'app/entities/student-exam.model'; import { round } from 'app/shared/util/utils'; import dayjs from 'dayjs/esm'; +import { ArtemisDurationFromSecondsPipe } from 'app/shared/pipes/artemis-duration-from-seconds.pipe'; @Component({ - selector: 'jhi-testexam-working-time', - templateUrl: './testexam-working-time.component.html', + selector: 'jhi-test-exam-working-time', + templateUrl: './test-exam-working-time.component.html', providers: [], + imports: [ArtemisDurationFromSecondsPipe], }) -export class TestexamWorkingTimeComponent implements OnInit { +export class TestExamWorkingTimeComponent implements OnInit { @Input() studentExam: StudentExam; percentUsedWorkingTime = 0; diff --git a/src/main/webapp/app/exam/shared/working-time-change/working-time-change.component.ts b/src/main/webapp/app/exam/shared/working-time-change/working-time-change.component.ts index c5eec114e2e6..919ee6a667be 100644 --- a/src/main/webapp/app/exam/shared/working-time-change/working-time-change.component.ts +++ b/src/main/webapp/app/exam/shared/working-time-change/working-time-change.component.ts @@ -1,8 +1,11 @@ import { Component, Input } from '@angular/core'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisDurationFromSecondsPipe } from 'app/shared/pipes/artemis-duration-from-seconds.pipe'; @Component({ selector: 'jhi-working-time-change', templateUrl: './working-time-change.component.html', + imports: [TranslateDirective, ArtemisDurationFromSecondsPipe], }) export class WorkingTimeChangeComponent { @Input() oldWorkingTime: number; diff --git a/src/main/webapp/app/exam/shared/working-time-control/working-time-control.component.ts b/src/main/webapp/app/exam/shared/working-time-control/working-time-control.component.ts index 4d90cf31e917..4250a0f3c727 100644 --- a/src/main/webapp/app/exam/shared/working-time-control/working-time-control.component.ts +++ b/src/main/webapp/app/exam/shared/working-time-control/working-time-control.component.ts @@ -1,10 +1,11 @@ -import { Component, Input } from '@angular/core'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { Component, Input, inject } from '@angular/core'; +import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; import { Exam } from 'app/entities/exam/exam.model'; import { round } from 'app/shared/util/utils'; import { ArtemisDurationFromSecondsPipe } from 'app/shared/pipes/artemis-duration-from-seconds.pipe'; import { getRelativeWorkingTimeExtension } from 'app/exam/participate/exam.utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-working-time-control', @@ -18,8 +19,11 @@ import { getRelativeWorkingTimeExtension } from 'app/exam/participate/exam.utils useExisting: WorkingTimeControlComponent, }, ], + imports: [TranslateDirective, FormsModule], }) export class WorkingTimeControlComponent implements ControlValueAccessor { + private artemisDurationFromSecondsPipe = inject(ArtemisDurationFromSecondsPipe); + // Control disabled state @Input() disabled = false; @Input() allowNegative = false; @@ -56,8 +60,6 @@ export class WorkingTimeControlComponent implements ControlValueAccessor { private onTouched = () => {}; private onChange: (_: number) => void = () => {}; - constructor(private artemisDurationFromSecondsPipe: ArtemisDurationFromSecondsPipe) {} - /** * Updates the working time duration inputs whenever * the value of the form control changes. diff --git a/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.component.ts b/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.component.ts index e259fd3ea284..1a75f8c43aec 100644 --- a/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.component.ts +++ b/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.component.ts @@ -1,7 +1,7 @@ -import { Location } from '@angular/common'; +import { Location, UpperCasePipe } from '@angular/common'; import { HttpErrorResponse } from '@angular/common/http'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewEncapsulation, inject } from '@angular/core'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { faListAlt } from '@fortawesome/free-regular-svg-icons'; import { TranslateService } from '@ngx-translate/core'; import { isAllowedToModifyFeedback } from 'app/assessment/assessment.service'; @@ -24,19 +24,51 @@ import { getPositiveAndCappedTotalScore, getTotalMaxPoints } from 'app/exercises import { assessmentNavigateBack } from 'app/exercises/shared/navigate-back.util'; import { StructuredGradingCriterionService } from 'app/exercises/shared/structured-grading-criterion/structured-grading-criterion.service'; import { SubmissionService } from 'app/exercises/shared/submission/submission.service'; +import { UnreferencedFeedbackComponent } from 'app/exercises/shared/unreferenced-feedback/unreferenced-feedback.component'; import { FileService } from 'app/shared/http/file.service'; import { onError } from 'app/shared/util/global.utils'; import { getExerciseDashboardLink, getLinkToSubmissionAssessment } from 'app/utils/navigation.utils'; import dayjs from 'dayjs/esm'; import { filter, finalize } from 'rxjs/operators'; +import { AssessmentLayoutComponent } from 'app/assessment/assessment-layout/assessment-layout.component'; +import { ResizeableContainerComponent } from 'app/shared/resizeable-container/resizeable-container.component'; +import { ScoreDisplayComponent } from 'app/shared/score-display/score-display.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { AssessmentInstructionsComponent } from 'app/assessment/assessment-instructions/assessment-instructions/assessment-instructions.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ providers: [FileUploadAssessmentService], templateUrl: './file-upload-assessment.component.html', - styles: [], encapsulation: ViewEncapsulation.None, + imports: [ + AssessmentLayoutComponent, + ResizeableContainerComponent, + ScoreDisplayComponent, + TranslateDirective, + FaIconComponent, + AssessmentInstructionsComponent, + UnreferencedFeedbackComponent, + RouterLink, + UpperCasePipe, + ArtemisTranslatePipe, + ], }) export class FileUploadAssessmentComponent implements OnInit, OnDestroy { + private changeDetectorRef = inject(ChangeDetectorRef); + private alertService = inject(AlertService); + private router = inject(Router); + private route = inject(ActivatedRoute); + private fileUploadAssessmentService = inject(FileUploadAssessmentService); + private accountService = inject(AccountService); + private location = inject(Location); + private fileUploadSubmissionService = inject(FileUploadSubmissionService); + private complaintService = inject(ComplaintService); + private fileService = inject(FileService); + structuredGradingCriterionService = inject(StructuredGradingCriterionService); + submissionService = inject(SubmissionService); + text: string; participation: StudentParticipation; submission?: FileUploadSubmission; @@ -73,21 +105,9 @@ export class FileUploadAssessmentComponent implements OnInit, OnDestroy { // Icons farListAlt = faListAlt; - constructor( - private changeDetectorRef: ChangeDetectorRef, - private alertService: AlertService, - private router: Router, - private route: ActivatedRoute, - private fileUploadAssessmentService: FileUploadAssessmentService, - private accountService: AccountService, - private location: Location, - private fileUploadSubmissionService: FileUploadSubmissionService, - private complaintService: ComplaintService, - private fileService: FileService, - public structuredGradingCriterionService: StructuredGradingCriterionService, - public submissionService: SubmissionService, - translateService: TranslateService, - ) { + constructor() { + const translateService = inject(TranslateService); + this.assessmentsAreValid = false; translateService.get('artemisApp.assessment.messages.confirmCancel').subscribe((text) => (this.cancelConfirmationText = text)); } diff --git a/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.module.ts b/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.module.ts index bb16e7ebf643..7a65e727ac23 100644 --- a/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.module.ts +++ b/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.module.ts @@ -21,7 +21,7 @@ import { ArtemisAssessmentProgressLabelModule } from 'app/exercises/shared/asses ArtemisMarkdownModule, SubmissionResultStatusModule, ArtemisAssessmentProgressLabelModule, + FileUploadAssessmentComponent, ], - declarations: [FileUploadAssessmentComponent], }) export class ArtemisFileUploadAssessmentModule {} diff --git a/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.route.ts b/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.route.ts index 7043cf832c72..1acf7913fb87 100644 --- a/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.route.ts +++ b/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.route.ts @@ -1,13 +1,13 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { FileUploadAssessmentComponent } from 'app/exercises/file-upload/assess/file-upload-assessment.component'; + import { Authority } from 'app/shared/constants/authority.constants'; export const routes: Routes = [ { path: ':courseId/file-upload-exercises/:exerciseId/submissions/:submissionId/assessment', - component: FileUploadAssessmentComponent, + loadComponent: () => import('app/exercises/file-upload/assess/file-upload-assessment.component').then((m) => m.FileUploadAssessmentComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.fileUploadExercise.home.title', @@ -16,7 +16,7 @@ export const routes: Routes = [ }, { path: ':courseId/file-upload-exercises/:exerciseId/submissions/:submissionId/assessments/:resultId', - component: FileUploadAssessmentComponent, + loadComponent: () => import('app/exercises/file-upload/assess/file-upload-assessment.component').then((m) => m.FileUploadAssessmentComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.fileUploadExercise.home.title', diff --git a/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.service.ts b/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.service.ts index b109fcb079b9..a2265eb1c59e 100644 --- a/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.service.ts +++ b/src/main/webapp/app/exercises/file-upload/assess/file-upload-assessment.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { ComplaintResponse } from 'app/entities/complaint-response.model'; @@ -14,9 +14,9 @@ type FileUploadAssessmentDTO = { feedbacks: Feedback[]; assessmentNote?: string providedIn: 'root', }) export class FileUploadAssessmentService { - private resourceUrl = 'api'; + private http = inject(HttpClient); - constructor(private http: HttpClient) {} + private resourceUrl = 'api'; saveAssessment(feedbacks: Feedback[], submissionId: number, assessmentNote: string | undefined, submit = false): Observable { let params = new HttpParams(); diff --git a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-detail.component.ts b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-detail.component.ts index abb0c24df3ba..e23ce8f5d636 100644 --- a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-detail.component.ts @@ -1,7 +1,9 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { SafeHtml } from '@angular/platform-browser'; +import { NonProgrammingExerciseDetailCommonActionsComponent } from 'app/exercises/shared/exercise-detail-common-actions/non-programming-exercise-detail-common-actions.component'; +import { ExerciseDetailStatisticsComponent } from 'app/exercises/shared/statistics/exercise-detail-statistics.component'; import { Subscription } from 'rxjs'; import { FileUploadExercise } from 'app/entities/file-upload-exercise.model'; import { FileUploadExerciseService } from './file-upload-exercise.service'; @@ -25,12 +27,23 @@ import { getExerciseProblemDetailSection, } from 'app/exercises/shared/utils'; import { ArtemisMarkdownService } from 'app/shared/markdown.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { DetailOverviewListComponent } from 'app/detail-overview-list/detail-overview-list.component'; @Component({ selector: 'jhi-file-upload-exercise-detail', templateUrl: './file-upload-exercise-detail.component.html', + imports: [TranslateDirective, DocumentationButtonComponent, NonProgrammingExerciseDetailCommonActionsComponent, ExerciseDetailStatisticsComponent, DetailOverviewListComponent], }) export class FileUploadExerciseDetailComponent implements OnInit, OnDestroy { + private eventManager = inject(EventManager); + private fileUploadExerciseService = inject(FileUploadExerciseService); + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + private statisticsService = inject(StatisticsService); + private artemisMarkdown = inject(ArtemisMarkdownService); + readonly documentationType: DocumentationType = 'FileUpload'; readonly ExerciseType = ExerciseType; readonly dayjs = dayjs; @@ -47,15 +60,6 @@ export class FileUploadExerciseDetailComponent implements OnInit, OnDestroy { formattedExampleSolution: SafeHtml | null; formattedGradingInstructions: SafeHtml | null; - constructor( - private eventManager: EventManager, - private fileUploadExerciseService: FileUploadExerciseService, - private route: ActivatedRoute, - private alertService: AlertService, - private statisticsService: StatisticsService, - private artemisMarkdown: ArtemisMarkdownService, - ) {} - /** * Initializes subscription for file upload exercise */ diff --git a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-management-resolve.service.ts b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-management-resolve.service.ts index ae506ef9ffa6..353bf5a1c5b1 100644 --- a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-management-resolve.service.ts +++ b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-management-resolve.service.ts @@ -4,18 +4,16 @@ import { CourseManagementService } from 'app/course/manage/course-management.ser import { ExerciseGroupService } from 'app/exam/manage/exercise-groups/exercise-group.service'; import { ExerciseGroup } from 'app/entities/exercise-group.model'; import { Course } from 'app/entities/course.model'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { HttpResponse } from '@angular/common/http'; import { filter, map, of } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class FileUploadExerciseManagementResolve implements Resolve { - constructor( - private fileUploadExerciseService: FileUploadExerciseService, - private courseService: CourseManagementService, - private exerciseGroupService: ExerciseGroupService, - ) {} + private fileUploadExerciseService = inject(FileUploadExerciseService); + private courseService = inject(CourseManagementService); + private exerciseGroupService = inject(ExerciseGroupService); /** * Resolves the route and initializes file upload exercise either from exerciseId (existing exercise) or diff --git a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-management.module.ts b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-management.module.ts index be4a8a832e6f..2b9a93a12606 100644 --- a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-management.module.ts +++ b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-management.module.ts @@ -22,7 +22,7 @@ import { ExerciseTitleChannelNameModule } from 'app/exercises/shared/exercise-ti import { ExerciseUpdateNotificationModule } from 'app/exercises/shared/exercise-update-notification/exercise-update-notification.module'; import { DetailModule } from 'app/detail-overview-list/detail.module'; import { ArtemisExerciseModule } from 'app/exercises/shared/exercise/exercise.module'; -import { FormsModule } from 'app/forms/forms.module'; +import { ArtemisFormsModule } from 'app/forms/artemis-forms.module'; @NgModule({ imports: [ @@ -46,9 +46,11 @@ import { FormsModule } from 'app/forms/forms.module'; ExerciseTitleChannelNameModule, ExerciseUpdateNotificationModule, DetailModule, - FormsModule, + ArtemisFormsModule, + FileUploadExerciseComponent, + FileUploadExerciseDetailComponent, + FileUploadExerciseUpdateComponent, ], - declarations: [FileUploadExerciseComponent, FileUploadExerciseDetailComponent, FileUploadExerciseUpdateComponent], exports: [FileUploadExerciseComponent], }) export class ArtemisFileUploadExerciseManagementModule {} diff --git a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-management.route.ts b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-management.route.ts index 30a829a6ebc5..115357a32ba6 100644 --- a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-management.route.ts +++ b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-management.route.ts @@ -1,16 +1,16 @@ import { RouterModule, Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { FileUploadExerciseDetailComponent } from './file-upload-exercise-detail.component'; + import { NgModule } from '@angular/core'; -import { FileUploadExerciseUpdateComponent } from 'app/exercises/file-upload/manage/file-upload-exercise-update.component'; + import { Authority } from 'app/shared/constants/authority.constants'; -import { ExerciseStatisticsComponent } from 'app/exercises/shared/statistics/exercise-statistics.component'; + import { FileUploadExerciseManagementResolve } from 'app/exercises/file-upload/manage/file-upload-exercise-management-resolve.service'; const routes: Routes = [ { path: ':courseId/file-upload-exercises/new', - component: FileUploadExerciseUpdateComponent, + loadComponent: () => import('app/exercises/file-upload/manage/file-upload-exercise-update.component').then((m) => m.FileUploadExerciseUpdateComponent), resolve: { fileUploadExercise: FileUploadExerciseManagementResolve, }, @@ -22,7 +22,7 @@ const routes: Routes = [ }, { path: ':courseId/file-upload-exercises/:exerciseId/import', - component: FileUploadExerciseUpdateComponent, + loadComponent: () => import('app/exercises/file-upload/manage/file-upload-exercise-update.component').then((m) => m.FileUploadExerciseUpdateComponent), resolve: { fileUploadExercise: FileUploadExerciseManagementResolve, }, @@ -35,7 +35,7 @@ const routes: Routes = [ { path: ':courseId/file-upload-exercises/:exerciseId/edit', - component: FileUploadExerciseUpdateComponent, + loadComponent: () => import('app/exercises/file-upload/manage/file-upload-exercise-update.component').then((m) => m.FileUploadExerciseUpdateComponent), resolve: { fileUploadExercise: FileUploadExerciseManagementResolve, }, @@ -47,7 +47,7 @@ const routes: Routes = [ }, { path: ':courseId/file-upload-exercises/:exerciseId', - component: FileUploadExerciseDetailComponent, + loadComponent: () => import('./file-upload-exercise-detail.component').then((m) => m.FileUploadExerciseDetailComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.fileUploadExercise.home.title', @@ -60,7 +60,7 @@ const routes: Routes = [ }, { path: ':courseId/file-upload-exercises/:exerciseId/exercise-statistics', - component: ExerciseStatisticsComponent, + loadComponent: () => import('app/exercises/shared/statistics/exercise-statistics.component').then((m) => m.ExerciseStatisticsComponent), resolve: { fileUploadExercise: FileUploadExerciseManagementResolve, }, diff --git a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-paging.service.ts b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-paging.service.ts index e2d97cfa5934..cf144194dd52 100644 --- a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-paging.service.ts +++ b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-paging.service.ts @@ -1,5 +1,5 @@ import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ExercisePagingService } from 'app/exercises/shared/manage/exercise-paging.service'; import { FileUploadExercise } from 'app/entities/file-upload-exercise.model'; @@ -7,7 +7,9 @@ import { FileUploadExercise } from 'app/entities/file-upload-exercise.model'; export class FileUploadExercisePagingService extends ExercisePagingService { private static readonly RESOURCE_URL = 'api/file-upload-exercises'; - constructor(http: HttpClient) { + constructor() { + const http = inject(HttpClient); + super(http, FileUploadExercisePagingService.RESOURCE_URL); } } diff --git a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-update.component.ts b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-update.component.ts index 798a1d50f57d..cf61a8e45700 100644 --- a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-update.component.ts +++ b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise-update.component.ts @@ -1,7 +1,11 @@ -import { AfterViewInit, ChangeDetectionStrategy, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { AfterViewInit, ChangeDetectionStrategy, Component, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; import { ActivatedRoute, Params } from '@angular/router'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { AlertService, AlertType } from 'app/core/util/alert.service'; +import { DifficultyPickerComponent } from 'app/exercises/shared/difficulty-picker/difficulty-picker.component'; +import { IncludedInOverallScorePickerComponent } from 'app/exercises/shared/included-in-overall-score-picker/included-in-overall-score-picker.component'; +import { PresentationScoreComponent } from 'app/exercises/shared/presentation-score/presentation-score.component'; +import { GradingInstructionsDetailsComponent } from 'app/exercises/shared/structured-grading-criterion/grading-instructions-details/grading-instructions-details.component'; import { FileUploadExerciseService } from './file-upload-exercise.service'; import { FileUploadExercise } from 'app/entities/file-upload-exercise.model'; import { CourseManagementService } from 'app/course/manage/course-management.service'; @@ -10,7 +14,7 @@ import { Exercise, ExerciseMode, IncludedInOverallScore, getCourseId, resetForIm import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; import { ExerciseCategory } from 'app/entities/exercise-category.model'; import { cloneDeep } from 'lodash-es'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { ExerciseUpdateWarningService } from 'app/exercises/shared/exercise-update-warning/exercise-update-warning.service'; import { onError } from 'app/shared/util/global.utils'; import { EditType, SaveExerciseCommand } from 'app/exercises/shared/exercise/exercise.utils'; @@ -22,17 +26,62 @@ import { scrollToTopOfPage } from 'app/shared/util/utils'; import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component'; import { ExerciseTitleChannelNameComponent } from 'app/exercises/shared/exercise-title-channel-name/exercise-title-channel-name.component'; import { TeamConfigFormGroupComponent } from 'app/exercises/shared/team-config-form-group/team-config-form-group.component'; -import { NgModel } from '@angular/forms'; +import { FormsModule, NgModel } from '@angular/forms'; import { Subscription } from 'rxjs'; import { FormSectionStatus } from 'app/forms/form-status-bar/form-status-bar.component'; import { FormulaAction } from 'app/shared/monaco-editor/model/actions/formula.action'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { FormStatusBarComponent } from 'app/forms/form-status-bar/form-status-bar.component'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { CategorySelectorComponent } from 'app/shared/category-selector/category-selector.component'; +import { MarkdownEditorMonacoComponent } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { CompetencySelectionComponent } from 'app/shared/competency-selection/competency-selection.component'; +import { CustomMinDirective } from 'app/shared/validators/custom-min-validator.directive'; +import { CustomMaxDirective } from 'app/shared/validators/custom-max-validator.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { FormFooterComponent } from 'app/forms/form-footer/form-footer.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-file-upload-exercise-update', templateUrl: './file-upload-exercise-update.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + FormsModule, + TranslateDirective, + DocumentationButtonComponent, + FormStatusBarComponent, + ExerciseTitleChannelNameComponent, + HelpIconComponent, + CategorySelectorComponent, + DifficultyPickerComponent, + TeamConfigFormGroupComponent, + MarkdownEditorMonacoComponent, + CompetencySelectionComponent, + FormDateTimePickerComponent, + IncludedInOverallScorePickerComponent, + CustomMinDirective, + CustomMaxDirective, + FaIconComponent, + NgbTooltip, + PresentationScoreComponent, + GradingInstructionsDetailsComponent, + FormFooterComponent, + ArtemisTranslatePipe, + ], }) export class FileUploadExerciseUpdateComponent implements AfterViewInit, OnDestroy, OnInit { + private fileUploadExerciseService = inject(FileUploadExerciseService); + private modalService = inject(NgbModal); + private popupService = inject(ExerciseUpdateWarningService); + private activatedRoute = inject(ActivatedRoute); + private courseService = inject(CourseManagementService); + private exerciseService = inject(ExerciseService); + private alertService = inject(AlertService); + private navigationUtilService = inject(ArtemisNavigationUtilService); + private exerciseGroupService = inject(ExerciseGroupService); + protected readonly faQuestionCircle = faQuestionCircle; readonly IncludedInOverallScore = IncludedInOverallScore; @@ -68,18 +117,6 @@ export class FileUploadExerciseUpdateComponent implements AfterViewInit, OnDestr bonusPointsSubscription?: Subscription; teamSubscription?: Subscription; - constructor( - private fileUploadExerciseService: FileUploadExerciseService, - private modalService: NgbModal, - private popupService: ExerciseUpdateWarningService, - private activatedRoute: ActivatedRoute, - private courseService: CourseManagementService, - private exerciseService: ExerciseService, - private alertService: AlertService, - private navigationUtilService: ArtemisNavigationUtilService, - private exerciseGroupService: ExerciseGroupService, - ) {} - get editType(): EditType { if (this.isImport) { return EditType.IMPORT; diff --git a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise.component.ts b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise.component.ts index 0874dea0faf6..9d6e49fad41a 100644 --- a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise.component.ts +++ b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise.component.ts @@ -12,10 +12,20 @@ import { AlertService } from 'app/core/util/alert.service'; import { faBook, faPlus, faSort, faTable, faTrash, faUsers, faWrench } from '@fortawesome/free-solid-svg-icons'; import { faListAlt } from '@fortawesome/free-regular-svg-icons'; import { CourseExerciseService } from 'app/exercises/shared/course-exercises/course-exercise.service'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { FormsModule } from '@angular/forms'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { RouterLink } from '@angular/router'; +import { ExerciseCategoriesComponent } from 'app/shared/exercise-categories/exercise-categories.component'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; @Component({ selector: 'jhi-file-upload-exercise', templateUrl: './file-upload-exercise.component.html', + imports: [SortDirective, FormsModule, SortByDirective, TranslateDirective, FaIconComponent, RouterLink, ExerciseCategoriesComponent, DeleteButtonDirective, ArtemisDatePipe], }) export class FileUploadExerciseComponent extends ExerciseComponent { protected exerciseService = inject(ExerciseService); diff --git a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise.service.ts b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise.service.ts index cd19cb977939..06339252611e 100644 --- a/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise.service.ts +++ b/src/main/webapp/app/exercises/file-upload/manage/file-upload-exercise.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -12,12 +12,10 @@ export type EntityArrayResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class FileUploadExerciseService implements ExerciseServicable { - private resourceUrl = 'api/file-upload-exercises'; + private http = inject(HttpClient); + private exerciseService = inject(ExerciseService); - constructor( - private http: HttpClient, - private exerciseService: ExerciseService, - ) {} + private resourceUrl = 'api/file-upload-exercises'; /** * Sends request to create new file upload exercise diff --git a/src/main/webapp/app/exercises/file-upload/participate/file-upload-participation.module.ts b/src/main/webapp/app/exercises/file-upload/participate/file-upload-participation.module.ts index 19a5d3e8d7fe..26f24f2ea86e 100644 --- a/src/main/webapp/app/exercises/file-upload/participate/file-upload-participation.module.ts +++ b/src/main/webapp/app/exercises/file-upload/participate/file-upload-participation.module.ts @@ -19,8 +19,8 @@ import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; ArtemisHeaderExercisePageWithDetailsModule, RatingModule, ArtemisMarkdownModule, + FileUploadSubmissionComponent, ], - declarations: [FileUploadSubmissionComponent], exports: [FileUploadSubmissionComponent], }) export class ArtemisFileUploadParticipationModule {} diff --git a/src/main/webapp/app/exercises/file-upload/participate/file-upload-participation.route.ts b/src/main/webapp/app/exercises/file-upload/participate/file-upload-participation.route.ts index 7cfcb7220534..5b047f5097a0 100644 --- a/src/main/webapp/app/exercises/file-upload/participate/file-upload-participation.route.ts +++ b/src/main/webapp/app/exercises/file-upload/participate/file-upload-participation.route.ts @@ -2,13 +2,13 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; import { PendingChangesGuard } from 'app/shared/guard/pending-changes.guard'; -import { FileUploadSubmissionComponent } from 'app/exercises/file-upload/participate/file-upload-submission.component'; + import { Authority } from 'app/shared/constants/authority.constants'; export const routes: Routes = [ { path: 'participate/:participationId', - component: FileUploadSubmissionComponent, + loadComponent: () => import('app/exercises/file-upload/participate/file-upload-submission.component').then((m) => m.FileUploadSubmissionComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.fileUploadExercise.home.title', diff --git a/src/main/webapp/app/exercises/file-upload/participate/file-upload-submission.component.ts b/src/main/webapp/app/exercises/file-upload/participate/file-upload-submission.component.ts index ebd49234be13..9ec02f5fa01b 100644 --- a/src/main/webapp/app/exercises/file-upload/participate/file-upload-submission.component.ts +++ b/src/main/webapp/app/exercises/file-upload/participate/file-upload-submission.component.ts @@ -1,9 +1,11 @@ -import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; -import { Location } from '@angular/common'; +import { Component, ElementRef, Input, OnInit, ViewChild, inject } from '@angular/core'; +import { Location, UpperCasePipe } from '@angular/common'; import { TranslateService } from '@ngx-translate/core'; import { ActivatedRoute } from '@angular/router'; import { HttpErrorResponse } from '@angular/common/http'; import { AlertService } from 'app/core/util/alert.service'; +import { HeaderParticipationPageComponent } from 'app/exercises/shared/exercise-headers/header-participation-page.component'; +import { RatingComponent } from 'app/exercises/shared/rating/rating.component'; import dayjs from 'dayjs/esm'; import { StudentParticipation } from 'app/entities/participation/student-participation.model'; import { FileUploadSubmissionService } from 'app/exercises/file-upload/participate/file-upload-submission.service'; @@ -29,12 +31,49 @@ import { getCourseFromExercise } from 'app/entities/exercise.model'; import { Course } from 'app/entities/course.model'; import { faListAlt } from '@fortawesome/free-regular-svg-icons'; import { faDownload } from '@fortawesome/free-solid-svg-icons'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { ResizeableContainerComponent } from 'app/shared/resizeable-container/resizeable-container.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ExerciseActionButtonComponent } from 'app/shared/components/exercise-action-button.component'; +import { AdditionalFeedbackComponent } from 'app/shared/additional-feedback/additional-feedback.component'; +import { ComplaintsStudentViewComponent } from 'app/complaints/complaints-for-students/complaints-student-view.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { ArtemisTimeAgoPipe } from 'app/shared/pipes/artemis-time-ago.pipe'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-file-upload-submission', templateUrl: './file-upload-submission.component.html', + imports: [ + HeaderParticipationPageComponent, + ButtonComponent, + ResizeableContainerComponent, + TranslateDirective, + ExerciseActionButtonComponent, + AdditionalFeedbackComponent, + RatingComponent, + ComplaintsStudentViewComponent, + FaIconComponent, + UpperCasePipe, + ArtemisTranslatePipe, + ArtemisTimeAgoPipe, + HtmlForMarkdownPipe, + ], }) export class FileUploadSubmissionComponent implements OnInit, ComponentCanDeactivate { + private route = inject(ActivatedRoute); + private fileUploadSubmissionService = inject(FileUploadSubmissionService); + private fileUploaderService = inject(FileUploaderService); + private resultService = inject(ResultService); + private alertService = inject(AlertService); + private location = inject(Location); + private translateService = inject(TranslateService); + private fileService = inject(FileService); + private participationWebsocketService = inject(ParticipationWebsocketService); + private fileUploadAssessmentService = inject(FileUploadAssessmentService); + private accountService = inject(AccountService); + readonly addParticipationToResult = addParticipationToResult; @ViewChild('fileInput', { static: false }) fileInput: ElementRef; @@ -74,19 +113,9 @@ export class FileUploadSubmissionComponent implements OnInit, ComponentCanDeacti // Icons farListAlt = faListAlt; - constructor( - private route: ActivatedRoute, - private fileUploadSubmissionService: FileUploadSubmissionService, - private fileUploaderService: FileUploaderService, - private resultService: ResultService, - private alertService: AlertService, - private location: Location, - private translateService: TranslateService, - private fileService: FileService, - private participationWebsocketService: ParticipationWebsocketService, - private fileUploadAssessmentService: FileUploadAssessmentService, - private accountService: AccountService, - ) { + constructor() { + const translateService = this.translateService; + translateService.get('artemisApp.fileUploadSubmission.confirmSubmission').subscribe((text) => (this.submissionConfirmationText = text)); } diff --git a/src/main/webapp/app/exercises/file-upload/participate/file-upload-submission.service.ts b/src/main/webapp/app/exercises/file-upload/participate/file-upload-submission.service.ts index b685eae92bc2..0d961a76caaa 100644 --- a/src/main/webapp/app/exercises/file-upload/participate/file-upload-submission.service.ts +++ b/src/main/webapp/app/exercises/file-upload/participate/file-upload-submission.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -12,10 +12,8 @@ export type EntityResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class FileUploadSubmissionService { - constructor( - private http: HttpClient, - private submissionService: SubmissionService, - ) {} + private http = inject(HttpClient); + private submissionService = inject(SubmissionService); /** * Updates File Upload submission on the server diff --git a/src/main/webapp/app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.component.ts b/src/main/webapp/app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.component.ts index fe7a6017459f..9b30052e6905 100644 --- a/src/main/webapp/app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.component.ts +++ b/src/main/webapp/app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.component.ts @@ -1,9 +1,10 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { Location } from '@angular/common'; +import { UnreferencedFeedbackComponent } from 'app/exercises/shared/unreferenced-feedback/unreferenced-feedback.component'; import { firstValueFrom } from 'rxjs'; import { AlertService } from 'app/core/util/alert.service'; import { UMLDiagramType, UMLModel } from '@ls1intum/apollon'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { AccountService } from 'app/core/auth/account.service'; import { HttpErrorResponse } from '@angular/common/http'; import { TranslateService } from '@ngx-translate/core'; @@ -31,13 +32,45 @@ import { isAllowedToModifyFeedback } from 'app/assessment/assessment.service'; import { AssessmentAfterComplaint } from 'app/complaints/complaints-for-tutor/complaints-for-tutor.component'; import { AthenaService } from 'app/assessment/athena.service'; import { faCircleNotch, faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; +import { AssessmentLayoutComponent } from 'app/assessment/assessment-layout/assessment-layout.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ModelingAssessmentComponent } from '../modeling-assessment.component'; +import { CollapsableAssessmentInstructionsComponent } from 'app/assessment/assessment-instructions/collapsable-assessment-instructions/collapsable-assessment-instructions.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-modeling-assessment-editor', templateUrl: './modeling-assessment-editor.component.html', styleUrls: ['./modeling-assessment-editor.component.scss'], + imports: [ + AssessmentLayoutComponent, + TranslateDirective, + NgbTooltip, + FaIconComponent, + ModelingAssessmentComponent, + CollapsableAssessmentInstructionsComponent, + UnreferencedFeedbackComponent, + RouterLink, + ArtemisTranslatePipe, + ], }) export class ModelingAssessmentEditorComponent implements OnInit { + private alertService = inject(AlertService); + private router = inject(Router); + private route = inject(ActivatedRoute); + private modelingSubmissionService = inject(ModelingSubmissionService); + private modelingAssessmentService = inject(ModelingAssessmentService); + private accountService = inject(AccountService); + private location = inject(Location); + private translateService = inject(TranslateService); + private complaintService = inject(ComplaintService); + private structuredGradingCriterionService = inject(StructuredGradingCriterionService); + private submissionService = inject(SubmissionService); + private exampleSubmissionService = inject(ExampleSubmissionService); + private athenaService = inject(AthenaService); + totalScore = 0; submission?: ModelingSubmission; model?: UMLModel; @@ -78,21 +111,9 @@ export class ModelingAssessmentEditorComponent implements OnInit { protected readonly faCircleNotch = faCircleNotch; protected readonly faQuestionCircle = faQuestionCircle; - constructor( - private alertService: AlertService, - private router: Router, - private route: ActivatedRoute, - private modelingSubmissionService: ModelingSubmissionService, - private modelingAssessmentService: ModelingAssessmentService, - private accountService: AccountService, - private location: Location, - private translateService: TranslateService, - private complaintService: ComplaintService, - private structuredGradingCriterionService: StructuredGradingCriterionService, - private submissionService: SubmissionService, - private exampleSubmissionService: ExampleSubmissionService, - private athenaService: AthenaService, - ) { + constructor() { + const translateService = this.translateService; + translateService.get('artemisApp.modelingAssessmentEditor.messages.confirmCancel').subscribe((text) => (this.cancelConfirmationText = text)); } diff --git a/src/main/webapp/app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.module.ts b/src/main/webapp/app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.module.ts index b52ddeaee956..f7b7326a1670 100644 --- a/src/main/webapp/app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.module.ts +++ b/src/main/webapp/app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.module.ts @@ -21,8 +21,8 @@ import { ArtemisAssessmentProgressLabelModule } from 'app/exercises/shared/asses ModelingAssessmentModule, SubmissionResultStatusModule, ArtemisAssessmentProgressLabelModule, + ModelingAssessmentEditorComponent, ], - declarations: [ModelingAssessmentEditorComponent], exports: [ModelingAssessmentEditorComponent], }) export class ArtemisModelingAssessmentEditorModule {} diff --git a/src/main/webapp/app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.route.ts b/src/main/webapp/app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.route.ts index 526c30454334..2c21e3200e1a 100644 --- a/src/main/webapp/app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.route.ts +++ b/src/main/webapp/app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.route.ts @@ -1,13 +1,14 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { ModelingAssessmentEditorComponent } from 'app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.component'; + import { Authority } from 'app/shared/constants/authority.constants'; export const routes: Routes = [ { path: ':courseId/modeling-exercises/:exerciseId/submissions/:submissionId/assessment', - component: ModelingAssessmentEditorComponent, + loadComponent: () => + import('app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.component').then((m) => m.ModelingAssessmentEditorComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.modelingExercise.home.title', @@ -16,7 +17,8 @@ export const routes: Routes = [ }, { path: ':courseId/modeling-exercises/:exerciseId/submissions/:submissionId/assessments/:resultId', - component: ModelingAssessmentEditorComponent, + loadComponent: () => + import('app/exercises/modeling/assess/modeling-assessment-editor/modeling-assessment-editor.component').then((m) => m.ModelingAssessmentEditorComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], usePathForBreadcrumbs: true, diff --git a/src/main/webapp/app/exercises/modeling/assess/modeling-assessment.component.ts b/src/main/webapp/app/exercises/modeling/assess/modeling-assessment.component.ts index d39b9a9f1830..0944dd628d07 100644 --- a/src/main/webapp/app/exercises/modeling/assess/modeling-assessment.component.ts +++ b/src/main/webapp/app/exercises/modeling/assess/modeling-assessment.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, EventEmitter, Input, OnChanges, OnDestroy, Output, SimpleChanges } from '@angular/core'; +import { AfterViewInit, Component, EventEmitter, Input, OnChanges, OnDestroy, Output, SimpleChanges, inject } from '@angular/core'; import { ApollonEditor, ApollonMode, Assessment, Selection, UMLDiagramType, UMLElementType, UMLModel, UMLRelationshipType, addOrUpdateAssessment } from '@ls1intum/apollon'; import { Feedback, FeedbackType } from 'app/entities/feedback.model'; import { ModelElementCount } from 'app/entities/modeling-submission.model'; @@ -7,6 +7,9 @@ import { Course } from 'app/entities/course.model'; import { GradingInstruction } from 'app/exercises/shared/structured-grading-criterion/grading-instruction.model'; import { ModelingComponent } from 'app/exercises/modeling/shared/modeling.component'; import { filterInvalidFeedback } from 'app/exercises/modeling/assess/modeling-assessment.util'; +import { ScoreDisplayComponent } from 'app/shared/score-display/score-display.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ModelingExplanationEditorComponent } from '../shared/modeling-explanation-editor.component'; export interface DropInfo { instruction: GradingInstruction; @@ -19,8 +22,11 @@ export interface DropInfo { selector: 'jhi-modeling-assessment', templateUrl: './modeling-assessment.component.html', styleUrls: ['./modeling-assessment.component.scss'], + imports: [ScoreDisplayComponent, FaIconComponent, ModelingExplanationEditorComponent], }) export class ModelingAssessmentComponent extends ModelingComponent implements AfterViewInit, OnDestroy, OnChanges { + private artemisTranslatePipe = inject(ArtemisTranslatePipe); + @Input() maxScore: number; @Input() maxBonusPoints = 0; @Input() totalScore: number; @@ -49,7 +55,7 @@ export class ModelingAssessmentComponent extends ModelingComponent implements Af firstCorrectionRoundColor = '#3e8acc'; secondCorrectionRoundColor = '#ffa561'; - constructor(private artemisTranslatePipe: ArtemisTranslatePipe) { + constructor() { super(); } diff --git a/src/main/webapp/app/exercises/modeling/assess/modeling-assessment.module.ts b/src/main/webapp/app/exercises/modeling/assess/modeling-assessment.module.ts index c9e898bcb860..d324b46c1484 100644 --- a/src/main/webapp/app/exercises/modeling/assess/modeling-assessment.module.ts +++ b/src/main/webapp/app/exercises/modeling/assess/modeling-assessment.module.ts @@ -5,8 +5,7 @@ import { ArtemisAssessmentSharedModule } from 'app/assessment/assessment-shared. import { ArtemisModelingEditorModule } from 'app/exercises/modeling/shared/modeling-editor.module'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisAssessmentSharedModule, ArtemisModelingEditorModule], - declarations: [ModelingAssessmentComponent], + imports: [ArtemisSharedModule, ArtemisAssessmentSharedModule, ArtemisModelingEditorModule, ModelingAssessmentComponent], exports: [ModelingAssessmentComponent], }) export class ModelingAssessmentModule {} diff --git a/src/main/webapp/app/exercises/modeling/assess/modeling-assessment.service.ts b/src/main/webapp/app/exercises/modeling/assess/modeling-assessment.service.ts index d03f7f22adcc..7f5c89709873 100644 --- a/src/main/webapp/app/exercises/modeling/assess/modeling-assessment.service.ts +++ b/src/main/webapp/app/exercises/modeling/assess/modeling-assessment.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { ComplaintResponse } from 'app/entities/complaint-response.model'; @@ -12,12 +12,12 @@ type ModelingAssessmentDTO = { feedbacks: Feedback[]; assessmentNote?: string }; @Injectable({ providedIn: 'root' }) export class ModelingAssessmentService { + private http = inject(HttpClient); + private readonly MAX_FEEDBACK_TEXT_LENGTH = 500; private readonly MAX_FEEDBACK_DETAIL_TEXT_LENGTH = 5000; private resourceUrl = 'api'; - constructor(private http: HttpClient) {} - saveAssessment(resultId: number, feedbacks: Feedback[], submissionId: number, assessmentNote?: string, submit = false): Observable { let params = new HttpParams(); if (submit) { diff --git a/src/main/webapp/app/exercises/modeling/manage/example-modeling/example-modeling-submission.component.ts b/src/main/webapp/app/exercises/modeling/manage/example-modeling/example-modeling-submission.component.ts index 27d7cd03894d..1533b9407188 100644 --- a/src/main/webapp/app/exercises/modeling/manage/example-modeling/example-modeling-submission.component.ts +++ b/src/main/webapp/app/exercises/modeling/manage/example-modeling/example-modeling-submission.component.ts @@ -14,6 +14,7 @@ import { ModelingAssessmentService } from 'app/exercises/modeling/assess/modelin import { ModelingSubmission } from 'app/entities/modeling-submission.model'; import { ModelingExercise } from 'app/entities/modeling-exercise.model'; import { ModelingAssessmentComponent } from 'app/exercises/modeling/assess/modeling-assessment.component'; +import { UnreferencedFeedbackComponent } from 'app/exercises/shared/unreferenced-feedback/unreferenced-feedback.component'; import { catchError, concatMap, map, tap } from 'rxjs/operators'; import { getLatestSubmissionResult, setLatestSubmissionResult } from 'app/entities/submission.model'; import { getPositiveAndCappedTotalScore, getTotalMaxPoints } from 'app/exercises/shared/exercise/exercise.utils'; @@ -28,13 +29,39 @@ import { forkJoin } from 'rxjs'; import { filterInvalidFeedback } from 'app/exercises/modeling/assess/modeling-assessment.util'; import { Theme, ThemeService } from 'app/core/theme/theme.service'; import { scrollToTopOfPage } from 'app/shared/util/utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { FormsModule } from '@angular/forms'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { CollapsableAssessmentInstructionsComponent } from 'app/assessment/assessment-instructions/collapsable-assessment-instructions/collapsable-assessment-instructions.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-example-modeling-submission', templateUrl: './example-modeling-submission.component.html', styleUrls: ['./example-modeling-submission.component.scss'], + imports: [ + TranslateDirective, + HelpIconComponent, + FormsModule, + FaIconComponent, + ModelingEditorComponent, + ModelingAssessmentComponent, + UnreferencedFeedbackComponent, + CollapsableAssessmentInstructionsComponent, + ArtemisTranslatePipe, + ], }) export class ExampleModelingSubmissionComponent implements OnInit, FeedbackMarker { + private exerciseService = inject(ExerciseService); + private exampleSubmissionService = inject(ExampleSubmissionService); + private modelingAssessmentService = inject(ModelingAssessmentService); + private tutorParticipationService = inject(TutorParticipationService); + private alertService = inject(AlertService); + private route = inject(ActivatedRoute); + private router = inject(Router); + private navigationUtilService = inject(ArtemisNavigationUtilService); + @ViewChild(ModelingEditorComponent, { static: false }) modelingEditor: ModelingEditorComponent; @ViewChild(ModelingAssessmentComponent, { static: false }) @@ -106,16 +133,7 @@ export class ExampleModelingSubmissionComponent implements OnInit, FeedbackMarke faCodeBranch = faCodeBranch; faChalkboardTeacher = faChalkboardTeacher; - constructor( - private exerciseService: ExerciseService, - private exampleSubmissionService: ExampleSubmissionService, - private modelingAssessmentService: ModelingAssessmentService, - private tutorParticipationService: TutorParticipationService, - private alertService: AlertService, - private route: ActivatedRoute, - private router: Router, - private navigationUtilService: ArtemisNavigationUtilService, - ) { + constructor() { effect(() => { // Update highlighted elements as soon as current theme changes const highlightColor = this.highlightColor(); diff --git a/src/main/webapp/app/exercises/modeling/manage/example-modeling/example-modeling-submission.module.ts b/src/main/webapp/app/exercises/modeling/manage/example-modeling/example-modeling-submission.module.ts index b3dca289b27a..6d6b50342419 100644 --- a/src/main/webapp/app/exercises/modeling/manage/example-modeling/example-modeling-submission.module.ts +++ b/src/main/webapp/app/exercises/modeling/manage/example-modeling/example-modeling-submission.module.ts @@ -19,7 +19,7 @@ import { ArtemisSharedComponentModule } from 'app/shared/components/shared-compo ArtemisAssessmentSharedModule, AssessmentInstructionsModule, ArtemisSharedComponentModule, + ExampleModelingSubmissionComponent, ], - declarations: [ExampleModelingSubmissionComponent], }) export class ArtemisExampleModelingSubmissionModule {} diff --git a/src/main/webapp/app/exercises/modeling/manage/example-modeling/example-modeling-submission.route.ts b/src/main/webapp/app/exercises/modeling/manage/example-modeling/example-modeling-submission.route.ts index c1bee6307701..387a5d3ec926 100644 --- a/src/main/webapp/app/exercises/modeling/manage/example-modeling/example-modeling-submission.route.ts +++ b/src/main/webapp/app/exercises/modeling/manage/example-modeling/example-modeling-submission.route.ts @@ -1,13 +1,13 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { ExampleModelingSubmissionComponent } from './example-modeling-submission.component'; + import { Authority } from 'app/shared/constants/authority.constants'; export const routes: Routes = [ { path: ':courseId/modeling-exercises/:exerciseId/example-submissions/:exampleSubmissionId', - component: ExampleModelingSubmissionComponent, + loadComponent: () => import('./example-modeling-submission.component').then((m) => m.ExampleModelingSubmissionComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.exampleSubmission.home.editor', diff --git a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-detail.component.ts b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-detail.component.ts index 487d9213e763..42c7363b1c28 100644 --- a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-detail.component.ts @@ -1,8 +1,10 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { SafeHtml } from '@angular/platform-browser'; import { ActivatedRoute } from '@angular/router'; import { HttpResponse } from '@angular/common/http'; import { UMLModel } from '@ls1intum/apollon'; +import { NonProgrammingExerciseDetailCommonActionsComponent } from 'app/exercises/shared/exercise-detail-common-actions/non-programming-exercise-detail-common-actions.component'; +import { ExerciseDetailStatisticsComponent } from 'app/exercises/shared/statistics/exercise-detail-statistics.component'; import { Subscription } from 'rxjs'; import { ModelingExercise } from 'app/entities/modeling-exercise.model'; import { ModelingExerciseService } from './modeling-exercise.service'; @@ -25,12 +27,25 @@ import { getExerciseProblemDetailSection, } from 'app/exercises/shared/utils'; import { DetailOverviewSection, DetailType } from 'app/detail-overview-list/detail-overview-list.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { DetailOverviewListComponent } from 'app/detail-overview-list/detail-overview-list.component'; @Component({ selector: 'jhi-modeling-exercise-detail', templateUrl: './modeling-exercise-detail.component.html', + imports: [TranslateDirective, DocumentationButtonComponent, NonProgrammingExerciseDetailCommonActionsComponent, ExerciseDetailStatisticsComponent, DetailOverviewListComponent], }) export class ModelingExerciseDetailComponent implements OnInit, OnDestroy { + private eventManager = inject(EventManager); + private modelingExerciseService = inject(ModelingExerciseService); + private route = inject(ActivatedRoute); + private artemisMarkdown = inject(ArtemisMarkdownService); + private alertService = inject(AlertService); + private statisticsService = inject(StatisticsService); + private accountService = inject(AccountService); + private profileService = inject(ProfileService); + readonly documentationType: DocumentationType = 'Model'; readonly ExerciseType = ExerciseType; readonly dayjs = dayjs; @@ -52,17 +67,6 @@ export class ModelingExerciseDetailComponent implements OnInit, OnDestroy { isAdmin = false; isApollonProfileActive = false; - constructor( - private eventManager: EventManager, - private modelingExerciseService: ModelingExerciseService, - private route: ActivatedRoute, - private artemisMarkdown: ArtemisMarkdownService, - private alertService: AlertService, - private statisticsService: StatisticsService, - private accountService: AccountService, - private profileService: ProfileService, - ) {} - ngOnInit() { this.isAdmin = this.accountService.isAdmin(); this.subscription = this.route.params.subscribe((params) => { diff --git a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-paging.service.ts b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-paging.service.ts index d7038c75bad7..33b28ca196dd 100644 --- a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-paging.service.ts +++ b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-paging.service.ts @@ -1,5 +1,5 @@ import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ModelingExercise } from 'app/entities/modeling-exercise.model'; import { ExercisePagingService } from 'app/exercises/shared/manage/exercise-paging.service'; @@ -7,7 +7,9 @@ import { ExercisePagingService } from 'app/exercises/shared/manage/exercise-pagi export class ModelingExercisePagingService extends ExercisePagingService { private static readonly RESOURCE_URL = 'api/modeling-exercises'; - constructor(http: HttpClient) { + constructor() { + const http = inject(HttpClient); + super(http, ModelingExercisePagingService.RESOURCE_URL); } } diff --git a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-resolver.service.ts b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-resolver.service.ts index 3744c119d2bc..7fa79cb8a351 100644 --- a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-resolver.service.ts +++ b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-resolver.service.ts @@ -5,7 +5,7 @@ import { ExerciseGroupService } from 'app/exam/manage/exercise-groups/exercise-g import { ExerciseGroup } from 'app/entities/exercise-group.model'; import { Course } from 'app/entities/course.model'; import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpResponse } from '@angular/common/http'; import { filter, map } from 'rxjs/operators'; import { of } from 'rxjs'; @@ -13,11 +13,9 @@ import { UMLDiagramType } from '@ls1intum/apollon'; @Injectable({ providedIn: 'root' }) export class ModelingExerciseResolver implements Resolve { - constructor( - private modelingExerciseService: ModelingExerciseService, - private courseService: CourseManagementService, - private exerciseGroupService: ExerciseGroupService, - ) {} + private modelingExerciseService = inject(ModelingExerciseService); + private courseService = inject(CourseManagementService); + private exerciseGroupService = inject(ExerciseGroupService); resolve(route: ActivatedRouteSnapshot) { if (route.params['exerciseId']) { diff --git a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-update.component.ts b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-update.component.ts index 18faee221f26..e5fb402000db 100644 --- a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-update.component.ts +++ b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise-update.component.ts @@ -1,7 +1,12 @@ -import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { HttpErrorResponse } from '@angular/common/http'; import { ModelingExercise } from 'app/entities/modeling-exercise.model'; +import { DifficultyPickerComponent } from 'app/exercises/shared/difficulty-picker/difficulty-picker.component'; +import { ExerciseFeedbackSuggestionOptionsComponent } from 'app/exercises/shared/feedback-suggestion/exercise-feedback-suggestion-options.component'; +import { IncludedInOverallScorePickerComponent } from 'app/exercises/shared/included-in-overall-score-picker/included-in-overall-score-picker.component'; +import { PresentationScoreComponent } from 'app/exercises/shared/presentation-score/presentation-score.component'; +import { GradingInstructionsDetailsComponent } from 'app/exercises/shared/structured-grading-criterion/grading-instructions-details/grading-instructions-details.component'; import { ModelingExerciseService } from './modeling-exercise.service'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { ExerciseService } from 'app/exercises/shared/exercise/exercise.service'; @@ -26,23 +31,69 @@ import { loadCourseExerciseCategories } from 'app/exercises/shared/course-exerci import { FormSectionStatus } from 'app/forms/form-status-bar/form-status-bar.component'; import { Subscription } from 'rxjs'; import { ExerciseTitleChannelNameComponent } from 'app/exercises/shared/exercise-title-channel-name/exercise-title-channel-name.component'; -import { NgModel } from '@angular/forms'; +import { FormsModule, NgModel } from '@angular/forms'; import { ExerciseUpdatePlagiarismComponent } from 'app/exercises/shared/plagiarism/exercise-update-plagiarism/exercise-update-plagiarism.component'; import { TeamConfigFormGroupComponent } from 'app/exercises/shared/team-config-form-group/team-config-form-group.component'; import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component'; import { FormulaAction } from 'app/shared/monaco-editor/model/actions/formula.action'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { FormStatusBarComponent } from 'app/forms/form-status-bar/form-status-bar.component'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { CategorySelectorComponent } from 'app/shared/category-selector/category-selector.component'; +import { MarkdownEditorMonacoComponent } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { CompetencySelectionComponent } from 'app/shared/competency-selection/competency-selection.component'; +import { CustomMinDirective } from 'app/shared/validators/custom-min-validator.directive'; +import { CustomMaxDirective } from 'app/shared/validators/custom-max-validator.directive'; +import { FormFooterComponent } from 'app/forms/form-footer/form-footer.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-modeling-exercise-update', templateUrl: './modeling-exercise-update.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + FormsModule, + TranslateDirective, + DocumentationButtonComponent, + FormStatusBarComponent, + ExerciseTitleChannelNameComponent, + HelpIconComponent, + CategorySelectorComponent, + DifficultyPickerComponent, + TeamConfigFormGroupComponent, + MarkdownEditorMonacoComponent, + CompetencySelectionComponent, + ModelingEditorComponent, + FormDateTimePickerComponent, + IncludedInOverallScorePickerComponent, + CustomMinDirective, + CustomMaxDirective, + ExerciseFeedbackSuggestionOptionsComponent, + ExerciseUpdatePlagiarismComponent, + PresentationScoreComponent, + GradingInstructionsDetailsComponent, + FormFooterComponent, + ArtemisTranslatePipe, + ], }) export class ModelingExerciseUpdateComponent implements AfterViewInit, OnDestroy, OnInit { + private alertService = inject(AlertService); + private modelingExerciseService = inject(ModelingExerciseService); + private modalService = inject(NgbModal); + private popupService = inject(ExerciseUpdateWarningService); + private courseService = inject(CourseManagementService); + private exerciseService = inject(ExerciseService); + private exerciseGroupService = inject(ExerciseGroupService); + private eventManager = inject(EventManager); + private activatedRoute = inject(ActivatedRoute); + private navigationUtilService = inject(ArtemisNavigationUtilService); + private changeDetectorRef = inject(ChangeDetectorRef); + @ViewChild(ExerciseTitleChannelNameComponent) exerciseTitleChannelNameComponent: ExerciseTitleChannelNameComponent; @ViewChild(ExerciseUpdatePlagiarismComponent) exerciseUpdatePlagiarismComponent?: ExerciseUpdatePlagiarismComponent; @ViewChild(TeamConfigFormGroupComponent) teamConfigFormGroupComponent?: TeamConfigFormGroupComponent; - @ViewChild(ModelingEditorComponent, { static: false }) - modelingEditor?: ModelingEditorComponent; + @ViewChild(ModelingEditorComponent, { static: false }) modelingEditor?: ModelingEditorComponent; @ViewChild('bonusPoints') bonusPoints?: NgModel; @ViewChild('points') points?: NgModel; @ViewChild('solutionPublicationDate') solutionPublicationDateField?: FormDateTimePickerComponent; @@ -80,20 +131,6 @@ export class ModelingExerciseUpdateComponent implements AfterViewInit, OnDestroy plagiarismSubscription?: Subscription; teamSubscription?: Subscription; - constructor( - private alertService: AlertService, - private modelingExerciseService: ModelingExerciseService, - private modalService: NgbModal, - private popupService: ExerciseUpdateWarningService, - private courseService: CourseManagementService, - private exerciseService: ExerciseService, - private exerciseGroupService: ExerciseGroupService, - private eventManager: EventManager, - private activatedRoute: ActivatedRoute, - private navigationUtilService: ArtemisNavigationUtilService, - private changeDetectorRef: ChangeDetectorRef, - ) {} - get editType(): EditType { if (this.isImport) { return EditType.IMPORT; diff --git a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.component.ts b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.component.ts index e1ea83ce136e..070f9134faf9 100644 --- a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.component.ts +++ b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.component.ts @@ -11,10 +11,20 @@ import { AlertService } from 'app/core/util/alert.service'; import { faBook, faPlus, faSort, faTable, faTimes, faTrash, faUsers, faWrench } from '@fortawesome/free-solid-svg-icons'; import { faListAlt } from '@fortawesome/free-regular-svg-icons'; import { CourseExerciseService } from 'app/exercises/shared/course-exercises/course-exercise.service'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { FormsModule } from '@angular/forms'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { RouterLink } from '@angular/router'; +import { ExerciseCategoriesComponent } from 'app/shared/exercise-categories/exercise-categories.component'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; @Component({ selector: 'jhi-modeling-exercise', templateUrl: './modeling-exercise.component.html', + imports: [SortDirective, FormsModule, SortByDirective, TranslateDirective, FaIconComponent, RouterLink, ExerciseCategoriesComponent, DeleteButtonDirective, ArtemisDatePipe], }) export class ModelingExerciseComponent extends ExerciseComponent { protected exerciseService = inject(ExerciseService); diff --git a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.module.ts b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.module.ts index 752915ce1096..3e5a9684b5b4 100644 --- a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.module.ts +++ b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.module.ts @@ -26,7 +26,7 @@ import { ExerciseUpdateNotificationModule } from 'app/exercises/shared/exercise- import { ExerciseUpdatePlagiarismModule } from 'app/exercises/shared/plagiarism/exercise-update-plagiarism/exercise-update-plagiarism.module'; import { DetailModule } from 'app/detail-overview-list/detail.module'; import { ArtemisExerciseModule } from 'app/exercises/shared/exercise/exercise.module'; -import { FormsModule } from 'app/forms/forms.module'; +import { ArtemisFormsModule } from 'app/forms/artemis-forms.module'; import { ExerciseFeedbackSuggestionOptionsModule } from 'app/exercises/shared/feedback-suggestion/exercise-feedback-suggestion-options.module'; @NgModule({ @@ -56,9 +56,11 @@ import { ExerciseFeedbackSuggestionOptionsModule } from 'app/exercises/shared/fe ExerciseUpdatePlagiarismModule, ExerciseFeedbackSuggestionOptionsModule, DetailModule, - FormsModule, + ArtemisFormsModule, + ModelingExerciseComponent, + ModelingExerciseDetailComponent, + ModelingExerciseUpdateComponent, ], - declarations: [ModelingExerciseComponent, ModelingExerciseDetailComponent, ModelingExerciseUpdateComponent], exports: [ModelingExerciseComponent], }) export class ArtemisModelingExerciseModule {} diff --git a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.route.ts b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.route.ts index 01b6d2a081bd..aae78b63a80b 100644 --- a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.route.ts +++ b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.route.ts @@ -1,18 +1,15 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { ModelingExerciseDetailComponent } from './modeling-exercise-detail.component'; -import { ModelingExerciseUpdateComponent } from 'app/exercises/modeling/manage/modeling-exercise-update.component'; -import { PlagiarismInspectorComponent } from 'app/exercises/shared/plagiarism/plagiarism-inspector/plagiarism-inspector.component'; + import { Authority } from 'app/shared/constants/authority.constants'; -import { ExerciseStatisticsComponent } from 'app/exercises/shared/statistics/exercise-statistics.component'; -import { ExampleSubmissionsComponent } from 'app/exercises/shared/example-submission/example-submissions.component'; + import { ModelingExerciseResolver } from 'app/exercises/modeling/manage/modeling-exercise-resolver.service'; export const routes: Routes = [ { path: ':courseId/modeling-exercises/new', - component: ModelingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/modeling/manage/modeling-exercise-update.component').then((m) => m.ModelingExerciseUpdateComponent), resolve: { modelingExercise: ModelingExerciseResolver, }, @@ -24,7 +21,7 @@ export const routes: Routes = [ }, { path: ':courseId/modeling-exercises/:exerciseId/edit', - component: ModelingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/modeling/manage/modeling-exercise-update.component').then((m) => m.ModelingExerciseUpdateComponent), resolve: { modelingExercise: ModelingExerciseResolver, }, @@ -36,7 +33,7 @@ export const routes: Routes = [ }, { path: ':courseId/modeling-exercises/:exerciseId/import', - component: ModelingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/modeling/manage/modeling-exercise-update.component').then((m) => m.ModelingExerciseUpdateComponent), resolve: { modelingExercise: ModelingExerciseResolver, }, @@ -48,7 +45,7 @@ export const routes: Routes = [ }, { path: ':courseId/modeling-exercises/:exerciseId', - component: ModelingExerciseDetailComponent, + loadComponent: () => import('./modeling-exercise-detail.component').then((m) => m.ModelingExerciseDetailComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.modelingExercise.home.title', @@ -57,7 +54,7 @@ export const routes: Routes = [ }, { path: ':courseId/modeling-exercises/:exerciseId/example-submissions', - component: ExampleSubmissionsComponent, + loadComponent: () => import('app/exercises/shared/example-submission/example-submissions.component').then((m) => m.ExampleSubmissionsComponent), resolve: { exercise: ModelingExerciseResolver, }, @@ -69,7 +66,7 @@ export const routes: Routes = [ }, { path: ':courseId/modeling-exercises/:exerciseId/plagiarism', - component: PlagiarismInspectorComponent, + loadComponent: () => import('app/exercises/shared/plagiarism/plagiarism-inspector/plagiarism-inspector.component').then((m) => m.PlagiarismInspectorComponent), resolve: { exercise: ModelingExerciseResolver, }, @@ -85,7 +82,7 @@ export const routes: Routes = [ }, { path: ':courseId/modeling-exercises/:exerciseId/exercise-statistics', - component: ExerciseStatisticsComponent, + loadComponent: () => import('app/exercises/shared/statistics/exercise-statistics.component').then((m) => m.ExerciseStatisticsComponent), resolve: { exercise: ModelingExerciseResolver, }, diff --git a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.service.ts b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.service.ts index a56210f6e655..da4833981af3 100644 --- a/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.service.ts +++ b/src/main/webapp/app/exercises/modeling/manage/modeling-exercise.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map, tap } from 'rxjs/operators'; @@ -15,13 +15,15 @@ export type EntityArrayResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class ModelingExerciseService implements ExerciseServicable { + private http = inject(HttpClient); + private exerciseService = inject(ExerciseService); + public resourceUrl = 'api/modeling-exercises'; public adminResourceUrl = 'api/admin/modeling-exercises'; - constructor( - private http: HttpClient, - private exerciseService: ExerciseService, - ) { + constructor() { + const exerciseService = this.exerciseService; + this.exerciseService = exerciseService; } diff --git a/src/main/webapp/app/exercises/modeling/participate/modeling-participation.module.ts b/src/main/webapp/app/exercises/modeling/participate/modeling-participation.module.ts index f558adc3103e..be5a3969b048 100644 --- a/src/main/webapp/app/exercises/modeling/participate/modeling-participation.module.ts +++ b/src/main/webapp/app/exercises/modeling/participate/modeling-participation.module.ts @@ -8,7 +8,7 @@ import { ArtemisModelingEditorModule } from 'app/exercises/modeling/shared/model import { ModelingAssessmentModule } from 'app/exercises/modeling/assess/modeling-assessment.module'; import { ArtemisModelingParticipationRoutingModule } from 'app/exercises/modeling/participate/modeling-participation.route'; import { ArtemisHeaderExercisePageWithDetailsModule } from 'app/exercises/shared/exercise-headers/exercise-headers.module'; -import { ArtemisTeamSubmissionSyncModule } from 'app/exercises/shared/team-submission-sync/team-submission-sync.module'; + import { ArtemisFullscreenModule } from 'app/shared/fullscreen/fullscreen.module'; import { RatingModule } from 'app/exercises/shared/rating/rating.module'; import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; @@ -25,14 +25,13 @@ import { RequestFeedbackButtonComponent } from 'app/overview/exercise-details/re ArtemisModelingParticipationRoutingModule, ArtemisHeaderExercisePageWithDetailsModule, ModelingAssessmentModule, - ArtemisTeamSubmissionSyncModule, ArtemisFullscreenModule, RatingModule, ArtemisMarkdownModule, ArtemisTeamParticipeModule, RequestFeedbackButtonComponent, + ModelingSubmissionComponent, ], - declarations: [ModelingSubmissionComponent], exports: [ModelingSubmissionComponent], }) export class ArtemisModelingParticipationModule {} diff --git a/src/main/webapp/app/exercises/modeling/participate/modeling-participation.route.ts b/src/main/webapp/app/exercises/modeling/participate/modeling-participation.route.ts index 1c460eee70b0..d8cdb2396651 100644 --- a/src/main/webapp/app/exercises/modeling/participate/modeling-participation.route.ts +++ b/src/main/webapp/app/exercises/modeling/participate/modeling-participation.route.ts @@ -2,13 +2,13 @@ import { NgModule } from '@angular/core'; import { PendingChangesGuard } from 'app/shared/guard/pending-changes.guard'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; import { RouterModule, Routes } from '@angular/router'; -import { ModelingSubmissionComponent } from './modeling-submission.component'; + import { Authority } from 'app/shared/constants/authority.constants'; export const routes: Routes = [ { path: 'participate/:participationId', - component: ModelingSubmissionComponent, + loadComponent: () => import('./modeling-submission.component').then((m) => m.ModelingSubmissionComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.modelingExercise.home.title', @@ -18,7 +18,7 @@ export const routes: Routes = [ }, { path: 'participate/:participationId/submission/:submissionId', - component: ModelingSubmissionComponent, + loadComponent: () => import('./modeling-submission.component').then((m) => m.ModelingSubmissionComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.modelingExercise.home.title', diff --git a/src/main/webapp/app/exercises/modeling/participate/modeling-submission.component.ts b/src/main/webapp/app/exercises/modeling/participate/modeling-submission.component.ts index b77b05f098dd..091e3ecb34da 100644 --- a/src/main/webapp/app/exercises/modeling/participate/modeling-submission.component.ts +++ b/src/main/webapp/app/exercises/modeling/participate/modeling-submission.component.ts @@ -1,6 +1,6 @@ import { HttpErrorResponse } from '@angular/common/http'; -import { Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { Component, Input, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { Patch, Selection, UMLDiagramType, UMLElementType, UMLModel, UMLRelationshipType } from '@ls1intum/apollon'; import { TranslateService } from '@ngx-translate/core'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; @@ -14,9 +14,13 @@ import { getFirstResultWithComplaint, getLatestSubmissionResult } from 'app/enti import { ModelingAssessmentService } from 'app/exercises/modeling/assess/modeling-assessment.service'; import { ModelingSubmissionService } from 'app/exercises/modeling/participate/modeling-submission.service'; import { ModelingEditorComponent } from 'app/exercises/modeling/shared/modeling-editor.component'; +import { HeaderParticipationPageComponent } from 'app/exercises/shared/exercise-headers/header-participation-page.component'; import { getExerciseDueDate, hasExerciseDueDatePassed } from 'app/exercises/shared/exercise/exercise.utils'; +import { RatingComponent } from 'app/exercises/shared/rating/rating.component'; import { addParticipationToResult, getUnreferencedFeedback } from 'app/exercises/shared/result/result.utils'; import { AccountService } from 'app/core/auth/account.service'; +import { TeamSubmissionSyncComponent } from 'app/exercises/shared/team-submission-sync/team-submission-sync.component'; +import { TeamParticipateInfoBoxComponent } from 'app/exercises/shared/team/team-participate/team-participate-info-box.component'; import { GuidedTourService } from 'app/guided-tour/guided-tour.service'; import { modelingTour } from 'app/guided-tour/tours/modeling-tour'; import { ParticipationWebsocketService } from 'app/overview/participation-websocket.service'; @@ -39,20 +43,66 @@ import { AssessmentType } from 'app/entities/assessment-type.model'; import { catchError, filter, skip, switchMap, tap } from 'rxjs/operators'; import { onError } from 'app/shared/util/global.utils'; import { of } from 'rxjs'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { RequestFeedbackButtonComponent } from 'app/overview/exercise-details/request-feedback-button/request-feedback-button.component'; +import { ResultHistoryComponent } from 'app/overview/result-history/result-history.component'; +import { ResizeableContainerComponent } from 'app/shared/resizeable-container/resizeable-container.component'; +import { FullscreenComponent } from 'app/shared/fullscreen/fullscreen.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ModelingAssessmentComponent } from '../assess/modeling-assessment.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DecimalPipe, NgClass } from '@angular/common'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { AdditionalFeedbackComponent } from 'app/shared/additional-feedback/additional-feedback.component'; +import { ComplaintsStudentViewComponent } from 'app/complaints/complaints-for-students/complaints-student-view.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-modeling-submission', templateUrl: './modeling-submission.component.html', styleUrls: ['./modeling-submission.component.scss'], + imports: [ + HeaderParticipationPageComponent, + ButtonComponent, + RouterLink, + RequestFeedbackButtonComponent, + ResultHistoryComponent, + ResizeableContainerComponent, + TeamParticipateInfoBoxComponent, + FullscreenComponent, + ModelingEditorComponent, + FaIconComponent, + TeamSubmissionSyncComponent, + ModelingAssessmentComponent, + TranslateDirective, + NgClass, + NgbTooltip, + AdditionalFeedbackComponent, + RatingComponent, + ComplaintsStudentViewComponent, + DecimalPipe, + ArtemisTranslatePipe, + HtmlForMarkdownPipe, + ], }) export class ModelingSubmissionComponent implements OnInit, OnDestroy, ComponentCanDeactivate { + private jhiWebsocketService = inject(JhiWebsocketService); + private modelingSubmissionService = inject(ModelingSubmissionService); + private modelingAssessmentService = inject(ModelingAssessmentService); + private alertService = inject(AlertService); + private route = inject(ActivatedRoute); + private translateService = inject(TranslateService); + private participationWebsocketService = inject(ParticipationWebsocketService); + private guidedTourService = inject(GuidedTourService); + private accountService = inject(AccountService); + readonly addParticipationToResult = addParticipationToResult; readonly buildFeedbackTextForReview = buildFeedbackTextForReview; - - @ViewChild(ModelingEditorComponent, { static: false }) - modelingEditor: ModelingEditorComponent; ButtonType = ButtonType; + @ViewChild(ModelingEditorComponent, { static: false }) modelingEditor: ModelingEditorComponent; + @Input() participationId?: number; @Input() displayHeader: boolean = true; @Input() isPrinting?: boolean = false; @@ -127,17 +177,7 @@ export class ModelingSubmissionComponent implements OnInit, OnDestroy, Component isFeedbackView: boolean = false; showResultHistory: boolean = false; - constructor( - private jhiWebsocketService: JhiWebsocketService, - private modelingSubmissionService: ModelingSubmissionService, - private modelingAssessmentService: ModelingAssessmentService, - private alertService: AlertService, - private route: ActivatedRoute, - private translateService: TranslateService, - private participationWebsocketService: ParticipationWebsocketService, - private guidedTourService: GuidedTourService, - private accountService: AccountService, - ) { + constructor() { this.isSaving = false; this.autoSaveTimer = 0; this.isLoading = true; diff --git a/src/main/webapp/app/exercises/modeling/participate/modeling-submission.service.ts b/src/main/webapp/app/exercises/modeling/participate/modeling-submission.service.ts index 9da063181dbe..2fb2188d001c 100644 --- a/src/main/webapp/app/exercises/modeling/participate/modeling-submission.service.ts +++ b/src/main/webapp/app/exercises/modeling/participate/modeling-submission.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -12,12 +12,10 @@ export type EntityResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class ModelingSubmissionService { - public resourceUrl = 'api'; + private http = inject(HttpClient); + private submissionService = inject(SubmissionService); - constructor( - private http: HttpClient, - private submissionService: SubmissionService, - ) {} + public resourceUrl = 'api'; /** * Create a new modeling submission diff --git a/src/main/webapp/app/exercises/modeling/shared/modeling-editor.component.ts b/src/main/webapp/app/exercises/modeling/shared/modeling-editor.component.ts index f9e488df0298..09c5b76ce6b3 100644 --- a/src/main/webapp/app/exercises/modeling/shared/modeling-editor.component.ts +++ b/src/main/webapp/app/exercises/modeling/shared/modeling-editor.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, EventEmitter, Input, OnChanges, OnDestroy, Output, SimpleChanges, ViewEncapsulation } from '@angular/core'; +import { AfterViewInit, Component, EventEmitter, Input, OnChanges, OnDestroy, Output, SimpleChanges, ViewEncapsulation, inject } from '@angular/core'; import { ApollonEditor, ApollonMode, SVG, UMLDiagramType, UMLElementType, UMLModel, UMLRelationship, UMLRelationshipType } from '@ls1intum/apollon'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { associationUML, personUML, studentUML } from 'app/guided-tour/guided-tour-task.model'; @@ -9,14 +9,23 @@ import { faQuestionCircle } from '@fortawesome/free-regular-svg-icons'; import { ModelingComponent } from 'app/exercises/modeling/shared/modeling.component'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { Patch } from '@ls1intum/apollon'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgClass, NgStyle } from '@angular/common'; +import { ModelingExplanationEditorComponent } from './modeling-explanation-editor.component'; @Component({ selector: 'jhi-modeling-editor', templateUrl: './modeling-editor.component.html', styleUrls: ['./modeling-editor.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [TranslateDirective, FaIconComponent, NgStyle, NgClass, ModelingExplanationEditorComponent], }) export class ModelingEditorComponent extends ModelingComponent implements AfterViewInit, OnDestroy, OnChanges { + private modalService = inject(NgbModal); + private guidedTourService = inject(GuidedTourService); + private sanitizer = inject(DomSanitizer); + @Input() showHelpButton = true; @Input() withExplanation = false; @Input() savedStatus?: { isChanged?: boolean; isSaving?: boolean }; @@ -42,11 +51,7 @@ export class ModelingEditorComponent extends ModelingComponent implements AfterV readonlyApollonDiagram?: SVG; readOnlySVG?: SafeHtml; - constructor( - private modalService: NgbModal, - private guidedTourService: GuidedTourService, - private sanitizer: DomSanitizer, - ) { + constructor() { super(); } diff --git a/src/main/webapp/app/exercises/modeling/shared/modeling-editor.module.ts b/src/main/webapp/app/exercises/modeling/shared/modeling-editor.module.ts index 832db40470c3..6567fa4b7efb 100644 --- a/src/main/webapp/app/exercises/modeling/shared/modeling-editor.module.ts +++ b/src/main/webapp/app/exercises/modeling/shared/modeling-editor.module.ts @@ -4,8 +4,7 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ModelingExplanationEditorComponent } from './modeling-explanation-editor.component'; @NgModule({ - imports: [ArtemisSharedModule], - declarations: [ModelingEditorComponent, ModelingExplanationEditorComponent], + imports: [ArtemisSharedModule, ModelingEditorComponent, ModelingExplanationEditorComponent], exports: [ModelingEditorComponent, ModelingExplanationEditorComponent], }) export class ArtemisModelingEditorModule {} diff --git a/src/main/webapp/app/exercises/modeling/shared/modeling-explanation-editor.component.ts b/src/main/webapp/app/exercises/modeling/shared/modeling-explanation-editor.component.ts index 3319f4d2b399..ec8c3caa9d26 100644 --- a/src/main/webapp/app/exercises/modeling/shared/modeling-explanation-editor.component.ts +++ b/src/main/webapp/app/exercises/modeling/shared/modeling-explanation-editor.component.ts @@ -1,10 +1,13 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { MAX_SUBMISSION_TEXT_LENGTH } from 'app/shared/constants/input.constants'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; @Component({ selector: 'jhi-modeling-explanation-editor', templateUrl: './modeling-explanation-editor.component.html', styleUrls: ['./modeling-explanation-editor.component.scss'], + imports: [TranslateDirective, FormsModule], }) export class ModelingExplanationEditorComponent { @Input() diff --git a/src/main/webapp/app/exercises/modeling/shared/modeling.component.ts b/src/main/webapp/app/exercises/modeling/shared/modeling.component.ts index 51d061c46cdc..667f25718fc6 100644 --- a/src/main/webapp/app/exercises/modeling/shared/modeling.component.ts +++ b/src/main/webapp/app/exercises/modeling/shared/modeling.component.ts @@ -4,7 +4,9 @@ import { ApollonEditor, UMLDiagramType, UMLModel } from '@ls1intum/apollon'; import { MODELING_EDITOR_MAX_HEIGHT, MODELING_EDITOR_MAX_WIDTH, MODELING_EDITOR_MIN_HEIGHT, MODELING_EDITOR_MIN_WIDTH } from 'app/shared/constants/modeling.constants'; import interact from 'interactjs'; -@Component({ template: '' }) +@Component({ + template: '', +}) export abstract class ModelingComponent { @ViewChild('editorContainer', { static: false }) editorContainer: ElementRef; @ViewChild('resizeContainer', { static: false }) resizeContainer: ElementRef; @@ -20,8 +22,6 @@ export abstract class ModelingComponent { faGripLines = faGripLines; faGripLinesVertical = faGripLinesVertical; - protected constructor() {} - protected setupInteract(): void { if (this.resizeOptions) { interact('.resizable') diff --git a/src/main/webapp/app/exercises/programming/assess/code-editor-tutor-assessment-container.component.html b/src/main/webapp/app/exercises/programming/assess/code-editor-tutor-assessment-container.component.html index 9382ac324adf..0ce53d07531a 100644 --- a/src/main/webapp/app/exercises/programming/assess/code-editor-tutor-assessment-container.component.html +++ b/src/main/webapp/app/exercises/programming/assess/code-editor-tutor-assessment-container.component.html @@ -52,35 +52,36 @@ - - @if (!loadingParticipation && !participationCouldNotBeFetched) { - -
-
- -
-
- } -
+ + + + + + + + @if (!loadingParticipation && !participationCouldNotBeFetched) { + +
+
+ +
+
+ } + @@ -97,28 +98,29 @@ - - @if (isAtLeastEditor && localVCEnabled && !isTestRun) { -
- - - - } - - @if (isAtLeastEditor && !localVCEnabled) { - - } - + + + @if (isAtLeastEditor && localVCEnabled && !isTestRun) { + + + + + } + + @if (isAtLeastEditor && !localVCEnabled) { + + } + @if (participation) { ; - @ContentChild('overrideExportGoToRepository') overrideExportGoToRepository: TemplateRef; + // TODO: the extension point for Orion does not work with Angular 19, we need to find a different solution + // @ContentChild('overrideCodeEditor') overrideCodeEditor: TemplateRef; + // @ContentChild('overrideExportGoToRepository') overrideExportGoToRepository: TemplateRef; // listener, will get notified upon loading of feedback @Output() onFeedbackLoaded = new EventEmitter(); // function override, if set will be executed instead of going to the next submission page @@ -122,24 +162,9 @@ export class CodeEditorTutorAssessmentContainerComponent implements OnInit, OnDe return this.feedbackSuggestions.filter((feedback) => !feedback.reference); } - constructor( - private manualResultService: ProgrammingAssessmentManualResultService, - private router: Router, - private location: Location, - private accountService: AccountService, - private programmingSubmissionService: ProgrammingSubmissionService, - private domainService: DomainService, - private complaintService: ComplaintService, - private route: ActivatedRoute, - private alertService: AlertService, - private structuredGradingCriterionService: StructuredGradingCriterionService, - private repositoryFileService: CodeEditorRepositoryFileService, - private programmingExerciseService: ProgrammingExerciseService, - private profileService: ProfileService, - private modalService: NgbModal, - private athenaService: AthenaService, - translateService: TranslateService, - ) { + constructor() { + const translateService = inject(TranslateService); + translateService.get('artemisApp.assessment.messages.confirmCancel').subscribe((text) => (this.cancelConfirmationText = text)); translateService.get('artemisApp.assessment.messages.acceptComplaintWithoutMoreScore').subscribe((text) => (this.acceptComplaintWithoutMoreScoreText = text)); } diff --git a/src/main/webapp/app/exercises/programming/assess/code-editor-tutor-assessment-inline-feedback-suggestion.component.ts b/src/main/webapp/app/exercises/programming/assess/code-editor-tutor-assessment-inline-feedback-suggestion.component.ts index 5bef12933962..f15f909d7bff 100644 --- a/src/main/webapp/app/exercises/programming/assess/code-editor-tutor-assessment-inline-feedback-suggestion.component.ts +++ b/src/main/webapp/app/exercises/programming/assess/code-editor-tutor-assessment-inline-feedback-suggestion.component.ts @@ -1,13 +1,17 @@ -import { Component, ElementRef, EventEmitter, Input, Output } from '@angular/core'; +import { Component, ElementRef, EventEmitter, Input, Output, inject } from '@angular/core'; import { Feedback, buildFeedbackTextForReview } from 'app/entities/feedback.model'; +import { FeedbackSuggestionBadgeComponent } from 'app/exercises/shared/feedback/feedback-suggestion-badge/feedback-suggestion-badge.component'; import { roundValueSpecifiedByCourseSettings } from 'app/shared/util/utils'; import { Course } from 'app/entities/course.model'; import { faCheck, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-code-editor-tutor-assessment-inline-feedback-suggestion', templateUrl: './code-editor-tutor-assessment-inline-feedback-suggestion.component.html', styleUrls: ['./code-editor-tutor-assessment-inline-feedback-suggestion.component.scss'], + imports: [FeedbackSuggestionBadgeComponent, TranslateDirective, FaIconComponent], }) export class CodeEditorTutorAssessmentInlineFeedbackSuggestionComponent { @Input() @@ -30,9 +34,12 @@ export class CodeEditorTutorAssessmentInlineFeedbackSuggestionComponent { faCheck = faCheck; faTrash = faTrash; - public elementRef: ElementRef; // Needed for the outer editor to access the DOM node of this component + public elementRef: ElementRef; + // Needed for the outer editor to access the DOM node of this component + + constructor() { + const elementRef = inject(ElementRef); - constructor(elementRef: ElementRef) { this.elementRef = elementRef; } } diff --git a/src/main/webapp/app/exercises/programming/assess/code-editor-tutor-assessment-inline-feedback.component.ts b/src/main/webapp/app/exercises/programming/assess/code-editor-tutor-assessment-inline-feedback.component.ts index 1687051aa12e..f1eae56d3400 100644 --- a/src/main/webapp/app/exercises/programming/assess/code-editor-tutor-assessment-inline-feedback.component.ts +++ b/src/main/webapp/app/exercises/programming/assess/code-editor-tutor-assessment-inline-feedback.component.ts @@ -1,5 +1,6 @@ -import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core'; +import { Component, ElementRef, EventEmitter, Input, Output, ViewChild, inject } from '@angular/core'; import { Feedback, FeedbackType, buildFeedbackTextForReview } from 'app/entities/feedback.model'; +import { FeedbackSuggestionBadgeComponent } from 'app/exercises/shared/feedback/feedback-suggestion-badge/feedback-suggestion-badge.component'; import { ButtonSize } from 'app/shared/components/button.component'; import { cloneDeep } from 'lodash-es'; import { TranslateService } from '@ngx-translate/core'; @@ -8,12 +9,38 @@ import { roundValueSpecifiedByCourseSettings } from 'app/shared/util/utils'; import { Course } from 'app/entities/course.model'; import { faBan, faExclamationTriangle, faPencilAlt, faQuestionCircle, faSave, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; import { Subject } from 'rxjs'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { GradingInstructionLinkIconComponent } from 'app/shared/grading-instruction-link-icon/grading-instruction-link-icon.component'; +import { FormsModule } from '@angular/forms'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { AssessmentCorrectionRoundBadgeComponent } from 'app/assessment/unreferenced-feedback-detail/assessment-correction-round-badge/assessment-correction-round-badge.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { FeedbackContentPipe } from 'app/shared/pipes/feedback-content.pipe'; +import { QuotePipe } from 'app/shared/pipes/quote.pipe'; @Component({ selector: 'jhi-code-editor-tutor-assessment-inline-feedback', templateUrl: './code-editor-tutor-assessment-inline-feedback.component.html', + imports: [ + FeedbackSuggestionBadgeComponent, + TranslateDirective, + FaIconComponent, + NgbTooltip, + GradingInstructionLinkIconComponent, + FormsModule, + DeleteButtonDirective, + AssessmentCorrectionRoundBadgeComponent, + ArtemisTranslatePipe, + FeedbackContentPipe, + QuotePipe, + ], }) export class CodeEditorTutorAssessmentInlineFeedbackComponent { + private translateService = inject(TranslateService); + structuredGradingCriterionService = inject(StructuredGradingCriterionService); + @Input() get feedback(): Feedback { return this._feedback; @@ -66,11 +93,9 @@ export class CodeEditorTutorAssessmentInlineFeedbackComponent { faTrashAlt = faTrashAlt; faExclamationTriangle = faExclamationTriangle; - constructor( - private translateService: TranslateService, - public structuredGradingCriterionService: StructuredGradingCriterionService, - elementRef: ElementRef, - ) { + constructor() { + const elementRef = inject(ElementRef); + this.elementRef = elementRef; } diff --git a/src/main/webapp/app/exercises/programming/assess/manual-result/programming-assessment-manual-result.service.ts b/src/main/webapp/app/exercises/programming/assess/manual-result/programming-assessment-manual-result.service.ts index 220f3818fddf..251aa5892a57 100644 --- a/src/main/webapp/app/exercises/programming/assess/manual-result/programming-assessment-manual-result.service.ts +++ b/src/main/webapp/app/exercises/programming/assess/manual-result/programming-assessment-manual-result.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { HttpClient, HttpParams } from '@angular/common/http'; import { ComplaintResponse } from 'app/entities/complaint-response.model'; @@ -9,12 +9,12 @@ import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class ProgrammingAssessmentManualResultService { + private http = inject(HttpClient); + private resultService = inject(ResultService); + private resourceUrl = 'api'; + // TODO: It would be good to refactor the convertDate methods into a separate service, so that we don't have to import the result service here. - constructor( - private http: HttpClient, - private resultService: ResultService, - ) {} /** * Saves a new manual result and stores it in the server diff --git a/src/main/webapp/app/exercises/programming/assess/programming-assessment.module.ts b/src/main/webapp/app/exercises/programming/assess/programming-assessment.module.ts index 7ae991b6ac22..af0ce2f667ea 100644 --- a/src/main/webapp/app/exercises/programming/assess/programming-assessment.module.ts +++ b/src/main/webapp/app/exercises/programming/assess/programming-assessment.module.ts @@ -3,7 +3,7 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { FormDateTimePickerModule } from 'app/shared/date-time-picker/date-time-picker.module'; import { FormsModule } from '@angular/forms'; -import { FeatureToggleModule } from 'app/shared/feature-toggle/feature-toggle.module'; + import { ProgrammingAssessmentRepoExportButtonComponent } from 'app/exercises/programming/assess/repo-export/programming-assessment-repo-export-button.component'; import { ProgrammingAssessmentRepoExportDialogComponent } from 'app/exercises/programming/assess/repo-export/programming-assessment-repo-export-dialog.component'; import { ArtemisProgrammingAssessmentRoutingModule } from 'app/exercises/programming/assess/programming-assessment.route'; @@ -25,7 +25,6 @@ import { ComplaintsForTutorComponent } from 'app/complaints/complaints-for-tutor ArtemisSharedComponentModule, FormDateTimePickerModule, FormsModule, - FeatureToggleModule, ComplaintsForTutorComponent, ArtemisProgrammingAssessmentRoutingModule, ArtemisAssessmentSharedModule, @@ -36,8 +35,6 @@ import { ComplaintsForTutorComponent } from 'app/complaints/complaints-for-tutor AssessmentInstructionsModule, ArtemisHeaderExercisePageWithDetailsModule, SubmissionResultStatusModule, - ], - declarations: [ ProgrammingAssessmentRepoExportButtonComponent, ProgrammingAssessmentRepoExportDialogComponent, CodeEditorTutorAssessmentContainerComponent, diff --git a/src/main/webapp/app/exercises/programming/assess/programming-manual-assessment.module.ts b/src/main/webapp/app/exercises/programming/assess/programming-manual-assessment.module.ts index c33d739891c9..d53486a4a31a 100644 --- a/src/main/webapp/app/exercises/programming/assess/programming-manual-assessment.module.ts +++ b/src/main/webapp/app/exercises/programming/assess/programming-manual-assessment.module.ts @@ -20,8 +20,9 @@ import { QuotePipe } from 'app/shared/pipes/quote.pipe'; ArtemisFeedbackModule, FeedbackContentPipe, QuotePipe, + CodeEditorTutorAssessmentInlineFeedbackComponent, + CodeEditorTutorAssessmentInlineFeedbackSuggestionComponent, ], - declarations: [CodeEditorTutorAssessmentInlineFeedbackComponent, CodeEditorTutorAssessmentInlineFeedbackSuggestionComponent], exports: [CodeEditorTutorAssessmentInlineFeedbackComponent, CodeEditorTutorAssessmentInlineFeedbackSuggestionComponent], }) export class ArtemisProgrammingManualAssessmentModule {} diff --git a/src/main/webapp/app/exercises/programming/assess/repo-export/programming-assessment-repo-export-button.component.ts b/src/main/webapp/app/exercises/programming/assess/repo-export/programming-assessment-repo-export-button.component.ts index 9a2b5af07fb0..38cc387c67a4 100644 --- a/src/main/webapp/app/exercises/programming/assess/repo-export/programming-assessment-repo-export-button.component.ts +++ b/src/main/webapp/app/exercises/programming/assess/repo-export/programming-assessment-repo-export-button.component.ts @@ -1,10 +1,11 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output, inject } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { ProgrammingAssessmentRepoExportDialogComponent } from 'app/exercises/programming/assess/repo-export/programming-assessment-repo-export-dialog.component'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; import { faDownload } from '@fortawesome/free-solid-svg-icons'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; +import { ButtonComponent } from 'app/shared/components/button.component'; @Component({ selector: 'jhi-programming-assessment-repo-export', @@ -20,8 +21,11 @@ import { ProgrammingExercise } from 'app/entities/programming/programming-exerci (onClick)="openRepoExportDialog($event)" /> `, + imports: [ButtonComponent], }) export class ProgrammingAssessmentRepoExportButtonComponent { + private modalService = inject(NgbModal); + readonly ButtonType = ButtonType; readonly ButtonSize = ButtonSize; readonly FeatureToggle = FeatureToggle; @@ -36,8 +40,6 @@ export class ProgrammingAssessmentRepoExportButtonComponent { // Icons faDownload = faDownload; - constructor(private modalService: NgbModal) {} - /** * Stops the propagation of the mouse event and updates the component instance * of the modalRef with this instance's values diff --git a/src/main/webapp/app/exercises/programming/assess/repo-export/programming-assessment-repo-export-dialog.component.ts b/src/main/webapp/app/exercises/programming/assess/repo-export/programming-assessment-repo-export-dialog.component.ts index e61c909e6893..41451632ef5e 100644 --- a/src/main/webapp/app/exercises/programming/assess/repo-export/programming-assessment-repo-export-dialog.component.ts +++ b/src/main/webapp/app/exercises/programming/assess/repo-export/programming-assessment-repo-export-dialog.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { AlertService } from 'app/core/util/alert.service'; import { ProgrammingAssessmentRepoExportService, RepositoryExportOptions } from 'app/exercises/programming/assess/repo-export/programming-assessment-repo-export.service'; @@ -8,13 +8,25 @@ import { ProgrammingExercise } from 'app/entities/programming/programming-exerci import { ExerciseService } from 'app/exercises/shared/exercise/exercise.service'; import { downloadZipFileFromResponse } from 'app/shared/util/download.util'; import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component'; +import { FeatureToggleDirective } from 'app/shared/feature-toggle/feature-toggle.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-exercise-scores-repo-export-dialog', templateUrl: './programming-assessment-repo-export-dialog.component.html', styles: ['textarea { width: 100%; }'], + imports: [FormsModule, TranslateDirective, HelpIconComponent, FormDateTimePickerComponent, FeatureToggleDirective, FaIconComponent], }) export class ProgrammingAssessmentRepoExportDialogComponent implements OnInit { + private exerciseService = inject(ExerciseService); + private repoExportService = inject(ProgrammingAssessmentRepoExportService); + activeModal = inject(NgbActiveModal); + private alertService = inject(AlertService); + @Input() programmingExercises: ProgrammingExercise[]; // Either a participationId list or a participantIdentifier (student login or team short name) list can be provided that is used for exporting the repos. // Priority: participationId >> participantIdentifier. @@ -31,13 +43,6 @@ export class ProgrammingAssessmentRepoExportDialogComponent implements OnInit { // Icons faCircleNotch = faCircleNotch; - constructor( - private exerciseService: ExerciseService, - private repoExportService: ProgrammingAssessmentRepoExportService, - public activeModal: NgbActiveModal, - private alertService: AlertService, - ) {} - ngOnInit() { this.isLoading = true; this.exportInProgress = false; diff --git a/src/main/webapp/app/exercises/programming/assess/repo-export/programming-assessment-repo-export.service.ts b/src/main/webapp/app/exercises/programming/assess/repo-export/programming-assessment-repo-export.service.ts index 03a0e49a2bdb..83045e49cf77 100644 --- a/src/main/webapp/app/exercises/programming/assess/repo-export/programming-assessment-repo-export.service.ts +++ b/src/main/webapp/app/exercises/programming/assess/repo-export/programming-assessment-repo-export.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import dayjs from 'dayjs/esm'; @@ -16,11 +16,11 @@ export type RepositoryExportOptions = { @Injectable({ providedIn: 'root' }) export class ProgrammingAssessmentRepoExportService { + private http = inject(HttpClient); + // TODO: We should move this endpoint to api/programming-exercises. public resourceUrl = 'api/programming-exercises'; - constructor(private http: HttpClient) {} - /** * Exports repositories to the server by their participant identifiers * @param {number} exerciseId - Id of the exercise diff --git a/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-file-panel-title.component.ts b/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-file-panel-title.component.ts index 74b0f35dfab0..4ff117dc795b 100644 --- a/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-file-panel-title.component.ts +++ b/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-file-panel-title.component.ts @@ -12,7 +12,6 @@ enum FileStatus { selector: 'jhi-git-diff-file-panel-title', templateUrl: './git-diff-file-panel-title.component.html', styleUrls: ['./git-diff-file-panel-title.component.scss'], - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [TranslateDirective, CommonModule], }) diff --git a/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-file-panel.component.ts b/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-file-panel.component.ts index 0417e9239618..8f3ae5c388f7 100644 --- a/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-file-panel.component.ts +++ b/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-file-panel.component.ts @@ -5,15 +5,15 @@ import { GitDiffFilePanelTitleComponent } from 'app/exercises/programming/git-di import { GitDiffLineStatComponent } from 'app/exercises/programming/git-diff-report/git-diff-line-stat.component'; import { GitDiffFileComponent } from 'app/exercises/programming/git-diff-report/git-diff-file.component'; import { ArtemisSharedModule } from 'app/shared/shared.module'; +import { NgbAccordionModule, NgbCollapse } from '@ng-bootstrap/ng-bootstrap'; @Component({ selector: 'jhi-git-diff-file-panel', templateUrl: './git-diff-file-panel.component.html', styleUrls: ['./git-diff-file-panel.component.scss'], encapsulation: ViewEncapsulation.None, - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, - imports: [GitDiffFilePanelTitleComponent, GitDiffLineStatComponent, GitDiffFileComponent, ArtemisSharedModule], + imports: [GitDiffFilePanelTitleComponent, GitDiffLineStatComponent, GitDiffFileComponent, ArtemisSharedModule, NgbAccordionModule, NgbCollapse], }) export class GitDiffFilePanelComponent { protected readonly faAngleUp = faAngleUp; diff --git a/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-file.component.ts b/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-file.component.ts index 055875de5a6a..5125c6078782 100644 --- a/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-file.component.ts +++ b/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-file.component.ts @@ -7,7 +7,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; selector: 'jhi-git-diff-file', templateUrl: './git-diff-file.component.html', encapsulation: ViewEncapsulation.None, - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MonacoDiffEditorComponent, TranslateDirective], }) diff --git a/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-line-stat.component.ts b/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-line-stat.component.ts index b82ab8d02c02..4711b1fef884 100644 --- a/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-line-stat.component.ts +++ b/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-line-stat.component.ts @@ -4,7 +4,6 @@ import { ChangeDetectionStrategy, Component, computed, input } from '@angular/co selector: 'jhi-git-diff-line-stat', templateUrl: './git-diff-line-stat.component.html', styleUrls: ['./git-diff-line-stat.component.scss'], - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, }) export class GitDiffLineStatComponent { diff --git a/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-report-modal.component.ts b/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-report-modal.component.ts index 96a16d6986ee..268a63c97a24 100644 --- a/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-report-modal.component.ts +++ b/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-report-modal.component.ts @@ -11,7 +11,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-git-diff-report-modal', templateUrl: './git-diff-report-modal.component.html', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [GitDiffReportComponent, TranslateDirective], }) @@ -32,21 +31,18 @@ export class GitDiffReportModalComponent { readonly rightCommitFileContentByPath = signal | undefined>(undefined); constructor() { - effect( - () => { - // We call the signal here to ensure the effect always runs when the report changes. - this.report(); - const diffBetweenTemplateAndSolution = this.diffForTemplateAndSolution(); - untracked(async () => { - if (diffBetweenTemplateAndSolution) { - await this.loadFilesForTemplateAndSolution(); - } else { - await this.loadRepositoryFilesForParticipationsFromCacheIfAvailable(); - } - }); - }, - { allowSignalWrites: true }, - ); + effect(() => { + // We call the signal here to ensure the effect always runs when the report changes. + this.report(); + const diffBetweenTemplateAndSolution = this.diffForTemplateAndSolution(); + untracked(async () => { + if (diffBetweenTemplateAndSolution) { + await this.loadFilesForTemplateAndSolution(); + } else { + await this.loadRepositoryFilesForParticipationsFromCacheIfAvailable(); + } + }); + }); } private async loadFilesForTemplateAndSolution(): Promise { diff --git a/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-report.component.ts b/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-report.component.ts index 7edc4f32aaf3..c3e200845b9f 100644 --- a/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-report.component.ts +++ b/src/main/webapp/app/exercises/programming/git-diff-report/git-diff-report.component.ts @@ -19,7 +19,6 @@ interface DiffInformation { @Component({ selector: 'jhi-git-diff-report', templateUrl: './git-diff-report.component.html', - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [GitDiffLineStatComponent, ArtemisSharedModule, ArtemisSharedComponentModule, GitDiffFilePanelComponent], }) diff --git a/src/main/webapp/app/exercises/programming/manage/build-plan-editor.component.ts b/src/main/webapp/app/exercises/programming/manage/build-plan-editor.component.ts index b160bf88b2be..a85a4ad265b9 100644 --- a/src/main/webapp/app/exercises/programming/manage/build-plan-editor.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/build-plan-editor.component.ts @@ -1,5 +1,6 @@ -import { AfterViewInit, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; +import { AfterViewInit, Component, OnInit, ViewChild, ViewEncapsulation, inject } from '@angular/core'; import { faCircleNotch, faPlayCircle } from '@fortawesome/free-solid-svg-icons'; +import { UpdatingResultComponent } from 'app/exercises/shared/result/updating-result.component'; import { onError } from 'app/shared/util/global.utils'; import { AlertService } from 'app/core/util/alert.service'; import { BuildPlanService } from 'app/exercises/programming/manage/services/build-plan.service'; @@ -8,14 +9,25 @@ import { ActivatedRoute } from '@angular/router'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { MonacoEditorComponent } from 'app/shared/monaco-editor/monaco-editor.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { CodeEditorHeaderComponent } from '../shared/code-editor/header/code-editor-header.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-build-plan-editor', templateUrl: './build-plan-editor.component.html', styleUrls: ['./build-plan-editor.scss'], encapsulation: ViewEncapsulation.None, + imports: [TranslateDirective, UpdatingResultComponent, NgbTooltip, FaIconComponent, CodeEditorHeaderComponent, MonacoEditorComponent, ArtemisTranslatePipe], }) export class BuildPlanEditorComponent implements AfterViewInit, OnInit { + private buildPlanService = inject(BuildPlanService); + private programmingExerciseService = inject(ProgrammingExerciseService); + private alertService = inject(AlertService); + private activatedRoute = inject(ActivatedRoute); + // Icons readonly faCircleNotch = faCircleNotch; readonly farPlayCircle = faPlayCircle; @@ -29,13 +41,6 @@ export class BuildPlanEditorComponent implements AfterViewInit, OnInit { programmingExercise: ProgrammingExercise; buildPlan: BuildPlan | undefined; - constructor( - private buildPlanService: BuildPlanService, - private programmingExerciseService: ProgrammingExerciseService, - private alertService: AlertService, - private activatedRoute: ActivatedRoute, - ) {} - /** * @function ngOnInit * Sets the exercise and corresponding build plan based on the exerciseId in the current URL. diff --git a/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-instructor-and-editor-container.component.ts b/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-instructor-and-editor-container.component.ts index f7fd38dc5515..3f73de34af1f 100644 --- a/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-instructor-and-editor-container.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-instructor-and-editor-container.component.ts @@ -1,23 +1,37 @@ import { Component, ViewChild } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { Location } from '@angular/common'; -import { AlertService } from 'app/core/util/alert.service'; +import { ProgrammingExerciseStudentTriggerBuildButtonComponent } from 'app/exercises/programming/shared/actions/programming-exercise-student-trigger-build-button.component'; +import { CodeEditorContainerComponent } from 'app/exercises/programming/shared/code-editor/container/code-editor-container.component'; +import { IncludedInScoreBadgeComponent } from 'app/exercises/shared/exercise-headers/included-in-score-badge.component'; import { UpdatingResultComponent } from 'app/exercises/shared/result/updating-result.component'; import { CodeEditorInstructorBaseContainerComponent } from 'app/exercises/programming/manage/code-editor/code-editor-instructor-base-container.component'; -import { DomainService } from 'app/exercises/programming/shared/code-editor/service/code-editor-domain.service'; -import { ProgrammingExerciseParticipationService } from 'app/exercises/programming/manage/services/programming-exercise-participation.service'; -import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; -import { ParticipationService } from 'app/exercises/shared/participation/participation.service'; import { ProgrammingExerciseEditableInstructionComponent } from 'app/exercises/programming/manage/instructions-editor/programming-exercise-editable-instruction.component'; import { IncludedInOverallScore } from 'app/entities/exercise.model'; import { faCircleNotch, faPlus, faTimes, faTimesCircle } from '@fortawesome/free-solid-svg-icons'; -import { CourseExerciseService } from 'app/exercises/shared/course-exercises/course-exercise.service'; import { IrisSettings } from 'app/entities/iris/settings/iris-settings.model'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ProgrammingExerciseInstructorExerciseStatusComponent } from '../status/programming-exercise-instructor-exercise-status.component'; +import { NgbDropdown, NgbDropdownButtonItem, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle } from '@ng-bootstrap/ng-bootstrap'; @Component({ selector: 'jhi-code-editor-instructor', templateUrl: './code-editor-instructor-and-editor-container.component.html', styleUrl: 'code-editor-instructor-and-editor-container.scss', + imports: [ + FaIconComponent, + TranslateDirective, + CodeEditorContainerComponent, + IncludedInScoreBadgeComponent, + ProgrammingExerciseInstructorExerciseStatusComponent, + NgbDropdown, + NgbDropdownToggle, + NgbDropdownMenu, + NgbDropdownButtonItem, + NgbDropdownItem, + UpdatingResultComponent, + ProgrammingExerciseStudentTriggerBuildButtonComponent, + ProgrammingExerciseEditableInstructionComponent, + ], }) export class CodeEditorInstructorAndEditorContainerComponent extends CodeEditorInstructorBaseContainerComponent { @ViewChild(UpdatingResultComponent, { static: false }) resultComp: UpdatingResultComponent; @@ -32,18 +46,4 @@ export class CodeEditorInstructorAndEditorContainerComponent extends CodeEditorI faTimesCircle = faTimesCircle; irisSettings?: IrisSettings; - - constructor( - router: Router, - exerciseService: ProgrammingExerciseService, - courseExerciseService: CourseExerciseService, - domainService: DomainService, - programmingExerciseParticipationService: ProgrammingExerciseParticipationService, - location: Location, - participationService: ParticipationService, - route: ActivatedRoute, - alertService: AlertService, - ) { - super(router, exerciseService, courseExerciseService, domainService, programmingExerciseParticipationService, location, participationService, route, alertService); - } } diff --git a/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-instructor-base-container.component.ts b/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-instructor-base-container.component.ts index 0b6e1efd5d89..ccc3557d3f11 100644 --- a/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-instructor-base-container.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-instructor-base-container.component.ts @@ -1,4 +1,5 @@ -import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { Component, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; +import { CodeEditorContainerComponent } from 'app/exercises/programming/shared/code-editor/container/code-editor-container.component'; import { Observable, Subscription, of, throwError } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; import { Location } from '@angular/common'; @@ -9,14 +10,12 @@ import { Participation } from 'app/entities/participation/participation.model'; import { ButtonSize } from 'app/shared/components/button.component'; import { DomainService } from 'app/exercises/programming/shared/code-editor/service/code-editor-domain.service'; import { TemplateProgrammingExerciseParticipation } from 'app/entities/participation/template-programming-exercise-participation.model'; -import { ProgrammingExerciseParticipationService } from 'app/exercises/programming/manage/services/programming-exercise-participation.service'; import { ExerciseType } from 'app/entities/exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { ProgrammingExerciseStudentParticipation } from 'app/entities/participation/programming-exercise-student-participation.model'; import { SolutionProgrammingExerciseParticipation } from 'app/entities/participation/solution-programming-exercise-participation.model'; import { DomainChange, DomainType } from 'app/exercises/programming/shared/code-editor/model/code-editor.model'; -import { CodeEditorContainerComponent } from '../../shared/code-editor/container/code-editor-container.component'; import { Course } from 'app/entities/course.model'; import { CourseExerciseService } from 'app/exercises/shared/course-exercises/course-exercise.service'; @@ -42,10 +41,21 @@ export enum LOADING_STATE { DELETING_ASSIGNMENT_REPO = 'DELETING_ASSIGNMENT_REPO', } -@Component({ template: '' }) +@Component({ + template: '', +}) export abstract class CodeEditorInstructorBaseContainerComponent implements OnInit, OnDestroy { @ViewChild(CodeEditorContainerComponent, { static: false }) codeEditorContainer: CodeEditorContainerComponent; + private router = inject(Router); + private exerciseService = inject(ProgrammingExerciseService); + private courseExerciseService = inject(CourseExerciseService); + private domainService = inject(DomainService); + private location = inject(Location); + private participationService = inject(ParticipationService); + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + ButtonSize = ButtonSize; REPOSITORY = REPOSITORY; LOADING_STATE = LOADING_STATE; @@ -75,18 +85,6 @@ export abstract class CodeEditorInstructorBaseContainerComponent implements OnIn // State variables loadingState = LOADING_STATE.CLEAR; - protected constructor( - protected router: Router, - private exerciseService: ProgrammingExerciseService, - private courseExerciseService: CourseExerciseService, - private domainService: DomainService, - private programmingExerciseParticipationService: ProgrammingExerciseParticipationService, - private location: Location, - private participationService: ParticipationService, - protected route: ActivatedRoute, - private alertService: AlertService, - ) {} - /** * Initialize the route params subscription. * On route param change load the exercise and the selected participation OR the test repository. diff --git a/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-management-routing.module.ts b/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-management-routing.module.ts index f2b7ac2605a5..a009e0ff1a75 100644 --- a/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-management-routing.module.ts +++ b/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-management-routing.module.ts @@ -1,14 +1,17 @@ import { RouterModule, Routes } from '@angular/router'; -import { CodeEditorInstructorAndEditorContainerComponent } from 'app/exercises/programming/manage/code-editor/code-editor-instructor-and-editor-container.component'; + import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { CodeEditorInstructorAndEditorOrionContainerComponent } from 'app/orion/management/code-editor-instructor-and-editor-orion-container.component'; + import { NgModule } from '@angular/core'; import { Authority } from 'app/shared/constants/authority.constants'; const routes: Routes = [ { path: 'test', - component: CodeEditorInstructorAndEditorContainerComponent, + loadComponent: () => + import('app/exercises/programming/manage/code-editor/code-editor-instructor-and-editor-container.component').then( + (m) => m.CodeEditorInstructorAndEditorContainerComponent, + ), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.editor.home.title', @@ -17,7 +20,8 @@ const routes: Routes = [ }, { path: 'ide/test', - component: CodeEditorInstructorAndEditorOrionContainerComponent, + loadComponent: () => + import('app/orion/management/code-editor-instructor-and-editor-orion-container.component').then((m) => m.CodeEditorInstructorAndEditorOrionContainerComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.editor.home.title', @@ -26,7 +30,8 @@ const routes: Routes = [ }, { path: 'ide/:participationId', - component: CodeEditorInstructorAndEditorOrionContainerComponent, + loadComponent: () => + import('app/orion/management/code-editor-instructor-and-editor-orion-container.component').then((m) => m.CodeEditorInstructorAndEditorOrionContainerComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.editor.home.title', @@ -35,7 +40,10 @@ const routes: Routes = [ }, { path: ':participationId', - component: CodeEditorInstructorAndEditorContainerComponent, + loadComponent: () => + import('app/exercises/programming/manage/code-editor/code-editor-instructor-and-editor-container.component').then( + (m) => m.CodeEditorInstructorAndEditorContainerComponent, + ), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.editor.home.title', @@ -44,7 +52,10 @@ const routes: Routes = [ }, { path: 'auxiliary/:repositoryId', - component: CodeEditorInstructorAndEditorContainerComponent, + loadComponent: () => + import('app/exercises/programming/manage/code-editor/code-editor-instructor-and-editor-container.component').then( + (m) => m.CodeEditorInstructorAndEditorContainerComponent, + ), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.editor.home.title', diff --git a/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-management.module.ts b/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-management.module.ts index 4eb51f50768f..d00b4c8d9978 100644 --- a/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-management.module.ts +++ b/src/main/webapp/app/exercises/programming/manage/code-editor/code-editor-management.module.ts @@ -28,7 +28,8 @@ import { IrisModule } from 'app/iris/iris.module'; SubmissionResultStatusModule, ArtemisSharedComponentModule, IrisModule, + CodeEditorInstructorAndEditorContainerComponent, + CodeEditorInstructorAndEditorOrionContainerComponent, ], - declarations: [CodeEditorInstructorAndEditorContainerComponent, CodeEditorInstructorAndEditorOrionContainerComponent], }) export class ArtemisCodeEditorManagementModule {} diff --git a/src/main/webapp/app/exercises/programming/manage/grading/charts/category-issues-chart.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/charts/category-issues-chart.component.ts index 236a85bf0cce..1d6b2c450872 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/charts/category-issues-chart.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/charts/category-issues-chart.component.ts @@ -1,6 +1,7 @@ import { Component, Input, OnChanges } from '@angular/core'; import { IssuesMap } from 'app/entities/programming/programming-exercise-test-case-statistics.model'; import { StaticCodeAnalysisCategory, StaticCodeAnalysisCategoryState } from 'app/entities/programming/static-code-analysis-category.model'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; export class IssueColumn { w: string; @@ -22,6 +23,7 @@ export class IssueColumn { `, + imports: [NgbTooltip], }) export class CategoryIssuesChartComponent implements OnChanges { @Input() issuesMap?: IssuesMap; diff --git a/src/main/webapp/app/exercises/programming/manage/grading/charts/sca-category-distribution-chart.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/charts/sca-category-distribution-chart.component.ts index 58e2d7aa9dd3..e095b0f91c0a 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/charts/sca-category-distribution-chart.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/charts/sca-category-distribution-chart.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, Output, inject } from '@angular/core'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { StaticCodeAnalysisCategory, StaticCodeAnalysisCategoryState } from 'app/entities/programming/static-code-analysis-category.model'; import { CategoryIssuesMap } from 'app/entities/programming/programming-exercise-test-case-statistics.model'; @@ -7,6 +7,9 @@ import { getColor } from 'app/exercises/programming/manage/grading/charts/progra import { ProgrammingGradingChartsDirective } from 'app/exercises/programming/manage/grading/charts/programming-grading-charts.directive'; import { NgxChartsMultiSeriesDataEntry } from 'app/shared/chart/ngx-charts-datatypes'; import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { BarChartModule } from '@swimlane/ngx-charts'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; enum ScaChartBarTitle { PENALTY = 'Penalty', @@ -83,8 +86,12 @@ enum ScaChartBarTitle { `, + imports: [TranslateDirective, BarChartModule, ArtemisTranslatePipe], }) export class ScaCategoryDistributionChartComponent extends ProgrammingGradingChartsDirective implements OnChanges { + private translateService = inject(TranslateService); + private navigationUtilsService = inject(ArtemisNavigationUtilService); + @Input() categories: StaticCodeAnalysisCategory[]; @Input() categoryIssuesMap?: CategoryIssuesMap; @Input() exercise: ProgrammingExercise; @@ -97,11 +104,10 @@ export class ScaCategoryDistributionChartComponent extends ProgrammingGradingCha // ngx ngxData: NgxChartsMultiSeriesDataEntry[] = []; - constructor( - private translateService: TranslateService, - private navigationUtilsService: ArtemisNavigationUtilService, - ) { + constructor() { super(); + const translateService = this.translateService; + translateService.onLangChange.subscribe(() => { this.updateTranslations(); }); diff --git a/src/main/webapp/app/exercises/programming/manage/grading/charts/test-case-distribution-chart.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/charts/test-case-distribution-chart.component.ts index 568402289fca..4c4af16c5a9e 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/charts/test-case-distribution-chart.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/charts/test-case-distribution-chart.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, inject } from '@angular/core'; import { ProgrammingExerciseTestCase, Visibility } from 'app/entities/programming/programming-exercise-test-case.model'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { TestCaseStatsMap } from 'app/entities/programming/programming-exercise-test-case-statistics.model'; @@ -8,6 +8,9 @@ import { ProgrammingGradingChartsDirective } from 'app/exercises/programming/man import { getTotalMaxPoints } from 'app/exercises/shared/exercise/exercise.utils'; import { NgxChartsMultiSeriesDataEntry } from 'app/shared/chart/ngx-charts-datatypes'; import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { BarChartModule } from '@swimlane/ngx-charts'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; enum TestCaseBarTitle { WEIGHT_EN = 'Weight', @@ -24,8 +27,12 @@ type TestCaseColors = { selector: 'jhi-test-case-distribution-chart', styleUrls: ['./sca-category-distribution-chart.scss'], templateUrl: './test-case-distribution-chart.component.html', + imports: [TranslateDirective, BarChartModule, ArtemisTranslatePipe], }) export class TestCaseDistributionChartComponent extends ProgrammingGradingChartsDirective implements OnInit, OnChanges { + private translateService = inject(TranslateService); + private navigationUtilService = inject(ArtemisNavigationUtilService); + @Input() testCases: ProgrammingExerciseTestCase[]; @Input() testCaseStatsMap?: TestCaseStatsMap; @Input() totalParticipations?: number; @@ -47,10 +54,7 @@ export class TestCaseDistributionChartComponent extends ProgrammingGradingCharts // array containing the ngx-dedicated objects in order to display the points chart ngxPointsData: NgxChartsMultiSeriesDataEntry[] = [{ name: '', series: [] as any[] }]; - constructor( - private translateService: TranslateService, - private navigationUtilService: ArtemisNavigationUtilService, - ) { + constructor() { super(); this.translateService.onLangChange.subscribe(() => { diff --git a/src/main/webapp/app/exercises/programming/manage/grading/charts/test-case-passed-builds-chart.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/charts/test-case-passed-builds-chart.component.ts index 03e4a076bc58..55efa5baabc5 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/charts/test-case-passed-builds-chart.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/charts/test-case-passed-builds-chart.component.ts @@ -1,6 +1,7 @@ import { Component, Input, OnChanges } from '@angular/core'; import { TestCaseStats } from 'app/entities/programming/programming-exercise-test-case-statistics.model'; import { round } from 'app/shared/util/utils'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; @Component({ selector: 'jhi-test-case-passed-builds-chart', @@ -15,6 +16,7 @@ import { round } from 'app/shared/util/utils'; '.passed-bar { position: absolute; top: 0; left: 0; height: 10px; background-color: #28a745 }', '.failed-bar { position: absolute; top: 0; height: 10px; background-color: #dc3545 }', ], + imports: [NgbTooltip], }) export class TestCasePassedBuildsChartComponent implements OnChanges { @Input() testCaseStats?: TestCaseStats; diff --git a/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/confirm-feedback-channel-creation-modal.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/confirm-feedback-channel-creation-modal.component.ts index 4a31192b6299..4beca713648e 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/confirm-feedback-channel-creation-modal.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/confirm-feedback-channel-creation-modal.component.ts @@ -6,7 +6,6 @@ import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; selector: 'jhi-confirm-feedback-channel-creation-modal', templateUrl: './confirm-feedback-channel-creation-modal.component.html', imports: [ArtemisSharedCommonModule], - standalone: true, }) export class ConfirmFeedbackChannelCreationModalComponent { protected readonly TRANSLATION_BASE = 'artemisApp.programmingExercise.configureGrading.feedbackAnalysis.feedbackDetailChannel.confirmationModal'; diff --git a/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-affected-students-modal.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-affected-students-modal.component.ts index ed5b2d2fb36a..4cc518982ea2 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-affected-students-modal.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-affected-students-modal.component.ts @@ -11,7 +11,6 @@ import { faSpinner } from '@fortawesome/free-solid-svg-icons'; templateUrl: './feedback-affected-students-modal.component.html', imports: [ArtemisSharedCommonModule, ArtemisSharedComponentModule], providers: [FeedbackAnalysisService], - standalone: true, }) export class AffectedStudentsModalComponent { courseId = input.required(); diff --git a/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-detail-channel-modal.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-detail-channel-modal.component.ts index 5e9577ea889d..5d40561709ee 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-detail-channel-modal.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-detail-channel-modal.component.ts @@ -1,5 +1,5 @@ import { Component, inject, input, output, signal } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { ChannelDTO } from 'app/entities/metis/conversation/channel.model'; import { FeedbackDetail } from 'app/exercises/programming/manage/grading/feedback-analysis/feedback-analysis.service'; @@ -10,8 +10,7 @@ import { AlertService } from 'app/core/util/alert.service'; @Component({ selector: 'jhi-feedback-detail-channel-modal', templateUrl: './feedback-detail-channel-modal.component.html', - imports: [ArtemisSharedCommonModule], - standalone: true, + imports: [ArtemisSharedCommonModule, FormsModule, ReactiveFormsModule], }) export class FeedbackDetailChannelModalComponent { protected readonly TRANSLATION_BASE = 'artemisApp.programmingExercise.configureGrading.feedbackAnalysis.feedbackDetailChannel'; diff --git a/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-filter-modal.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-filter-modal.component.ts index cf7632c82337..c5a20a3941a6 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-filter-modal.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-filter-modal.component.ts @@ -17,7 +17,6 @@ export interface FilterData { templateUrl: './feedback-filter-modal.component.html', imports: [RangeSliderComponent, ArtemisSharedCommonModule], providers: [FeedbackAnalysisService], - standalone: true, }) export class FeedbackFilterModalComponent { private localStorage = inject(LocalStorageService); diff --git a/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-modal.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-modal.component.ts index af60c0af8569..abbead9b4518 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-modal.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-modal.component.ts @@ -7,7 +7,6 @@ import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; selector: 'jhi-feedback-modal', templateUrl: './feedback-modal.component.html', imports: [ArtemisSharedCommonModule], - standalone: true, }) export class FeedbackModalComponent { feedbackDetail = input.required(); diff --git a/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/feedback-analysis.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/feedback-analysis.component.ts index a787eeecf13a..c740ebbcd9ab 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/feedback-analysis.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/feedback-analysis/feedback-analysis.component.ts @@ -1,9 +1,8 @@ import { Component, computed, effect, inject, input, signal, untracked } from '@angular/core'; import { FeedbackAnalysisService, FeedbackChannelRequestDTO, FeedbackDetail } from './feedback-analysis.service'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbModule, NgbPagination } from '@ng-bootstrap/ng-bootstrap'; import { AlertService } from 'app/core/util/alert.service'; -import { faCircleQuestion, faFilter, faMessage, faSort, faSortDown, faSortUp, faSpinner, faUsers } from '@fortawesome/free-solid-svg-icons'; -import { facDetails } from '../../../../../../content/icons/icons'; +import { faCircleQuestion, faFilter, faMessage, faSort, faSpinner, faUsers } from '@fortawesome/free-solid-svg-icons'; import { SearchResult, SortingOrder } from 'app/shared/table/pageable-table'; import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; import { FeedbackModalComponent } from 'app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-modal.component'; @@ -15,13 +14,13 @@ import { AffectedStudentsModalComponent } from 'app/exercises/programming/manage import { FeedbackDetailChannelModalComponent } from 'app/exercises/programming/manage/grading/feedback-analysis/Modal/feedback-detail-channel-modal.component'; import { ChannelDTO } from 'app/entities/metis/conversation/channel.model'; import { Router } from '@angular/router'; +import { facDetails } from 'app/icons/icons'; @Component({ selector: 'jhi-feedback-analysis', templateUrl: './feedback-analysis.component.html', styleUrls: ['./feedback-analysis.component.scss'], - standalone: true, - imports: [ArtemisSharedCommonModule, SortIconComponent], + imports: [ArtemisSharedCommonModule, SortIconComponent, NgbModule, NgbPagination], providers: [FeedbackAnalysisService], }) export class FeedbackAnalysisComponent { @@ -48,8 +47,6 @@ export class FeedbackAnalysisComponent { readonly TRANSLATION_BASE = 'artemisApp.programmingExercise.configureGrading.feedbackAnalysis'; readonly faSort = faSort; - readonly faSortUp = faSortUp; - readonly faSortDown = faSortDown; readonly faFilter = faFilter; readonly facDetails = facDetails; readonly faUsers = faUsers; diff --git a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-configure-grading-actions.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-configure-grading-actions.component.ts index 6c91acef5676..7f38b3748fab 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-configure-grading-actions.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-configure-grading-actions.component.ts @@ -1,5 +1,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; +import { ProgrammingExerciseReEvaluateButtonComponent } from 'app/exercises/programming/shared/actions/programming-exercise-re-evaluate-button.component'; +import { ProgrammingExerciseTriggerAllButtonComponent } from 'app/exercises/programming/shared/actions/programming-exercise-trigger-all-button.component'; /** * The actions of the grading page: @@ -12,6 +14,7 @@ import { ProgrammingExercise } from 'app/entities/programming/programming-exerci `, + imports: [ProgrammingExerciseReEvaluateButtonComponent, ProgrammingExerciseTriggerAllButtonComponent], }) export class ProgrammingExerciseConfigureGradingActionsComponent { @Input() exercise: ProgrammingExercise; diff --git a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-configure-grading-status.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-configure-grading-status.component.ts index cf73c3a9e075..8d3d5b687b86 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-configure-grading-status.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-configure-grading-status.component.ts @@ -1,5 +1,9 @@ import { Component, Input } from '@angular/core'; import { faCheckCircle, faExclamationTriangle, faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; /** * Two status indicators for the test case table: @@ -79,6 +83,7 @@ import { faCheckCircle, faExclamationTriangle, faQuestionCircle } from '@fortawe `, + imports: [FaIconComponent, TranslateDirective, NgbTooltip, ArtemisTranslatePipe], }) export class ProgrammingExerciseConfigureGradingStatusComponent { @Input() exerciseIsReleasedAndHasResults: boolean; diff --git a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-configure-grading.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-configure-grading.component.ts index 13ce8237d382..f864a080c423 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-configure-grading.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-configure-grading.component.ts @@ -1,5 +1,5 @@ -import { Location } from '@angular/common'; -import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { Location, NgClass, NgTemplateOutlet } from '@angular/common'; +import { Component, OnDestroy, OnInit, ViewEncapsulation, inject } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { faQuestionCircle, faSort, faSortDown, faSortUp, faSquare } from '@fortawesome/free-solid-svg-icons'; import { TranslateService } from '@ngx-translate/core'; @@ -17,12 +17,29 @@ import { ProgrammingExerciseGradingService, StaticCodeAnalysisCategoryUpdate } f import { ProgrammingExerciseWebsocketService } from 'app/exercises/programming/manage/services/programming-exercise-websocket.service'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { SubmissionPolicyService } from 'app/exercises/programming/manage/services/submission-policy.service'; +import { SubmissionPolicyUpdateComponent } from 'app/exercises/shared/submission-policy/submission-policy-update.component'; import { ComponentCanDeactivate } from 'app/shared/guard/can-deactivate.model'; import { roundValueSpecifiedByCourseSettings } from 'app/shared/util/utils'; import { differenceBy as _differenceBy, differenceWith as _differenceWith, intersectionWith as _intersectionWith, unionBy as _unionBy } from 'lodash-es'; import { Observable, Subscription, of, zip } from 'rxjs'; import { catchError, distinctUntilChanged, map, take, tap } from 'rxjs/operators'; import { ProgrammingExerciseTaskService } from 'app/exercises/programming/manage/grading/tasks/programming-exercise-task.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ProgrammingExerciseConfigureGradingStatusComponent } from './programming-exercise-configure-grading-status.component'; +import { ProgrammingExerciseConfigureGradingActionsComponent } from './programming-exercise-configure-grading-actions.component'; +import { ProgrammingExerciseGradingSubmissionPolicyConfigurationActionsComponent } from './programming-exercise-grading-submission-policy-configuration-actions.component'; +import { NgbAlert, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ProgrammingExerciseGradingTasksTableComponent } from './tasks/programming-exercise-grading-tasks-table.component'; +import { TestCaseDistributionChartComponent } from './charts/test-case-distribution-chart.component'; +import { ProgrammingExerciseGradingTableActionsComponent } from './programming-exercise-grading-table-actions.component'; +import { NgxDatatableModule } from '@siemens/ngx-datatable'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { FormsModule } from '@angular/forms'; +import { TableEditableFieldComponent } from 'app/shared/table/table-editable-field.component'; +import { CategoryIssuesChartComponent } from './charts/category-issues-chart.component'; +import { ScaCategoryDistributionChartComponent } from './charts/sca-category-distribution-chart.component'; +import { FeedbackAnalysisComponent } from './feedback-analysis/feedback-analysis.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; /** * Describes the editableField @@ -65,8 +82,43 @@ export type Table = 'testCases' | 'codeAnalysis'; styleUrls: ['./programming-exercise-configure-grading.scss'], encapsulation: ViewEncapsulation.None, providers: [ProgrammingExerciseTaskService], + imports: [ + NgClass, + TranslateDirective, + NgTemplateOutlet, + ProgrammingExerciseConfigureGradingStatusComponent, + ProgrammingExerciseConfigureGradingActionsComponent, + ProgrammingExerciseGradingSubmissionPolicyConfigurationActionsComponent, + SubmissionPolicyUpdateComponent, + NgbAlert, + ProgrammingExerciseGradingTasksTableComponent, + TestCaseDistributionChartComponent, + ProgrammingExerciseGradingTableActionsComponent, + NgxDatatableModule, + FaIconComponent, + NgbTooltip, + FormsModule, + TableEditableFieldComponent, + CategoryIssuesChartComponent, + ScaCategoryDistributionChartComponent, + FeedbackAnalysisComponent, + ArtemisTranslatePipe, + ], }) export class ProgrammingExerciseConfigureGradingComponent implements OnInit, OnDestroy, ComponentCanDeactivate { + private accountService = inject(AccountService); + private gradingService = inject(ProgrammingExerciseGradingService); + private programmingExerciseService = inject(ProgrammingExerciseService); + private programmingExerciseSubmissionPolicyService = inject(SubmissionPolicyService); + private programmingExerciseWebsocketService = inject(ProgrammingExerciseWebsocketService); + private programmingExerciseTaskService = inject(ProgrammingExerciseTaskService); + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + private translateService = inject(TranslateService); + private location = inject(Location); + private router = inject(Router); + private courseManagementService = inject(CourseManagementService); + readonly EditableField = EditableField; readonly CategoryState = StaticCodeAnalysisCategoryState; readonly Visibility = Visibility; @@ -161,21 +213,6 @@ export class ProgrammingExerciseConfigureGradingComponent implements OnInit, OnD this.updateTestCaseFilter(); } - constructor( - private accountService: AccountService, - private gradingService: ProgrammingExerciseGradingService, - private programmingExerciseService: ProgrammingExerciseService, - private programmingExerciseSubmissionPolicyService: SubmissionPolicyService, - private programmingExerciseWebsocketService: ProgrammingExerciseWebsocketService, - private programmingExerciseTaskService: ProgrammingExerciseTaskService, - private route: ActivatedRoute, - private alertService: AlertService, - private translateService: TranslateService, - private location: Location, - private router: Router, - private courseManagementService: CourseManagementService, - ) {} - /** * Subscribes to the route params to get the current exerciseId. * Uses the exerciseId to subscribe to the newest value of the exercise's test cases. diff --git a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading-dirty-warning.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading-dirty-warning.component.ts index 197d3501fae6..a20231c7616f 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading-dirty-warning.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading-dirty-warning.component.ts @@ -1,8 +1,11 @@ -import { Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core'; +import { Component, Input, OnChanges, OnDestroy, SimpleChanges, inject } from '@angular/core'; import { ProgrammingExerciseWebsocketService } from 'app/exercises/programming/manage/services/programming-exercise-websocket.service'; import { tap } from 'rxjs/operators'; import { Subscription } from 'rxjs'; import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; /** * Two status indicators for the test case table: @@ -21,8 +24,11 @@ import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; /> } `, + imports: [FaIconComponent, NgbTooltip, ArtemisTranslatePipe], }) export class ProgrammingExerciseGradingDirtyWarningComponent implements OnChanges, OnDestroy { + private programmingExerciseWebsocketService = inject(ProgrammingExerciseWebsocketService); + @Input() programmingExerciseId: number; @Input() hasUpdatedGradingConfigInitialValue: boolean; @@ -32,8 +38,6 @@ export class ProgrammingExerciseGradingDirtyWarningComponent implements OnChange // Icons faExclamationTriangle = faExclamationTriangle; - constructor(private programmingExerciseWebsocketService: ProgrammingExerciseWebsocketService) {} - /** * Set the initial updated test case value on the first change of the property. * Subscribe for the test case state. This component is only visible if the programming exercise has updated (= dirty) test cases. diff --git a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading-submission-policy-configuration-actions.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading-submission-policy-configuration-actions.component.ts index 7e5156faaa52..6b6ad0c342cf 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading-submission-policy-configuration-actions.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading-submission-policy-configuration-actions.component.ts @@ -3,6 +3,7 @@ import { faSave } from '@fortawesome/free-solid-svg-icons'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { SubmissionPolicyType } from 'app/entities/submission-policy.model'; import { ButtonType } from 'app/shared/components/button.component'; +import { ButtonComponent } from 'app/shared/components/button.component'; /** * The actions of the submission policy configuration: @@ -43,6 +44,7 @@ import { ButtonType } from 'app/shared/components/button.component'; } `, + imports: [ButtonComponent], }) export class ProgrammingExerciseGradingSubmissionPolicyConfigurationActionsComponent { readonly ButtonType = ButtonType; diff --git a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading-table-actions.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading-table-actions.component.ts index ae956e5b7a96..ee6496ae7ff4 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading-table-actions.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading-table-actions.component.ts @@ -1,10 +1,12 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output, inject } from '@angular/core'; import { faCopy } from '@fortawesome/free-solid-svg-icons'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { ExerciseType } from 'app/entities/exercise.model'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { GradingTab } from 'app/exercises/programming/manage/grading/programming-exercise-configure-grading.component'; import { ExerciseImportWrapperComponent } from 'app/exercises/shared/import/exercise-import-wrapper/exercise-import-wrapper.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; /** * The actions of the test case table: @@ -14,8 +16,11 @@ import { ExerciseImportWrapperComponent } from 'app/exercises/shared/import/exer @Component({ selector: 'jhi-programming-exercise-grading-table-actions', templateUrl: './programming-exercise-grading-table-actions.component.html', + imports: [FaIconComponent, TranslateDirective], }) export class ProgrammingExerciseGradingTableActionsComponent { + private modalService = inject(NgbModal); + readonly faCopy = faCopy; @Input() exercise: ProgrammingExercise; @Input() hasUnsavedChanges: boolean; @@ -26,8 +31,6 @@ export class ProgrammingExerciseGradingTableActionsComponent { @Output() onReset = new EventEmitter(); @Output() onCategoryImport = new EventEmitter(); - constructor(private modalService: NgbModal) {} - openImportModal() { const modalRef = this.modalService.open(ExerciseImportWrapperComponent, { size: 'lg', backdrop: 'static' }); modalRef.componentInstance.exerciseType = ExerciseType.PROGRAMMING; diff --git a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading.module.ts b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading.module.ts index 705638a44789..d8dd1a51f35a 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading.module.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/programming-exercise-grading.module.ts @@ -35,8 +35,6 @@ import { FeedbackAnalysisComponent } from 'app/exercises/programming/manage/grad SubmissionPolicyUpdateModule, BarChartModule, FeedbackAnalysisComponent, - ], - declarations: [ ProgrammingExerciseConfigureGradingComponent, ProgrammingExerciseConfigureGradingStatusComponent, ProgrammingExerciseConfigureGradingActionsComponent, diff --git a/src/main/webapp/app/exercises/programming/manage/grading/tasks/programming-exercise-grading-tasks-table.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/tasks/programming-exercise-grading-tasks-table.component.ts index ec88a4dc9ae1..17e1f33ffefc 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/tasks/programming-exercise-grading-tasks-table.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/tasks/programming-exercise-grading-tasks-table.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { ProgrammingExerciseTaskService } from 'app/exercises/programming/manage/grading/tasks/programming-exercise-task.service'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { Course } from 'app/entities/course.model'; @@ -9,6 +9,13 @@ import { Observable, Subject } from 'rxjs'; import { ProgrammingExerciseTestCase } from 'app/entities/programming/programming-exercise-test-case.model'; import { isExamExercise } from 'app/shared/util/utils'; import { ProgrammingExerciseServerSideTask } from 'app/entities/programming-exercise-task.model'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ProgrammingExerciseTaskComponent } from './programming-exercise-task/programming-exercise-task.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; type Sort = { by: 'name' | 'weight' | 'multiplier' | 'bonusPoints' | 'visibility' | 'resulting' | 'type'; @@ -21,8 +28,11 @@ type TaskComparator = (a: ProgrammingExerciseTask | ProgrammingExerciseTestCase, selector: 'jhi-programming-exercise-grading-tasks-table', templateUrl: './programming-exercise-grading-tasks-table.component.html', styleUrls: ['./programming-exercise-grading-tasks-table.scss'], + imports: [ButtonComponent, TranslateDirective, FormsModule, NgbTooltip, FaIconComponent, ProgrammingExerciseTaskComponent, ArtemisTranslatePipe], }) export class ProgrammingExerciseGradingTasksTableComponent implements OnInit { + private taskService = inject(ProgrammingExerciseTaskService); + @Input() exercise: ProgrammingExercise; @Input() course: Course; @Input() gradingStatisticsObservable: Observable; @@ -47,8 +57,6 @@ export class ProgrammingExerciseGradingTasksTableComponent implements OnInit { return this.taskService.ignoreInactive; } - constructor(private taskService: ProgrammingExerciseTaskService) {} - ngOnInit(): void { this.allTasksExpandedSubject = new Subject(); this.gradingStatisticsObservable.subscribe((gradingStatistics) => { diff --git a/src/main/webapp/app/exercises/programming/manage/grading/tasks/programming-exercise-task.service.ts b/src/main/webapp/app/exercises/programming/manage/grading/tasks/programming-exercise-task.service.ts index 3021e5e548f2..9c9fd15cbd65 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/tasks/programming-exercise-task.service.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/tasks/programming-exercise-task.service.ts @@ -1,5 +1,5 @@ import { HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ProgrammingExerciseServerSideTask } from 'app/entities/programming-exercise-task.model'; import { Observable, catchError, of, tap } from 'rxjs'; import { Exercise } from 'app/entities/exercise.model'; @@ -15,6 +15,10 @@ import { map, mergeMap } from 'rxjs/operators'; @Injectable() export class ProgrammingExerciseTaskService { + private http = inject(HttpClient); + private alertService = inject(AlertService); + private gradingService = inject(ProgrammingExerciseGradingService); + exercise: ProgrammingExercise; course: Course; gradingStatistics: ProgrammingExerciseGradingStatistics; @@ -28,12 +32,6 @@ export class ProgrammingExerciseTaskService { public resourceUrl = 'api/programming-exercises'; - constructor( - private http: HttpClient, - private alertService: AlertService, - private gradingService: ProgrammingExerciseGradingService, - ) {} - get totalWeights() { return sum(this.testCases.map(({ weight }) => weight ?? 0)); } diff --git a/src/main/webapp/app/exercises/programming/manage/grading/tasks/programming-exercise-task/programming-exercise-task.component.ts b/src/main/webapp/app/exercises/programming/manage/grading/tasks/programming-exercise-task/programming-exercise-task.component.ts index 837c0210f76d..9ad4da1ce5b5 100644 --- a/src/main/webapp/app/exercises/programming/manage/grading/tasks/programming-exercise-task/programming-exercise-task.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/grading/tasks/programming-exercise-task/programming-exercise-task.component.ts @@ -1,16 +1,23 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core'; import { faAngleDown, faAngleRight } from '@fortawesome/free-solid-svg-icons'; import { ProgrammingExerciseTask } from 'app/exercises/programming/manage/grading/tasks/programming-exercise-task'; import { ProgrammingExerciseTestCase, Visibility } from 'app/entities/programming/programming-exercise-test-case.model'; import { ProgrammingExerciseTaskService } from '../programming-exercise-task.service'; import { Subject } from 'rxjs'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { FormsModule } from '@angular/forms'; +import { TestCasePassedBuildsChartComponent } from '../../charts/test-case-passed-builds-chart.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-programming-exercise-task', templateUrl: './programming-exercise-task.component.html', styleUrls: ['../programming-exercise-grading-tasks-table.scss'], + imports: [FaIconComponent, FormsModule, TestCasePassedBuildsChartComponent, ArtemisTranslatePipe], }) export class ProgrammingExerciseTaskComponent implements OnInit { + private programmingExerciseTaskService = inject(ProgrammingExerciseTaskService); + @Input() index: number; @Input() task: ProgrammingExerciseTask; @Input() openSubject: Subject; @@ -31,8 +38,6 @@ export class ProgrammingExerciseTaskComponent implements OnInit { return this.programmingExerciseTaskService?.gradingStatistics?.numParticipations ?? 0; } - constructor(private programmingExerciseTaskService: ProgrammingExerciseTaskService) {} - ngOnInit(): void { this.openSubject.subscribe((open) => (this.open = open)); diff --git a/src/main/webapp/app/exercises/programming/manage/instructions-editor/analysis/programming-exercise-instruction-analysis.component.ts b/src/main/webapp/app/exercises/programming/manage/instructions-editor/analysis/programming-exercise-instruction-analysis.component.ts index 026a37bbdc0d..0a3581a8062f 100644 --- a/src/main/webapp/app/exercises/programming/manage/instructions-editor/analysis/programming-exercise-instruction-analysis.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/instructions-editor/analysis/programming-exercise-instruction-analysis.component.ts @@ -1,15 +1,23 @@ -import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, inject } from '@angular/core'; import { Subject, Subscription } from 'rxjs'; import { debounceTime, map, tap } from 'rxjs/operators'; import { ProgrammingExerciseInstructionAnalysisService } from 'app/exercises/programming/manage/instructions-editor/analysis/programming-exercise-instruction-analysis.service'; import { ProblemStatementAnalysis } from 'app/exercises/programming/manage/instructions-editor/analysis/programming-exercise-instruction-analysis.model'; import { faCheckCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { TaskCountWarningComponent } from './task-count-warning/task-count-warning.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-programming-exercise-instruction-instructor-analysis', templateUrl: './programming-exercise-instruction-analysis.component.html', + imports: [FaIconComponent, NgbTooltip, TranslateDirective, TaskCountWarningComponent, ArtemisTranslatePipe], }) export class ProgrammingExerciseInstructionAnalysisComponent implements OnInit, OnChanges, OnDestroy { + private analysisService = inject(ProgrammingExerciseInstructionAnalysisService); + @Input() exerciseTestCases: string[]; @Input() problemStatement: string; @Input() taskRegex: RegExp; @@ -27,8 +35,6 @@ export class ProgrammingExerciseInstructionAnalysisComponent implements OnInit, faCheckCircle = faCheckCircle; faExclamationTriangle = faExclamationTriangle; - constructor(private analysisService: ProgrammingExerciseInstructionAnalysisService) {} - ngOnInit(): void { this.analysisSubscription = this.delayedAnalysisSubject .pipe( diff --git a/src/main/webapp/app/exercises/programming/manage/instructions-editor/analysis/programming-exercise-instruction-analysis.service.ts b/src/main/webapp/app/exercises/programming/manage/instructions-editor/analysis/programming-exercise-instruction-analysis.service.ts index 14f8dc19b04a..d65778147c7c 100644 --- a/src/main/webapp/app/exercises/programming/manage/instructions-editor/analysis/programming-exercise-instruction-analysis.service.ts +++ b/src/main/webapp/app/exercises/programming/manage/instructions-editor/analysis/programming-exercise-instruction-analysis.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { uniq } from 'lodash-es'; import { RegExpLineNumberMatchArray, matchRegexWithLineNumbers } from 'app/shared/util/global.utils'; @@ -17,7 +17,7 @@ const REPEATED_TEST_CASE_TRANSLATION = 'artemisApp.programmingExercise.testCaseA */ @Injectable() export class ProgrammingExerciseInstructionAnalysisService { - constructor(private translateService: TranslateService) {} + private translateService = inject(TranslateService); /** * Given a programming exercise's problem statement, analyze the test cases contained (or not contained!) in it. diff --git a/src/main/webapp/app/exercises/programming/manage/instructions-editor/analysis/task-count-warning/task-count-warning.component.ts b/src/main/webapp/app/exercises/programming/manage/instructions-editor/analysis/task-count-warning/task-count-warning.component.ts index 1fd2ec9f876e..e6b6f52c532b 100644 --- a/src/main/webapp/app/exercises/programming/manage/instructions-editor/analysis/task-count-warning/task-count-warning.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/instructions-editor/analysis/task-count-warning/task-count-warning.component.ts @@ -1,9 +1,13 @@ import { Component, Input } from '@angular/core'; import { faCheckCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-task-count-warning', templateUrl: './task-count-warning.component.html', + imports: [FaIconComponent, NgbTooltip, TranslateDirective], }) export class TaskCountWarningComponent { readonly faExclamationTriangle = faExclamationTriangle; diff --git a/src/main/webapp/app/exercises/programming/manage/instructions-editor/programming-exercise-editable-instruction.component.ts b/src/main/webapp/app/exercises/programming/manage/instructions-editor/programming-exercise-editable-instruction.component.ts index f945acc5a972..c755be38732a 100644 --- a/src/main/webapp/app/exercises/programming/manage/instructions-editor/programming-exercise-editable-instruction.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/instructions-editor/programming-exercise-editable-instruction.component.ts @@ -1,5 +1,6 @@ -import { AfterViewInit, Component, EventEmitter, HostListener, Input, OnChanges, OnDestroy, Output, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core'; +import { AfterViewInit, Component, EventEmitter, HostListener, Input, OnChanges, OnDestroy, Output, SimpleChanges, ViewChild, ViewEncapsulation, inject } from '@angular/core'; import { AlertService } from 'app/core/util/alert.service'; +import { ProgrammingExerciseInstructionComponent } from 'app/exercises/programming/shared/instructions-render/programming-exercise-instruction.component'; import { Observable, Subject, Subscription, of, throwError } from 'rxjs'; import { catchError, map as rxMap, switchMap, tap } from 'rxjs/operators'; import { ProgrammingExerciseTestCase } from 'app/entities/programming/programming-exercise-test-case.model'; @@ -18,14 +19,35 @@ import { FormulaAction } from 'app/shared/monaco-editor/model/actions/formula.ac import { TaskAction } from 'app/shared/monaco-editor/model/actions/task.action'; import { TestCaseAction } from 'app/shared/monaco-editor/model/actions/test-case.action'; import { TextEditorDomainAction } from 'app/shared/monaco-editor/model/actions/text-editor-domain-action.model'; +import { NgClass } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ProgrammingExerciseInstructionAnalysisComponent } from './analysis/programming-exercise-instruction-analysis.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-programming-exercise-editable-instructions', templateUrl: './programming-exercise-editable-instruction.component.html', styleUrls: ['./programming-exercise-editable-instruction.scss'], encapsulation: ViewEncapsulation.None, + imports: [ + MarkdownEditorMonacoComponent, + ProgrammingExerciseInstructionComponent, + NgClass, + FaIconComponent, + TranslateDirective, + NgbTooltip, + ProgrammingExerciseInstructionAnalysisComponent, + ArtemisTranslatePipe, + ], }) export class ProgrammingExerciseEditableInstructionComponent implements AfterViewInit, OnChanges, OnDestroy { + private programmingExerciseService = inject(ProgrammingExerciseService); + private alertService = inject(AlertService); + private programmingExerciseParticipationService = inject(ProgrammingExerciseParticipationService); + private testCaseService = inject(ProgrammingExerciseGradingService); + participationValue: Participation; programmingExercise: ProgrammingExercise; @@ -95,13 +117,6 @@ export class ProgrammingExerciseEditableInstructionComponent implements AfterVie protected readonly MarkdownEditorHeight = MarkdownEditorHeight; - constructor( - private programmingExerciseService: ProgrammingExerciseService, - private alertService: AlertService, - private programmingExerciseParticipationService: ProgrammingExerciseParticipationService, - private testCaseService: ProgrammingExerciseGradingService, - ) {} - ngOnChanges(changes: SimpleChanges): void { if (hasExerciseChanged(changes)) { this.setupTestCaseSubscription(); diff --git a/src/main/webapp/app/exercises/programming/manage/instructions-editor/programming-exercise-instructions-editor.module.ts b/src/main/webapp/app/exercises/programming/manage/instructions-editor/programming-exercise-instructions-editor.module.ts index 5507f89b908c..61b8b32a15c2 100644 --- a/src/main/webapp/app/exercises/programming/manage/instructions-editor/programming-exercise-instructions-editor.module.ts +++ b/src/main/webapp/app/exercises/programming/manage/instructions-editor/programming-exercise-instructions-editor.module.ts @@ -9,8 +9,15 @@ import { ProgrammingExerciseInstructionAnalysisService } from 'app/exercises/pro import { TaskCountWarningComponent } from './analysis/task-count-warning/task-count-warning.component'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisProgrammingExerciseInstructionsRenderModule, ArtemisMarkdownEditorModule, ArtemisProgrammingExerciseStatusModule], - declarations: [ProgrammingExerciseEditableInstructionComponent, ProgrammingExerciseInstructionAnalysisComponent, TaskCountWarningComponent], + imports: [ + ArtemisSharedModule, + ArtemisProgrammingExerciseInstructionsRenderModule, + ArtemisMarkdownEditorModule, + ArtemisProgrammingExerciseStatusModule, + ProgrammingExerciseEditableInstructionComponent, + ProgrammingExerciseInstructionAnalysisComponent, + TaskCountWarningComponent, + ], providers: [ProgrammingExerciseInstructionAnalysisService], exports: [ArtemisProgrammingExerciseInstructionsRenderModule, ProgrammingExerciseEditableInstructionComponent], }) diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-create-buttons.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-create-buttons.component.ts index 9c842a025b85..b07cbb6b9082 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-create-buttons.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-create-buttons.component.ts @@ -1,4 +1,4 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { Course } from 'app/entities/course.model'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; import { faFileImport, faKeyboard, faPlus } from '@fortawesome/free-solid-svg-icons'; @@ -6,13 +6,21 @@ import { ExerciseImportWrapperComponent } from 'app/exercises/shared/import/exer import { ExerciseType } from 'app/entities/exercise.model'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { Router } from '@angular/router'; +import { Router, RouterLink } from '@angular/router'; +import { FeatureToggleLinkDirective } from 'app/shared/feature-toggle/feature-toggle-link.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FeatureToggleDirective } from 'app/shared/feature-toggle/feature-toggle.directive'; @Component({ selector: 'jhi-programming-exercise-create-buttons', templateUrl: './programming-exercise-create-buttons.component.html', + imports: [FeatureToggleLinkDirective, RouterLink, FaIconComponent, TranslateDirective, FeatureToggleDirective], }) export class ProgrammingExerciseCreateButtonsComponent { + private router = inject(Router); + private modalService = inject(NgbModal); + readonly FeatureToggle = FeatureToggle; @Input() @@ -22,11 +30,6 @@ export class ProgrammingExerciseCreateButtonsComponent { faFileImport = faFileImport; faKeyboard = faKeyboard; - constructor( - private router: Router, - private modalService: NgbModal, - ) {} - openImportModal() { const modalRef = this.modalService.open(ExerciseImportWrapperComponent, { size: 'lg', backdrop: 'static' }); modalRef.componentInstance.exerciseType = ExerciseType.PROGRAMMING; diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index a7ae630cfa52..c3eff649807f 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -1,7 +1,8 @@ -import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { Component, OnDestroy, OnInit, ViewEncapsulation, inject } from '@angular/core'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { SafeHtml } from '@angular/platform-browser'; import { ProgrammingExerciseBuildConfig } from 'app/entities/programming/programming-exercise-build.config'; +import { ExerciseDetailStatisticsComponent } from 'app/exercises/shared/statistics/exercise-detail-statistics.component'; import { Subject, Subscription, of } from 'rxjs'; import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; @@ -13,7 +14,7 @@ import { ActionType } from 'app/shared/delete-dialog/delete-dialog.model'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; import { ExerciseService } from 'app/exercises/shared/exercise/exercise.service'; import { ExerciseType, IncludedInOverallScore } from 'app/entities/exercise.model'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { ConfirmAutofocusModalComponent } from 'app/shared/components/confirm-autofocus-modal.component'; import { TranslateService } from '@ngx-translate/core'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; @@ -58,14 +59,59 @@ import { AeolusService } from 'app/exercises/programming/shared/service/aeolus.s import { catchError, mergeMap, tap } from 'rxjs/operators'; import { ProgrammingExerciseGitDiffReport } from 'app/entities/programming-exercise-git-diff-report.model'; import { BuildLogStatisticsDTO } from 'app/entities/programming/build-log-statistics-dto'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { OrionFilterDirective } from 'app/shared/orion/orion-filter.directive'; +import { FeatureToggleLinkDirective } from 'app/shared/feature-toggle/feature-toggle-link.directive'; +import { ProgrammingExerciseInstructorExerciseDownloadComponent } from '../shared/actions/programming-exercise-instructor-exercise-download.component'; +import { FeatureToggleDirective } from 'app/shared/feature-toggle/feature-toggle.directive'; +import { ProgrammingExerciseResetButtonDirective } from './reset/programming-exercise-reset-button.directive'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { DetailOverviewListComponent } from 'app/detail-overview-list/detail-overview-list.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-programming-exercise-detail', templateUrl: './programming-exercise-detail.component.html', styleUrls: ['./programming-exercise-detail.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [ + TranslateDirective, + DocumentationButtonComponent, + RouterLink, + FaIconComponent, + OrionFilterDirective, + FeatureToggleLinkDirective, + NgbTooltip, + ProgrammingExerciseInstructorExerciseDownloadComponent, + FeatureToggleDirective, + ProgrammingExerciseResetButtonDirective, + DeleteButtonDirective, + ExerciseDetailStatisticsComponent, + DetailOverviewListComponent, + ArtemisTranslatePipe, + ], }) export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { + private activatedRoute = inject(ActivatedRoute); + private accountService = inject(AccountService); + private programmingExerciseService = inject(ProgrammingExerciseService); + exerciseService = inject(ExerciseService); + private artemisMarkdown = inject(ArtemisMarkdownService); + private alertService = inject(AlertService); + private programmingExerciseSubmissionPolicyService = inject(SubmissionPolicyService); + private eventManager = inject(EventManager); + modalService = inject(NgbModal); + private translateService = inject(TranslateService); + private profileService = inject(ProfileService); + private statisticsService = inject(StatisticsService); + private router = inject(Router); + private programmingLanguageFeatureService = inject(ProgrammingLanguageFeatureService); + private consistencyCheckService = inject(ConsistencyCheckService); + private irisSettingsService = inject(IrisSettingsService); + private aeolusService = inject(AeolusService); + protected readonly dayjs = dayjs; protected readonly ActionType = ActionType; protected readonly ProgrammingExerciseParticipationType = ProgrammingExerciseParticipationType; @@ -131,26 +177,6 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { exerciseDetailSections: DetailOverviewSection[]; - constructor( - private activatedRoute: ActivatedRoute, - private accountService: AccountService, - private programmingExerciseService: ProgrammingExerciseService, - public exerciseService: ExerciseService, - private artemisMarkdown: ArtemisMarkdownService, - private alertService: AlertService, - private programmingExerciseSubmissionPolicyService: SubmissionPolicyService, - private eventManager: EventManager, - public modalService: NgbModal, - private translateService: TranslateService, - private profileService: ProfileService, - private statisticsService: StatisticsService, - private router: Router, - private programmingLanguageFeatureService: ProgrammingLanguageFeatureService, - private consistencyCheckService: ConsistencyCheckService, - private irisSettingsService: IrisSettingsService, - private aeolusService: AeolusService, - ) {} - ngOnInit() { this.checkBuildPlanEditable(); diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-edit-selected.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-edit-selected.component.ts index 287e50b11913..0761976562a0 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-edit-selected.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-edit-selected.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { TranslateService } from '@ngx-translate/core'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; @@ -8,12 +8,25 @@ import { ProgrammingExerciseService } from 'app/exercises/programming/manage/ser import { AlertService, AlertType } from 'app/core/util/alert.service'; import { faSave } from '@fortawesome/free-solid-svg-icons'; import { ExerciseService } from 'app/exercises/shared/exercise/exercise.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { ProgrammingExerciseLifecycleComponent } from '../shared/lifecycle/programming-exercise-lifecycle.component'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-programming-exercise-edit-selected', templateUrl: './programming-exercise-edit-selected.component.html', + imports: [TranslateDirective, FormsModule, HelpIconComponent, ProgrammingExerciseLifecycleComponent, ButtonComponent, FaIconComponent], }) export class ProgrammingExerciseEditSelectedComponent implements OnInit { + private activeModal = inject(NgbActiveModal); + private translateService = inject(TranslateService); + private alertService = inject(AlertService); + private programmingExerciseService = inject(ProgrammingExerciseService); + private exerciseService = inject(ExerciseService); + newProgrammingExercise: ProgrammingExercise; selectedProgrammingExercises: ProgrammingExercise[]; @@ -27,14 +40,6 @@ export class ProgrammingExerciseEditSelectedComponent implements OnInit { // Icons faSave = faSave; - constructor( - private activeModal: NgbActiveModal, - private translateService: TranslateService, - private alertService: AlertService, - private programmingExerciseService: ProgrammingExerciseService, - private exerciseService: ExerciseService, - ) {} - ngOnInit(): void { this.notificationText = undefined; this.newProgrammingExercise = new ProgrammingExercise(undefined, undefined); diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-management-routing.module.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-management-routing.module.ts index bda9a0f7860c..c44e83c4b563 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-management-routing.module.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-management-routing.module.ts @@ -1,27 +1,20 @@ import { ActivatedRouteSnapshot, Resolve, RouterModule, Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { Injectable, NgModule } from '@angular/core'; -import { ProgrammingExerciseDetailComponent } from 'app/exercises/programming/manage/programming-exercise-detail.component'; -import { ProgrammingExerciseUpdateComponent } from 'app/exercises/programming/manage/update/programming-exercise-update.component'; +import { Injectable, NgModule, inject } from '@angular/core'; + import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { map } from 'rxjs/operators'; import { HttpResponse } from '@angular/common/http'; import { of } from 'rxjs'; -import { ProgrammingExerciseConfigureGradingComponent } from 'app/exercises/programming/manage/grading/programming-exercise-configure-grading.component'; + import { Authority } from 'app/shared/constants/authority.constants'; -import { PlagiarismInspectorComponent } from 'app/exercises/shared/plagiarism/plagiarism-inspector/plagiarism-inspector.component'; -import { ExerciseStatisticsComponent } from 'app/exercises/shared/statistics/exercise-statistics.component'; -import { BuildPlanEditorComponent } from 'app/exercises/programming/manage/build-plan-editor.component'; -import { RepositoryViewComponent } from 'app/localvc/repository-view/repository-view.component'; -import { CommitHistoryComponent } from 'app/localvc/commit-history/commit-history.component'; -import { CommitDetailsViewComponent } from 'app/localvc/commit-details-view/commit-details-view.component'; + import { LocalVCGuard } from 'app/localvc/localvc-guard.service'; -import { VcsRepositoryAccessLogViewComponent } from 'app/localvc/vcs-repository-access-log-view/vcs-repository-access-log-view.component'; @Injectable({ providedIn: 'root' }) export class ProgrammingExerciseResolve implements Resolve { - constructor(private service: ProgrammingExerciseService) {} + private service = inject(ProgrammingExerciseService); resolve(route: ActivatedRouteSnapshot) { const exerciseId = route.params['exerciseId'] ? route.params['exerciseId'] : undefined; @@ -35,7 +28,7 @@ export class ProgrammingExerciseResolve implements Resolve export const routes: Routes = [ { path: ':courseId/programming-exercises/new', - component: ProgrammingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/programming/manage/update/programming-exercise-update.component').then((m) => m.ProgrammingExerciseUpdateComponent), resolve: { programmingExercise: ProgrammingExerciseResolve, }, @@ -47,7 +40,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/edit', - component: ProgrammingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/programming/manage/update/programming-exercise-update.component').then((m) => m.ProgrammingExerciseUpdateComponent), resolve: { programmingExercise: ProgrammingExerciseResolve, }, @@ -59,7 +52,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/import/:exerciseId', - component: ProgrammingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/programming/manage/update/programming-exercise-update.component').then((m) => m.ProgrammingExerciseUpdateComponent), resolve: { programmingExercise: ProgrammingExerciseResolve, }, @@ -71,7 +64,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/import-from-file', - component: ProgrammingExerciseUpdateComponent, + loadComponent: () => import('app/exercises/programming/manage/update/programming-exercise-update.component').then((m) => m.ProgrammingExerciseUpdateComponent), resolve: { programmingExercise: ProgrammingExerciseResolve, }, @@ -83,7 +76,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId', - component: ProgrammingExerciseDetailComponent, + loadComponent: () => import('app/exercises/programming/manage/programming-exercise-detail.component').then((m) => m.ProgrammingExerciseDetailComponent), resolve: { programmingExercise: ProgrammingExerciseResolve, }, @@ -95,7 +88,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/plagiarism', - component: PlagiarismInspectorComponent, + loadComponent: () => import('app/exercises/shared/plagiarism/plagiarism-inspector/plagiarism-inspector.component').then((m) => m.PlagiarismInspectorComponent), resolve: { exercise: ProgrammingExerciseResolve, }, @@ -107,7 +100,8 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/grading/:tab', - component: ProgrammingExerciseConfigureGradingComponent, + loadComponent: () => + import('app/exercises/programming/manage/grading/programming-exercise-configure-grading.component').then((m) => m.ProgrammingExerciseConfigureGradingComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.programmingExercise.home.title', @@ -120,7 +114,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/exercise-statistics', - component: ExerciseStatisticsComponent, + loadComponent: () => import('app/exercises/shared/statistics/exercise-statistics.component').then((m) => m.ExerciseStatisticsComponent), resolve: { exercise: ProgrammingExerciseResolve, }, @@ -137,7 +131,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/edit-build-plan', - component: BuildPlanEditorComponent, + loadComponent: () => import('app/exercises/programming/manage/build-plan-editor.component').then((m) => m.BuildPlanEditorComponent), resolve: { exercise: ProgrammingExerciseResolve, }, @@ -149,7 +143,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/repository/:repositoryType', - component: RepositoryViewComponent, + loadComponent: () => import('app/localvc/repository-view/repository-view.component').then((m) => m.RepositoryViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.repository.title', @@ -158,7 +152,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/repository/:repositoryType/repo/:repositoryId', - component: RepositoryViewComponent, + loadComponent: () => import('app/localvc/repository-view/repository-view.component').then((m) => m.RepositoryViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.repository.title', @@ -167,7 +161,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/repository/:repositoryType/commit-history', - component: CommitHistoryComponent, + loadComponent: () => import('app/localvc/commit-history/commit-history.component').then((m) => m.CommitHistoryComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR], pageTitle: 'artemisApp.repository.title', @@ -176,7 +170,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/repository/:repositoryType/repo/:repositoryId/commit-history', - component: CommitHistoryComponent, + loadComponent: () => import('app/localvc/commit-history/commit-history.component').then((m) => m.CommitHistoryComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR], pageTitle: 'artemisApp.repository.title', @@ -185,7 +179,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/repository/:repositoryType/vcs-access-log', - component: VcsRepositoryAccessLogViewComponent, + loadComponent: () => import('app/localvc/vcs-repository-access-log-view/vcs-repository-access-log-view.component').then((m) => m.VcsRepositoryAccessLogViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], pageTitle: 'artemisApp.repository.title', @@ -194,7 +188,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/repository/:repositoryType/repo/:repositoryId/vcs-access-log', - component: VcsRepositoryAccessLogViewComponent, + loadComponent: () => import('app/localvc/vcs-repository-access-log-view/vcs-repository-access-log-view.component').then((m) => m.VcsRepositoryAccessLogViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], pageTitle: 'artemisApp.repository.title', @@ -203,7 +197,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/repository/:repositoryType/commit-history/:commitHash', - component: CommitDetailsViewComponent, + loadComponent: () => import('app/localvc/commit-details-view/commit-details-view.component').then((m) => m.CommitDetailsViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR], pageTitle: 'artemisApp.repository.title', @@ -212,7 +206,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/participations/:participationId/repository', - component: RepositoryViewComponent, + loadComponent: () => import('app/localvc/repository-view/repository-view.component').then((m) => m.RepositoryViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.repository.title', @@ -221,7 +215,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/participations/:participationId/repository/commit-history', - component: CommitHistoryComponent, + loadComponent: () => import('app/localvc/commit-history/commit-history.component').then((m) => m.CommitHistoryComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.repository.title', @@ -230,7 +224,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/participations/:participationId/repository/vcs-access-log', - component: VcsRepositoryAccessLogViewComponent, + loadComponent: () => import('app/localvc/vcs-repository-access-log-view/vcs-repository-access-log-view.component').then((m) => m.VcsRepositoryAccessLogViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR], pageTitle: 'artemisApp.repository.title', @@ -239,7 +233,7 @@ export const routes: Routes = [ }, { path: ':courseId/programming-exercises/:exerciseId/participations/:participationId/repository/commit-history/:commitHash', - component: CommitDetailsViewComponent, + loadComponent: () => import('app/localvc/commit-details-view/commit-details-view.component').then((m) => m.CommitDetailsViewComponent), data: { authorities: [Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA], pageTitle: 'artemisApp.repository.title', diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-management.module.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-management.module.ts index d7aa345e3758..a0b4f6cf625d 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-management.module.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-management.module.ts @@ -10,7 +10,7 @@ import { ArtemisProgrammingExerciseInstructionsEditorModule } from 'app/exercise import { ArtemisProgrammingExerciseUpdateModule } from 'app/exercises/programming/manage/update/programming-exercise-update.module'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { ArtemisProgrammingExerciseStatusModule } from 'app/exercises/programming/manage/status/programming-exercise-status.module'; -import { FeatureToggleModule } from 'app/shared/feature-toggle/feature-toggle.module'; + import { ArtemisProgrammingExerciseModule } from 'app/exercises/programming/shared/programming-exercise.module'; import { AssessmentInstructionsModule } from 'app/assessment/assessment-instructions/assessment-instructions.module'; import { ProgrammingExerciseEditSelectedComponent } from 'app/exercises/programming/manage/programming-exercise-edit-selected.component'; @@ -42,7 +42,6 @@ import { CodeEditorHeaderComponent } from 'app/exercises/programming/shared/code ArtemisProgrammingExerciseInstructionsEditorModule, ArtemisProgrammingExerciseUpdateModule, ArtemisProgrammingExerciseStatusModule, - FeatureToggleModule, AssessmentInstructionsModule, OrionModule, ArtemisProgrammingExerciseLifecycleModule, @@ -53,8 +52,6 @@ import { CodeEditorHeaderComponent } from 'app/exercises/programming/shared/code IrisModule, MonacoEditorComponent, CodeEditorHeaderComponent, - ], - declarations: [ ProgrammingExerciseDetailComponent, ProgrammingExerciseEditSelectedComponent, ProgrammingExerciseInstructorExerciseDownloadComponent, diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise.component.html b/src/main/webapp/app/exercises/programming/manage/programming-exercise.component.html index fd15337f32c2..3b507c6750dd 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise.component.html +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise.component.html @@ -16,10 +16,11 @@       - - @if (!localVCEnabled) { -   - } + + + + + @@ -76,7 +77,9 @@ {{ programmingExercise.maxPoints }} {{ programmingExercise.bonusPoints }} {{ exerciseService.isIncludedInScore(programmingExercise) }} - + + +
@if (programmingExercise.templateParticipation && programmingExercise.templateParticipation.repositoryUri) { @@ -128,7 +131,9 @@
@if (!localVCEnabled) { - + + + @if (programmingExercise.templateParticipation?.buildPlanId) { Template } @@ -159,7 +164,9 @@ - + + +
@if (programmingExercise.teamMode && programmingExercise.isAtLeastTutor) { diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise.component.ts index 3a33c7b88f83..57220812410c 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise.component.ts @@ -1,5 +1,6 @@ -import { Component, ContentChild, Input, OnDestroy, OnInit, TemplateRef, inject } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; +import { ExerciseScoresExportButtonComponent } from 'app/exercises/shared/exercise-scores/exercise-scores-export-button.component'; import { merge } from 'rxjs'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { ProgrammingExerciseInstructorRepositoryType, ProgrammingExerciseService } from './services/programming-exercise.service'; @@ -22,7 +23,6 @@ import { faCheckDouble, faDownload, faFileSignature, - faLightbulb, faListAlt, faPencilAlt, faPlus, @@ -36,10 +36,47 @@ import { import { CourseExerciseService } from 'app/exercises/shared/course-exercises/course-exercise.service'; import { downloadZipFileFromResponse } from 'app/shared/util/download.util'; import { PROFILE_LOCALCI, PROFILE_LOCALVC, PROFILE_THEIA } from 'app/app.constants'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { FormsModule } from '@angular/forms'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { RouterLink } from '@angular/router'; +import { ProgrammingExerciseGradingDirtyWarningComponent } from './grading/programming-exercise-grading-dirty-warning.component'; +import { ProgrammingExerciseInstructorStatusComponent } from './status/programming-exercise-instructor-status.component'; +import { ExerciseCategoriesComponent } from 'app/shared/exercise-categories/exercise-categories.component'; +import { FeatureToggleLinkDirective } from 'app/shared/feature-toggle/feature-toggle-link.directive'; +import { ProgrammingExerciseResetButtonDirective } from './reset/programming-exercise-reset-button.directive'; +import { FeatureToggleDirective } from 'app/shared/feature-toggle/feature-toggle.directive'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { ProgrammingAssessmentRepoExportButtonComponent } from '../assess/repo-export/programming-assessment-repo-export-button.component'; +import { SlicePipe } from '@angular/common'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; @Component({ selector: 'jhi-programming-exercise', templateUrl: './programming-exercise.component.html', + imports: [ + SortDirective, + FormsModule, + SortByDirective, + TranslateDirective, + FaIconComponent, + RouterLink, + ProgrammingExerciseGradingDirtyWarningComponent, + ProgrammingExerciseInstructorStatusComponent, + ExerciseCategoriesComponent, + FeatureToggleLinkDirective, + ProgrammingExerciseResetButtonDirective, + FeatureToggleDirective, + DeleteButtonDirective, + ProgrammingAssessmentRepoExportButtonComponent, + ExerciseScoresExportButtonComponent, + SlicePipe, + ArtemisDatePipe, + // TODO: the extension point for Orion does not work with Angular 19, we need to find a different solution + // ExtensionPointDirective, + ], }) export class ProgrammingExerciseComponent extends ExerciseComponent implements OnInit, OnDestroy { protected exerciseService = inject(ExerciseService); @@ -63,8 +100,9 @@ export class ProgrammingExerciseComponent extends ExerciseComponent implements O onlineIdeEnabled = false; // extension points, see shared/extension-point - @ContentChild('overrideRepositoryAndBuildPlan') overrideRepositoryAndBuildPlan: TemplateRef; - @ContentChild('overrideButtons') overrideButtons: TemplateRef; + // TODO: the extension point for Orion does not work with Angular 19, we need to find a different solution + // @ContentChild('overrideRepositoryAndBuildPlan') overrideRepositoryAndBuildPlan: TemplateRef; + // @ContentChild('overrideButtons') overrideButtons: TemplateRef; private buildPlanLinkTemplate: string; // Icons @@ -79,7 +117,6 @@ export class ProgrammingExerciseComponent extends ExerciseComponent implements O faTable = faTable; faTrash = faTrash; faListAlt = faListAlt; - faLightbulb = faLightbulb; faPencilAlt = faPencilAlt; faFileSignature = faFileSignature; @@ -135,7 +172,7 @@ export class ProgrammingExerciseComponent extends ExerciseComponent implements O this.emitFilteredExerciseCount(this.filteredProgrammingExercises.length); } - trackId(index: number, item: ProgrammingExercise) { + trackId(_index: number, item: ProgrammingExercise) { return item.id; } diff --git a/src/main/webapp/app/exercises/programming/manage/reset/programming-exercise-reset-button.directive.ts b/src/main/webapp/app/exercises/programming/manage/reset/programming-exercise-reset-button.directive.ts index f249959c63b5..dc1a02192c7c 100644 --- a/src/main/webapp/app/exercises/programming/manage/reset/programming-exercise-reset-button.directive.ts +++ b/src/main/webapp/app/exercises/programming/manage/reset/programming-exercise-reset-button.directive.ts @@ -1,19 +1,15 @@ -import { Directive, ElementRef, HostListener, Input, OnInit, Renderer2 } from '@angular/core'; +import { Directive, ElementRef, HostListener, Input, OnInit, Renderer2, inject } from '@angular/core'; import { ProgrammingExerciseResetDialogComponent } from 'app/exercises/programming/manage/reset/programming-exercise-reset-dialog.component'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; -@Directive({ - selector: '[jhiProgrammingExerciseResetButton]', -}) +@Directive({ selector: '[jhiProgrammingExerciseResetButton]' }) export class ProgrammingExerciseResetButtonDirective implements OnInit { - @Input() programmingExercise: ProgrammingExercise; + private modalService = inject(NgbModal); + private renderer = inject(Renderer2); + private elementRef = inject(ElementRef); - constructor( - private modalService: NgbModal, - private renderer: Renderer2, - private elementRef: ElementRef, - ) {} + @Input() programmingExercise: ProgrammingExercise; ngOnInit() { this.renderer.addClass(this.elementRef.nativeElement, 'btn'); diff --git a/src/main/webapp/app/exercises/programming/manage/reset/programming-exercise-reset-dialog.component.html b/src/main/webapp/app/exercises/programming/manage/reset/programming-exercise-reset-dialog.component.html index aab1fee57223..677358ac3321 100644 --- a/src/main/webapp/app/exercises/programming/manage/reset/programming-exercise-reset-dialog.component.html +++ b/src/main/webapp/app/exercises/programming/manage/reset/programming-exercise-reset-dialog.component.html @@ -118,8 +118,8 @@
`, + imports: [FormsModule, TranslateDirective, FaIconComponent], }) export class ProgrammingExerciseInstructorTriggerAllDialogComponent { + private activeModal = inject(NgbActiveModal); + @Input() exerciseId: number; @Input() dueDatePassed: boolean; @@ -119,8 +125,6 @@ export class ProgrammingExerciseInstructorTriggerAllDialogComponent { faBan = faBan; faTimes = faTimes; - constructor(private activeModal: NgbActiveModal) {} - cancel() { this.activeModal.dismiss('cancel'); } diff --git a/src/main/webapp/app/exercises/programming/shared/actions/programming-exercise-trigger-build-button.component.ts b/src/main/webapp/app/exercises/programming/shared/actions/programming-exercise-trigger-build-button.component.ts index 1431ad0bfe38..14ff2154ed02 100644 --- a/src/main/webapp/app/exercises/programming/shared/actions/programming-exercise-trigger-build-button.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/actions/programming-exercise-trigger-build-button.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core'; +import { Component, Input, OnChanges, OnDestroy, SimpleChanges, inject } from '@angular/core'; import { filter, tap } from 'rxjs/operators'; import { Subscription } from 'rxjs'; import { head, orderBy } from 'lodash-es'; @@ -11,7 +11,6 @@ import { Result } from 'app/entities/result.model'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; import { SubmissionType } from 'app/entities/submission.model'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; -import { AlertService } from 'app/core/util/alert.service'; import { hasParticipationChanged } from 'app/exercises/shared/participation/participation.utils'; import { isManualResult } from 'app/exercises/shared/result/result.utils'; @@ -20,11 +19,16 @@ import { isManualResult } from 'app/exercises/shared/result/result.utils'; * The participation given as input needs to have the results attached as this component checks if there is at least one result. * If there is no result, the button is disabled because this would mean that the student has not made a commit yet. */ -@Component({ template: '' }) +@Component({ + template: '', +}) export abstract class ProgrammingExerciseTriggerBuildButtonComponent implements OnChanges, OnDestroy { FeatureToggle = FeatureToggle; ButtonType = ButtonType; + private submissionService = inject(ProgrammingSubmissionService); + private participationWebsocketService = inject(ParticipationWebsocketService); + @Input() exercise: ProgrammingExercise; @Input() participation: Participation; @Input() btnSize = ButtonSize.SMALL; @@ -44,12 +48,6 @@ export abstract class ProgrammingExerciseTriggerBuildButtonComponent implements // True if the student triggers. false if an instructor triggers it protected personalParticipation: boolean; - protected constructor( - protected submissionService: ProgrammingSubmissionService, - protected participationWebsocketService: ParticipationWebsocketService, - protected alertService: AlertService, - ) {} - /** * Check if the participation has changed, if so set up the websocket connections. * diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts index d1932dc53ff3..d5233d052bed 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts @@ -6,7 +6,6 @@ import { AuxiliaryRepository } from 'app/entities/programming/programming-exerci selector: 'jhi-programming-exercise-build-plan-checkout-directories', templateUrl: './programming-exercise-build-plan-checkout-directories.component.html', styleUrls: ['../../manage/programming-exercise-form.scss'], - standalone: true, }) export class ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent { @Input() checkoutDirectories?: BuildPlanCheckoutDirectoriesDTO; diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-edit-checkout-directories/programming-exercise-edit-checkout-directories.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-edit-checkout-directories/programming-exercise-edit-checkout-directories.component.ts index 460a48c84aea..014c12b70b1b 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-edit-checkout-directories/programming-exercise-edit-checkout-directories.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-edit-checkout-directories/programming-exercise-edit-checkout-directories.component.ts @@ -8,7 +8,6 @@ import { NgModel } from '@angular/forms'; @Component({ selector: 'jhi-programming-exercise-edit-checkout-directories', - standalone: true, imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule], templateUrl: './programming-exercise-edit-checkout-directories.component.html', styleUrls: ['../../../manage/programming-exercise-form.scss'], diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts index ae0a3a091ca6..d527c18ebf01 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, inject } from '@angular/core'; import { getCourseFromExercise } from 'app/entities/exercise.model'; import type { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming/programming-exercise.model'; import { ProgrammingExerciseBuildConfig } from 'app/entities/programming/programming-exercise-build.config'; @@ -14,10 +14,11 @@ import { BuildPlanCheckoutDirectoriesDTO } from 'app/entities/programming/build- selector: 'jhi-programming-exercise-repository-and-build-plan-details', templateUrl: './programming-exercise-repository-and-build-plan-details.component.html', styleUrls: ['../../manage/programming-exercise-form.scss'], - standalone: true, imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule, ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent], }) export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implements OnInit, OnChanges, OnDestroy { + private programmingExerciseService = inject(ProgrammingExerciseService); + @Input() programmingExercise: ProgrammingExercise; @Input() programmingExerciseBuildConfig?: ProgrammingExerciseBuildConfig; @Input() programmingLanguage?: ProgrammingLanguage; @@ -27,8 +28,6 @@ export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implement @Input() isEditMode = false; @Output() submissionBuildPlanEvent = new EventEmitter(); - constructor(private programmingExerciseService: ProgrammingExerciseService) {} - checkoutDirectorySubscription?: Subscription; courseShortName?: string; diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/actions/code-editor-actions.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/actions/code-editor-actions.component.ts index 2eafc4badde4..aa6558311aa9 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/actions/code-editor-actions.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/actions/code-editor-actions.component.ts @@ -1,6 +1,6 @@ -import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, input } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, inject, input } from '@angular/core'; import { HttpErrorResponse } from '@angular/common/http'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { catchError, switchMap, tap } from 'rxjs/operators'; import { Observable, Subscription, of, throwError } from 'rxjs'; import { isEmpty as _isEmpty } from 'lodash-es'; @@ -15,12 +15,24 @@ import { AUTOSAVE_CHECK_INTERVAL, AUTOSAVE_EXERCISE_INTERVAL } from 'app/shared/ import { faCircleNotch, faSync, faTimes } from '@fortawesome/free-solid-svg-icons'; import { faPlayCircle } from '@fortawesome/free-regular-svg-icons'; import { Participation } from 'app/entities/participation/participation.model'; +import { RequestFeedbackButtonComponent } from 'app/overview/exercise-details/request-feedback-button/request-feedback-button.component'; +import { FeatureToggleDirective } from 'app/shared/feature-toggle/feature-toggle.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-code-editor-actions', templateUrl: './code-editor-actions.component.html', + imports: [RequestFeedbackButtonComponent, FeatureToggleDirective, NgbTooltip, FaIconComponent, TranslateDirective, ArtemisTranslatePipe], }) export class CodeEditorActionsComponent implements OnInit, OnDestroy, OnChanges { + private repositoryService = inject(CodeEditorRepositoryService); + private repositoryFileService = inject(CodeEditorRepositoryFileService); + private conflictService = inject(CodeEditorConflictStateService); + private modalService = inject(NgbModal); + private submissionService = inject(CodeEditorSubmissionService); + CommitState = CommitState; EditorState = EditorState; FeatureToggle = FeatureToggle; @@ -72,14 +84,6 @@ export class CodeEditorActionsComponent implements OnInit, OnDestroy, OnChanges this.editorStateChange.emit(editorState); } - constructor( - private repositoryService: CodeEditorRepositoryService, - private repositoryFileService: CodeEditorRepositoryFileService, - private conflictService: CodeEditorConflictStateService, - private modalService: NgbModal, - private submissionService: CodeEditorSubmissionService, - ) {} - ngOnInit(): void { this.conflictStateSubscription = this.conflictService.subscribeConflictState().subscribe((gitConflictState: GitConflictState) => { // When the conflict is encountered when opening the code-editor, setting the commitState here could cause an uncheckedException. @@ -171,7 +175,7 @@ export class CodeEditorActionsComponent implements OnInit, OnDestroy, OnChanges } /** - * @function saveFiles + * @param andCommit whether the saved changed in the files should be committed or not * @desc Saves all files that have unsaved changes in the editor. */ saveChangedFiles(andCommit = false): Observable { diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/actions/code-editor-confirm-refresh-modal.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/actions/code-editor-confirm-refresh-modal.component.ts index c74bd5cee679..de69a79d85c8 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/actions/code-editor-confirm-refresh-modal.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/actions/code-editor-confirm-refresh-modal.component.ts @@ -1,27 +1,29 @@ -import { Component, EventEmitter } from '@angular/core'; +import { Component, EventEmitter, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { CodeEditorRepositoryFileService, CodeEditorRepositoryService } from 'app/exercises/programming/shared/code-editor/service/code-editor-repository.service'; import { CodeEditorConflictStateService } from 'app/exercises/programming/shared/code-editor/service/code-editor-conflict-state.service'; import { faBan, faExclamationTriangle, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-code-editor-confirm-refresh-modal', templateUrl: './code-editor-confirm-refresh-modal.component.html', styleUrls: ['./code-editor-resolve-conflict-modal.scss'], providers: [CodeEditorRepositoryFileService], + imports: [FormsModule, TranslateDirective, FaIconComponent], }) export class CodeEditorConfirmRefreshModalComponent { + activeModal = inject(NgbActiveModal); + private repositoryService = inject(CodeEditorRepositoryService); + private conflictService = inject(CodeEditorConflictStateService); + // Icons faExclamationTriangle = faExclamationTriangle; faBan = faBan; faTimes = faTimes; - constructor( - public activeModal: NgbActiveModal, - private repositoryService: CodeEditorRepositoryService, - private conflictService: CodeEditorConflictStateService, - ) {} - shouldRefresh: EventEmitter = new EventEmitter(); /** diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/actions/code-editor-resolve-conflict-modal.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/actions/code-editor-resolve-conflict-modal.component.ts index 013b41adfea5..68934a3d9dde 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/actions/code-editor-resolve-conflict-modal.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/actions/code-editor-resolve-conflict-modal.component.ts @@ -1,20 +1,24 @@ -import { Component, EventEmitter } from '@angular/core'; +import { Component, EventEmitter, inject } from '@angular/core'; import { faBan, faExclamationTriangle, faTimes } from '@fortawesome/free-solid-svg-icons'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-code-editor-resolve-conflict-modal', templateUrl: './code-editor-resolve-conflict-modal.component.html', styleUrls: ['./code-editor-resolve-conflict-modal.scss'], + imports: [FormsModule, TranslateDirective, FaIconComponent], }) export class CodeEditorResolveConflictModalComponent { + activeModal = inject(NgbActiveModal); + // Icons faBan = faBan; faTimes = faTimes; faExclamationTriangle = faExclamationTriangle; - constructor(public activeModal: NgbActiveModal) {} - shouldReset: EventEmitter = new EventEmitter(); /** diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/build-output/code-editor-build-output.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/build-output/code-editor-build-output.component.ts index 1c7535cbc9d6..d055b35bb665 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/build-output/code-editor-build-output.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/build-output/code-editor-build-output.component.ts @@ -1,5 +1,5 @@ import { ParticipationWebsocketService } from 'app/overview/participation-websocket.service'; -import { AfterViewInit, Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges } from '@angular/core'; +import { AfterViewInit, Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, inject } from '@angular/core'; import { Observable, Subscription, of } from 'rxjs'; import { catchError, filter, map, switchMap, tap } from 'rxjs/operators'; import { BuildLogEntry, BuildLogEntryArray } from 'app/entities/programming/build-log.model'; @@ -19,13 +19,22 @@ import { faChevronDown, faCircleNotch, faTerminal } from '@fortawesome/free-soli import { hasParticipationChanged } from 'app/exercises/shared/participation/participation.utils'; import { AssessmentType } from 'app/entities/assessment-type.model'; import { Annotation } from '../monaco/code-editor-monaco.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; @Component({ selector: 'jhi-code-editor-build-output', templateUrl: './code-editor-build-output.component.html', styleUrls: ['./code-editor-build-output.scss'], + imports: [FaIconComponent, TranslateDirective, ArtemisDatePipe], }) export class CodeEditorBuildOutputComponent implements AfterViewInit, OnInit, OnChanges, OnDestroy { + private buildLogService = inject(CodeEditorBuildLogService); + private resultService = inject(ResultService); + private participationWebsocketService = inject(ParticipationWebsocketService); + private submissionService = inject(CodeEditorSubmissionService); + @Input() participation: Participation; @@ -52,13 +61,6 @@ export class CodeEditorBuildOutputComponent implements AfterViewInit, OnInit, On faCircleNotch = faCircleNotch; faTerminal = faTerminal; - constructor( - private buildLogService: CodeEditorBuildLogService, - private resultService: ResultService, - private participationWebsocketService: ParticipationWebsocketService, - private submissionService: CodeEditorSubmissionService, - ) {} - ngOnInit(): void { this.setupSubmissionWebsocket(); } diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/code-editor.module.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/code-editor.module.ts index a7d5af4a1cfc..9b42929ee85a 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/code-editor.module.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/code-editor.module.ts @@ -13,7 +13,7 @@ import { CodeEditorFileBrowserCreateNodeComponent } from 'app/exercises/programm import { CodeEditorFileBrowserFileComponent } from 'app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-file.component'; import { CodeEditorFileBrowserComponent } from 'app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser.component'; import { CodeEditorStatusComponent } from 'app/exercises/programming/shared/code-editor/status/code-editor-status.component'; -import { FeatureToggleModule } from 'app/shared/feature-toggle/feature-toggle.module'; + import { CodeEditorConfirmRefreshModalComponent } from 'app/exercises/programming/shared/code-editor/actions/code-editor-confirm-refresh-modal.component'; import { CodeEditorContainerComponent } from 'app/exercises/programming/shared/code-editor/container/code-editor-container.component'; import { ArtemisProgrammingManualAssessmentModule } from 'app/exercises/programming/assess/programming-manual-assessment.module'; @@ -29,7 +29,6 @@ import { MonacoEditorComponent } from 'app/shared/monaco-editor/monaco-editor.co imports: [ NgbModule, ArtemisSharedModule, - FeatureToggleModule, TreeviewModule.forRoot(), ArtemisProgrammingExerciseInstructionsEditorModule, ArtemisProgrammingManualAssessmentModule, @@ -37,8 +36,6 @@ import { MonacoEditorComponent } from 'app/shared/monaco-editor/monaco-editor.co ArtemisSharedComponentModule, RequestFeedbackButtonComponent, CodeEditorMonacoComponent, - ], - declarations: [ CodeEditorGridComponent, CodeEditorRepositoryIsLockedComponent, CodeEditorFileBrowserComponent, diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/container/code-editor-container.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/container/code-editor-container.component.ts index b2b81406b23a..30e1e4ed83e4 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/container/code-editor-container.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/container/code-editor-container.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewChild } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewChild, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { isEmpty as _isEmpty, fromPairs, toPairs, uniq } from 'lodash-es'; import { CodeEditorFileService } from 'app/exercises/programming/shared/code-editor/service/code-editor-file.service'; @@ -24,6 +24,7 @@ import { Feedback } from 'app/entities/feedback.model'; import { Course } from 'app/entities/course.model'; import { ConnectionError } from 'app/exercises/programming/shared/code-editor/service/code-editor-repository.service'; import { Annotation, CodeEditorMonacoComponent } from 'app/exercises/programming/shared/code-editor/monaco/code-editor-monaco.component'; +import { KeysPipe } from 'app/shared/pipes/keys.pipe'; export enum CollapsableCodeEditorElement { FileBrowser, @@ -35,8 +36,21 @@ export enum CollapsableCodeEditorElement { selector: 'jhi-code-editor-container', templateUrl: './code-editor-container.component.html', styleUrls: ['./code-editor-container.component.scss'], + imports: [ + CodeEditorGridComponent, + CodeEditorActionsComponent, + CodeEditorFileBrowserComponent, + CodeEditorMonacoComponent, + CodeEditorInstructionsComponent, + CodeEditorBuildOutputComponent, + KeysPipe, + ], }) export class CodeEditorContainerComponent implements OnChanges { + private translateService = inject(TranslateService); + private alertService = inject(AlertService); + private fileService = inject(CodeEditorFileService); + readonly CommitState = CommitState; readonly EditorState = EditorState; readonly CollapsableCodeEditorElement = CollapsableCodeEditorElement; @@ -107,11 +121,7 @@ export class CodeEditorContainerComponent implements OnChanges { errorFiles: string[] = []; annotations: Array = []; - constructor( - private translateService: TranslateService, - private alertService: AlertService, - private fileService: CodeEditorFileService, - ) { + constructor() { this.initializeProperties(); } diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-badge.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-badge.component.ts index ea851defda95..23ef8f15535a 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-badge.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-badge.component.ts @@ -1,20 +1,23 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { IconDefinition, faLightbulb } from '@fortawesome/free-solid-svg-icons'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { TranslateService } from '@ngx-translate/core'; import { FileBadge, FileBadgeType } from 'app/exercises/programming/shared/code-editor/model/code-editor.model'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-file-browser-badge', templateUrl: './code-editor-file-browser-badge.component.html', styleUrls: ['./code-editor-file-browser-badge.component.scss'], providers: [NgbModal], + imports: [NgbTooltip, FaIconComponent], }) export class CodeEditorFileBrowserBadgeComponent { - @Input() badge: FileBadge; - @Input() onColoredBackground: boolean = false; // Only slightly darken the background and use white text + private translateService = inject(TranslateService); - constructor(private translateService: TranslateService) {} + @Input() badge: FileBadge; + @Input() onColoredBackground: boolean = false; + // Only slightly darken the background and use white text get tooltip(): string | undefined { switch (this.badge.type) { diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-create-node.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-create-node.component.ts index c90d2c4272bc..5b2dbbd20a8c 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-create-node.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-create-node.component.ts @@ -2,12 +2,14 @@ import { AfterViewInit, Component, ElementRef, EventEmitter, Input, Output, View import { faFile, faFolder } from '@fortawesome/free-solid-svg-icons'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { FileType } from 'app/exercises/programming/shared/code-editor/model/code-editor.model'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-code-editor-file-browser-create-node', templateUrl: './code-editor-file-browser-create-node.component.html', styleUrls: ['./code-editor-file-browser-create-node.component.scss'], providers: [NgbModal], + imports: [FaIconComponent], }) export class CodeEditorFileBrowserCreateNodeComponent implements AfterViewInit { FileType = FileType; diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-delete.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-delete.ts index e393b4b81bee..35a5f759508c 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-delete.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-delete.ts @@ -1,18 +1,26 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { DeleteFileChange, FileType } from 'app/exercises/programming/shared/code-editor/model/code-editor.model'; import { CodeEditorRepositoryFileService } from 'app/exercises/programming/shared/code-editor/service/code-editor-repository.service'; import { IFileDeleteDelegate } from 'app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-on-file-delete-delegate'; import { captureException } from '@sentry/angular'; import { faBan, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; // Modal -> Delete repository file @Component({ selector: 'jhi-code-editor-file-browser-delete', templateUrl: './code-editor-file-browser-delete.component.html', providers: [CodeEditorRepositoryFileService], + imports: [FormsModule, TranslateDirective, FaIconComponent, ArtemisTranslatePipe], }) export class CodeEditorFileBrowserDeleteComponent implements OnInit { + activeModal = inject(NgbActiveModal); + private repositoryFileService = inject(CodeEditorRepositoryFileService); + @Input() fileNameToDelete: string; @Input() parent: IFileDeleteDelegate; @Input() fileType: FileType; @@ -23,11 +31,6 @@ export class CodeEditorFileBrowserDeleteComponent implements OnInit { faBan = faBan; faTrashAlt = faTrashAlt; - constructor( - public activeModal: NgbActiveModal, - private repositoryFileService: CodeEditorRepositoryFileService, - ) {} - /** * @function ngOnInit * @desc Initializes variables diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-file.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-file.component.ts index b5738903dd33..ac3878a170d4 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-file.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-file.component.ts @@ -3,11 +3,16 @@ import { faEdit, faFile, faTrash } from '@fortawesome/free-solid-svg-icons'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { CodeEditorFileBrowserNodeComponent } from 'app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-node.component'; import { FileBadge } from 'app/exercises/programming/shared/code-editor/model/code-editor.model'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgClass } from '@angular/common'; +import { CodeEditorFileBrowserBadgeComponent } from './code-editor-file-browser-badge.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-code-editor-file-browser-file', templateUrl: './code-editor-file-browser-file.component.html', providers: [NgbModal], + imports: [FaIconComponent, NgClass, CodeEditorFileBrowserBadgeComponent, ArtemisTranslatePipe], }) export class CodeEditorFileBrowserFileComponent extends CodeEditorFileBrowserNodeComponent { @Input() disableActions: boolean; diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-folder.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-folder.component.ts index d1693b244d82..bc824e76f760 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-folder.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-folder.component.ts @@ -4,11 +4,15 @@ import { FileBadge, FileType } from 'app/exercises/programming/shared/code-edito import { CodeEditorFileBrowserNodeComponent } from 'app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-node.component'; import { faChevronDown, faChevronRight, faEdit, faFile, faFolder, faFolderOpen, faTrash } from '@fortawesome/free-solid-svg-icons'; import { TreeviewItem } from 'app/exercises/programming/shared/code-editor/treeview/models/treeview-item'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { CodeEditorFileBrowserBadgeComponent } from './code-editor-file-browser-badge.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-code-editor-file-browser-folder', templateUrl: './code-editor-file-browser-folder.component.html', providers: [NgbModal], + imports: [FaIconComponent, CodeEditorFileBrowserBadgeComponent, ArtemisTranslatePipe], }) export class CodeEditorFileBrowserFolderComponent extends CodeEditorFileBrowserNodeComponent { @Input() onCollapseExpand: () => void; diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-node.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-node.component.ts index afe9806ffece..dbd4f7ac93b5 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-node.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-node.component.ts @@ -2,7 +2,9 @@ import { Component, ElementRef, EventEmitter, Input, OnChanges, Output, SimpleCh import { FileType } from 'app/exercises/programming/shared/code-editor/model/code-editor.model'; import { TreeviewItem } from 'app/exercises/programming/shared/code-editor/treeview/models/treeview-item'; -@Component({ template: '' }) +@Component({ + template: '', +}) export abstract class CodeEditorFileBrowserNodeComponent implements OnChanges { FileType = FileType; diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser.component.ts index 158129a2dab8..cfa724dad377 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild, inject } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { Observable, Subscription, of, throwError } from 'rxjs'; import { catchError, map as rxMap, switchMap, tap } from 'rxjs/operators'; @@ -27,6 +27,13 @@ import { TreeItem, TreeviewItem } from 'app/exercises/programming/shared/code-ed import { TreeviewComponent } from 'app/exercises/programming/shared/code-editor/treeview/components/treeview/treeview.component'; import { findItemInList } from 'app/exercises/programming/shared/code-editor/treeview/helpers/treeview-helper'; import { TEXT_FILE_EXTENSIONS } from 'app/shared/constants/file-extensions.constants'; +import { NgStyle } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CodeEditorFileBrowserCreateNodeComponent } from './code-editor-file-browser-create-node.component'; +import { CodeEditorFileBrowserFolderComponent } from './code-editor-file-browser-folder.component'; +import { CodeEditorFileBrowserFileComponent } from './code-editor-file-browser-file.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export type InteractableEvent = { // Click event object; contains target information @@ -47,8 +54,25 @@ export interface FileTreeItem extends TreeItem { templateUrl: './code-editor-file-browser.component.html', styleUrls: ['./code-editor-file-browser.scss'], providers: [NgbModal], + imports: [ + NgStyle, + FaIconComponent, + TranslateDirective, + CodeEditorFileBrowserCreateNodeComponent, + TreeviewComponent, + CodeEditorStatusComponent, + CodeEditorFileBrowserFolderComponent, + CodeEditorFileBrowserFileComponent, + ArtemisTranslatePipe, + ], }) export class CodeEditorFileBrowserComponent implements OnInit, OnChanges, AfterViewInit, IFileDeleteDelegate { + modalService = inject(NgbModal); + private repositoryFileService = inject(CodeEditorRepositoryFileService); + private repositoryService = inject(CodeEditorRepositoryService); + private fileService = inject(CodeEditorFileService); + private conflictService = inject(CodeEditorConflictStateService); + CommitState = CommitState; FileType = FileType; @@ -142,14 +166,6 @@ export class CodeEditorFileBrowserComponent implements OnInit, OnChanges, AfterV this.commitStateChange.emit(commitState); } - constructor( - public modalService: NgbModal, - private repositoryFileService: CodeEditorRepositoryFileService, - private repositoryService: CodeEditorRepositoryService, - private fileService: CodeEditorFileService, - private conflictService: CodeEditorConflictStateService, - ) {} - ngOnInit(): void { this.conflictSubscription = this.conflictService.subscribeConflictState().subscribe((gitConflictState: GitConflictState) => { // When the git conflict was resolved, unset the selectedFile, as it can't be assured that it still exists. diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/header/code-editor-header.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/header/code-editor-header.component.ts index 63ec5588aa4d..b3e6abc479f2 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/header/code-editor-header.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/header/code-editor-header.component.ts @@ -1,14 +1,14 @@ import { ChangeDetectionStrategy, Component, input, model, output } from '@angular/core'; import { faFileAlt } from '@fortawesome/free-regular-svg-icons'; import { faCircleNotch, faGear } from '@fortawesome/free-solid-svg-icons'; +import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'; import { MAX_TAB_SIZE } from 'app/shared/monaco-editor/monaco-editor.component'; import { ArtemisSharedModule } from 'app/shared/shared.module'; @Component({ selector: 'jhi-code-editor-header', templateUrl: './code-editor-header.component.html', - imports: [ArtemisSharedModule], - standalone: true, + imports: [ArtemisSharedModule, NgbDropdown], changeDetection: ChangeDetectionStrategy.OnPush, }) export class CodeEditorHeaderComponent { diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/instructions/code-editor-instructions.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/instructions/code-editor-instructions.component.ts index 2739d8504f12..9a8c234b471e 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/instructions/code-editor-instructions.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/instructions/code-editor-instructions.component.ts @@ -3,11 +3,15 @@ import { faListAlt } from '@fortawesome/free-regular-svg-icons'; import { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons'; import { Interactable } from '@interactjs/core/Interactable'; import interact from 'interactjs'; +import { NgStyle } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-code-editor-instructions', styleUrls: ['./code-editor-instructions.scss'], templateUrl: './code-editor-instructions.component.html', + imports: [NgStyle, FaIconComponent, TranslateDirective], }) export class CodeEditorInstructionsComponent implements AfterViewInit { @Output() @@ -27,8 +31,6 @@ export class CodeEditorInstructionsComponent implements AfterViewInit { faChevronLeft = faChevronLeft; farListAlt = faListAlt; - constructor() {} - /** * After the view was initialized, we create an interact.js resizable object, * designate the edges which can be used to resize the target element and set min and max values. diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/layout/code-editor-grid.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/layout/code-editor-grid.component.ts index f770dd7de1ba..0ae80b132b95 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/layout/code-editor-grid.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/layout/code-editor-grid.component.ts @@ -1,18 +1,22 @@ -import { AfterViewInit, Component, ContentChild, ElementRef, EventEmitter, Input, Output, Renderer2, ViewChild, ViewEncapsulation } from '@angular/core'; +import { AfterViewInit, Component, ContentChild, ElementRef, EventEmitter, Input, Output, Renderer2, ViewChild, ViewEncapsulation, inject } from '@angular/core'; import { Interactable } from '@interactjs/core/Interactable'; import interact from 'interactjs'; import { ResizeType } from 'app/exercises/programming/shared/code-editor/model/code-editor.model'; import { InteractableEvent } from 'app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser.component'; import { faGripLines, faGripLinesVertical } from '@fortawesome/free-solid-svg-icons'; import { CollapsableCodeEditorElement } from 'app/exercises/programming/shared/code-editor/container/code-editor-container.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-code-editor-grid', templateUrl: './code-editor-grid.component.html', styleUrls: ['./code-editor-grid.scss'], encapsulation: ViewEncapsulation.None, + imports: [FaIconComponent], }) export class CodeEditorGridComponent implements AfterViewInit { + private renderer = inject(Renderer2); + @ContentChild('editorSidebarRight', { static: false }) editorSidebarRight: ElementRef; @ContentChild('editorSidebarLeft', { static: false }) editorSidebarLeft: ElementRef; @ContentChild('editorBottomArea', { static: false }) editorBottomArea: ElementRef; @@ -48,8 +52,6 @@ export class CodeEditorGridComponent implements AfterViewInit { faGripLines = faGripLines; faGripLinesVertical = faGripLinesVertical; - constructor(private renderer: Renderer2) {} - /** * After the view was initialized, we create an interact.js resizable object, * designate the edges which can be used to resize the target element and set min and max values. diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/layout/code-editor-repository-is-locked.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/layout/code-editor-repository-is-locked.component.ts index 312443f90241..0c27d6a5e22d 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/layout/code-editor-repository-is-locked.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/layout/code-editor-repository-is-locked.component.ts @@ -1,5 +1,9 @@ import { Component } from '@angular/core'; import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-code-editor-repository-is-locked', @@ -16,6 +20,7 @@ import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'; `, styles: ['.locked-lable {font-size: 1.2rem; color: white}'], + imports: [FaIconComponent, TranslateDirective, NgbTooltip, ArtemisTranslatePipe], }) export class CodeEditorRepositoryIsLockedComponent { // Icons diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/monaco/code-editor-monaco.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/monaco/code-editor-monaco.component.ts index 60ea6ca7fa0e..008f3355249e 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/monaco/code-editor-monaco.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/monaco/code-editor-monaco.component.ts @@ -52,7 +52,6 @@ export type Annotation = { fileName: string; row: number; column: number; text: encapsulation: ViewEncapsulation.None, imports: [ArtemisSharedModule, ArtemisProgrammingManualAssessmentModule, MonacoEditorComponent, CodeEditorHeaderComponent], providers: [RepositoryFileService], - standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, }) export class CodeEditorMonacoComponent implements OnChanges { @@ -128,19 +127,13 @@ export class CodeEditorMonacoComponent implements OnChanges { annotationsArray: Array = []; constructor() { - effect( - () => { - this.feedbackInternal.set(this.feedbacks()); - }, - { allowSignalWrites: true }, - ); + effect(() => { + this.feedbackInternal.set(this.feedbacks()); + }); - effect( - () => { - this.feedbackSuggestionsInternal.set(this.feedbackSuggestions()); - }, - { allowSignalWrites: true }, - ); + effect(() => { + this.feedbackSuggestionsInternal.set(this.feedbackSuggestions()); + }); effect(() => { const annotations = this.buildAnnotations(); diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-conflict-state.service.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-conflict-state.service.ts index a045a3b2b62b..e3429e7e4901 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-conflict-state.service.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-conflict-state.service.ts @@ -1,8 +1,7 @@ import { BehaviorSubject, Observable } from 'rxjs'; -import { Injectable, OnDestroy } from '@angular/core'; +import { Injectable, OnDestroy, inject } from '@angular/core'; import { distinctUntilChanged } from 'rxjs/operators'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; -import { DomainService } from 'app/exercises/programming/shared/code-editor/service/code-editor-domain.service'; import { DomainType, GitConflictState } from 'app/exercises/programming/shared/code-editor/model/code-editor.model'; import { DomainDependentService } from 'app/exercises/programming/shared/code-editor/service/code-editor-domain-dependent.service'; @@ -17,14 +16,13 @@ export interface IConflictStateService { */ @Injectable({ providedIn: 'root' }) export class CodeEditorConflictStateService extends DomainDependentService implements IConflictStateService, OnDestroy { + private jhiWebsocketService = inject(JhiWebsocketService); + private conflictSubjects: Map> = new Map(); private websocketConnections: Map = new Map(); - constructor( - domainService: DomainService, - private jhiWebsocketService: JhiWebsocketService, - ) { - super(domainService); + constructor() { + super(); this.initDomainSubscription(); } diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-domain-dependent-endpoint.service.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-domain-dependent-endpoint.service.ts index b124042fec13..bd34fcd567a0 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-domain-dependent-endpoint.service.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-domain-dependent-endpoint.service.ts @@ -2,20 +2,18 @@ import { DomainDependentService } from 'app/exercises/programming/shared/code-ed import { HttpClient } from '@angular/common/http'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; import { DomainChange, DomainType } from 'app/exercises/programming/shared/code-editor/model/code-editor.model'; -import { DomainService } from 'app/exercises/programming/shared/code-editor/service/code-editor-domain.service'; +import { inject } from '@angular/core'; /** * Service that can be extended to update rest endpoint urls with the received domain information. */ export abstract class DomainDependentEndpointService extends DomainDependentService { protected restResourceUrl?: string; + protected http = inject(HttpClient); + protected jhiWebsocketService = inject(JhiWebsocketService); - protected constructor( - protected http: HttpClient, - protected jhiWebsocketService: JhiWebsocketService, - domainService: DomainService, - ) { - super(domainService); + protected constructor() { + super(); this.initDomainSubscription(); } diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-domain-dependent.service.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-domain-dependent.service.ts index 2445d8f9d351..9b259a208d9a 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-domain-dependent.service.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-domain-dependent.service.ts @@ -1,4 +1,4 @@ -import { Injectable, OnDestroy } from '@angular/core'; +import { Injectable, OnDestroy, inject } from '@angular/core'; import { DomainChange } from 'app/exercises/programming/shared/code-editor/model/code-editor.model'; import { Subscription } from 'rxjs'; import { filter, tap } from 'rxjs/operators'; @@ -9,11 +9,11 @@ import { DomainService } from 'app/exercises/programming/shared/code-editor/serv */ @Injectable({ providedIn: 'root' }) export abstract class DomainDependentService implements OnDestroy { + private domainService = inject(DomainService); + protected domain: DomainChange; protected domainChangeSubscription: Subscription; - protected constructor(private domainService: DomainService) {} - /** * Initializes a domain subscription. */ diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-domain.service.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-domain.service.ts index cebaae778af9..21213d9df226 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-domain.service.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-domain.service.ts @@ -16,8 +16,6 @@ export class DomainService { protected domain: DomainChange; private subject = new BehaviorSubject(undefined); - constructor() {} - /** * Sets domain and subject.next according to parameter. * @param domain - defines new domain of the service. diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-repository.service.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-repository.service.ts index 172146cafe15..11fb43e73077 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-repository.service.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-repository.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpErrorResponse, HttpParams } from '@angular/common/http'; -import { Injectable, OnDestroy } from '@angular/core'; +import { HttpErrorResponse, HttpParams } from '@angular/common/http'; +import { Injectable, OnDestroy, inject } from '@angular/core'; import { Observable, Subject, UnaryFunction, of, pipe, throwError } from 'rxjs'; import { catchError, map, tap } from 'rxjs/operators'; import { @@ -14,8 +14,6 @@ import { } from 'app/exercises/programming/shared/code-editor/model/code-editor.model'; import { CodeEditorConflictStateService } from 'app/exercises/programming/shared/code-editor/service/code-editor-conflict-state.service'; import { BuildLogService } from 'app/exercises/programming/shared/service/build-log.service'; -import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; -import { DomainService } from 'app/exercises/programming/shared/code-editor/service/code-editor-domain.service'; import { DomainDependentEndpointService } from 'app/exercises/programming/shared/code-editor/service/code-editor-domain-dependent-endpoint.service'; import { downloadFile } from 'app/shared/util/download.util'; @@ -79,13 +77,11 @@ const handleErrorResponse = (conflictService: CodeEditorConflictStateService) @Injectable({ providedIn: 'root' }) export class CodeEditorRepositoryService extends DomainDependentEndpointService implements ICodeEditorRepositoryService { - constructor( - http: HttpClient, - jhiWebsocketService: JhiWebsocketService, - domainService: DomainService, - private conflictService: CodeEditorConflictStateService, - ) { - super(http, jhiWebsocketService, domainService); + private conflictService = inject(CodeEditorConflictStateService); + + // necessary to be used in providers array in component + constructor() { + super(); } getStatus = () => { @@ -118,13 +114,11 @@ export class CodeEditorRepositoryService extends DomainDependentEndpointService @Injectable({ providedIn: 'root' }) export class CodeEditorBuildLogService extends DomainDependentEndpointService { - constructor( - private buildLogService: BuildLogService, - http: HttpClient, - jhiWebsocketService: JhiWebsocketService, - domainService: DomainService, - ) { - super(http, jhiWebsocketService, domainService); + private buildLogService = inject(BuildLogService); + + // necessary to be used in providers array in component + constructor() { + super(); } getBuildLogs = () => { @@ -138,14 +132,13 @@ export class CodeEditorBuildLogService extends DomainDependentEndpointService { @Injectable({ providedIn: 'root' }) export class CodeEditorRepositoryFileService extends DomainDependentEndpointService implements ICodeEditorRepositoryFileService, OnDestroy { + private conflictService = inject(CodeEditorConflictStateService); + fileUpdateSubject = new Subject(); - constructor( - http: HttpClient, - jhiWebsocketService: JhiWebsocketService, - domainService: DomainService, - private conflictService: CodeEditorConflictStateService, - ) { - super(http, jhiWebsocketService, domainService); + + // necessary to be used in providers array in component + constructor() { + super(); } /** diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-submission.service.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-submission.service.ts index 31be0e3ab0e4..9b6dc3c6f120 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-submission.service.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/service/code-editor-submission.service.ts @@ -1,8 +1,7 @@ -import { Injectable, OnDestroy } from '@angular/core'; +import { Injectable, OnDestroy, inject } from '@angular/core'; import { AlertService } from 'app/core/util/alert.service'; import { Subject, Subscription } from 'rxjs'; import { map, tap } from 'rxjs/operators'; -import { DomainService } from 'app/exercises/programming/shared/code-editor/service/code-editor-domain.service'; import { ProgrammingSubmissionService, ProgrammingSubmissionState } from 'app/exercises/programming/participate/programming-submission.service'; import { StudentParticipation } from 'app/entities/participation/student-participation.model'; import { SolutionProgrammingExerciseParticipation } from 'app/entities/participation/solution-programming-exercise-participation.model'; @@ -14,17 +13,16 @@ import { DomainDependentService } from 'app/exercises/programming/shared/code-ed */ @Injectable({ providedIn: 'root' }) export class CodeEditorSubmissionService extends DomainDependentService implements OnDestroy { + private submissionService = inject(ProgrammingSubmissionService); + private alertService = inject(AlertService); + private participationId?: number; private exerciseId?: number; private isBuildingSubject = new Subject(); private submissionSubscription: Subscription; - constructor( - domainService: DomainService, - private submissionService: ProgrammingSubmissionService, - private alertService: AlertService, - ) { - super(domainService); + constructor() { + super(); this.initDomainSubscription(); } diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/status/code-editor-status.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/status/code-editor-status.component.ts index 4547d93259bc..da1342e39ac7 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/status/code-editor-status.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/status/code-editor-status.component.ts @@ -1,11 +1,16 @@ import { Component, Input } from '@angular/core'; import { faCheckCircle, faCircleNotch, faExclamationTriangle, faTimesCircle } from '@fortawesome/free-solid-svg-icons'; import { CommitState, EditorState } from 'app/exercises/programming/shared/code-editor/model/code-editor.model'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-code-editor-status', templateUrl: './code-editor-status.component.html', providers: [], + imports: [NgbTooltip, FaIconComponent, TranslateDirective, ArtemisTranslatePipe], }) export class CodeEditorStatusComponent { CommitState = CommitState; diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/treeview/components/treeview-item/treeview-item.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/treeview/components/treeview-item/treeview-item.component.ts index bb8d03651e73..4a82fd6234a1 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/treeview/components/treeview-item/treeview-item.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/treeview/components/treeview-item/treeview-item.component.ts @@ -1,12 +1,13 @@ import { Component, EventEmitter, Input, Output, TemplateRef } from '@angular/core'; import { TreeviewItem } from '../../models/treeview-item'; import { TreeviewItemTemplateContext } from '../../models/treeview-item-template-context'; +import { NgTemplateOutlet } from '@angular/common'; @Component({ - // eslint-disable-next-line @angular-eslint/component-selector selector: 'treeview-item', templateUrl: './treeview-item.component.html', styleUrls: ['./treeview-item.component.scss'], + imports: [NgTemplateOutlet], }) export class TreeviewItemComponent { @Input() template: TemplateRef>; diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/treeview/components/treeview/treeview.component.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/treeview/components/treeview/treeview.component.ts index 6eaec7181425..13a8fba38ca6 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/treeview/components/treeview/treeview.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/treeview/components/treeview/treeview.component.ts @@ -1,12 +1,14 @@ import { Component, EventEmitter, Input, Output, TemplateRef } from '@angular/core'; import { TreeviewItem } from '../../models/treeview-item'; import { TreeviewItemTemplateContext } from '../../models/treeview-item-template-context'; +import { FormsModule } from '@angular/forms'; +import { TreeviewItemComponent } from '../treeview-item/treeview-item.component'; @Component({ - // eslint-disable-next-line @angular-eslint/component-selector selector: 'treeview', templateUrl: './treeview.component.html', styleUrls: ['./treeview.component.scss'], + imports: [FormsModule, TreeviewItemComponent], }) export class TreeviewComponent { @Input() itemTemplate: TemplateRef>; diff --git a/src/main/webapp/app/exercises/programming/shared/code-editor/treeview/treeview.module.ts b/src/main/webapp/app/exercises/programming/shared/code-editor/treeview/treeview.module.ts index 3c229ba788c4..0642b734b261 100644 --- a/src/main/webapp/app/exercises/programming/shared/code-editor/treeview/treeview.module.ts +++ b/src/main/webapp/app/exercises/programming/shared/code-editor/treeview/treeview.module.ts @@ -5,8 +5,7 @@ import { TreeviewComponent } from './components/treeview/treeview.component'; import { TreeviewItemComponent } from './components/treeview-item/treeview-item.component'; @NgModule({ - imports: [FormsModule, CommonModule], - declarations: [TreeviewComponent, TreeviewItemComponent], + imports: [FormsModule, CommonModule, TreeviewComponent, TreeviewItemComponent], exports: [TreeviewComponent], }) export class TreeviewModule { diff --git a/src/main/webapp/app/exercises/programming/shared/commits-info/commits-info-group/commits-info-group.component.ts b/src/main/webapp/app/exercises/programming/shared/commits-info/commits-info-group/commits-info-group.component.ts index 64ed91bab723..9c69a23ff4f3 100644 --- a/src/main/webapp/app/exercises/programming/shared/commits-info/commits-info-group/commits-info-group.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/commits-info/commits-info-group/commits-info-group.component.ts @@ -1,9 +1,12 @@ import { Component, Input } from '@angular/core'; import type { CommitInfo } from 'app/entities/programming/programming-submission.model'; +import { CommitsInfoRowComponent } from './commits-info-row/commits-info-row.component'; +import { NgStyle } from '@angular/common'; @Component({ selector: 'jhi-commits-info-group', templateUrl: './commits-info-group.component.html', + imports: [CommitsInfoRowComponent, NgStyle], }) export class CommitsInfoGroupComponent { @Input() commits: CommitInfo[]; diff --git a/src/main/webapp/app/exercises/programming/shared/commits-info/commits-info-group/commits-info-row/commits-info-row.component.ts b/src/main/webapp/app/exercises/programming/shared/commits-info/commits-info-group/commits-info-row/commits-info-row.component.ts index a944e452e1b4..dc2435949768 100644 --- a/src/main/webapp/app/exercises/programming/shared/commits-info/commits-info-group/commits-info-row/commits-info-row.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/commits-info/commits-info-group/commits-info-row/commits-info-row.component.ts @@ -2,10 +2,18 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import type { CommitInfo } from 'app/entities/programming/programming-submission.model'; import { faCircle } from '@fortawesome/free-regular-svg-icons'; import { faAngleDown, faAngleLeft } from '@fortawesome/free-solid-svg-icons'; +import { RouterLink } from '@angular/router'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ResultComponent } from 'app/exercises/shared/result/result.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { TruncatePipe } from 'app/shared/pipes/truncate.pipe'; @Component({ selector: 'jhi-commits-info-row', templateUrl: './commits-info-row.component.html', + imports: [RouterLink, NgbTooltip, ResultComponent, FaIconComponent, TranslateDirective, ArtemisDatePipe, TruncatePipe], }) export class CommitsInfoRowComponent { @Input() commit: CommitInfo; diff --git a/src/main/webapp/app/exercises/programming/shared/commits-info/commits-info.component.ts b/src/main/webapp/app/exercises/programming/shared/commits-info/commits-info.component.ts index 28a46506caab..61d629913bd7 100644 --- a/src/main/webapp/app/exercises/programming/shared/commits-info/commits-info.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/commits-info/commits-info.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { CommitInfo, ProgrammingSubmission } from 'app/entities/programming/programming-submission.model'; import { ProgrammingExerciseParticipationService } from 'app/exercises/programming/manage/services/programming-exercise-participation.service'; import dayjs from 'dayjs/esm'; @@ -6,12 +6,19 @@ import { createCommitUrl } from 'app/exercises/programming/shared/utils/programm import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { PROFILE_LOCALVC } from 'app/app.constants'; import { Subscription } from 'rxjs'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CommitsInfoGroupComponent } from './commits-info-group/commits-info-group.component'; +import { NgStyle } from '@angular/common'; @Component({ selector: 'jhi-commits-info', templateUrl: './commits-info.component.html', + imports: [TranslateDirective, CommitsInfoGroupComponent, NgStyle], }) export class CommitsInfoComponent implements OnInit, OnDestroy { + private programmingExerciseParticipationService = inject(ProgrammingExerciseParticipationService); + private profileService = inject(ProfileService); + @Input() commits?: CommitInfo[]; @Input() currentSubmissionHash?: string; @Input() previousSubmissionHash?: string; @@ -28,11 +35,6 @@ export class CommitsInfoComponent implements OnInit, OnDestroy { localVC = false; - constructor( - private programmingExerciseParticipationService: ProgrammingExerciseParticipationService, - private profileService: ProfileService, - ) {} - ngOnInit(): void { if (!this.commits) { if (this.participationId) { diff --git a/src/main/webapp/app/exercises/programming/shared/instructions-render/extensions/programming-exercise-plant-uml.extension.ts b/src/main/webapp/app/exercises/programming/shared/instructions-render/extensions/programming-exercise-plant-uml.extension.ts index 886520d929f4..7b691d4dccee 100644 --- a/src/main/webapp/app/exercises/programming/shared/instructions-render/extensions/programming-exercise-plant-uml.extension.ts +++ b/src/main/webapp/app/exercises/programming/shared/instructions-render/extensions/programming-exercise-plant-uml.extension.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ProgrammingExerciseTestCase } from 'app/entities/programming/programming-exercise-test-case.model'; import { ArtemisTextReplacementPlugin } from 'app/shared/markdown-editor/extensions/ArtemisTextReplacementPlugin'; import { escapeStringForUseInRegex } from 'app/shared/util/global.utils'; @@ -14,6 +14,9 @@ const testsColorRegex = /testsColor\((\s*[^()\s]+(\([^()]*\))?)\)/g; @Injectable({ providedIn: 'root' }) export class ProgrammingExercisePlantUmlExtensionWrapper extends ArtemisTextReplacementPlugin { + private programmingExerciseInstructionService = inject(ProgrammingExerciseInstructionService); + private plantUmlService = inject(ProgrammingExercisePlantUmlService); + private latestResult?: Result; private testCases?: ProgrammingExerciseTestCase[]; private injectableElementsFoundSubject = new Subject<() => void>(); @@ -21,10 +24,7 @@ export class ProgrammingExercisePlantUmlExtensionWrapper extends ArtemisTextRepl // unique index, even if multiple plant uml diagrams are shown from different problem statements on the same page (in different tabs) private plantUmlIndex = 0; - constructor( - private programmingExerciseInstructionService: ProgrammingExerciseInstructionService, - private plantUmlService: ProgrammingExercisePlantUmlService, - ) { + constructor() { super(); } diff --git a/src/main/webapp/app/exercises/programming/shared/instructions-render/programming-exercise-instruction.component.ts b/src/main/webapp/app/exercises/programming/shared/instructions-render/programming-exercise-instruction.component.ts index b978289acf7d..30bcf9bf92e4 100644 --- a/src/main/webapp/app/exercises/programming/shared/instructions-render/programming-exercise-instruction.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/instructions-render/programming-exercise-instruction.component.ts @@ -41,13 +41,28 @@ import { ProgrammingExerciseInstructionService } from 'app/exercises/programming import { escapeStringForUseInRegex } from 'app/shared/util/global.utils'; import { ProgrammingExerciseInstructionTaskStatusComponent } from 'app/exercises/programming/shared/instructions-render/task/programming-exercise-instruction-task-status.component'; import { toObservable } from '@angular/core/rxjs-interop'; +import { ProgrammingExerciseInstructionStepWizardComponent } from './step-wizard/programming-exercise-instruction-step-wizard.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-programming-exercise-instructions', templateUrl: './programming-exercise-instruction.component.html', styleUrls: ['./programming-exercise-instruction.scss'], + imports: [ProgrammingExerciseInstructionStepWizardComponent, ExamExerciseUpdateHighlighterComponent, FaIconComponent], }) export class ProgrammingExerciseInstructionComponent implements OnChanges, OnDestroy { + viewContainerRef = inject(ViewContainerRef); + private resultService = inject(ResultService); + private participationWebsocketService = inject(ParticipationWebsocketService); + private programmingExerciseTaskWrapper = inject(ProgrammingExerciseTaskExtensionWrapper); + private programmingExercisePlantUmlWrapper = inject(ProgrammingExercisePlantUmlExtensionWrapper); + private programmingExerciseParticipationService = inject(ProgrammingExerciseParticipationService); + private programmingExerciseGradingService = inject(ProgrammingExerciseGradingService); + private sanitizer = inject(DomSanitizer); + private programmingExerciseInstructionService = inject(ProgrammingExerciseInstructionService); + private appRef = inject(ApplicationRef); + private injector = inject(EnvironmentInjector); + private themeService = inject(ThemeService); @Input() public exercise: ProgrammingExercise; @@ -86,7 +101,6 @@ export class ProgrammingExerciseInstructionComponent implements OnChanges, OnDes markdownExtensions: PluginSimple[]; private injectableContentFoundSubscription: Subscription; - private tasksSubscription: Subscription; private generateHtmlSubscription: Subscription; private testCases?: ProgrammingExerciseTestCase[]; private themeChangeSubscription = toObservable(this.themeService.currentTheme).subscribe(() => { @@ -98,19 +112,7 @@ export class ProgrammingExerciseInstructionComponent implements OnChanges, OnDes // Icons faSpinner = faSpinner; - constructor( - public viewContainerRef: ViewContainerRef, - private resultService: ResultService, - private participationWebsocketService: ParticipationWebsocketService, - private programmingExerciseTaskWrapper: ProgrammingExerciseTaskExtensionWrapper, - private programmingExercisePlantUmlWrapper: ProgrammingExercisePlantUmlExtensionWrapper, - private programmingExerciseParticipationService: ProgrammingExerciseParticipationService, - private programmingExerciseGradingService: ProgrammingExerciseGradingService, - private sanitizer: DomSanitizer, - private programmingExerciseInstructionService: ProgrammingExerciseInstructionService, - private appRef: ApplicationRef, - private injector: EnvironmentInjector, - ) { + constructor() { this.programmingExerciseTaskWrapper.viewContainerRef = this.viewContainerRef; } diff --git a/src/main/webapp/app/exercises/programming/shared/instructions-render/programming-exercise-instructions-render.module.ts b/src/main/webapp/app/exercises/programming/shared/instructions-render/programming-exercise-instructions-render.module.ts index fbfc110d7304..6ae307eb4875 100644 --- a/src/main/webapp/app/exercises/programming/shared/instructions-render/programming-exercise-instructions-render.module.ts +++ b/src/main/webapp/app/exercises/programming/shared/instructions-render/programming-exercise-instructions-render.module.ts @@ -9,8 +9,16 @@ import { ExamExerciseUpdateHighlighterModule } from 'app/exam/participate/exerci import { SafeHtmlPipe } from 'app/shared/pipes/safe-html.pipe'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisResultModule, ArtemisMarkdownModule, ExamExerciseUpdateHighlighterModule, SafeHtmlPipe], - declarations: [ProgrammingExerciseInstructionComponent, ProgrammingExerciseInstructionStepWizardComponent, ProgrammingExerciseInstructionTaskStatusComponent], + imports: [ + ArtemisSharedModule, + ArtemisResultModule, + ArtemisMarkdownModule, + ExamExerciseUpdateHighlighterModule, + SafeHtmlPipe, + ProgrammingExerciseInstructionComponent, + ProgrammingExerciseInstructionStepWizardComponent, + ProgrammingExerciseInstructionTaskStatusComponent, + ], exports: [ProgrammingExerciseInstructionComponent], }) export class ArtemisProgrammingExerciseInstructionsRenderModule {} diff --git a/src/main/webapp/app/exercises/programming/shared/instructions-render/step-wizard/programming-exercise-instruction-step-wizard.component.ts b/src/main/webapp/app/exercises/programming/shared/instructions-render/step-wizard/programming-exercise-instruction-step-wizard.component.ts index 4bd4d7cea397..e5d5deda1062 100644 --- a/src/main/webapp/app/exercises/programming/shared/instructions-render/step-wizard/programming-exercise-instruction-step-wizard.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/instructions-render/step-wizard/programming-exercise-instruction-step-wizard.component.ts @@ -1,18 +1,24 @@ -import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { Component, Input, OnChanges, SimpleChanges, inject } from '@angular/core'; +import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { ProgrammingExerciseInstructionService, TestCaseState } from 'app/exercises/programming/shared/instructions-render/service/programming-exercise-instruction.service'; import { TaskArray } from 'app/exercises/programming/shared/instructions-render/task/programming-exercise-task.model'; import { FeedbackComponent } from 'app/exercises/shared/feedback/feedback.component'; import { Exercise, ExerciseType } from 'app/entities/exercise.model'; import { Result } from 'app/entities/result.model'; import { faCheck, faCircle, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-programming-exercise-instructions-step-wizard', templateUrl: './programming-exercise-instruction-step-wizard.component.html', styleUrls: ['./programming-exercise-instruction-step-wizard.scss'], + imports: [TranslateDirective, NgbTooltip, FaIconComponent], }) export class ProgrammingExerciseInstructionStepWizardComponent implements OnChanges { + private modalService = inject(NgbModal); + private instructionService = inject(ProgrammingExerciseInstructionService); + TestCaseState = TestCaseState; @Input() exercise: Exercise; @@ -26,11 +32,6 @@ export class ProgrammingExerciseInstructionStepWizardComponent implements OnChan faCheck = faCheck; faCircle = faCircle; - constructor( - private modalService: NgbModal, - private instructionService: ProgrammingExerciseInstructionService, - ) {} - /** * Life cycle hook called by Angular to indicate that changes are detected. * @param changes - change that is detected. diff --git a/src/main/webapp/app/exercises/programming/shared/instructions-render/task/programming-exercise-instruction-task-status.component.ts b/src/main/webapp/app/exercises/programming/shared/instructions-render/task/programming-exercise-instruction-task-status.component.ts index e85002c954af..68192ebc955c 100644 --- a/src/main/webapp/app/exercises/programming/shared/instructions-render/task/programming-exercise-instruction-task-status.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/instructions-render/task/programming-exercise-instruction-task-status.component.ts @@ -1,17 +1,24 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { faCheckCircle, faCircleDot, faTimesCircle } from '@fortawesome/free-regular-svg-icons'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { Exercise, ExerciseType } from 'app/entities/exercise.model'; import { Result } from 'app/entities/result.model'; import { ProgrammingExerciseInstructionService, TestCaseState } from 'app/exercises/programming/shared/instructions-render/service/programming-exercise-instruction.service'; import { FeedbackComponent } from 'app/exercises/shared/feedback/feedback.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { SafeHtmlPipe } from 'app/shared/pipes/safe-html.pipe'; @Component({ selector: 'jhi-programming-exercise-instructions-task-status', templateUrl: './programming-exercise-instruction-task-status.component.html', styleUrls: ['./programming-exercise-instruction-task-status.scss'], + imports: [FaIconComponent, ArtemisTranslatePipe, SafeHtmlPipe], }) export class ProgrammingExerciseInstructionTaskStatusComponent { + private programmingExerciseInstructionService = inject(ProgrammingExerciseInstructionService); + private modalService = inject(NgbModal); + TestCaseState = TestCaseState; translationBasePath = 'artemisApp.editor.testStatusLabels.'; @@ -44,11 +51,6 @@ export class ProgrammingExerciseInstructionTaskStatusComponent { farCheckCircle = faCheckCircle; farTimesCircle = faTimesCircle; - constructor( - private programmingExerciseInstructionService: ProgrammingExerciseInstructionService, - private modalService: NgbModal, - ) {} - set testIds(testIds: number[]) { this.testIdsValue = testIds; const { diff --git a/src/main/webapp/app/exercises/programming/shared/lifecycle/programming-exercise-lifecycle.component.ts b/src/main/webapp/app/exercises/programming/shared/lifecycle/programming-exercise-lifecycle.component.ts index d1506497f4d6..547d659f16fe 100644 --- a/src/main/webapp/app/exercises/programming/shared/lifecycle/programming-exercise-lifecycle.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/lifecycle/programming-exercise-lifecycle.component.ts @@ -1,4 +1,5 @@ -import { AfterViewInit, Component, Input, OnChanges, OnDestroy, OnInit, QueryList, SimpleChanges, ViewChildren, input } from '@angular/core'; +import { AfterViewInit, Component, Input, OnChanges, OnDestroy, OnInit, QueryList, SimpleChanges, ViewChildren, inject, input } from '@angular/core'; +import { ExerciseFeedbackSuggestionOptionsComponent } from 'app/exercises/shared/feedback-suggestion/exercise-feedback-suggestion-options.component'; import dayjs from 'dayjs/esm'; import { TranslateService } from '@ngx-translate/core'; import { AssessmentType } from 'app/entities/assessment-type.model'; @@ -14,13 +15,35 @@ import { ActivatedRoute } from '@angular/router'; import { tap } from 'rxjs/operators'; import { ImportOptions } from 'app/types/programming-exercises'; import { ProgrammingExerciseInputField } from 'app/exercises/programming/manage/update/programming-exercise-update.helper'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { AsyncPipe, NgStyle } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-programming-exercise-lifecycle', templateUrl: './programming-exercise-lifecycle.component.html', styleUrls: ['./programming-exercise-test-schedule-picker.scss'], + imports: [ + ProgrammingExerciseTestScheduleDatePickerComponent, + FormsModule, + TranslateDirective, + HelpIconComponent, + FaIconComponent, + NgStyle, + ExerciseFeedbackSuggestionOptionsComponent, + AsyncPipe, + ArtemisTranslatePipe, + ], }) export class ProgrammingExerciseLifecycleComponent implements AfterViewInit, OnDestroy, OnInit, OnChanges { + private translateService = inject(TranslateService); + private exerciseService = inject(ExerciseService); + private athenaService = inject(AthenaService); + private activatedRoute = inject(ActivatedRoute); + protected readonly assessmentType = AssessmentType; protected readonly IncludedInOverallScore = IncludedInOverallScore; protected readonly faCogs = faCogs; @@ -47,13 +70,6 @@ export class ProgrammingExerciseLifecycleComponent implements AfterViewInit, OnD isImport: boolean = false; private urlSubscription: Subscription; - constructor( - private translateService: TranslateService, - private exerciseService: ExerciseService, - private athenaService: AthenaService, - private activatedRoute: ActivatedRoute, - ) {} - /** * If the programming exercise does not have an id, set the assessment Type to AUTOMATIC */ diff --git a/src/main/webapp/app/exercises/programming/shared/lifecycle/programming-exercise-lifecycle.module.ts b/src/main/webapp/app/exercises/programming/shared/lifecycle/programming-exercise-lifecycle.module.ts index 3a6a81c38b82..6e05465983bc 100644 --- a/src/main/webapp/app/exercises/programming/shared/lifecycle/programming-exercise-lifecycle.module.ts +++ b/src/main/webapp/app/exercises/programming/shared/lifecycle/programming-exercise-lifecycle.module.ts @@ -7,8 +7,14 @@ import { OwlDateTimeModule } from '@danielmoncada/angular-datetime-picker'; import { ExerciseFeedbackSuggestionOptionsModule } from 'app/exercises/shared/feedback-suggestion/exercise-feedback-suggestion-options.module'; @NgModule({ - imports: [ArtemisSharedComponentModule, OwlDateTimeModule, ArtemisSharedModule, ExerciseFeedbackSuggestionOptionsModule], - declarations: [ProgrammingExerciseLifecycleComponent, ProgrammingExerciseTestScheduleDatePickerComponent], + imports: [ + ArtemisSharedComponentModule, + OwlDateTimeModule, + ArtemisSharedModule, + ExerciseFeedbackSuggestionOptionsModule, + ProgrammingExerciseLifecycleComponent, + ProgrammingExerciseTestScheduleDatePickerComponent, + ], exports: [ProgrammingExerciseLifecycleComponent], }) export class ArtemisProgrammingExerciseLifecycleModule {} diff --git a/src/main/webapp/app/exercises/programming/shared/lifecycle/programming-exercise-test-schedule-date-picker.component.ts b/src/main/webapp/app/exercises/programming/shared/lifecycle/programming-exercise-test-schedule-date-picker.component.ts index e0766b849452..20e118b715d7 100644 --- a/src/main/webapp/app/exercises/programming/shared/lifecycle/programming-exercise-test-schedule-date-picker.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/lifecycle/programming-exercise-test-schedule-date-picker.component.ts @@ -1,8 +1,13 @@ import { Component, EventEmitter, Input, Output, ViewChild, forwardRef } from '@angular/core'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR, NgModel } from '@angular/forms'; +import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR, NgModel } from '@angular/forms'; import dayjs from 'dayjs/esm'; import { isDate } from 'app/shared/util/utils'; import { faCalendarCheck, faCalendarMinus, faCalendarPlus } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { OwlDateTimeModule } from '@danielmoncada/angular-datetime-picker'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; @Component({ selector: 'jhi-programming-exercise-test-schedule-date-picker', @@ -15,6 +20,7 @@ import { faCalendarCheck, faCalendarMinus, faCalendarPlus } from '@fortawesome/f }, ], styleUrls: ['./programming-exercise-test-schedule-picker.scss'], + imports: [TranslateDirective, HelpIconComponent, FormsModule, OwlDateTimeModule, FaIconComponent, ArtemisDatePipe], }) export class ProgrammingExerciseTestScheduleDatePickerComponent implements ControlValueAccessor { @ViewChild('dateInput', { static: false }) dateInput: NgModel; diff --git a/src/main/webapp/app/exercises/programming/shared/programming-exercise.module.ts b/src/main/webapp/app/exercises/programming/shared/programming-exercise.module.ts index 9953a9f5aa84..a9afe6cd545f 100644 --- a/src/main/webapp/app/exercises/programming/shared/programming-exercise.module.ts +++ b/src/main/webapp/app/exercises/programming/shared/programming-exercise.module.ts @@ -5,7 +5,7 @@ import { OrionModule } from 'app/shared/orion/orion.module'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { RouterModule } from '@angular/router'; import { ArtemisProgrammingExerciseGradingModule } from 'app/exercises/programming/manage/grading/programming-exercise-grading.module'; -import { FeatureToggleModule } from 'app/shared/feature-toggle/feature-toggle.module'; + import { ArtemisExerciseScoresModule } from 'app/exercises/shared/exercise-scores/exercise-scores.module'; import { OrionProgrammingExerciseComponent } from 'app/orion/management/orion-programming-exercise.component'; import { ArtemisProgrammingAssessmentModule } from 'app/exercises/programming/assess/programming-assessment.module'; @@ -21,7 +21,6 @@ import { CommitsInfoRowComponent } from 'app/exercises/programming/shared/commit @NgModule({ imports: [ ArtemisSharedModule, - FeatureToggleModule, RouterModule, OrionModule, ArtemisProgrammingExerciseStatusModule, @@ -30,8 +29,6 @@ import { CommitsInfoRowComponent } from 'app/exercises/programming/shared/commit ArtemisProgrammingAssessmentModule, ExerciseCategoriesModule, SubmissionResultStatusModule, - ], - declarations: [ ProgrammingExerciseComponent, ProgrammingExerciseCreateButtonsComponent, OrionProgrammingExerciseComponent, diff --git a/src/main/webapp/app/exercises/programming/shared/service/aeolus.service.ts b/src/main/webapp/app/exercises/programming/shared/service/aeolus.service.ts index 9c07e5caee1f..528be78989c1 100644 --- a/src/main/webapp/app/exercises/programming/shared/service/aeolus.service.ts +++ b/src/main/webapp/app/exercises/programming/shared/service/aeolus.service.ts @@ -1,5 +1,5 @@ import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { BuildAction, PlatformAction, ScriptAction } from 'app/entities/programming/build.action'; import { WindFile } from 'app/entities/programming/wind.file'; import { Observable } from 'rxjs'; @@ -8,9 +8,9 @@ import { ProgrammingLanguage, ProjectType } from 'app/entities/programming/progr @Injectable({ providedIn: 'root' }) export class AeolusService { - private resourceUrl = 'api/aeolus'; + private http = inject(HttpClient); - constructor(private http: HttpClient) {} + private resourceUrl = 'api/aeolus'; /** * Fetches the aeolus template file for the given programming language diff --git a/src/main/webapp/app/exercises/programming/shared/service/build-log.service.ts b/src/main/webapp/app/exercises/programming/shared/service/build-log.service.ts index 3f749357f188..74926345a2c0 100644 --- a/src/main/webapp/app/exercises/programming/shared/service/build-log.service.ts +++ b/src/main/webapp/app/exercises/programming/shared/service/build-log.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { HttpClient, HttpParams } from '@angular/common/http'; import { BuildLogEntry } from 'app/entities/programming/build-log.model'; @@ -9,9 +9,9 @@ export interface IBuildLogService { @Injectable({ providedIn: 'root' }) export class BuildLogService implements IBuildLogService { - private assignmentResourceUrl = 'api/repository'; + private http = inject(HttpClient); - constructor(private http: HttpClient) {} + private assignmentResourceUrl = 'api/repository'; /** * Retrieves the build logs for a given participation and optionally, a given result. diff --git a/src/main/webapp/app/exercises/programming/shared/service/file-type.service.ts b/src/main/webapp/app/exercises/programming/shared/service/file-type.service.ts index cce6e02d4b2e..a656b814f4db 100644 --- a/src/main/webapp/app/exercises/programming/shared/service/file-type.service.ts +++ b/src/main/webapp/app/exercises/programming/shared/service/file-type.service.ts @@ -9,8 +9,6 @@ const IGNORED_CHAR_CODES = [CHAR_CODE_TAB, CHAR_CODE_LINE_FEED, CHAR_CODE_CARRIA providedIn: 'root', }) export class FileTypeService { - constructor() {} - /** * Determines for a string whether it represents the content of a binary file. * This is done by checking for characters that would not typically be found in plain text files, e.g. the 0-byte. diff --git a/src/main/webapp/app/exercises/programming/shared/service/programming-language-feature/programming-language-feature.service.ts b/src/main/webapp/app/exercises/programming/shared/service/programming-language-feature/programming-language-feature.service.ts index e535502030ef..9188c2afaea0 100644 --- a/src/main/webapp/app/exercises/programming/shared/service/programming-language-feature/programming-language-feature.service.ts +++ b/src/main/webapp/app/exercises/programming/shared/service/programming-language-feature/programming-language-feature.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ProgrammingLanguage, ProjectType } from 'app/entities/programming/programming-exercise.model'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; @@ -19,9 +19,11 @@ export type ProgrammingLanguageFeature = { @Injectable({ providedIn: 'root' }) export class ProgrammingLanguageFeatureService { + private profileService = inject(ProfileService); + private programmingLanguageFeatures: Map = new Map(); - constructor(private profileService: ProfileService) { + constructor() { this.profileService.getProfileInfo().subscribe((profileInfo) => { profileInfo.programmingLanguageFeatures.forEach((programmingLanguageFeature) => { this.programmingLanguageFeatures.set(programmingLanguageFeature.programmingLanguage, programmingLanguageFeature); diff --git a/src/main/webapp/app/exercises/programming/shared/service/theia.service.ts b/src/main/webapp/app/exercises/programming/shared/service/theia.service.ts index 3165730ddab7..c82734db10b9 100644 --- a/src/main/webapp/app/exercises/programming/shared/service/theia.service.ts +++ b/src/main/webapp/app/exercises/programming/shared/service/theia.service.ts @@ -1,14 +1,14 @@ import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { ProgrammingLanguage } from 'app/entities/programming/programming-exercise.model'; @Injectable({ providedIn: 'root' }) export class TheiaService { - private resourceUrl = 'api/theia'; + private http = inject(HttpClient); - constructor(private http: HttpClient) {} + private resourceUrl = 'api/theia'; /** * Fetches the theia images for the given programming language diff --git a/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-create-form.component.ts b/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-create-form.component.ts index 64cd23e5d90d..96f4e84bbd71 100644 --- a/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-create-form.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-create-form.component.ts @@ -1,16 +1,24 @@ -import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, ViewChild, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { AlertService } from 'app/core/util/alert.service'; import { ApollonDiagramService } from 'app/exercises/quiz/manage/apollon-diagrams/apollon-diagram.service'; import { ApollonDiagram } from 'app/entities/apollon-diagram.model'; import { faSave } from '@fortawesome/free-solid-svg-icons'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-apollon-diagram-create-form', templateUrl: './apollon-diagram-create-form.component.html', providers: [ApollonDiagramService], + imports: [FormsModule, TranslateDirective, FaIconComponent], }) export class ApollonDiagramCreateFormComponent implements AfterViewInit { + private activeModal = inject(NgbActiveModal); + private apollonDiagramService = inject(ApollonDiagramService); + private alertService = inject(AlertService); + apollonDiagram: ApollonDiagram; isSaving: boolean; @ViewChild('titleInput', { static: false }) titleInput: ElementRef; @@ -18,12 +26,6 @@ export class ApollonDiagramCreateFormComponent implements AfterViewInit { // Icons faSave = faSave; - constructor( - private activeModal: NgbActiveModal, - private apollonDiagramService: ApollonDiagramService, - private alertService: AlertService, - ) {} - /** * Adds focus on the title input field */ diff --git a/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-detail.component.ts b/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-detail.component.ts index ef93f826cc49..cd30090ee2d7 100644 --- a/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-detail.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-detail.component.ts @@ -1,7 +1,7 @@ -import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; +import { Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { ApollonEditor, ApollonMode, Locale, UMLModel } from '@ls1intum/apollon'; -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbModalRef, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { JhiLanguageHelper } from 'app/core/language/language.helper'; import { convertRenderedSVGToPNG } from './exercise-generation/svg-renderer'; import { ApollonDiagramService } from 'app/exercises/quiz/manage/apollon-diagrams/apollon-diagram.service'; @@ -16,14 +16,26 @@ import { CourseManagementService } from 'app/course/manage/course-management.ser import { DragAndDropQuestion } from 'app/entities/quiz/drag-and-drop-question.model'; import { ConfirmAutofocusModalComponent } from 'app/shared/components/confirm-autofocus-modal.component'; import { lastValueFrom } from 'rxjs'; -import { NgModel } from '@angular/forms'; +import { FormsModule, NgModel } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-apollon-diagram-detail', templateUrl: './apollon-diagram-detail.component.html', providers: [ApollonDiagramService], + imports: [TranslateDirective, FaIconComponent, FormsModule, NgbTooltip, ArtemisTranslatePipe], }) export class ApollonDiagramDetailComponent implements OnInit, OnDestroy { + private apollonDiagramService = inject(ApollonDiagramService); + private courseService = inject(CourseManagementService); + private alertService = inject(AlertService); + private translateService = inject(TranslateService); + private languageHelper = inject(JhiLanguageHelper); + private modalService = inject(NgbModal); + private route = inject(ActivatedRoute); + @ViewChild('editorContainer', { static: false }) editorContainer: ElementRef; @ViewChild('titleField') titleField?: NgModel; @@ -71,16 +83,6 @@ export class ApollonDiagramDetailComponent implements OnInit, OnDestroy { faArrow = faArrowLeft; faX = faX; - constructor( - private apollonDiagramService: ApollonDiagramService, - private courseService: CourseManagementService, - private alertService: AlertService, - private translateService: TranslateService, - private languageHelper: JhiLanguageHelper, - private modalService: NgbModal, - private route: ActivatedRoute, - ) {} - /** * Initializes Apollon Editor and sets auto save timer */ diff --git a/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-import-dialog.component.ts b/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-import-dialog.component.ts index 6f62cf1de360..edc94bcea84d 100644 --- a/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-import-dialog.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-import-dialog.component.ts @@ -1,22 +1,25 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { ApollonDiagramService } from 'app/exercises/quiz/manage/apollon-diagrams/apollon-diagram.service'; import { DragAndDropQuestion } from 'app/entities/quiz/drag-and-drop-question.model'; +import { ApollonDiagramListComponent } from './apollon-diagram-list.component'; +import { ApollonDiagramDetailComponent } from './apollon-diagram-detail.component'; @Component({ selector: 'jhi-apollon-diagram-import-dialog', templateUrl: './apollon-diagram-import-dialog.component.html', providers: [ApollonDiagramService], + imports: [ApollonDiagramListComponent, ApollonDiagramDetailComponent], }) export class ApollonDiagramImportDialogComponent { + private activeModal = inject(NgbActiveModal); + @Input() courseId: number; isInEditView = false; apollonDiagramDetailId: number; - constructor(private activeModal: NgbActiveModal) {} - handleDetailOpen(id: number) { this.isInEditView = true; this.apollonDiagramDetailId = id; diff --git a/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-list.component.ts b/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-list.component.ts index fbcb1c0fb0b2..97e729b61d97 100644 --- a/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-list.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-list.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core'; import { HttpResponse } from '@angular/common/http'; import { ActivatedRoute } from '@angular/router'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; @@ -14,13 +14,27 @@ import { Course } from 'app/entities/course.model'; import { faPlus, faSort, faTimes, faX } from '@fortawesome/free-solid-svg-icons'; import { ButtonSize } from 'app/shared/components/button.component'; import { UMLDiagramType } from '@ls1intum/apollon'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; @Component({ selector: 'jhi-apollon-diagram-list', templateUrl: './apollon-diagram-list.component.html', providers: [ApollonDiagramService], + imports: [TranslateDirective, FaIconComponent, SortDirective, SortByDirective, DeleteButtonDirective], }) export class ApollonDiagramListComponent implements OnInit { + private apollonDiagramsService = inject(ApollonDiagramService); + private alertService = inject(AlertService); + private modalService = inject(NgbModal); + private sortService = inject(SortService); + private route = inject(ActivatedRoute); + private courseService = inject(CourseManagementService); + private accountService = inject(AccountService); + apollonDiagrams: ApollonDiagram[] = []; predicate: string; reverse: boolean; @@ -43,15 +57,7 @@ export class ApollonDiagramListComponent implements OnInit { ButtonSize = ButtonSize; - constructor( - private apollonDiagramsService: ApollonDiagramService, - private alertService: AlertService, - private modalService: NgbModal, - private sortService: SortService, - private route: ActivatedRoute, - private courseService: CourseManagementService, - private accountService: AccountService, - ) { + constructor() { this.predicate = 'id'; this.reverse = true; } diff --git a/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram.module.ts b/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram.module.ts index fb7448499f4c..b9104e1d2bc5 100644 --- a/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram.module.ts +++ b/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram.module.ts @@ -6,7 +6,6 @@ import { ApollonDiagramListComponent } from './apollon-diagram-list.component'; import { ArtemisSharedModule } from 'app/shared/shared.module'; @NgModule({ - imports: [ArtemisSharedModule], - declarations: [ApollonDiagramCreateFormComponent, ApollonDiagramDetailComponent, ApollonDiagramListComponent, ApollonDiagramImportDialogComponent], + imports: [ArtemisSharedModule, ApollonDiagramCreateFormComponent, ApollonDiagramDetailComponent, ApollonDiagramListComponent, ApollonDiagramImportDialogComponent], }) export class ArtemisApollonDiagramsModule {} diff --git a/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram.service.ts b/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram.service.ts index fd6fd5cb1fd7..f99733ab4681 100644 --- a/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram.service.ts +++ b/src/main/webapp/app/exercises/quiz/manage/apollon-diagrams/apollon-diagram.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable, tap } from 'rxjs'; @@ -10,12 +10,10 @@ export type EntityResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class ApollonDiagramService { - private resourceUrl = 'api'; + private http = inject(HttpClient); + private entityTitleService = inject(EntityTitleService); - constructor( - private http: HttpClient, - private entityTitleService: EntityTitleService, - ) {} + private resourceUrl = 'api'; /** * Creates diagram. diff --git a/src/main/webapp/app/exercises/quiz/manage/drag-and-drop-question/drag-and-drop-question-edit.component.ts b/src/main/webapp/app/exercises/quiz/manage/drag-and-drop-question/drag-and-drop-question-edit.component.ts index 56ec3e7aaaec..ddb1427917b2 100644 --- a/src/main/webapp/app/exercises/quiz/manage/drag-and-drop-question/drag-and-drop-question-edit.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/drag-and-drop-question/drag-and-drop-question-edit.component.ts @@ -11,22 +11,37 @@ import { SimpleChanges, ViewChild, ViewEncapsulation, + inject, } from '@angular/core'; import { DragAndDropQuestionUtil } from 'app/exercises/quiz/shared/drag-and-drop-question-util.service'; import { DragAndDropMouseEvent } from 'app/exercises/quiz/manage/drag-and-drop-question/drag-and-drop-mouse-event.class'; import { DragState } from 'app/entities/quiz/drag-state.enum'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbCollapse, NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { DragAndDropMapping } from 'app/entities/quiz/drag-and-drop-mapping.model'; import { DragAndDropQuestion } from 'app/entities/quiz/drag-and-drop-question.model'; import { DragItem } from 'app/entities/quiz/drag-item.model'; import { DropLocation } from 'app/entities/quiz/drop-location.model'; import { QuizQuestionEdit } from 'app/exercises/quiz/manage/quiz-question-edit.interface'; +import { DragAndDropQuestionComponent } from 'app/exercises/quiz/shared/questions/drag-and-drop-question/drag-and-drop-question.component'; import { cloneDeep } from 'lodash-es'; import { round } from 'app/shared/util/utils'; import { MAX_SIZE_UNIT } from 'app/exercises/quiz/manage/apollon-diagrams/exercise-generation/quiz-exercise-generator'; import { debounceTime, filter } from 'rxjs/operators'; import { ImageLoadingStatus, SecuredImageComponent } from 'app/shared/image/secured-image.component'; import { generateExerciseHintExplanation } from 'app/shared/util/markdown.util'; +import { faFileImage } from '@fortawesome/free-regular-svg-icons'; +import { CdkDrag, CdkDragDrop, CdkDragPlaceholder, CdkDragPreview, CdkDropList, CdkDropListGroup } from '@angular/cdk/drag-drop'; +import { MAX_QUIZ_QUESTION_POINTS } from 'app/shared/constants/input.constants'; +import { FileService } from 'app/shared/http/file.service'; +import { QuizHintAction } from 'app/shared/monaco-editor/model/actions/quiz/quiz-hint.action'; +import { QuizExplanationAction } from 'app/shared/monaco-editor/model/actions/quiz/quiz-explanation.action'; +import { MarkdownEditorMonacoComponent, TextWithDomainAction } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { QuizScoringInfoModalComponent } from '../quiz-scoring-info-modal/quiz-scoring-info-modal.component'; +import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; import { faAngleDown, faAngleRight, @@ -45,13 +60,6 @@ import { faUnlink, faUpload, } from '@fortawesome/free-solid-svg-icons'; -import { faFileImage } from '@fortawesome/free-regular-svg-icons'; -import { CdkDragDrop } from '@angular/cdk/drag-drop'; -import { MAX_QUIZ_QUESTION_POINTS } from 'app/shared/constants/input.constants'; -import { FileService } from 'app/shared/http/file.service'; -import { QuizHintAction } from 'app/shared/monaco-editor/model/actions/quiz/quiz-hint.action'; -import { QuizExplanationAction } from 'app/shared/monaco-editor/model/actions/quiz/quiz-explanation.action'; -import { MarkdownEditorMonacoComponent, TextWithDomainAction } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; @Component({ selector: 'jhi-drag-and-drop-question-edit', @@ -59,8 +67,33 @@ import { MarkdownEditorMonacoComponent, TextWithDomainAction } from 'app/shared/ providers: [DragAndDropQuestionUtil], styleUrls: ['./drag-and-drop-question-edit.component.scss', '../quiz-exercise.scss', '../../shared/quiz.scss'], encapsulation: ViewEncapsulation.None, + imports: [ + FaIconComponent, + FormsModule, + TranslateDirective, + NgbTooltip, + NgbCollapse, + QuizScoringInfoModalComponent, + MarkdownEditorMonacoComponent, + CdkDropListGroup, + SecuredImageComponent, + NgClass, + CdkDropList, + NgStyle, + CdkDrag, + CdkDragPreview, + NgTemplateOutlet, + CdkDragPlaceholder, + DragAndDropQuestionComponent, + ArtemisTranslatePipe, + ], }) export class DragAndDropQuestionEditComponent implements OnInit, OnChanges, AfterViewInit, QuizQuestionEdit { + private dragAndDropQuestionUtil = inject(DragAndDropQuestionUtil); + private modalService = inject(NgbModal); + private changeDetector = inject(ChangeDetectorRef); + private fileService = inject(FileService); + @ViewChild('clickLayer', { static: false }) private clickLayer: ElementRef; @ViewChild('backgroundImage ', { static: false }) private backgroundImage: SecuredImageComponent; @ViewChild('markdownEditor', { static: false }) private markdownEditor: MarkdownEditorMonacoComponent; @@ -131,13 +164,6 @@ export class DragAndDropQuestionEditComponent implements OnInit, OnChanges, Afte readonly MAX_POINTS = MAX_QUIZ_QUESTION_POINTS; - constructor( - private dragAndDropQuestionUtil: DragAndDropQuestionUtil, - private modalService: NgbModal, - private changeDetector: ChangeDetectorRef, - private fileService: FileService, - ) {} - /** * Actions when initializing component. */ diff --git a/src/main/webapp/app/exercises/quiz/manage/match-percentage-info-modal/match-percentage-info-modal.component.ts b/src/main/webapp/app/exercises/quiz/manage/match-percentage-info-modal/match-percentage-info-modal.component.ts index 447ea315e40b..07f4c1477bfd 100644 --- a/src/main/webapp/app/exercises/quiz/manage/match-percentage-info-modal/match-percentage-info-modal.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/match-percentage-info-modal/match-percentage-info-modal.component.ts @@ -1,15 +1,19 @@ -import { Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { faQuestionCircle } from '@fortawesome/free-regular-svg-icons'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-match-percentage-info-modal', templateUrl: './match-percentage-info-modal.component.html', + imports: [TranslateDirective, FaIconComponent], }) export class MatchPercentageInfoModalComponent { + private modalService = inject(NgbModal); + // Icons farQuestionCircle = faQuestionCircle; - constructor(private modalService: NgbModal) {} /** * Open a large modal with the given content. diff --git a/src/main/webapp/app/exercises/quiz/manage/multiple-choice-question/multiple-choice-question-edit.component.ts b/src/main/webapp/app/exercises/quiz/manage/multiple-choice-question/multiple-choice-question-edit.component.ts index 553aa5f3edf8..5d917c4a0c49 100644 --- a/src/main/webapp/app/exercises/quiz/manage/multiple-choice-question/multiple-choice-question-edit.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/multiple-choice-question/multiple-choice-question-edit.component.ts @@ -1,8 +1,9 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation, inject } from '@angular/core'; +import { NgbCollapse, NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { AnswerOption } from 'app/entities/quiz/answer-option.model'; import { MultipleChoiceQuestion } from 'app/entities/quiz/multiple-choice-question.model'; import { QuizQuestionEdit } from 'app/exercises/quiz/manage/quiz-question-edit.interface'; +import { MultipleChoiceQuestionComponent } from 'app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-question.component'; import { generateExerciseHintExplanation } from 'app/shared/util/markdown.util'; import { faAngleDown, faAngleRight, faQuestionCircle, faTrash } from '@fortawesome/free-solid-svg-icons'; import { ScoringType } from 'app/entities/quiz/quiz-question.model'; @@ -13,6 +14,11 @@ import { CorrectMultipleChoiceAnswerAction } from 'app/shared/monaco-editor/mode import { QuizExplanationAction } from 'app/shared/monaco-editor/model/actions/quiz/quiz-explanation.action'; import { MarkdownEditorMonacoComponent, TextWithDomainAction } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; import { MultipleChoiceVisualQuestionComponent } from 'app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-visual-question.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { QuizScoringInfoModalComponent } from '../quiz-scoring-info-modal/quiz-scoring-info-modal.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-multiple-choice-question-edit', @@ -20,8 +26,23 @@ import { MultipleChoiceVisualQuestionComponent } from 'app/exercises/quiz/shared styleUrls: ['../quiz-exercise.scss', '../../shared/quiz.scss'], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, + imports: [ + FaIconComponent, + FormsModule, + TranslateDirective, + NgbCollapse, + QuizScoringInfoModalComponent, + NgbTooltip, + MarkdownEditorMonacoComponent, + MultipleChoiceQuestionComponent, + MultipleChoiceVisualQuestionComponent, + ArtemisTranslatePipe, + ], }) export class MultipleChoiceQuestionEditComponent implements OnInit, QuizQuestionEdit { + private modalService = inject(NgbModal); + private changeDetector = inject(ChangeDetectorRef); + @ViewChild('markdownEditor', { static: false }) private markdownEditor: MarkdownEditorMonacoComponent; @@ -63,11 +84,6 @@ export class MultipleChoiceQuestionEditComponent implements OnInit, QuizQuestion readonly MAX_POINTS = MAX_QUIZ_QUESTION_POINTS; - constructor( - private modalService: NgbModal, - private changeDetector: ChangeDetectorRef, - ) {} - /** * Init the question editor text by parsing the markdown. */ diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-confirm-import-invalid-questions-modal.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-confirm-import-invalid-questions-modal.component.ts index 9c690f072e19..a4bb1ee35156 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-confirm-import-invalid-questions-modal.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-confirm-import-invalid-questions-modal.component.ts @@ -1,21 +1,26 @@ -import { Component, EventEmitter } from '@angular/core'; +import { Component, EventEmitter, inject } from '@angular/core'; import { faBan, faExclamationTriangle, faTimes } from '@fortawesome/free-solid-svg-icons'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { ValidationReason } from 'app/entities/exercise.model'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { JsonPipe } from '@angular/common'; @Component({ selector: 'jhi-quiz-confirm-import-invalid-questions-modal', templateUrl: './quiz-confirm-import-invalid-questions-modal.component.html', styleUrls: ['./quiz-confirm-import-invalid-questions-modal.scss'], + imports: [FormsModule, TranslateDirective, FaIconComponent, JsonPipe], }) export class QuizConfirmImportInvalidQuestionsModalComponent { + activeModal = inject(NgbActiveModal); + // Icons faBan = faBan; faTimes = faTimes; faExclamationTriangle = faExclamationTriangle; - constructor(public activeModal: NgbActiveModal) {} - invalidFlaggedQuestions: ValidationReason[]; shouldImport: EventEmitter = new EventEmitter(); diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-create-buttons.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-create-buttons.component.ts index 80924d7e8254..fb7b697885cd 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-create-buttons.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-create-buttons.component.ts @@ -1,17 +1,23 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { Course } from 'app/entities/course.model'; import { faCheckDouble, faFileExport, faFileImport, faPlus } from '@fortawesome/free-solid-svg-icons'; import { ExerciseImportWrapperComponent } from 'app/exercises/shared/import/exercise-import-wrapper/exercise-import-wrapper.component'; import { ExerciseType } from 'app/entities/exercise.model'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { Router } from '@angular/router'; +import { Router, RouterLink } from '@angular/router'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-quiz-exercise-create-buttons', templateUrl: './quiz-exercise-create-buttons.component.html', + imports: [RouterLink, FaIconComponent, TranslateDirective], }) export class QuizExerciseCreateButtonsComponent { + private router = inject(Router); + private modalService = inject(NgbModal); + @Input() course: Course; @Input() quizExercisesCount: number; @@ -21,11 +27,6 @@ export class QuizExerciseCreateButtonsComponent { faFileExport = faFileExport; faCheckDouble = faCheckDouble; - constructor( - private router: Router, - private modalService: NgbModal, - ) {} - /** * Opens the import modal for a quiz exercise */ diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-detail.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-detail.component.ts index 77166e7bfb2b..e12d777b0826 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-detail.component.ts @@ -1,5 +1,6 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; +import { ExerciseDetailStatisticsComponent } from 'app/exercises/shared/statistics/exercise-detail-statistics.component'; import dayjs from 'dayjs/esm'; import { QuizExerciseService } from 'app/exercises/quiz/manage/quiz-exercise.service'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; @@ -13,12 +14,30 @@ import { ExerciseManagementStatisticsDto } from 'app/exercises/shared/statistics import { StatisticsService } from 'app/shared/statistics-graph/statistics.service'; import { TranslateService } from '@ngx-translate/core'; import { QuizQuestionType } from 'app/entities/quiz/quiz-question.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { QuizExerciseManageButtonsComponent } from './quiz-exercise-manage-buttons.component'; +import { QuizExerciseLifecycleButtonsComponent } from './quiz-exercise-lifecycle-buttons.component'; +import { DetailOverviewListComponent } from 'app/detail-overview-list/detail-overview-list.component'; @Component({ selector: 'jhi-quiz-exercise-detail', templateUrl: './quiz-exercise-detail.component.html', + imports: [ + TranslateDirective, + DocumentationButtonComponent, + QuizExerciseManageButtonsComponent, + QuizExerciseLifecycleButtonsComponent, + ExerciseDetailStatisticsComponent, + DetailOverviewListComponent, + ], }) export class QuizExerciseDetailComponent implements OnInit { + private route = inject(ActivatedRoute); + private quizExerciseService = inject(QuizExerciseService); + private statisticsService = inject(StatisticsService); + private translateService = inject(TranslateService); + readonly documentationType: DocumentationType = 'Quiz'; readonly dayjs = dayjs; @@ -33,13 +52,6 @@ export class QuizExerciseDetailComponent implements OnInit { detailOverviewSections: DetailOverviewSection[]; - constructor( - private route: ActivatedRoute, - private quizExerciseService: QuizExerciseService, - private statisticsService: StatisticsService, - private translateService: TranslateService, - ) {} - /** * Load the quizzes of the course for export on init. */ diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-export.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-export.component.ts index 149419c039ca..816f33e08c60 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-export.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-export.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { TranslateService } from '@ngx-translate/core'; @@ -10,26 +10,27 @@ import { CourseManagementService } from 'app/course/manage/course-management.ser import { QuizQuestion } from 'app/entities/quiz/quiz-question.model'; import { Course } from 'app/entities/course.model'; import { onError } from 'app/shared/util/global.utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; @Component({ selector: 'jhi-quiz-exercise-export', templateUrl: './quiz-exercise-export.component.html', styleUrls: ['./quiz-exercise-export.component.scss', '../shared/quiz.scss'], + imports: [TranslateDirective, FormsModule], }) export class QuizExerciseExportComponent implements OnInit { + private route = inject(ActivatedRoute); + private quizExerciseService = inject(QuizExerciseService); + private courseService = inject(CourseManagementService); + private alertService = inject(AlertService); + private router = inject(Router); + private translateService = inject(TranslateService); + questions: QuizQuestion[] = new Array(0); courseId: number; course: Course; - constructor( - private route: ActivatedRoute, - private quizExerciseService: QuizExerciseService, - private courseService: CourseManagementService, - private alertService: AlertService, - private router: Router, - private translateService: TranslateService, - ) {} - /** * Load the quizzes of the course for export on init. */ diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-lifecycle-buttons.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-lifecycle-buttons.component.ts index 8732f2f297ff..bbd9a2b84872 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-lifecycle-buttons.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-lifecycle-buttons.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output, inject } from '@angular/core'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { QuizExercise, QuizMode, QuizStatus } from 'app/entities/quiz/quiz-exercise.model'; import { QuizExerciseService } from './quiz-exercise.service'; @@ -6,12 +6,19 @@ import { ActionType } from 'app/shared/delete-dialog/delete-dialog.model'; import { AlertService } from 'app/core/util/alert.service'; import { faEye, faFileExport, faPlayCircle, faPlus, faSignal, faSort, faStopCircle, faTable, faTimes, faWrench } from '@fortawesome/free-solid-svg-icons'; import { Subject } from 'rxjs'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; @Component({ selector: 'jhi-quiz-exercise-lifecycle-buttons', templateUrl: './quiz-exercise-lifecycle-buttons.component.html', + imports: [FaIconComponent, TranslateDirective, DeleteButtonDirective], }) export class QuizExerciseLifecycleButtonsComponent { + private quizExerciseService = inject(QuizExerciseService); + private alertService = inject(AlertService); + protected readonly QuizMode = QuizMode; protected readonly QuizStatus = QuizStatus; protected readonly ActionType = ActionType; @@ -40,11 +47,6 @@ export class QuizExerciseLifecycleButtonsComponent { @Output() handleNewQuizExercise = new EventEmitter(); - constructor( - private quizExerciseService: QuizExerciseService, - private alertService: AlertService, - ) {} - /** * Set the quiz open for practice */ diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-manage-buttons.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-manage-buttons.component.ts index 3575e81897b1..b7184d99cbe9 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-manage-buttons.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-manage-buttons.component.ts @@ -1,8 +1,8 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; import { QuizExerciseService } from './quiz-exercise.service'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { ActionType } from 'app/shared/delete-dialog/delete-dialog.model'; import { ExerciseService } from 'app/exercises/shared/exercise/exercise.service'; import { AlertService } from 'app/core/util/alert.service'; @@ -10,12 +10,24 @@ import { EventManager } from 'app/core/util/event-manager.service'; import { faClipboardCheck, faEye, faFileExport, faListAlt, faSignal, faTable, faTrash, faUndo, faWrench } from '@fortawesome/free-solid-svg-icons'; import { Subject } from 'rxjs'; import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; @Component({ selector: 'jhi-quiz-exercise-manage-buttons', templateUrl: './quiz-exercise-manage-buttons.component.html', + imports: [RouterLink, FaIconComponent, TranslateDirective, ButtonComponent, DeleteButtonDirective], }) export class QuizExerciseManageButtonsComponent implements OnInit { + private quizExerciseService = inject(QuizExerciseService); + private eventManager = inject(EventManager); + private alertService = inject(AlertService); + private exerciseService = inject(ExerciseService); + private route = inject(ActivatedRoute); + private router = inject(Router); + protected readonly ActionType = ActionType; readonly faEye = faEye; readonly faSignal = faSignal; @@ -40,15 +52,6 @@ export class QuizExerciseManageButtonsComponent implements OnInit { baseUrl: string; isEvaluatingQuizExercise: boolean; - constructor( - private quizExerciseService: QuizExerciseService, - private eventManager: EventManager, - private alertService: AlertService, - private exerciseService: ExerciseService, - private route: ActivatedRoute, - private router: Router, - ) {} - @Input() isDetailPage: boolean; diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-paging.service.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-paging.service.ts index 305f36c48fbb..1dfaa760e998 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-paging.service.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-paging.service.ts @@ -1,12 +1,15 @@ import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; import { ExercisePagingService } from 'app/exercises/shared/manage/exercise-paging.service'; @Injectable({ providedIn: 'root' }) export class QuizExercisePagingService extends ExercisePagingService { private static readonly RESOURCE_URL = 'api/quiz-exercises'; - constructor(http: HttpClient) { + + constructor() { + const http = inject(HttpClient); + super(http, QuizExercisePagingService.RESOURCE_URL); } } diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-popup.service.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-popup.service.ts index dcbfdc19ae4f..a16d2d65df21 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-popup.service.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-popup.service.ts @@ -1,4 +1,4 @@ -import { Component, Injectable } from '@angular/core'; +import { Component, Injectable, inject } from '@angular/core'; import { Router } from '@angular/router'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { QuizExerciseService } from './quiz-exercise.service'; @@ -6,13 +6,13 @@ import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; @Injectable({ providedIn: 'root' }) export class QuizExercisePopupService { + private modalService = inject(NgbModal); + private router = inject(Router); + private quizExerciseService = inject(QuizExerciseService); + private ngbModalRef: NgbModalRef | null; - constructor( - private modalService: NgbModal, - private router: Router, - private quizExerciseService: QuizExerciseService, - ) { + constructor() { this.ngbModalRef = null; } diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-update.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-update.component.ts index 0c03bd54d888..1e9e3761cb47 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-update.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-update.component.ts @@ -1,4 +1,7 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnChanges, OnInit, SimpleChanges, ViewChild, ViewEncapsulation } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnChanges, OnInit, SimpleChanges, ViewChild, ViewEncapsulation, inject } from '@angular/core'; +import { DifficultyPickerComponent } from 'app/exercises/shared/difficulty-picker/difficulty-picker.component'; +import { ExerciseTitleChannelNameComponent } from 'app/exercises/shared/exercise-title-channel-name/exercise-title-channel-name.component'; +import { IncludedInOverallScorePickerComponent } from 'app/exercises/shared/included-in-overall-score-picker/included-in-overall-score-picker.component'; import { QuizExerciseService } from './quiz-exercise.service'; import { ActivatedRoute, Router } from '@angular/router'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; @@ -8,7 +11,7 @@ import { DragAndDropQuestionUtil } from 'app/exercises/quiz/shared/drag-and-drop import { ShortAnswerQuestionUtil } from 'app/exercises/quiz/shared/short-answer-question-util.service'; import { TranslateService } from '@ngx-translate/core'; import { Duration } from './quiz-exercise-interfaces'; -import { NgbDate, NgbModal, NgbModalOptions, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { NgbDate, NgbModal, NgbModalOptions, NgbModalRef, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import dayjs from 'dayjs/esm'; import { AlertService } from 'app/core/util/alert.service'; import { ComponentCanDeactivate } from 'app/shared/guard/can-deactivate.model'; @@ -33,6 +36,17 @@ import { QuizQuestionListEditComponent } from 'app/exercises/quiz/manage/quiz-qu import { DragAndDropQuestion } from 'app/entities/quiz/drag-and-drop-question.model'; import { GenericConfirmationDialogComponent } from 'app/overview/course-conversations/dialogs/generic-confirmation-dialog/generic-confirmation-dialog.component'; import { ShortAnswerQuestion } from 'app/entities/quiz/short-answer-question.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { FormsModule } from '@angular/forms'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { CategorySelectorComponent } from 'app/shared/category-selector/category-selector.component'; +import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { CompetencySelectionComponent } from 'app/shared/competency-selection/competency-selection.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { JsonPipe, NgClass } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-quiz-exercise-detail', @@ -41,8 +55,39 @@ import { ShortAnswerQuestion } from 'app/entities/quiz/short-answer-question.mod providers: [DragAndDropQuestionUtil, ShortAnswerQuestionUtil], styleUrls: ['./quiz-exercise-update.component.scss', '../shared/quiz.scss'], encapsulation: ViewEncapsulation.None, + imports: [ + TranslateDirective, + DocumentationButtonComponent, + FormsModule, + ExerciseTitleChannelNameComponent, + HelpIconComponent, + CategorySelectorComponent, + DifficultyPickerComponent, + FormDateTimePickerComponent, + ButtonComponent, + IncludedInOverallScorePickerComponent, + CompetencySelectionComponent, + QuizQuestionListEditComponent, + NgbTooltip, + FaIconComponent, + NgClass, + JsonPipe, + ArtemisTranslatePipe, + ], }) export class QuizExerciseUpdateComponent extends QuizExerciseValidationDirective implements OnInit, OnChanges, ComponentCanDeactivate { + private route = inject(ActivatedRoute); + private courseService = inject(CourseManagementService); + private quizExerciseService = inject(QuizExerciseService); + private router = inject(Router); + private translateService = inject(TranslateService); + private exerciseService = inject(ExerciseService); + private alertService = inject(AlertService); + private changeDetector = inject(ChangeDetectorRef); + private exerciseGroupService = inject(ExerciseGroupService); + private navigationUtilService = inject(ArtemisNavigationUtilService); + private modalService = inject(NgbModal); + @ViewChild('quizQuestionsEdit') quizQuestionListEditComponent: QuizQuestionListEditComponent; @@ -101,24 +146,6 @@ export class QuizExerciseUpdateComponent extends QuizExerciseValidationDirective centered: true, }; - constructor( - private route: ActivatedRoute, - private courseService: CourseManagementService, - private quizExerciseService: QuizExerciseService, - private router: Router, - private translateService: TranslateService, - private exerciseService: ExerciseService, - private alertService: AlertService, - public changeDetector: ChangeDetectorRef, - private exerciseGroupService: ExerciseGroupService, - private navigationUtilService: ArtemisNavigationUtilService, - dragAndDropQuestionUtil: DragAndDropQuestionUtil, - shortAnswerQuestionUtil: ShortAnswerQuestionUtil, - private modalService: NgbModal, - ) { - super(dragAndDropQuestionUtil, shortAnswerQuestionUtil); - } - /** * Initialize variables and load course and quiz from server. */ diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-validation.directive.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-validation.directive.ts index c32fa0d96453..a476655f060c 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-validation.directive.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise-validation.directive.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Directive } from '@angular/core'; +import { ChangeDetectorRef, Directive, inject } from '@angular/core'; import { QuizExercise, QuizMode } from 'app/entities/quiz/quiz-exercise.model'; import { QuizQuestion, QuizQuestionType } from 'app/entities/quiz/quiz-question.model'; import { MultipleChoiceQuestion } from 'app/entities/quiz/multiple-choice-question.model'; @@ -16,6 +16,9 @@ import { ShortAnswerQuestionUtil } from 'app/exercises/quiz/shared/short-answer- @Directive() export abstract class QuizExerciseValidationDirective { + protected dragAndDropQuestionUtil = inject(DragAndDropQuestionUtil); + protected shortAnswerQuestionUtil = inject(ShortAnswerQuestionUtil); + // Make constants available to html for comparison readonly DRAG_AND_DROP = QuizQuestionType.DRAG_AND_DROP; readonly MULTIPLE_CHOICE = QuizQuestionType.MULTIPLE_CHOICE; @@ -37,11 +40,6 @@ export abstract class QuizExerciseValidationDirective { protected invalidFlaggedQuestions: InvalidFlaggedQuestions = {}; pendingChangesCache: boolean; - protected constructor( - protected dragAndDropQuestionUtil: DragAndDropQuestionUtil, - protected shortAnswerQuestionUtil: ShortAnswerQuestionUtil, - ) {} - /** * 1. Check whether the inputs in the quiz are valid * 2. Check if warning are needed for the inputs diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise.component.ts index 22ac2e1a7685..3b219c2f8626 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise.component.ts @@ -10,10 +10,34 @@ import { ExerciseService } from 'app/exercises/shared/exercise/exercise.service' import { AlertService } from 'app/core/util/alert.service'; import { faSort, faTrash } from '@fortawesome/free-solid-svg-icons'; import { isQuizEditable } from 'app/exercises/quiz/shared/quiz-manage-util.service'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { FormsModule } from '@angular/forms'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { RouterLink } from '@angular/router'; +import { QuizExerciseLifecycleButtonsComponent } from './quiz-exercise-lifecycle-buttons.component'; +import { ExerciseCategoriesComponent } from 'app/shared/exercise-categories/exercise-categories.component'; +import { QuizExerciseManageButtonsComponent } from './quiz-exercise-manage-buttons.component'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; @Component({ selector: 'jhi-quiz-exercise', templateUrl: './quiz-exercise.component.html', + imports: [ + SortDirective, + FormsModule, + SortByDirective, + TranslateDirective, + FaIconComponent, + RouterLink, + QuizExerciseLifecycleButtonsComponent, + ExerciseCategoriesComponent, + QuizExerciseManageButtonsComponent, + DeleteButtonDirective, + ArtemisDatePipe, + ], }) export class QuizExerciseComponent extends ExerciseComponent { protected exerciseService = inject(ExerciseService); diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise.service.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise.service.ts index 91a252bd6eb3..6a3dfb64b5c9 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-exercise.service.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-exercise.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -17,13 +17,11 @@ export type EntityArrayResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class QuizExerciseService { + private http = inject(HttpClient); + private exerciseService = inject(ExerciseService); + private fileService = inject(FileService); private resourceUrl = 'api/quiz-exercises'; - constructor( - private http: HttpClient, - private exerciseService: ExerciseService, - ) {} - /** * Create the given quiz exercise * @param quizExercise the quiz exercise that should be created @@ -297,8 +295,7 @@ export class QuizExerciseService { * @param filePath the internal path of the file to be fetched */ async fetchFilePromise(fileName: string, zip: JSZip, filePath: string) { - const fileService = new FileService(this.http); - return fileService + return this.fileService .getFile(filePath) .then((fileResult) => { zip.file(fileName, fileResult); diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-management.module.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-management.module.ts index 829eae9fbb76..a2cbf264690a 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-management.module.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-management.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; -import { MultipleChoiceQuestionEditComponent } from './multiple-choice-question/multiple-choice-question-edit.component'; -import { DragAndDropQuestionEditComponent } from './drag-and-drop-question/drag-and-drop-question-edit.component'; -import { ShortAnswerQuestionEditComponent } from './short-answer-question/short-answer-question-edit.component'; +import { MultipleChoiceQuestionEditComponent } from 'app/exercises/quiz/manage/multiple-choice-question/multiple-choice-question-edit.component'; +import { DragAndDropQuestionEditComponent } from 'app/exercises/quiz/manage/drag-and-drop-question/drag-and-drop-question-edit.component'; +import { ShortAnswerQuestionEditComponent } from 'app/exercises/quiz/manage/short-answer-question/short-answer-question-edit.component'; import { ArtemisMarkdownEditorModule } from 'app/shared/markdown-editor/markdown-editor.module'; import { DragDropModule } from '@angular/cdk/drag-drop'; import { QuizScoringInfoModalComponent } from './quiz-scoring-info-modal/quiz-scoring-info-modal.component'; @@ -27,7 +27,7 @@ import { QuizConfirmImportInvalidQuestionsModalComponent } from 'app/exercises/q import { ArtemisIncludedInOverallScorePickerModule } from 'app/exercises/shared/included-in-overall-score-picker/included-in-overall-score-picker.module'; import { MatchPercentageInfoModalComponent } from 'app/exercises/quiz/manage/match-percentage-info-modal/match-percentage-info-modal.component'; import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; -import { FitTextModule } from 'app/exercises/quiz/shared/fit-text/fit-text.module'; + import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { ExerciseCategoriesModule } from 'app/shared/exercise-categories/exercise-categories.module'; import { QuizPoolMappingComponent } from 'app/exercises/quiz/manage/quiz-pool-mapping.component'; @@ -59,14 +59,11 @@ const ENTITY_STATES = [...quizManagementRoute]; ArtemisIncludedInOverallScorePickerModule, ArtemisQuizParticipationModule, ArtemisMarkdownModule, - FitTextModule, ArtemisSharedComponentModule, ExerciseCategoriesModule, ExerciseTitleChannelNameModule, DetailModule, ArtemisExerciseModule, - ], - declarations: [ QuizExerciseManageButtonsComponent, QuizExerciseComponent, QuizExerciseCreateButtonsComponent, diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-management.route.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-management.route.ts index 8a7967a5c9c1..f80fb864a44b 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-management.route.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-management.route.ts @@ -1,12 +1,9 @@ import { Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { QuizExerciseUpdateComponent } from './quiz-exercise-update.component'; -import { QuizExerciseExportComponent } from './quiz-exercise-export.component'; + import { PendingChangesGuard } from 'app/shared/guard/pending-changes.guard'; -import { QuizReEvaluateComponent } from 'app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate.component'; -import { QuizParticipationComponent } from 'app/exercises/quiz/participate/quiz-participation.component'; + import { Authority } from 'app/shared/constants/authority.constants'; -import { QuizExerciseDetailComponent } from 'app/exercises/quiz/manage/quiz-exercise-detail.component'; export const quizManagementRoute: Routes = [ { @@ -15,7 +12,7 @@ export const quizManagementRoute: Routes = [ }, { path: ':courseId/quiz-exercises/new', - component: QuizExerciseUpdateComponent, + loadComponent: () => import('./quiz-exercise-update.component').then((m) => m.QuizExerciseUpdateComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -25,7 +22,7 @@ export const quizManagementRoute: Routes = [ }, { path: ':courseId/quiz-exercises/export', - component: QuizExerciseExportComponent, + loadComponent: () => import('./quiz-exercise-export.component').then((m) => m.QuizExerciseExportComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -34,7 +31,7 @@ export const quizManagementRoute: Routes = [ }, { path: ':courseId/quiz-exercises/:exerciseId', - component: QuizExerciseDetailComponent, + loadComponent: () => import('app/exercises/quiz/manage/quiz-exercise-detail.component').then((m) => m.QuizExerciseDetailComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -43,7 +40,7 @@ export const quizManagementRoute: Routes = [ }, { path: ':courseId/quiz-exercises/:exerciseId/re-evaluate', - component: QuizReEvaluateComponent, + loadComponent: () => import('app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate.component').then((m) => m.QuizReEvaluateComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -52,7 +49,7 @@ export const quizManagementRoute: Routes = [ }, { path: ':courseId/quiz-exercises/:exerciseId/edit', - component: QuizExerciseUpdateComponent, + loadComponent: () => import('./quiz-exercise-update.component').then((m) => m.QuizExerciseUpdateComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -62,7 +59,7 @@ export const quizManagementRoute: Routes = [ }, { path: ':courseId/quiz-exercises/:exerciseId/import', - component: QuizExerciseUpdateComponent, + loadComponent: () => import('./quiz-exercise-update.component').then((m) => m.QuizExerciseUpdateComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.importLabel', @@ -72,7 +69,7 @@ export const quizManagementRoute: Routes = [ }, { path: ':courseId/quiz-exercises/:exerciseId/preview', - component: QuizParticipationComponent, + loadComponent: () => import('app/exercises/quiz/participate/quiz-participation.component').then((m) => m.QuizParticipationComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', @@ -82,7 +79,7 @@ export const quizManagementRoute: Routes = [ }, { path: ':courseId/quiz-exercises/:exerciseId/solution', - component: QuizParticipationComponent, + loadComponent: () => import('app/exercises/quiz/participate/quiz-participation.component').then((m) => m.QuizParticipationComponent), data: { authorities: [Authority.TA, Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.quizExercise.home.title', diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-pool-mapping-question-list.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-pool-mapping-question-list.component.ts index 11f72daf4686..23d73f2b23cd 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-pool-mapping-question-list.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-pool-mapping-question-list.component.ts @@ -1,13 +1,14 @@ import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core'; import { QuizQuestion } from 'app/entities/quiz/quiz-question.model'; import { QuizQuestionType } from 'app/entities/quiz/quiz-question.model'; -import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop'; +import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop'; @Component({ selector: 'jhi-quiz-pool-mapping-question-list', templateUrl: './quiz-pool-mapping-question-list.component.html', styleUrls: ['./quiz-pool-mapping-question-list.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [CdkDropList, CdkDrag], }) export class QuizPoolMappingQuestionListComponent { @Input() quizQuestions: Array; diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-pool-mapping.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-pool-mapping.component.ts index e4fd431ab46f..d3c59b6cff6a 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-pool-mapping.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-pool-mapping.component.ts @@ -1,16 +1,25 @@ -import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, inject } from '@angular/core'; import { faExclamationCircle, faPlus, faTimes } from '@fortawesome/free-solid-svg-icons'; import { QuizGroup } from 'app/entities/quiz/quiz-group.model'; import { Subject } from 'rxjs'; import { QuizQuestion } from 'app/entities/quiz/quiz-question.model'; import { AlertService } from 'app/core/util/alert.service'; +import { CdkDropListGroup } from '@angular/cdk/drag-drop'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { QuizPoolMappingQuestionListComponent } from './quiz-pool-mapping-question-list.component'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { NgStyle } from '@angular/common'; @Component({ selector: 'jhi-quiz-pool-mapping', templateUrl: './quiz-pool-mapping.component.html', styleUrls: ['./quiz-pool-mapping.component.scss'], + imports: [CdkDropListGroup, FaIconComponent, TranslateDirective, QuizPoolMappingQuestionListComponent, DeleteButtonDirective, NgStyle], }) export class QuizPoolMappingComponent implements OnInit, OnChanges, OnDestroy { + private alertService = inject(AlertService); + @Input() quizGroups: QuizGroup[] = []; @Input() quizQuestions: QuizQuestion[] = []; @Input() disabled = false; @@ -28,8 +37,6 @@ export class QuizPoolMappingComponent implements OnInit, OnChanges, OnDestroy { protected dialogErrorSource = new Subject(); dialogError$ = this.dialogErrorSource.asObservable(); - constructor(private alertService: AlertService) {} - ngOnInit(): void { this.handleUpdate(); } diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-pool.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-pool.component.ts index ea04a7e2fe7f..85ee99f058e4 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-pool.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-pool.component.ts @@ -1,5 +1,5 @@ import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewChild, ViewEncapsulation, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { QuizPool } from 'app/entities/quiz/quiz-pool.model'; import { QuizPoolService } from 'app/exercises/quiz/manage/quiz-pool.service'; @@ -17,6 +17,11 @@ import { computeQuizQuestionInvalidReason, isQuizQuestionValid } from 'app/exerc import { ExamManagementService } from 'app/exam/manage/exam-management.service'; import { Exam } from 'app/entities/exam/exam.model'; import dayjs from 'dayjs/esm'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { JsonPipe } from '@angular/common'; @Component({ selector: 'jhi-quiz-pool', @@ -25,8 +30,17 @@ import dayjs from 'dayjs/esm'; changeDetection: ChangeDetectionStrategy.OnPush, styleUrls: ['./quiz-pool.component.scss', '../shared/quiz.scss'], encapsulation: ViewEncapsulation.None, + imports: [TranslateDirective, QuizPoolMappingComponent, FormsModule, QuizQuestionListEditComponent, NgbTooltip, FaIconComponent, JsonPipe], }) export class QuizPoolComponent implements OnInit { + private route = inject(ActivatedRoute); + private quizPoolService = inject(QuizPoolService); + private examService = inject(ExamManagementService); + private changeDetectorRef = inject(ChangeDetectorRef); + private dragAndDropQuestionUtil = inject(DragAndDropQuestionUtil); + private shortAnswerQuestionUtil = inject(ShortAnswerQuestionUtil); + private alertService = inject(AlertService); + @ViewChild('quizPoolQuestionMapping') quizPoolMappingComponent: QuizPoolMappingComponent; @ViewChild('quizQuestionsEdit') @@ -46,16 +60,6 @@ export class QuizPoolComponent implements OnInit { examId: number; isExamStarted: boolean; - constructor( - private route: ActivatedRoute, - private quizPoolService: QuizPoolService, - private examService: ExamManagementService, - private changeDetectorRef: ChangeDetectorRef, - private dragAndDropQuestionUtil: DragAndDropQuestionUtil, - private shortAnswerQuestionUtil: ShortAnswerQuestionUtil, - private alertService: AlertService, - ) {} - ngOnInit(): void { this.courseId = Number(this.route.snapshot.paramMap.get('courseId')); this.examId = Number(this.route.snapshot.paramMap.get('examId')); diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-pool.service.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-pool.service.ts index c1b8e7cf4fae..f0c8944dafc1 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-pool.service.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-pool.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; @@ -10,7 +10,7 @@ export type EntityArrayResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class QuizPoolService { - constructor(private http: HttpClient) {} + private http = inject(HttpClient); /** * Update the given quiz pool that belongs to the given course id and exam id diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-question-list-edit-existing.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-question-list-edit-existing.component.ts index 7dc2df7ed5d3..3509836a4224 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-question-list-edit-existing.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-question-list-edit-existing.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, ViewEncapsulation } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, ViewEncapsulation, inject } from '@angular/core'; import { QuizQuestion, QuizQuestionType } from 'app/entities/quiz/quiz-question.model'; import { DragAndDropQuestion } from 'app/entities/quiz/drag-and-drop-question.model'; import { MultipleChoiceQuestion } from 'app/entities/quiz/multiple-choice-question.model'; @@ -17,6 +17,9 @@ import { onError } from 'app/shared/util/global.utils'; import { checkForInvalidFlaggedQuestions } from 'app/exercises/quiz/shared/quiz-manage-util.service'; import { FileService } from 'app/shared/http/file.service'; import JSZip from 'jszip'; +import { KeyValuePipe, NgClass } from '@angular/common'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; export enum State { COURSE = 'Course', @@ -30,8 +33,17 @@ export enum State { changeDetection: ChangeDetectionStrategy.OnPush, styleUrls: ['../shared/quiz.scss'], encapsulation: ViewEncapsulation.None, + imports: [NgClass, TranslateDirective, FormsModule, KeyValuePipe], }) export class QuizQuestionListEditExistingComponent implements OnChanges { + private modalService = inject(NgbModal); + private fileService = inject(FileService); + private courseManagementService = inject(CourseManagementService); + private examManagementService = inject(ExamManagementService); + private quizExerciseService = inject(QuizExerciseService); + private alertService = inject(AlertService); + private changeDetectorRef = inject(ChangeDetectorRef); + @Input() show: boolean; @Input() courseId: number; @Input() filePool: Map; @@ -59,16 +71,6 @@ export class QuizQuestionListEditExistingComponent implements OnChanges { importFile?: File; importFileName: string; - constructor( - private modalService: NgbModal, - private fileService: FileService, - private courseManagementService: CourseManagementService, - private examManagementService: ExamManagementService, - private quizExerciseService: QuizExerciseService, - private alertService: AlertService, - private changeDetectorRef: ChangeDetectorRef, - ) {} - ngOnChanges(): void { if (this.show) { this.courseManagementService.getAllCoursesWithQuizExercises().subscribe((res: HttpResponse) => { diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-question-list-edit.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-question-list-edit.component.ts index 3d3da811b347..bff74eb3afd8 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-question-list-edit.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-question-list-edit.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, QueryList, ViewChildren, ViewEncapsulation } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, QueryList, ViewChildren, ViewEncapsulation, inject } from '@angular/core'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { QuizQuestion, QuizQuestionType, ScoringType } from 'app/entities/quiz/quiz-question.model'; import { MultipleChoiceQuestion } from 'app/entities/quiz/multiple-choice-question.model'; @@ -11,6 +11,10 @@ import { MultipleChoiceQuestionEditComponent } from 'app/exercises/quiz/manage/m import { DragAndDropQuestionEditComponent } from 'app/exercises/quiz/manage/drag-and-drop-question/drag-and-drop-question-edit.component'; import { ShortAnswerQuestionEditComponent } from 'app/exercises/quiz/manage/short-answer-question/short-answer-question-edit.component'; import { ApollonDiagramImportDialogComponent } from 'app/exercises/quiz/manage/apollon-diagrams/apollon-diagram-import-dialog.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgClass } from '@angular/common'; +import { QuizQuestionListEditExistingComponent } from './quiz-question-list-edit-existing.component'; @Component({ selector: 'jhi-quiz-question-list-edit', @@ -18,8 +22,19 @@ import { ApollonDiagramImportDialogComponent } from 'app/exercises/quiz/manage/a changeDetection: ChangeDetectionStrategy.OnPush, styleUrls: ['./quiz-question-list-edit.component.scss', '../shared/quiz.scss'], encapsulation: ViewEncapsulation.None, + imports: [ + TranslateDirective, + MultipleChoiceQuestionEditComponent, + DragAndDropQuestionEditComponent, + ShortAnswerQuestionEditComponent, + FaIconComponent, + NgClass, + QuizQuestionListEditExistingComponent, + ], }) export class QuizQuestionListEditComponent { + private modalService = inject(NgbModal); + @Input() courseId: number; @Input() quizQuestions: QuizQuestion[] = []; @Input() disabled = false; @@ -47,8 +62,6 @@ export class QuizQuestionListEditComponent { fileMap = new Map(); - constructor(private modalService: NgbModal) {} - /** * Emit onQuestionUpdated if there is an update of the question. */ diff --git a/src/main/webapp/app/exercises/quiz/manage/quiz-scoring-info-modal/quiz-scoring-info-modal.component.ts b/src/main/webapp/app/exercises/quiz/manage/quiz-scoring-info-modal/quiz-scoring-info-modal.component.ts index d362837455f4..18d21089f3b9 100644 --- a/src/main/webapp/app/exercises/quiz/manage/quiz-scoring-info-modal/quiz-scoring-info-modal.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/quiz-scoring-info-modal/quiz-scoring-info-modal.component.ts @@ -1,15 +1,19 @@ -import { Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { faQuestionCircle } from '@fortawesome/free-regular-svg-icons'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-quiz-scoring-info-modal', templateUrl: './quiz-scoring-info-modal.component.html', + imports: [TranslateDirective, FaIconComponent], }) export class QuizScoringInfoModalComponent { + private modalService = inject(NgbModal); + // Icons farQuestionCircle = faQuestionCircle; - constructor(private modalService: NgbModal) {} /** * Open a large modal with the given content. diff --git a/src/main/webapp/app/exercises/quiz/manage/re-evaluate/drag-and-drop-question/re-evaluate-drag-and-drop-question.component.ts b/src/main/webapp/app/exercises/quiz/manage/re-evaluate/drag-and-drop-question/re-evaluate-drag-and-drop-question.component.ts index 1fd06c312206..0db02d8ebd73 100644 --- a/src/main/webapp/app/exercises/quiz/manage/re-evaluate/drag-and-drop-question/re-evaluate-drag-and-drop-question.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/re-evaluate/drag-and-drop-question/re-evaluate-drag-and-drop-question.component.ts @@ -19,6 +19,7 @@ import { DragAndDropQuestionEditComponent } from 'app/exercises/quiz/manage/drag /> `, providers: [], + imports: [DragAndDropQuestionEditComponent], }) export class ReEvaluateDragAndDropQuestionComponent { /** @@ -49,8 +50,6 @@ export class ReEvaluateDragAndDropQuestionComponent { fileMap = new Map(); - constructor() {} - /** * Add the given file to the fileMap for later upload. * @param event the event containing the file and its name. The name provided may be different from the actual file name but has to correspond to the name set in the entity object. diff --git a/src/main/webapp/app/exercises/quiz/manage/re-evaluate/multiple-choice-question/re-evaluate-multiple-choice-question.component.ts b/src/main/webapp/app/exercises/quiz/manage/re-evaluate/multiple-choice-question/re-evaluate-multiple-choice-question.component.ts index a9a0afae1077..fd1ddcf39660 100644 --- a/src/main/webapp/app/exercises/quiz/manage/re-evaluate/multiple-choice-question/re-evaluate-multiple-choice-question.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/re-evaluate/multiple-choice-question/re-evaluate-multiple-choice-question.component.ts @@ -5,14 +5,21 @@ import { escapeStringForUseInRegex } from 'app/shared/util/global.utils'; import { cloneDeep } from 'lodash-es'; import { generateExerciseHintExplanation, parseExerciseHintExplanation } from 'app/shared/util/markdown.util'; import { faAngleDown, faAngleRight, faArrowsAltV, faChevronDown, faChevronUp, faTrash, faUndo } from '@fortawesome/free-solid-svg-icons'; -import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; +import { CdkDrag, CdkDragDrop, CdkDragHandle, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop'; import { CorrectMultipleChoiceAnswerAction } from 'app/shared/monaco-editor/model/actions/quiz/correct-multiple-choice-answer.action'; import { WrongMultipleChoiceAnswerAction } from 'app/shared/monaco-editor/model/actions/quiz/wrong-multiple-choice-answer.action'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { FormsModule } from '@angular/forms'; +import { NgbCollapse, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { MarkdownEditorMonacoComponent } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-re-evaluate-multiple-choice-question', templateUrl: './re-evaluate-multiple-choice-question.component.html', styleUrls: ['./re-evaluate-multiple-choice-question.component.scss', '../../../shared/quiz.scss'], + imports: [FaIconComponent, FormsModule, NgbTooltip, NgbCollapse, TranslateDirective, MarkdownEditorMonacoComponent, CdkDropList, CdkDrag, CdkDragHandle, ArtemisTranslatePipe], }) export class ReEvaluateMultipleChoiceQuestionComponent implements OnInit { @Input() question: MultipleChoiceQuestion; diff --git a/src/main/webapp/app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate-warning.component.ts b/src/main/webapp/app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate-warning.component.ts index 6947cdbb1635..63ef0a60b647 100644 --- a/src/main/webapp/app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate-warning.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate-warning.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { QuizReEvaluateService } from './quiz-re-evaluate.service'; import { ShortAnswerQuestion } from 'app/entities/quiz/short-answer-question.model'; @@ -10,13 +10,22 @@ import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; import { EventManager } from 'app/core/util/event-manager.service'; import { faBan, faCheck, faCheckCircle, faSpinner, faTimes } from '@fortawesome/free-solid-svg-icons'; import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-quiz-re-evaluate-warning', templateUrl: './quiz-re-evaluate-warning.component.html', styleUrls: ['../../shared/quiz.scss'], + imports: [TranslateDirective, FaIconComponent], }) export class QuizReEvaluateWarningComponent implements OnInit { + activeModal = inject(NgbActiveModal); + private eventManager = inject(EventManager); + private quizExerciseService = inject(QuizExerciseService); + private quizReEvaluateService = inject(QuizReEvaluateService); + private navigationUtilService = inject(ArtemisNavigationUtilService); + isSaving: boolean; successful = false; @@ -43,14 +52,6 @@ export class QuizReEvaluateWarningComponent implements OnInit { faCheck = faCheck; faCheckCircle = faCheckCircle; - constructor( - public activeModal: NgbActiveModal, - private eventManager: EventManager, - private quizExerciseService: QuizExerciseService, - private quizReEvaluateService: QuizReEvaluateService, - private navigationUtilService: ArtemisNavigationUtilService, - ) {} - /** * Reset saving status, load the quiz by id and back it up. */ diff --git a/src/main/webapp/app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate.component.ts b/src/main/webapp/app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate.component.ts index 22525d9e37a1..518e50f49ca0 100644 --- a/src/main/webapp/app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate.component.ts @@ -1,7 +1,8 @@ -import { ChangeDetectorRef, Component, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewChildren, ViewEncapsulation } from '@angular/core'; +import { ChangeDetectorRef, Component, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewChildren, ViewEncapsulation, inject } from '@angular/core'; +import { IncludedInOverallScorePickerComponent } from 'app/exercises/shared/included-in-overall-score-picker/included-in-overall-score-picker.component'; import { Subscription } from 'rxjs'; import { ActivatedRoute } from '@angular/router'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { QuizReEvaluateWarningComponent } from './quiz-re-evaluate-warning.component'; import { DragAndDropQuestionUtil } from 'app/exercises/quiz/shared/drag-and-drop-question-util.service'; import { HttpResponse } from '@angular/common/http'; @@ -18,6 +19,14 @@ import { QuizExerciseValidationDirective } from 'app/exercises/quiz/manage/quiz- import { ShortAnswerQuestionUtil } from 'app/exercises/quiz/shared/short-answer-question-util.service'; import { faExclamationCircle, faExclamationTriangle, faUndo } from '@fortawesome/free-solid-svg-icons'; import { ReEvaluateDragAndDropQuestionComponent } from 'app/exercises/quiz/manage/re-evaluate/drag-and-drop-question/re-evaluate-drag-and-drop-question.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { FormsModule } from '@angular/forms'; +import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component'; +import { ReEvaluateMultipleChoiceQuestionComponent } from './multiple-choice-question/re-evaluate-multiple-choice-question.component'; +import { ReEvaluateShortAnswerQuestionComponent } from './short-answer-question/re-evaluate-short-answer-question.component'; +import { JsonPipe } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-quiz-re-evaluate', @@ -25,8 +34,28 @@ import { ReEvaluateDragAndDropQuestionComponent } from 'app/exercises/quiz/manag styleUrls: ['./quiz-re-evaluate.component.scss', '../../shared/quiz.scss'], encapsulation: ViewEncapsulation.None, providers: [DragAndDropQuestionUtil, ShortAnswerQuestionUtil], + imports: [ + TranslateDirective, + FaIconComponent, + FormsModule, + NgbTooltip, + FormDateTimePickerComponent, + IncludedInOverallScorePickerComponent, + ReEvaluateMultipleChoiceQuestionComponent, + ReEvaluateDragAndDropQuestionComponent, + ReEvaluateShortAnswerQuestionComponent, + JsonPipe, + ArtemisTranslatePipe, + ], }) export class QuizReEvaluateComponent extends QuizExerciseValidationDirective implements OnInit, OnChanges, OnDestroy { + private quizExerciseService = inject(QuizExerciseService); + private route = inject(ActivatedRoute); + private modalServiceC = inject(NgbModal); + private quizExercisePopupService = inject(QuizExercisePopupService); + private changeDetector = inject(ChangeDetectorRef); + private navigationUtilService = inject(ArtemisNavigationUtilService); + private subscription: Subscription; @ViewChildren(ReEvaluateDragAndDropQuestionComponent) @@ -43,19 +72,6 @@ export class QuizReEvaluateComponent extends QuizExerciseValidationDirective imp faExclamationCircle = faExclamationCircle; faExclamationTriangle = faExclamationTriangle; - constructor( - private quizExerciseService: QuizExerciseService, - private route: ActivatedRoute, - private modalServiceC: NgbModal, - private quizExercisePopupService: QuizExercisePopupService, - public changeDetector: ChangeDetectorRef, - private navigationUtilService: ArtemisNavigationUtilService, - dragAndDropQuestionUtil: DragAndDropQuestionUtil, - shortAnswerQuestionUtil: ShortAnswerQuestionUtil, - ) { - super(dragAndDropQuestionUtil, shortAnswerQuestionUtil); - } - ngOnInit(): void { this.subscription = this.route.params.subscribe((params) => { this.quizExerciseService.find(params['exerciseId']).subscribe((response: HttpResponse) => { diff --git a/src/main/webapp/app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate.service.ts b/src/main/webapp/app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate.service.ts index 8a863a6906b7..4c43bc6b6fcf 100644 --- a/src/main/webapp/app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate.service.ts +++ b/src/main/webapp/app/exercises/quiz/manage/re-evaluate/quiz-re-evaluate.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; import { ExerciseService } from 'app/exercises/shared/exercise/exercise.service'; @@ -6,9 +6,9 @@ import { objectToJsonBlob } from 'app/utils/blob-util'; @Injectable({ providedIn: 'root' }) export class QuizReEvaluateService { - private resourceUrl = 'api/quiz-exercises/'; + private http = inject(HttpClient); - constructor(private http: HttpClient) {} + private resourceUrl = 'api/quiz-exercises/'; reevaluate(quizExercise: QuizExercise, files: Map) { const copy = this.convert(quizExercise); diff --git a/src/main/webapp/app/exercises/quiz/manage/re-evaluate/short-answer-question/re-evaluate-short-answer-question.component.ts b/src/main/webapp/app/exercises/quiz/manage/re-evaluate/short-answer-question/re-evaluate-short-answer-question.component.ts index 136135c58221..289b20cace34 100644 --- a/src/main/webapp/app/exercises/quiz/manage/re-evaluate/short-answer-question/re-evaluate-short-answer-question.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/re-evaluate/short-answer-question/re-evaluate-short-answer-question.component.ts @@ -1,6 +1,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { QuizQuestion } from 'app/entities/quiz/quiz-question.model'; import { ShortAnswerQuestion } from 'app/entities/quiz/short-answer-question.model'; +import { ShortAnswerQuestionEditComponent } from '../../short-answer-question/short-answer-question-edit.component'; @Component({ selector: 'jhi-re-evaluate-short-answer-question', @@ -16,6 +17,7 @@ import { ShortAnswerQuestion } from 'app/entities/quiz/short-answer-question.mod /> `, providers: [], + imports: [ShortAnswerQuestionEditComponent], }) export class ReEvaluateShortAnswerQuestionComponent { shortAnswerQuestion: ShortAnswerQuestion; @@ -34,6 +36,4 @@ export class ReEvaluateShortAnswerQuestionComponent { questionMoveUp = new EventEmitter(); @Output() questionMoveDown = new EventEmitter(); - - constructor() {} } diff --git a/src/main/webapp/app/exercises/quiz/manage/short-answer-question/short-answer-question-edit.component.ts b/src/main/webapp/app/exercises/quiz/manage/short-answer-question/short-answer-question-edit.component.ts index 896a6c743bbe..b71f3010f050 100644 --- a/src/main/webapp/app/exercises/quiz/manage/short-answer-question/short-answer-question-edit.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/short-answer-question/short-answer-question-edit.component.ts @@ -11,9 +11,10 @@ import { SimpleChanges, ViewChild, ViewEncapsulation, + inject, } from '@angular/core'; import { ShortAnswerQuestionUtil } from 'app/exercises/quiz/shared/short-answer-question-util.service'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbCollapse, NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { ShortAnswerQuestion } from 'app/entities/quiz/short-answer-question.model'; import { ShortAnswerMapping } from 'app/entities/quiz/short-answer-mapping.model'; import { QuizQuestionEdit } from 'app/exercises/quiz/manage/quiz-question-edit.interface'; @@ -38,20 +39,45 @@ import { InsertShortAnswerSpotAction } from 'app/shared/monaco-editor/model/acti import { TextEditorAction } from 'app/shared/monaco-editor/model/actions/text-editor-action.model'; import { InsertShortAnswerOptionAction } from 'app/shared/monaco-editor/model/actions/quiz/insert-short-answer-option.action'; import { SHORT_ANSWER_QUIZ_QUESTION_EDITOR_OPTIONS } from 'app/shared/monaco-editor/monaco-editor-option.helper'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { QuizScoringInfoModalComponent } from '../quiz-scoring-info-modal/quiz-scoring-info-modal.component'; +import { MatchPercentageInfoModalComponent } from '../match-percentage-info-modal/match-percentage-info-modal.component'; +import { CdkDrag, CdkDragPlaceholder, CdkDragPreview, CdkDropList, CdkDropListGroup } from '@angular/cdk/drag-drop'; +import { NgClass } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-short-answer-question-edit', templateUrl: './short-answer-question-edit.component.html', styleUrls: ['./short-answer-question-edit.component.scss', '../quiz-exercise.scss', '../../shared/quiz.scss'], encapsulation: ViewEncapsulation.None, + imports: [ + FaIconComponent, + FormsModule, + TranslateDirective, + NgbTooltip, + NgbCollapse, + QuizScoringInfoModalComponent, + MatchPercentageInfoModalComponent, + MarkdownEditorMonacoComponent, + CdkDropListGroup, + CdkDropList, + NgClass, + CdkDrag, + CdkDragPlaceholder, + CdkDragPreview, + ArtemisTranslatePipe, + ], }) export class ShortAnswerQuestionEditComponent implements OnInit, OnChanges, AfterViewInit, QuizQuestionEdit { - @ViewChild('questionEditor', { static: false }) - private questionEditor: MarkdownEditorMonacoComponent; - @ViewChild('clickLayer', { static: false }) - private clickLayer: ElementRef; - @ViewChild('question', { static: false }) - questionElement: ElementRef; + shortAnswerQuestionUtil = inject(ShortAnswerQuestionUtil); + private modalService = inject(NgbModal); + private changeDetector = inject(ChangeDetectorRef); + + @ViewChild('questionEditor', { static: false }) private questionEditor: MarkdownEditorMonacoComponent; + @ViewChild('question', { static: false }) questionElement: ElementRef; markdownActions: TextEditorAction[]; insertShortAnswerOptionAction = new InsertShortAnswerOptionAction(); @@ -112,12 +138,6 @@ export class ShortAnswerQuestionEditComponent implements OnInit, OnChanges, Afte protected readonly MAX_POINTS = MAX_QUIZ_QUESTION_POINTS; protected readonly MarkdownEditorHeight = MarkdownEditorHeight; - constructor( - public shortAnswerQuestionUtil: ShortAnswerQuestionUtil, - private modalService: NgbModal, - private changeDetector: ChangeDetectorRef, - ) {} - ngOnInit(): void { this.markdownActions = [ new BoldAction(), @@ -137,7 +157,7 @@ export class ShortAnswerQuestionEditComponent implements OnInit, OnChanges, Afte /** We create now the structure on how to display the text of the question * 1. The question text is split at every new line. The first element of the array would be then the first line of the question text. - * 2. Now each line of the question text will be divided into each word (we use whitespace and the borders of spots as separator, see {@link #regex}). + * 2. Now each line of the question text will be divided into each word (we use whitespace and the borders of spots as separator, see regex). */ this.textParts = this.parseQuestionTextIntoTextBlocks(this.shortAnswerQuestion.text!); diff --git a/src/main/webapp/app/exercises/quiz/manage/statistics/drag-and-drop-question-statistic/drag-and-drop-question-statistic.component.ts b/src/main/webapp/app/exercises/quiz/manage/statistics/drag-and-drop-question-statistic/drag-and-drop-question-statistic.component.ts index 2e0208207eeb..6965c21f0f58 100644 --- a/src/main/webapp/app/exercises/quiz/manage/statistics/drag-and-drop-question-statistic/drag-and-drop-question-statistic.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/statistics/drag-and-drop-question-statistic/drag-and-drop-question-statistic.component.ts @@ -1,18 +1,20 @@ -import { ChangeDetectorRef, Component, ViewEncapsulation } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; +import { Component, ViewEncapsulation, inject } from '@angular/core'; +import { DragItemComponent } from 'app/exercises/quiz/shared/questions/drag-and-drop-question/drag-item.component'; import { QuizStatisticUtil } from 'app/exercises/quiz/shared/quiz-statistic-util.service'; import { DragAndDropQuestionUtil } from 'app/exercises/quiz/shared/drag-and-drop-question-util.service'; import { ArtemisMarkdownService } from 'app/shared/markdown.service'; -import { AccountService } from 'app/core/auth/account.service'; -import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; -import { QuizExerciseService } from 'app/exercises/quiz/manage/quiz-exercise.service'; import { DragAndDropQuestion } from 'app/entities/quiz/drag-and-drop-question.model'; import { DragAndDropQuestionStatistic } from 'app/entities/quiz/drag-and-drop-question-statistic.model'; import { DropLocation } from 'app/entities/quiz/drop-location.model'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; import { QuestionStatisticComponent, blueColor, greenColor } from 'app/exercises/quiz/manage/statistics/question-statistic.component'; import { faCheckCircle, faSync, faTimesCircle } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { BarChartModule } from '@swimlane/ngx-charts'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { SecuredImageComponent } from 'app/shared/image/secured-image.component'; +import { NgStyle } from '@angular/common'; +import { QuizStatisticsFooterComponent } from '../quiz-statistics-footer/quiz-statistics-footer.component'; @Component({ selector: 'jhi-drag-and-drop-question-statistic', @@ -24,8 +26,12 @@ import { faCheckCircle, faSync, faTimesCircle } from '@fortawesome/free-solid-sv './drag-and-drop-question-statistic.component.scss', ], encapsulation: ViewEncapsulation.None, + imports: [TranslateDirective, BarChartModule, FaIconComponent, SecuredImageComponent, NgStyle, DragItemComponent, QuizStatisticsFooterComponent], }) export class DragAndDropQuestionStatisticComponent extends QuestionStatisticComponent { + private dragAndDropQuestionUtil = inject(DragAndDropQuestionUtil); + private artemisMarkdown = inject(ArtemisMarkdownService); + declare question: DragAndDropQuestion; // Icons @@ -33,27 +39,6 @@ export class DragAndDropQuestionStatisticComponent extends QuestionStatisticComp faCheckCircle = faCheckCircle; faTimesCircle = faTimesCircle; - constructor( - route: ActivatedRoute, - router: Router, - accountService: AccountService, - translateService: TranslateService, - quizExerciseService: QuizExerciseService, - jhiWebsocketService: JhiWebsocketService, - quizStatisticUtil: QuizStatisticUtil, - private dragAndDropQuestionUtil: DragAndDropQuestionUtil, - private artemisMarkdown: ArtemisMarkdownService, - protected changeDetector: ChangeDetectorRef, - ) { - super(route, router, accountService, translateService, quizExerciseService, jhiWebsocketService, changeDetector); - } - - /** - * load the Quiz, which is necessary to build the Web-Template - * - * @param {QuizExercise} quiz: the quizExercise, which the selected question is part of. - * @param {boolean} refresh: true if method is called from Websocket - */ loadQuiz(quiz: QuizExercise, refresh: boolean) { const updatedQuestion = super.loadQuizCommon(quiz); if (!updatedQuestion) { @@ -75,7 +60,7 @@ export class DragAndDropQuestionStatisticComponent extends QuestionStatisticComp this.resetLabelsColors(); // set label and background color based on the dropLocations - this.question.dropLocations!.forEach((dropLocation, i) => { + this.question.dropLocations!.forEach((_dropLocation, i) => { this.labels.push(this.getLetter(i) + '.'); this.solutionLabels.push(this.getLetter(i) + '.'); this.backgroundColors.push(blueColor); @@ -127,8 +112,8 @@ export class DragAndDropQuestionStatisticComponent extends QuestionStatisticComp /** * Get the drag item that was mapped to the given drop location in the sample solution * - * @param dropLocation {object} the drop location that the drag item should be mapped to - * @return {DragItem | undefined} the mapped drag item, or undefined if no drag item has been mapped to this location + * @param dropLocation the drop location that the drag item should be mapped to + * @return the mapped drag item, or undefined if no drag item has been mapped to this location */ correctDragItemForDropLocation(dropLocation: DropLocation) { const currMapping = this.dragAndDropQuestionUtil.solve(this.question, undefined).filter((mapping) => mapping.dropLocation!.id === dropLocation.id)[0]; diff --git a/src/main/webapp/app/exercises/quiz/manage/statistics/multiple-choice-question-statistic/multiple-choice-question-statistic.component.ts b/src/main/webapp/app/exercises/quiz/manage/statistics/multiple-choice-question-statistic/multiple-choice-question-statistic.component.ts index b8071ce5823e..d294491f4881 100644 --- a/src/main/webapp/app/exercises/quiz/manage/statistics/multiple-choice-question-statistic/multiple-choice-question-statistic.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/statistics/multiple-choice-question-statistic/multiple-choice-question-statistic.component.ts @@ -1,25 +1,26 @@ -import { ChangeDetectorRef, Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { SafeHtml } from '@angular/platform-browser'; -import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; import { QuizStatisticUtil } from 'app/exercises/quiz/shared/quiz-statistic-util.service'; import { ArtemisMarkdownService } from 'app/shared/markdown.service'; -import { AccountService } from 'app/core/auth/account.service'; -import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; -import { QuizExerciseService } from 'app/exercises/quiz/manage/quiz-exercise.service'; import { MultipleChoiceQuestionStatistic } from 'app/entities/quiz/multiple-choice-question-statistic.model'; import { MultipleChoiceQuestion } from 'app/entities/quiz/multiple-choice-question.model'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; import { QuestionStatisticComponent, blueColor, greenColor, redColor } from 'app/exercises/quiz/manage/statistics/question-statistic.component'; import { faCheckCircle, faSync, faTimesCircle } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { BarChartModule } from '@swimlane/ngx-charts'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { QuizStatisticsFooterComponent } from '../quiz-statistics-footer/quiz-statistics-footer.component'; @Component({ selector: 'jhi-multiple-choice-question-statistic', templateUrl: './multiple-choice-question-statistic.component.html', styleUrls: ['../quiz-point-statistic/quiz-point-statistic.component.scss', '../../../../../shared/chart/vertical-bar-chart.scss'], providers: [QuizStatisticUtil], + imports: [TranslateDirective, BarChartModule, FaIconComponent, QuizStatisticsFooterComponent], }) export class MultipleChoiceQuestionStatisticComponent extends QuestionStatisticComponent { + private artemisMarkdown = inject(ArtemisMarkdownService); declare question: MultipleChoiceQuestion; answerTextRendered: SafeHtml[]; @@ -29,26 +30,6 @@ export class MultipleChoiceQuestionStatisticComponent extends QuestionStatisticC faCheckCircle = faCheckCircle; faTimesCircle = faTimesCircle; - constructor( - route: ActivatedRoute, - router: Router, - accountService: AccountService, - translateService: TranslateService, - quizExerciseService: QuizExerciseService, - jhiWebsocketService: JhiWebsocketService, - private quizStatisticUtil: QuizStatisticUtil, - private artemisMarkdown: ArtemisMarkdownService, - protected changeDetector: ChangeDetectorRef, - ) { - super(route, router, accountService, translateService, quizExerciseService, jhiWebsocketService, changeDetector); - } - - /** - * This functions loads the Quiz, which is necessary to build the Web-Template - * - * @param {QuizExercise} quiz: the quizExercise, which the selected question is part of. - * @param {boolean} refresh: true if method is called from Websocket - */ loadQuiz(quiz: QuizExercise, refresh: boolean) { const updatedQuestion = super.loadQuizCommon(quiz); if (!updatedQuestion) { @@ -73,7 +54,7 @@ export class MultipleChoiceQuestionStatisticComponent extends QuestionStatisticC const answerOptions = this.question.answerOptions!; // set label and background-Color based on the AnswerOptions - answerOptions.forEach((answerOption, i) => { + answerOptions.forEach((_answerOption, i) => { this.labels.push(this.getLetter(i) + '.'); this.backgroundColors.push(blueColor); }); diff --git a/src/main/webapp/app/exercises/quiz/manage/statistics/question-statistic.component.ts b/src/main/webapp/app/exercises/quiz/manage/statistics/question-statistic.component.ts index f483ce7c6059..7b79e4dfb324 100644 --- a/src/main/webapp/app/exercises/quiz/manage/statistics/question-statistic.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/statistics/question-statistic.component.ts @@ -8,10 +8,9 @@ import { Authority } from 'app/shared/constants/authority.constants'; import { Subscription } from 'rxjs'; import { SafeHtml } from '@angular/platform-browser'; import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { CanBecomeInvalid } from 'app/entities/quiz/drop-location.model'; -import { QuizStatistics } from 'app/exercises/quiz/manage/statistics/quiz-statistics'; +import { AbstractQuizStatisticComponent } from 'app/exercises/quiz/manage/statistics/quiz-statistics'; export const redColor = '#d9534f'; export const greenColor = '#5cb85c'; @@ -19,8 +18,17 @@ export const blueColor = '#428bca'; export const lightBlueColor = '#5bc0de'; export const greyColor = '#838383'; -@Component({ template: '' }) -export abstract class QuestionStatisticComponent extends QuizStatistics implements OnInit, OnDestroy { +@Component({ + template: '', +}) +export abstract class QuestionStatisticComponent extends AbstractQuizStatisticComponent implements OnInit, OnDestroy { + protected route = inject(ActivatedRoute); + protected router = inject(Router); + protected accountService = inject(AccountService); + protected quizExerciseService = inject(QuizExerciseService); + protected jhiWebsocketService = inject(JhiWebsocketService); + protected changeDetector = inject(ChangeDetectorRef); + question: QuizQuestion; questionStatistic: QuizQuestionStatistic; @@ -45,22 +53,10 @@ export abstract class QuestionStatisticComponent extends QuizStatistics implemen backgroundColors: string[] = []; backgroundSolutionColors: string[] = []; - constructor( - protected route: ActivatedRoute, - protected router: Router, - protected accountService: AccountService, - protected translateService: TranslateService, - protected quizExerciseService: QuizExerciseService, - protected jhiWebsocketService: JhiWebsocketService, - protected changeDetector: ChangeDetectorRef, - ) { - super(translateService); - translateService.onLangChange.subscribe(() => { + ngOnInit() { + this.translateService.onLangChange.subscribe(() => { this.setAxisLabels('showStatistic.questionStatistic.xAxes', 'showStatistic.questionStatistic.yAxes'); }); - } - - ngOnInit() { this.sub = this.route.params.subscribe((params) => { this.questionIdParam = +params['questionId']; // use different REST-call if the User is a Student @@ -132,6 +128,12 @@ export abstract class QuestionStatisticComponent extends QuizStatistics implemen this.loadDataInDiagram(); } + /** + * This functions loads the Quiz, which is necessary to build the Web-Template + * + * @param quiz the quizExercise, which the selected question is part of. + * @param refresh true if method is called from Websocket + */ abstract loadQuiz(quiz: QuizExercise, refresh: boolean): void; loadQuizCommon(quiz: QuizExercise) { diff --git a/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-point-statistic/quiz-point-statistic.component.ts b/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-point-statistic/quiz-point-statistic.component.ts index bf9877902dfe..bb31e1baee65 100644 --- a/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-point-statistic/quiz-point-statistic.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-point-statistic/quiz-point-statistic.component.ts @@ -1,7 +1,6 @@ -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { Subscription } from 'rxjs'; -import { QuizStatisticUtil } from 'app/exercises/quiz/shared/quiz-statistic-util.service'; +import { AbstractQuizStatisticComponent } from 'app/exercises/quiz/manage/statistics/quiz-statistics'; import { AccountService } from 'app/core/auth/account.service'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; import { PointCounter } from 'app/entities/quiz/point-counter.model'; @@ -12,23 +11,34 @@ import { Authority } from 'app/shared/constants/authority.constants'; import { blueColor } from 'app/exercises/quiz/manage/statistics/question-statistic.component'; import { UI_RELOAD_TIME } from 'app/shared/constants/exercise-exam-constants'; import { round } from 'app/shared/util/utils'; -import { QuizStatistics } from 'app/exercises/quiz/manage/statistics/quiz-statistics'; -import { TranslateService } from '@ngx-translate/core'; import { faSync } from '@fortawesome/free-solid-svg-icons'; import { calculateMaxScore } from 'app/exercises/quiz/manage/statistics/quiz-statistic/quiz-statistics.utils'; import { ArtemisServerDateService } from 'app/shared/server-date.service'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { BarChartModule } from '@swimlane/ngx-charts'; +import { QuizStatisticsFooterComponent } from '../quiz-statistics-footer/quiz-statistics-footer.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-quiz-point-statistic', templateUrl: './quiz-point-statistic.component.html', styleUrls: ['./quiz-point-statistic.component.scss', '../../../../../shared/chart/vertical-bar-chart.scss'], + imports: [FaIconComponent, TranslateDirective, BarChartModule, QuizStatisticsFooterComponent, ArtemisTranslatePipe], }) -export class QuizPointStatisticComponent extends QuizStatistics implements OnInit, OnDestroy { +export class QuizPointStatisticComponent extends AbstractQuizStatisticComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private router = inject(Router); + private accountService = inject(AccountService); + private quizExerciseService = inject(QuizExerciseService); + private jhiWebsocketService = inject(JhiWebsocketService); + private changeDetector = inject(ChangeDetectorRef); + private serverDateService = inject(ArtemisServerDateService); + readonly round = round; quizExercise: QuizExercise; quizPointStatistic: QuizPointStatistic; - private sub: Subscription; labels: string[] = []; @@ -48,7 +58,6 @@ export class QuizPointStatisticComponent extends QuizStatistics implements OnIni roundEdges = true; showDataLabel = true; height = 500; - tooltipDisabled = true; animations = false; // timer @@ -60,25 +69,11 @@ export class QuizPointStatisticComponent extends QuizStatistics implements OnIni // Icons faSync = faSync; - constructor( - private route: ActivatedRoute, - private router: Router, - private accountService: AccountService, - protected translateService: TranslateService, - private quizExerciseService: QuizExerciseService, - private quizStatisticUtil: QuizStatisticUtil, - private jhiWebsocketService: JhiWebsocketService, - protected changeDetector: ChangeDetectorRef, - private serverDateService: ArtemisServerDateService, - ) { - super(translateService); + ngOnInit() { this.translateService.onLangChange.subscribe(() => { this.setAxisLabels('showStatistic.quizPointStatistic.xAxes', 'showStatistic.quizPointStatistic.yAxes'); }); - } - - ngOnInit() { - this.sub = this.route.params.subscribe((params) => { + this.route.params.subscribe((params) => { // use different REST-call if the User is a Student if (this.accountService.hasAnyAuthorityDirect([Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA])) { this.quizExerciseService.find(params['exerciseId']).subscribe((res) => { @@ -142,8 +137,8 @@ export class QuizPointStatisticComponent extends QuizStatistics implements OnIni /** * Express the given timespan as humanized text * - * @param remainingTimeSeconds {number} the amount of seconds to display - * @return {string} humanized text for the given amount of seconds + * @param remainingTimeSeconds the amount of seconds to display + * @return humanized text for the given amount of seconds */ relativeTimeText(remainingTimeSeconds: number) { if (remainingTimeSeconds > 210) { @@ -163,8 +158,7 @@ export class QuizPointStatisticComponent extends QuizStatistics implements OnIni /** * load the new quizPointStatistic from the server if the Websocket has been notified * - * @param {QuizPointStatistic} statistic: the new quizPointStatistic - * from the server with the new Data. + * @param statistic the new quizPointStatistic from the server with the new Data. */ loadNewData(statistic: QuizPointStatistic) { // if the Student finds a way to the Website @@ -179,8 +173,7 @@ export class QuizPointStatisticComponent extends QuizStatistics implements OnIni /** * This functions loads the Quiz, which is necessary to build the Web-Template * - * @param {QuizExercise} quizExercise: the quizExercise, - * which this quiz-point-statistic presents. + * @param quizExercise the quizExercise, which this quiz-point-statistic presents. */ loadQuizSuccess(quizExercise: QuizExercise) { // if the Student finds a way to the Website diff --git a/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistic.module.ts b/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistic.module.ts index e11918e73541..41dac88556de 100644 --- a/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistic.module.ts +++ b/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistic.module.ts @@ -15,8 +15,12 @@ import { BarChartModule } from '@swimlane/ngx-charts'; const ENTITY_STATES = [...quizStatisticRoute]; @NgModule({ - imports: [ArtemisSharedModule, RouterModule.forChild(ENTITY_STATES), ArtemisQuizQuestionTypesModule, ArtemisMarkdownModule, BarChartModule], - declarations: [ + imports: [ + ArtemisSharedModule, + RouterModule.forChild(ENTITY_STATES), + ArtemisQuizQuestionTypesModule, + ArtemisMarkdownModule, + BarChartModule, QuizStatisticComponent, QuizPointStatisticComponent, MultipleChoiceQuestionStatisticComponent, diff --git a/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistic.route.ts b/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistic.route.ts index 15b6ae44fbca..b25b085b3da4 100644 --- a/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistic.route.ts +++ b/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistic.route.ts @@ -1,16 +1,12 @@ import { Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { QuizStatisticComponent } from './quiz-statistic/quiz-statistic.component'; -import { QuizPointStatisticComponent } from './quiz-point-statistic/quiz-point-statistic.component'; -import { MultipleChoiceQuestionStatisticComponent } from './multiple-choice-question-statistic/multiple-choice-question-statistic.component'; -import { DragAndDropQuestionStatisticComponent } from './drag-and-drop-question-statistic/drag-and-drop-question-statistic.component'; -import { ShortAnswerQuestionStatisticComponent } from './short-answer-question-statistic/short-answer-question-statistic.component'; + import { Authority } from 'app/shared/constants/authority.constants'; export const quizStatisticRoute: Routes = [ { path: ':courseId/quiz-exercises/:exerciseId/quiz-statistic', - component: QuizStatisticComponent, + loadComponent: () => import('./quiz-statistic/quiz-statistic.component').then((m) => m.QuizStatisticComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.course.home.title', @@ -19,7 +15,7 @@ export const quizStatisticRoute: Routes = [ }, { path: ':courseId/quiz-exercises/:exerciseId/quiz-point-statistic', - component: QuizPointStatisticComponent, + loadComponent: () => import('./quiz-point-statistic/quiz-point-statistic.component').then((m) => m.QuizPointStatisticComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.course.home.title', @@ -28,7 +24,7 @@ export const quizStatisticRoute: Routes = [ }, { path: ':courseId/quiz-exercises/:exerciseId/mc-question-statistic/:questionId', - component: MultipleChoiceQuestionStatisticComponent, + loadComponent: () => import('./multiple-choice-question-statistic/multiple-choice-question-statistic.component').then((m) => m.MultipleChoiceQuestionStatisticComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.course.home.title', @@ -37,7 +33,7 @@ export const quizStatisticRoute: Routes = [ }, { path: ':courseId/quiz-exercises/:exerciseId/dnd-question-statistic/:questionId', - component: DragAndDropQuestionStatisticComponent, + loadComponent: () => import('./drag-and-drop-question-statistic/drag-and-drop-question-statistic.component').then((m) => m.DragAndDropQuestionStatisticComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.course.home.title', @@ -46,7 +42,7 @@ export const quizStatisticRoute: Routes = [ }, { path: ':courseId/quiz-exercises/:exerciseId/sa-question-statistic/:questionId', - component: ShortAnswerQuestionStatisticComponent, + loadComponent: () => import('./short-answer-question-statistic/short-answer-question-statistic.component').then((m) => m.ShortAnswerQuestionStatisticComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.course.home.title', diff --git a/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistic/quiz-statistic.component.ts b/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistic/quiz-statistic.component.ts index 9cea337abc1e..45b010a9e8df 100644 --- a/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistic/quiz-statistic.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistic/quiz-statistic.component.ts @@ -1,27 +1,35 @@ -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; import { HttpResponse } from '@angular/common/http'; -import { Subscription } from 'rxjs'; -import { QuizStatisticUtil } from 'app/exercises/quiz/shared/quiz-statistic-util.service'; import { AccountService } from 'app/core/auth/account.service'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; import { QuizExerciseService } from 'app/exercises/quiz/manage/quiz-exercise.service'; import { Authority } from 'app/shared/constants/authority.constants'; -import { QuizStatistics } from 'app/exercises/quiz/manage/statistics/quiz-statistics'; +import { AbstractQuizStatisticComponent } from 'app/exercises/quiz/manage/statistics/quiz-statistics'; import { faSync } from '@fortawesome/free-solid-svg-icons'; import { calculateMaxScore } from 'app/exercises/quiz/manage/statistics/quiz-statistic/quiz-statistics.utils'; import { round } from 'app/shared/util/utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { BarChartModule } from '@swimlane/ngx-charts'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { QuizStatisticsFooterComponent } from '../quiz-statistics-footer/quiz-statistics-footer.component'; @Component({ selector: 'jhi-quiz-statistic', templateUrl: './quiz-statistic.component.html', styleUrls: ['../quiz-point-statistic/quiz-point-statistic.component.scss', '../../../../../shared/chart/vertical-bar-chart.scss'], + imports: [TranslateDirective, BarChartModule, FaIconComponent, QuizStatisticsFooterComponent], }) -export class QuizStatisticComponent extends QuizStatistics implements OnInit, OnDestroy { +export class QuizStatisticComponent extends AbstractQuizStatisticComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private router = inject(Router); + private accountService = inject(AccountService); + private quizExerciseService = inject(QuizExerciseService); + private jhiWebsocketService = inject(JhiWebsocketService); + private changeDetector = inject(ChangeDetectorRef); + quizExercise: QuizExercise; - private sub: Subscription; label: string[] = []; backgroundColor: string[] = []; @@ -34,26 +42,13 @@ export class QuizStatisticComponent extends QuizStatistics implements OnInit, On // Icons faSync = faSync; - constructor( - private route: ActivatedRoute, - private router: Router, - private accountService: AccountService, - protected translateService: TranslateService, - private quizExerciseService: QuizExerciseService, - private quizStatisticUtil: QuizStatisticUtil, - private jhiWebsocketService: JhiWebsocketService, - private changeDetector: ChangeDetectorRef, - ) { - super(translateService); + ngOnInit() { this.translateService.onLangChange.subscribe(() => { this.setAxisLabels('showStatistic.quizStatistic.xAxes', 'showStatistic.quizStatistic.yAxes'); this.ngxData[this.ngxData.length - 1].name = this.translateService.instant('showStatistic.quizStatistic.average'); this.ngxData = [...this.ngxData]; }); - } - - ngOnInit() { - this.sub = this.route.params.subscribe((params) => { + this.route.params.subscribe((params) => { // use different REST-call if the User is a Student if (this.accountService.hasAnyAuthorityDirect([Authority.ADMIN, Authority.INSTRUCTOR, Authority.EDITOR, Authority.TA])) { this.quizExerciseService.find(params['exerciseId']).subscribe((res: HttpResponse) => { @@ -85,7 +80,7 @@ export class QuizStatisticComponent extends QuizStatistics implements OnInit, On * This functions loads the Quiz, which is necessary to build the Web-Template * And it loads the new Data if the Websocket has been notified * - * @param {QuizExercise} quiz: the quizExercise, which this quiz-statistic presents. + * @param quiz the quizExercise, which this quiz-statistic presents. */ loadQuizSuccess(quiz: QuizExercise) { // if the Student finds a way to the Website -> the Student will be sent back to Courses diff --git a/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistics-footer/quiz-statistics-footer.component.ts b/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistics-footer/quiz-statistics-footer.component.ts index 8765ef7488a4..f3cc4662659c 100644 --- a/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistics-footer/quiz-statistics-footer.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistics-footer/quiz-statistics-footer.component.ts @@ -1,5 +1,5 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { Component, Input, OnDestroy, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { QuizStatisticUtil } from 'app/exercises/quiz/shared/quiz-statistic-util.service'; import { ShortAnswerQuestionUtil } from 'app/exercises/quiz/shared/short-answer-question-util.service'; import { TranslateService } from '@ngx-translate/core'; @@ -16,14 +16,30 @@ import { Authority } from 'app/shared/constants/authority.constants'; import { UI_RELOAD_TIME } from 'app/shared/constants/exercise-exam-constants'; import { faListAlt } from '@fortawesome/free-regular-svg-icons'; import { ArtemisServerDateService } from 'app/shared/server-date.service'; +import { NgbDropdown, NgbDropdownMenu, NgbDropdownToggle } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgClass } from '@angular/common'; +import { JhiConnectionStatusComponent } from 'app/shared/connection-status/connection-status.component'; +import { TruncatePipe } from 'app/shared/pipes/truncate.pipe'; @Component({ selector: 'jhi-quiz-statistics-footer', templateUrl: './quiz-statistics-footer.component.html', providers: [QuizStatisticUtil, ShortAnswerQuestionUtil], styleUrls: ['./quiz-statistics-footer.component.scss', '../../../shared/quiz.scss'], + imports: [NgbDropdown, NgbDropdownToggle, FaIconComponent, TranslateDirective, NgbDropdownMenu, RouterLink, NgClass, JhiConnectionStatusComponent, TruncatePipe], }) export class QuizStatisticsFooterComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private router = inject(Router); + private accountService = inject(AccountService); + private translateService = inject(TranslateService); + private quizExerciseService = inject(QuizExerciseService); + private quizStatisticUtil = inject(QuizStatisticUtil); + private jhiWebsocketService = inject(JhiWebsocketService); + private serverDateService = inject(ArtemisServerDateService); + @Input() isQuizPointStatistic: boolean; @Input() isQuizStatistic: boolean; @@ -47,17 +63,6 @@ export class QuizStatisticsFooterComponent implements OnInit, OnDestroy { // Icons farListAlt = faListAlt; - constructor( - private route: ActivatedRoute, - private router: Router, - private accountService: AccountService, - private translateService: TranslateService, - private quizExerciseService: QuizExerciseService, - private quizStatisticUtil: QuizStatisticUtil, - private jhiWebsocketService: JhiWebsocketService, - private serverDateService: ArtemisServerDateService, - ) {} - ngOnInit() { this.sub = this.route.params.subscribe((params) => { this.questionIdParam = +params['questionId']; diff --git a/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistics.ts b/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistics.ts index 39feb170c584..6598c34e86b8 100644 --- a/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistics.ts +++ b/src/main/webapp/app/exercises/quiz/manage/statistics/quiz-statistics.ts @@ -1,11 +1,15 @@ -import { ChangeDetectorRef } from '@angular/core'; +import { ChangeDetectorRef, Component, inject } from '@angular/core'; import { Color, ScaleType } from '@swimlane/ngx-charts'; import { round } from 'app/shared/util/utils'; import { QuizStatistic } from 'app/entities/quiz/quiz-statistic.model'; import { TranslateService } from '@ngx-translate/core'; import { NgxChartsSingleSeriesDataEntry } from 'app/shared/chart/ngx-charts-datatypes'; -export abstract class QuizStatistics { +@Component({ + template: '', +}) +export abstract class AbstractQuizStatisticComponent { + protected translateService = inject(TranslateService); data: number[] = []; ratedData: number[] = []; unratedData: number[] = []; @@ -26,8 +30,6 @@ export abstract class QuizStatistics { chartLabels: string[] = []; totalParticipants = 0; - constructor(protected translateService: TranslateService) {} - /** * Depending on if the rated or unrated results should be displayed, * The amount of participants as well as the corresponding scores are set diff --git a/src/main/webapp/app/exercises/quiz/manage/statistics/short-answer-question-statistic/short-answer-question-statistic.component.ts b/src/main/webapp/app/exercises/quiz/manage/statistics/short-answer-question-statistic/short-answer-question-statistic.component.ts index 1f60773b9d81..401a339ed563 100644 --- a/src/main/webapp/app/exercises/quiz/manage/statistics/short-answer-question-statistic/short-answer-question-statistic.component.ts +++ b/src/main/webapp/app/exercises/quiz/manage/statistics/short-answer-question-statistic/short-answer-question-statistic.component.ts @@ -1,18 +1,17 @@ -import { ChangeDetectorRef, Component } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; +import { Component, inject } from '@angular/core'; import { QuizStatisticUtil } from 'app/exercises/quiz/shared/quiz-statistic-util.service'; import { ShortAnswerQuestionUtil } from 'app/exercises/quiz/shared/short-answer-question-util.service'; import { ArtemisMarkdownService } from 'app/shared/markdown.service'; -import { AccountService } from 'app/core/auth/account.service'; -import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; import { ShortAnswerQuestion } from 'app/entities/quiz/short-answer-question.model'; -import { QuizExerciseService } from 'app/exercises/quiz/manage/quiz-exercise.service'; import { ShortAnswerQuestionStatistic } from 'app/entities/quiz/short-answer-question-statistic.model'; import { ShortAnswerSolution } from 'app/entities/quiz/short-answer-solution.model'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; import { QuestionStatisticComponent, blueColor, greenColor } from 'app/exercises/quiz/manage/statistics/question-statistic.component'; import { faCheckCircle, faSync, faTimesCircle } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { BarChartModule } from '@swimlane/ngx-charts'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { QuizStatisticsFooterComponent } from '../quiz-statistics-footer/quiz-statistics-footer.component'; @Component({ selector: 'jhi-short-answer-question-statistic', @@ -23,8 +22,12 @@ import { faCheckCircle, faSync, faTimesCircle } from '@fortawesome/free-solid-sv '../quiz-point-statistic/quiz-point-statistic.component.scss', './short-answer-question-statistic.component.scss', ], + imports: [TranslateDirective, BarChartModule, FaIconComponent, QuizStatisticsFooterComponent], }) export class ShortAnswerQuestionStatisticComponent extends QuestionStatisticComponent { + shortAnswerQuestionUtil = inject(ShortAnswerQuestionUtil); + private artemisMarkdown = inject(ArtemisMarkdownService); + declare question: ShortAnswerQuestion; textParts: string[][]; @@ -37,27 +40,6 @@ export class ShortAnswerQuestionStatisticComponent extends QuestionStatisticComp faCheckCircle = faCheckCircle; faTimesCircle = faTimesCircle; - constructor( - route: ActivatedRoute, - router: Router, - accountService: AccountService, - translateService: TranslateService, - quizExerciseService: QuizExerciseService, - jhiWebsocketService: JhiWebsocketService, - quizStatisticUtil: QuizStatisticUtil, - public shortAnswerQuestionUtil: ShortAnswerQuestionUtil, - private artemisMarkdown: ArtemisMarkdownService, - protected changeDetector: ChangeDetectorRef, - ) { - super(route, router, accountService, translateService, quizExerciseService, jhiWebsocketService, changeDetector); - } - - /** - * This functions loads the Quiz, which is necessary to build the Web-Template - * - * @param {QuizExercise} quiz: the quizExercise, which the selected question is part of. - * @param {boolean} refresh: true if method is called from Websocket - */ loadQuiz(quiz: QuizExercise, refresh: boolean) { const updatedQuestion = super.loadQuizCommon(quiz); if (!updatedQuestion) { @@ -102,8 +84,8 @@ export class ShortAnswerQuestionStatisticComponent extends QuestionStatisticComp loadLayout() { this.resetLabelsColors(); - // set label and backgroundcolor based on the spots - this.question.spots!.forEach((spot, i) => { + // set label and background color based on the spots + this.question.spots!.forEach((_spot, i) => { this.labels.push(this.getLetter(i) + '.'); this.solutionLabels.push(this.getLetter(i) + '.'); this.backgroundColors.push(blueColor); diff --git a/src/main/webapp/app/exercises/quiz/participate/quiz-participation.component.ts b/src/main/webapp/app/exercises/quiz/participate/quiz-participation.component.ts index 599e48e43a22..70a3f28af980 100644 --- a/src/main/webapp/app/exercises/quiz/participate/quiz-participation.component.ts +++ b/src/main/webapp/app/exercises/quiz/participate/quiz-participation.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core'; +import { Component, OnDestroy, OnInit, QueryList, ViewChildren, inject } from '@angular/core'; import dayjs from 'dayjs/esm'; import isMobile from 'ismobilejs-es5'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; @@ -38,14 +38,49 @@ import { captureException } from '@sentry/angular'; import { getCourseFromExercise } from 'app/entities/exercise.model'; import { faCircleNotch, faSync } from '@fortawesome/free-solid-svg-icons'; import { ArtemisServerDateService } from 'app/shared/server-date.service'; +import { NgClass, NgTemplateOutlet } from '@angular/common'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { JhiConnectionStatusComponent } from 'app/shared/connection-status/connection-status.component'; +import { FormsModule } from '@angular/forms'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-quiz', templateUrl: './quiz-participation.component.html', providers: [ParticipationService], styleUrls: ['./quiz-participation.component.scss'], + imports: [ + NgClass, + NgTemplateOutlet, + TranslateDirective, + ButtonComponent, + NgbTooltip, + MultipleChoiceQuestionComponent, + DragAndDropQuestionComponent, + ShortAnswerQuestionComponent, + JhiConnectionStatusComponent, + FormsModule, + FaIconComponent, + ArtemisDatePipe, + ArtemisTranslatePipe, + ], }) export class QuizParticipationComponent implements OnInit, OnDestroy { + private jhiWebsocketService = inject(JhiWebsocketService); + private quizExerciseService = inject(QuizExerciseService); + private participationService = inject(ParticipationService); + private route = inject(ActivatedRoute); + private router = inject(Router); + private alertService = inject(AlertService); + private quizParticipationService = inject(QuizParticipationService); + private translateService = inject(TranslateService); + private quizService = inject(ArtemisQuizService); + private serverDateService = inject(ArtemisServerDateService); + // make constants available to html for comparison readonly DRAG_AND_DROP = QuizQuestionType.DRAG_AND_DROP; readonly MULTIPLE_CHOICE = QuizQuestionType.MULTIPLE_CHOICE; @@ -128,18 +163,7 @@ export class QuizParticipationComponent implements OnInit, OnDestroy { faSync = faSync; faCircleNotch = faCircleNotch; - constructor( - private jhiWebsocketService: JhiWebsocketService, - private quizExerciseService: QuizExerciseService, - private participationService: ParticipationService, - private route: ActivatedRoute, - private router: Router, - private alertService: AlertService, - private quizParticipationService: QuizParticipationService, - private translateService: TranslateService, - private quizService: ArtemisQuizService, - private serverDateService: ArtemisServerDateService, - ) { + constructor() { smoothscroll.polyfill(); } diff --git a/src/main/webapp/app/exercises/quiz/participate/quiz-participation.module.ts b/src/main/webapp/app/exercises/quiz/participate/quiz-participation.module.ts index 596dcbec2306..30682ecaf6d2 100644 --- a/src/main/webapp/app/exercises/quiz/participate/quiz-participation.module.ts +++ b/src/main/webapp/app/exercises/quiz/participate/quiz-participation.module.ts @@ -1,13 +1,12 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; -import { quizParticipationRoute } from './quiz-participation.route'; -import { QuizParticipationComponent } from './quiz-participation.component'; +import { quizParticipationRoute } from 'app/exercises/quiz/participate/quiz-participation.route'; +import { QuizParticipationComponent } from 'app/exercises/quiz/participate/quiz-participation.component'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ArtemisQuizQuestionTypesModule } from 'app/exercises/quiz/shared/questions/artemis-quiz-question-types.module'; @NgModule({ - imports: [ArtemisSharedModule, RouterModule.forChild(quizParticipationRoute), ArtemisSharedComponentModule, ArtemisQuizQuestionTypesModule], - declarations: [QuizParticipationComponent], + imports: [ArtemisSharedModule, RouterModule.forChild(quizParticipationRoute), ArtemisSharedComponentModule, ArtemisQuizQuestionTypesModule, QuizParticipationComponent], }) export class ArtemisQuizParticipationModule {} diff --git a/src/main/webapp/app/exercises/quiz/participate/quiz-participation.route.ts b/src/main/webapp/app/exercises/quiz/participate/quiz-participation.route.ts index 4c6e37d7b94e..48d5110a64b2 100644 --- a/src/main/webapp/app/exercises/quiz/participate/quiz-participation.route.ts +++ b/src/main/webapp/app/exercises/quiz/participate/quiz-participation.route.ts @@ -1,12 +1,11 @@ import { Routes } from '@angular/router'; -import { QuizParticipationComponent } from './quiz-participation.component'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; export const quizParticipationRoute: Routes = [ { path: 'live', - component: QuizParticipationComponent, + loadComponent: () => import('./quiz-participation.component').then((m) => m.QuizParticipationComponent), data: { authorities: [], pageTitle: 'artemisApp.quizExercise.home.title', @@ -16,7 +15,7 @@ export const quizParticipationRoute: Routes = [ }, { path: 'practice', - component: QuizParticipationComponent, + loadComponent: () => import('./quiz-participation.component').then((m) => m.QuizParticipationComponent), data: { authorities: [], pageTitle: 'artemisApp.quizExercise.home.title', diff --git a/src/main/webapp/app/exercises/quiz/participate/quiz-participation.service.ts b/src/main/webapp/app/exercises/quiz/participate/quiz-participation.service.ts index f6eb1bdc696c..5ccce2db131b 100644 --- a/src/main/webapp/app/exercises/quiz/participate/quiz-participation.service.ts +++ b/src/main/webapp/app/exercises/quiz/participate/quiz-participation.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { QuizSubmission } from 'app/entities/quiz/quiz-submission.model'; @@ -11,10 +11,8 @@ export type ResultResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class QuizParticipationService { - constructor( - private http: HttpClient, - private submissionService: SubmissionService, - ) {} + private http = inject(HttpClient); + private submissionService = inject(SubmissionService); submitForPractice(quizSubmission: QuizSubmission, exerciseId: number): Observable { const copy = this.submissionService.convert(quizSubmission); diff --git a/src/main/webapp/app/exercises/quiz/shared/drag-and-drop-question-util.service.ts b/src/main/webapp/app/exercises/quiz/shared/drag-and-drop-question-util.service.ts index 741254eb7446..73462d5e6752 100644 --- a/src/main/webapp/app/exercises/quiz/shared/drag-and-drop-question-util.service.ts +++ b/src/main/webapp/app/exercises/quiz/shared/drag-and-drop-question-util.service.ts @@ -6,8 +6,6 @@ import { BaseEntityWithTempId, DropLocation } from 'app/entities/quiz/drop-locat @Injectable({ providedIn: 'root' }) export class DragAndDropQuestionUtil { - constructor() {} - /** * Get a sample solution for the given drag and drop question * diff --git a/src/main/webapp/app/exercises/quiz/shared/fit-text/fit-text.directive.ts b/src/main/webapp/app/exercises/quiz/shared/fit-text/fit-text.directive.ts index eb0c9fc9ba89..b41c9d4b1924 100644 --- a/src/main/webapp/app/exercises/quiz/shared/fit-text/fit-text.directive.ts +++ b/src/main/webapp/app/exercises/quiz/shared/fit-text/fit-text.directive.ts @@ -1,10 +1,11 @@ -import { AfterViewInit, Directive, ElementRef, HostListener, Input, OnChanges, OnInit, Renderer2, SimpleChanges } from '@angular/core'; +import { AfterViewInit, Directive, ElementRef, HostListener, Input, OnChanges, OnDestroy, OnInit, Renderer2, SimpleChanges, inject } from '@angular/core'; // NOTE: this code was taken from https://github.com/sollenne/angular-fittext because the repository was not maintained any more since June 2018 -// eslint-disable-next-line @angular-eslint/directive-selector @Directive({ selector: '[fitText]' }) -export class FitTextDirective implements AfterViewInit, OnInit, OnChanges { +export class FitTextDirective implements AfterViewInit, OnInit, OnChanges, OnDestroy { + private renderer = inject(Renderer2); + @Input() fitText = true; @Input() compression = 1; @Input() activateOnResize = true; @@ -23,12 +24,11 @@ export class FitTextDirective implements AfterViewInit, OnInit, OnChanges { private fitTextMinFontSize: number; private fitTextMaxFontSize: number; private calcSize = 10; - private resizeTimeout: any; + private resizeTimeout: NodeJS.Timeout; + + constructor() { + const el = inject(ElementRef); - constructor( - private el: ElementRef, - private renderer: Renderer2, - ) { this.fitTextElement = el.nativeElement; this.fitTextParent = this.fitTextElement.parentElement!; this.computed = window.getComputedStyle(this.fitTextElement); @@ -65,6 +65,10 @@ export class FitTextDirective implements AfterViewInit, OnInit, OnChanges { } } + public ngOnDestroy() { + clearTimeout(this.resizeTimeout); + } + private setFontSize = (delay: number = this.delay): void => { this.resizeTimeout = setTimeout(() => { if (this.fitTextElement.offsetHeight * this.fitTextElement.offsetWidth !== 0) { diff --git a/src/main/webapp/app/exercises/quiz/shared/fit-text/fit-text.module.ts b/src/main/webapp/app/exercises/quiz/shared/fit-text/fit-text.module.ts deleted file mode 100644 index f2e9ed2dccdc..000000000000 --- a/src/main/webapp/app/exercises/quiz/shared/fit-text/fit-text.module.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { NgModule } from '@angular/core'; -import { FitTextDirective } from 'app/exercises/quiz/shared/fit-text/fit-text.directive'; - -@NgModule({ - declarations: [FitTextDirective], - exports: [FitTextDirective], -}) -export class FitTextModule {} diff --git a/src/main/webapp/app/exercises/quiz/shared/questions/artemis-quiz-question-types.module.ts b/src/main/webapp/app/exercises/quiz/shared/questions/artemis-quiz-question-types.module.ts index 65ca1d3acea7..3d1bc34d5a45 100644 --- a/src/main/webapp/app/exercises/quiz/shared/questions/artemis-quiz-question-types.module.ts +++ b/src/main/webapp/app/exercises/quiz/shared/questions/artemis-quiz-question-types.module.ts @@ -7,12 +7,14 @@ import { DragItemComponent } from './drag-and-drop-question/drag-item.component' import { DragDropModule } from '@angular/cdk/drag-drop'; import { QuizScoringInfoStudentModalComponent } from 'app/exercises/quiz/shared/questions/quiz-scoring-infostudent-modal/quiz-scoring-info-student-modal.component'; import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; -import { FitTextModule } from 'app/exercises/quiz/shared/fit-text/fit-text.module'; + import { MultipleChoiceVisualQuestionComponent } from 'app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-visual-question.component'; @NgModule({ - imports: [ArtemisSharedModule, DragDropModule, ArtemisMarkdownModule, FitTextModule], - declarations: [ + imports: [ + ArtemisSharedModule, + DragDropModule, + ArtemisMarkdownModule, DragItemComponent, DragAndDropQuestionComponent, MultipleChoiceQuestionComponent, diff --git a/src/main/webapp/app/exercises/quiz/shared/questions/drag-and-drop-question/drag-and-drop-question.component.ts b/src/main/webapp/app/exercises/quiz/shared/questions/drag-and-drop-question/drag-and-drop-question.component.ts index 64275c7e790f..0f724312c2e2 100644 --- a/src/main/webapp/app/exercises/quiz/shared/questions/drag-and-drop-question/drag-and-drop-question.component.ts +++ b/src/main/webapp/app/exercises/quiz/shared/questions/drag-and-drop-question/drag-and-drop-question.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewChild, ViewEncapsulation, inject } from '@angular/core'; import { ArtemisMarkdownService } from 'app/shared/markdown.service'; import { DragAndDropQuestionUtil } from 'app/exercises/quiz/shared/drag-and-drop-question-util.service'; import { polyfill } from 'mobile-drag-drop'; @@ -9,8 +9,14 @@ import { DragAndDropMapping } from 'app/entities/quiz/drag-and-drop-mapping.mode import { RenderedQuizQuestionMarkDownElement } from 'app/entities/quiz/quiz-question.model'; import { DropLocation } from 'app/entities/quiz/drop-location.model'; import { faExclamationCircle, faExclamationTriangle, faQuestionCircle, faSpinner } from '@fortawesome/free-solid-svg-icons'; -import { CdkDragDrop } from '@angular/cdk/drag-drop'; +import { CdkDragDrop, CdkDropList, CdkDropListGroup } from '@angular/cdk/drag-drop'; import { DragItem } from 'app/entities/quiz/drag-item.model'; +import { NgClass, NgStyle } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbPopover, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { QuizScoringInfoStudentModalComponent } from '../quiz-scoring-infostudent-modal/quiz-scoring-info-student-modal.component'; +import { DragItemComponent } from './drag-item.component'; // options are optional ;) polyfill({ @@ -36,8 +42,24 @@ enum MappingResult { providers: [DragAndDropQuestionUtil], styleUrls: ['./drag-and-drop-question.component.scss', '../../../participate/quiz-participation.scss'], encapsulation: ViewEncapsulation.None, + imports: [ + NgClass, + FaIconComponent, + TranslateDirective, + NgbPopover, + QuizScoringInfoStudentModalComponent, + CdkDropListGroup, + SecuredImageComponent, + CdkDropList, + NgStyle, + DragItemComponent, + NgbTooltip, + ], }) export class DragAndDropQuestionComponent implements OnChanges, OnInit { + private artemisMarkdown = inject(ArtemisMarkdownService); + private dragAndDropQuestionUtil = inject(DragAndDropQuestionUtil); + /** needed to trigger a manual reload of the drag and drop background picture */ @ViewChild(SecuredImageComponent, { static: false }) secureImageComponent: SecuredImageComponent; @@ -100,11 +122,6 @@ export class DragAndDropQuestionComponent implements OnChanges, OnInit { faExclamationTriangle = faExclamationTriangle; faExclamationCircle = faExclamationCircle; - constructor( - private artemisMarkdown: ArtemisMarkdownService, - private dragAndDropQuestionUtil: DragAndDropQuestionUtil, - ) {} - ngOnInit(): void { this.evaluateDropLocations(); } @@ -215,8 +232,8 @@ export class DragAndDropQuestionComponent implements OnChanges, OnInit { /** * Get the drag item that was mapped to the given drop location * - * @param dropLocation {object} the drop location that the drag item should be mapped to - * @return {object | undefined} the mapped drag item, or undefined, if no drag item has been mapped to this location + * @param dropLocation the drop location that the drag item should be mapped to + * @return the mapped drag item, or undefined, if no drag item has been mapped to this location */ dragItemForDropLocation(dropLocation: DropLocation) { if (this.mappings) { @@ -238,7 +255,7 @@ export class DragAndDropQuestionComponent implements OnChanges, OnInit { /** * Get all drag items that have not been assigned to a drop location yet * - * @return {Array} an array of all unassigned drag items + * @returnan array of all unassigned drag items */ getUnassignedDragItems() { return this.question.dragItems?.filter((dragItem) => { @@ -312,8 +329,8 @@ export class DragAndDropQuestionComponent implements OnChanges, OnInit { /** * Get the drag item that was mapped to the given drop location in the sample solution * - * @param dropLocation {object} the drop location that the drag item should be mapped to - * @return {DragItem | undefined} the mapped drag item, or undefined, if no drag item has been mapped to this location + * @param dropLocation the drop location that the drag item should be mapped to + * @return the mapped drag item, or undefined, if no drag item has been mapped to this location */ correctDragItemForDropLocation(dropLocation: DropLocation) { const dragAndDropQuestionUtil = this.dragAndDropQuestionUtil; diff --git a/src/main/webapp/app/exercises/quiz/shared/questions/drag-and-drop-question/drag-item.component.ts b/src/main/webapp/app/exercises/quiz/shared/questions/drag-and-drop-question/drag-item.component.ts index 1d2b06714b93..3d4e920820d5 100644 --- a/src/main/webapp/app/exercises/quiz/shared/questions/drag-and-drop-question/drag-item.component.ts +++ b/src/main/webapp/app/exercises/quiz/shared/questions/drag-and-drop-question/drag-item.component.ts @@ -1,12 +1,18 @@ import { Component, Input, OnInit, ViewEncapsulation } from '@angular/core'; import isMobile from 'ismobilejs-es5'; import { DragItem } from 'app/entities/quiz/drag-item.model'; +import { NgClass, NgStyle } from '@angular/common'; +import { CdkDrag, CdkDragPlaceholder, CdkDragPreview } from '@angular/cdk/drag-drop'; +import { SecuredImageComponent } from 'app/shared/image/secured-image.component'; +import { FitTextDirective } from '../../fit-text/fit-text.directive'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-drag-item', templateUrl: './drag-item.component.html', styleUrls: ['./drag-item.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [NgClass, NgStyle, CdkDrag, SecuredImageComponent, CdkDragPlaceholder, FitTextDirective, CdkDragPreview, TranslateDirective], }) export class DragItemComponent implements OnInit { @Input() minWidth: string; @@ -16,8 +22,6 @@ export class DragItemComponent implements OnInit { @Input() filePreviewPaths: Map = new Map(); isMobile = false; - constructor() {} - /** * Initializes device information and whether the device is a mobile device */ diff --git a/src/main/webapp/app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-question.component.ts b/src/main/webapp/app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-question.component.ts index 183d2f78a897..26a84e2563d9 100644 --- a/src/main/webapp/app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-question.component.ts +++ b/src/main/webapp/app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-question.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core'; +import { Component, EventEmitter, Input, Output, ViewEncapsulation, inject } from '@angular/core'; import { ArtemisMarkdownService } from 'app/shared/markdown.service'; import { AnswerOption } from 'app/entities/quiz/answer-option.model'; import { MultipleChoiceQuestion } from 'app/entities/quiz/multiple-choice-question.model'; @@ -6,14 +6,23 @@ import { QuizQuestion, RenderedQuizQuestionMarkDownElement } from 'app/entities/ import { Result } from 'app/entities/result.model'; import { faExclamationCircle, faExclamationTriangle, faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; import { faCheckSquare, faCircle, faDotCircle, faSquare } from '@fortawesome/free-regular-svg-icons'; +import { NgClass } from '@angular/common'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbPopover, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { QuizScoringInfoStudentModalComponent } from '../quiz-scoring-infostudent-modal/quiz-scoring-info-student-modal.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-multiple-choice-question', templateUrl: './multiple-choice-question.component.html', styleUrls: ['./multiple-choice-question.component.scss', '../../../participate/quiz-participation.scss'], encapsulation: ViewEncapsulation.None, + imports: [NgClass, TranslateDirective, NgbPopover, FaIconComponent, QuizScoringInfoStudentModalComponent, NgbTooltip, ArtemisTranslatePipe], }) export class MultipleChoiceQuestionComponent { + private artemisMarkdown = inject(ArtemisMarkdownService); + _question: MultipleChoiceQuestion; @Input() @@ -58,8 +67,6 @@ export class MultipleChoiceQuestionComponent { faCircle = faCircle; faDotCircle = faDotCircle; - constructor(private artemisMarkdown: ArtemisMarkdownService) {} - /** * Update html for text, hint and explanation for the question and every answer option */ diff --git a/src/main/webapp/app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-visual-question.component.ts b/src/main/webapp/app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-visual-question.component.ts index 5d3ce99651c3..2f8d68fe691e 100644 --- a/src/main/webapp/app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-visual-question.component.ts +++ b/src/main/webapp/app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-visual-question.component.ts @@ -3,12 +3,19 @@ import { MultipleChoiceQuestion } from 'app/entities/quiz/multiple-choice-questi import { faCheck, faExclamationCircle, faExclamationTriangle, faPlus, faQuestionCircle, faTrash, faXmark } from '@fortawesome/free-solid-svg-icons'; import { faCircle } from '@fortawesome/free-regular-svg-icons'; import { AnswerOption } from 'app/entities/quiz/answer-option.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { NgClass } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-multiple-choice-visual-question', templateUrl: './multiple-choice-visual-question.component.html', styleUrls: ['./multiple-choice-question.component.scss', '../../../participate/quiz-participation.scss'], encapsulation: ViewEncapsulation.None, + imports: [TranslateDirective, FormsModule, FaIconComponent, NgbTooltip, NgClass, ArtemisTranslatePipe], }) export class MultipleChoiceVisualQuestionComponent { _question: MultipleChoiceQuestion; @@ -33,8 +40,6 @@ export class MultipleChoiceVisualQuestionComponent { faTrash = faTrash; faXmark = faXmark; - constructor() {} - parseQuestion() { let markdown = this.question.text ?? ''; diff --git a/src/main/webapp/app/exercises/quiz/shared/questions/quiz-scoring-infostudent-modal/quiz-scoring-info-student-modal.component.ts b/src/main/webapp/app/exercises/quiz/shared/questions/quiz-scoring-infostudent-modal/quiz-scoring-info-student-modal.component.ts index 5ac7d0af0c23..864d808ca87a 100644 --- a/src/main/webapp/app/exercises/quiz/shared/questions/quiz-scoring-infostudent-modal/quiz-scoring-info-student-modal.component.ts +++ b/src/main/webapp/app/exercises/quiz/shared/questions/quiz-scoring-infostudent-modal/quiz-scoring-info-student-modal.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, Input } from '@angular/core'; +import { AfterViewInit, Component, Input, inject } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TranslateService } from '@ngx-translate/core'; import { Result } from 'app/entities/result.model'; @@ -11,13 +11,20 @@ import { AnswerOption } from 'app/entities/quiz/answer-option.model'; import { ShortAnswerSubmittedText } from 'app/entities/quiz/short-answer-submitted-text.model'; import { MultipleChoiceQuestion } from 'app/entities/quiz/multiple-choice-question.model'; import { faQuestionCircle } from '@fortawesome/free-regular-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgClass } from '@angular/common'; @Component({ selector: 'jhi-quiz-scoring-infostudent-modal', templateUrl: './quiz-scoring-info-student-modal.component.html', styleUrls: ['./quiz-scoring-info-student-modal.component.scss'], + imports: [TranslateDirective, FaIconComponent, NgClass], }) export class QuizScoringInfoStudentModalComponent implements AfterViewInit { + private modalService = inject(NgbModal); + private translateService = inject(TranslateService); + QuizQuestionType = QuizQuestionType; ScoringType = ScoringType; @@ -68,11 +75,6 @@ export class QuizScoringInfoStudentModalComponent implements AfterViewInit { // Icons farQuestionCircle = faQuestionCircle; - constructor( - private modalService: NgbModal, - private translateService: TranslateService, - ) {} - /** * Count the variables depending on the quiz question type */ diff --git a/src/main/webapp/app/exercises/quiz/shared/questions/short-answer-question/short-answer-question.component.ts b/src/main/webapp/app/exercises/quiz/shared/questions/short-answer-question/short-answer-question.component.ts index 8d6e7a41e96e..523ac041f6a5 100644 --- a/src/main/webapp/app/exercises/quiz/shared/questions/short-answer-question/short-answer-question.component.ts +++ b/src/main/webapp/app/exercises/quiz/shared/questions/short-answer-question/short-answer-question.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core'; +import { Component, EventEmitter, Input, Output, ViewEncapsulation, inject } from '@angular/core'; import { ArtemisMarkdownService } from 'app/shared/markdown.service'; import { ShortAnswerQuestionUtil } from 'app/exercises/quiz/shared/short-answer-question-util.service'; import { ShortAnswerSolution } from 'app/entities/quiz/short-answer-solution.model'; @@ -8,6 +8,12 @@ import { QuizQuestion, RenderedQuizQuestionMarkDownElement } from 'app/entities/ import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons'; import { faQuestionCircle } from '@fortawesome/free-regular-svg-icons'; import { MAX_QUIZ_SHORT_ANSWER_TEXT_LENGTH } from 'app/shared/constants/input.constants'; +import { NgClass } from '@angular/common'; +import { NgbPopover, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { QuizScoringInfoStudentModalComponent } from '../quiz-scoring-infostudent-modal/quiz-scoring-info-student-modal.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-short-answer-question', @@ -15,8 +21,12 @@ import { MAX_QUIZ_SHORT_ANSWER_TEXT_LENGTH } from 'app/shared/constants/input.co providers: [ShortAnswerQuestionUtil], styleUrls: ['./short-answer-question.component.scss', '../../../participate/quiz-participation.scss'], encapsulation: ViewEncapsulation.None, + imports: [NgClass, NgbTooltip, TranslateDirective, NgbPopover, FaIconComponent, QuizScoringInfoStudentModalComponent, ArtemisTranslatePipe], }) export class ShortAnswerQuestionComponent { + private artemisMarkdown = inject(ArtemisMarkdownService); + shortAnswerQuestionUtil = inject(ShortAnswerQuestionUtil); + shortAnswerQuestion: ShortAnswerQuestion; _forceSampleSolution: boolean; @@ -65,11 +75,6 @@ export class ShortAnswerQuestionComponent { faExclamationCircle = faExclamationCircle; farQuestionCircle = faQuestionCircle; - constructor( - private artemisMarkdown: ArtemisMarkdownService, - public shortAnswerQuestionUtil: ShortAnswerQuestionUtil, - ) {} - /** * Update html for text, hint and explanation for the question and every answer option */ diff --git a/src/main/webapp/app/exercises/quiz/shared/quiz-statistic-util.service.ts b/src/main/webapp/app/exercises/quiz/shared/quiz-statistic-util.service.ts index dc4464ed8fed..2a2f80ad30b6 100644 --- a/src/main/webapp/app/exercises/quiz/shared/quiz-statistic-util.service.ts +++ b/src/main/webapp/app/exercises/quiz/shared/quiz-statistic-util.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { Router } from '@angular/router'; import { QuizQuestion, QuizQuestionType } from 'app/entities/quiz/quiz-question.model'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; @@ -6,7 +6,7 @@ import { getCourseId } from 'app/entities/exercise.model'; @Injectable({ providedIn: 'root' }) export class QuizStatisticUtil { - constructor(private router: Router) {} + private router = inject(Router); /** * Gets the URL to the quiz exercise detail/edit view diff --git a/src/main/webapp/app/exercises/quiz/shared/short-answer-question-util.service.ts b/src/main/webapp/app/exercises/quiz/shared/short-answer-question-util.service.ts index 6e6aac7e24eb..232ba77bc1dc 100644 --- a/src/main/webapp/app/exercises/quiz/shared/short-answer-question-util.service.ts +++ b/src/main/webapp/app/exercises/quiz/shared/short-answer-question-util.service.ts @@ -8,8 +8,6 @@ import { htmlForMarkdown } from 'app/shared/util/markdown.conversion.util'; @Injectable({ providedIn: 'root' }) export class ShortAnswerQuestionUtil { - constructor() {} - /** * Validate that no mapping exists that makes it impossible to solve the question. * We iterate through all spots and remove all possible mappings (solutions) for that spot. diff --git a/src/main/webapp/app/exercises/shared/assessment-progress-label/assessment-progress-label.component.ts b/src/main/webapp/app/exercises/shared/assessment-progress-label/assessment-progress-label.component.ts index 254a3b2a5f82..3b6942134bdb 100644 --- a/src/main/webapp/app/exercises/shared/assessment-progress-label/assessment-progress-label.component.ts +++ b/src/main/webapp/app/exercises/shared/assessment-progress-label/assessment-progress-label.component.ts @@ -1,10 +1,13 @@ import { Component, Input, OnChanges } from '@angular/core'; import { Submission, getLatestSubmissionResult } from 'app/entities/submission.model'; import { isManualResult } from 'app/exercises/shared/result/result.utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DecimalPipe, NgClass } from '@angular/common'; @Component({ selector: 'jhi-assessment-progress-label', templateUrl: './assessment-progress-label.component.html', + imports: [TranslateDirective, NgClass, DecimalPipe], }) export class AssessmentProgressLabelComponent implements OnChanges { @Input() diff --git a/src/main/webapp/app/exercises/shared/assessment-progress-label/assessment-progress-label.module.ts b/src/main/webapp/app/exercises/shared/assessment-progress-label/assessment-progress-label.module.ts index 9b8bfa4925f0..8516a51d2e75 100644 --- a/src/main/webapp/app/exercises/shared/assessment-progress-label/assessment-progress-label.module.ts +++ b/src/main/webapp/app/exercises/shared/assessment-progress-label/assessment-progress-label.module.ts @@ -3,8 +3,7 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; import { AssessmentProgressLabelComponent } from 'app/exercises/shared/assessment-progress-label/assessment-progress-label.component'; @NgModule({ - imports: [ArtemisSharedModule], - declarations: [AssessmentProgressLabelComponent], + imports: [ArtemisSharedModule, AssessmentProgressLabelComponent], exports: [AssessmentProgressLabelComponent], }) export class ArtemisAssessmentProgressLabelModule {} diff --git a/src/main/webapp/app/exercises/shared/course-exercises/course-exercise.service.ts b/src/main/webapp/app/exercises/shared/course-exercises/course-exercise.service.ts index c9ea1e512eb3..b467799e3adc 100644 --- a/src/main/webapp/app/exercises/shared/course-exercises/course-exercise.service.ts +++ b/src/main/webapp/app/exercises/shared/course-exercises/course-exercise.service.ts @@ -9,20 +9,18 @@ import { Exercise } from 'app/entities/exercise.model'; import { StudentParticipation } from 'app/entities/participation/student-participation.model'; import { Observable, map } from 'rxjs'; import { HttpClient, HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { convertDateFromServer } from 'app/utils/date.utils'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; @Injectable({ providedIn: 'root' }) export class CourseExerciseService { - private resourceUrl = `api/courses`; + private http = inject(HttpClient); + private participationWebsocketService = inject(ParticipationWebsocketService); + private accountService = inject(AccountService); + private profileService = inject(ProfileService); - constructor( - private http: HttpClient, - private participationWebsocketService: ParticipationWebsocketService, - private accountService: AccountService, - private profileService: ProfileService, - ) {} + private resourceUrl = `api/courses`; /** * returns all programming exercises for the course corresponding to courseId diff --git a/src/main/webapp/app/exercises/shared/dashboards/tutor/exercise-assessment-dashboard.component.html b/src/main/webapp/app/exercises/shared/dashboards/tutor/exercise-assessment-dashboard.component.html index b1b2e9295b76..fbfe3529f40c 100644 --- a/src/main/webapp/app/exercises/shared/dashboards/tutor/exercise-assessment-dashboard.component.html +++ b/src/main/webapp/app/exercises/shared/dashboards/tutor/exercise-assessment-dashboard.component.html @@ -258,7 +258,9 @@

-
+ + +
@if (tutorParticipationStatus === REVIEWED_INSTRUCTIONS && !isTestRun) {
- @if (this.lectureIngestionEnabled && this.lectureUnit.type == LectureUnitType.ATTACHMENT) { + @if (this.lectureIngestionEnabled && lectureUnit.type == LectureUnitType.ATTACHMENT) {
@if (lecture.course?.id && showCompetencies) { { - constructor(private attachmentUnitService: AttachmentUnitService) {} + private attachmentUnitService = inject(AttachmentUnitService); resolve(route: ActivatedRouteSnapshot): Observable { const lectureId = route.params['lectureId']; @@ -41,7 +30,7 @@ export class AttachmentUnitResolve implements Resolve { export const lectureUnitRoute: Routes = [ { path: 'unit-management', - component: LectureUnitManagementComponent, + loadComponent: () => import('app/lecture/lecture-unit/lecture-unit-management/lecture-unit-management.component').then((m) => m.LectureUnitManagementComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.lectureUnit.home.title', @@ -57,7 +46,8 @@ export const lectureUnitRoute: Routes = [ children: [ { path: 'exercise-units/create', - component: CreateExerciseUnitComponent, + loadComponent: () => + import('app/lecture/lecture-unit/lecture-unit-management/create-exercise-unit/create-exercise-unit.component').then((m) => m.CreateExerciseUnitComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.exerciseUnit.createExerciseUnit.title', @@ -65,7 +55,7 @@ export const lectureUnitRoute: Routes = [ }, { path: 'attachment-units/process', - component: AttachmentUnitsComponent, + loadComponent: () => import('app/lecture/lecture-unit/lecture-unit-management/attachment-units/attachment-units.component').then((m) => m.AttachmentUnitsComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.attachmentUnit.createAttachmentUnits.pageTitle', @@ -73,7 +63,8 @@ export const lectureUnitRoute: Routes = [ }, { path: 'attachment-units/create', - component: CreateAttachmentUnitComponent, + loadComponent: () => + import('app/lecture/lecture-unit/lecture-unit-management/create-attachment-unit/create-attachment-unit.component').then((m) => m.CreateAttachmentUnitComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.attachmentUnit.createAttachmentUnit.title', @@ -81,7 +72,8 @@ export const lectureUnitRoute: Routes = [ }, { path: 'video-units/create', - component: CreateVideoUnitComponent, + loadComponent: () => + import('app/lecture/lecture-unit/lecture-unit-management/create-video-unit/create-video-unit.component').then((m) => m.CreateVideoUnitComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.videoUnit.createVideoUnit.title', @@ -89,7 +81,8 @@ export const lectureUnitRoute: Routes = [ }, { path: 'online-units/create', - component: CreateOnlineUnitComponent, + loadComponent: () => + import('app/lecture/lecture-unit/lecture-unit-management/create-online-unit/create-online-unit.component').then((m) => m.CreateOnlineUnitComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.onlineUnit.createOnlineUnit.title', @@ -97,7 +90,7 @@ export const lectureUnitRoute: Routes = [ }, { path: 'text-units/create', - component: CreateTextUnitComponent, + loadComponent: () => import('app/lecture/lecture-unit/lecture-unit-management/create-text-unit/create-text-unit.component').then((m) => m.CreateTextUnitComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.textUnit.createTextUnit.title', @@ -105,7 +98,8 @@ export const lectureUnitRoute: Routes = [ }, { path: 'attachment-units/:attachmentUnitId/edit', - component: EditAttachmentUnitComponent, + loadComponent: () => + import('app/lecture/lecture-unit/lecture-unit-management/edit-attachment-unit/edit-attachment-unit.component').then((m) => m.EditAttachmentUnitComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.attachmentUnit.editAttachmentUnit.title', @@ -113,7 +107,7 @@ export const lectureUnitRoute: Routes = [ }, { path: 'attachment-units/:attachmentUnitId/view', - component: PdfPreviewComponent, + loadComponent: () => import('app/lecture/pdf-preview/pdf-preview.component').then((m) => m.PdfPreviewComponent), resolve: { course: CourseManagementResolve, attachmentUnit: AttachmentUnitResolve, @@ -121,7 +115,7 @@ export const lectureUnitRoute: Routes = [ }, { path: 'video-units/:videoUnitId/edit', - component: EditVideoUnitComponent, + loadComponent: () => import('app/lecture/lecture-unit/lecture-unit-management/edit-video-unit/edit-video-unit.component').then((m) => m.EditVideoUnitComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.videoUnit.editVideoUnit.title', @@ -129,7 +123,7 @@ export const lectureUnitRoute: Routes = [ }, { path: 'online-units/:onlineUnitId/edit', - component: EditOnlineUnitComponent, + loadComponent: () => import('app/lecture/lecture-unit/lecture-unit-management/edit-online-unit/edit-online-unit.component').then((m) => m.EditOnlineUnitComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.onlineUnit.editOnlineUnit.title', @@ -137,7 +131,7 @@ export const lectureUnitRoute: Routes = [ }, { path: 'text-units/:textUnitId/edit', - component: EditTextUnitComponent, + loadComponent: () => import('app/lecture/lecture-unit/lecture-unit-management/edit-text-unit/edit-text-unit.component').then((m) => m.EditTextUnitComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.textUnit.editTextUnit.title', diff --git a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/lectureUnit.service.ts b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/lectureUnit.service.ts index 053b29704369..3c0f56576ba9 100644 --- a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/lectureUnit.service.ts +++ b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/lectureUnit.service.ts @@ -6,7 +6,7 @@ import { LectureUnitCompletionEvent } from 'app/overview/course-lectures/course- import { onError } from 'app/shared/util/global.utils'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { AttachmentUnit, IngestionState } from 'app/entities/lecture-unit/attachmentUnit.model'; import { AttachmentService } from 'app/lecture/attachment.service'; import { ExerciseUnit } from 'app/entities/lecture-unit/exerciseUnit.model'; @@ -19,13 +19,11 @@ type EntityArrayResponseType = HttpResponse; providedIn: 'root', }) export class LectureUnitService { - private resourceURL = 'api'; + private httpClient = inject(HttpClient); + private attachmentService = inject(AttachmentService); + private alertService = inject(AlertService); - constructor( - private httpClient: HttpClient, - private attachmentService: AttachmentService, - private alertService: AlertService, - ) {} + private resourceURL = 'api'; updateOrder(lectureId: number, lectureUnits: LectureUnit[]): Observable> { // Send an ordered list of ids of the lecture units diff --git a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-resource-dto.model.ts b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-resource-dto.model.ts index e601d3325fa6..6760fe301adc 100644 --- a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-resource-dto.model.ts +++ b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-resource-dto.model.ts @@ -2,6 +2,4 @@ export class OnlineResourceDTO { url: string; title: string; description: string; - - constructor() {} } diff --git a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.ts b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.ts index 241feda894e8..d140ab89d67e 100644 --- a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.ts +++ b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.ts @@ -1,6 +1,6 @@ import dayjs from 'dayjs/esm'; import { Component, OnChanges, computed, inject, input, output, viewChild } from '@angular/core'; -import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { AbstractControl, FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { faArrowLeft, faTimes } from '@fortawesome/free-solid-svg-icons'; import { map } from 'rxjs'; import { HttpResponse } from '@angular/common/http'; @@ -9,6 +9,10 @@ import { OnlineUnitService } from 'app/lecture/lecture-unit/lecture-unit-managem import { CompetencyLectureUnitLink } from 'app/entities/competency.model'; import { toSignal } from '@angular/core/rxjs-interop'; import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CompetencySelectionComponent } from 'app/shared/competency-selection/competency-selection.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface OnlineUnitFormData { name?: string; @@ -33,6 +37,7 @@ function urlValidator(control: AbstractControl) { @Component({ selector: 'jhi-online-unit-form', templateUrl: './online-unit-form.component.html', + imports: [FormsModule, ReactiveFormsModule, TranslateDirective, FormDateTimePickerComponent, CompetencySelectionComponent, FaIconComponent, ArtemisTranslatePipe], }) export class OnlineUnitFormComponent implements OnChanges { protected readonly faArrowLeft = faArrowLeft; diff --git a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/onlineUnit.service.ts b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/onlineUnit.service.ts index 7c6d1d4426af..5b7956e7cd98 100644 --- a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/onlineUnit.service.ts +++ b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/onlineUnit.service.ts @@ -1,5 +1,5 @@ import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { OnlineUnit } from 'app/entities/lecture-unit/onlineUnit.model'; import { LectureUnitService } from 'app/lecture/lecture-unit/lecture-unit-management/lectureUnit.service'; import { Observable } from 'rxjs'; @@ -12,12 +12,10 @@ type EntityResponseType = HttpResponse; providedIn: 'root', }) export class OnlineUnitService { - private resourceURL = 'api'; + private httpClient = inject(HttpClient); + private lectureUnitService = inject(LectureUnitService); - constructor( - private httpClient: HttpClient, - private lectureUnitService: LectureUnitService, - ) {} + private resourceURL = 'api'; create(onlineUnit: OnlineUnit, lectureId: number): Observable { return this.httpClient diff --git a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.ts b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.ts index 3ed05d37b8c1..50304d1fb183 100644 --- a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.ts +++ b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.ts @@ -1,6 +1,6 @@ import { Component, OnChanges, OnDestroy, OnInit, computed, inject, input, output, viewChild } from '@angular/core'; import dayjs from 'dayjs/esm'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { Router } from '@angular/router'; import { Subject, Subscription } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; @@ -9,6 +9,11 @@ import { faTimes } from '@fortawesome/free-solid-svg-icons'; import { CompetencyLectureUnitLink } from 'app/entities/competency.model'; import { toSignal } from '@angular/core/rxjs-interop'; import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CompetencySelectionComponent } from 'app/shared/competency-selection/competency-selection.component'; +import { MarkdownEditorMonacoComponent } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface TextUnitFormData { name?: string; @@ -20,9 +25,21 @@ export interface TextUnitFormData { @Component({ selector: 'jhi-text-unit-form', templateUrl: './text-unit-form.component.html', - styles: [], + imports: [ + FormsModule, + ReactiveFormsModule, + TranslateDirective, + FormDateTimePickerComponent, + CompetencySelectionComponent, + MarkdownEditorMonacoComponent, + FaIconComponent, + ArtemisTranslatePipe, + ], }) export class TextUnitFormComponent implements OnInit, OnChanges, OnDestroy { + private router = inject(Router); + private translateService = inject(TranslateService); + protected readonly faTimes = faTimes; formData = input(); @@ -54,11 +71,6 @@ export class TextUnitFormComponent implements OnInit, OnChanges, OnDestroy { private markdownChanges = new Subject(); private markdownChangesSubscription: Subscription; - constructor( - private router: Router, - private translateService: TranslateService, - ) {} - get nameControl() { return this.form.get('name'); } diff --git a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/textUnit.service.ts b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/textUnit.service.ts index eef971981c68..298d0f3b86dc 100644 --- a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/textUnit.service.ts +++ b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/textUnit.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { TextUnit } from 'app/entities/lecture-unit/textUnit.model'; import { Observable } from 'rxjs'; @@ -11,12 +11,10 @@ type EntityResponseType = HttpResponse; providedIn: 'root', }) export class TextUnitService { - private resourceURL = 'api'; + private httpClient = inject(HttpClient); + private lectureUnitService = inject(LectureUnitService); - constructor( - private httpClient: HttpClient, - private lectureUnitService: LectureUnitService, - ) {} + private resourceURL = 'api'; create(textUnit: TextUnit, lectureId: number): Observable { return this.httpClient diff --git a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/unit-creation-card/unit-creation-card.component.ts b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/unit-creation-card/unit-creation-card.component.ts index 5ab4782d70b8..6cdca8ffd0d3 100644 --- a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/unit-creation-card/unit-creation-card.component.ts +++ b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/unit-creation-card/unit-creation-card.component.ts @@ -2,10 +2,16 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { faCheck, faFileUpload, faLink, faScroll, faVideo } from '@fortawesome/free-solid-svg-icons'; import { DocumentationType } from 'app/shared/components/documentation-button/documentation-button.component'; import { LectureUnitType } from 'app/entities/lecture-unit/lectureUnit.model'; +import { RouterLink } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-unit-creation-card', templateUrl: './unit-creation-card.component.html', + imports: [RouterLink, FaIconComponent, TranslateDirective, DocumentationButtonComponent, ArtemisTranslatePipe], }) export class UnitCreationCardComponent { readonly documentationType: DocumentationType = 'Units'; diff --git a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/video-unit-form/video-unit-form.component.ts b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/video-unit-form/video-unit-form.component.ts index 0ffea72952dc..42e134552c15 100644 --- a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/video-unit-form/video-unit-form.component.ts +++ b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/video-unit-form/video-unit-form.component.ts @@ -1,11 +1,15 @@ import dayjs from 'dayjs/esm'; import { Component, computed, effect, inject, input, output, untracked, viewChild } from '@angular/core'; -import { AbstractControl, FormBuilder, FormGroup, ValidationErrors, Validators } from '@angular/forms'; +import { AbstractControl, FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, ValidationErrors, Validators } from '@angular/forms'; import urlParser from 'js-video-url-parser'; import { faArrowLeft, faTimes } from '@fortawesome/free-solid-svg-icons'; import { CompetencyLectureUnitLink } from 'app/entities/competency.model'; import { toSignal } from '@angular/core/rxjs-interop'; import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CompetencySelectionComponent } from 'app/shared/competency-selection/competency-selection.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface VideoUnitFormData { name?: string; @@ -58,6 +62,7 @@ function videoSourceUrlValidator(control: AbstractControl): ValidationErrors | u @Component({ selector: 'jhi-video-unit-form', templateUrl: './video-unit-form.component.html', + imports: [FormsModule, ReactiveFormsModule, TranslateDirective, FormDateTimePickerComponent, CompetencySelectionComponent, FaIconComponent, ArtemisTranslatePipe], }) export class VideoUnitFormComponent { protected readonly faTimes = faTimes; diff --git a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/videoUnit.service.ts b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/videoUnit.service.ts index d0eee745fdac..f17f73c3804b 100644 --- a/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/videoUnit.service.ts +++ b/src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/videoUnit.service.ts @@ -1,5 +1,5 @@ import { HttpClient, HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { VideoUnit } from 'app/entities/lecture-unit/videoUnit.model'; import { LectureUnitService } from 'app/lecture/lecture-unit/lecture-unit-management/lectureUnit.service'; import { Observable } from 'rxjs'; @@ -11,12 +11,10 @@ type EntityResponseType = HttpResponse; providedIn: 'root', }) export class VideoUnitService { - private resourceURL = 'api'; + private httpClient = inject(HttpClient); + private lectureUnitService = inject(LectureUnitService); - constructor( - private httpClient: HttpClient, - private lectureUnitService: LectureUnitService, - ) {} + private resourceURL = 'api'; create(videoUnit: VideoUnit, lectureId: number): Observable { return this.httpClient diff --git a/src/main/webapp/app/lecture/lecture-units/lecture-units.component.ts b/src/main/webapp/app/lecture/lecture-units/lecture-units.component.ts index d9c11741275a..6bce60f7cc38 100644 --- a/src/main/webapp/app/lecture/lecture-units/lecture-units.component.ts +++ b/src/main/webapp/app/lecture/lecture-units/lecture-units.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit, ViewChild, computed, signal, viewChild } from '@angular/core'; +import { Component, Input, OnInit, ViewChild, computed, inject, signal, viewChild } from '@angular/core'; import { Lecture } from 'app/entities/lecture.model'; import { TextUnit } from 'app/entities/lecture-unit/textUnit.model'; import { VideoUnit } from 'app/entities/lecture-unit/videoUnit.model'; @@ -21,12 +21,32 @@ import { HttpErrorResponse } from '@angular/common/http'; import { AttachmentUnitService } from 'app/lecture/lecture-unit/lecture-unit-management/attachmentUnit.service'; import dayjs from 'dayjs/esm'; import { ActivatedRoute } from '@angular/router'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { UnitCreationCardComponent } from '../lecture-unit/lecture-unit-management/unit-creation-card/unit-creation-card.component'; +import { CreateExerciseUnitComponent } from '../lecture-unit/lecture-unit-management/create-exercise-unit/create-exercise-unit.component'; @Component({ selector: 'jhi-lecture-update-units', templateUrl: './lecture-units.component.html', + imports: [ + TranslateDirective, + LectureUnitManagementComponent, + UnitCreationCardComponent, + TextUnitFormComponent, + VideoUnitFormComponent, + OnlineUnitFormComponent, + AttachmentUnitFormComponent, + CreateExerciseUnitComponent, + ], }) export class LectureUpdateUnitsComponent implements OnInit { + protected activatedRoute = inject(ActivatedRoute); + protected alertService = inject(AlertService); + protected textUnitService = inject(TextUnitService); + protected videoUnitService = inject(VideoUnitService); + protected onlineUnitService = inject(OnlineUnitService); + protected attachmentUnitService = inject(AttachmentUnitService); + @Input() lecture: Lecture; @ViewChild(LectureUnitManagementComponent, { static: false }) unitManagementComponent: LectureUnitManagementComponent; @@ -60,15 +80,6 @@ export class LectureUpdateUnitsComponent implements OnInit { onlineUnitFormData: OnlineUnitFormData; attachmentUnitFormData: AttachmentUnitFormData; - constructor( - protected activatedRoute: ActivatedRoute, - protected alertService: AlertService, - protected textUnitService: TextUnitService, - protected videoUnitService: VideoUnitService, - protected onlineUnitService: OnlineUnitService, - protected attachmentUnitService: AttachmentUnitService, - ) {} - ngOnInit() { this.activatedRoute.queryParams.subscribe((params) => { // Checks if the exercise unit form should be opened initially, i.e. coming back from the exercise creation diff --git a/src/main/webapp/app/lecture/lecture-update.component.ts b/src/main/webapp/app/lecture/lecture-update.component.ts index 092e1348c536..a89242a2e80b 100644 --- a/src/main/webapp/app/lecture/lecture-update.component.ts +++ b/src/main/webapp/app/lecture/lecture-update.component.ts @@ -20,11 +20,32 @@ import cloneDeep from 'lodash-es/cloneDeep'; import { FormSectionStatus, FormStatusBarComponent } from 'app/forms/form-status-bar/form-status-bar.component'; import { LectureAttachmentsComponent } from 'app/lecture/lecture-attachments.component'; import { LectureUpdateUnitsComponent } from 'app/lecture/lecture-units/lecture-units.component'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from '../shared/language/translate.directive'; +import { DocumentationButtonComponent } from '../shared/components/documentation-button/documentation-button.component'; +import { MarkdownEditorMonacoComponent } from '../shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisTranslatePipe } from '../shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-lecture-update', templateUrl: './lecture-update.component.html', styleUrls: ['./lecture-update.component.scss'], + imports: [ + FormsModule, + TranslateDirective, + DocumentationButtonComponent, + FormStatusBarComponent, + LectureTitleChannelNameComponent, + MarkdownEditorMonacoComponent, + LectureUpdatePeriodComponent, + FaIconComponent, + LectureAttachmentsComponent, + LectureUpdateUnitsComponent, + NgbTooltip, + ArtemisTranslatePipe, + ], }) export class LectureUpdateComponent implements OnInit, OnDestroy { protected readonly documentationType: DocumentationType = 'Lecture'; diff --git a/src/main/webapp/app/lecture/lecture.component.ts b/src/main/webapp/app/lecture/lecture.component.ts index 7bbe6d1b18b3..13ca7d9ebd61 100644 --- a/src/main/webapp/app/lecture/lecture.component.ts +++ b/src/main/webapp/app/lecture/lecture.component.ts @@ -1,13 +1,13 @@ import { PROFILE_IRIS } from 'app/app.constants'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import dayjs from 'dayjs/esm'; -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { filter, map } from 'rxjs/operators'; import { LectureService } from './lecture.service'; import { Lecture } from 'app/entities/lecture.model'; -import { ActivatedRoute, Router } from '@angular/router'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; +import { NgbDropdown, NgbDropdownMenu, NgbDropdownToggle, NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { onError } from 'app/shared/util/global.utils'; import { AlertService } from 'app/core/util/alert.service'; import { faFile, faFileExport, faFileImport, faFilter, faPencilAlt, faPlus, faPuzzlePiece, faSort, faTrash } from '@fortawesome/free-solid-svg-icons'; @@ -17,6 +17,15 @@ import { DocumentationType } from 'app/shared/components/documentation-button/do import { SortService } from 'app/shared/service/sort.service'; import { IrisSettingsService } from 'app/iris/settings/shared/iris-settings.service'; import { IngestionState } from 'app/entities/lecture-unit/attachmentUnit.model'; +import { TranslateDirective } from '../shared/language/translate.directive'; +import { DocumentationButtonComponent } from '../shared/components/documentation-button/documentation-button.component'; +import { NgClass } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { SortDirective } from '../shared/sort/sort.directive'; +import { SortByDirective } from '../shared/sort/sort-by.directive'; +import { DeleteButtonDirective } from '../shared/delete-dialog/delete-button.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { HtmlForMarkdownPipe } from '../shared/pipes/html-for-markdown.pipe'; export enum LectureDateFilter { PAST = 'filterPast', @@ -28,8 +37,32 @@ export enum LectureDateFilter { @Component({ selector: 'jhi-lecture', templateUrl: './lecture.component.html', + imports: [ + TranslateDirective, + DocumentationButtonComponent, + NgbDropdown, + NgbDropdownToggle, + NgClass, + FaIconComponent, + NgbDropdownMenu, + RouterLink, + SortDirective, + SortByDirective, + DeleteButtonDirective, + ArtemisDatePipe, + HtmlForMarkdownPipe, + ], }) export class LectureComponent implements OnInit, OnDestroy { + protected lectureService = inject(LectureService); + private route = inject(ActivatedRoute); + private router = inject(Router); + private alertService = inject(AlertService); + private modalService = inject(NgbModal); + private sortService = inject(SortService); + private profileService = inject(ProfileService); + private irisSettingsService = inject(IrisSettingsService); + lectures: Lecture[]; filteredLectures: Lecture[]; courseId: number; @@ -63,16 +96,7 @@ export class LectureComponent implements OnInit, OnDestroy { private profileInfoSubscription: Subscription; - constructor( - protected lectureService: LectureService, - private route: ActivatedRoute, - private router: Router, - private alertService: AlertService, - private modalService: NgbModal, - private sortService: SortService, - private profileService: ProfileService, - private irisSettingsService: IrisSettingsService, - ) { + constructor() { this.predicate = 'id'; this.ascending = true; } diff --git a/src/main/webapp/app/lecture/lecture.module.ts b/src/main/webapp/app/lecture/lecture.module.ts index 83afd92a0e56..ac06b95dea21 100644 --- a/src/main/webapp/app/lecture/lecture.module.ts +++ b/src/main/webapp/app/lecture/lecture.module.ts @@ -17,7 +17,7 @@ import { TitleChannelNameModule } from 'app/shared/form/title-channel-name/title import { LectureTitleChannelNameComponent } from 'app/lecture/lecture-title-channel-name.component'; import { DetailModule } from 'app/detail-overview-list/detail.module'; import { CompetencyFormComponent } from 'app/course/competencies/forms/competency/competency-form.component'; -import { FormsModule } from 'app/forms/forms.module'; +import { ArtemisFormsModule } from 'app/forms/artemis-forms.module'; import { LectureUpdateUnitsComponent } from 'app/lecture/lecture-units/lecture-units.component'; import { LectureUpdatePeriodComponent } from 'app/lecture/lecture-period/lecture-period.component'; @@ -36,9 +36,7 @@ const ENTITY_STATES = [...lectureRoute]; TitleChannelNameModule, DetailModule, CompetencyFormComponent, - FormsModule, - ], - declarations: [ + ArtemisFormsModule, LectureComponent, LectureDetailComponent, LectureImportComponent, diff --git a/src/main/webapp/app/lecture/lecture.route.ts b/src/main/webapp/app/lecture/lecture.route.ts index aa36380de4a1..12619243b61f 100644 --- a/src/main/webapp/app/lecture/lecture.route.ts +++ b/src/main/webapp/app/lecture/lecture.route.ts @@ -1,27 +1,24 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpResponse } from '@angular/common/http'; import { ActivatedRouteSnapshot, Resolve, Routes } from '@angular/router'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; import { Observable, of } from 'rxjs'; import { filter, map } from 'rxjs/operators'; import { LectureService } from './lecture.service'; -import { LectureComponent } from './lecture.component'; -import { LectureDetailComponent } from './lecture-detail.component'; -import { LectureUpdateComponent } from './lecture-update.component'; + import { Lecture } from 'app/entities/lecture.model'; -import { LectureAttachmentsComponent } from 'app/lecture/lecture-attachments.component'; + import { Authority } from 'app/shared/constants/authority.constants'; import { lectureUnitRoute } from 'app/lecture/lecture-unit/lecture-unit-management/lecture-unit-management.route'; import { CourseManagementResolve } from 'app/course/manage/course-management-resolve.service'; -import { CourseManagementTabBarComponent } from 'app/course/manage/course-management-tab-bar/course-management-tab-bar.component'; -import { PdfPreviewComponent } from 'app/lecture/pdf-preview/pdf-preview.component'; + import { Attachment } from 'app/entities/attachment.model'; import { AttachmentService } from 'app/lecture/attachment.service'; import { hasLectureUnsavedChangesGuard } from './hasLectureUnsavedChanges.guard'; @Injectable({ providedIn: 'root' }) export class LectureResolve implements Resolve { - constructor(private lectureService: LectureService) {} + private lectureService = inject(LectureService); resolve(route: ActivatedRouteSnapshot): Observable { const lectureId = route.params['lectureId']; @@ -37,7 +34,7 @@ export class LectureResolve implements Resolve { @Injectable({ providedIn: 'root' }) export class AttachmentResolve implements Resolve { - constructor(private attachmentService: AttachmentService) {} + private attachmentService = inject(AttachmentService); resolve(route: ActivatedRouteSnapshot): Observable { const attachmentId = route.params['attachmentId']; @@ -54,11 +51,11 @@ export class AttachmentResolve implements Resolve { export const lectureRoute: Routes = [ { path: ':courseId/lectures', - component: CourseManagementTabBarComponent, + loadComponent: () => import('app/course/manage/course-management-tab-bar/course-management-tab-bar.component').then((m) => m.CourseManagementTabBarComponent), children: [ { path: '', - component: LectureComponent, + loadComponent: () => import('./lecture.component').then((m) => m.LectureComponent), resolve: { course: CourseManagementResolve, }, @@ -77,7 +74,7 @@ export const lectureRoute: Routes = [ children: [ { path: 'new', - component: LectureUpdateComponent, + loadComponent: () => import('./lecture-update.component').then((m) => m.LectureUpdateComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'global.generic.create', @@ -86,7 +83,7 @@ export const lectureRoute: Routes = [ }, { path: ':lectureId', - component: LectureDetailComponent, + loadComponent: () => import('./lecture-detail.component').then((m) => m.LectureDetailComponent), resolve: { lecture: LectureResolve, }, @@ -104,7 +101,7 @@ export const lectureRoute: Routes = [ children: [ { path: 'attachments', - component: LectureAttachmentsComponent, + loadComponent: () => import('app/lecture/lecture-attachments.component').then((m) => m.LectureAttachmentsComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.lecture.attachments.title', @@ -117,7 +114,7 @@ export const lectureRoute: Routes = [ children: [ { path: ':attachmentId', - component: PdfPreviewComponent, + loadComponent: () => import('app/lecture/pdf-preview/pdf-preview.component').then((m) => m.PdfPreviewComponent), resolve: { attachment: AttachmentResolve, course: CourseManagementResolve, @@ -127,7 +124,7 @@ export const lectureRoute: Routes = [ }, { path: 'edit', - component: LectureUpdateComponent, + loadComponent: () => import('./lecture-update.component').then((m) => m.LectureUpdateComponent), data: { authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'global.generic.edit', diff --git a/src/main/webapp/app/lecture/lecture.service.ts b/src/main/webapp/app/lecture/lecture.service.ts index 118ef77172d8..07d926dafcdf 100644 --- a/src/main/webapp/app/lecture/lecture.service.ts +++ b/src/main/webapp/app/lecture/lecture.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map, tap } from 'rxjs/operators'; @@ -15,14 +15,12 @@ type EntityArrayResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class LectureService { - public resourceUrl = 'api/lectures'; + protected http = inject(HttpClient); + private accountService = inject(AccountService); + private lectureUnitService = inject(LectureUnitService); + private entityTitleService = inject(EntityTitleService); - constructor( - protected http: HttpClient, - private accountService: AccountService, - private lectureUnitService: LectureUnitService, - private entityTitleService: EntityTitleService, - ) {} + public resourceUrl = 'api/lectures'; create(lecture: Lecture): Observable { const copy = this.convertLectureDatesFromClient(lecture); diff --git a/src/main/webapp/app/lecture/pdf-preview/pdf-preview-enlarged-canvas/pdf-preview-enlarged-canvas.component.ts b/src/main/webapp/app/lecture/pdf-preview/pdf-preview-enlarged-canvas/pdf-preview-enlarged-canvas.component.ts index 789aba78aefb..4c2c3242d541 100644 --- a/src/main/webapp/app/lecture/pdf-preview/pdf-preview-enlarged-canvas/pdf-preview-enlarged-canvas.component.ts +++ b/src/main/webapp/app/lecture/pdf-preview/pdf-preview-enlarged-canvas/pdf-preview-enlarged-canvas.component.ts @@ -7,7 +7,6 @@ type NavigationDirection = 'next' | 'prev'; selector: 'jhi-pdf-preview-enlarged-canvas-component', templateUrl: './pdf-preview-enlarged-canvas.component.html', styleUrls: ['./pdf-preview-enlarged-canvas.component.scss'], - standalone: true, imports: [ArtemisSharedModule], }) export class PdfPreviewEnlargedCanvasComponent { @@ -29,13 +28,10 @@ export class PdfPreviewEnlargedCanvasComponent { isEnlargedViewOutput = output(); constructor() { - effect( - () => { - this.enlargedContainer().nativeElement.style.top = `${this.pdfContainer().scrollTop}px`; - this.displayEnlargedCanvas(this.originalCanvas()!); - }, - { allowSignalWrites: true }, - ); + effect(() => { + this.enlargedContainer().nativeElement.style.top = `${this.pdfContainer().scrollTop}px`; + this.displayEnlargedCanvas(this.originalCanvas()!); + }); } /** diff --git a/src/main/webapp/app/lecture/pdf-preview/pdf-preview-thumbnail-grid/pdf-preview-thumbnail-grid.component.ts b/src/main/webapp/app/lecture/pdf-preview/pdf-preview-thumbnail-grid/pdf-preview-thumbnail-grid.component.ts index 84a220ad8cba..30dababea0cf 100644 --- a/src/main/webapp/app/lecture/pdf-preview/pdf-preview-thumbnail-grid/pdf-preview-thumbnail-grid.component.ts +++ b/src/main/webapp/app/lecture/pdf-preview/pdf-preview-thumbnail-grid/pdf-preview-thumbnail-grid.component.ts @@ -10,7 +10,6 @@ import { PdfPreviewEnlargedCanvasComponent } from 'app/lecture/pdf-preview/pdf-p selector: 'jhi-pdf-preview-thumbnail-grid-component', templateUrl: './pdf-preview-thumbnail-grid.component.html', styleUrls: ['./pdf-preview-thumbnail-grid.component.scss'], - standalone: true, imports: [ArtemisSharedModule, PdfPreviewEnlargedCanvasComponent], }) export class PdfPreviewThumbnailGridComponent { @@ -37,12 +36,9 @@ export class PdfPreviewThumbnailGridComponent { private readonly alertService = inject(AlertService); constructor() { - effect( - () => { - this.loadOrAppendPdf(this.currentPdfUrl()!, this.appendFile()); - }, - { allowSignalWrites: true }, - ); + effect(() => { + this.loadOrAppendPdf(this.currentPdfUrl()!, this.appendFile()); + }); } /** diff --git a/src/main/webapp/app/lecture/pdf-preview/pdf-preview.component.ts b/src/main/webapp/app/lecture/pdf-preview/pdf-preview.component.ts index d3271475e580..60abfb7eaa3c 100644 --- a/src/main/webapp/app/lecture/pdf-preview/pdf-preview.component.ts +++ b/src/main/webapp/app/lecture/pdf-preview/pdf-preview.component.ts @@ -22,7 +22,6 @@ import { PDFDocument } from 'pdf-lib'; selector: 'jhi-pdf-preview-component', templateUrl: './pdf-preview.component.html', styleUrls: ['./pdf-preview.component.scss'], - standalone: true, imports: [ArtemisSharedModule, PdfPreviewThumbnailGridComponent], }) export class PdfPreviewComponent implements OnInit, OnDestroy { diff --git a/src/main/webapp/app/localci/build-agents/build-agent-details/build-agent-details/build-agent-details.component.ts b/src/main/webapp/app/localci/build-agents/build-agent-details/build-agent-details/build-agent-details.component.ts index 3f1b1628d951..07defd4cac33 100644 --- a/src/main/webapp/app/localci/build-agents/build-agent-details/build-agent-details/build-agent-details.component.ts +++ b/src/main/webapp/app/localci/build-agents/build-agent-details/build-agent-details/build-agent-details.component.ts @@ -18,7 +18,6 @@ import { SubmissionResultStatusModule } from 'app/overview/submission-result-sta selector: 'jhi-build-agent-details', templateUrl: './build-agent-details.component.html', styleUrl: './build-agent-details.component.scss', - standalone: true, imports: [ArtemisSharedModule, NgxDatatableModule, ArtemisDataTableModule, SubmissionResultStatusModule], }) export class BuildAgentDetailsComponent implements OnInit, OnDestroy { diff --git a/src/main/webapp/app/localci/build-agents/build-agent-summary/build-agent-summary.component.ts b/src/main/webapp/app/localci/build-agents/build-agent-summary/build-agent-summary.component.ts index b3a9e8fcf5c8..08d8772163bd 100644 --- a/src/main/webapp/app/localci/build-agents/build-agent-summary/build-agent-summary.component.ts +++ b/src/main/webapp/app/localci/build-agents/build-agent-summary/build-agent-summary.component.ts @@ -15,7 +15,6 @@ import { NgxDatatableModule } from '@siemens/ngx-datatable'; @Component({ selector: 'jhi-build-agents', - standalone: true, templateUrl: './build-agent-summary.component.html', styleUrl: './build-agent-summary.component.scss', imports: [ArtemisSharedModule, NgxDatatableModule, ArtemisDataTableModule], diff --git a/src/main/webapp/app/localci/build-queue/build-queue.component.ts b/src/main/webapp/app/localci/build-queue/build-queue.component.ts index 45b337ba1bd1..0783f89952ff 100644 --- a/src/main/webapp/app/localci/build-queue/build-queue.component.ts +++ b/src/main/webapp/app/localci/build-queue/build-queue.component.ts @@ -1,5 +1,5 @@ -import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { Component, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { BuildJob, BuildJobStatistics, FinishedBuildJob, SpanType } from 'app/entities/programming/build-job.model'; import { faAngleDown, faAngleRight, faCircleCheck, faExclamationCircle, faExclamationTriangle, faFilter, faSort, faSync, faTimes } from '@fortawesome/free-solid-svg-icons'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; @@ -13,13 +13,28 @@ import { HttpErrorResponse, HttpHeaders, HttpParams, HttpResponse } from '@angul import { AlertService } from 'app/core/util/alert.service'; import dayjs from 'dayjs/esm'; import { GraphColors } from 'app/entities/statistics.model'; -import { Color, ScaleType } from '@swimlane/ngx-charts'; +import { Color, PieChartModule, ScaleType } from '@swimlane/ngx-charts'; import { NgxChartsSingleSeriesDataEntry } from 'app/shared/chart/ngx-charts-datatypes'; -import { NgbModal, NgbTypeahead } from '@ng-bootstrap/ng-bootstrap'; +import { NgbCollapse, NgbModal, NgbPagination, NgbTypeahead } from '@ng-bootstrap/ng-bootstrap'; import { LocalStorageService } from 'ngx-webstorage'; import { Observable, OperatorFunction, Subject, Subscription, merge } from 'rxjs'; import { UI_RELOAD_TIME } from 'app/shared/constants/exercise-exam-constants'; import { BuildLogEntry, BuildLogLines } from 'app/entities/programming/build-log.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { DataTableComponent } from 'app/shared/data-table/data-table.component'; +import { NgxDatatableModule } from '@siemens/ngx-datatable'; +import { NgClass } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { ResultComponent } from '../../exercises/shared/result/result.component'; +import { ItemCountComponent } from 'app/shared/pagination/item-count.component'; +import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { ArtemisDurationFromSecondsPipe } from 'app/shared/pipes/artemis-duration-from-seconds.pipe'; export class FinishedBuildJobFilter { status?: string = undefined; @@ -105,8 +120,37 @@ export enum FinishedBuildJobFilterStorageKey { selector: 'jhi-build-queue', templateUrl: './build-queue.component.html', styleUrl: './build-queue.component.scss', + imports: [ + TranslateDirective, + HelpIconComponent, + FaIconComponent, + NgbCollapse, + PieChartModule, + DataTableComponent, + NgxDatatableModule, + NgClass, + RouterLink, + FormsModule, + SortDirective, + SortByDirective, + ResultComponent, + ItemCountComponent, + NgbPagination, + NgbTypeahead, + FormDateTimePickerComponent, + ArtemisDatePipe, + ArtemisTranslatePipe, + ArtemisDurationFromSecondsPipe, + ], }) export class BuildQueueComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private websocketService = inject(JhiWebsocketService); + private buildQueueService = inject(BuildQueueService); + private alertService = inject(AlertService); + private modalService = inject(NgbModal); + private localStorage = inject(LocalStorageService); + protected readonly TriggeredByPushTo = TriggeredByPushTo; queuedBuildJobs: BuildJob[] = []; @@ -163,15 +207,6 @@ export class BuildQueueComponent implements OnInit, OnDestroy { rawBuildLogs: BuildLogLines[] = []; displayedBuildJobId?: string; - constructor( - private route: ActivatedRoute, - private websocketService: JhiWebsocketService, - private buildQueueService: BuildQueueService, - private alertService: AlertService, - private modalService: NgbModal, - private localStorage: LocalStorageService, - ) {} - ngOnInit() { this.buildStatusFilterValues = Object.values(BuildJobStatusFilter); this.loadQueue(); diff --git a/src/main/webapp/app/localci/build-queue/build-queue.service.ts b/src/main/webapp/app/localci/build-queue/build-queue.service.ts index a004acb9eaa8..bd76991f1d22 100644 --- a/src/main/webapp/app/localci/build-queue/build-queue.service.ts +++ b/src/main/webapp/app/localci/build-queue/build-queue.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -11,11 +11,12 @@ import { BuildLogEntry } from 'app/entities/programming/build-log.model'; @Injectable({ providedIn: 'root' }) export class BuildQueueService { + private http = inject(HttpClient); + public resourceUrl = 'api'; public adminResourceUrl = 'api/admin'; nestedDtoKey = 'pageable'; - constructor(private http: HttpClient) {} /** * Get all build jobs of a course in the queue * @param courseId diff --git a/src/main/webapp/app/localci/localci-guard.service.ts b/src/main/webapp/app/localci/localci-guard.service.ts index 407e80d4f3a8..35cb0aa8d6c1 100644 --- a/src/main/webapp/app/localci/localci-guard.service.ts +++ b/src/main/webapp/app/localci/localci-guard.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { CanActivate, Router } from '@angular/router'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; @@ -8,11 +8,10 @@ import { PROFILE_LOCALCI } from 'app/app.constants'; providedIn: 'root', }) export class LocalCIGuard implements CanActivate { + private profileService = inject(ProfileService); + private router = inject(Router); + localCIActive: boolean = false; - constructor( - private profileService: ProfileService, - private router: Router, - ) {} async canActivate(): Promise { this.profileService.getProfileInfo().subscribe((profileInfo) => { diff --git a/src/main/webapp/app/localvc/commit-details-view/commit-details-view.component.ts b/src/main/webapp/app/localvc/commit-details-view/commit-details-view.component.ts index b147bd0892cd..e5e0d49558a0 100644 --- a/src/main/webapp/app/localvc/commit-details-view/commit-details-view.component.ts +++ b/src/main/webapp/app/localvc/commit-details-view/commit-details-view.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { ProgrammingExerciseGitDiffReport } from 'app/entities/programming-exercise-git-diff-report.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { ProgrammingExerciseParticipationService } from 'app/exercises/programming/manage/services/programming-exercise-participation.service'; @@ -7,12 +7,20 @@ import { ActivatedRoute } from '@angular/router'; import { CommitInfo } from 'app/entities/programming/programming-submission.model'; import dayjs from 'dayjs/esm'; import { catchError, map, tap } from 'rxjs/operators'; +import { GitDiffReportComponent } from '../../exercises/programming/git-diff-report/git-diff-report.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-commit-details-view', templateUrl: './commit-details-view.component.html', + imports: [GitDiffReportComponent, ArtemisDatePipe, ArtemisTranslatePipe], }) export class CommitDetailsViewComponent implements OnDestroy, OnInit { + private programmingExerciseService = inject(ProgrammingExerciseService); + private programmingExerciseParticipationService = inject(ProgrammingExerciseParticipationService); + private route = inject(ActivatedRoute); + report: ProgrammingExerciseGitDiffReport; exerciseId: number; participationId?: number; @@ -34,12 +42,6 @@ export class CommitDetailsViewComponent implements OnDestroy, OnInit { paramSub: Subscription; participationSub: Subscription; - constructor( - private programmingExerciseService: ProgrammingExerciseService, - private programmingExerciseParticipationService: ProgrammingExerciseParticipationService, - private route: ActivatedRoute, - ) {} - ngOnDestroy(): void { this.repoFilesSubscription?.unsubscribe(); this.participationRepoFilesAtLeftCommitSubscription?.unsubscribe(); diff --git a/src/main/webapp/app/localvc/commit-history/commit-history.component.ts b/src/main/webapp/app/localvc/commit-history/commit-history.component.ts index f734f9f2eec3..359c3a4f9298 100644 --- a/src/main/webapp/app/localvc/commit-history/commit-history.component.ts +++ b/src/main/webapp/app/localvc/commit-history/commit-history.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Subscription } from 'rxjs'; import dayjs from 'dayjs/esm'; @@ -11,12 +11,18 @@ import { ProgrammingExercise } from 'app/entities/programming/programming-exerci import { SolutionProgrammingExerciseParticipation } from 'app/entities/participation/solution-programming-exercise-participation.model'; import { TemplateProgrammingExerciseParticipation } from 'app/entities/participation/template-programming-exercise-participation.model'; import { ProgrammingExerciseStudentParticipation } from 'app/entities/participation/programming-exercise-student-participation.model'; +import { CommitsInfoComponent } from '../../exercises/programming/shared/commits-info/commits-info.component'; @Component({ selector: 'jhi-commit-history', templateUrl: './commit-history.component.html', + imports: [CommitsInfoComponent], }) export class CommitHistoryComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private programmingExerciseParticipationService = inject(ProgrammingExerciseParticipationService); + private programmingExerciseService = inject(ProgrammingExerciseService); + readonly PROGRAMMING = ExerciseType.PROGRAMMING; readonly dayjs = dayjs; @@ -34,12 +40,6 @@ export class CommitHistoryComponent implements OnInit, OnDestroy { isTestRepository = false; - constructor( - private route: ActivatedRoute, - private programmingExerciseParticipationService: ProgrammingExerciseParticipationService, - private programmingExerciseService: ProgrammingExerciseService, - ) {} - ngOnDestroy() { this.paramSub?.unsubscribe(); this.commitsInfoSubscription?.unsubscribe(); diff --git a/src/main/webapp/app/localvc/localvc-guard.service.ts b/src/main/webapp/app/localvc/localvc-guard.service.ts index 43e6a57346af..3d41962de6a9 100644 --- a/src/main/webapp/app/localvc/localvc-guard.service.ts +++ b/src/main/webapp/app/localvc/localvc-guard.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { CanActivate, Router } from '@angular/router'; import { firstValueFrom } from 'rxjs'; @@ -9,11 +9,10 @@ import { PROFILE_LOCALVC } from 'app/app.constants'; providedIn: 'root', }) export class LocalVCGuard implements CanActivate { + private profileService = inject(ProfileService); + private router = inject(Router); + localVCActive: boolean = false; - constructor( - private profileService: ProfileService, - private router: Router, - ) {} async canActivate(): Promise { try { diff --git a/src/main/webapp/app/localvc/repository-view/repository-view.component.ts b/src/main/webapp/app/localvc/repository-view/repository-view.component.ts index 8e0b537d7abd..6bd2912052b1 100644 --- a/src/main/webapp/app/localvc/repository-view/repository-view.component.ts +++ b/src/main/webapp/app/localvc/repository-view/repository-view.component.ts @@ -1,6 +1,6 @@ -import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { Component, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; import { Observable, Subscription } from 'rxjs'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { DomainService } from 'app/exercises/programming/shared/code-editor/service/code-editor-domain.service'; import { ExerciseType, getCourseFromExercise } from 'app/entities/exercise.model'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; @@ -18,12 +18,40 @@ import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; import { Feedback } from 'app/entities/feedback.model'; import { PROFILE_LOCALVC } from 'app/app.constants'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ButtonComponent } from 'app/shared/components/button.component'; +import { ResultComponent } from 'app/exercises/shared/result/result.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { CodeButtonComponent } from 'app/shared/components/code-button/code-button.component'; +import { ProgrammingExerciseStudentRepoDownloadComponent } from 'app/exercises/programming/shared/actions/programming-exercise-student-repo-download.component'; +import { ProgrammingExerciseInstructorRepoDownloadComponent } from 'app/exercises/programming/shared/actions/programming-exercise-instructor-repo-download.component'; +import { ProgrammingExerciseInstructionComponent } from 'app/exercises/programming/shared/instructions-render/programming-exercise-instruction.component'; @Component({ selector: 'jhi-repository-view', templateUrl: './repository-view.component.html', + imports: [ + CodeEditorContainerComponent, + TranslateDirective, + ButtonComponent, + ResultComponent, + RouterLink, + FaIconComponent, + CodeButtonComponent, + ProgrammingExerciseStudentRepoDownloadComponent, + ProgrammingExerciseInstructorRepoDownloadComponent, + ProgrammingExerciseInstructionComponent, + ], }) export class RepositoryViewComponent implements OnInit, OnDestroy { + private accountService = inject(AccountService); + domainService = inject(DomainService); + private route = inject(ActivatedRoute); + private profileService = inject(ProfileService); + private programmingExerciseParticipationService = inject(ProgrammingExerciseParticipationService); + private programmingExerciseService = inject(ProgrammingExerciseService); + private router = inject(Router); + @ViewChild(CodeEditorContainerComponent, { static: false }) codeEditorContainer: CodeEditorContainerComponent; PROGRAMMING = ExerciseType.PROGRAMMING; @@ -56,16 +84,6 @@ export class RepositoryViewComponent implements OnInit, OnDestroy { participationWithLatestResultSub: Subscription; differentParticipationSub: Subscription; - constructor( - private accountService: AccountService, - public domainService: DomainService, - private route: ActivatedRoute, - private profileService: ProfileService, - private programmingExerciseParticipationService: ProgrammingExerciseParticipationService, - private programmingExerciseService: ProgrammingExerciseService, - private router: Router, - ) {} - /** * Unsubscribe from all subscriptions when the component is destroyed */ diff --git a/src/main/webapp/app/localvc/vcs-repository-access-log-view/vcs-repository-access-log-view.component.ts b/src/main/webapp/app/localvc/vcs-repository-access-log-view/vcs-repository-access-log-view.component.ts index 0f72191f8405..41f318a77a18 100644 --- a/src/main/webapp/app/localvc/vcs-repository-access-log-view/vcs-repository-access-log-view.component.ts +++ b/src/main/webapp/app/localvc/vcs-repository-access-log-view/vcs-repository-access-log-view.component.ts @@ -10,7 +10,6 @@ import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-vcs-repository-access-log-view', templateUrl: './vcs-repository-access-log-view.component.html', - standalone: true, imports: [TranslateDirective], }) export class VcsRepositoryAccessLogViewComponent { @@ -32,16 +31,13 @@ export class VcsRepositoryAccessLogViewComponent { private readonly repositoryType = computed(() => String(this.params().repositoryType)); constructor() { - effect( - async () => { - if (this.participationId()) { - await this.loadVcsAccessLogForParticipation(this.participationId()!); - } else { - await this.loadVcsAccessLog(this.exerciseId(), this.repositoryType()); - } - }, - { allowSignalWrites: true }, - ); + effect(async () => { + if (this.participationId()) { + await this.loadVcsAccessLogForParticipation(this.participationId()!); + } else { + await this.loadVcsAccessLog(this.exerciseId(), this.repositoryType()); + } + }); } public async loadVcsAccessLogForParticipation(participationId: number) { diff --git a/src/main/webapp/app/lti/lti-course-card.component.ts b/src/main/webapp/app/lti/lti-course-card.component.ts index bb66951dfd2a..4bb1323eb492 100644 --- a/src/main/webapp/app/lti/lti-course-card.component.ts +++ b/src/main/webapp/app/lti/lti-course-card.component.ts @@ -10,7 +10,6 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; selector: 'jhi-overview-lti-course-card', templateUrl: './lti-course-card.component.html', styleUrls: ['../overview/course-card.scss'], - standalone: true, imports: [RouterLink, NgStyle, ArtemisSharedModule], }) export class LtiCourseCardComponent { diff --git a/src/main/webapp/app/lti/lti.module.ts b/src/main/webapp/app/lti/lti.module.ts index aa71f406cbaa..4d4b6ee9a02d 100644 --- a/src/main/webapp/app/lti/lti.module.ts +++ b/src/main/webapp/app/lti/lti.module.ts @@ -3,14 +3,13 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; import { RouterModule } from '@angular/router'; import { Lti13ExerciseLaunchComponent } from 'app/lti/lti13-exercise-launch.component'; import { Lti13DynamicRegistrationComponent } from 'app/lti/lti13-dynamic-registration.component'; -import { ArtemisCoreModule } from 'app/core/core.module'; import { ltiLaunchState } from './lti.route'; import { Lti13DeepLinkingComponent } from 'app/lti/lti13-deep-linking.component'; import { FormsModule } from '@angular/forms'; import { Lti13SelectContentComponent } from 'app/lti/lti13-select-content.component'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { LtiCoursesComponent } from 'app/lti/lti13-select-course.component'; -import { ArtemisSharedLibsModule } from 'app/shared/shared-libs.module'; + import { LtiCourseCardComponent } from 'app/lti/lti-course-card.component'; const LTI_LAUNCH_ROUTES = [...ltiLaunchState]; @@ -18,11 +17,9 @@ const LTI_LAUNCH_ROUTES = [...ltiLaunchState]; @NgModule({ imports: [ RouterModule.forChild(LTI_LAUNCH_ROUTES), - ArtemisCoreModule, ArtemisSharedModule, FormsModule, ArtemisSharedComponentModule, - ArtemisSharedLibsModule, Lti13ExerciseLaunchComponent, Lti13DynamicRegistrationComponent, Lti13DeepLinkingComponent, diff --git a/src/main/webapp/app/lti/lti.route.ts b/src/main/webapp/app/lti/lti.route.ts index 4c93660e7fd4..c637ed7e9088 100644 --- a/src/main/webapp/app/lti/lti.route.ts +++ b/src/main/webapp/app/lti/lti.route.ts @@ -1,37 +1,33 @@ import { Routes } from '@angular/router'; -import { Lti13ExerciseLaunchComponent } from 'app/lti/lti13-exercise-launch.component'; -import { Lti13DynamicRegistrationComponent } from 'app/lti/lti13-dynamic-registration.component'; -import { Lti13DeepLinkingComponent } from 'app/lti/lti13-deep-linking.component'; -import { Lti13SelectContentComponent } from 'app/lti/lti13-select-content.component'; -import { LtiCoursesComponent } from 'app/lti/lti13-select-course.component'; + import { Authority } from 'app/shared/constants/authority.constants'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; export const ltiLaunchRoutes: Routes = [ { path: 'launch', - component: Lti13ExerciseLaunchComponent, + loadComponent: () => import('app/lti/lti13-exercise-launch.component').then((m) => m.Lti13ExerciseLaunchComponent), data: { pageTitle: 'artemisApp.lti13.launch.title', }, }, { path: 'dynamic-registration', - component: Lti13DynamicRegistrationComponent, + loadComponent: () => import('app/lti/lti13-dynamic-registration.component').then((m) => m.Lti13DynamicRegistrationComponent), data: { pageTitle: 'artemisApp.lti13.dynamicRegistration.title', }, }, { path: 'select-content', - component: Lti13SelectContentComponent, + loadComponent: () => import('app/lti/lti13-select-content.component').then((m) => m.Lti13SelectContentComponent), data: { pageTitle: 'artemisApp.lti13.deepLinking.title', }, }, { path: 'select-course', - component: LtiCoursesComponent, + loadComponent: () => import('app/lti/lti13-select-course.component').then((m) => m.LtiCoursesComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.lti13.selectCourse', @@ -40,7 +36,7 @@ export const ltiLaunchRoutes: Routes = [ }, { path: 'exercises/:courseId', - component: Lti13DeepLinkingComponent, + loadComponent: () => import('app/lti/lti13-deep-linking.component').then((m) => m.Lti13DeepLinkingComponent), data: { authorities: [Authority.INSTRUCTOR, Authority.ADMIN], pageTitle: 'artemisApp.lti13.deepLinking.title', diff --git a/src/main/webapp/app/lti/lti13-deep-linking.component.ts b/src/main/webapp/app/lti/lti13-deep-linking.component.ts index 2ac4c0aa9098..51a5a42ebf3f 100644 --- a/src/main/webapp/app/lti/lti13-deep-linking.component.ts +++ b/src/main/webapp/app/lti/lti13-deep-linking.component.ts @@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from '@angular/router'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { Exercise } from 'app/entities/exercise.model'; import { faExclamationTriangle, faSort, faWrench } from '@fortawesome/free-solid-svg-icons'; +import { HasAnyAuthorityDirective } from 'app/shared/auth/has-any-authority.directive'; import { SortService } from 'app/shared/service/sort.service'; import { HttpClient, HttpParams } from '@angular/common/http'; import { AccountService } from 'app/core/auth/account.service'; @@ -20,8 +21,16 @@ import { FormsModule } from '@angular/forms'; @Component({ selector: 'jhi-deep-linking', templateUrl: './lti13-deep-linking.component.html', - standalone: true, - imports: [ArtemisSharedModule, TranslateDirective, ArtemisSharedComponentModule, ArtemisSharedCommonModule, FaIconComponent, FormsModule], + imports: [ + ArtemisSharedModule, + TranslateDirective, + ArtemisSharedComponentModule, + ArtemisSharedCommonModule, + FaIconComponent, + FormsModule, + // NOTE: this is actually used in the html template, otherwise *jhiHasAnyAuthority would not work + HasAnyAuthorityDirective, + ], }) export class Lti13DeepLinkingComponent implements OnInit { route = inject(ActivatedRoute); diff --git a/src/main/webapp/app/lti/lti13-dynamic-registration.component.ts b/src/main/webapp/app/lti/lti13-dynamic-registration.component.ts index 11fc898d8b96..40db894990c7 100644 --- a/src/main/webapp/app/lti/lti13-dynamic-registration.component.ts +++ b/src/main/webapp/app/lti/lti13-dynamic-registration.component.ts @@ -6,7 +6,6 @@ import { TranslateDirective } from '../shared/language/translate.directive'; @Component({ selector: 'jhi-dynamic-registration', templateUrl: './lti13-dynamic-registration.component.html', - standalone: true, imports: [TranslateDirective], }) export class Lti13DynamicRegistrationComponent implements OnInit { diff --git a/src/main/webapp/app/lti/lti13-exercise-launch.component.ts b/src/main/webapp/app/lti/lti13-exercise-launch.component.ts index 9f0c9826e333..75309b1777d2 100644 --- a/src/main/webapp/app/lti/lti13-exercise-launch.component.ts +++ b/src/main/webapp/app/lti/lti13-exercise-launch.component.ts @@ -18,7 +18,6 @@ type LtiLaunchResponse = { @Component({ selector: 'jhi-lti-exercise-launch', templateUrl: './lti13-exercise-launch.component.html', - standalone: true, imports: [TranslateDirective, CommonModule], }) export class Lti13ExerciseLaunchComponent implements OnInit { diff --git a/src/main/webapp/app/lti/lti13-select-content.component.ts b/src/main/webapp/app/lti/lti13-select-content.component.ts index d2a68ccf61ba..c1fa2e37ff84 100644 --- a/src/main/webapp/app/lti/lti13-select-content.component.ts +++ b/src/main/webapp/app/lti/lti13-select-content.component.ts @@ -15,7 +15,6 @@ import { ArtemisSharedPipesModule } from '../shared/pipes/shared-pipes.module'; @Component({ selector: 'jhi-select-exercise', templateUrl: './lti13-select-content.component.html', - standalone: true, imports: [TranslateDirective, FormsModule, ArtemisSharedPipesModule], }) export class Lti13SelectContentComponent implements OnInit { diff --git a/src/main/webapp/app/lti/lti13-select-course.component.ts b/src/main/webapp/app/lti/lti13-select-course.component.ts index f9633a91315f..1b5bc95f7540 100644 --- a/src/main/webapp/app/lti/lti13-select-course.component.ts +++ b/src/main/webapp/app/lti/lti13-select-course.component.ts @@ -9,7 +9,6 @@ import { TranslateDirective } from '../shared/language/translate.directive'; @Component({ selector: 'jhi-lti-courses-overview', templateUrl: './lti13-select-course.component.html', - standalone: true, imports: [LtiCourseCardComponent, TranslateDirective], }) export class LtiCoursesComponent implements OnInit { diff --git a/src/main/webapp/app/lti/online-course-dto.model.ts b/src/main/webapp/app/lti/online-course-dto.model.ts index e26d4b4e200c..5b5e8267225a 100644 --- a/src/main/webapp/app/lti/online-course-dto.model.ts +++ b/src/main/webapp/app/lti/online-course-dto.model.ts @@ -3,6 +3,4 @@ export class OnlineCourseDtoModel { public title?: string; public shortName?: string; public registrationId?: string; - - constructor() {} } diff --git a/src/main/webapp/app/orion/assessment/orion-assessment-instructions.component.ts b/src/main/webapp/app/orion/assessment/orion-assessment-instructions.component.ts index 5467b1975e99..99aa2fc9b189 100644 --- a/src/main/webapp/app/orion/assessment/orion-assessment-instructions.component.ts +++ b/src/main/webapp/app/orion/assessment/orion-assessment-instructions.component.ts @@ -1,6 +1,7 @@ import { Component, Input } from '@angular/core'; import { ProgrammingExerciseStudentParticipation } from 'app/entities/participation/programming-exercise-student-participation.model'; import { Exercise } from 'app/entities/exercise.model'; +import { AssessmentInstructionsComponent } from '../../assessment/assessment-instructions/assessment-instructions/assessment-instructions.component'; @Component({ selector: 'jhi-orion-assessment-instructions', @@ -9,6 +10,7 @@ import { Exercise } from 'app/entities/exercise.model'; `, + imports: [AssessmentInstructionsComponent], }) export class OrionAssessmentInstructionsComponent { @Input() readOnly: boolean; diff --git a/src/main/webapp/app/orion/assessment/orion-assessment.service.ts b/src/main/webapp/app/orion/assessment/orion-assessment.service.ts index 9463fc7f3e32..a60d30966701 100644 --- a/src/main/webapp/app/orion/assessment/orion-assessment.service.ts +++ b/src/main/webapp/app/orion/assessment/orion-assessment.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ProgrammingSubmission } from 'app/entities/programming/programming-submission.model'; import { ProgrammingAssessmentRepoExportService, RepositoryExportOptions } from 'app/exercises/programming/assess/repo-export/programming-assessment-repo-export.service'; import { OrionConnectorService } from 'app/shared/orion/orion-connector.service'; @@ -10,24 +10,26 @@ import { AlertService } from 'app/core/util/alert.service'; @Injectable({ providedIn: 'root' }) export class OrionAssessmentService { + private orionConnectorService = inject(OrionConnectorService); + private programmingSubmissionService = inject(ProgrammingSubmissionService); + private repositoryExportService = inject(ProgrammingAssessmentRepoExportService); + private manualAssessmentService = inject(ProgrammingAssessmentManualResultService); + private alertService = inject(AlertService); + orionState: OrionState; // Stores which submission has been lastly opened activeSubmissionId: number | undefined = undefined; - constructor( - private orionConnectorService: OrionConnectorService, - private programmingSubmissionService: ProgrammingSubmissionService, - private repositoryExportService: ProgrammingAssessmentRepoExportService, - private manualAssessmentService: ProgrammingAssessmentManualResultService, - private alertService: AlertService, - ) { - this.orionConnectorService.state().subscribe((state) => { - if (this.orionState?.cloning && !state.cloning && this.activeSubmissionId !== undefined) { - // If the client sends a cloning = false the download was cancelled, unlock the pending submission - this.manualAssessmentService.cancelAssessment(this.activeSubmissionId).subscribe(); - } - this.orionState = { ...state }; - }); + constructor() { + if (this.orionConnectorService && this.orionConnectorService.state()) { + this.orionConnectorService.state().subscribe((state) => { + if (this.orionState?.cloning && !state.cloning && this.activeSubmissionId !== undefined) { + // If the client sends a cloning = false the download was cancelled, unlock the pending submission + this.manualAssessmentService.cancelAssessment(this.activeSubmissionId).subscribe(); + } + this.orionState = { ...state }; + }); + } } /** diff --git a/src/main/webapp/app/orion/assessment/orion-exercise-assessment-dashboard.component.ts b/src/main/webapp/app/orion/assessment/orion-exercise-assessment-dashboard.component.ts index 33a3f8871172..11eb809bcc7b 100644 --- a/src/main/webapp/app/orion/assessment/orion-exercise-assessment-dashboard.component.ts +++ b/src/main/webapp/app/orion/assessment/orion-exercise-assessment-dashboard.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { AlertService } from 'app/core/util/alert.service'; import { Submission } from 'app/entities/submission.model'; @@ -10,13 +10,23 @@ import { ExerciseService } from 'app/exercises/shared/exercise/exercise.service' import { onError } from 'app/shared/util/global.utils'; import { OrionAssessmentService } from 'app/orion/assessment/orion-assessment.service'; import { OrionButtonType } from 'app/shared/orion/orion-button/orion-button.component'; +import { ExerciseAssessmentDashboardComponent } from '../../exercises/shared/dashboards/tutor/exercise-assessment-dashboard.component'; +import { OrionButtonComponent } from 'app/shared/orion/orion-button/orion-button.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-orion-exercise-assessment-dashboard', templateUrl: './orion-exercise-assessment-dashboard.component.html', providers: [CourseManagementService], + imports: [ExerciseAssessmentDashboardComponent, OrionButtonComponent, ArtemisTranslatePipe], }) export class OrionExerciseAssessmentDashboardComponent implements OnInit { + private route = inject(ActivatedRoute); + private exerciseService = inject(ExerciseService); + private orionAssessmentService = inject(OrionAssessmentService); + private orionConnectorService = inject(OrionConnectorService); + private alertService = inject(AlertService); + readonly ExerciseView = ExerciseView; readonly ExerciseType = ExerciseType; protected readonly OrionButtonType = OrionButtonType; @@ -25,22 +35,15 @@ export class OrionExerciseAssessmentDashboardComponent implements OnInit { exerciseId: number; exercise: Exercise; - constructor( - private route: ActivatedRoute, - private exerciseService: ExerciseService, - private orionAssessmentService: OrionAssessmentService, - private orionConnectorService: OrionConnectorService, - private alertService: AlertService, - ) {} - ngOnInit(): void { this.exerciseId = Number(this.route.snapshot.paramMap.get('exerciseId')); this.exerciseService.getForTutors(this.exerciseId).subscribe({ next: (res) => (this.exercise = res.body!), error: (error) => onError(this.alertService, error), }); - - this.orionConnectorService.state().subscribe((state) => (this.orionState = state)); + if (this.orionConnectorService && this.orionConnectorService.state()) { + this.orionConnectorService.state().subscribe((state) => (this.orionState = state)); + } } /** diff --git a/src/main/webapp/app/orion/assessment/orion-tutor-assessment.component.ts b/src/main/webapp/app/orion/assessment/orion-tutor-assessment.component.ts index e1518de3e2a8..23ca17653fc8 100644 --- a/src/main/webapp/app/orion/assessment/orion-tutor-assessment.component.ts +++ b/src/main/webapp/app/orion/assessment/orion-tutor-assessment.component.ts @@ -1,22 +1,27 @@ -import { Component, ViewChild } from '@angular/core'; +import { Component, ViewChild, inject } from '@angular/core'; import { CodeEditorTutorAssessmentContainerComponent } from 'app/exercises/programming/assess/code-editor-tutor-assessment-container.component'; import { Feedback } from 'app/entities/feedback.model'; import { OrionConnectorService } from 'app/shared/orion/orion-connector.service'; import { OrionAssessmentService } from 'app/orion/assessment/orion-assessment.service'; import { AlertService } from 'app/core/util/alert.service'; +import { NgTemplateOutlet } from '@angular/common'; +import { OrionAssessmentInstructionsComponent } from './orion-assessment-instructions.component'; @Component({ selector: 'jhi-orion-course-management-exercises', templateUrl: './orion-tutor-assessment.component.html', + imports: [CodeEditorTutorAssessmentContainerComponent, NgTemplateOutlet, OrionAssessmentInstructionsComponent], }) export class OrionTutorAssessmentComponent { + private orionConnectorService = inject(OrionConnectorService); + private alertService = inject(AlertService); + private orionAssessmentService = inject(OrionAssessmentService); + @ViewChild(CodeEditorTutorAssessmentContainerComponent) container: CodeEditorTutorAssessmentContainerComponent; - constructor( - private orionConnectorService: OrionConnectorService, - private alertService: AlertService, - private orionAssessmentService: OrionAssessmentService, - ) { + constructor() { + const orionConnectorService = this.orionConnectorService; + // Register this component as receiver of updates from Orion orionConnectorService.activeAssessmentComponent = this; } diff --git a/src/main/webapp/app/orion/management/code-editor-instructor-and-editor-orion-container.component.ts b/src/main/webapp/app/orion/management/code-editor-instructor-and-editor-orion-container.component.ts index fece685811c2..ec410975c4cf 100644 --- a/src/main/webapp/app/orion/management/code-editor-instructor-and-editor-orion-container.component.ts +++ b/src/main/webapp/app/orion/management/code-editor-instructor-and-editor-orion-container.component.ts @@ -1,27 +1,45 @@ -import { Component, OnInit } from '@angular/core'; -import { ProgrammingExerciseParticipationService } from 'app/exercises/programming/manage/services/programming-exercise-participation.service'; -import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; -import { ParticipationService } from 'app/exercises/shared/participation/participation.service'; -import { ActivatedRoute, Router } from '@angular/router'; -import { Location } from '@angular/common'; -import { TranslateService } from '@ngx-translate/core'; -import { AlertService } from 'app/core/util/alert.service'; +import { Component, OnInit, inject } from '@angular/core'; import { CodeEditorInstructorBaseContainerComponent, REPOSITORY } from 'app/exercises/programming/manage/code-editor/code-editor-instructor-base-container.component'; -import { DomainService } from 'app/exercises/programming/shared/code-editor/service/code-editor-domain.service'; import { OrionConnectorService } from 'app/shared/orion/orion-connector.service'; import { OrionBuildAndTestService } from 'app/shared/orion/orion-build-and-test.service'; import { OrionState } from 'app/shared/orion/orion'; import { faCircleNotch, faTimesCircle } from '@fortawesome/free-solid-svg-icons'; -import { CourseExerciseService } from 'app/exercises/shared/course-exercises/course-exercise.service'; import { MarkdownEditorHeight } from 'app/shared/markdown-editor/monaco/markdown-editor-monaco.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { UpdatingResultComponent } from '../../exercises/shared/result/updating-result.component'; +import { ProgrammingExerciseInstructorExerciseStatusComponent } from '../../exercises/programming/manage/status/programming-exercise-instructor-exercise-status.component'; +import { NgbDropdown, NgbDropdownButtonItem, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle } from '@ng-bootstrap/ng-bootstrap'; +import { ProgrammingExerciseStudentTriggerBuildButtonComponent } from '../../exercises/programming/shared/actions/programming-exercise-student-trigger-build-button.component'; +import { OrionButtonComponent } from 'app/shared/orion/orion-button/orion-button.component'; +import { ProgrammingExerciseEditableInstructionComponent } from '../../exercises/programming/manage/instructions-editor/programming-exercise-editable-instruction.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-code-editor-instructor-orion', templateUrl: './code-editor-instructor-and-editor-orion-container.component.html', styles: ['.instructions-orion { height: 700px }'], + imports: [ + FaIconComponent, + TranslateDirective, + UpdatingResultComponent, + ProgrammingExerciseInstructorExerciseStatusComponent, + NgbDropdown, + NgbDropdownToggle, + NgbDropdownMenu, + NgbDropdownButtonItem, + NgbDropdownItem, + ProgrammingExerciseStudentTriggerBuildButtonComponent, + OrionButtonComponent, + ProgrammingExerciseEditableInstructionComponent, + ArtemisTranslatePipe, + ], }) export class CodeEditorInstructorAndEditorOrionContainerComponent extends CodeEditorInstructorBaseContainerComponent implements OnInit { + private orionConnectorService = inject(OrionConnectorService); + private orionBuildAndTestService = inject(OrionBuildAndTestService); + orionState: OrionState; // Icons @@ -30,30 +48,15 @@ export class CodeEditorInstructorAndEditorOrionContainerComponent extends CodeEd protected readonly MarkdownEditorHeight = MarkdownEditorHeight; - constructor( - private orionConnectorService: OrionConnectorService, - private orionBuildAndTestService: OrionBuildAndTestService, - router: Router, - exerciseService: ProgrammingExerciseService, - courseExerciseService: CourseExerciseService, - domainService: DomainService, - programmingExerciseParticipationService: ProgrammingExerciseParticipationService, - location: Location, - participationService: ParticipationService, - translateService: TranslateService, - route: ActivatedRoute, - alertService: AlertService, - ) { - super(router, exerciseService, courseExerciseService, domainService, programmingExerciseParticipationService, location, participationService, route, alertService); - } - /** * Calls ngOnInit of its superclass and initialize the subscription to * the Orion connector service, on component initialization */ ngOnInit(): void { super.ngOnInit(); - this.orionConnectorService.state().subscribe((state) => (this.orionState = state)); + if (this.orionConnectorService && this.orionConnectorService.state()) { + this.orionConnectorService.state().subscribe((state) => (this.orionState = state)); + } } protected applyDomainChange(domainType: any, domainValue: any) { diff --git a/src/main/webapp/app/orion/management/orion-course-management-exercises.component.ts b/src/main/webapp/app/orion/management/orion-course-management-exercises.component.ts index 2130f8169d20..8bdf0a853e97 100644 --- a/src/main/webapp/app/orion/management/orion-course-management-exercises.component.ts +++ b/src/main/webapp/app/orion/management/orion-course-management-exercises.component.ts @@ -1,4 +1,6 @@ import { Component } from '@angular/core'; +import { CourseManagementExercisesComponent } from '../../course/manage/course-management-exercises.component'; +import { OrionProgrammingExerciseComponent } from './orion-programming-exercise.component'; @Component({ selector: 'jhi-orion-course-management-exercises', @@ -24,6 +26,7 @@ import { Component } from '@angular/core'; `, + imports: [CourseManagementExercisesComponent, OrionProgrammingExerciseComponent], }) export class OrionCourseManagementExercisesComponent { // only overrides the programming exercise list with Orion's programming exercise list and suppresses the other exercises diff --git a/src/main/webapp/app/orion/management/orion-programming-exercise.component.html b/src/main/webapp/app/orion/management/orion-programming-exercise.component.html index 4164d6a59602..291c16ad5eb2 100644 --- a/src/main/webapp/app/orion/management/orion-programming-exercise.component.html +++ b/src/main/webapp/app/orion/management/orion-programming-exercise.component.html @@ -8,22 +8,24 @@ - @if (orionState.view === ExerciseView.INSTRUCTOR && orionState.opened === exercise.id && exercise.isAtLeastEditor && exercise.templateParticipation) { - - } @else { - @if (exercise.isAtLeastEditor && exercise.templateParticipation) { + @if (orionState) { + @if (orionState.view === ExerciseView.INSTRUCTOR && orionState.opened === exercise.id && exercise.isAtLeastEditor && exercise.templateParticipation) { + } @else { + @if (exercise.isAtLeastEditor && exercise.templateParticipation) { + + } } } diff --git a/src/main/webapp/app/orion/management/orion-programming-exercise.component.ts b/src/main/webapp/app/orion/management/orion-programming-exercise.component.ts index 2854122be21c..1d42aecb6e40 100644 --- a/src/main/webapp/app/orion/management/orion-programming-exercise.component.ts +++ b/src/main/webapp/app/orion/management/orion-programming-exercise.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { OrionConnectorService } from 'app/shared/orion/orion-connector.service'; import { ExerciseView, OrionState } from 'app/shared/orion/orion'; @@ -7,12 +7,20 @@ import { Course } from 'app/entities/course.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { ExerciseFilter } from 'app/entities/exercise-filter.model'; import { OrionButtonType } from 'app/shared/orion/orion-button/orion-button.component'; +import { ProgrammingExerciseComponent } from 'app/exercises/programming/manage/programming-exercise.component'; +import { OrionButtonComponent } from 'app/shared/orion/orion-button/orion-button.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-orion-programming-exercise', templateUrl: './orion-programming-exercise.component.html', + imports: [ProgrammingExerciseComponent, OrionButtonComponent, ArtemisTranslatePipe], }) export class OrionProgrammingExerciseComponent implements OnInit { + private orionConnectorService = inject(OrionConnectorService); + private router = inject(Router); + private programmingExerciseService = inject(ProgrammingExerciseService); + @Input() embedded = false; @Input() course: Course; @Input() exerciseFilter: ExerciseFilter; @@ -23,16 +31,12 @@ export class OrionProgrammingExerciseComponent implements OnInit { protected readonly OrionButtonType = OrionButtonType; orionState: OrionState; - constructor( - private orionConnectorService: OrionConnectorService, - private router: Router, - private programmingExerciseService: ProgrammingExerciseService, - ) {} - ngOnInit() { - this.orionConnectorService.state().subscribe((state) => { - this.orionState = state; - }); + if (this.orionConnectorService && this.orionConnectorService.state()) { + this.orionConnectorService.state().subscribe((state) => { + this.orionState = state; + }); + } } /** diff --git a/src/main/webapp/app/orion/participation/orion-course-exercise-details.component.ts b/src/main/webapp/app/orion/participation/orion-course-exercise-details.component.ts index a330a872b25d..d24f48cc8246 100644 --- a/src/main/webapp/app/orion/participation/orion-course-exercise-details.component.ts +++ b/src/main/webapp/app/orion/participation/orion-course-exercise-details.component.ts @@ -1,4 +1,6 @@ import { Component } from '@angular/core'; +import { CourseExerciseDetailsComponent } from 'app/overview/exercise-details/course-exercise-details.component'; +import { OrionExerciseDetailsStudentActionsComponent } from './orion-exercise-details-student-actions.component'; @Component({ selector: 'jhi-orion-course-exercise-details', @@ -9,6 +11,7 @@ import { Component } from '@angular/core'; `, + imports: [CourseExerciseDetailsComponent, OrionExerciseDetailsStudentActionsComponent], }) export class OrionCourseExerciseDetailsComponent { // only replaces the student actions with Orion student actions in the overview diff --git a/src/main/webapp/app/orion/participation/orion-exercise-details-student-actions.component.html b/src/main/webapp/app/orion/participation/orion-exercise-details-student-actions.component.html index e91dda6f3f21..f98986f2f7fc 100644 --- a/src/main/webapp/app/orion/participation/orion-exercise-details-student-actions.component.html +++ b/src/main/webapp/app/orion/participation/orion-exercise-details-student-actions.component.html @@ -1,34 +1,36 @@ - @if (isOfflineIdeAllowed && (orionState.view !== ExerciseView.STUDENT || orionState.opened !== this.exercise.id)) { - - } - @if (isOfflineIdeAllowed && orionState.view === ExerciseView.STUDENT && orionState.opened === this.exercise.id) { - - } - @if (isOfflineIdeAllowed && orionState.view === ExerciseView.STUDENT && orionState.opened === this.exercise.id && isDueDatePassed()) { - + @if (orionState !== undefined && orionState.view !== undefined) { + @if (isOfflineIdeAllowed && (orionState.view !== ExerciseView.STUDENT || orionState.opened !== this.exercise.id)) { + + } + @if (isOfflineIdeAllowed && orionState.view === ExerciseView.STUDENT && orionState.opened === this.exercise.id) { + + } + @if (isOfflineIdeAllowed && orionState.view === ExerciseView.STUDENT && orionState.opened === this.exercise.id && isDueDatePassed()) { + + } } diff --git a/src/main/webapp/app/orion/participation/orion-exercise-details-student-actions.component.ts b/src/main/webapp/app/orion/participation/orion-exercise-details-student-actions.component.ts index 30f6b585e32c..ebeba647bcfc 100644 --- a/src/main/webapp/app/orion/participation/orion-exercise-details-student-actions.component.ts +++ b/src/main/webapp/app/orion/participation/orion-exercise-details-student-actions.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; @@ -8,13 +8,21 @@ import { OrionConnectorService } from 'app/shared/orion/orion-connector.service' import { OrionBuildAndTestService } from 'app/shared/orion/orion-build-and-test.service'; import { Exercise } from 'app/entities/exercise.model'; import { OrionButtonType } from 'app/shared/orion/orion-button/orion-button.component'; +import { ExerciseDetailsStudentActionsComponent } from 'app/overview/exercise-details/exercise-details-student-actions.component'; +import { OrionButtonComponent } from 'app/shared/orion/orion-button/orion-button.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-orion-exercise-details-student-actions', templateUrl: './orion-exercise-details-student-actions.component.html', styleUrls: ['../../overview/course-overview.scss'], + imports: [ExerciseDetailsStudentActionsComponent, OrionButtonComponent, ArtemisTranslatePipe], }) export class OrionExerciseDetailsStudentActionsComponent implements OnInit { + private orionConnectorService = inject(OrionConnectorService); + private ideBuildAndTestService = inject(OrionBuildAndTestService); + private route = inject(ActivatedRoute); + readonly ExerciseView = ExerciseView; orionState: OrionState; FeatureToggle = FeatureToggle; @@ -23,24 +31,21 @@ export class OrionExerciseDetailsStudentActionsComponent implements OnInit { @Input() courseId: number; @Input() smallButtons: boolean; @Input() examMode: boolean; - protected readonly OrionButtonType = OrionButtonType; - constructor( - private orionConnectorService: OrionConnectorService, - private ideBuildAndTestService: OrionBuildAndTestService, - private route: ActivatedRoute, - ) {} + protected readonly OrionButtonType = OrionButtonType; /** * get orionState and submit changes if withIdeSubmit set in route query */ ngOnInit(): void { - this.orionConnectorService.state().subscribe((orionState: OrionState) => (this.orionState = orionState)); - this.route.queryParams.subscribe((params) => { - if (params['withIdeSubmit']) { - this.submitChanges(); - } - }); + if (this.orionConnectorService && this.orionConnectorService.state()) { + this.orionConnectorService.state().subscribe((orionState: OrionState) => (this.orionState = orionState)); + this.route.queryParams.subscribe((params) => { + if (params['withIdeSubmit']) { + this.submitChanges(); + } + }); + } } get isOfflineIdeAllowed() { diff --git a/src/main/webapp/app/overview/course-archive/course-archive.component.ts b/src/main/webapp/app/overview/course-archive/course-archive.component.ts index eb88ee898038..2bc638119b41 100644 --- a/src/main/webapp/app/overview/course-archive/course-archive.component.ts +++ b/src/main/webapp/app/overview/course-archive/course-archive.component.ts @@ -16,7 +16,6 @@ import { SearchFilterComponent } from 'app/shared/search-filter/search-filter.co selector: 'jhi-course-archive', templateUrl: './course-archive.component.html', styleUrls: ['./course-archive.component.scss'], - standalone: true, imports: [ArtemisSharedModule, CourseCardHeaderComponent, SearchFilterComponent], }) export class CourseArchiveComponent implements OnInit, OnDestroy { diff --git a/src/main/webapp/app/overview/course-card-header/course-card-header.component.ts b/src/main/webapp/app/overview/course-card-header/course-card-header.component.ts index 3b1bb9b1c433..9aef1b0a8150 100644 --- a/src/main/webapp/app/overview/course-card-header/course-card-header.component.ts +++ b/src/main/webapp/app/overview/course-card-header/course-card-header.component.ts @@ -7,7 +7,6 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; selector: 'jhi-course-card-header', templateUrl: './course-card-header.component.html', styleUrls: ['./course-card-header.component.scss'], - standalone: true, imports: [ArtemisSharedModule], }) export class CourseCardHeaderComponent implements OnInit { diff --git a/src/main/webapp/app/overview/course-card.component.ts b/src/main/webapp/app/overview/course-card.component.ts index ce8bbb0bcc7e..7e9cde3079c8 100644 --- a/src/main/webapp/app/overview/course-card.component.ts +++ b/src/main/webapp/app/overview/course-card.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnChanges } from '@angular/core'; +import { Component, Input, OnChanges, inject } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { Color, ScaleType } from '@swimlane/ngx-charts'; import { ARTEMIS_DEFAULT_COLOR } from 'app/app.constants'; @@ -22,10 +22,14 @@ import { RouterLink } from '@angular/router'; selector: 'jhi-overview-course-card', templateUrl: './course-card.component.html', styleUrls: ['course-card.scss'], - standalone: true, imports: [CourseCardHeaderComponent, ArtemisSharedCommonModule, NgxChartsModule, PieChartModule, TranslateDirective, RouterLink], }) export class CourseCardComponent implements OnChanges { + private router = inject(Router); + private route = inject(ActivatedRoute); + private scoresStorageService = inject(ScoresStorageService); + private exerciseService = inject(ExerciseService); + protected readonly faArrowRight = faArrowRight; readonly ARTEMIS_DEFAULT_COLOR = ARTEMIS_DEFAULT_COLOR; @@ -55,13 +59,6 @@ export class CourseCardComponent implements OnChanges { domain: [GraphColors.GREEN, GraphColors.RED], } as Color; - constructor( - private router: Router, - private route: ActivatedRoute, - private scoresStorageService: ScoresStorageService, - private exerciseService: ExerciseService, - ) {} - ngOnChanges() { if (this.course.exercises && this.course.exercises.length > 0) { this.exerciseCount = this.course.exercises.length; diff --git a/src/main/webapp/app/overview/course-competencies/course-competencies-details.component.ts b/src/main/webapp/app/overview/course-competencies/course-competencies-details.component.ts index 065a6d802c64..df8dbb0047f6 100644 --- a/src/main/webapp/app/overview/course-competencies/course-competencies-details.component.ts +++ b/src/main/webapp/app/overview/course-competencies/course-competencies-details.component.ts @@ -1,6 +1,6 @@ import dayjs from 'dayjs/esm'; -import { Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { Competency, CompetencyJol, @@ -26,13 +26,55 @@ import { FeatureToggle, FeatureToggleService } from 'app/shared/feature-toggle/f import { CourseStorageService } from 'app/course/manage/course-storage.service'; import { Course } from 'app/entities/course.model'; import { CourseCompetencyService } from 'app/course/competencies/course-competency.service'; +import { FireworksComponent } from 'app/shared/fireworks/fireworks.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { NgClass } from '@angular/common'; +import { ExerciseUnitComponent } from '../course-lectures/exercise-unit/exercise-unit.component'; +import { AttachmentUnitComponent } from '../course-lectures/attachment-unit/attachment-unit.component'; +import { VideoUnitComponent } from '../course-lectures/video-unit/video-unit.component'; +import { TextUnitComponent } from '../course-lectures/text-unit/text-unit.component'; +import { OnlineUnitComponent } from '../course-lectures/online-unit/online-unit.component'; +import { CompetencyRingsComponent } from '../../course/competencies/competency-rings/competency-rings.component'; +import { SidePanelComponent } from 'app/shared/side-panel/side-panel.component'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { ArtemisTimeAgoPipe } from 'app/shared/pipes/artemis-time-ago.pipe'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-course-competencies-details', templateUrl: './course-competencies-details.component.html', styleUrls: ['../course-overview.scss'], + imports: [ + FireworksComponent, + TranslateDirective, + FaIconComponent, + NgbTooltip, + NgClass, + RouterLink, + ExerciseUnitComponent, + AttachmentUnitComponent, + VideoUnitComponent, + TextUnitComponent, + OnlineUnitComponent, + CompetencyRingsComponent, + SidePanelComponent, + HelpIconComponent, + ArtemisTranslatePipe, + ArtemisTimeAgoPipe, + HtmlForMarkdownPipe, + ], }) export class CourseCompetenciesDetailsComponent implements OnInit, OnDestroy { + private featureToggleService = inject(FeatureToggleService); + private courseStorageService = inject(CourseStorageService); + private alertService = inject(AlertService); + private activatedRoute = inject(ActivatedRoute); + private courseCompetencyService = inject(CourseCompetencyService); + private lectureUnitService = inject(LectureUnitService); + competencyId?: number; course?: Course; courseId?: number; @@ -51,15 +93,6 @@ export class CourseCompetenciesDetailsComponent implements OnInit, OnDestroy { faPencilAlt = faPencilAlt; getIcon = getIcon; - constructor( - private featureToggleService: FeatureToggleService, - private courseStorageService: CourseStorageService, - private alertService: AlertService, - private activatedRoute: ActivatedRoute, - private courseCompetencyService: CourseCompetencyService, - private lectureUnitService: LectureUnitService, - ) {} - ngOnInit(): void { // example route looks like: /courses/1/competencies/10 const courseIdParams$ = this.activatedRoute.parent?.parent?.parent?.params; diff --git a/src/main/webapp/app/overview/course-competencies/course-competencies-details.module.ts b/src/main/webapp/app/overview/course-competencies/course-competencies-details.module.ts index ba6934db7a8c..d9b5bc3d3028 100644 --- a/src/main/webapp/app/overview/course-competencies/course-competencies-details.module.ts +++ b/src/main/webapp/app/overview/course-competencies/course-competencies-details.module.ts @@ -1,3 +1,4 @@ +import { CourseCompetenciesDetailsComponent } from 'app/overview/course-competencies/course-competencies-details.component'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { ArtemisSharedPipesModule } from 'app/shared/pipes/shared-pipes.module'; @@ -8,9 +9,9 @@ import { UserRouteAccessService } from 'app/core/auth/user-route-access-service' import { Authority } from 'app/shared/constants/authority.constants'; import { RouterModule, Routes } from '@angular/router'; import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; -import { CourseCompetenciesDetailsComponent } from 'app/overview/course-competencies/course-competencies-details.component'; + import { ArtemisSidePanelModule } from 'app/shared/side-panel/side-panel.module'; -import { FireworksModule } from 'app/shared/fireworks/fireworks.module'; + import { JudgementOfLearningRatingComponent } from 'app/course/competencies/judgement-of-learning-rating/judgement-of-learning-rating.component'; import { AttachmentUnitComponent } from 'app/overview/course-lectures/attachment-unit/attachment-unit.component'; import { VideoUnitComponent } from 'app/overview/course-lectures/video-unit/video-unit.component'; @@ -20,7 +21,7 @@ import { OnlineUnitComponent } from 'app/overview/course-lectures/online-unit/on const routes: Routes = [ { path: '', - component: CourseCompetenciesDetailsComponent, + loadComponent: () => import('app/overview/course-competencies/course-competencies-details.component').then((m) => m.CourseCompetenciesDetailsComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.competencies', @@ -38,14 +39,13 @@ const routes: Routes = [ ArtemisCompetenciesModule, ArtemisMarkdownModule, ArtemisSidePanelModule, - FireworksModule, JudgementOfLearningRatingComponent, AttachmentUnitComponent, VideoUnitComponent, TextUnitComponent, OnlineUnitComponent, + CourseCompetenciesDetailsComponent, ], - declarations: [CourseCompetenciesDetailsComponent], exports: [CourseCompetenciesDetailsComponent], }) export class ArtemisCourseCompetenciesDetailsModule {} diff --git a/src/main/webapp/app/overview/course-competencies/course-competencies.component.ts b/src/main/webapp/app/overview/course-competencies/course-competencies.component.ts index 8d15b59fae94..17f7f895a01c 100644 --- a/src/main/webapp/app/overview/course-competencies/course-competencies.component.ts +++ b/src/main/webapp/app/overview/course-competencies/course-competencies.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { AlertService } from 'app/core/util/alert.service'; import { onError } from 'app/shared/util/global.utils'; @@ -10,13 +10,24 @@ import { faAngleDown, faAngleUp } from '@fortawesome/free-solid-svg-icons'; import { CourseStorageService } from 'app/course/manage/course-storage.service'; import { FeatureToggle, FeatureToggleService } from 'app/shared/feature-toggle/feature-toggle.service'; import { CourseCompetencyService } from 'app/course/competencies/course-competency.service'; +import { CompetencyCardComponent } from '../../course/competencies/competency-card/competency-card.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-course-competencies', templateUrl: './course-competencies.component.html', styleUrls: ['../course-overview.scss'], + imports: [CompetencyCardComponent, FaIconComponent, TranslateDirective, ArtemisTranslatePipe], }) export class CourseCompetenciesComponent implements OnInit, OnDestroy { + private featureToggleService = inject(FeatureToggleService); + private activatedRoute = inject(ActivatedRoute); + private alertService = inject(AlertService); + private courseStorageService = inject(CourseStorageService); + private courseCompetencyService = inject(CourseCompetencyService); + @Input() courseId: number; @@ -35,14 +46,6 @@ export class CourseCompetenciesComponent implements OnInit, OnDestroy { private dashboardFeatureToggleActiveSubscription: Subscription; dashboardFeatureActive = false; - constructor( - private featureToggleService: FeatureToggleService, - private activatedRoute: ActivatedRoute, - private alertService: AlertService, - private courseStorageService: CourseStorageService, - private courseCompetencyService: CourseCompetencyService, - ) {} - ngOnInit(): void { const courseIdParams$ = this.activatedRoute.parent?.parent?.parent?.params; if (courseIdParams$) { diff --git a/src/main/webapp/app/overview/course-competencies/course-competencies.module.ts b/src/main/webapp/app/overview/course-competencies/course-competencies.module.ts index afdcd8e23a2d..42b823fa6996 100644 --- a/src/main/webapp/app/overview/course-competencies/course-competencies.module.ts +++ b/src/main/webapp/app/overview/course-competencies/course-competencies.module.ts @@ -1,12 +1,12 @@ +import { CourseCompetenciesComponent } from 'app/overview/course-competencies/course-competencies.component'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; -import { CourseCompetenciesComponent } from 'app/overview/course-competencies/course-competencies.component'; + import { Authority } from 'app/shared/constants/authority.constants'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; import { ArtemisCompetenciesModule } from 'app/course/competencies/competency.module'; -import { FireworksModule } from 'app/shared/fireworks/fireworks.module'; const routes: Routes = [ { @@ -16,14 +16,13 @@ const routes: Routes = [ authorities: [Authority.USER], pageTitle: 'overview.competencies', }, - component: CourseCompetenciesComponent, + loadComponent: () => import('app/overview/course-competencies/course-competencies.component').then((m) => m.CourseCompetenciesComponent), canActivate: [UserRouteAccessService], }, ]; @NgModule({ - imports: [RouterModule.forChild(routes), ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisCompetenciesModule, FireworksModule], - declarations: [CourseCompetenciesComponent], + imports: [RouterModule.forChild(routes), ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisCompetenciesModule, CourseCompetenciesComponent], exports: [CourseCompetenciesComponent], }) export class CourseCompetenciesModule {} diff --git a/src/main/webapp/app/overview/course-conversations/code-of-conduct/course-conversations-code-of-conduct.component.ts b/src/main/webapp/app/overview/course-conversations/code-of-conduct/course-conversations-code-of-conduct.component.ts index 55d32ade492a..5d6bdbfdae2d 100644 --- a/src/main/webapp/app/overview/course-conversations/code-of-conduct/course-conversations-code-of-conduct.component.ts +++ b/src/main/webapp/app/overview/course-conversations/code-of-conduct/course-conversations-code-of-conduct.component.ts @@ -1,26 +1,27 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { User } from 'app/core/user/user.model'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { onError } from 'app/shared/util/global.utils'; import { AlertService } from 'app/core/util/alert.service'; import { Course } from 'app/entities/course.model'; import { ConversationService } from 'app/shared/metis/conversations/conversation.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-course-conversations-code-of-conduct', templateUrl: './course-conversations-code-of-conduct.component.html', + imports: [TranslateDirective, HtmlForMarkdownPipe], }) export class CourseConversationsCodeOfConductComponent implements OnInit { + private alertService = inject(AlertService); + private conversationService = inject(ConversationService); + @Input() course: Course; responsibleContacts: User[] = []; - constructor( - private alertService: AlertService, - private conversationService: ConversationService, - ) {} - ngOnInit() { if (this.course.id) { this.conversationService.getResponsibleUsersForCodeOfConduct(this.course.id).subscribe({ diff --git a/src/main/webapp/app/overview/course-conversations/course-conversations.component.ts b/src/main/webapp/app/overview/course-conversations/course-conversations.component.ts index ad2ac6c0a364..1f2828608d82 100644 --- a/src/main/webapp/app/overview/course-conversations/course-conversations.component.ts +++ b/src/main/webapp/app/overview/course-conversations/course-conversations.component.ts @@ -1,15 +1,7 @@ +import { NgClass } from '@angular/common'; import { ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, OnDestroy, OnInit, ViewChild, ViewEncapsulation, inject } from '@angular/core'; -import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model'; -import { Post } from 'app/entities/metis/post.model'; +import { FormsModule } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; -import { EMPTY, Observable, Subject, Subscription, from, take, takeUntil } from 'rxjs'; -import { catchError, debounceTime, distinctUntilChanged } from 'rxjs/operators'; -import { MetisConversationService } from 'app/shared/metis/metis-conversation.service'; -import { ChannelDTO, ChannelSubType, getAsChannelDTO } from 'app/entities/metis/conversation/channel.model'; -import { MetisService } from 'app/shared/metis/metis.service'; -import { Course, isMessagingEnabled } from 'app/entities/course.model'; -import { PageType, SortDirection } from 'app/shared/metis/metis.util'; import { faBan, faBookmark, @@ -26,22 +18,41 @@ import { faSearch, faTimes, } from '@fortawesome/free-solid-svg-icons'; -import { ButtonType } from 'app/shared/components/button.component'; +import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { UserPublicInfoDTO } from 'app/core/user/user.model'; +import { Course, isMessagingEnabled } from 'app/entities/course.model'; +import { ChannelDTO, ChannelSubType, getAsChannelDTO } from 'app/entities/metis/conversation/channel.model'; +import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model'; +import { Post } from 'app/entities/metis/post.model'; +import { Posting, PostingType, SavedPostStatus, SavedPostStatusMap } from 'app/entities/metis/posting.model'; import { CourseWideSearchComponent, CourseWideSearchConfig } from 'app/overview/course-conversations/course-wide-search/course-wide-search.component'; -import { AccordionGroups, ChannelTypeIcons, CollapseState, SidebarCardElement, SidebarData, SidebarItemShowAlways } from 'app/types/sidebar'; -import { CourseOverviewService } from 'app/overview/course-overview.service'; +import { ChannelsCreateDialogComponent } from 'app/overview/course-conversations/dialogs/channels-create-dialog/channels-create-dialog.component'; +import { ChannelAction, ChannelsOverviewDialogComponent } from 'app/overview/course-conversations/dialogs/channels-overview-dialog/channels-overview-dialog.component'; import { GroupChatCreateDialogComponent } from 'app/overview/course-conversations/dialogs/group-chat-create-dialog/group-chat-create-dialog.component'; -import { defaultFirstLayerDialogOptions, defaultSecondLayerDialogOptions } from 'app/overview/course-conversations/other/conversation.util'; -import { UserPublicInfoDTO } from 'app/core/user/user.model'; import { OneToOneChatCreateDialogComponent } from 'app/overview/course-conversations/dialogs/one-to-one-chat-create-dialog/one-to-one-chat-create-dialog.component'; -import { ChannelAction, ChannelsOverviewDialogComponent } from 'app/overview/course-conversations/dialogs/channels-overview-dialog/channels-overview-dialog.component'; -import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; -import { ChannelsCreateDialogComponent } from 'app/overview/course-conversations/dialogs/channels-create-dialog/channels-create-dialog.component'; +import { defaultFirstLayerDialogOptions, defaultSecondLayerDialogOptions } from 'app/overview/course-conversations/other/conversation.util'; +import { CourseOverviewService } from 'app/overview/course-overview.service'; import { CourseSidebarService } from 'app/overview/course-sidebar.service'; -import { LayoutService } from 'app/shared/breakpoints/layout.service'; import { CustomBreakpointNames } from 'app/shared/breakpoints/breakpoints.service'; -import { Posting, PostingType, SavedPostStatus, SavedPostStatusMap } from 'app/entities/metis/posting.model'; +import { LayoutService } from 'app/shared/breakpoints/layout.service'; +import { ButtonComponent, ButtonType } from 'app/shared/components/button.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; import { canCreateChannel } from 'app/shared/metis/conversations/conversation-permissions.utils'; +import { MetisConversationService } from 'app/shared/metis/metis-conversation.service'; +import { MetisService } from 'app/shared/metis/metis.service'; +import { PageType, SortDirection } from 'app/shared/metis/metis.util'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { SidebarComponent } from 'app/shared/sidebar/sidebar.component'; +import { AccordionGroups, ChannelTypeIcons, CollapseState, SidebarCardElement, SidebarData, SidebarItemShowAlways } from 'app/types/sidebar'; +import { EMPTY, Observable, Subject, Subscription, from, take, takeUntil } from 'rxjs'; +import { catchError, debounceTime, distinctUntilChanged } from 'rxjs/operators'; +import { CourseConversationsCodeOfConductComponent } from './code-of-conduct/course-conversations-code-of-conduct.component'; +import { ConversationHeaderComponent } from './layout/conversation-header/conversation-header.component'; +import { ConversationMessagesComponent } from './layout/conversation-messages/conversation-messages.component'; +import { ConversationThreadSidebarComponent } from './layout/conversation-thread-sidebar/conversation-thread-sidebar.component'; +import { SavedPostsComponent } from './saved-posts/saved-posts.component'; const DEFAULT_CHANNEL_GROUPS: AccordionGroups = { favoriteChannels: { entityData: [] }, @@ -99,8 +110,31 @@ const DEFAULT_SHOW_ALWAYS: SidebarItemShowAlways = { styleUrls: ['../course-overview.scss', './course-conversations.component.scss'], encapsulation: ViewEncapsulation.None, providers: [MetisService], + imports: [ + LoadingIndicatorContainerComponent, + FormsModule, + ButtonComponent, + CourseConversationsCodeOfConductComponent, + TranslateDirective, + NgClass, + SidebarComponent, + ConversationHeaderComponent, + ConversationMessagesComponent, + CourseWideSearchComponent, + SavedPostsComponent, + ConversationThreadSidebarComponent, + ArtemisTranslatePipe, + ], }) export class CourseConversationsComponent implements OnInit, OnDestroy { + private router = inject(Router); + private activatedRoute = inject(ActivatedRoute); + private metisConversationService = inject(MetisConversationService); + private metisService = inject(MetisService); + private courseOverviewService = inject(CourseOverviewService); + private modalService = inject(NgbModal); + private profileService = inject(ProfileService); + private ngUnsubscribe = new Subject(); private closeSidebarEventSubscription: Subscription; private openSidebarEventSubscription: Subscription; @@ -158,16 +192,6 @@ export class CourseConversationsComponent implements OnInit, OnDestroy { private layoutService: LayoutService = inject(LayoutService); private changeDetector: ChangeDetectorRef = inject(ChangeDetectorRef); - constructor( - private router: Router, - private activatedRoute: ActivatedRoute, - private metisConversationService: MetisConversationService, - private metisService: MetisService, - private courseOverviewService: CourseOverviewService, - private modalService: NgbModal, - private profileService: ProfileService, - ) {} - getAsChannel = getAsChannelDTO; private subscribeToMetis() { @@ -403,8 +427,7 @@ export class CourseConversationsComponent implements OnInit, OnDestroy { complete: () => { this.sidebarConversations = this.courseOverviewService.mapConversationsToSidebarCardElements(this.course!, this.conversationsOfUser); this.accordionConversationGroups = this.courseOverviewService.groupConversationsByChannelType(this.course!, this.conversationsOfUser, this.messagingEnabled); - const currentConversations = this.sidebarConversations?.filter((item) => item.isCurrent) || []; - this.accordionConversationGroups.recents.entityData = currentConversations; + this.accordionConversationGroups.recents.entityData = this.sidebarConversations?.filter((item) => item.isCurrent) || []; this.updateSidebarData(); }, }); diff --git a/src/main/webapp/app/overview/course-conversations/course-conversations.module.ts b/src/main/webapp/app/overview/course-conversations/course-conversations.module.ts index 10d2cea22583..4a932bb3f54d 100644 --- a/src/main/webapp/app/overview/course-conversations/course-conversations.module.ts +++ b/src/main/webapp/app/overview/course-conversations/course-conversations.module.ts @@ -1,12 +1,12 @@ +import { CourseConversationsComponent } from 'app/overview/course-conversations/course-conversations.component'; import { MetisModule } from 'app/shared/metis/metis.module'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; -import { CourseConversationsComponent } from 'app/overview/course-conversations/course-conversations.component'; + import { ArtemisDataTableModule } from 'app/shared/data-table/data-table.module'; import { ConversationMessagesComponent } from 'app/overview/course-conversations/layout/conversation-messages/conversation-messages.component'; -import { InfiniteScrollModule } from 'ngx-infinite-scroll'; import { ConversationThreadSidebarComponent } from 'app/overview/course-conversations/layout/conversation-thread-sidebar/conversation-thread-sidebar.component'; import { ChannelsOverviewDialogComponent } from './dialogs/channels-overview-dialog/channels-overview-dialog.component'; import { ChannelItemComponent } from './dialogs/channels-overview-dialog/channel-item/channel-item.component'; @@ -33,6 +33,7 @@ import { ArtemisSidebarModule } from 'app/shared/sidebar/sidebar.module'; import { ProfilePictureComponent } from 'app/shared/profile-picture/profile-picture.component'; import { SavedPostsComponent } from 'app/overview/course-conversations/saved-posts/saved-posts.component'; import { PostingSummaryComponent } from 'app/overview/course-conversations/posting-summary/posting-summary.component'; +import { InfiniteScrollDirective } from 'ngx-infinite-scroll'; const routes: Routes = [ { @@ -41,7 +42,7 @@ const routes: Routes = [ data: { pageTitle: 'artemisApp.conversationsLayout.tabTitle', }, - component: CourseConversationsComponent, + loadComponent: () => import('app/overview/course-conversations/course-conversations.component').then((m) => m.CourseConversationsComponent), }, ]; @@ -54,11 +55,9 @@ const routes: Routes = [ ArtemisSharedComponentModule, ArtemisDataTableModule, ArtemisSidebarModule, - InfiniteScrollModule, + InfiniteScrollDirective, CourseUsersSelectorModule, ProfilePictureComponent, - ], - declarations: [ CourseConversationsComponent, CourseConversationsCodeOfConductComponent, ConversationThreadSidebarComponent, diff --git a/src/main/webapp/app/overview/course-conversations/course-wide-search/course-wide-search.component.ts b/src/main/webapp/app/overview/course-conversations/course-wide-search/course-wide-search.component.ts index 556291d952d1..21a97f3dc9e5 100644 --- a/src/main/webapp/app/overview/course-conversations/course-wide-search/course-wide-search.component.ts +++ b/src/main/webapp/app/overview/course-conversations/course-wide-search/course-wide-search.component.ts @@ -15,7 +15,7 @@ import { inject, } from '@angular/core'; import { faChevronLeft, faCircleNotch, faEnvelope, faFilter, faLongArrowAltDown, faLongArrowAltUp, faPlus, faTimes } from '@fortawesome/free-solid-svg-icons'; -import { FormBuilder, FormGroup } from '@angular/forms'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { Subject, takeUntil } from 'rxjs'; import { Course } from 'app/entities/course.model'; import { ChannelDTO, getAsChannelDTO } from 'app/entities/metis/conversation/channel.model'; @@ -25,14 +25,27 @@ import { MetisConversationService } from 'app/shared/metis/metis-conversation.se import { PostContextFilter, PostSortCriterion, SortDirection } from 'app/shared/metis/metis.util'; import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model'; import { CourseSidebarService } from 'app/overview/course-sidebar.service'; +import { NgClass } from '@angular/common'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { InfiniteScrollDirective } from 'ngx-infinite-scroll'; +import { PostingThreadComponent } from 'app/shared/metis/posting-thread/posting-thread.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-course-wide-search', templateUrl: './course-wide-search.component.html', styleUrls: ['./course-wide-search.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [NgClass, TranslateDirective, FaIconComponent, FormsModule, ReactiveFormsModule, NgbTooltip, InfiniteScrollDirective, PostingThreadComponent, ArtemisTranslatePipe], }) export class CourseWideSearchComponent implements OnInit, AfterViewInit, OnDestroy { + metisService = inject(MetisService); + metisConversationService = inject(MetisConversationService); + private formBuilder = inject(FormBuilder); + cdr = inject(ChangeDetectorRef); + @Input() courseWideSearchConfig: CourseWideSearchConfig; @@ -74,13 +87,6 @@ export class CourseWideSearchComponent implements OnInit, AfterViewInit, OnDestr private courseSidebarService: CourseSidebarService = inject(CourseSidebarService); - constructor( - public metisService: MetisService, // instance from course-conversations.component - public metisConversationService: MetisConversationService, // instance from course-conversations.component - private formBuilder: FormBuilder, - public cdr: ChangeDetectorRef, - ) {} - ngOnInit() { this.subscribeToMetis(); this.resetFormGroup(); diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/abstract-dialog.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/abstract-dialog.component.ts index a42b8aa465ef..4f161f653357 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/abstract-dialog.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/abstract-dialog.component.ts @@ -1,8 +1,9 @@ -import { Directive } from '@angular/core'; +import { Directive, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; @Directive() export abstract class AbstractDialogComponent { + activeModal = inject(NgbActiveModal); isInitialized = false; initialize(requiredInputs?: string[]) { @@ -14,8 +15,6 @@ export abstract class AbstractDialogComponent { } } - constructor(public activeModal: NgbActiveModal) {} - dismiss() { if (this.activeModal) { this.activeModal.dismiss(); diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/channels-create-dialog/channel-form/channel-form.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/channels-create-dialog/channel-form/channel-form.component.ts index bd471be6ca8b..a7c06ca44353 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/channels-create-dialog/channel-form/channel-form.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/channels-create-dialog/channel-form/channel-form.component.ts @@ -1,6 +1,9 @@ -import { Component, EventEmitter, OnChanges, OnDestroy, OnInit, Output } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { Component, EventEmitter, OnChanges, OnDestroy, OnInit, Output, inject } from '@angular/core'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; +import { ChannelIconComponent } from 'app/overview/course-conversations/other/channel-icon/channel-icon.component'; import { Subject, takeUntil } from 'rxjs'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface ChannelFormData { name?: string; @@ -16,8 +19,11 @@ export const channelRegex = new RegExp('^[a-z0-9-]{1}[a-z0-9-]{0,30}$'); @Component({ selector: 'jhi-channel-form', templateUrl: './channel-form.component.html', + imports: [FormsModule, ReactiveFormsModule, TranslateDirective, ChannelIconComponent, ArtemisTranslatePipe], }) export class ChannelFormComponent implements OnInit, OnChanges, OnDestroy { + private fb = inject(FormBuilder); + private ngUnsubscribe = new Subject(); formData: ChannelFormData = { @@ -32,8 +38,6 @@ export class ChannelFormComponent implements OnInit, OnChanges, OnDestroy { form: FormGroup; - constructor(private fb: FormBuilder) {} - get nameControl() { return this.form.get('name'); } diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/channels-create-dialog/channels-create-dialog.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/channels-create-dialog/channels-create-dialog.component.ts index 35c4de065757..14c66dfc94c5 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/channels-create-dialog/channels-create-dialog.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/channels-create-dialog/channels-create-dialog.component.ts @@ -3,14 +3,17 @@ import { ChannelFormData, ChannelType } from 'app/overview/course-conversations/ import { Course } from 'app/entities/course.model'; import { ChannelDTO } from 'app/entities/metis/conversation/channel.model'; import { AbstractDialogComponent } from 'app/overview/course-conversations/dialogs/abstract-dialog.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ChannelFormComponent } from './channel-form/channel-form.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-channels-create-dialog', templateUrl: './channels-create-dialog.component.html', + imports: [TranslateDirective, ChannelFormComponent, ArtemisTranslatePipe], }) export class ChannelsCreateDialogComponent extends AbstractDialogComponent { - @Input() - course: Course; + @Input() course: Course; initialize() { super.initialize(['course']); @@ -19,6 +22,7 @@ export class ChannelsCreateDialogComponent extends AbstractDialogComponent { channelToCreate: ChannelDTO = new ChannelDTO(); isPublicChannel = true; isAnnouncementChannel = false; + onChannelTypeChanged($event: ChannelType) { this.isPublicChannel = $event === 'PUBLIC'; } diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/channels-overview-dialog/channel-item/channel-item.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/channels-overview-dialog/channel-item/channel-item.component.ts index 04e21dcc1f35..de0e0c918479 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/channels-overview-dialog/channel-item/channel-item.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/channels-overview-dialog/channel-item/channel-item.component.ts @@ -1,12 +1,16 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { ChannelDTO } from 'app/entities/metis/conversation/channel.model'; import { ChannelAction, ChannelActionType } from 'app/overview/course-conversations/dialogs/channels-overview-dialog/channels-overview-dialog.component'; +import { ChannelIconComponent } from 'app/overview/course-conversations/other/channel-icon/channel-icon.component'; import { canJoinChannel, canLeaveConversation } from 'app/shared/metis/conversations/conversation-permissions.utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-channel-item', templateUrl: './channel-item.component.html', styleUrls: ['./channel-item.component.scss'], + imports: [ChannelIconComponent, TranslateDirective, ArtemisTranslatePipe], }) export class ChannelItemComponent { canJoinChannel = canJoinChannel; diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/channels-overview-dialog/channels-overview-dialog.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/channels-overview-dialog/channels-overview-dialog.component.ts index deb055e00a5e..45b3bbe9d5c3 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/channels-overview-dialog/channels-overview-dialog.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/channels-overview-dialog/channels-overview-dialog.component.ts @@ -1,15 +1,17 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { Observable, Subject, debounceTime, distinctUntilChanged, finalize, map, takeUntil } from 'rxjs'; import { faChevronRight } from '@fortawesome/free-solid-svg-icons'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { onError } from 'app/shared/util/global.utils'; import { AlertService } from 'app/core/util/alert.service'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { ChannelService } from 'app/shared/metis/conversations/channel.service'; import { ChannelDTO, ChannelSubType } from 'app/entities/metis/conversation/channel.model'; import { Course } from 'app/entities/course.model'; import { canCreateChannel } from 'app/shared/metis/conversations/conversation-permissions.utils'; import { AbstractDialogComponent } from 'app/overview/course-conversations/dialogs/abstract-dialog.component'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { ChannelItemComponent } from './channel-item/channel-item.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export type ChannelActionType = 'register' | 'deregister' | 'view' | 'create'; export type ChannelAction = { @@ -20,19 +22,19 @@ export type ChannelAction = { selector: 'jhi-channels-overview-dialog', templateUrl: './channels-overview-dialog.component.html', styleUrls: ['./channels-overview-dialog.component.scss'], + imports: [LoadingIndicatorContainerComponent, ChannelItemComponent, ArtemisTranslatePipe], }) export class ChannelsOverviewDialogComponent extends AbstractDialogComponent implements OnInit, OnDestroy { + private channelService = inject(ChannelService); + private alertService = inject(AlertService); + private ngUnsubscribe = new Subject(); canCreateChannel = canCreateChannel; - @Input() - createChannelFn?: (channel: ChannelDTO) => Observable; - - @Input() - course: Course; - @Input() - channelSubType: ChannelSubType; + @Input() createChannelFn?: (channel: ChannelDTO) => Observable; + @Input() course: Course; + @Input() channelSubType: ChannelSubType; channelActions$ = new Subject(); @@ -52,15 +54,6 @@ export class ChannelsOverviewDialogComponent extends AbstractDialogComponent imp } } - constructor( - private channelService: ChannelService, - private alertService: AlertService, - - activeModal: NgbActiveModal, - ) { - super(activeModal); - } - ngOnInit(): void { this.channelActions$.pipe(debounceTime(500), distinctUntilChanged(), takeUntil(this.ngUnsubscribe)).subscribe((channelAction) => { this.performChannelAction(channelAction); diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-add-users-dialog/add-users-form/conversation-add-users-form.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-add-users-dialog/add-users-form/conversation-add-users-form.component.ts index f2cec3a67fc5..6a439a7a66d6 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-add-users-dialog/add-users-form/conversation-add-users-form.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-add-users-dialog/add-users-form/conversation-add-users-form.component.ts @@ -1,9 +1,13 @@ -import { Component, EventEmitter, Input, OnChanges, OnInit, Output, input } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, inject, input } from '@angular/core'; import { UserPublicInfoDTO } from 'app/core/user/user.model'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model'; import { getAsChannelDTO } from 'app/entities/metis/conversation/channel.model'; import { faSpinner } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CourseUsersSelectorComponent } from 'app/shared/course-users-selector/course-users-selector.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface AddUsersFormData { selectedUsers?: UserPublicInfoDTO[]; @@ -16,8 +20,11 @@ export interface AddUsersFormData { @Component({ selector: 'jhi-conversation-add-users-form', templateUrl: './conversation-add-users-form.component.html', + imports: [TranslateDirective, FormsModule, ReactiveFormsModule, CourseUsersSelectorComponent, FaIconComponent, ArtemisTranslatePipe], }) export class ConversationAddUsersFormComponent implements OnInit, OnChanges { + private fb = inject(FormBuilder); + @Output() formSubmitted: EventEmitter = new EventEmitter(); @Input() courseId: number; @@ -34,7 +41,6 @@ export class ConversationAddUsersFormComponent implements OnInit, OnChanges { getAsChannel = getAsChannelDTO; mode: 'individual' | 'group' = 'individual'; - constructor(private fb: FormBuilder) {} get selectedUsersControl() { return this.form.get('selectedUsers'); diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-add-users-dialog/conversation-add-users-dialog.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-add-users-dialog/conversation-add-users-dialog.component.ts index 3813b3939fa6..7c578cf22b11 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-add-users-dialog/conversation-add-users-dialog.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-add-users-dialog/conversation-add-users-dialog.component.ts @@ -1,6 +1,5 @@ -import { Component, Input, OnDestroy } from '@angular/core'; +import { Component, Input, OnDestroy, inject } from '@angular/core'; import { AlertService } from 'app/core/util/alert.service'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { AddUsersFormData } from 'app/overview/course-conversations/dialogs/conversation-add-users-dialog/add-users-form/conversation-add-users-form.component'; import { UserPublicInfoDTO } from 'app/core/user/user.model'; import { Course } from 'app/entities/course.model'; @@ -16,12 +15,22 @@ import { GroupChatService } from 'app/shared/metis/conversations/group-chat.serv import { Subject, takeUntil } from 'rxjs'; import { AbstractDialogComponent } from 'app/overview/course-conversations/dialogs/abstract-dialog.component'; import { finalize } from 'rxjs/operators'; +import { ChannelIconComponent } from '../../other/channel-icon/channel-icon.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ConversationAddUsersFormComponent } from './add-users-form/conversation-add-users-form.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-conversation-add-users-dialog', templateUrl: './conversation-add-users-dialog.component.html', + imports: [ChannelIconComponent, TranslateDirective, ConversationAddUsersFormComponent, ArtemisTranslatePipe], }) export class ConversationAddUsersDialogComponent extends AbstractDialogComponent implements OnDestroy { + private alertService = inject(AlertService); + channelService = inject(ChannelService); + conversationService = inject(ConversationService); + groupChatService = inject(GroupChatService); + private ngUnsubscribe = new Subject(); @Input() course: Course; @@ -40,17 +49,6 @@ export class ConversationAddUsersDialogComponent extends AbstractDialogComponent } } - constructor( - private alertService: AlertService, - - activeModal: NgbActiveModal, - public channelService: ChannelService, - public conversationService: ConversationService, - public groupChatService: GroupChatService, - ) { - super(activeModal); - } - ngOnDestroy() { this.ngUnsubscribe.next(); this.ngUnsubscribe.complete(); diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.ts index bd75071f1610..2092c6c13794 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.ts @@ -1,13 +1,19 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model'; import { Course } from 'app/entities/course.model'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { getAsChannelDTO } from 'app/entities/metis/conversation/channel.model'; import { ConversationService } from 'app/shared/metis/conversations/conversation.service'; import { isOneToOneChatDTO } from 'app/entities/metis/conversation/one-to-one-chat.model'; import { getAsGroupChatDTO } from 'app/entities/metis/conversation/group-chat.model'; import { AbstractDialogComponent } from 'app/overview/course-conversations/dialogs/abstract-dialog.component'; import { faPeopleGroup } from '@fortawesome/free-solid-svg-icons'; +import { ChannelIconComponent } from '../../other/channel-icon/channel-icon.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { RouterLink } from '@angular/router'; +import { ConversationMembersComponent } from './tabs/conversation-members/conversation-members.component'; +import { ConversationInfoComponent } from './tabs/conversation-info/conversation-info.component'; +import { ConversationSettingsComponent } from './tabs/conversation-settings/conversation-settings.component'; export enum ConversationDetailTabs { MEMBERS = 'members', @@ -18,8 +24,11 @@ export enum ConversationDetailTabs { @Component({ selector: 'jhi-conversation-detail-dialog', templateUrl: './conversation-detail-dialog.component.html', + imports: [ChannelIconComponent, FaIconComponent, TranslateDirective, RouterLink, ConversationMembersComponent, ConversationInfoComponent, ConversationSettingsComponent], }) export class ConversationDetailDialogComponent extends AbstractDialogComponent { + conversationService = inject(ConversationService); + @Input() public activeConversation: ConversationDTO; @Input() course: Course; @Input() selectedTab: ConversationDetailTabs = ConversationDetailTabs.MEMBERS; @@ -38,12 +47,6 @@ export class ConversationDetailDialogComponent extends AbstractDialogComponent { changesWerePerformed = false; Tabs = ConversationDetailTabs; - constructor( - activeModal: NgbActiveModal, - public conversationService: ConversationService, - ) { - super(activeModal); - } clear() { if (this.changesWerePerformed) { diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.ts index 496322be93a6..e645cf032673 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.ts @@ -20,11 +20,15 @@ import { GroupChatDTO, getAsGroupChatDTO, isGroupChatDTO } from 'app/entities/me import { GroupChatService } from 'app/shared/metis/conversations/group-chat.service'; import { catchError } from 'rxjs/operators'; import { ConversationUserDTO } from 'app/entities/metis/conversation/conversation-user-dto.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-conversation-info', templateUrl: './conversation-info.component.html', styleUrls: ['./conversation-info.component.scss'], + imports: [TranslateDirective, ArtemisDatePipe, ArtemisTranslatePipe], }) export class ConversationInfoComponent implements OnInit, OnDestroy { private ngUnsubscribe = new Subject(); diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.ts index 9112db6a5021..513312fe34a2 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.ts @@ -3,7 +3,7 @@ import { faEllipsis, faUser, faUserCheck, faUserGear, faUserGraduate } from '@fo import { User } from 'app/core/user/user.model'; import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model'; import { AccountService } from 'app/core/auth/account.service'; -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { NgbDropdown, NgbDropdownButtonItem, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle, NgbModal, NgbModalRef, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { EMPTY, Observable, Subject, from, takeUntil } from 'rxjs'; import { Course } from 'app/entities/course.model'; import { canGrantChannelModeratorRole, canRemoveUsersFromConversation, canRevokeChannelModeratorRole } from 'app/shared/metis/conversations/conversation-permissions.utils'; @@ -20,12 +20,27 @@ import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { getAsGroupChatDTO, isGroupChatDTO } from 'app/entities/metis/conversation/group-chat.model'; import { GroupChatService } from 'app/shared/metis/conversations/group-chat.service'; import { catchError } from 'rxjs/operators'; +import { ProfilePictureComponent } from 'app/shared/profile-picture/profile-picture.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ - // eslint-disable-next-line @angular-eslint/component-selector selector: '[jhi-conversation-member-row]', templateUrl: './conversation-member-row.component.html', styleUrls: ['./conversation-member-row.component.scss'], + imports: [ + ProfilePictureComponent, + FaIconComponent, + NgbTooltip, + NgbDropdown, + NgbDropdownToggle, + NgbDropdownMenu, + NgbDropdownButtonItem, + NgbDropdownItem, + TranslateDirective, + ArtemisTranslatePipe, + ], }) export class ConversationMemberRowComponent implements OnInit, OnDestroy { private ngUnsubscribe = new Subject(); diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.ts index 4164cce5f8ca..c4757f1e2622 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.ts @@ -8,12 +8,18 @@ import { AlertService } from 'app/core/util/alert.service'; import { onError } from 'app/shared/util/global.utils'; import { EMPTY, Subject, from, map } from 'rxjs'; import { faMagnifyingGlass, faUserPlus } from '@fortawesome/free-solid-svg-icons'; -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { NgbModal, NgbModalRef, NgbPagination } from '@ng-bootstrap/ng-bootstrap'; import { ConversationAddUsersDialogComponent } from 'app/overview/course-conversations/dialogs/conversation-add-users-dialog/conversation-add-users-dialog.component'; import { getAsChannelDTO, isChannelDTO } from 'app/entities/metis/conversation/channel.model'; import { canAddUsersToConversation } from 'app/shared/metis/conversations/conversation-permissions.utils'; import { ConversationUserDTO } from 'app/entities/metis/conversation/conversation-user-dto.model'; import { defaultSecondLayerDialogOptions } from 'app/overview/course-conversations/other/conversation.util'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { ConversationMemberRowComponent } from './conversation-member-row/conversation-member-row.component'; +import { ItemCountComponent } from 'app/shared/pagination/item-count.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; interface SearchQuery { searchTerm: string; @@ -22,6 +28,7 @@ interface SearchQuery { @Component({ selector: 'jhi-conversation-members', templateUrl: './conversation-members.component.html', + imports: [FaIconComponent, TranslateDirective, FormsModule, ConversationMemberRowComponent, ItemCountComponent, NgbPagination, ArtemisTranslatePipe], }) export class ConversationMembersComponent implements OnInit, OnDestroy { private ngUnsubscribe = new Subject(); diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts index e9e5743b66d7..738c02c9298e 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts @@ -15,11 +15,15 @@ import { GroupChatService } from 'app/shared/metis/conversations/group-chat.serv import { isGroupChatDTO } from 'app/entities/metis/conversation/group-chat.model'; import { defaultSecondLayerDialogOptions } from 'app/overview/course-conversations/other/conversation.util'; import { catchError } from 'rxjs/operators'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-conversation-settings', templateUrl: './conversation-settings.component.html', styleUrls: ['./conversation-settings.component.scss'], + imports: [TranslateDirective, DeleteButtonDirective, FaIconComponent], }) export class ConversationSettingsComponent implements OnInit, OnDestroy { private ngUnsubscribe = new Subject(); diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/generic-confirmation-dialog/generic-confirmation-dialog.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/generic-confirmation-dialog/generic-confirmation-dialog.component.ts index 7389eb84cf83..bb9b1c5bef48 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/generic-confirmation-dialog/generic-confirmation-dialog.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/generic-confirmation-dialog/generic-confirmation-dialog.component.ts @@ -1,6 +1,7 @@ import { Component, Input } from '@angular/core'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { AbstractDialogComponent } from 'app/overview/course-conversations/dialogs/abstract-dialog.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface GenericConfirmationTranslationKeys { titleKey: string; @@ -11,23 +12,13 @@ export interface GenericConfirmationTranslationKeys { @Component({ selector: 'jhi-generic-confirmation-dialog', templateUrl: './generic-confirmation-dialog.component.html', + imports: [TranslateDirective, ArtemisTranslatePipe], }) export class GenericConfirmationDialogComponent extends AbstractDialogComponent { - @Input() - translationParameters = {}; - - @Input() - translationKeys: GenericConfirmationTranslationKeys; - - @Input() - canBeUndone = true; - - @Input() - isDangerousAction = false; - - constructor(activeModal: NgbActiveModal) { - super(activeModal); - } + @Input() translationParameters = {}; + @Input() translationKeys: GenericConfirmationTranslationKeys; + @Input() canBeUndone = true; + @Input() isDangerousAction = false; initialize() { super.initialize(['translationKeys']); diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/generic-update-text-property-dialog/generic-update-text-property-dialog.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/generic-update-text-property-dialog/generic-update-text-property-dialog.component.ts index 6df266a1fbde..c1ca7c07295c 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/generic-update-text-property-dialog/generic-update-text-property-dialog.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/generic-update-text-property-dialog/generic-update-text-property-dialog.component.ts @@ -1,8 +1,9 @@ -import { Component, Input } from '@angular/core'; -import { FormGroup, Validators } from '@angular/forms'; +import { Component, Input, inject } from '@angular/core'; +import { FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { FormBuilder } from '@angular/forms'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { AbstractDialogComponent } from 'app/overview/course-conversations/dialogs/abstract-dialog.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface GenericUpdateTextPropertyTranslationKeys { labelKey: string; @@ -20,25 +21,18 @@ export interface GenericUpdateTextPropertyTranslationKeys { @Component({ selector: 'jhi-generic-update-text-property-dialog', templateUrl: './generic-update-text-property-dialog.component.html', + imports: [FormsModule, ReactiveFormsModule, TranslateDirective, ArtemisTranslatePipe], }) export class GenericUpdateTextPropertyDialogComponent extends AbstractDialogComponent { - @Input() - propertyName: string; + private fb = inject(FormBuilder); - @Input() - isRequired = false; + @Input() propertyName: string; + @Input() isRequired = false; + @Input() regexPattern: RegExp | undefined; + @Input() maxPropertyLength: number; + @Input() initialValue: string | undefined; + @Input() translationKeys: GenericUpdateTextPropertyTranslationKeys; - @Input() - regexPattern: RegExp | undefined; - - @Input() - maxPropertyLength: number; - - @Input() - initialValue: string | undefined; - - @Input() - translationKeys: GenericUpdateTextPropertyTranslationKeys; form: FormGroup; initialize() { @@ -55,12 +49,7 @@ export class GenericUpdateTextPropertyDialogComponent extends AbstractDialogComp get control() { return this.form.get(this.propertyName); } - constructor( - private fb: FormBuilder, - activeModal: NgbActiveModal, - ) { - super(activeModal); - } + private initializeForm() { if (this.form) { return; diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/group-chat-create-dialog/group-chat-create-dialog.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/group-chat-create-dialog/group-chat-create-dialog.component.ts index c694f953f9a3..20ded5b205a0 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/group-chat-create-dialog/group-chat-create-dialog.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/group-chat-create-dialog/group-chat-create-dialog.component.ts @@ -1,24 +1,21 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { Course } from 'app/entities/course.model'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { AbstractDialogComponent } from 'app/overview/course-conversations/dialogs/abstract-dialog.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CourseUsersSelectorComponent } from 'app/shared/course-users-selector/course-users-selector.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-group-chat-create-dialog', templateUrl: './group-chat-create-dialog.component.html', + imports: [TranslateDirective, FormsModule, ReactiveFormsModule, CourseUsersSelectorComponent, ArtemisTranslatePipe], }) export class GroupChatCreateDialogComponent extends AbstractDialogComponent { - @Input() - course: Course; - form: FormGroup; + private fb = inject(FormBuilder); - constructor( - activeModal: NgbActiveModal, - private fb: FormBuilder, - ) { - super(activeModal); - } + @Input() course: Course; + form: FormGroup; initialize() { super.initialize(['course']); diff --git a/src/main/webapp/app/overview/course-conversations/dialogs/one-to-one-chat-create-dialog/one-to-one-chat-create-dialog.component.ts b/src/main/webapp/app/overview/course-conversations/dialogs/one-to-one-chat-create-dialog/one-to-one-chat-create-dialog.component.ts index 669a7b4027f7..e113fe358f0a 100644 --- a/src/main/webapp/app/overview/course-conversations/dialogs/one-to-one-chat-create-dialog/one-to-one-chat-create-dialog.component.ts +++ b/src/main/webapp/app/overview/course-conversations/dialogs/one-to-one-chat-create-dialog/one-to-one-chat-create-dialog.component.ts @@ -1,24 +1,24 @@ import { Component, Input } from '@angular/core'; import { Course } from 'app/entities/course.model'; import { UserPublicInfoDTO } from 'app/core/user/user.model'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { AbstractDialogComponent } from 'app/overview/course-conversations/dialogs/abstract-dialog.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CourseUsersSelectorComponent } from 'app/shared/course-users-selector/course-users-selector.component'; +import { FormsModule } from '@angular/forms'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-one-to-one-chat-create-dialog', templateUrl: './one-to-one-chat-create-dialog.component.html', + imports: [TranslateDirective, CourseUsersSelectorComponent, FormsModule, ArtemisTranslatePipe], }) export class OneToOneChatCreateDialogComponent extends AbstractDialogComponent { - @Input() - course: Course; + @Input() course: Course; isInitialized = false; selectedUsers: UserPublicInfoDTO[] = []; userToChatWith?: UserPublicInfoDTO; - constructor(activeModal: NgbActiveModal) { - super(activeModal); - } initialize() { super.initialize(['course']); } diff --git a/src/main/webapp/app/overview/course-conversations/layout/conversation-header/conversation-header.component.ts b/src/main/webapp/app/overview/course-conversations/layout/conversation-header/conversation-header.component.ts index a8c9ff8ffe26..83f7caf63f97 100644 --- a/src/main/webapp/app/overview/course-conversations/layout/conversation-header/conversation-header.component.ts +++ b/src/main/webapp/app/overview/course-conversations/layout/conversation-header/conversation-header.component.ts @@ -20,13 +20,24 @@ import { MetisService } from 'app/shared/metis/metis.service'; import { CourseSidebarService } from 'app/overview/course-sidebar.service'; import { getAsOneToOneChatDTO } from 'app/entities/metis/conversation/one-to-one-chat.model'; import { ConversationUserDTO } from 'app/entities/metis/conversation/conversation-user-dto.model'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ChannelIconComponent } from '../../other/channel-icon/channel-icon.component'; +import { ProfilePictureComponent } from 'app/shared/profile-picture/profile-picture.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { RouterLink } from '@angular/router'; @Component({ selector: 'jhi-conversation-header', templateUrl: './conversation-header.component.html', styleUrls: ['./conversation-header.component.scss'], + imports: [FaIconComponent, ChannelIconComponent, ProfilePictureComponent, TranslateDirective, RouterLink], }) export class ConversationHeaderComponent implements OnInit, OnDestroy { + private modalService = inject(NgbModal); + metisConversationService = inject(MetisConversationService); + conversationService = inject(ConversationService); + private metisService = inject(MetisService); + private ngUnsubscribe = new Subject(); @Output() collapseSearch = new EventEmitter(); @@ -51,14 +62,6 @@ export class ConversationHeaderComponent implements OnInit, OnDestroy { private courseSidebarService: CourseSidebarService = inject(CourseSidebarService); - constructor( - private modalService: NgbModal, - // instantiated at course-conversation.component.ts - public metisConversationService: MetisConversationService, - public conversationService: ConversationService, - private metisService: MetisService, - ) {} - getAsGroupChat = getAsGroupChatDTO; getAsOneToOneChat = getAsOneToOneChatDTO; diff --git a/src/main/webapp/app/overview/course-conversations/layout/conversation-messages/conversation-messages.component.ts b/src/main/webapp/app/overview/course-conversations/layout/conversation-messages/conversation-messages.component.ts index ddac0b0efacb..694c0cbe3d7b 100644 --- a/src/main/webapp/app/overview/course-conversations/layout/conversation-messages/conversation-messages.component.ts +++ b/src/main/webapp/app/overview/course-conversations/layout/conversation-messages/conversation-messages.component.ts @@ -9,7 +9,6 @@ import { OnInit, Output, QueryList, - Renderer2, ViewChild, ViewChildren, ViewEncapsulation, @@ -36,6 +35,13 @@ import { CustomBreakpointNames } from 'app/shared/breakpoints/breakpoints.servic import dayjs from 'dayjs/esm'; import { User } from 'app/core/user/user.model'; import { PostingThreadComponent } from 'app/shared/metis/posting-thread/posting-thread.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { InfiniteScrollDirective } from 'ngx-infinite-scroll'; +import { NgClass } from '@angular/common'; +import { PostCreateEditModalComponent } from 'app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-create-edit-modal.component'; +import { MessageInlineInputComponent } from 'app/shared/metis/message/message-inline-input/message-inline-input.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; interface PostGroup { author: User | undefined; @@ -47,8 +53,22 @@ interface PostGroup { templateUrl: './conversation-messages.component.html', styleUrls: ['./conversation-messages.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [ + FaIconComponent, + TranslateDirective, + InfiniteScrollDirective, + NgClass, + PostingThreadComponent, + PostCreateEditModalComponent, + MessageInlineInputComponent, + ArtemisTranslatePipe, + ], }) export class ConversationMessagesComponent implements OnInit, AfterViewInit, OnDestroy { + metisService = inject(MetisService); + metisConversationService = inject(MetisConversationService); + cdr = inject(ChangeDetectorRef); + private ngUnsubscribe = new Subject(); readonly sessionStorageKey = 'conversationId.scrollPosition.'; @@ -62,19 +82,14 @@ export class ConversationMessagesComponent implements OnInit, AfterViewInit, OnD @Output() openThread = new EventEmitter(); - @ViewChild('searchInput') - searchInput: ElementRef; - - @ViewChildren('postingThread') - messages: QueryList; - @ViewChild('container') - content: ElementRef; - @Input() - course?: Course; - @Input() - searchbarCollapsed = false; - @Input() - contentHeightDev: boolean = false; + @ViewChild('searchInput') searchInput: ElementRef; + @ViewChildren('postingThread') messages: QueryList; + @ViewChild('container') content: ElementRef; + + @Input() course?: Course; + @Input() searchbarCollapsed = false; + @Input() contentHeightDev: boolean = false; + readonly focusPostId = input(undefined); readonly openThreadOnFocus = input(false); @@ -109,13 +124,8 @@ export class ConversationMessagesComponent implements OnInit, AfterViewInit, OnD isOpenThreadOnFocus: boolean = false; private layoutService: LayoutService = inject(LayoutService); - private renderer = inject(Renderer2); - constructor( - public metisService: MetisService, // instance from course-conversations.component - public metisConversationService: MetisConversationService, // instance from course-conversations.component - public cdr: ChangeDetectorRef, - ) { + constructor() { effect(() => { this.focusOnPostId = this.focusPostId(); this.isOpenThreadOnFocus = this.openThreadOnFocus(); @@ -355,9 +365,9 @@ export class ConversationMessagesComponent implements OnInit, AfterViewInit, OnD return this.metisService.createEmptyPostForContext(conversation); } - postsGroupTrackByFn = (index: number, post: PostGroup): string => 'grp_' + post.posts.map((p) => p.id?.toString()).join('_'); + postsGroupTrackByFn = (_index: number, post: PostGroup): string => 'grp_' + post.posts.map((p) => p.id?.toString()).join('_'); - postsTrackByFn = (index: number, post: Post): string => 'post_' + post.id!; + postsTrackByFn = (_index: number, post: Post): string => 'post_' + post.id!; setPostForThread(post: Post) { this.openThread.emit(post); diff --git a/src/main/webapp/app/overview/course-conversations/layout/conversation-thread-sidebar/conversation-thread-sidebar.component.ts b/src/main/webapp/app/overview/course-conversations/layout/conversation-thread-sidebar/conversation-thread-sidebar.component.ts index 2307a9f9d182..780198d01f2a 100644 --- a/src/main/webapp/app/overview/course-conversations/layout/conversation-thread-sidebar/conversation-thread-sidebar.component.ts +++ b/src/main/webapp/app/overview/course-conversations/layout/conversation-thread-sidebar/conversation-thread-sidebar.component.ts @@ -5,11 +5,18 @@ import { faArrowLeft, faChevronLeft, faGripLinesVertical, faXmark } from '@forta import { AnswerPost } from 'app/entities/metis/answer-post.model'; import { Conversation, ConversationDTO } from 'app/entities/metis/conversation/conversation.model'; import { getAsChannelDTO } from 'app/entities/metis/conversation/channel.model'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { PostComponent } from 'app/shared/metis/post/post.component'; +import { MessageReplyInlineInputComponent } from 'app/shared/metis/message/message-reply-inline-input/message-reply-inline-input.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-conversation-thread-sidebar', templateUrl: './conversation-thread-sidebar.component.html', styleUrls: ['./conversation-thread-sidebar.component.scss'], + imports: [FaIconComponent, TranslateDirective, NgbTooltip, PostComponent, MessageReplyInlineInputComponent, ArtemisTranslatePipe], }) export class ConversationThreadSidebarComponent implements AfterViewInit { @ViewChild('scrollBody', { static: false }) scrollBody?: ElementRef; diff --git a/src/main/webapp/app/overview/course-conversations/other/channel-icon/channel-icon.component.ts b/src/main/webapp/app/overview/course-conversations/other/channel-icon/channel-icon.component.ts index e42fa8358454..6dda4bb3f70b 100644 --- a/src/main/webapp/app/overview/course-conversations/other/channel-icon/channel-icon.component.ts +++ b/src/main/webapp/app/overview/course-conversations/other/channel-icon/channel-icon.component.ts @@ -1,9 +1,11 @@ import { Component, Input } from '@angular/core'; import { faBoxArchive, faBullhorn, faHashtag, faLock } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-channel-icon', templateUrl: './channel-icon.component.html', + imports: [FaIconComponent], }) export class ChannelIconComponent { @Input() diff --git a/src/main/webapp/app/overview/course-conversations/posting-summary/posting-summary.component.ts b/src/main/webapp/app/overview/course-conversations/posting-summary/posting-summary.component.ts index 6e5b23539180..ed80391c59cc 100644 --- a/src/main/webapp/app/overview/course-conversations/posting-summary/posting-summary.component.ts +++ b/src/main/webapp/app/overview/course-conversations/posting-summary/posting-summary.component.ts @@ -3,11 +3,20 @@ import { Posting, PostingType, SavedPostStatus } from 'app/entities/metis/postin import { faBookmark, faBoxArchive, faCheckSquare, faEllipsis, faHashtag, faLock } from '@fortawesome/free-solid-svg-icons'; import { ConversationType } from 'app/entities/metis/conversation/conversation.model'; import dayjs from 'dayjs/esm'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgClass } from '@angular/common'; +import { ProfilePictureComponent } from 'app/shared/profile-picture/profile-picture.component'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { PostingContentComponent } from 'app/shared/metis/posting-content/posting-content.components'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-posting-summary', templateUrl: './posting-summary.component.html', styleUrls: ['./posting-summary.component.scss'], + imports: [FaIconComponent, TranslateDirective, NgClass, ProfilePictureComponent, NgbTooltip, PostingContentComponent, ArtemisDatePipe, ArtemisTranslatePipe], }) export class PostingSummaryComponent { readonly post = input(); diff --git a/src/main/webapp/app/overview/course-conversations/saved-posts/saved-posts.component.ts b/src/main/webapp/app/overview/course-conversations/saved-posts/saved-posts.component.ts index f3606114b830..126b0691fafd 100644 --- a/src/main/webapp/app/overview/course-conversations/saved-posts/saved-posts.component.ts +++ b/src/main/webapp/app/overview/course-conversations/saved-posts/saved-posts.component.ts @@ -2,11 +2,15 @@ import { Component, effect, inject, input, output } from '@angular/core'; import { Posting, SavedPostStatus, SavedPostStatusMap } from 'app/entities/metis/posting.model'; import { SavedPostService } from 'app/shared/metis/saved-post.service'; import { faBookmark, faInfoCircle } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { PostingSummaryComponent } from '../posting-summary/posting-summary.component'; @Component({ selector: 'jhi-saved-posts', templateUrl: './saved-posts.component.html', styleUrls: ['./saved-posts.component.scss'], + imports: [TranslateDirective, FaIconComponent, PostingSummaryComponent], }) export class SavedPostsComponent { readonly savedPostStatus = input(); diff --git a/src/main/webapp/app/overview/course-dashboard/course-dashboard.component.ts b/src/main/webapp/app/overview/course-dashboard/course-dashboard.component.ts index 469ec9257996..9b54d2eb1616 100644 --- a/src/main/webapp/app/overview/course-dashboard/course-dashboard.component.ts +++ b/src/main/webapp/app/overview/course-dashboard/course-dashboard.component.ts @@ -1,4 +1,4 @@ -import { Component, ElementRef, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core'; +import { Component, ElementRef, OnDestroy, OnInit, QueryList, ViewChildren, inject } from '@angular/core'; import { CourseStorageService } from 'app/course/manage/course-storage.service'; import { Subscription } from 'rxjs'; import { ActivatedRoute, Router } from '@angular/router'; @@ -18,13 +18,38 @@ import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { PROFILE_IRIS } from 'app/app.constants'; import { CompetencyAccordionToggleEvent } from 'app/course/competencies/competency-accordion/competency-accordion.component'; import { AccountService } from 'app/core/auth/account.service'; +import { CourseChatbotComponent } from '../../iris/course-chatbot/course-chatbot.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbProgressbar } from '@ng-bootstrap/ng-bootstrap'; +import { CourseExercisePerformanceComponent } from './course-exercise-performance/course-exercise-performance.component'; +import { CourseExerciseLatenessComponent } from './course-exercise-lateness/course-exercise-lateness.component'; +import { CompetencyAccordionComponent } from '../../course/competencies/competency-accordion/competency-accordion.component'; +import { FeatureToggleHideDirective } from 'app/shared/feature-toggle/feature-toggle-hide.directive'; @Component({ selector: 'jhi-course-dashboard', templateUrl: './course-dashboard.component.html', styleUrls: ['./course-dashboard.component.scss'], + imports: [ + CourseChatbotComponent, + TranslateDirective, + NgbProgressbar, + CourseExercisePerformanceComponent, + CourseExerciseLatenessComponent, + CompetencyAccordionComponent, + FeatureToggleHideDirective, + ], }) export class CourseDashboardComponent implements OnInit, OnDestroy { + private courseStorageService = inject(CourseStorageService); + private alertService = inject(AlertService); + private route = inject(ActivatedRoute); + private router = inject(Router); + private courseDashboardService = inject(CourseDashboardService); + private irisSettingsService = inject(IrisSettingsService); + private profileService = inject(ProfileService); + private accountService = inject(AccountService); + courseId: number; exerciseId: number; points: number = 0; @@ -52,17 +77,6 @@ export class CourseDashboardComponent implements OnInit, OnDestroy { @ViewChildren('competencyAccordionElement', { read: ElementRef }) competencyAccordions: QueryList; - constructor( - private courseStorageService: CourseStorageService, - private alertService: AlertService, - private route: ActivatedRoute, - private router: Router, - private courseDashboardService: CourseDashboardService, - private irisSettingsService: IrisSettingsService, - private profileService: ProfileService, - private accountService: AccountService, - ) {} - ngOnInit(): void { this.paramSubscription = this.route.parent?.parent?.params.subscribe((params) => { this.courseId = parseInt(params['courseId'], 10); diff --git a/src/main/webapp/app/overview/course-dashboard/course-dashboard.module.ts b/src/main/webapp/app/overview/course-dashboard/course-dashboard.module.ts index 834b3db16f4a..126431958157 100644 --- a/src/main/webapp/app/overview/course-dashboard/course-dashboard.module.ts +++ b/src/main/webapp/app/overview/course-dashboard/course-dashboard.module.ts @@ -2,6 +2,7 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; import { CourseDashboardComponent } from 'app/overview/course-dashboard/course-dashboard.component'; + import { ArtemisSharedModule } from 'app/shared/shared.module'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; import { RouterModule, Routes } from '@angular/router'; @@ -14,14 +15,14 @@ import { ArtemisSharedComponentModule } from 'app/shared/components/shared-compo import { NgxDatatableModule } from '@siemens/ngx-datatable'; import { LineChartModule } from '@swimlane/ngx-charts'; import { IrisModule } from 'app/iris/iris.module'; -import { FeatureToggleModule } from 'app/shared/feature-toggle/feature-toggle.module'; + import { ArtemisCompetenciesModule } from 'app/course/competencies/competency.module'; const routes: Routes = [ { path: '', pathMatch: 'full', - component: CourseDashboardComponent, + loadComponent: () => import('app/overview/course-dashboard/course-dashboard.component').then((m) => m.CourseDashboardComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.dashboard', @@ -31,7 +32,6 @@ const routes: Routes = [ ]; @NgModule({ - declarations: [CourseDashboardComponent, CourseExercisePerformanceComponent, CourseExerciseLatenessComponent], exports: [CourseDashboardComponent], imports: [ CommonModule, @@ -44,8 +44,10 @@ const routes: Routes = [ ArtemisSharedComponentModule, LineChartModule, IrisModule, - FeatureToggleModule, ArtemisCompetenciesModule, + CourseDashboardComponent, + CourseExercisePerformanceComponent, + CourseExerciseLatenessComponent, ], }) export class CourseDashboardModule {} diff --git a/src/main/webapp/app/overview/course-dashboard/course-dashboard.service.ts b/src/main/webapp/app/overview/course-dashboard/course-dashboard.service.ts index a6a1e09c0750..daf177e123ef 100644 --- a/src/main/webapp/app/overview/course-dashboard/course-dashboard.service.ts +++ b/src/main/webapp/app/overview/course-dashboard/course-dashboard.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable, map } from 'rxjs'; import { CompetencyMetrics, ExerciseInformation, LectureUnitInformation, StudentMetrics } from 'app/entities/student-metrics.model'; @@ -10,9 +10,9 @@ import { CompetencyJol } from 'app/entities/competency.model'; @Injectable({ providedIn: 'root' }) export class CourseDashboardService { - public resourceUrl = 'api/metrics'; + private http = inject(HttpClient); - constructor(private http: HttpClient) {} + public resourceUrl = 'api/metrics'; getCourseMetricsForUser(courseId: number): Observable> { return this.http.get(`${this.resourceUrl}/course/${courseId}/student`, { observe: 'response' }).pipe( diff --git a/src/main/webapp/app/overview/course-dashboard/course-exercise-lateness/course-exercise-lateness.component.ts b/src/main/webapp/app/overview/course-dashboard/course-exercise-lateness/course-exercise-lateness.component.ts index 0192a35fff98..c69dafbe0da2 100644 --- a/src/main/webapp/app/overview/course-dashboard/course-exercise-lateness/course-exercise-lateness.component.ts +++ b/src/main/webapp/app/overview/course-dashboard/course-exercise-lateness/course-exercise-lateness.component.ts @@ -1,10 +1,13 @@ -import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, OnChanges, OnDestroy, OnInit, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; -import { Color, ScaleType } from '@swimlane/ngx-charts'; +import { Color, LineChartModule, ScaleType } from '@swimlane/ngx-charts'; import { GraphColors } from 'app/entities/statistics.model'; import { NgxChartsMultiSeriesDataEntry } from 'app/shared/chart/ngx-charts-datatypes'; import { round } from 'app/shared/util/utils'; import { Subscription } from 'rxjs'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface ExerciseLateness { exerciseId: number; @@ -21,8 +24,11 @@ const AVERAGE_GRAPH_COLOR = GraphColors.YELLOW; selector: 'jhi-course-exercise-lateness', templateUrl: './course-exercise-lateness.component.html', styleUrls: ['./course-exercise-lateness.component.scss'], + imports: [TranslateDirective, HelpIconComponent, LineChartModule, ArtemisTranslatePipe], }) export class CourseExerciseLatenessComponent implements OnInit, OnChanges, OnDestroy { + private translateService = inject(TranslateService); + @Input() exerciseLateness: ExerciseLateness[] = []; yourLatenessLabel: string; @@ -42,7 +48,7 @@ export class CourseExerciseLatenessComponent implements OnInit, OnChanges, OnDes protected readonly YOUR_GRAPH_COLOR = YOUR_GRAPH_COLOR; protected readonly AVERAGE_GRAPH_COLOR = AVERAGE_GRAPH_COLOR; - constructor(private translateService: TranslateService) { + constructor() { this.translateServiceSubscription = this.translateService.onLangChange.subscribe(() => { this.setupChart(); }); diff --git a/src/main/webapp/app/overview/course-dashboard/course-exercise-performance/course-exercise-performance.component.ts b/src/main/webapp/app/overview/course-dashboard/course-exercise-performance/course-exercise-performance.component.ts index 127b4ad92bb7..db775e1a95c5 100644 --- a/src/main/webapp/app/overview/course-dashboard/course-exercise-performance/course-exercise-performance.component.ts +++ b/src/main/webapp/app/overview/course-dashboard/course-exercise-performance/course-exercise-performance.component.ts @@ -1,10 +1,13 @@ -import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, OnChanges, OnDestroy, OnInit, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; -import { Color, ScaleType } from '@swimlane/ngx-charts'; +import { Color, LineChartModule, ScaleType } from '@swimlane/ngx-charts'; import { GraphColors } from 'app/entities/statistics.model'; import { NgxChartsMultiSeriesDataEntry } from 'app/shared/chart/ngx-charts-datatypes'; import { round } from 'app/shared/util/utils'; import { Subscription } from 'rxjs'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; export interface ExercisePerformance { exerciseId: number; @@ -21,8 +24,11 @@ const AVERAGE_GRAPH_COLOR = GraphColors.YELLOW; selector: 'jhi-course-exercise-performance', templateUrl: './course-exercise-performance.component.html', styleUrls: ['./course-exercise-performance.component.scss'], + imports: [TranslateDirective, HelpIconComponent, LineChartModule, ArtemisTranslatePipe], }) export class CourseExercisePerformanceComponent implements OnInit, OnChanges, OnDestroy { + private translateService = inject(TranslateService); + @Input() exercisePerformance: ExercisePerformance[] = []; yourScoreLabel: string; @@ -41,7 +47,7 @@ export class CourseExercisePerformanceComponent implements OnInit, OnChanges, On protected readonly YOUR_GRAPH_COLOR = YOUR_GRAPH_COLOR; protected readonly AVERAGE_GRAPH_COLOR = AVERAGE_GRAPH_COLOR; - constructor(private translateService: TranslateService) { + constructor() { this.translateServiceSubscription = this.translateService.onLangChange.subscribe(() => { this.setupChart(); }); diff --git a/src/main/webapp/app/overview/course-exams/course-exams.component.ts b/src/main/webapp/app/overview/course-exams/course-exams.component.ts index 33e28167ea69..4b59e30d337f 100644 --- a/src/main/webapp/app/overview/course-exams/course-exams.component.ts +++ b/src/main/webapp/app/overview/course-exams/course-exams.component.ts @@ -1,6 +1,6 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { Course } from 'app/entities/course.model'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterOutlet } from '@angular/router'; import { Subscription } from 'rxjs'; import { Exam } from 'app/entities/exam/exam.model'; import dayjs from 'dayjs/esm'; @@ -13,6 +13,9 @@ import { AccordionGroups, CollapseState, SidebarCardElement, SidebarData } from import { CourseOverviewService } from '../course-overview.service'; import { cloneDeep } from 'lodash-es'; import { lastValueFrom } from 'rxjs'; +import { NgClass } from '@angular/common'; +import { SidebarComponent } from 'app/shared/sidebar/sidebar.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; const DEFAULT_UNIT_GROUPS: AccordionGroups = { real: { entityData: [] }, @@ -33,8 +36,16 @@ const DEFAULT_SHOW_ALWAYS: CollapseState = { selector: 'jhi-course-exams', templateUrl: './course-exams.component.html', styleUrls: ['./course-exams.component.scss'], + imports: [NgClass, SidebarComponent, RouterOutlet, TranslateDirective], }) export class CourseExamsComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private courseStorageService = inject(CourseStorageService); + private serverDateService = inject(ArtemisServerDateService); + private examParticipationService = inject(ExamParticipationService); + private courseOverviewService = inject(CourseOverviewService); + private router = inject(Router); + courseId: number; public course?: Course; private parentParamSubscription?: Subscription; @@ -64,15 +75,6 @@ export class CourseExamsComponent implements OnInit, OnDestroy { readonly DEFAULT_COLLAPSE_STATE = DEFAULT_COLLAPSE_STATE; protected readonly DEFAULT_SHOW_ALWAYS = DEFAULT_SHOW_ALWAYS; - constructor( - private route: ActivatedRoute, - private courseStorageService: CourseStorageService, - private serverDateService: ArtemisServerDateService, - private examParticipationService: ExamParticipationService, - private courseOverviewService: CourseOverviewService, - private router: Router, - ) {} - /** * subscribe to changes in the course and fetch course by the path parameter */ diff --git a/src/main/webapp/app/overview/course-exams/course-exams.module.ts b/src/main/webapp/app/overview/course-exams/course-exams.module.ts index 3bbf8e98043b..69d09384d273 100644 --- a/src/main/webapp/app/overview/course-exams/course-exams.module.ts +++ b/src/main/webapp/app/overview/course-exams/course-exams.module.ts @@ -7,8 +7,7 @@ import { ArtemisSharedComponentModule } from 'app/shared/components/shared-compo import { ArtemisSidebarModule } from 'app/shared/sidebar/sidebar.module'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisSharedCommonModule, ArtemisSharedComponentModule, ArtemisExamSharedModule, ArtemisSidebarModule], - declarations: [CourseExamsComponent], + imports: [ArtemisSharedModule, ArtemisSharedCommonModule, ArtemisSharedComponentModule, ArtemisExamSharedModule, ArtemisSidebarModule, CourseExamsComponent], exports: [CourseExamsComponent], }) export class CourseExamsModule {} diff --git a/src/main/webapp/app/overview/course-exams/course-exams.route.ts b/src/main/webapp/app/overview/course-exams/course-exams.route.ts index 2e2a7264c14a..fc8482570ee0 100644 --- a/src/main/webapp/app/overview/course-exams/course-exams.route.ts +++ b/src/main/webapp/app/overview/course-exams/course-exams.route.ts @@ -1,12 +1,11 @@ import { Routes } from '@angular/router'; import { Authority } from 'app/shared/constants/authority.constants'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { CourseExamsComponent } from 'app/overview/course-exams/course-exams.component'; export const routes: Routes = [ { path: '', - component: CourseExamsComponent, + loadComponent: () => import('app/overview/course-exams/course-exams.component').then((m) => m.CourseExamsComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.exams', diff --git a/src/main/webapp/app/overview/course-exercises/course-exercise-row.component.ts b/src/main/webapp/app/overview/course-exercises/course-exercise-row.component.ts index d61d2da89cb5..cbf8b6fcf8b6 100644 --- a/src/main/webapp/app/overview/course-exercises/course-exercise-row.component.ts +++ b/src/main/webapp/app/overview/course-exercises/course-exercise-row.component.ts @@ -1,4 +1,4 @@ -import { Component, HostBinding, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; +import { Component, HostBinding, Input, OnChanges, OnDestroy, OnInit, inject } from '@angular/core'; import { ParticipationService } from 'app/exercises/shared/participation/participation.service'; import { ParticipationWebsocketService } from 'app/overview/participation-websocket.service'; import dayjs from 'dayjs/esm'; @@ -11,13 +11,44 @@ import { Exercise, ExerciseType, IncludedInOverallScore, getIcon, getIconTooltip import { ExerciseService } from 'app/exercises/shared/exercise/exercise.service'; import { getExerciseDueDate } from 'app/exercises/shared/exercise/exercise.utils'; import { ExerciseCategory } from 'app/entities/exercise-category.model'; +import { RouterLink } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { SubmissionResultStatusComponent } from '../submission-result-status.component'; +import { ExerciseDetailsStudentActionsComponent } from '../exercise-details/exercise-details-student-actions.component'; +import { OrionFilterDirective } from 'app/shared/orion/orion-filter.directive'; +import { NgClass } from '@angular/common'; +import { ExerciseCategoriesComponent } from 'app/shared/exercise-categories/exercise-categories.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { ArtemisTimeAgoPipe } from 'app/shared/pipes/artemis-time-ago.pipe'; @Component({ selector: 'jhi-course-exercise-row', templateUrl: './course-exercise-row.component.html', styleUrls: ['./course-exercise-row.scss'], + imports: [ + RouterLink, + FaIconComponent, + NgbTooltip, + SubmissionResultStatusComponent, + ExerciseDetailsStudentActionsComponent, + OrionFilterDirective, + NgClass, + ExerciseCategoriesComponent, + TranslateDirective, + ArtemisDatePipe, + ArtemisTranslatePipe, + ArtemisTimeAgoPipe, + ], }) export class CourseExerciseRowComponent implements OnInit, OnDestroy, OnChanges { + private accountService = inject(AccountService); + private participationService = inject(ParticipationService); + private exerciseService = inject(ExerciseService); + private participationWebsocketService = inject(ParticipationWebsocketService); + readonly IncludedInOverallScore = IncludedInOverallScore; readonly dayjs = dayjs; @HostBinding('class') classes = 'exercise-row'; @@ -40,13 +71,6 @@ export class CourseExerciseRowComponent implements OnInit, OnDestroy, OnChanges participationUpdateListener: Subscription; - constructor( - private accountService: AccountService, - private participationService: ParticipationService, - private exerciseService: ExerciseService, - private participationWebsocketService: ParticipationWebsocketService, - ) {} - ngOnInit() { if (this.exercise?.studentParticipations?.length) { this.gradedStudentParticipation = this.participationService.getSpecificStudentParticipation(this.exercise.studentParticipations, false); diff --git a/src/main/webapp/app/overview/course-exercises/course-exercise-row.module.ts b/src/main/webapp/app/overview/course-exercises/course-exercise-row.module.ts index 50b444611e85..a7c9cf14a21a 100644 --- a/src/main/webapp/app/overview/course-exercises/course-exercise-row.module.ts +++ b/src/main/webapp/app/overview/course-exercises/course-exercise-row.module.ts @@ -21,8 +21,8 @@ import { ExerciseCategoriesModule } from 'app/shared/exercise-categories/exercis GradingKeyOverviewModule, SubmissionResultStatusModule, ExerciseCategoriesModule, + CourseExerciseRowComponent, ], - declarations: [CourseExerciseRowComponent], exports: [CourseExerciseRowComponent], }) export class ArtemisCourseExerciseRowModule {} diff --git a/src/main/webapp/app/overview/course-exercises/course-exercises.component.ts b/src/main/webapp/app/overview/course-exercises/course-exercises.component.ts index 5f0adeed54b5..abd416b192c6 100644 --- a/src/main/webapp/app/overview/course-exercises/course-exercises.component.ts +++ b/src/main/webapp/app/overview/course-exercises/course-exercises.component.ts @@ -1,6 +1,6 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { Course } from 'app/entities/course.model'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterOutlet } from '@angular/router'; import { Subscription } from 'rxjs'; import { GuidedTourService } from 'app/guided-tour/guided-tour.service'; import { courseExerciseOverviewTour } from 'app/guided-tour/tours/course-exercise-overview-tour'; @@ -10,6 +10,9 @@ import { CourseStorageService } from 'app/course/manage/course-storage.service'; import { AccordionGroups, CollapseState, SidebarCardElement, SidebarData, SidebarItemShowAlways } from 'app/types/sidebar'; import { CourseOverviewService } from '../course-overview.service'; import { LtiService } from 'app/shared/service/lti.service'; +import { NgClass, NgStyle } from '@angular/common'; +import { SidebarComponent } from 'app/shared/sidebar/sidebar.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; const DEFAULT_UNIT_GROUPS: AccordionGroups = { future: { entityData: [] }, @@ -39,8 +42,17 @@ const DEFAULT_SHOW_ALWAYS: SidebarItemShowAlways = { selector: 'jhi-course-exercises', templateUrl: './course-exercises.component.html', styleUrls: ['../course-overview.scss'], + imports: [NgClass, SidebarComponent, NgStyle, RouterOutlet, TranslateDirective], }) export class CourseExercisesComponent implements OnInit, OnDestroy { + private courseStorageService = inject(CourseStorageService); + private route = inject(ActivatedRoute); + private guidedTourService = inject(GuidedTourService); + private programmingSubmissionService = inject(ProgrammingSubmissionService); + private router = inject(Router); + private courseOverviewService = inject(CourseOverviewService); + private ltiService = inject(LtiService); + private parentParamSubscription: Subscription; private courseUpdatesSubscription: Subscription; private ltiSubscription: Subscription; @@ -60,16 +72,6 @@ export class CourseExercisesComponent implements OnInit, OnDestroy { protected readonly DEFAULT_COLLAPSE_STATE = DEFAULT_COLLAPSE_STATE; protected readonly DEFAULT_SHOW_ALWAYS = DEFAULT_SHOW_ALWAYS; - constructor( - private courseStorageService: CourseStorageService, - private route: ActivatedRoute, - private guidedTourService: GuidedTourService, - private programmingSubmissionService: ProgrammingSubmissionService, - private router: Router, - private courseOverviewService: CourseOverviewService, - private ltiService: LtiService, - ) {} - ngOnInit() { this.isCollapsed = this.courseOverviewService.getSidebarCollapseStateFromStorage('exercise'); this.parentParamSubscription = this.route.parent!.params.subscribe((params) => { diff --git a/src/main/webapp/app/overview/course-faq/course-faq-accordion-component.ts b/src/main/webapp/app/overview/course-faq/course-faq-accordion-component.ts index 881a07f2d784..28233b9b60d1 100644 --- a/src/main/webapp/app/overview/course-faq/course-faq-accordion-component.ts +++ b/src/main/webapp/app/overview/course-faq/course-faq-accordion-component.ts @@ -1,5 +1,4 @@ import { Component, OnDestroy, input } from '@angular/core'; -import { TranslateDirective } from 'app/shared/language/translate.directive'; import { Faq } from 'app/entities/faq.model'; import { CustomExerciseCategoryBadgeComponent } from 'app/shared/exercise-categories/custom-exercise-category-badge/custom-exercise-category-badge.component'; import { Subject } from 'rxjs/internal/Subject'; @@ -9,9 +8,7 @@ import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; selector: 'jhi-course-faq-accordion', templateUrl: './course-faq-accordion.component.html', styleUrl: './course-faq-accordion.component.scss', - standalone: true, - - imports: [TranslateDirective, CustomExerciseCategoryBadgeComponent, ArtemisMarkdownModule], + imports: [CustomExerciseCategoryBadgeComponent, ArtemisMarkdownModule], }) export class CourseFaqAccordionComponent implements OnDestroy { private ngUnsubscribe = new Subject(); diff --git a/src/main/webapp/app/overview/course-faq/course-faq.component.ts b/src/main/webapp/app/overview/course-faq/course-faq.component.ts index 8138013ad4fa..0be571a70de4 100644 --- a/src/main/webapp/app/overview/course-faq/course-faq.component.ts +++ b/src/main/webapp/app/overview/course-faq/course-faq.component.ts @@ -19,14 +19,22 @@ import { SearchFilterComponent } from 'app/shared/search-filter/search-filter.co import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; import { SortService } from 'app/shared/service/sort.service'; import { Renderer2 } from '@angular/core'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; @Component({ selector: 'jhi-course-faq', templateUrl: './course-faq.component.html', styleUrls: ['../course-overview.scss', 'course-faq.component.scss'], encapsulation: ViewEncapsulation.None, - standalone: true, - imports: [ArtemisSharedComponentModule, ArtemisSharedModule, CourseFaqAccordionComponent, CustomExerciseCategoryBadgeComponent, SearchFilterComponent, ArtemisMarkdownModule], + imports: [ + ArtemisSharedComponentModule, + ArtemisSharedModule, + CourseFaqAccordionComponent, + CustomExerciseCategoryBadgeComponent, + SearchFilterComponent, + ArtemisMarkdownModule, + NgbModule, + ], }) export class CourseFaqComponent implements OnInit, OnDestroy { faqElements = viewChildren('faqElement'); diff --git a/src/main/webapp/app/overview/course-lectures/attachment-unit/attachment-unit.component.ts b/src/main/webapp/app/overview/course-lectures/attachment-unit/attachment-unit.component.ts index ecc6c9f39f85..cde836380a81 100644 --- a/src/main/webapp/app/overview/course-lectures/attachment-unit/attachment-unit.component.ts +++ b/src/main/webapp/app/overview/course-lectures/attachment-unit/attachment-unit.component.ts @@ -22,7 +22,6 @@ import { FileService } from 'app/shared/http/file.service'; @Component({ selector: 'jhi-attachment-unit', - standalone: true, imports: [LectureUnitComponent, ArtemisSharedCommonModule], templateUrl: './attachment-unit.component.html', }) diff --git a/src/main/webapp/app/overview/course-lectures/course-lecture-details.component.ts b/src/main/webapp/app/overview/course-lectures/course-lecture-details.component.ts index 14cc75d10ef7..301803ba2bea 100644 --- a/src/main/webapp/app/overview/course-lectures/course-lecture-details.component.ts +++ b/src/main/webapp/app/overview/course-lectures/course-lecture-details.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { HttpErrorResponse } from '@angular/common/http'; import { downloadStream } from 'app/shared/util/download.util'; @@ -16,10 +16,22 @@ import { faSpinner } from '@fortawesome/free-solid-svg-icons'; import { LectureUnitService } from 'app/lecture/lecture-unit/lecture-unit-management/lectureUnit.service'; import { isCommunicationEnabled, isMessagingEnabled } from 'app/entities/course.model'; import { AbstractScienceComponent } from 'app/shared/science/science.component'; -import { ScienceService } from 'app/shared/science/science.service'; import { ScienceEventType } from 'app/shared/science/science.model'; import { Subscription } from 'rxjs'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgClass, UpperCasePipe } from '@angular/common'; +import { ExerciseUnitComponent } from './exercise-unit/exercise-unit.component'; +import { AttachmentUnitComponent } from './attachment-unit/attachment-unit.component'; +import { VideoUnitComponent } from './video-unit/video-unit.component'; +import { TextUnitComponent } from './text-unit/text-unit.component'; +import { OnlineUnitComponent } from './online-unit/online-unit.component'; +import { CompetenciesPopoverComponent } from 'app/course/competencies/competencies-popover/competencies-popover.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { DiscussionSectionComponent } from '../discussion-section/discussion-section.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; export interface LectureUnitCompletionEvent { lectureUnit: LectureUnit; @@ -30,8 +42,32 @@ export interface LectureUnitCompletionEvent { selector: 'jhi-course-lecture-details', templateUrl: './course-lecture-details.component.html', styleUrls: ['../course-overview.scss', './course-lectures.scss'], + imports: [ + TranslateDirective, + NgClass, + ExerciseUnitComponent, + AttachmentUnitComponent, + VideoUnitComponent, + TextUnitComponent, + OnlineUnitComponent, + CompetenciesPopoverComponent, + FaIconComponent, + DiscussionSectionComponent, + UpperCasePipe, + ArtemisDatePipe, + ArtemisTranslatePipe, + HtmlForMarkdownPipe, + ], }) export class CourseLectureDetailsComponent extends AbstractScienceComponent implements OnInit, OnDestroy { + private alertService = inject(AlertService); + private lectureService = inject(LectureService); + private lectureUnitService = inject(LectureUnitService); + private activatedRoute = inject(ActivatedRoute); + private fileService = inject(FileService); + private router = inject(Router); + private profileService = inject(ProfileService); + lectureId?: number; courseId?: number; isLoading = false; @@ -53,17 +89,8 @@ export class CourseLectureDetailsComponent extends AbstractScienceComponent impl // Icons faSpinner = faSpinner; - constructor( - private alertService: AlertService, - private lectureService: LectureService, - private lectureUnitService: LectureUnitService, - private activatedRoute: ActivatedRoute, - private fileService: FileService, - private router: Router, - scienceService: ScienceService, - private profileService: ProfileService, - ) { - super(scienceService, ScienceEventType.LECTURE__OPEN); + constructor() { + super(ScienceEventType.LECTURE__OPEN); } ngOnInit(): void { diff --git a/src/main/webapp/app/overview/course-lectures/course-lecture-details.module.ts b/src/main/webapp/app/overview/course-lectures/course-lecture-details.module.ts index 315de44054b0..000ffd522b6c 100644 --- a/src/main/webapp/app/overview/course-lectures/course-lecture-details.module.ts +++ b/src/main/webapp/app/overview/course-lectures/course-lecture-details.module.ts @@ -1,8 +1,9 @@ +import { CourseLectureDetailsComponent } from 'app/overview/course-lectures/course-lecture-details.component'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { ArtemisSharedPipesModule } from 'app/shared/pipes/shared-pipes.module'; import { ArtemisLectureUnitsModule } from 'app/overview/course-lectures/lecture-units.module'; -import { CourseLectureDetailsComponent } from 'app/overview/course-lectures/course-lecture-details.component'; + import { NgModule } from '@angular/core'; import { ArtemisCompetenciesModule } from 'app/course/competencies/competency.module'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; @@ -18,7 +19,7 @@ import { DiscussionSectionComponent } from 'app/overview/discussion-section/disc const routes: Routes = [ { path: '', - component: CourseLectureDetailsComponent, + loadComponent: () => import('app/overview/course-lectures/course-lecture-details.component').then((m) => m.CourseLectureDetailsComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.lectures', @@ -40,8 +41,8 @@ const routes: Routes = [ OnlineUnitComponent, AttachmentUnitComponent, DiscussionSectionComponent, + CourseLectureDetailsComponent, ], - declarations: [CourseLectureDetailsComponent], exports: [CourseLectureDetailsComponent], }) export class ArtemisCourseLectureDetailsModule {} diff --git a/src/main/webapp/app/overview/course-lectures/course-lecture-row.component.ts b/src/main/webapp/app/overview/course-lectures/course-lecture-row.component.ts index 9cdb6b4e09f2..10e584b6a94a 100644 --- a/src/main/webapp/app/overview/course-lectures/course-lecture-row.component.ts +++ b/src/main/webapp/app/overview/course-lectures/course-lecture-row.component.ts @@ -3,11 +3,20 @@ import dayjs from 'dayjs/esm'; import { Course } from 'app/entities/course.model'; import { Lecture } from 'app/entities/lecture.model'; import { faChalkboardTeacher } from '@fortawesome/free-solid-svg-icons'; +import { RouterLink } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { NgClass } from '@angular/common'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { ArtemisTimeAgoPipe } from 'app/shared/pipes/artemis-time-ago.pipe'; @Component({ selector: 'jhi-course-lecture-row', templateUrl: './course-lecture-row.component.html', styleUrls: ['../course-exercises/course-exercise-row.scss'], + imports: [RouterLink, FaIconComponent, NgbTooltip, NgClass, TranslateDirective, ArtemisDatePipe, ArtemisTranslatePipe, ArtemisTimeAgoPipe], }) export class CourseLectureRowComponent { @HostBinding('class') classes = 'exercise-row'; @@ -17,8 +26,6 @@ export class CourseLectureRowComponent { // Icons faChalkboardTeacher = faChalkboardTeacher; - constructor() {} - getUrgentClass(date?: dayjs.Dayjs) { if (!date) { return ''; diff --git a/src/main/webapp/app/overview/course-lectures/course-lectures.component.ts b/src/main/webapp/app/overview/course-lectures/course-lectures.component.ts index 8e12e392d125..3457662017e8 100644 --- a/src/main/webapp/app/overview/course-lectures/course-lectures.component.ts +++ b/src/main/webapp/app/overview/course-lectures/course-lectures.component.ts @@ -1,11 +1,14 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { Course } from 'app/entities/course.model'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterOutlet } from '@angular/router'; import { Subscription } from 'rxjs'; import { Lecture } from 'app/entities/lecture.model'; import { CourseStorageService } from 'app/course/manage/course-storage.service'; import { AccordionGroups, CollapseState, SidebarCardElement, SidebarData, SidebarItemShowAlways } from 'app/types/sidebar'; import { CourseOverviewService } from '../course-overview.service'; +import { NgClass } from '@angular/common'; +import { SidebarComponent } from 'app/shared/sidebar/sidebar.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; const DEFAULT_UNIT_GROUPS: AccordionGroups = { future: { entityData: [] }, @@ -35,8 +38,14 @@ const DEFAULT_SHOW_ALWAYS: SidebarItemShowAlways = { selector: 'jhi-course-lectures', templateUrl: './course-lectures.component.html', styleUrls: ['../course-overview.scss'], + imports: [NgClass, SidebarComponent, RouterOutlet, TranslateDirective], }) export class CourseLecturesComponent implements OnInit, OnDestroy { + private courseStorageService = inject(CourseStorageService); + private route = inject(ActivatedRoute); + private router = inject(Router); + private courseOverviewService = inject(CourseOverviewService); + private parentParamSubscription: Subscription; private courseUpdatesSubscription: Subscription; course?: Course; @@ -51,13 +60,6 @@ export class CourseLecturesComponent implements OnInit, OnDestroy { readonly DEFAULT_COLLAPSE_STATE = DEFAULT_COLLAPSE_STATE; protected readonly DEFAULT_SHOW_ALWAYS = DEFAULT_SHOW_ALWAYS; - constructor( - private courseStorageService: CourseStorageService, - private route: ActivatedRoute, - private router: Router, - private courseOverviewService: CourseOverviewService, - ) {} - ngOnInit() { this.isCollapsed = this.courseOverviewService.getSidebarCollapseStateFromStorage('lecture'); this.parentParamSubscription = this.route.parent!.params.subscribe((params) => { diff --git a/src/main/webapp/app/overview/course-lectures/exercise-unit/exercise-unit.component.ts b/src/main/webapp/app/overview/course-lectures/exercise-unit/exercise-unit.component.ts index b415b0e95ac4..ecdf4679c624 100644 --- a/src/main/webapp/app/overview/course-lectures/exercise-unit/exercise-unit.component.ts +++ b/src/main/webapp/app/overview/course-lectures/exercise-unit/exercise-unit.component.ts @@ -1,12 +1,14 @@ import { Component, HostBinding, Input, ViewEncapsulation } from '@angular/core'; import { Course } from 'app/entities/course.model'; import { ExerciseUnit } from 'app/entities/lecture-unit/exerciseUnit.model'; +import { CourseExerciseRowComponent } from '../../course-exercises/course-exercise-row.component'; @Component({ selector: 'jhi-exercise-unit', templateUrl: './exercise-unit.component.html', encapsulation: ViewEncapsulation.None, styleUrls: ['./exercise-unit.component.scss'], + imports: [CourseExerciseRowComponent], }) export class ExerciseUnitComponent { @HostBinding('className') componentClass: string; diff --git a/src/main/webapp/app/overview/course-lectures/lecture-unit/lecture-unit.component.ts b/src/main/webapp/app/overview/course-lectures/lecture-unit/lecture-unit.component.ts index b4cf868d5d5a..583c0bd11dcc 100644 --- a/src/main/webapp/app/overview/course-lectures/lecture-unit/lecture-unit.component.ts +++ b/src/main/webapp/app/overview/course-lectures/lecture-unit/lecture-unit.component.ts @@ -7,7 +7,6 @@ import { LectureUnit } from 'app/entities/lecture-unit/lectureUnit.model'; @Component({ selector: 'jhi-lecture-unit-card', - standalone: true, imports: [FontAwesomeModule, ArtemisSharedCommonModule, NgbCollapseModule], templateUrl: './lecture-unit.component.html', styleUrl: './lecture-unit.component.scss', diff --git a/src/main/webapp/app/overview/course-lectures/lecture-unit/lecture-unit.directive.ts b/src/main/webapp/app/overview/course-lectures/lecture-unit/lecture-unit.directive.ts index 51fe2cf35726..190645cc5b14 100644 --- a/src/main/webapp/app/overview/course-lectures/lecture-unit/lecture-unit.directive.ts +++ b/src/main/webapp/app/overview/course-lectures/lecture-unit/lecture-unit.directive.ts @@ -1,24 +1,21 @@ import { AbstractScienceComponent } from 'app/shared/science/science.component'; -import { ScienceService } from 'app/shared/science/science.service'; import { ScienceEventType } from 'app/shared/science/science.model'; import { LectureUnit } from 'app/entities/lecture-unit/lectureUnit.model'; import { effect, input, output } from '@angular/core'; import { Directive } from '@angular/core'; import { LectureUnitCompletionEvent } from 'app/overview/course-lectures/course-lecture-details.component'; -@Directive({ - standalone: true, -}) +@Directive() export class LectureUnitDirective extends AbstractScienceComponent { - readonly lectureUnit = input.required(); + lectureUnit = input.required(); readonly onCompletion = output(); readonly onCollapse = output(); - readonly isPresentationMode = input(false); + isPresentationMode = input(false); - constructor(scienceService: ScienceService) { - super(scienceService, ScienceEventType.LECTURE__OPEN_UNIT); + constructor() { + super(ScienceEventType.LECTURE__OPEN_UNIT); effect(() => { this.setResourceId(this.lectureUnit().id!); diff --git a/src/main/webapp/app/overview/course-lectures/lecture-units.module.ts b/src/main/webapp/app/overview/course-lectures/lecture-units.module.ts index 5ef001e15d5f..e8a662b7af81 100644 --- a/src/main/webapp/app/overview/course-lectures/lecture-units.module.ts +++ b/src/main/webapp/app/overview/course-lectures/lecture-units.module.ts @@ -7,8 +7,7 @@ import { ExerciseUnitComponent } from 'app/overview/course-lectures/exercise-uni import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisSharedPipesModule, ArtemisCourseExerciseRowModule, ArtemisMarkdownModule], - declarations: [ExerciseUnitComponent], + imports: [ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisSharedPipesModule, ArtemisCourseExerciseRowModule, ArtemisMarkdownModule, ExerciseUnitComponent], exports: [ExerciseUnitComponent], }) export class ArtemisLectureUnitsModule {} diff --git a/src/main/webapp/app/overview/course-lectures/online-unit/online-unit.component.ts b/src/main/webapp/app/overview/course-lectures/online-unit/online-unit.component.ts index 9bc979d903a3..f2880956b71b 100644 --- a/src/main/webapp/app/overview/course-lectures/online-unit/online-unit.component.ts +++ b/src/main/webapp/app/overview/course-lectures/online-unit/online-unit.component.ts @@ -6,7 +6,6 @@ import { faUpRightFromSquare } from '@fortawesome/free-solid-svg-icons'; @Component({ selector: 'jhi-online-unit', - standalone: true, imports: [LectureUnitComponent], templateUrl: './online-unit.component.html', }) diff --git a/src/main/webapp/app/overview/course-lectures/text-unit/text-unit.component.ts b/src/main/webapp/app/overview/course-lectures/text-unit/text-unit.component.ts index 7563ccc34e1b..f9f19721182e 100644 --- a/src/main/webapp/app/overview/course-lectures/text-unit/text-unit.component.ts +++ b/src/main/webapp/app/overview/course-lectures/text-unit/text-unit.component.ts @@ -8,7 +8,6 @@ import { LectureUnitDirective } from 'app/overview/course-lectures/lecture-unit/ @Component({ selector: 'jhi-text-unit', - standalone: true, imports: [LectureUnitComponent], templateUrl: './text-unit.component.html', }) diff --git a/src/main/webapp/app/overview/course-lectures/video-unit/video-unit.component.ts b/src/main/webapp/app/overview/course-lectures/video-unit/video-unit.component.ts index 7cbf2829048b..9284448e63d9 100644 --- a/src/main/webapp/app/overview/course-lectures/video-unit/video-unit.component.ts +++ b/src/main/webapp/app/overview/course-lectures/video-unit/video-unit.component.ts @@ -8,7 +8,6 @@ import { LectureUnitComponent } from 'app/overview/course-lectures/lecture-unit/ @Component({ selector: 'jhi-video-unit', - standalone: true, imports: [ArtemisSharedPipesModule, LectureUnitComponent], templateUrl: './video-unit.component.html', }) diff --git a/src/main/webapp/app/overview/course-overview.component.ts b/src/main/webapp/app/overview/course-overview.component.ts index 8e09014c4fb1..58cca05e2238 100644 --- a/src/main/webapp/app/overview/course-overview.component.ts +++ b/src/main/webapp/app/overview/course-overview.component.ts @@ -14,7 +14,7 @@ import { ViewContainerRef, inject, } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router'; import { IconDefinition, faChalkboardUser, @@ -39,7 +39,7 @@ import { faTimes, faWrench, } from '@fortawesome/free-solid-svg-icons'; -import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgbDropdown, NgbDropdownButtonItem, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle, NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { AlertService, AlertType } from 'app/core/util/alert.service'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; import { CourseAccessStorageService } from 'app/course/course-access-storage.service'; @@ -57,7 +57,7 @@ import { ArtemisServerDateService } from 'app/shared/server-date.service'; import { BarControlConfiguration, BarControlConfigurationProvider } from 'app/shared/tab-bar/tab-bar'; import dayjs from 'dayjs/esm'; import { Observable, Subject, Subscription, catchError, firstValueFrom, map, of, takeUntil, throwError } from 'rxjs'; -import { facSidebar } from '../../content/icons/icons'; +import { facSidebar } from 'app/icons/icons'; import { CourseManagementService } from '../course/manage/course-management.service'; import { CourseExercisesComponent } from './course-exercises/course-exercises.component'; import { CourseLecturesComponent } from './course-lectures/course-lectures.component'; @@ -69,6 +69,13 @@ import { sortCourses } from 'app/shared/util/course.util'; import { CourseUnenrollmentModalComponent } from './course-unenrollment-modal.component'; import { LtiService } from 'app/shared/service/lti.service'; import { CourseSidebarService } from 'app/overview/course-sidebar.service'; +import { NgClass, NgStyle, NgTemplateOutlet, SlicePipe } from '@angular/common'; +import { MatSidenav, MatSidenavContainer, MatSidenavContent } from '@angular/material/sidenav'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from '../shared/language/translate.directive'; +import { SecuredImageComponent } from '../shared/image/secured-image.component'; +import { OrionFilterDirective } from '../shared/orion/orion-filter.directive'; +import { FeatureToggleHideDirective } from '../shared/feature-toggle/feature-toggle-hide.directive'; interface CourseActionItem { title: string; @@ -95,8 +102,48 @@ interface SidebarItem { templateUrl: './course-overview.component.html', styleUrls: ['course-overview.scss', 'course-overview.component.scss'], providers: [MetisConversationService], + imports: [ + NgClass, + MatSidenavContainer, + MatSidenav, + NgbDropdown, + NgbDropdownToggle, + NgTemplateOutlet, + NgbDropdownMenu, + NgbDropdownButtonItem, + NgbDropdownItem, + FaIconComponent, + TranslateDirective, + NgbTooltip, + MatSidenavContent, + NgStyle, + RouterLink, + RouterOutlet, + SecuredImageComponent, + OrionFilterDirective, + RouterLinkActive, + FeatureToggleHideDirective, + SlicePipe, + ], }) export class CourseOverviewComponent implements OnInit, OnDestroy, AfterViewInit { + private courseService = inject(CourseManagementService); + private courseExerciseService = inject(CourseExerciseService); + private courseStorageService = inject(CourseStorageService); + private route = inject(ActivatedRoute); + private teamService = inject(TeamService); + private jhiWebsocketService = inject(JhiWebsocketService); + private serverDateService = inject(ArtemisServerDateService); + private alertService = inject(AlertService); + private changeDetectorRef = inject(ChangeDetectorRef); + private metisConversationService = inject(MetisConversationService); + private router = inject(Router); + private courseAccessStorageService = inject(CourseAccessStorageService); + private profileService = inject(ProfileService); + private modalService = inject(NgbModal); + private examParticipationService = inject(ExamParticipationService); + private ltiService = inject(LtiService); + private ngUnsubscribe = new Subject(); private closeSidebarEventSubscription: Subscription; private openSidebarEventSubscription: Subscription; @@ -189,25 +236,6 @@ export class CourseOverviewComponent implements OnInit, OnDestroy, AfterViewInit private courseSidebarService: CourseSidebarService = inject(CourseSidebarService); - constructor( - private courseService: CourseManagementService, - private courseExerciseService: CourseExerciseService, - private courseStorageService: CourseStorageService, - private route: ActivatedRoute, - private teamService: TeamService, - private jhiWebsocketService: JhiWebsocketService, - private serverDateService: ArtemisServerDateService, - private alertService: AlertService, - private changeDetectorRef: ChangeDetectorRef, - private metisConversationService: MetisConversationService, - private router: Router, - private courseAccessStorageService: CourseAccessStorageService, - private profileService: ProfileService, - private modalService: NgbModal, - private examParticipationService: ExamParticipationService, - private ltiService: LtiService, - ) {} - async ngOnInit() { this.openSidebarEventSubscription = this.courseSidebarService.openSidebar$.subscribe(() => { this.isSidebarCollapsed = true; diff --git a/src/main/webapp/app/overview/course-overview.service.ts b/src/main/webapp/app/overview/course-overview.service.ts index 6e13440242bb..8408654338cf 100644 --- a/src/main/webapp/app/overview/course-overview.service.ts +++ b/src/main/webapp/app/overview/course-overview.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { Exercise, getIcon } from 'app/entities/exercise.model'; import { Lecture } from 'app/entities/lecture.model'; @@ -71,11 +71,9 @@ const DEFAULT_CHANNEL_GROUPS: AccordionGroups = { providedIn: 'root', }) export class CourseOverviewService { - constructor( - private participationService: ParticipationService, - private translate: TranslateService, - private conversationService: ConversationService, - ) {} + private participationService = inject(ParticipationService); + private translate = inject(TranslateService); + private conversationService = inject(ConversationService); readonly faBullhorn = faBullhorn; readonly faHashtag = faHashtag; diff --git a/src/main/webapp/app/overview/course-registration/course-prerequisites-button/course-prerequisites-button.component.ts b/src/main/webapp/app/overview/course-registration/course-prerequisites-button/course-prerequisites-button.component.ts index 765c849561f8..ca92ba3a701e 100644 --- a/src/main/webapp/app/overview/course-registration/course-prerequisites-button/course-prerequisites-button.component.ts +++ b/src/main/webapp/app/overview/course-registration/course-prerequisites-button/course-prerequisites-button.component.ts @@ -1,16 +1,18 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { Course } from 'app/entities/course.model'; import { CoursePrerequisitesModalComponent } from 'app/overview/course-registration/course-registration-prerequisites-modal/course-prerequisites-modal.component'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-course-prerequisites-button', templateUrl: './course-prerequisites-button.component.html', + imports: [TranslateDirective], }) export class CoursePrerequisitesButtonComponent { - @Input() course: Course; + private modalService = inject(NgbModal); - constructor(private modalService: NgbModal) {} + @Input() course: Course; /** * Opens a modal with the prerequisites for the course diff --git a/src/main/webapp/app/overview/course-registration/course-prerequisites-button/course-prerequisites-button.module.ts b/src/main/webapp/app/overview/course-registration/course-prerequisites-button/course-prerequisites-button.module.ts index fea08dd0fe9c..ab1126a79968 100644 --- a/src/main/webapp/app/overview/course-registration/course-prerequisites-button/course-prerequisites-button.module.ts +++ b/src/main/webapp/app/overview/course-registration/course-prerequisites-button/course-prerequisites-button.module.ts @@ -6,8 +6,7 @@ import { CoursePrerequisitesButtonComponent } from 'app/overview/course-registra import { CoursePrerequisitesModalModule } from 'app/overview/course-registration/course-registration-prerequisites-modal/course-prerequisites-modal.module'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisCompetenciesModule, CoursePrerequisitesModalModule], - declarations: [CoursePrerequisitesButtonComponent], + imports: [ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisCompetenciesModule, CoursePrerequisitesModalModule, CoursePrerequisitesButtonComponent], exports: [CoursePrerequisitesButtonComponent], }) export class CoursePrerequisitesButtonModule {} diff --git a/src/main/webapp/app/overview/course-registration/course-registration-button/course-registration-button.component.ts b/src/main/webapp/app/overview/course-registration/course-registration-button/course-registration-button.component.ts index 0dacd75e250c..3b38f79e22d6 100644 --- a/src/main/webapp/app/overview/course-registration/course-registration-button/course-registration-button.component.ts +++ b/src/main/webapp/app/overview/course-registration/course-registration-button/course-registration-button.component.ts @@ -1,29 +1,30 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core'; import { AccountService } from 'app/core/auth/account.service'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { Course } from 'app/entities/course.model'; import { matchesRegexFully } from 'app/utils/regex.util'; import { AlertService } from 'app/core/util/alert.service'; +import { ConfirmAutofocusButtonComponent } from 'app/shared/components/confirm-autofocus-button.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-course-registration-button', templateUrl: './course-registration-button.component.html', + imports: [ConfirmAutofocusButtonComponent, TranslateDirective], }) export class CourseRegistrationButtonComponent implements OnInit { + private accountService = inject(AccountService); + private courseService = inject(CourseManagementService); + private profileService = inject(ProfileService); + private alertService = inject(AlertService); + @Input() course: Course; @Output() onRegistration = new EventEmitter(); userIsAllowedToRegister = false; loading = false; - constructor( - private accountService: AccountService, - private courseService: CourseManagementService, - private profileService: ProfileService, - private alertService: AlertService, - ) {} - loadUserIsAllowedToRegister() { this.loading = true; this.accountService.identity().then((user) => { diff --git a/src/main/webapp/app/overview/course-registration/course-registration-button/course-registration-button.module.ts b/src/main/webapp/app/overview/course-registration/course-registration-button/course-registration-button.module.ts index a5248566e71d..11535e93dc5d 100644 --- a/src/main/webapp/app/overview/course-registration/course-registration-button/course-registration-button.module.ts +++ b/src/main/webapp/app/overview/course-registration/course-registration-button/course-registration-button.module.ts @@ -5,8 +5,7 @@ import { ArtemisCompetenciesModule } from 'app/course/competencies/competency.mo import { CourseRegistrationButtonComponent } from 'app/overview/course-registration/course-registration-button/course-registration-button.component'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisCompetenciesModule], - declarations: [CourseRegistrationButtonComponent], + imports: [ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisCompetenciesModule, CourseRegistrationButtonComponent], exports: [CourseRegistrationButtonComponent], }) export class CourseRegistrationButtonModule {} diff --git a/src/main/webapp/app/overview/course-registration/course-registration-detail/course-registration-detail.component.ts b/src/main/webapp/app/overview/course-registration/course-registration-detail/course-registration-detail.component.ts index 09c3086a8ea5..9abb842aac51 100644 --- a/src/main/webapp/app/overview/course-registration/course-registration-detail/course-registration-detail.component.ts +++ b/src/main/webapp/app/overview/course-registration/course-registration-detail/course-registration-detail.component.ts @@ -1,28 +1,30 @@ import { HttpErrorResponse } from '@angular/common/http'; -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { AccountService } from 'app/core/auth/account.service'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { Course } from 'app/entities/course.model'; import { Observable, catchError, map, of, throwError } from 'rxjs'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CoursePrerequisitesButtonComponent } from '../course-prerequisites-button/course-prerequisites-button.component'; +import { CourseRegistrationButtonComponent } from '../course-registration-button/course-registration-button.component'; @Component({ selector: 'jhi-course-registration-detail-selector', templateUrl: './course-registration-detail.component.html', + imports: [TranslateDirective, CoursePrerequisitesButtonComponent, CourseRegistrationButtonComponent], }) export class CourseRegistrationDetailComponent implements OnInit, OnDestroy { + private accountService = inject(AccountService); + private courseService = inject(CourseManagementService); + private route = inject(ActivatedRoute); + private router = inject(Router); + loading = false; courseId: number; course: Course | null = null; private paramSubscription: any; - constructor( - private accountService: AccountService, - private courseService: CourseManagementService, - private route: ActivatedRoute, - private router: Router, - ) {} - ngOnInit(): void { this.loading = true; this.paramSubscription = this.route.parent!.params.subscribe((params) => { diff --git a/src/main/webapp/app/overview/course-registration/course-registration-detail/course-registration-detail.module.ts b/src/main/webapp/app/overview/course-registration/course-registration-detail/course-registration-detail.module.ts index 973b58af98ae..940212a8299b 100644 --- a/src/main/webapp/app/overview/course-registration/course-registration-detail/course-registration-detail.module.ts +++ b/src/main/webapp/app/overview/course-registration/course-registration-detail/course-registration-detail.module.ts @@ -1,17 +1,19 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; +import { CourseRegistrationDetailComponent } from 'app/overview/course-registration/course-registration-detail/course-registration-detail.component'; import { Authority } from 'app/shared/constants/authority.constants'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; -import { CourseRegistrationDetailComponent } from 'app/overview/course-registration/course-registration-detail/course-registration-detail.component'; + import { CoursePrerequisitesButtonModule } from 'app/overview/course-registration/course-prerequisites-button/course-prerequisites-button.module'; import { CourseRegistrationButtonModule } from 'app/overview/course-registration/course-registration-button/course-registration-button.module'; const routes: Routes = [ { path: '', - component: CourseRegistrationDetailComponent, + loadComponent: () => + import('app/overview/course-registration/course-registration-detail/course-registration-detail.component').then((m) => m.CourseRegistrationDetailComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.studentDashboard.enroll.title', @@ -21,7 +23,13 @@ const routes: Routes = [ ]; @NgModule({ - imports: [ArtemisSharedModule, ArtemisSharedComponentModule, RouterModule.forChild(routes), CoursePrerequisitesButtonModule, CourseRegistrationButtonModule], - declarations: [CourseRegistrationDetailComponent], + imports: [ + ArtemisSharedModule, + ArtemisSharedComponentModule, + RouterModule.forChild(routes), + CoursePrerequisitesButtonModule, + CourseRegistrationButtonModule, + CourseRegistrationDetailComponent, + ], }) export class CourseRegistrationDetailModule {} diff --git a/src/main/webapp/app/overview/course-registration/course-registration-prerequisites-modal/course-prerequisites-modal.component.ts b/src/main/webapp/app/overview/course-registration/course-registration-prerequisites-modal/course-prerequisites-modal.component.ts index 9e2bd74f2adf..c0f84b71a3c5 100644 --- a/src/main/webapp/app/overview/course-registration/course-registration-prerequisites-modal/course-prerequisites-modal.component.ts +++ b/src/main/webapp/app/overview/course-registration/course-registration-prerequisites-modal/course-prerequisites-modal.component.ts @@ -1,28 +1,28 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { AlertService } from 'app/core/util/alert.service'; import { finalize } from 'rxjs/operators'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { PrerequisiteService } from 'app/course/competencies/prerequisite.service'; import { Prerequisite } from 'app/entities/prerequisite.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { CompetencyCardComponent } from 'app/course/competencies/competency-card/competency-card.component'; @Component({ selector: 'jhi-course-prerequisites-modal', templateUrl: './course-prerequisites-modal.component.html', - styles: [], + imports: [TranslateDirective, CompetencyCardComponent], }) export class CoursePrerequisitesModalComponent implements OnInit { + private alertService = inject(AlertService); + private activeModal = inject(NgbActiveModal); + private prerequisiteService = inject(PrerequisiteService); + @Input() courseId: number; isLoading = false; prerequisites: Prerequisite[] = []; - constructor( - private alertService: AlertService, - private activeModal: NgbActiveModal, - private prerequisiteService: PrerequisiteService, - ) {} - ngOnInit(): void { if (this.courseId) { this.loadData(); diff --git a/src/main/webapp/app/overview/course-registration/course-registration-prerequisites-modal/course-prerequisites-modal.module.ts b/src/main/webapp/app/overview/course-registration/course-registration-prerequisites-modal/course-prerequisites-modal.module.ts index 8e8b0a852bb8..f3122ec53333 100644 --- a/src/main/webapp/app/overview/course-registration/course-registration-prerequisites-modal/course-prerequisites-modal.module.ts +++ b/src/main/webapp/app/overview/course-registration/course-registration-prerequisites-modal/course-prerequisites-modal.module.ts @@ -5,7 +5,6 @@ import { CoursePrerequisitesModalComponent } from 'app/overview/course-registrat import { ArtemisCompetenciesModule } from 'app/course/competencies/competency.module'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisCompetenciesModule], - declarations: [CoursePrerequisitesModalComponent], + imports: [ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisCompetenciesModule, CoursePrerequisitesModalComponent], }) export class CoursePrerequisitesModalModule {} diff --git a/src/main/webapp/app/overview/course-registration/course-registration.component.ts b/src/main/webapp/app/overview/course-registration/course-registration.component.ts index 36483cae58a1..9bdbbf73f539 100644 --- a/src/main/webapp/app/overview/course-registration/course-registration.component.ts +++ b/src/main/webapp/app/overview/course-registration/course-registration.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { AccountService } from 'app/core/auth/account.service'; import { Course } from 'app/entities/course.model'; import { CourseManagementService } from 'app/course/manage/course-management.service'; @@ -7,12 +7,36 @@ import { ASC, DESC, SORT } from 'app/shared/constants/pagination.constants'; import { ActivatedRoute, Router } from '@angular/router'; import { combineLatest } from 'rxjs'; import { SortService } from 'app/shared/service/sort.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { SortDirective } from 'app/shared/sort/sort.directive'; +import { SortByDirective } from 'app/shared/sort/sort-by.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { CoursePrerequisitesButtonComponent } from './course-prerequisites-button/course-prerequisites-button.component'; +import { CourseRegistrationButtonComponent } from './course-registration-button/course-registration-button.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-course-registration-selector', templateUrl: './course-registration.component.html', + imports: [ + TranslateDirective, + FormsModule, + SortDirective, + SortByDirective, + FaIconComponent, + CoursePrerequisitesButtonComponent, + CourseRegistrationButtonComponent, + ArtemisTranslatePipe, + ], }) export class CourseRegistrationComponent implements OnInit { + private accountService = inject(AccountService); + private courseService = inject(CourseManagementService); + private activatedRoute = inject(ActivatedRoute); + private router = inject(Router); + private sortService = inject(SortService); + coursesToSelect: Course[] = []; loading = false; predicate!: string; @@ -23,14 +47,6 @@ export class CourseRegistrationComponent implements OnInit { faCheckCircle = faCheckCircle; faSort = faSort; - constructor( - private accountService: AccountService, - private courseService: CourseManagementService, - private activatedRoute: ActivatedRoute, - private router: Router, - private sortService: SortService, - ) {} - ngOnInit(): void { this.handleNavigation(); } diff --git a/src/main/webapp/app/overview/course-registration/course-registration.module.ts b/src/main/webapp/app/overview/course-registration/course-registration.module.ts index 1fea470fdf8e..8acb12cd1b3d 100644 --- a/src/main/webapp/app/overview/course-registration/course-registration.module.ts +++ b/src/main/webapp/app/overview/course-registration/course-registration.module.ts @@ -1,6 +1,7 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { CourseRegistrationComponent } from 'app/overview/course-registration/course-registration.component'; + import { Authority } from 'app/shared/constants/authority.constants'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; import { ArtemisSharedModule } from 'app/shared/shared.module'; @@ -12,7 +13,7 @@ import { CoursePrerequisitesButtonModule } from 'app/overview/course-registratio const routes: Routes = [ { path: '', - component: CourseRegistrationComponent, + loadComponent: () => import('app/overview/course-registration/course-registration.component').then((m) => m.CourseRegistrationComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.studentDashboard.enroll.title', @@ -29,7 +30,7 @@ const routes: Routes = [ ArtemisCompetenciesModule, CourseRegistrationButtonModule, CoursePrerequisitesButtonModule, + CourseRegistrationComponent, ], - declarations: [CourseRegistrationComponent], }) export class CourseRegistrationModule {} diff --git a/src/main/webapp/app/overview/course-sidebar.service.ts b/src/main/webapp/app/overview/course-sidebar.service.ts index 642de68c5e33..189a3fb1c380 100644 --- a/src/main/webapp/app/overview/course-sidebar.service.ts +++ b/src/main/webapp/app/overview/course-sidebar.service.ts @@ -8,8 +8,6 @@ export class CourseSidebarService { public openSidebar$: EventEmitter = new EventEmitter(); public toggleSidebar$: EventEmitter = new EventEmitter(); - constructor() {} - public closeSidebar(): void { this.closeSidebar$.emit(); } diff --git a/src/main/webapp/app/overview/course-statistics/course-statistics.component.ts b/src/main/webapp/app/overview/course-statistics/course-statistics.component.ts index 27ba9ed43ef3..345c8d95b97d 100644 --- a/src/main/webapp/app/overview/course-statistics/course-statistics.component.ts +++ b/src/main/webapp/app/overview/course-statistics/course-statistics.component.ts @@ -1,8 +1,8 @@ -import { AfterViewInit, Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { AfterViewInit, Component, OnDestroy, OnInit, TemplateRef, ViewChild, inject } from '@angular/core'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { faClipboard, faFilter, faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; import { TranslateService } from '@ngx-translate/core'; -import { Color, ScaleType } from '@swimlane/ngx-charts'; +import { BarChartModule, Color, PieChartModule, ScaleType } from '@swimlane/ngx-charts'; import { CourseScores } from 'app/course/course-scores/course-scores'; import { ScoresStorageService } from 'app/course/course-scores/scores-storage.service'; import { ParticipationResultDTO } from 'app/course/manage/course-for-dashboard-dto'; @@ -25,6 +25,13 @@ import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; import dayjs from 'dayjs/esm'; import { sortBy } from 'lodash-es'; import { Subject, Subscription } from 'rxjs'; +import { NgbDropdown, NgbDropdownMenu, NgbDropdownToggle, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { DocumentationButtonComponent } from 'app/shared/components/documentation-button/documentation-button.component'; +import { ExerciseScoresChartComponent } from '../visualizations/exercise-scores-chart/exercise-scores-chart.component'; +import { KeyValuePipe } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; const QUIZ_EXERCISE_COLOR = '#17a2b8'; const PROGRAMMING_EXERCISE_COLOR = '#fd7e14'; @@ -92,8 +99,31 @@ enum ChartBarTitle { selector: 'jhi-course-statistics', templateUrl: './course-statistics.component.html', styleUrls: ['../course-overview.scss'], + imports: [ + NgbDropdown, + NgbDropdownToggle, + FaIconComponent, + TranslateDirective, + NgbDropdownMenu, + DocumentationButtonComponent, + PieChartModule, + NgbTooltip, + RouterLink, + ExerciseScoresChartComponent, + BarChartModule, + KeyValuePipe, + ArtemisTranslatePipe, + ], }) export class CourseStatisticsComponent implements OnInit, OnDestroy, AfterViewInit, BarControlConfigurationProvider { + private courseStorageService = inject(CourseStorageService); + private scoresStorageService = inject(ScoresStorageService); + private translateService = inject(TranslateService); + private route = inject(ActivatedRoute); + private gradingSystemService = inject(GradingSystemService); + private navigationUtilService = inject(ArtemisNavigationUtilService); + categoryFilter = inject(ChartCategoryFilter); + readonly documentationType: DocumentationType = 'Statistics'; courseId: number; @@ -213,16 +243,6 @@ export class CourseStatisticsComponent implements OnInit, OnDestroy, AfterViewIn subject: new Subject>(), }; - constructor( - private courseStorageService: CourseStorageService, - private scoresStorageService: ScoresStorageService, - private translateService: TranslateService, - private route: ActivatedRoute, - private gradingSystemService: GradingSystemService, - private navigationUtilService: ArtemisNavigationUtilService, - public categoryFilter: ChartCategoryFilter, - ) {} - ngOnInit() { // Note: due to lazy loading and router outlet, we use parent 2x here this.paramSubscription = this.route.parent?.parent?.params.subscribe((params) => { diff --git a/src/main/webapp/app/overview/course-statistics/course-statistics.module.ts b/src/main/webapp/app/overview/course-statistics/course-statistics.module.ts index 5ef402281eb4..dc8ef5f4e22c 100644 --- a/src/main/webapp/app/overview/course-statistics/course-statistics.module.ts +++ b/src/main/webapp/app/overview/course-statistics/course-statistics.module.ts @@ -1,19 +1,20 @@ import { NgModule } from '@angular/core'; -import { ArtemisSharedModule } from 'app/shared/shared.module'; import { CourseStatisticsComponent } from 'app/overview/course-statistics/course-statistics.component'; +import { ArtemisSharedModule } from 'app/shared/shared.module'; + import { Authority } from 'app/shared/constants/authority.constants'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; import { RouterModule, Routes } from '@angular/router'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; import { ArtemisExerciseScoresChartModule } from 'app/overview/visualizations/exercise-scores-chart.module'; import { BarChartModule, PieChartModule } from '@swimlane/ngx-charts'; -import { GradingKeyOverviewComponent } from 'app/grading-system/grading-key-overview/grading-key-overview.component'; + import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; const routes: Routes = [ { path: '', - component: CourseStatisticsComponent, + loadComponent: () => import('app/overview/course-statistics/course-statistics.component').then((m) => m.CourseStatisticsComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.statistics', @@ -22,7 +23,7 @@ const routes: Routes = [ }, { path: 'grading-key', - component: GradingKeyOverviewComponent, + loadComponent: () => import('app/grading-system/grading-key-overview/grading-key-overview.component').then((m) => m.GradingKeyOverviewComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.gradingSystem.title', @@ -40,7 +41,7 @@ const routes: Routes = [ BarChartModule, PieChartModule, ArtemisSharedComponentModule, + CourseStatisticsComponent, ], - declarations: [CourseStatisticsComponent], }) export class CourseStatisticsModule {} diff --git a/src/main/webapp/app/overview/course-tutorial-groups/course-tutorial-group-card/course-tutorial-group-card.component.ts b/src/main/webapp/app/overview/course-tutorial-groups/course-tutorial-group-card/course-tutorial-group-card.component.ts index 53bbf5cd4d99..d23f745134ca 100644 --- a/src/main/webapp/app/overview/course-tutorial-groups/course-tutorial-group-card/course-tutorial-group-card.component.ts +++ b/src/main/webapp/app/overview/course-tutorial-groups/course-tutorial-group-card/course-tutorial-group-card.component.ts @@ -2,6 +2,10 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { faPersonChalkboard } from '@fortawesome/free-solid-svg-icons'; import { Course, isMessagingEnabled } from 'app/entities/course.model'; +import { RouterLink } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; @Component({ selector: 'jhi-course-tutorial-group-card', @@ -9,6 +13,7 @@ import { Course, isMessagingEnabled } from 'app/entities/course.model'; styleUrls: ['./course-tutorial-group-card.component.scss'], host: { class: 'card tutorial-group-card' }, changeDetection: ChangeDetectionStrategy.OnPush, + imports: [RouterLink, FaIconComponent, TranslateDirective, ArtemisDatePipe], }) export class CourseTutorialGroupCardComponent { @Input() diff --git a/src/main/webapp/app/overview/course-tutorial-groups/course-tutorial-groups.component.ts b/src/main/webapp/app/overview/course-tutorial-groups/course-tutorial-groups.component.ts index ed90dd068fb1..3fa12636b836 100644 --- a/src/main/webapp/app/overview/course-tutorial-groups/course-tutorial-groups.component.ts +++ b/src/main/webapp/app/overview/course-tutorial-groups/course-tutorial-groups.component.ts @@ -1,8 +1,8 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { Subject, finalize } from 'rxjs'; import { Course } from 'app/entities/course.model'; import { CourseManagementService } from 'app/course/manage/course-management.service'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterOutlet } from '@angular/router'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { TutorialGroupsService } from 'app/course/tutorial-groups/services/tutorial-groups.service'; import { map, takeUntil } from 'rxjs/operators'; @@ -15,6 +15,9 @@ import { TutorialGroupsConfiguration } from 'app/entities/tutorial-group/tutoria import { AccordionGroups, CollapseState, SidebarCardElement, SidebarData, SidebarItemShowAlways, TutorialGroupCategory } from 'app/types/sidebar'; import { CourseOverviewService } from '../course-overview.service'; import { cloneDeep } from 'lodash-es'; +import { NgClass } from '@angular/common'; +import { SidebarComponent } from 'app/shared/sidebar/sidebar.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; const TUTORIAL_UNIT_GROUPS: AccordionGroups = { registered: { entityData: [] }, @@ -38,8 +41,18 @@ const DEFAULT_SHOW_ALWAYS: SidebarItemShowAlways = { selector: 'jhi-course-tutorial-groups', templateUrl: './course-tutorial-groups.component.html', changeDetection: ChangeDetectionStrategy.OnPush, + imports: [NgClass, SidebarComponent, RouterOutlet, TranslateDirective], }) export class CourseTutorialGroupsComponent implements OnInit, OnDestroy { + private router = inject(Router); + private courseStorageService = inject(CourseStorageService); + private courseManagementService = inject(CourseManagementService); + private tutorialGroupService = inject(TutorialGroupsService); + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + private cdr = inject(ChangeDetectorRef); + private courseOverviewService = inject(CourseOverviewService); + ngUnsubscribe = new Subject(); tutorialGroups: TutorialGroup[] = []; @@ -58,17 +71,6 @@ export class CourseTutorialGroupsComponent implements OnInit, OnDestroy { protected readonly DEFAULT_SHOW_ALWAYS = DEFAULT_SHOW_ALWAYS; sidebarTutorialGroups: SidebarCardElement[] = []; - constructor( - private router: Router, - private courseStorageService: CourseStorageService, - private courseManagementService: CourseManagementService, - private tutorialGroupService: TutorialGroupsService, - private route: ActivatedRoute, - private alertService: AlertService, - private cdr: ChangeDetectorRef, - private courseOverviewService: CourseOverviewService, - ) {} - get registeredTutorialGroups() { if (this.course?.isAtLeastTutor) { return this.tutorialGroups.filter((tutorialGroup) => tutorialGroup.isUserTutor); diff --git a/src/main/webapp/app/overview/course-tutorial-groups/course-tutorial-groups.module.ts b/src/main/webapp/app/overview/course-tutorial-groups/course-tutorial-groups.module.ts index af87e1b67370..687a0fff4a2e 100644 --- a/src/main/webapp/app/overview/course-tutorial-groups/course-tutorial-groups.module.ts +++ b/src/main/webapp/app/overview/course-tutorial-groups/course-tutorial-groups.module.ts @@ -4,10 +4,8 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; import { CourseTutorialGroupCardComponent } from './course-tutorial-group-card/course-tutorial-group-card.component'; import { ArtemisTutorialGroupsSharedModule } from 'app/course/tutorial-groups/shared/tutorial-groups-shared.module'; import { ArtemisSidebarModule } from 'app/shared/sidebar/sidebar.module'; -import { ArtemisAppRoutingModule } from 'app/app-routing.module'; @NgModule({ - imports: [ArtemisAppRoutingModule, ArtemisSharedModule, ArtemisTutorialGroupsSharedModule, ArtemisSidebarModule], - declarations: [CourseTutorialGroupsComponent, CourseTutorialGroupCardComponent], + imports: [ArtemisSharedModule, ArtemisTutorialGroupsSharedModule, ArtemisSidebarModule, CourseTutorialGroupsComponent, CourseTutorialGroupCardComponent], }) export class CourseTutorialGroupsModule {} diff --git a/src/main/webapp/app/overview/course-unenrollment-modal.component.ts b/src/main/webapp/app/overview/course-unenrollment-modal.component.ts index 0a27a334da31..d295ac24e948 100644 --- a/src/main/webapp/app/overview/course-unenrollment-modal.component.ts +++ b/src/main/webapp/app/overview/course-unenrollment-modal.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { Router } from '@angular/router'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { faXmark } from '@fortawesome/free-solid-svg-icons'; @@ -6,26 +6,29 @@ import dayjs from 'dayjs/esm'; import { Course } from 'app/entities/course.model'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { AlertService } from 'app/core/util/alert.service'; -import { AbstractControl, FormControl, FormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms'; +import { AbstractControl, FormControl, FormGroup, FormsModule, ReactiveFormsModule, ValidationErrors, ValidatorFn, Validators } from '@angular/forms'; +import { TranslateDirective } from '../shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from '../shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-course-unenrollment-modal', templateUrl: './course-unenrollment-modal.component.html', + imports: [TranslateDirective, FormsModule, ReactiveFormsModule, FaIconComponent, ArtemisDatePipe, ArtemisTranslatePipe], }) export class CourseUnenrollmentModalComponent implements OnInit { + private activeModal = inject(NgbActiveModal); + private courseService = inject(CourseManagementService); + private alertService = inject(AlertService); + private router = inject(Router); + public course: Course; confirmationForm: FormGroup; // Icons faXmark = faXmark; - constructor( - private activeModal: NgbActiveModal, - private courseService: CourseManagementService, - private alertService: AlertService, - private router: Router, - ) {} - ngOnInit(): void { this.confirmationForm = new FormGroup({ confirmationInput: new FormControl('', Validators.compose([Validators.required, this.confirmationInputValidator()])), diff --git a/src/main/webapp/app/overview/courses-routing.module.ts b/src/main/webapp/app/overview/courses-routing.module.ts index 68e90e184205..0669891b2db4 100644 --- a/src/main/webapp/app/overview/courses-routing.module.ts +++ b/src/main/webapp/app/overview/courses-routing.module.ts @@ -1,17 +1,12 @@ import { RouterModule, Routes } from '@angular/router'; -import { CoursesComponent } from 'app/overview/courses.component'; + import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; -import { CourseLecturesComponent } from 'app/overview/course-lectures/course-lectures.component'; + import { NgModule } from '@angular/core'; import { Authority } from 'app/shared/constants/authority.constants'; -import { CourseExercisesComponent } from 'app/overview/course-exercises/course-exercises.component'; -import { CourseOverviewComponent } from './course-overview.component'; -import { CourseExamsComponent } from './course-exams/course-exams.component'; -import { CourseTutorialGroupsComponent } from './course-tutorial-groups/course-tutorial-groups.component'; -import { CourseTutorialGroupDetailComponent } from './tutorial-group-details/course-tutorial-group-detail/course-tutorial-group-detail.component'; -import { ExamParticipationComponent } from 'app/exam/participate/exam-participation.component'; + import { PendingChangesGuard } from 'app/shared/guard/pending-changes.guard'; -import { CourseArchiveComponent } from './course-archive/course-archive.component'; + import { CourseOverviewGuard } from 'app/overview/course-overview-guard'; export enum CourseOverviewRoutePath { @@ -32,7 +27,7 @@ export enum CourseOverviewRoutePath { const routes: Routes = [ { path: '', - component: CoursesComponent, + loadComponent: () => import('app/overview/courses.component').then((m) => m.CoursesComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.title', @@ -45,7 +40,7 @@ const routes: Routes = [ }, { path: CourseOverviewRoutePath.ARCHIVE, - component: CourseArchiveComponent, + loadComponent: () => import('./course-archive/course-archive.component').then((m) => m.CourseArchiveComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.archive', @@ -61,7 +56,7 @@ const routes: Routes = [ }, { path: ':courseId', - component: CourseOverviewComponent, + loadComponent: () => import('./course-overview.component').then((m) => m.CourseOverviewComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.course', @@ -70,7 +65,7 @@ const routes: Routes = [ children: [ { path: CourseOverviewRoutePath.EXERCISES, - component: CourseExercisesComponent, + loadComponent: () => import('app/overview/course-exercises/course-exercises.component').then((m) => m.CourseExercisesComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.exercises', @@ -144,7 +139,7 @@ const routes: Routes = [ { path: CourseOverviewRoutePath.LECTURES, - component: CourseLecturesComponent, + loadComponent: () => import('app/overview/course-lectures/course-lectures.component').then((m) => m.CourseLecturesComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.lectures', @@ -226,7 +221,7 @@ const routes: Routes = [ }, { path: CourseOverviewRoutePath.TUTORIAL_GROUPS, - component: CourseTutorialGroupsComponent, + loadComponent: () => import('./course-tutorial-groups/course-tutorial-groups.component').then((m) => m.CourseTutorialGroupsComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.tutorialGroups', @@ -237,7 +232,10 @@ const routes: Routes = [ children: [ { path: ':tutorialGroupId', - component: CourseTutorialGroupDetailComponent, + loadComponent: () => + import('./tutorial-group-details/course-tutorial-group-detail/course-tutorial-group-detail.component').then( + (m) => m.CourseTutorialGroupDetailComponent, + ), data: { authorities: [Authority.USER], pageTitle: 'overview.tutorialGroups', @@ -251,7 +249,7 @@ const routes: Routes = [ }, { path: CourseOverviewRoutePath.EXAMS, - component: CourseExamsComponent, + loadComponent: () => import('./course-exams/course-exams.component').then((m) => m.CourseExamsComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.exams', @@ -262,7 +260,7 @@ const routes: Routes = [ children: [ { path: ':examId', - component: ExamParticipationComponent, + loadComponent: () => import('app/exam/participate/exam-participation.component').then((m) => m.ExamParticipationComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.exams', diff --git a/src/main/webapp/app/overview/courses.component.ts b/src/main/webapp/app/overview/courses.component.ts index 2ad16cae7fcd..bf145a496679 100644 --- a/src/main/webapp/app/overview/courses.component.ts +++ b/src/main/webapp/app/overview/courses.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { CoursesForDashboardDTO } from 'app/course/manage/courses-for-dashboard-dto'; import { Course } from 'app/entities/course.model'; import { CourseManagementService } from '../course/manage/course-management.service'; @@ -9,18 +9,44 @@ import { TeamService } from 'app/exercises/shared/team/team.service'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; import dayjs from 'dayjs/esm'; import { Exam } from 'app/entities/exam/exam.model'; -import { Router } from '@angular/router'; +import { Router, RouterLink } from '@angular/router'; import { faArrowDownAZ, faArrowUpAZ, faDoorOpen, faPenAlt } from '@fortawesome/free-solid-svg-icons'; import { CourseAccessStorageService } from 'app/course/course-access-storage.service'; import { CourseForDashboardDTO } from 'app/course/manage/course-for-dashboard-dto'; import { sortCourses } from 'app/shared/util/course.util'; +import { TranslateDirective } from '../shared/language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { SearchFilterComponent } from '../shared/search-filter/search-filter.component'; +import { NgTemplateOutlet } from '@angular/common'; +import { CourseCardComponent } from './course-card.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from '../shared/pipes/artemis-translate.pipe'; +import { SearchFilterPipe } from 'app/shared/pipes/search-filter.pipe'; @Component({ selector: 'jhi-overview', templateUrl: './courses.component.html', styleUrls: ['./courses.component.scss'], + imports: [ + TranslateDirective, + FaIconComponent, + SearchFilterComponent, + RouterLink, + NgTemplateOutlet, + CourseCardComponent, + ArtemisDatePipe, + ArtemisTranslatePipe, + SearchFilterPipe, + ], }) export class CoursesComponent implements OnInit, OnDestroy { + private courseService = inject(CourseManagementService); + private guidedTourService = inject(GuidedTourService); + private teamService = inject(TeamService); + private jhiWebsocketService = inject(JhiWebsocketService); + private router = inject(Router); + private courseAccessStorageService = inject(CourseAccessStorageService); + protected readonly faPenAlt = faPenAlt; protected readonly faArrowDownAZ = faArrowDownAZ; protected readonly faArrowUpAZ = faArrowUpAZ; @@ -41,15 +67,6 @@ export class CoursesComponent implements OnInit, OnDestroy { coursesLoaded = false; isSortAscending = true; - constructor( - private courseService: CourseManagementService, - private guidedTourService: GuidedTourService, - private teamService: TeamService, - private jhiWebsocketService: JhiWebsocketService, - private router: Router, - private courseAccessStorageService: CourseAccessStorageService, - ) {} - async ngOnInit() { this.loadAndFilterCourses(); (await this.teamService.teamAssignmentUpdates).subscribe(); diff --git a/src/main/webapp/app/overview/courses.module.ts b/src/main/webapp/app/overview/courses.module.ts index 9d6693a17fdc..687ea33da9f8 100644 --- a/src/main/webapp/app/overview/courses.module.ts +++ b/src/main/webapp/app/overview/courses.module.ts @@ -3,7 +3,7 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ArtemisSidePanelModule } from 'app/shared/side-panel/side-panel.module'; import { CourseLectureRowComponent } from 'app/overview/course-lectures/course-lecture-row.component'; import { OrionModule } from 'app/shared/orion/orion.module'; -import { FeatureToggleModule } from 'app/shared/feature-toggle/feature-toggle.module'; + import { CourseCardComponent } from 'app/overview/course-card.component'; import { CourseOverviewComponent } from 'app/overview/course-overview.component'; import { ArtemisHeaderExercisePageWithDetailsModule } from 'app/exercises/shared/exercise-headers/exercise-headers.module'; @@ -32,14 +32,18 @@ import { SearchFilterComponent } from 'app/shared/search-filter/search-filter.co ArtemisHeaderExercisePageWithDetailsModule, OrionModule, ArtemisComplaintsModule, - FeatureToggleModule, RatingModule, NgxChartsModule, PieChartModule, ArtemisSidebarModule, CourseCardComponent, SearchFilterComponent, + CoursesComponent, + CourseOverviewComponent, + CourseExercisesComponent, + CourseLecturesComponent, + CourseLectureRowComponent, + CourseUnenrollmentModalComponent, ], - declarations: [CoursesComponent, CourseOverviewComponent, CourseExercisesComponent, CourseLecturesComponent, CourseLectureRowComponent, CourseUnenrollmentModalComponent], }) export class ArtemisCoursesModule {} diff --git a/src/main/webapp/app/overview/discussion-section/discussion-section.component.ts b/src/main/webapp/app/overview/discussion-section/discussion-section.component.ts index 63d5873cc3b1..b1e757f22b8a 100644 --- a/src/main/webapp/app/overview/discussion-section/discussion-section.component.ts +++ b/src/main/webapp/app/overview/discussion-section/discussion-section.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, ElementRef, OnDestroy, QueryList, ViewChild, ViewChildren, effect, input } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, OnDestroy, QueryList, ViewChild, ViewChildren, effect, inject, input } from '@angular/core'; import interact from 'interactjs'; import { Exercise } from 'app/entities/exercise.model'; import { Lecture } from 'app/entities/lecture.model'; @@ -11,23 +11,27 @@ import { PostCreateEditModalComponent } from 'app/shared/metis/posting-create-ed import { HttpResponse } from '@angular/common/http'; import { faArrowLeft, faChevronLeft, faChevronRight, faGripLinesVertical, faLongArrowRight } from '@fortawesome/free-solid-svg-icons'; import { CourseDiscussionDirective } from 'app/shared/metis/course-discussion.directive'; -import { FormBuilder } from '@angular/forms'; +import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { Channel, ChannelDTO } from 'app/entities/metis/conversation/channel.model'; import { ChannelService } from 'app/shared/metis/conversations/channel.service'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ArtemisPlagiarismCasesSharedModule } from 'app/course/plagiarism-cases/shared/plagiarism-cases-shared.module'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; -import { InfiniteScrollModule } from 'ngx-infinite-scroll'; +import { InfiniteScrollDirective } from 'ngx-infinite-scroll'; @Component({ selector: 'jhi-discussion-section', templateUrl: './discussion-section.component.html', styleUrls: ['./discussion-section.component.scss'], - imports: [FontAwesomeModule, ArtemisSharedModule, ArtemisPlagiarismCasesSharedModule, InfiniteScrollModule], - standalone: true, + imports: [FontAwesomeModule, ArtemisSharedModule, ArtemisPlagiarismCasesSharedModule, InfiniteScrollDirective, FormsModule, ReactiveFormsModule], providers: [MetisService], }) export class DiscussionSectionComponent extends CourseDiscussionDirective implements AfterViewInit, OnDestroy { + private channelService = inject(ChannelService); + private activatedRoute = inject(ActivatedRoute); + private router = inject(Router); + private formBuilder = inject(FormBuilder); + exercise = input(); lecture = input(); @@ -59,14 +63,8 @@ export class DiscussionSectionComponent extends CourseDiscussionDirective implem faArrowLeft = faArrowLeft; faLongArrowRight = faLongArrowRight; - constructor( - protected metisService: MetisService, - private channelService: ChannelService, - private activatedRoute: ActivatedRoute, - private router: Router, - private formBuilder: FormBuilder, - ) { - super(metisService); + constructor() { + super(); effect(() => this.loadData(this.exercise(), this.lecture())); } diff --git a/src/main/webapp/app/overview/exercise-details/course-exercise-details.component.html b/src/main/webapp/app/overview/exercise-details/course-exercise-details.component.html index 05e6e4d9d53e..a6b096b431c8 100644 --- a/src/main/webapp/app/overview/exercise-details/course-exercise-details.component.html +++ b/src/main/webapp/app/overview/exercise-details/course-exercise-details.component.html @@ -25,12 +25,14 @@
+ + + + + + + + @if (plagiarismCaseInfo && plagiarismCaseInfo.verdict !== PlagiarismVerdict.NO_PLAGIARISM) { @if (!plagiarismCaseInfo?.createdByContinuousPlagiarismControl) { diff --git a/src/main/webapp/app/overview/exercise-details/course-exercise-details.component.ts b/src/main/webapp/app/overview/exercise-details/course-exercise-details.component.ts index 6b81fedc9ad0..06b82b93db7d 100644 --- a/src/main/webapp/app/overview/exercise-details/course-exercise-details.component.ts +++ b/src/main/webapp/app/overview/exercise-details/course-exercise-details.component.ts @@ -1,6 +1,6 @@ -import { Component, ContentChild, OnDestroy, OnInit, TemplateRef } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, RouterLink } from '@angular/router'; import { Subscription, combineLatest } from 'rxjs'; import { filter, skip } from 'rxjs/operators'; import { Result } from 'app/entities/result.model'; @@ -17,13 +17,11 @@ import { ExampleSolutionInfo, ExerciseDetailsType, ExerciseService } from 'app/e import { AssessmentType } from 'app/entities/assessment-type.model'; import { hasExerciseDueDatePassed } from 'app/exercises/shared/exercise/exercise.utils'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; -import { GradingCriterion } from 'app/exercises/shared/structured-grading-criterion/grading-criterion.model'; import { AlertService } from 'app/core/util/alert.service'; import { TeamAssignmentPayload } from 'app/entities/team.model'; import { TeamService } from 'app/exercises/shared/team/team.service'; import { QuizExercise, QuizStatus } from 'app/entities/quiz/quiz-exercise.model'; import { QuizExerciseService } from 'app/exercises/quiz/manage/quiz-exercise.service'; -import { ExerciseCategory } from 'app/entities/exercise-category.model'; import { getFirstResultWithComplaintFromResults } from 'app/entities/submission.model'; import { ComplaintService } from 'app/complaints/complaint.service'; import { Complaint } from 'app/entities/complaint.model'; @@ -37,11 +35,30 @@ import { isCommunicationEnabled, isMessagingEnabled } from 'app/entities/course. import { ExerciseCacheService } from 'app/exercises/shared/exercise/exercise-cache.service'; import { IrisSettings } from 'app/entities/iris/settings/iris-settings.model'; import { AbstractScienceComponent } from 'app/shared/science/science.component'; -import { ScienceService } from 'app/shared/science/science.service'; import { ScienceEventType } from 'app/shared/science/science.model'; import { PROFILE_IRIS } from 'app/app.constants'; import { ChatServiceMode } from 'app/iris/iris-chat.service'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; +import { NgClass } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbDropdown, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ExerciseDetailsStudentActionsComponent } from './exercise-details-student-actions.component'; +import { ExerciseHeadersInformationComponent } from 'app/exercises/shared/exercise-headers/exercise-headers-information/exercise-headers-information.component'; +import { ResultHistoryComponent } from '../result-history/result-history.component'; +import { ResultComponent } from 'app/exercises/shared/result/result.component'; +import { ProblemStatementComponent } from './problem-statement/problem-statement.component'; +import { ResetRepoButtonComponent } from 'app/shared/components/reset-repo-button/reset-repo-button.component'; +import { ModelingEditorComponent } from 'app/exercises/modeling/shared/modeling-editor.component'; +import { ProgrammingExerciseExampleSolutionRepoDownloadComponent } from 'app/exercises/programming/shared/actions/programming-exercise-example-solution-repo-download.component'; +import { ExerciseInfoComponent } from 'app/exercises/shared/exercise-info/exercise-info.component'; +import { ComplaintsStudentViewComponent } from 'app/complaints/complaints-for-students/complaints-student-view.component'; +import { RatingComponent } from 'app/exercises/shared/rating/rating.component'; +import { IrisExerciseChatbotButtonComponent } from 'app/iris/exercise-chatbot/exercise-chatbot-button.component'; +import { DiscussionSectionComponent } from '../discussion-section/discussion-section.component'; +import { LtiInitializerComponent } from './lti-initializer.component'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; interface InstructorActionItem { routerLink: string; @@ -53,8 +70,49 @@ interface InstructorActionItem { templateUrl: './course-exercise-details.component.html', styleUrls: ['../course-overview.scss', './course-exercise-details.component.scss'], providers: [ExerciseCacheService], + imports: [ + NgClass, + FaIconComponent, + NgbDropdown, + NgbDropdownToggle, + NgbDropdownMenu, + NgbDropdownItem, + RouterLink, + TranslateDirective, + // TODO: the extension point for Orion does not work with Angular 19, we need to find a different solution + // ExtensionPointDirective, + ExerciseDetailsStudentActionsComponent, + ExerciseHeadersInformationComponent, + ResultHistoryComponent, + ResultComponent, + ProblemStatementComponent, + ResetRepoButtonComponent, + ModelingEditorComponent, + ProgrammingExerciseExampleSolutionRepoDownloadComponent, + NgbTooltip, + ExerciseInfoComponent, + ComplaintsStudentViewComponent, + RatingComponent, + IrisExerciseChatbotButtonComponent, + DiscussionSectionComponent, + LtiInitializerComponent, + ArtemisDatePipe, + ArtemisTranslatePipe, + ], }) export class CourseExerciseDetailsComponent extends AbstractScienceComponent implements OnInit, OnDestroy { + private exerciseService = inject(ExerciseService); + private participationWebsocketService = inject(ParticipationWebsocketService); + private participationService = inject(ParticipationService); + private route = inject(ActivatedRoute); + private profileService = inject(ProfileService); + private guidedTourService = inject(GuidedTourService); + private alertService = inject(AlertService); + private teamService = inject(TeamService); + private quizExerciseService = inject(QuizExerciseService); + private complaintService = inject(ComplaintService); + private artemisMarkdown = inject(ArtemisMarkdownService); + readonly AssessmentType = AssessmentType; readonly PlagiarismVerdict = PlagiarismVerdict; readonly QuizStatus = QuizStatus; @@ -75,12 +133,11 @@ export class CourseExerciseDetailsComponent extends AbstractScienceComponent imp public exerciseId: number; public courseId: number; public exercise: Exercise; - public resultWithComplaint?: Result; - public latestRatedResult?: Result; - public complaint?: Complaint; - public showMoreResults = false; + resultWithComplaint?: Result; + latestRatedResult?: Result; + complaint?: Complaint; + showMoreResults = false; public sortedHistoryResults: Result[]; - public exerciseCategories: ExerciseCategory[]; private participationUpdateListener: Subscription; private teamAssignmentUpdateListener: Subscription; private submissionSubscription: Subscription; @@ -89,9 +146,7 @@ export class CourseExerciseDetailsComponent extends AbstractScienceComponent imp practiceStudentParticipation?: StudentParticipation; isAfterAssessmentDueDate: boolean; allowComplaintsForAutomaticAssessments: boolean; - public gradingCriteria: GradingCriterion[]; baseResource: string; - isExamExercise: boolean; submissionPolicy?: SubmissionPolicy; exampleSolutionCollapsed: boolean; plagiarismCaseInfo?: PlagiarismCaseInfo; @@ -100,14 +155,15 @@ export class CourseExerciseDetailsComponent extends AbstractScienceComponent imp profileSubscription?: Subscription; isProduction = true; isTestServer = false; - isGeneratingFeedback: boolean = false; instructorActionItems: InstructorActionItem[] = []; exerciseIcon: IconProp; exampleSolutionInfo?: ExampleSolutionInfo; // extension points, see shared/extension-point - @ContentChild('overrideStudentActions') overrideStudentActions: TemplateRef; + // TODO: the extension point for Orion does not work with Angular 19, we need to find a different solution + // @ContentChild('overrideStudentActions') overrideStudentActions: TemplateRef; + // Icons faBook = faBook; faEye = faEye; @@ -117,21 +173,8 @@ export class CourseExerciseDetailsComponent extends AbstractScienceComponent imp faAngleDown = faAngleDown; faAngleUp = faAngleUp; - constructor( - private exerciseService: ExerciseService, - private participationWebsocketService: ParticipationWebsocketService, - private participationService: ParticipationService, - private route: ActivatedRoute, - private profileService: ProfileService, - private guidedTourService: GuidedTourService, - private alertService: AlertService, - private teamService: TeamService, - private quizExerciseService: QuizExerciseService, - private complaintService: ComplaintService, - private artemisMarkdown: ArtemisMarkdownService, - scienceService: ScienceService, - ) { - super(scienceService, ScienceEventType.EXERCISE__OPEN); + constructor() { + super(ScienceEventType.EXERCISE__OPEN); } ngOnInit() { @@ -182,7 +225,6 @@ export class CourseExerciseDetailsComponent extends AbstractScienceComponent imp this.filterUnfinishedResults(this.exercise.studentParticipations); this.mergeResultsAndSubmissionsForParticipations(); this.isAfterAssessmentDueDate = !this.exercise.assessmentDueDate || dayjs().isAfter(this.exercise.assessmentDueDate); - this.exerciseCategories = this.exercise.categories ?? []; this.allowComplaintsForAutomaticAssessments = false; this.plagiarismCaseInfo = newExerciseDetails.plagiarismCaseInfo; if (this.exercise.type === ExerciseType.PROGRAMMING) { @@ -295,7 +337,6 @@ export class CourseExerciseDetailsComponent extends AbstractScienceComponent imp changedParticipation.id === this.gradedStudentParticipation?.id && (changedParticipation.results?.length || 0) > (this.gradedStudentParticipation?.results?.length || 0) ) { - this.isGeneratingFeedback = false; this.alertService.success('artemisApp.exercise.lateSubmissionResultReceived'); } if ( @@ -304,7 +345,6 @@ export class CourseExerciseDetailsComponent extends AbstractScienceComponent imp changedParticipation.results?.last()?.assessmentType === AssessmentType.AUTOMATIC_ATHENA && changedParticipation.results?.last()?.successful !== undefined ) { - this.isGeneratingFeedback = false; if (changedParticipation.results?.last()?.successful === true) { this.alertService.success('artemisApp.exercise.athenaFeedbackSuccessful'); } else { diff --git a/src/main/webapp/app/overview/exercise-details/course-exercise-details.module.ts b/src/main/webapp/app/overview/exercise-details/course-exercise-details.module.ts index ec6495463ecc..289c8e30b68e 100644 --- a/src/main/webapp/app/overview/exercise-details/course-exercise-details.module.ts +++ b/src/main/webapp/app/overview/exercise-details/course-exercise-details.module.ts @@ -1,3 +1,4 @@ +import { OrionCourseExerciseDetailsComponent } from 'app/orion/participation/orion-course-exercise-details.component'; import { CourseExerciseDetailsComponent } from 'app/overview/exercise-details/course-exercise-details.component'; import { ArtemisProgrammingExerciseInstructionsRenderModule } from 'app/exercises/programming/shared/instructions-render/programming-exercise-instructions-render.module'; import { RouterModule, Routes } from '@angular/router'; @@ -5,7 +6,7 @@ import { NgModule } from '@angular/core'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ArtemisSidePanelModule } from 'app/shared/side-panel/side-panel.module'; import { OrionModule } from 'app/shared/orion/orion.module'; -import { FeatureToggleModule } from 'app/shared/feature-toggle/feature-toggle.module'; + import { ArtemisHeaderExercisePageWithDetailsModule } from 'app/exercises/shared/exercise-headers/exercise-headers.module'; import { ArtemisResultModule } from 'app/exercises/shared/result/result.module'; import { ArtemisComplaintsModule } from 'app/complaints/complaints.module'; @@ -16,8 +17,7 @@ import { ArtemisExerciseButtonsModule } from 'app/overview/exercise-details/exer import { ArtemisCourseExerciseRowModule } from 'app/overview/course-exercises/course-exercise-row.module'; import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; import { Authority } from 'app/shared/constants/authority.constants'; -import { OrionCourseExerciseDetailsComponent } from 'app/orion/participation/orion-course-exercise-details.component'; -import { isOrion } from 'app/shared/orion/orion'; + import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; import { ArtemisModelingEditorModule } from 'app/exercises/modeling/shared/modeling-editor.module'; import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; @@ -35,7 +35,7 @@ import { ExerciseHeadersInformationComponent } from 'app/exercises/shared/exerci const routes: Routes = [ { path: '', - component: !isOrion ? CourseExerciseDetailsComponent : OrionCourseExerciseDetailsComponent, + loadComponent: () => import('app/orion/participation/orion-course-exercise-details.component').then((m) => m.OrionCourseExerciseDetailsComponent), data: { authorities: [Authority.USER], pageTitle: 'overview.exercise', @@ -59,7 +59,6 @@ const standaloneComponents = [ExerciseHeadersInformationComponent]; ArtemisHeaderExercisePageWithDetailsModule, OrionModule, ArtemisComplaintsModule, - FeatureToggleModule, FontAwesomeModule, RatingModule, ArtemisProgrammingExerciseInstructionsRenderModule, @@ -73,8 +72,12 @@ const standaloneComponents = [ExerciseHeadersInformationComponent]; IrisModule, DiscussionSectionComponent, [...standaloneComponents], + CourseExerciseDetailsComponent, + OrionCourseExerciseDetailsComponent, + LtiInitializerComponent, + LtiInitializerModalComponent, + ProblemStatementComponent, ], - declarations: [CourseExerciseDetailsComponent, OrionCourseExerciseDetailsComponent, LtiInitializerComponent, LtiInitializerModalComponent, ProblemStatementComponent], exports: [CourseExerciseDetailsComponent, OrionCourseExerciseDetailsComponent, ProblemStatementComponent], }) export class CourseExerciseDetailsModule {} diff --git a/src/main/webapp/app/overview/exercise-details/exercise-buttons.module.ts b/src/main/webapp/app/overview/exercise-details/exercise-buttons.module.ts index 7b6aab3d5f7c..6bf6489f09ef 100644 --- a/src/main/webapp/app/overview/exercise-details/exercise-buttons.module.ts +++ b/src/main/webapp/app/overview/exercise-details/exercise-buttons.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { OrionModule } from 'app/shared/orion/orion.module'; -import { FeatureToggleModule } from 'app/shared/feature-toggle/feature-toggle.module'; + import { OrionExerciseDetailsStudentActionsComponent } from 'app/orion/participation/orion-exercise-details-student-actions.component'; import { ExerciseDetailsStudentActionsComponent } from 'app/overview/exercise-details/exercise-details-student-actions.component'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; @@ -9,8 +9,15 @@ import { ArtemisSharedPipesModule } from 'app/shared/pipes/shared-pipes.module'; import { RequestFeedbackButtonComponent } from 'app/overview/exercise-details/request-feedback-button/request-feedback-button.component'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisSharedPipesModule, OrionModule, FeatureToggleModule, RequestFeedbackButtonComponent], - declarations: [ExerciseDetailsStudentActionsComponent, OrionExerciseDetailsStudentActionsComponent], + imports: [ + ArtemisSharedModule, + ArtemisSharedComponentModule, + ArtemisSharedPipesModule, + OrionModule, + RequestFeedbackButtonComponent, + ExerciseDetailsStudentActionsComponent, + OrionExerciseDetailsStudentActionsComponent, + ], exports: [ExerciseDetailsStudentActionsComponent, OrionExerciseDetailsStudentActionsComponent], }) export class ArtemisExerciseButtonsModule {} diff --git a/src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.html b/src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.html index 6b7f975bec37..4e4b195b8a3a 100644 --- a/src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.html +++ b/src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.html @@ -107,40 +107,41 @@ /> } + code editor button. We should think about defining a component that contains only the code button. --> @if (shouldDisplayIDEButtons()) { - - @if (!examMode && programmingExercise?.allowOnlineEditor) { - - } - @if (programmingExercise?.allowOfflineIde) { - - } - @if (theiaEnabled) { - - - - - } - @if (exercise.allowFeedbackRequests && gradedParticipation && exercise.type === ExerciseType.PROGRAMMING) { - - } - + + + @if (!examMode && programmingExercise?.allowOnlineEditor) { + + } + @if (programmingExercise?.allowOfflineIde) { + + } + @if (theiaEnabled) { + + + + + } + @if (exercise.allowFeedbackRequests && gradedParticipation && exercise.type === ExerciseType.PROGRAMMING) { + + } + } @if ( diff --git a/src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.ts b/src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.ts index 97dc98b15681..7ec633dfa89e 100644 --- a/src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.ts +++ b/src/main/webapp/app/overview/exercise-details/exercise-details-student-actions.component.ts @@ -1,5 +1,5 @@ -import { Component, ContentChild, EventEmitter, HostBinding, Input, OnChanges, OnInit, Output, TemplateRef } from '@angular/core'; -import { Router } from '@angular/router'; +import { Component, EventEmitter, HostBinding, Input, OnChanges, OnInit, Output, inject } from '@angular/core'; +import { Router, RouterLink } from '@angular/router'; import { AlertService } from 'app/core/util/alert.service'; import { ExternalCloningService } from 'app/exercises/programming/shared/service/external-cloning.service'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; @@ -11,9 +11,8 @@ import { ProgrammingExercise } from 'app/entities/programming/programming-exerci import { StudentParticipation } from 'app/entities/participation/student-participation.model'; import { ArtemisQuizService } from 'app/shared/quiz/quiz.service'; import { finalize } from 'rxjs/operators'; -import { faCodeBranch, faDesktop, faEye, faFolderOpen, faPenSquare, faPlayCircle, faRedo, faUsers } from '@fortawesome/free-solid-svg-icons'; +import { faDesktop, faEye, faFolderOpen, faPlayCircle, faRedo, faUsers } from '@fortawesome/free-solid-svg-icons'; import { CourseExerciseService } from 'app/exercises/shared/course-exercises/course-exercise.service'; -import { TranslateService } from '@ngx-translate/core'; import { ParticipationService } from 'app/exercises/shared/participation/participation.service'; import dayjs from 'dayjs/esm'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; @@ -21,14 +20,47 @@ import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { PROFILE_ATHENA, PROFILE_LOCALVC, PROFILE_THEIA } from 'app/app.constants'; import { AssessmentType } from 'app/entities/assessment-type.model'; import { ButtonType } from 'app/shared/components/button.component'; +import { NgTemplateOutlet } from '@angular/common'; +import { ExerciseActionButtonComponent } from 'app/shared/components/exercise-action-button.component'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FeatureToggleDirective } from 'app/shared/feature-toggle/feature-toggle.directive'; +import { StartPracticeModeButtonComponent } from 'app/shared/components/start-practice-mode-button/start-practice-mode-button.component'; +import { OpenCodeEditorButtonComponent } from 'app/shared/components/open-code-editor-button/open-code-editor-button.component'; +import { CodeButtonComponent } from 'app/shared/components/code-button/code-button.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { RequestFeedbackButtonComponent } from './request-feedback-button/request-feedback-button.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ + imports: [ + NgTemplateOutlet, + ExerciseActionButtonComponent, + RouterLink, + NgbTooltip, + FeatureToggleDirective, + StartPracticeModeButtonComponent, + // TODO: the extension point for Orion does not work with Angular 19, we need to find a different solution + // ExtensionPointDirective, + OpenCodeEditorButtonComponent, + CodeButtonComponent, + FaIconComponent, + TranslateDirective, + RequestFeedbackButtonComponent, + ArtemisTranslatePipe, + ], + providers: [ExternalCloningService], selector: 'jhi-exercise-details-student-actions', - templateUrl: './exercise-details-student-actions.component.html', styleUrls: ['../course-overview.scss'], - providers: [ExternalCloningService], + templateUrl: './exercise-details-student-actions.component.html', }) export class ExerciseDetailsStudentActionsComponent implements OnInit, OnChanges { + private alertService = inject(AlertService); + private courseExerciseService = inject(CourseExerciseService); + private router = inject(Router); + private participationService = inject(ParticipationService); + private profileService = inject(ProfileService); + readonly FeatureToggle = FeatureToggle; readonly ExerciseType = ExerciseType; readonly InitializationState = InitializationState; @@ -46,7 +78,8 @@ export class ExerciseDetailsStudentActionsComponent implements OnInit, OnChanges @Output() generatingFeedback: EventEmitter = new EventEmitter(); // extension points, see shared/extension-point - @ContentChild('overrideCodeAndOnlineEditorButton') overrideCodeAndOnlineEditorButton: TemplateRef; + // TODO: the extension point for Orion does not work with Angular 19, we need to find a different solution + // @ContentChild('overrideCodeAndOnlineEditorButton') overrideCodeAndOnlineEditorButton: TemplateRef; uninitializedQuiz: boolean; quizNotStarted: boolean; @@ -71,20 +104,7 @@ export class ExerciseDetailsStudentActionsComponent implements OnInit, OnChanges readonly faEye = faEye; readonly faPlayCircle = faPlayCircle; readonly faRedo = faRedo; - readonly faCodeBranch = faCodeBranch; readonly faDesktop = faDesktop; - readonly faPenSquare = faPenSquare; - - private feedbackSent = false; - - constructor( - private alertService: AlertService, - private courseExerciseService: CourseExerciseService, - private router: Router, - private translateService: TranslateService, - private participationService: ParticipationService, - private profileService: ProfileService, - ) {} ngOnInit(): void { this.repositoryLink = this.router.url; @@ -308,8 +328,4 @@ export class ExerciseDetailsStudentActionsComponent implements OnInit, OnChanges const participations = this.exercise.studentParticipations; return participations?.length ? participations[0].team?.id : this.exercise.studentAssignedTeamId; } - - buildPlanUrl(participation: StudentParticipation) { - return (participation as ProgrammingExerciseStudentParticipation).buildPlanUrl; - } } diff --git a/src/main/webapp/app/overview/exercise-details/lti-initializer-modal.component.ts b/src/main/webapp/app/overview/exercise-details/lti-initializer-modal.component.ts index 0bb7a8b46d5a..69e4cd290199 100644 --- a/src/main/webapp/app/overview/exercise-details/lti-initializer-modal.component.ts +++ b/src/main/webapp/app/overview/exercise-details/lti-initializer-modal.component.ts @@ -1,11 +1,15 @@ import { Component, inject } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { AlertService } from 'app/core/util/alert.service'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { FormsModule } from '@angular/forms'; +import { CopyIconButtonComponent } from 'app/shared/components/copy-icon-button/copy-icon-button.component'; @Component({ selector: 'jhi-lti-initializer-modal', templateUrl: './lti-initializer-modal.component.html', + imports: [TranslateDirective, FormsModule, CopyIconButtonComponent, RouterLink], }) export class LtiInitializerModalComponent { private activeModal = inject(NgbActiveModal); diff --git a/src/main/webapp/app/overview/exercise-details/problem-statement/problem-statement.component.ts b/src/main/webapp/app/overview/exercise-details/problem-statement/problem-statement.component.ts index 3b70909f554e..4ca8c6409f23 100644 --- a/src/main/webapp/app/overview/exercise-details/problem-statement/problem-statement.component.ts +++ b/src/main/webapp/app/overview/exercise-details/problem-statement/problem-statement.component.ts @@ -1,29 +1,31 @@ import { HttpResponse } from '@angular/common/http'; -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Exercise, ExerciseType } from 'app/entities/exercise.model'; import { StudentParticipation } from 'app/entities/participation/student-participation.model'; import { ExerciseDetailsType, ExerciseService } from 'app/exercises/shared/exercise/exercise.service'; import { ParticipationService } from 'app/exercises/shared/participation/participation.service'; +import { ProgrammingExerciseInstructionComponent } from 'app/exercises/programming/shared/instructions-render/programming-exercise-instruction.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; @Component({ selector: 'jhi-problem-statement', templateUrl: './problem-statement.component.html', styleUrls: ['../../course-overview.scss'], + imports: [ProgrammingExerciseInstructionComponent, TranslateDirective, HtmlForMarkdownPipe], }) export class ProblemStatementComponent implements OnInit { + private route = inject(ActivatedRoute); + private exerciseService = inject(ExerciseService); + private participationService = inject(ParticipationService); + @Input() public exercise?: Exercise; @Input() participation?: StudentParticipation; - constructor( - private route: ActivatedRoute, - private exerciseService: ExerciseService, - private participationService: ParticipationService, - ) {} - ngOnInit() { this.route.params.subscribe((params) => { const exerciseId = parseInt(params['exerciseId'], 10); diff --git a/src/main/webapp/app/overview/exercise-details/request-feedback-button/request-feedback-button.component.ts b/src/main/webapp/app/overview/exercise-details/request-feedback-button/request-feedback-button.component.ts index 0f0ec10c1c14..f73c6ba0105d 100644 --- a/src/main/webapp/app/overview/exercise-details/request-feedback-button/request-feedback-button.component.ts +++ b/src/main/webapp/app/overview/exercise-details/request-feedback-button/request-feedback-button.component.ts @@ -18,7 +18,6 @@ import { ParticipationService } from 'app/exercises/shared/participation/partici @Component({ selector: 'jhi-request-feedback-button', - standalone: true, imports: [CommonModule, ArtemisSharedCommonModule, NgbTooltipModule, FontAwesomeModule], templateUrl: './request-feedback-button.component.html', }) diff --git a/src/main/webapp/app/overview/header-course.component.ts b/src/main/webapp/app/overview/header-course.component.ts index 3cdbdb04c465..d698b4d429ce 100644 --- a/src/main/webapp/app/overview/header-course.component.ts +++ b/src/main/webapp/app/overview/header-course.component.ts @@ -1,16 +1,24 @@ -import { Component, HostListener, Input, OnChanges } from '@angular/core'; +import { Component, HostListener, Input, OnChanges, inject } from '@angular/core'; import { Course } from 'app/entities/course.model'; import { ARTEMIS_DEFAULT_COLOR } from 'app/app.constants'; import { CachingStrategy } from 'app/shared/image/secured-image.component'; -import { Router } from '@angular/router'; +import { Router, RouterLink } from '@angular/router'; import { faArrowDown } from '@fortawesome/free-solid-svg-icons'; +import { NgStyle } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from '../shared/language/translate.directive'; +import { SecuredImageComponent } from '../shared/image/secured-image.component'; +import { ArtemisTranslatePipe } from '../shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-header-course', templateUrl: './header-course.component.html', styleUrls: ['./header-course.component.scss'], + imports: [NgStyle, FaIconComponent, TranslateDirective, RouterLink, SecuredImageComponent, ArtemisTranslatePipe], }) export class HeaderCourseComponent implements OnChanges { + protected router = inject(Router); + readonly ARTEMIS_DEFAULT_COLOR = ARTEMIS_DEFAULT_COLOR; readonly CachingStrategy = CachingStrategy; @@ -21,7 +29,6 @@ export class HeaderCourseComponent implements OnChanges { public longDescriptionShown = false; faArrowDown = faArrowDown; - constructor(protected router: Router) {} ngOnChanges() { this.adjustCourseDescription(); diff --git a/src/main/webapp/app/overview/participation-websocket.service.ts b/src/main/webapp/app/overview/participation-websocket.service.ts index 3836e7a81209..7e7f40e98f8d 100644 --- a/src/main/webapp/app/overview/participation-websocket.service.ts +++ b/src/main/webapp/app/overview/participation-websocket.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { BehaviorSubject, of, pipe } from 'rxjs'; import { switchMap, tap } from 'rxjs/operators'; import { Participation } from 'app/entities/participation/participation.model'; @@ -25,6 +25,9 @@ export interface IParticipationWebsocketService { @Injectable({ providedIn: 'root' }) export class ParticipationWebsocketService implements IParticipationWebsocketService { + private jhiWebsocketService = inject(JhiWebsocketService); + private participationService = inject(ParticipationService); + cachedParticipations: Map = new Map(); openResultWebsocketSubscriptions: Map = new Map(); openPersonalWebsocketSubscription?: string; /* url of websocket connection */ @@ -33,11 +36,6 @@ export class ParticipationWebsocketService implements IParticipationWebsocketSer subscribedExercises: Map /* IDs of the participations of this exercise */> = new Map>(); participationSubscriptionTypes: Map = new Map(); - constructor( - private jhiWebsocketService: JhiWebsocketService, - private participationService: ParticipationService, - ) {} - private getNotifyAllSubscribersPipe = () => { return pipe(tap(this.notifyResultSubscribers), switchMap(this.addResultToParticipation), tap(this.notifyParticipationSubscribers)); }; diff --git a/src/main/webapp/app/overview/result-history/result-history.component.ts b/src/main/webapp/app/overview/result-history/result-history.component.ts index ded0d2c95639..028ae3b59a1a 100644 --- a/src/main/webapp/app/overview/result-history/result-history.component.ts +++ b/src/main/webapp/app/overview/result-history/result-history.component.ts @@ -2,6 +2,9 @@ import { Component, OnChanges, input } from '@angular/core'; import { Result } from 'app/entities/result.model'; import { Exercise, ExerciseType } from 'app/entities/exercise.model'; import { MissingResultInformation, evaluateTemplateStatus, getResultIconClass, getTextColorClass } from 'app/exercises/shared/result/result.utils'; +import { NgClass, NgStyle } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ResultComponent } from '../../exercises/shared/result/result.component'; export const MAX_RESULT_HISTORY_LENGTH = 5; @@ -10,6 +13,7 @@ export const MAX_RESULT_HISTORY_LENGTH = 5; selector: 'jhi-result-history', templateUrl: './result-history.component.html', styleUrls: ['./result-history.scss'], + imports: [NgClass, FaIconComponent, ResultComponent, NgStyle], }) export class ResultHistoryComponent implements OnChanges { readonly getTextColorClass = getTextColorClass; diff --git a/src/main/webapp/app/overview/submission-result-status.component.ts b/src/main/webapp/app/overview/submission-result-status.component.ts index 78fc9b3a0a4d..ce737d23d33f 100644 --- a/src/main/webapp/app/overview/submission-result-status.component.ts +++ b/src/main/webapp/app/overview/submission-result-status.component.ts @@ -5,10 +5,14 @@ import { InitializationState } from 'app/entities/participation/participation.mo import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; import { ArtemisQuizService } from 'app/shared/quiz/quiz.service'; import dayjs from 'dayjs/esm'; +import { UpdatingResultComponent } from '../exercises/shared/result/updating-result.component'; +import { TranslateDirective } from '../shared/language/translate.directive'; +import { ProgrammingExerciseStudentTriggerBuildButtonComponent } from '../exercises/programming/shared/actions/programming-exercise-student-trigger-build-button.component'; @Component({ selector: 'jhi-submission-result-status', templateUrl: './submission-result-status.component.html', + imports: [UpdatingResultComponent, TranslateDirective, ProgrammingExerciseStudentTriggerBuildButtonComponent], }) export class SubmissionResultStatusComponent implements OnChanges { private readonly initializationStatesToShowProgrammingResult = [InitializationState.INITIALIZED, InitializationState.INACTIVE, InitializationState.FINISHED]; diff --git a/src/main/webapp/app/overview/submission-result-status.module.ts b/src/main/webapp/app/overview/submission-result-status.module.ts index eb16329d6fc5..8e5c1b8b4257 100644 --- a/src/main/webapp/app/overview/submission-result-status.module.ts +++ b/src/main/webapp/app/overview/submission-result-status.module.ts @@ -8,8 +8,15 @@ import { ArtemisSharedComponentModule } from 'app/shared/components/shared-compo import { ResultProgressBarComponent } from 'app/exercises/shared/result/result-progress-bar/result-progress-bar.component'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisProgrammingExerciseActionsModule, ArtemisSharedComponentModule, ResultProgressBarComponent], - declarations: [SubmissionResultStatusComponent, UpdatingResultComponent, ResultComponent], + imports: [ + ArtemisSharedModule, + ArtemisProgrammingExerciseActionsModule, + ArtemisSharedComponentModule, + ResultProgressBarComponent, + SubmissionResultStatusComponent, + UpdatingResultComponent, + ResultComponent, + ], exports: [SubmissionResultStatusComponent, UpdatingResultComponent, ResultComponent], }) export class SubmissionResultStatusModule {} diff --git a/src/main/webapp/app/overview/tutorial-group-details/course-tutorial-group-detail/course-tutorial-group-detail.component.ts b/src/main/webapp/app/overview/tutorial-group-details/course-tutorial-group-detail/course-tutorial-group-detail.component.ts index 047a8426ddee..287910f0c081 100644 --- a/src/main/webapp/app/overview/tutorial-group-details/course-tutorial-group-detail/course-tutorial-group-detail.component.ts +++ b/src/main/webapp/app/overview/tutorial-group-details/course-tutorial-group-detail/course-tutorial-group-detail.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { Course } from 'app/entities/course.model'; import { ActivatedRoute } from '@angular/router'; @@ -9,13 +9,23 @@ import { HttpErrorResponse } from '@angular/common/http'; import { onError } from 'app/shared/util/global.utils'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; +import { LoadingIndicatorContainerComponent } from 'app/shared/loading-indicator-container/loading-indicator-container.component'; +import { AsyncPipe, NgClass } from '@angular/common'; +import { TutorialGroupDetailComponent } from 'app/course/tutorial-groups/shared/tutorial-group-detail/tutorial-group-detail.component'; @Component({ selector: 'jhi-course-tutorial-group-detail', templateUrl: './course-tutorial-group-detail.component.html', styleUrls: ['./course-tutorial-group-detail.component.scss'], + imports: [LoadingIndicatorContainerComponent, NgClass, TutorialGroupDetailComponent, AsyncPipe], }) export class CourseTutorialGroupDetailComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private tutorialGroupService = inject(TutorialGroupsService); + private alertService = inject(AlertService); + private courseManagementService = inject(CourseManagementService); + private profileService = inject(ProfileService); + isLoading$ = new BehaviorSubject(false); tutorialGroup?: TutorialGroup; course?: Course; @@ -24,14 +34,6 @@ export class CourseTutorialGroupDetailComponent implements OnInit, OnDestroy { isProduction = true; isTestServer = false; - constructor( - private route: ActivatedRoute, - private tutorialGroupService: TutorialGroupsService, - private alertService: AlertService, - private courseManagementService: CourseManagementService, - private profileService: ProfileService, - ) {} - ngOnInit(): void { const courseIdParams$ = this.route.parent?.parent?.params; const tutorialGroupIdParams$ = this.route.params; diff --git a/src/main/webapp/app/overview/tutorial-group-details/course-tutorial-group-details.module.ts b/src/main/webapp/app/overview/tutorial-group-details/course-tutorial-group-details.module.ts index 090a381aa1c8..ae2ddcac2112 100644 --- a/src/main/webapp/app/overview/tutorial-group-details/course-tutorial-group-details.module.ts +++ b/src/main/webapp/app/overview/tutorial-group-details/course-tutorial-group-details.module.ts @@ -1,15 +1,17 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { ArtemisTutorialGroupsSharedModule } from 'app/course/tutorial-groups/shared/tutorial-groups-shared.module'; -import { CourseTutorialGroupDetailComponent } from 'app/overview/tutorial-group-details/course-tutorial-group-detail/course-tutorial-group-detail.component'; + import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; +import { CourseTutorialGroupDetailComponent } from 'app/overview/tutorial-group-details/course-tutorial-group-detail/course-tutorial-group-detail.component'; import { Authority } from 'app/shared/constants/authority.constants'; import { ArtemisSharedModule } from 'app/shared/shared.module'; const routes: Routes = [ { path: '', - component: CourseTutorialGroupDetailComponent, + loadComponent: () => + import('app/overview/tutorial-group-details/course-tutorial-group-detail/course-tutorial-group-detail.component').then((m) => m.CourseTutorialGroupDetailComponent), data: { authorities: [Authority.USER], pageTitle: 'artemisApp.pages.courseTutorialGroupDetail.title', @@ -19,7 +21,6 @@ const routes: Routes = [ ]; @NgModule({ - imports: [ArtemisTutorialGroupsSharedModule, RouterModule.forChild(routes), ArtemisSharedModule], - declarations: [CourseTutorialGroupDetailComponent], + imports: [ArtemisTutorialGroupsSharedModule, RouterModule.forChild(routes), ArtemisSharedModule, CourseTutorialGroupDetailComponent], }) export class CourseTutorialGroupDetailsModule {} diff --git a/src/main/webapp/app/overview/visualizations/exercise-scores-chart.module.ts b/src/main/webapp/app/overview/visualizations/exercise-scores-chart.module.ts index e0d3a22862c3..905cb064fb62 100644 --- a/src/main/webapp/app/overview/visualizations/exercise-scores-chart.module.ts +++ b/src/main/webapp/app/overview/visualizations/exercise-scores-chart.module.ts @@ -6,8 +6,7 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; import { LineChartModule } from '@swimlane/ngx-charts'; @NgModule({ - imports: [TranslateModule, CommonModule, ArtemisSharedModule, LineChartModule], - declarations: [ExerciseScoresChartComponent], + imports: [TranslateModule, CommonModule, ArtemisSharedModule, LineChartModule, ExerciseScoresChartComponent], exports: [ExerciseScoresChartComponent], }) export class ArtemisExerciseScoresChartModule {} diff --git a/src/main/webapp/app/overview/visualizations/exercise-scores-chart.service.ts b/src/main/webapp/app/overview/visualizations/exercise-scores-chart.service.ts index d92ca47740e8..e35422b48016 100644 --- a/src/main/webapp/app/overview/visualizations/exercise-scores-chart.service.ts +++ b/src/main/webapp/app/overview/visualizations/exercise-scores-chart.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import dayjs from 'dayjs/esm'; @@ -23,9 +23,10 @@ export class ExerciseScoresDTO { */ @Injectable({ providedIn: 'root' }) export class ExerciseScoresChartService { + private http = inject(HttpClient); + public resourceUrl = 'api'; - constructor(private http: HttpClient) {} /** * Get the course exercise performance statistics necessary for exercise-scores-chart.component.ts * @param courseId id of the course diff --git a/src/main/webapp/app/overview/visualizations/exercise-scores-chart/exercise-scores-chart.component.ts b/src/main/webapp/app/overview/visualizations/exercise-scores-chart/exercise-scores-chart.component.ts index 6d99a9962df0..01d5d8018854 100644 --- a/src/main/webapp/app/overview/visualizations/exercise-scores-chart/exercise-scores-chart.component.ts +++ b/src/main/webapp/app/overview/visualizations/exercise-scores-chart/exercise-scores-chart.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, Input, OnChanges } from '@angular/core'; +import { AfterViewInit, Component, Input, OnChanges, inject } from '@angular/core'; import { ExerciseScoresChartService, ExerciseScoresDTO } from 'app/overview/visualizations/exercise-scores-chart.service'; import { AlertService } from 'app/core/util/alert.service'; import { onError } from 'app/shared/util/global.utils'; @@ -7,13 +7,17 @@ import { HttpErrorResponse } from '@angular/common/http'; import { ActivatedRoute } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { cloneDeep, sortBy } from 'lodash-es'; -import { Color, ScaleType } from '@swimlane/ngx-charts'; +import { Color, LineChartModule, ScaleType } from '@swimlane/ngx-charts'; import { round } from 'app/shared/util/utils'; import { ExerciseType } from 'app/entities/exercise.model'; import { faFilter } from '@fortawesome/free-solid-svg-icons'; import { ChartExerciseTypeFilter } from 'app/shared/chart/chart-exercise-type-filter'; import { GraphColors } from 'app/entities/statistics.model'; import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbDropdown, NgbDropdownMenu, NgbDropdownToggle } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; type ChartSeries = { name: string; @@ -35,8 +39,16 @@ type SeriesDatapoint = { selector: 'jhi-exercise-scores-chart', templateUrl: './exercise-scores-chart.component.html', styleUrls: ['./exercise-scores-chart.component.scss'], + imports: [TranslateDirective, NgbDropdown, NgbDropdownToggle, FaIconComponent, NgbDropdownMenu, LineChartModule, ArtemisTranslatePipe], }) export class ExerciseScoresChartComponent implements AfterViewInit, OnChanges { + private navigationUtilService = inject(ArtemisNavigationUtilService); + private activatedRoute = inject(ActivatedRoute); + private alertService = inject(AlertService); + private exerciseScoresChartService = inject(ExerciseScoresChartService); + exerciseTypeFilter = inject(ChartExerciseTypeFilter); + private translateService = inject(TranslateService); + @Input() filteredExerciseIDs: number[]; courseId: number; @@ -69,14 +81,7 @@ export class ExerciseScoresChartComponent implements AfterViewInit, OnChanges { maximumScoreLabel: string; maxScale = 101; - constructor( - private navigationUtilService: ArtemisNavigationUtilService, - private activatedRoute: ActivatedRoute, - private alertService: AlertService, - private exerciseScoresChartService: ExerciseScoresChartService, - public exerciseTypeFilter: ChartExerciseTypeFilter, // used in html, therefore it must be public - private translateService: TranslateService, - ) { + constructor() { this.translateService.onLangChange.subscribe(() => { this.setTranslations(); }); diff --git a/src/main/webapp/app/shared/additional-feedback/additional-feedback.component.ts b/src/main/webapp/app/shared/additional-feedback/additional-feedback.component.ts index 2c6083340846..f1d9fee0f27b 100644 --- a/src/main/webapp/app/shared/additional-feedback/additional-feedback.component.ts +++ b/src/main/webapp/app/shared/additional-feedback/additional-feedback.component.ts @@ -1,4 +1,4 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { Feedback, buildFeedbackTextForReview } from 'app/entities/feedback.model'; import { getCourseFromExercise } from 'app/entities/exercise.model'; import { Course } from 'app/entities/course.model'; @@ -6,19 +6,24 @@ import { faCommentDots } from '@fortawesome/free-regular-svg-icons'; import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; import { LocaleConversionService } from 'app/shared/service/locale-conversion.service'; import { TranslateService } from '@ngx-translate/core'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from '../language/translate.directive'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-additional-feedback', templateUrl: './additional-feedback.component.html', styleUrls: ['./additional-feedback.component.scss'], + imports: [FaIconComponent, TranslateDirective, NgbTooltip, ArtemisTranslatePipe], }) export class AdditionalFeedbackComponent { - @Input() - feedback: Feedback[]; - @Input() - additional: boolean; - @Input() - course?: Course; + private translateService = inject(TranslateService); + private localeConversionService = inject(LocaleConversionService); + + @Input() feedback: Feedback[]; + @Input() additional: boolean; + @Input() course?: Course; // Icons faCommentDots = faCommentDots; @@ -28,11 +33,6 @@ export class AdditionalFeedbackComponent { readonly getCourseFromExercise = getCourseFromExercise; readonly buildFeedbackTextForReview = buildFeedbackTextForReview; - constructor( - private translateService: TranslateService, - private localeConversionService: LocaleConversionService, - ) {} - /** * Translates the points string based on the singularity of the given points. * In addition, the points are returned in a localized form. diff --git a/src/main/webapp/app/shared/alert/alert-overlay.component.ts b/src/main/webapp/app/shared/alert/alert-overlay.component.ts index c1a18cb51250..d9d8ac765959 100644 --- a/src/main/webapp/app/shared/alert/alert-overlay.component.ts +++ b/src/main/webapp/app/shared/alert/alert-overlay.component.ts @@ -1,7 +1,11 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { Alert, AlertService } from 'app/core/util/alert.service'; import { faTimes } from '@fortawesome/free-solid-svg-icons'; import { animate, group, style, transition, trigger } from '@angular/animations'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from '../language/translate.directive'; +import { NgClass, NgStyle } from '@angular/common'; +import { CloseCircleComponent } from '../close-circle/close-circle.component'; @Component({ selector: 'jhi-alert-overlay', @@ -44,11 +48,12 @@ import { animate, group, style, transition, trigger } from '@angular/animations' ]), ]), ], + imports: [FaIconComponent, TranslateDirective, NgClass, CloseCircleComponent, NgStyle], }) export class AlertOverlayComponent implements OnInit, OnDestroy { - alerts: Alert[] = []; + alertService = inject(AlertService); - constructor(public alertService: AlertService) {} + alerts: Alert[] = []; times = faTimes; diff --git a/src/main/webapp/app/shared/auth/has-any-authority.directive.ts b/src/main/webapp/app/shared/auth/has-any-authority.directive.ts index e0c1abfcd8cc..9d7eef8a8704 100644 --- a/src/main/webapp/app/shared/auth/has-any-authority.directive.ts +++ b/src/main/webapp/app/shared/auth/has-any-authority.directive.ts @@ -1,4 +1,4 @@ -import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; +import { Directive, Input, TemplateRef, ViewContainerRef, inject } from '@angular/core'; import { AccountService } from 'app/core/auth/account.service'; /** @@ -12,17 +12,13 @@ import { AccountService } from 'app/core/auth/account.service'; * ... * ``` */ -@Directive({ - selector: '[jhiHasAnyAuthority]', -}) +@Directive({ selector: '[jhiHasAnyAuthority]' }) export class HasAnyAuthorityDirective { - private authorities: string[]; + private accountService = inject(AccountService); + private templateRef = inject>(TemplateRef); + private viewContainerRef = inject(ViewContainerRef); - constructor( - private accountService: AccountService, - private templateRef: TemplateRef, - private viewContainerRef: ViewContainerRef, - ) {} + private authorities: string[]; @Input() set jhiHasAnyAuthority(value: string | string[]) { diff --git a/src/main/webapp/app/shared/breakpoints/layout.service.ts b/src/main/webapp/app/shared/breakpoints/layout.service.ts index 97ff7e71da29..461b674c05a5 100644 --- a/src/main/webapp/app/shared/breakpoints/layout.service.ts +++ b/src/main/webapp/app/shared/breakpoints/layout.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { BreakpointObserver } from '@angular/cdk/layout'; import { BreakpointsService } from './breakpoints.service'; import { map } from 'rxjs/operators'; @@ -8,12 +8,10 @@ import { Observable } from 'rxjs'; providedIn: 'root', }) export class LayoutService { - activeBreakpoints: string[] = []; + private breakpointObserver = inject(BreakpointObserver); + private breakpointService = inject(BreakpointsService); - constructor( - private breakpointObserver: BreakpointObserver, - private breakpointService: BreakpointsService, - ) {} + activeBreakpoints: string[] = []; subscribeToLayoutChanges(): Observable { return this.breakpointObserver.observe(this.breakpointService.getBreakpoints()).pipe(map((observeResponse) => this.parseBreakpointsResponse(observeResponse.breakpoints))); diff --git a/src/main/webapp/app/shared/category-selector/category-selector.component.ts b/src/main/webapp/app/shared/category-selector/category-selector.component.ts index 2c3e31b1e67f..f5e5bb76adcf 100644 --- a/src/main/webapp/app/shared/category-selector/category-selector.component.ts +++ b/src/main/webapp/app/shared/category-selector/category-selector.component.ts @@ -1,13 +1,18 @@ import { Component, ElementRef, EventEmitter, Input, OnChanges, Output, ViewChild, ViewEncapsulation } from '@angular/core'; import { ColorSelectorComponent } from 'app/shared/color-selector/color-selector.component'; import { ExerciseCategory } from 'app/entities/exercise-category.model'; -import { MatAutocompleteSelectedEvent, MatAutocompleteTrigger } from '@angular/material/autocomplete'; +import { MatAutocomplete, MatAutocompleteSelectedEvent, MatAutocompleteTrigger } from '@angular/material/autocomplete'; import { COMMA, ENTER, TAB } from '@angular/cdk/keycodes'; -import { FormControl } from '@angular/forms'; -import { MatChipInputEvent } from '@angular/material/chips'; +import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { MatChipGrid, MatChipInput, MatChipInputEvent, MatChipRemove, MatChipRow } from '@angular/material/chips'; import { Observable, map, startWith } from 'rxjs'; import { faTimes } from '@fortawesome/free-solid-svg-icons'; import { FaqCategory } from 'app/entities/faq-category.model'; +import { MatFormField } from '@angular/material/form-field'; +import { AsyncPipe, NgStyle } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { MatOption } from '@angular/material/core'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; const DEFAULT_COLORS = ['#6ae8ac', '#9dca53', '#94a11c', '#691b0b', '#ad5658', '#1b97ca', '#0d3cc2', '#0ab84f']; @@ -16,6 +21,23 @@ const DEFAULT_COLORS = ['#6ae8ac', '#9dca53', '#94a11c', '#691b0b', '#ad5658', ' templateUrl: './category-selector.component.html', styleUrls: ['./category-selector.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [ + MatFormField, + MatChipGrid, + MatChipRow, + NgStyle, + MatChipRemove, + FaIconComponent, + FormsModule, + MatAutocompleteTrigger, + MatChipInput, + ReactiveFormsModule, + MatAutocomplete, + MatOption, + ColorSelectorComponent, + AsyncPipe, + ArtemisTranslatePipe, + ], }) export class CategorySelectorComponent implements OnChanges { protected readonly faTimes = faTimes; diff --git a/src/main/webapp/app/shared/category-selector/category-selector.module.ts b/src/main/webapp/app/shared/category-selector/category-selector.module.ts index 9b9ed1a5f0e5..a114b2c98792 100644 --- a/src/main/webapp/app/shared/category-selector/category-selector.module.ts +++ b/src/main/webapp/app/shared/category-selector/category-selector.module.ts @@ -10,8 +10,17 @@ import { MatSelectModule } from '@angular/material/select'; import { MatFormFieldModule } from '@angular/material/form-field'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisColorSelectorModule, ReactiveFormsModule, FormsModule, MatChipsModule, MatAutocompleteModule, MatSelectModule, MatFormFieldModule], - declarations: [CategorySelectorComponent], + imports: [ + ArtemisSharedModule, + ArtemisColorSelectorModule, + ReactiveFormsModule, + FormsModule, + MatChipsModule, + MatAutocompleteModule, + MatSelectModule, + MatFormFieldModule, + CategorySelectorComponent, + ], exports: [CategorySelectorComponent], }) export class ArtemisCategorySelectorModule {} diff --git a/src/main/webapp/app/shared/chart/artemis-charts.module.ts b/src/main/webapp/app/shared/chart/artemis-charts.module.ts index f95d838f1b04..1072378c1b74 100644 --- a/src/main/webapp/app/shared/chart/artemis-charts.module.ts +++ b/src/main/webapp/app/shared/chart/artemis-charts.module.ts @@ -8,8 +8,17 @@ import { RouterModule } from '@angular/router'; import { BarChartModule, LineChartModule, PieChartModule } from '@swimlane/ngx-charts'; @NgModule({ - imports: [ArtemisSharedModule, RouterModule, BarChartModule, LineChartModule, PieChartModule], - declarations: [DoughnutChartComponent, StatisticsAverageScoreGraphComponent, StatisticsGraphComponent, StatisticsScoreDistributionGraphComponent], + imports: [ + ArtemisSharedModule, + RouterModule, + BarChartModule, + LineChartModule, + PieChartModule, + DoughnutChartComponent, + StatisticsAverageScoreGraphComponent, + StatisticsGraphComponent, + StatisticsScoreDistributionGraphComponent, + ], exports: [DoughnutChartComponent, StatisticsAverageScoreGraphComponent, StatisticsGraphComponent, StatisticsScoreDistributionGraphComponent], }) export class ArtemisChartsModule {} diff --git a/src/main/webapp/app/shared/circular-progress-bar/circular-progress-bar.component.ts b/src/main/webapp/app/shared/circular-progress-bar/circular-progress-bar.component.ts index f3669b92065b..6b7a547f41e1 100644 --- a/src/main/webapp/app/shared/circular-progress-bar/circular-progress-bar.component.ts +++ b/src/main/webapp/app/shared/circular-progress-bar/circular-progress-bar.component.ts @@ -15,8 +15,6 @@ export class CircularProgressBarComponent implements OnChanges { progressText = 'Completed'; circleColor = '#000000'; - constructor() {} - ngOnChanges() { if (this.progressInPercent > 100) { this.progressUsedForColorCalculation = 100; diff --git a/src/main/webapp/app/shared/color-selector/color-selector.component.ts b/src/main/webapp/app/shared/color-selector/color-selector.component.ts index 91061dc28f04..ce81d215aa95 100644 --- a/src/main/webapp/app/shared/color-selector/color-selector.component.ts +++ b/src/main/webapp/app/shared/color-selector/color-selector.component.ts @@ -1,5 +1,6 @@ -import { Component, ElementRef, EventEmitter, Input, OnInit, Output, Renderer2 } from '@angular/core'; +import { Component, ElementRef, EventEmitter, Input, OnInit, Output, Renderer2, inject } from '@angular/core'; import { ARTEMIS_DEFAULT_COLOR } from 'app/app.constants'; +import { NgStyle } from '@angular/common'; export interface Coordinates { left: number; @@ -29,19 +30,18 @@ const DEFAULT_COLORS = [ selector: 'jhi-color-selector', templateUrl: './color-selector.component.html', styleUrls: ['./color-selector.scss'], + imports: [NgStyle], }) export class ColorSelectorComponent implements OnInit { + private elementRef = inject(ElementRef); + private renderer = inject(Renderer2); + colorSelectorPosition: Coordinates; showColorSelector = false; height = 220; @Input() tagColors: string[] = DEFAULT_COLORS; @Output() selectedColor = new EventEmitter(); - constructor( - private elementRef: ElementRef, - private renderer: Renderer2, - ) {} - /** * set default position on init */ diff --git a/src/main/webapp/app/shared/color-selector/color-selector.module.ts b/src/main/webapp/app/shared/color-selector/color-selector.module.ts index 9366e250aa7a..819ffbc1df2b 100644 --- a/src/main/webapp/app/shared/color-selector/color-selector.module.ts +++ b/src/main/webapp/app/shared/color-selector/color-selector.module.ts @@ -4,8 +4,7 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ColorSelectorComponent } from './color-selector.component'; @NgModule({ - imports: [ArtemisSharedModule], - declarations: [ColorSelectorComponent], + imports: [ArtemisSharedModule, ColorSelectorComponent], exports: [ColorSelectorComponent], }) export class ArtemisColorSelectorModule {} diff --git a/src/main/webapp/app/shared/competency-selection/competency-selection.component.ts b/src/main/webapp/app/shared/competency-selection/competency-selection.component.ts index 41f2dcf0e67a..c448f38ca8a2 100644 --- a/src/main/webapp/app/shared/competency-selection/competency-selection.component.ts +++ b/src/main/webapp/app/shared/competency-selection/competency-selection.component.ts @@ -1,5 +1,5 @@ -import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, forwardRef } from '@angular/core'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, forwardRef, inject } from '@angular/core'; +import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; import { CompetencyLearningObjectLink, @@ -15,6 +15,10 @@ import { ActivatedRoute } from '@angular/router'; import { CourseStorageService } from 'app/course/manage/course-storage.service'; import { finalize } from 'rxjs'; import { CourseCompetencyService } from 'app/course/competencies/course-competency.service'; +import { FaIconComponent, FaStackComponent, FaStackItemSizeDirective } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from '../language/translate.directive'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-competency-selection', @@ -27,8 +31,14 @@ import { CourseCompetencyService } from 'app/course/competencies/course-competen useExisting: forwardRef(() => CompetencySelectionComponent), }, ], + imports: [FaStackComponent, NgbTooltip, FaIconComponent, FaStackItemSizeDirective, FormsModule, TranslateDirective, ArtemisTranslatePipe], }) export class CompetencySelectionComponent implements OnInit, ControlValueAccessor { + private route = inject(ActivatedRoute); + private courseStorageService = inject(CourseStorageService); + private courseCompetencyService = inject(CourseCompetencyService); + private changeDetector = inject(ChangeDetectorRef); + @Input() labelName: string; @Input() labelTooltip: string; @@ -53,14 +63,8 @@ export class CompetencySelectionComponent implements OnInit, ControlValueAccesso protected readonly MEDIUM_COMPETENCY_LINK_WEIGHT = MEDIUM_COMPETENCY_LINK_WEIGHT; protected readonly LOW_COMPETENCY_LINK_WEIGHT = LOW_COMPETENCY_LINK_WEIGHT; protected readonly LOW_COMPETENCY_LINK_WEIGHT_CUT_OFF = LOW_COMPETENCY_LINK_WEIGHT_CUT_OFF; // halfway between low and medium - protected readonly MEDIUM_COMPETENCY_LINK_WEIGHT_CUT_OFF = MEDIUM_COMPETENCY_LINK_WEIGHT_CUT_OFF; // halfway between medium and high - - constructor( - private route: ActivatedRoute, - private courseStorageService: CourseStorageService, - private courseCompetencyService: CourseCompetencyService, - private changeDetector: ChangeDetectorRef, - ) {} + protected readonly MEDIUM_COMPETENCY_LINK_WEIGHT_CUT_OFF = MEDIUM_COMPETENCY_LINK_WEIGHT_CUT_OFF; + // halfway between medium and high ngOnInit(): void { const courseId = Number(this.route.snapshot.paramMap.get('courseId')); diff --git a/src/main/webapp/app/shared/components/button.component.ts b/src/main/webapp/app/shared/components/button.component.ts index 5f488b280767..45587c1dbfa2 100644 --- a/src/main/webapp/app/shared/components/button.component.ts +++ b/src/main/webapp/app/shared/components/button.component.ts @@ -2,6 +2,12 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; +import { NgClass } from '@angular/common'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FeatureToggleDirective } from '../feature-toggle/feature-toggle.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from '../language/translate.directive'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; /** * enum for button types @@ -46,6 +52,7 @@ export enum TooltipPlacement { @Component({ selector: 'jhi-button', templateUrl: './button.component.html', + imports: [NgClass, NgbTooltip, FeatureToggleDirective, FaIconComponent, TranslateDirective, ArtemisTranslatePipe], }) export class ButtonComponent { @Input() btnType = ButtonType.PRIMARY; diff --git a/src/main/webapp/app/shared/components/checklist-check/checklist-check.component.ts b/src/main/webapp/app/shared/components/checklist-check/checklist-check.component.ts index 3718e0f73adf..84b458270530 100644 --- a/src/main/webapp/app/shared/components/checklist-check/checklist-check.component.ts +++ b/src/main/webapp/app/shared/components/checklist-check/checklist-check.component.ts @@ -1,10 +1,12 @@ import { Component, Input } from '@angular/core'; import { SizeProp } from '@fortawesome/fontawesome-svg-core'; import { faCheckCircle, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; @Component({ selector: 'jhi-checklist-check', templateUrl: './checklist-check.component.html', + imports: [FaIconComponent], }) export class ChecklistCheckComponent { protected readonly faTimes = faTimes; diff --git a/src/main/webapp/app/shared/components/code-button/code-button.component.ts b/src/main/webapp/app/shared/components/code-button/code-button.component.ts index 36046020db1b..15437f8ae64e 100644 --- a/src/main/webapp/app/shared/components/code-button/code-button.component.ts +++ b/src/main/webapp/app/shared/components/code-button/code-button.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnChanges, OnInit } from '@angular/core'; +import { Component, Input, OnChanges, OnInit, inject } from '@angular/core'; import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming/programming-exercise.model'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; import { ExternalCloningService } from 'app/exercises/programming/shared/service/external-cloning.service'; @@ -18,13 +18,49 @@ import { IdeSettingsService } from 'app/shared/user-settings/ide-preferences/ide import { Ide } from 'app/shared/user-settings/ide-preferences/ide.model'; import { SshUserSettingsService } from 'app/shared/user-settings/ssh-settings/ssh-user-settings.service'; import { UserSshPublicKey } from 'app/entities/programming/user-ssh-public-key.model'; +import { ExerciseActionButtonComponent } from '../exercise-action-button.component'; +import { FeatureToggleDirective } from '../../feature-toggle/feature-toggle.directive'; +import { NgbDropdown, NgbDropdownMenu, NgbDropdownToggle, NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from '../../language/translate.directive'; +import { NgClass } from '@angular/common'; +import { CdkCopyToClipboard } from '@angular/cdk/clipboard'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { RouterLink } from '@angular/router'; +import { HelpIconComponent } from '../help-icon.component'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; +import { SafeUrlPipe } from 'app/shared/pipes/safe-url.pipe'; @Component({ selector: 'jhi-code-button', templateUrl: './code-button.component.html', styleUrls: ['./code-button.component.scss'], + imports: [ + ExerciseActionButtonComponent, + FeatureToggleDirective, + NgbPopover, + TranslateDirective, + NgbDropdown, + NgbDropdownToggle, + NgbDropdownMenu, + NgClass, + CdkCopyToClipboard, + FaIconComponent, + RouterLink, + HelpIconComponent, + ArtemisTranslatePipe, + SafeUrlPipe, + ], }) export class CodeButtonComponent implements OnInit, OnChanges { + private translateService = inject(TranslateService); + private externalCloningService = inject(ExternalCloningService); + private sshUserSettingsService = inject(SshUserSettingsService); + private accountService = inject(AccountService); + private profileService = inject(ProfileService); + private localStorage = inject(LocalStorageService); + private participationService = inject(ParticipationService); + private ideSettingsService = inject(IdeSettingsService); + readonly FeatureToggle = FeatureToggle; readonly ProgrammingLanguage = ProgrammingLanguage; @@ -76,17 +112,6 @@ export class CodeButtonComponent implements OnInit, OnChanges { readonly faExternalLink = faExternalLink; ideName: string; - constructor( - private translateService: TranslateService, - private externalCloningService: ExternalCloningService, - private sshUserSettingsService: SshUserSettingsService, - private accountService: AccountService, - private profileService: ProfileService, - private localStorage: LocalStorageService, - private participationService: ParticipationService, - private ideSettingsService: IdeSettingsService, - ) {} - async ngOnInit() { const user = await this.accountService.identity(); if (!user) { diff --git a/src/main/webapp/app/shared/components/confirm-autofocus-button.component.ts b/src/main/webapp/app/shared/components/confirm-autofocus-button.component.ts index eafa2aedcb26..3de259b12f99 100644 --- a/src/main/webapp/app/shared/components/confirm-autofocus-button.component.ts +++ b/src/main/webapp/app/shared/components/confirm-autofocus-button.component.ts @@ -1,14 +1,18 @@ -import { Component, EventEmitter, Input, Output, TemplateRef, ViewChild } from '@angular/core'; +import { Component, EventEmitter, Input, Output, TemplateRef, ViewChild, inject } from '@angular/core'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { htmlForMarkdown } from 'app/shared/util/markdown.conversion.util'; import { ConfirmAutofocusModalComponent } from 'app/shared/components/confirm-autofocus-modal.component'; +import { ButtonComponent } from './button.component'; @Component({ selector: 'jhi-confirm-button', templateUrl: './confirm-autofocus-button.component.html', + imports: [ButtonComponent], }) export class ConfirmAutofocusButtonComponent { + private modalService = inject(NgbModal); + @Input() icon: IconProp; @Input() title: string; @Input() tooltip: string; @@ -25,8 +29,6 @@ export class ConfirmAutofocusButtonComponent { @ViewChild('content') content?: TemplateRef; - constructor(private modalService: NgbModal) {} - /** * open confirmation modal with text and title */ diff --git a/src/main/webapp/app/shared/components/confirm-autofocus-modal.component.ts b/src/main/webapp/app/shared/components/confirm-autofocus-modal.component.ts index 567c0672ff16..53d74b778076 100644 --- a/src/main/webapp/app/shared/components/confirm-autofocus-modal.component.ts +++ b/src/main/webapp/app/shared/components/confirm-autofocus-modal.component.ts @@ -1,17 +1,21 @@ -import { Component, Input, TemplateRef } from '@angular/core'; +import { Component, Input, TemplateRef, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { NgTemplateOutlet } from '@angular/common'; +import { TranslateDirective } from '../language/translate.directive'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-confirm-modal', templateUrl: './confirm-autofocus-modal.component.html', + imports: [NgTemplateOutlet, TranslateDirective, ArtemisTranslatePipe], }) export class ConfirmAutofocusModalComponent { + modal = inject(NgbActiveModal); + @Input() title: string; @Input() titleTranslationParams?: Record; @Input() text: string; @Input() translateText: boolean; @Input() textIsMarkdown: boolean; @Input() contentRef?: TemplateRef; - - constructor(public modal: NgbActiveModal) {} } diff --git a/src/main/webapp/app/shared/components/copy-icon-button/copy-icon-button.component.ts b/src/main/webapp/app/shared/components/copy-icon-button/copy-icon-button.component.ts index 13259f59b364..e15ef10bdaa4 100644 --- a/src/main/webapp/app/shared/components/copy-icon-button/copy-icon-button.component.ts +++ b/src/main/webapp/app/shared/components/copy-icon-button/copy-icon-button.component.ts @@ -1,9 +1,14 @@ import { Component, Input } from '@angular/core'; import { faCopy } from '@fortawesome/free-regular-svg-icons'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { CdkCopyToClipboard } from '@angular/cdk/clipboard'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-copy-icon-button', templateUrl: './copy-icon-button.component.html', + imports: [NgbTooltip, CdkCopyToClipboard, FaIconComponent, ArtemisTranslatePipe], }) export class CopyIconButtonComponent { @Input() copyText: string; diff --git a/src/main/webapp/app/shared/components/course-exam-archive-button/course-exam-archive-button.component.ts b/src/main/webapp/app/shared/components/course-exam-archive-button/course-exam-archive-button.component.ts index a26b939ed089..46eb02356885 100644 --- a/src/main/webapp/app/shared/components/course-exam-archive-button/course-exam-archive-button.component.ts +++ b/src/main/webapp/app/shared/components/course-exam-archive-button/course-exam-archive-button.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit, TemplateRef, ViewChild, inject } from '@angular/core'; import { AlertService } from 'app/core/util/alert.service'; import { CourseManagementService } from 'app/course/manage/course-management.service'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; @@ -15,6 +15,10 @@ import { Subject } from 'rxjs'; import { AccountService } from 'app/core/auth/account.service'; import { faArchive, faCircleNotch, faDownload, faEraser } from '@fortawesome/free-solid-svg-icons'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; +import { TranslateDirective } from '../../language/translate.directive'; +import { FeatureToggleDirective } from '../../feature-toggle/feature-toggle.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { DeleteButtonDirective } from '../../delete-dialog/delete-button.directive'; export type CourseExamArchiveState = { exportState: 'COMPLETED' | 'RUNNING' | 'COMPLETED_WITH_WARNINGS' | 'COMPLETED_WITH_ERRORS'; @@ -27,8 +31,17 @@ export type CourseExamArchiveState = { templateUrl: './course-exam-archive-button.component.html', styleUrls: ['./course-exam-archive-button.component.scss'], styles: [':host {display: contents}'], + imports: [TranslateDirective, FeatureToggleDirective, FaIconComponent, DeleteButtonDirective], }) export class CourseExamArchiveButtonComponent implements OnInit, OnDestroy { + private courseService = inject(CourseManagementService); + private examService = inject(ExamManagementService); + private alertService = inject(AlertService); + private websocketService = inject(JhiWebsocketService); + private translateService = inject(TranslateService); + private modalService = inject(NgbModal); + private accountService = inject(AccountService); + ButtonSize = ButtonSize; ActionType = ActionType; readonly FeatureToggle = FeatureToggle; @@ -62,16 +75,6 @@ export class CourseExamArchiveButtonComponent implements OnInit, OnDestroy { faEraser = faEraser; faArchive = faArchive; - constructor( - private courseService: CourseManagementService, - private examService: ExamManagementService, - private alertService: AlertService, - private websocketService: JhiWebsocketService, - private translateService: TranslateService, - private modalService: NgbModal, - private accountService: AccountService, - ) {} - ngOnInit() { if (!this.course && !this.exam) { // Component isn't initialized diff --git a/src/main/webapp/app/shared/components/documentation-button/documentation-button.component.ts b/src/main/webapp/app/shared/components/documentation-button/documentation-button.component.ts index 7724361d798e..3b22a87939d8 100644 --- a/src/main/webapp/app/shared/components/documentation-button/documentation-button.component.ts +++ b/src/main/webapp/app/shared/components/documentation-button/documentation-button.component.ts @@ -1,6 +1,8 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, inject } from '@angular/core'; import { faCircleInfo } from '@fortawesome/free-solid-svg-icons'; import { TranslateService } from '@ngx-translate/core'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; // The routes here are used to build the link to the documentation. // Therefore, it's important that they exactly match the url to the subpage of the documentation. @@ -39,16 +41,17 @@ export type DocumentationType = keyof typeof DocumentationLinks; `, + imports: [FaIconComponent, NgbTooltip], }) export class DocumentationButtonComponent { + private translateService = inject(TranslateService); + readonly BASE_URL = 'https://docs.artemis.cit.tum.de/user/'; readonly faCircleInfo = faCircleInfo; readonly DocumentationLinks = DocumentationLinks; @Input() type: DocumentationType; - constructor(private translateService: TranslateService) {} - getTooltipForType() { const typeKey = 'artemisApp.documentationLinks.' + this.type.toLowerCase(); return this.translateService.instant('artemisApp.documentationLinks.prefix') + this.translateService.instant(typeKey); diff --git a/src/main/webapp/app/shared/components/documentation-link/documentation-link.component.ts b/src/main/webapp/app/shared/components/documentation-link/documentation-link.component.ts index 86f5d19aafb6..8c483d617500 100644 --- a/src/main/webapp/app/shared/components/documentation-link/documentation-link.component.ts +++ b/src/main/webapp/app/shared/components/documentation-link/documentation-link.component.ts @@ -12,7 +12,6 @@ export type DocumentationType = keyof typeof DocumentationLinks; @Component({ selector: 'jhi-documentation-link', - standalone: true, templateUrl: './documentation-link.component.html', imports: [TranslateDirective], }) diff --git a/src/main/webapp/app/shared/components/exercise-action-button.component.ts b/src/main/webapp/app/shared/components/exercise-action-button.component.ts index a67d8a354d60..37cc076ab7da 100644 --- a/src/main/webapp/app/shared/components/exercise-action-button.component.ts +++ b/src/main/webapp/app/shared/components/exercise-action-button.component.ts @@ -1,12 +1,14 @@ import { Component, HostBinding, Input } from '@angular/core'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { faCircleNotch } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgClass } from '@angular/common'; @Component({ - /* eslint-disable-next-line @angular-eslint/component-selector */ selector: 'button[jhi-exercise-action-button]', templateUrl: './exercise-action-button.component.html', styleUrls: ['../../overview/course-overview.scss'], + imports: [FaIconComponent, NgClass], }) export class ExerciseActionButtonComponent { @Input() buttonIcon: IconProp; @@ -14,6 +16,7 @@ export class ExerciseActionButtonComponent { @Input() hideLabelMobile = true; @Input() overwriteDisabled = false; @Input() buttonLoading = false; + @HostBinding('class.btn-outline-primary') @Input() outlined = false; @HostBinding('class.btn-sm') @Input() smallButton = false; @HostBinding('class.btn') isButton = true; diff --git a/src/main/webapp/app/shared/components/help-icon.component.ts b/src/main/webapp/app/shared/components/help-icon.component.ts index b478c5f093aa..daf6956074e2 100644 --- a/src/main/webapp/app/shared/components/help-icon.component.ts +++ b/src/main/webapp/app/shared/components/help-icon.component.ts @@ -1,9 +1,13 @@ import { Component, input } from '@angular/core'; import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-help-icon', template: ` `, + imports: [FaIconComponent, NgbTooltip, ArtemisTranslatePipe], }) export class HelpIconComponent { protected readonly faQuestionCircle = faQuestionCircle; diff --git a/src/main/webapp/app/shared/components/not-released-tag.component.ts b/src/main/webapp/app/shared/components/not-released-tag.component.ts index 9fdb0a54a3a7..c91bcef2c286 100644 --- a/src/main/webapp/app/shared/components/not-released-tag.component.ts +++ b/src/main/webapp/app/shared/components/not-released-tag.component.ts @@ -1,11 +1,16 @@ import { Component, Input } from '@angular/core'; import dayjs from 'dayjs/esm'; import { Exercise } from 'app/entities/exercise.model'; +import { TranslateDirective } from '../language/translate.directive'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-not-released-tag', templateUrl: './not-released-tag.component.html', styleUrls: ['./not-released-tag.component.scss'], + imports: [TranslateDirective, NgbTooltip, ArtemisDatePipe, ArtemisTranslatePipe], }) export class NotReleasedTagComponent { @Input() public exercise: Exercise; diff --git a/src/main/webapp/app/shared/components/open-code-editor-button/open-code-editor-button.component.ts b/src/main/webapp/app/shared/components/open-code-editor-button/open-code-editor-button.component.ts index 10b32d55360e..93b6d33f0f3c 100644 --- a/src/main/webapp/app/shared/components/open-code-editor-button/open-code-editor-button.component.ts +++ b/src/main/webapp/app/shared/components/open-code-editor-button/open-code-editor-button.component.ts @@ -1,15 +1,24 @@ -import { Component, Input, OnChanges } from '@angular/core'; +import { Component, Input, OnChanges, inject } from '@angular/core'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; import { faFolderOpen } from '@fortawesome/free-solid-svg-icons'; import { ProgrammingExerciseStudentParticipation } from 'app/entities/participation/programming-exercise-student-participation.model'; import { ParticipationService } from 'app/exercises/shared/participation/participation.service'; import { Exercise } from 'app/entities/exercise.model'; +import { ExerciseActionButtonComponent } from '../exercise-action-button.component'; +import { FeatureToggleDirective } from '../../feature-toggle/feature-toggle.directive'; +import { RouterLink } from '@angular/router'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from '../../language/translate.directive'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-open-code-editor-button', templateUrl: './open-code-editor-button.component.html', + imports: [ExerciseActionButtonComponent, FeatureToggleDirective, RouterLink, NgbPopover, TranslateDirective, ArtemisTranslatePipe], }) export class OpenCodeEditorButtonComponent implements OnChanges { + private participationService = inject(ParticipationService); + readonly FeatureToggle = FeatureToggle; @Input() @@ -32,8 +41,6 @@ export class OpenCodeEditorButtonComponent implements OnChanges { // Icons faFolderOpen = faFolderOpen; - constructor(private participationService: ParticipationService) {} - ngOnChanges() { this.courseAndExerciseNavigationUrl = this.courseAndExerciseNavigationUrlSegment.reduce((acc, segment) => `${acc}/${segment}`); const shouldPreferPractice = this.participationService.shouldPreferPractice(this.exercise); diff --git a/src/main/webapp/app/shared/components/reset-repo-button/reset-repo-button.component.ts b/src/main/webapp/app/shared/components/reset-repo-button/reset-repo-button.component.ts index 07f7b5f7ca94..d512fac61c0e 100644 --- a/src/main/webapp/app/shared/components/reset-repo-button/reset-repo-button.component.ts +++ b/src/main/webapp/app/shared/components/reset-repo-button/reset-repo-button.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; import { faBackward } from '@fortawesome/free-solid-svg-icons'; import { ParticipationService } from 'app/exercises/shared/participation/participation.service'; @@ -10,13 +10,25 @@ import { getExerciseDueDate } from 'app/exercises/shared/exercise/exercise.utils import { finalize } from 'rxjs/operators'; import { AlertService } from 'app/core/util/alert.service'; import dayjs from 'dayjs/esm'; +import { ExerciseActionButtonComponent } from '../exercise-action-button.component'; +import { FeatureToggleDirective } from '../../feature-toggle/feature-toggle.directive'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from '../../language/translate.directive'; +import { ConfirmEntityNameComponent } from '../../confirm-entity-name/confirm-entity-name.component'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-reset-repo-button', templateUrl: './reset-repo-button.component.html', styleUrls: ['./reset-repo-button.component.scss'], + imports: [ExerciseActionButtonComponent, FeatureToggleDirective, NgbPopover, FormsModule, TranslateDirective, ConfirmEntityNameComponent, ArtemisTranslatePipe], }) export class ResetRepoButtonComponent implements OnInit { + private participationService = inject(ParticipationService); + private programmingExerciseParticipationService = inject(ProgrammingExerciseParticipationService); + private alertService = inject(AlertService); + readonly FeatureToggle = FeatureToggle; readonly INITIALIZED = InitializationState.INITIALIZED; @@ -31,12 +43,6 @@ export class ResetRepoButtonComponent implements OnInit { readonly faBackward = faBackward; - constructor( - private participationService: ParticipationService, - private programmingExerciseParticipationService: ProgrammingExerciseParticipationService, - private alertService: AlertService, - ) {} - ngOnInit() { this.gradedParticipation = this.participationService.getSpecificStudentParticipation(this.participations, false); this.practiceParticipation = this.participationService.getSpecificStudentParticipation(this.participations, true); diff --git a/src/main/webapp/app/shared/components/shared-component.module.ts b/src/main/webapp/app/shared/components/shared-component.module.ts index 090ebcf99f3d..348ce82ef2b3 100644 --- a/src/main/webapp/app/shared/components/shared-component.module.ts +++ b/src/main/webapp/app/shared/components/shared-component.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; import { ChecklistCheckComponent } from 'app/shared/components/checklist-check/checklist-check.component'; import { ArtemisSharedModule } from 'app/shared/shared.module'; -import { FeatureToggleModule } from 'app/shared/feature-toggle/feature-toggle.module'; + import { ConfirmAutofocusModalComponent } from 'app/shared/components/confirm-autofocus-modal.component'; import { HelpIconComponent } from 'app/shared/components/help-icon.component'; import { ButtonComponent } from 'app/shared/components/button.component'; @@ -24,8 +24,9 @@ import { ExerciseImportWrapperComponent } from 'app/exercises/shared/import/exer import { ConfirmAutofocusButtonComponent } from 'app/shared/components/confirm-autofocus-button.component'; @NgModule({ - imports: [ArtemisSharedModule, FeatureToggleModule, ClipboardModule], - declarations: [ + imports: [ + ArtemisSharedModule, + ClipboardModule, ButtonComponent, HelpIconComponent, ConfirmAutofocusButtonComponent, diff --git a/src/main/webapp/app/shared/components/start-practice-mode-button/start-practice-mode-button.component.ts b/src/main/webapp/app/shared/components/start-practice-mode-button/start-practice-mode-button.component.ts index 2601765baf68..1ec65a0fedee 100644 --- a/src/main/webapp/app/shared/components/start-practice-mode-button/start-practice-mode-button.component.ts +++ b/src/main/webapp/app/shared/components/start-practice-mode-button/start-practice-mode-button.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; import { finalize } from 'rxjs/operators'; import { faRedo } from '@fortawesome/free-solid-svg-icons'; @@ -9,21 +9,28 @@ import { AlertService } from 'app/core/util/alert.service'; import { StudentParticipation } from 'app/entities/participation/student-participation.model'; import { ParticipationService } from 'app/exercises/shared/participation/participation.service'; import { InitializationState } from 'app/entities/participation/participation.model'; +import { ExerciseActionButtonComponent } from '../exercise-action-button.component'; +import { FeatureToggleDirective } from '../../feature-toggle/feature-toggle.directive'; +import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from '../../language/translate.directive'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-start-practice-mode-button', templateUrl: './start-practice-mode-button.component.html', styleUrls: ['./start-practice-mode-button.component.scss'], + imports: [ExerciseActionButtonComponent, FeatureToggleDirective, NgbPopover, TranslateDirective, ArtemisTranslatePipe], }) export class StartPracticeModeButtonComponent implements OnInit { + private courseExerciseService = inject(CourseExerciseService); + private alertService = inject(AlertService); + private participationService = inject(ParticipationService); + readonly FeatureToggle = FeatureToggle; - @Input() - smallButtons: boolean; - @Input() - exercise: Exercise; - @Output() - practiceModeStarted = new EventEmitter(); + @Input() smallButtons: boolean; + @Input() exercise: Exercise; + @Output() practiceModeStarted = new EventEmitter(); startingPracticeMode = false; gradedStudentParticipation?: StudentParticipation; @@ -31,12 +38,6 @@ export class StartPracticeModeButtonComponent implements OnInit { // Icons faRedo = faRedo; - constructor( - private courseExerciseService: CourseExerciseService, - private alertService: AlertService, - private participationService: ParticipationService, - ) {} - ngOnInit() { this.gradedStudentParticipation = this.participationService.getSpecificStudentParticipation(this.exercise.studentParticipations ?? [], false); } diff --git a/src/main/webapp/app/shared/confirm-entity-name/confirm-entity-name.component.ts b/src/main/webapp/app/shared/confirm-entity-name/confirm-entity-name.component.ts index deaad28cc270..ab3606332f75 100644 --- a/src/main/webapp/app/shared/confirm-entity-name/confirm-entity-name.component.ts +++ b/src/main/webapp/app/shared/confirm-entity-name/confirm-entity-name.component.ts @@ -1,6 +1,19 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; -import { ControlValueAccessor, FormBuilder, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, ValidationErrors, Validator, Validators } from '@angular/forms'; +import { Component, Input, OnDestroy, OnInit, inject } from '@angular/core'; +import { + ControlValueAccessor, + FormBuilder, + FormControl, + FormsModule, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + ReactiveFormsModule, + ValidationErrors, + Validator, + Validators, +} from '@angular/forms'; import { Subscription } from 'rxjs'; +import { NgClass } from '@angular/common'; +import { TranslateDirective } from '../language/translate.directive'; @Component({ selector: 'jhi-confirm-entity-name', @@ -18,8 +31,11 @@ import { Subscription } from 'rxjs'; useExisting: ConfirmEntityNameComponent, }, ], + imports: [NgClass, TranslateDirective, FormsModule, ReactiveFormsModule], }) export class ConfirmEntityNameComponent implements OnInit, OnDestroy, ControlValueAccessor, Validator { + private fb = inject(FormBuilder); + @Input() warningTextColor: string; @Input() confirmationText: string; @@ -35,8 +51,6 @@ export class ConfirmEntityNameComponent implements OnInit, OnDestroy, ControlVal control: FormControl; - constructor(private fb: FormBuilder) {} - onTouched = () => {}; private currentEntityName: string; diff --git a/src/main/webapp/app/shared/confirm-icon/confirm-icon.component.ts b/src/main/webapp/app/shared/confirm-icon/confirm-icon.component.ts index 99c7cff72c06..c49207839371 100644 --- a/src/main/webapp/app/shared/confirm-icon/confirm-icon.component.ts +++ b/src/main/webapp/app/shared/confirm-icon/confirm-icon.component.ts @@ -1,10 +1,14 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { IconProp, SizeProp } from '@fortawesome/fontawesome-svg-core'; import { faCheck, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { NgClass } from '@angular/common'; @Component({ selector: 'jhi-confirm-icon', templateUrl: './confirm-icon.component.html', + imports: [FaIconComponent, NgbTooltip, NgClass], }) export class ConfirmIconComponent { @Input() initialIcon = faTrash; diff --git a/src/main/webapp/app/shared/confirm-icon/confirm-icon.module.ts b/src/main/webapp/app/shared/confirm-icon/confirm-icon.module.ts index be7452db9232..eca910d538ca 100644 --- a/src/main/webapp/app/shared/confirm-icon/confirm-icon.module.ts +++ b/src/main/webapp/app/shared/confirm-icon/confirm-icon.module.ts @@ -4,8 +4,7 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ConfirmIconComponent } from 'app/shared/confirm-icon/confirm-icon.component'; @NgModule({ - imports: [ArtemisSharedModule], - declarations: [ConfirmIconComponent], + imports: [ArtemisSharedModule, ConfirmIconComponent], exports: [ConfirmIconComponent], }) export class ArtemisConfirmIconModule {} diff --git a/src/main/webapp/app/shared/connection-status/connection-status.component.ts b/src/main/webapp/app/shared/connection-status/connection-status.component.ts index 315cbfcb3254..b29faab0f34a 100644 --- a/src/main/webapp/app/shared/connection-status/connection-status.component.ts +++ b/src/main/webapp/app/shared/connection-status/connection-status.component.ts @@ -1,14 +1,20 @@ -import { Component, ContentChild, ElementRef, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, ContentChild, ElementRef, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { faCircle, faExclamation, faTowerBroadcast } from '@fortawesome/free-solid-svg-icons'; import { Subscription } from 'rxjs'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; +import { NgClass } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from '../language/translate.directive'; @Component({ selector: 'jhi-connection-status', templateUrl: './connection-status.component.html', styleUrls: ['./connection-status.component.scss'], + imports: [NgClass, FaIconComponent, TranslateDirective], }) export class JhiConnectionStatusComponent implements OnInit, OnDestroy { + private websocketService = inject(JhiWebsocketService); + @ContentChild('innerContent', { static: false }) innerContent: ElementRef; @Input() isExamMode = false; disconnected = true; @@ -19,8 +25,6 @@ export class JhiConnectionStatusComponent implements OnInit, OnDestroy { readonly faTowerBroadcast = faTowerBroadcast; readonly faExclamation = faExclamation; - constructor(private websocketService: JhiWebsocketService) {} - ngOnInit() { // listen to connect / disconnect events this.websocketStatusSubscription = this.websocketService.connectionState.subscribe((status) => { diff --git a/src/main/webapp/app/shared/connection-warning/connection-warning.component.ts b/src/main/webapp/app/shared/connection-warning/connection-warning.component.ts index ce769ffe9e55..eae68db19f00 100644 --- a/src/main/webapp/app/shared/connection-warning/connection-warning.component.ts +++ b/src/main/webapp/app/shared/connection-warning/connection-warning.component.ts @@ -1,16 +1,24 @@ -import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { Component, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; import { faExclamationCircle, faWifi } from '@fortawesome/free-solid-svg-icons'; import { Subscription, filter } from 'rxjs'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'; import { NavigationEnd, Router } from '@angular/router'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from '../language/translate.directive'; +import { CloseCircleComponent } from '../close-circle/close-circle.component'; +import { NgClass } from '@angular/common'; @Component({ selector: 'jhi-connection-warning', templateUrl: './connection-warning.component.html', styleUrls: ['./connection-warning.component.scss'], + imports: [FaIconComponent, TranslateDirective, CloseCircleComponent, NgClass, NgbPopover], }) export class JhiConnectionWarningComponent implements OnInit, OnDestroy { + private websocketService = inject(JhiWebsocketService); + private router = inject(Router); + @ViewChild('popover') popover: NgbPopover; disconnected = false; @@ -23,10 +31,9 @@ export class JhiConnectionWarningComponent implements OnInit, OnDestroy { faExclamationCircle = faExclamationCircle; faWifi = faWifi; - constructor( - private websocketService: JhiWebsocketService, - private router: Router, - ) { + constructor() { + const router = this.router; + this.routerSubscription = router.events .pipe(filter((event) => event instanceof NavigationEnd)) .subscribe((event: NavigationEnd) => (this.isOnExamParticipationPage = !!event.url.match('^/courses/\\d+/exams/\\d+'))); diff --git a/src/main/webapp/app/shared/consistency-check/consistency-check.component.ts b/src/main/webapp/app/shared/consistency-check/consistency-check.component.ts index cfa9cf0ee405..fd5e650bfcb1 100644 --- a/src/main/webapp/app/shared/consistency-check/consistency-check.component.ts +++ b/src/main/webapp/app/shared/consistency-check/consistency-check.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { ConsistencyCheckService } from 'app/shared/consistency-check/consistency-check.service'; import { AlertService } from 'app/core/util/alert.service'; @@ -6,12 +6,20 @@ import { ConsistencyCheckError } from 'app/entities/consistency-check-result.mod import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { getCourseId } from 'app/entities/exercise.model'; import { faCheck, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { TranslateDirective } from '../language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { RouterLink } from '@angular/router'; @Component({ selector: 'jhi-consistency-check', templateUrl: './consistency-check.component.html', + imports: [TranslateDirective, FaIconComponent, RouterLink], }) export class ConsistencyCheckComponent implements OnInit { + private activeModal = inject(NgbActiveModal); + private consistencyCheckService = inject(ConsistencyCheckService); + private alertService = inject(AlertService); + @Input() exercisesToCheck: ProgrammingExercise[]; inconsistencies: ConsistencyCheckError[] = []; @@ -21,12 +29,6 @@ export class ConsistencyCheckComponent implements OnInit { faTimes = faTimes; faCheck = faCheck; - constructor( - private activeModal: NgbActiveModal, - private consistencyCheckService: ConsistencyCheckService, - private alertService: AlertService, - ) {} - ngOnInit(): void { this.isLoading = true; let exercisesRemaining = this.exercisesToCheck.length; diff --git a/src/main/webapp/app/shared/consistency-check/consistency-check.service.ts b/src/main/webapp/app/shared/consistency-check/consistency-check.service.ts index 856f74da4420..f815d44ebbcf 100644 --- a/src/main/webapp/app/shared/consistency-check/consistency-check.service.ts +++ b/src/main/webapp/app/shared/consistency-check/consistency-check.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { ConsistencyCheckError } from 'app/entities/consistency-check-result.model'; @@ -6,9 +6,9 @@ import { ConsistencyCheckError } from 'app/entities/consistency-check-result.mod providedIn: 'root', }) export class ConsistencyCheckService { - private readonly RESOURCE_URL = 'api/programming-exercises'; + private http = inject(HttpClient); - constructor(private http: HttpClient) {} + private readonly RESOURCE_URL = 'api/programming-exercises'; /** * Request consistency checks for a given programming exercise diff --git a/src/main/webapp/app/shared/course-group/course-group.component.ts b/src/main/webapp/app/shared/course-group/course-group.component.ts index dfd4a21a995a..89de3bd26ca6 100644 --- a/src/main/webapp/app/shared/course-group/course-group.component.ts +++ b/src/main/webapp/app/shared/course-group/course-group.component.ts @@ -11,6 +11,13 @@ import { download, generateCsv, mkConfig } from 'export-to-csv'; import { faDownload, faUserSlash } from '@fortawesome/free-solid-svg-icons'; import { TutorialGroup } from 'app/entities/tutorial-group/tutorial-group.model'; import { EMAIL_KEY, NAME_KEY, REGISTRATION_NUMBER_KEY, USERNAME_KEY } from 'app/shared/export/export-constants'; +import { UsersImportButtonComponent } from '../user-import/users-import-button.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from '../language/translate.directive'; +import { NgxDatatableModule } from '@siemens/ngx-datatable'; +import { RouterLink } from '@angular/router'; +import { ProfilePictureComponent } from '../profile-picture/profile-picture.component'; +import { DeleteButtonDirective } from '../delete-dialog/delete-button.directive'; const cssClasses = { alreadyMember: 'already-member', @@ -29,36 +36,25 @@ export type GroupUserInformationRow = { templateUrl: './course-group.component.html', styleUrls: ['./course-group.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [UsersImportButtonComponent, FaIconComponent, TranslateDirective, DataTableComponent, NgxDatatableModule, RouterLink, ProfilePictureComponent, DeleteButtonDirective], }) export class CourseGroupComponent implements OnDestroy { @ViewChild(DataTableComponent) dataTable: DataTableComponent; - @Input() - allGroupUsers: User[] = []; - @Input() - isLoadingAllGroupUsers = false; - @Input() - isAdmin = false; - @Input() - course: Course; - @Input() - tutorialGroup: TutorialGroup | undefined = undefined; - @Input() - courseGroup: CourseGroup; - @Input() - exportFileName: string; + @Input() allGroupUsers: User[] = []; + @Input() isLoadingAllGroupUsers = false; + @Input() isAdmin = false; + @Input() course: Course; + @Input() tutorialGroup: TutorialGroup | undefined = undefined; + @Input() courseGroup: CourseGroup; + @Input() exportFileName: string; - @Input() - userSearch: (loginOrName: string) => Observable> = () => of(new HttpResponse({ body: [] })); - @Input() - addUserToGroup: (login: string) => Observable> = () => of(new HttpResponse()); - @Input() - removeUserFromGroup: (login: string) => Observable> = () => of(new HttpResponse()); - @Input() - handleUsersSizeChange: (filteredUsersSize: number) => void = () => {}; + @Input() userSearch: (loginOrName: string) => Observable> = () => of(new HttpResponse({ body: [] })); + @Input() addUserToGroup: (login: string) => Observable> = () => of(new HttpResponse()); + @Input() removeUserFromGroup: (login: string) => Observable> = () => of(new HttpResponse()); + @Input() handleUsersSizeChange: (filteredUsersSize: number) => void = () => {}; - @Output() - importFinish: EventEmitter = new EventEmitter(); + @Output() importFinish: EventEmitter = new EventEmitter(); readonly ActionType = ActionType; diff --git a/src/main/webapp/app/shared/course-group/course-group.module.ts b/src/main/webapp/app/shared/course-group/course-group.module.ts index 0c145b7ad00c..04b531f5a7d7 100644 --- a/src/main/webapp/app/shared/course-group/course-group.module.ts +++ b/src/main/webapp/app/shared/course-group/course-group.module.ts @@ -8,8 +8,7 @@ import { RouterModule } from '@angular/router'; import { ProfilePictureComponent } from 'app/shared/profile-picture/profile-picture.component'; @NgModule({ - imports: [ArtemisDataTableModule, UserImportModule, NgxDatatableModule, ArtemisSharedModule, RouterModule, ProfilePictureComponent], - declarations: [CourseGroupComponent], + imports: [ArtemisDataTableModule, UserImportModule, NgxDatatableModule, ArtemisSharedModule, RouterModule, ProfilePictureComponent, CourseGroupComponent], exports: [CourseGroupComponent], }) export class ArtemisCourseGroupModule {} diff --git a/src/main/webapp/app/shared/course-users-selector/course-users-selector.component.ts b/src/main/webapp/app/shared/course-users-selector/course-users-selector.component.ts index ad8fc16d851f..5b206edda6d3 100644 --- a/src/main/webapp/app/shared/course-users-selector/course-users-selector.component.ts +++ b/src/main/webapp/app/shared/course-users-selector/course-users-selector.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, ElementRef, HostBinding, Input, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core'; +import { ChangeDetectorRef, Component, ElementRef, HostBinding, Input, OnDestroy, OnInit, ViewChild, ViewEncapsulation, inject } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { Observable, OperatorFunction, Subject, catchError, map, of } from 'rxjs'; import { CourseManagementService } from 'app/course/manage/course-management.service'; @@ -6,6 +6,10 @@ import { debounceTime, distinctUntilChanged, filter, switchMap, takeUntil, tap } import { User, UserPublicInfoDTO } from 'app/core/user/user.model'; import { NgbTypeahead, NgbTypeaheadSelectItemEvent } from '@ng-bootstrap/ng-bootstrap'; import { faX } from '@fortawesome/free-solid-svg-icons'; +import { ProfilePictureComponent } from '../profile-picture/profile-picture.component'; +import { TranslateDirective } from '../language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; let selectorId = 0; @@ -33,8 +37,12 @@ export type SearchRoleGroup = 'tutors' | 'students' | 'instructors'; }, ], encapsulation: ViewEncapsulation.None, + imports: [NgbTypeahead, ProfilePictureComponent, TranslateDirective, FaIconComponent, ArtemisTranslatePipe], }) export class CourseUsersSelectorComponent implements ControlValueAccessor, OnInit, OnDestroy { + private courseManagementService = inject(CourseManagementService); + private cdr = inject(ChangeDetectorRef); + @HostBinding('class.course-users-selector') hostClass = true; private ngUnsubscribe = new Subject(); @@ -68,11 +76,6 @@ export class CourseUsersSelectorComponent implements ControlValueAccessor, OnIni isSearching = false; searchFailed = false; - constructor( - private courseManagementService: CourseManagementService, - private cdr: ChangeDetectorRef, - ) {} - ngOnInit(): void { if (this.rolesToAllowSearchingIn.includes('students')) { this.searchStudents = true; diff --git a/src/main/webapp/app/shared/course-users-selector/course-users-selector.module.ts b/src/main/webapp/app/shared/course-users-selector/course-users-selector.module.ts index 8c47180607d0..82e2cf35a168 100644 --- a/src/main/webapp/app/shared/course-users-selector/course-users-selector.module.ts +++ b/src/main/webapp/app/shared/course-users-selector/course-users-selector.module.ts @@ -7,8 +7,7 @@ import { CourseUsersSelectorComponent } from 'app/shared/course-users-selector/c import { ProfilePictureComponent } from 'app/shared/profile-picture/profile-picture.component'; @NgModule({ - imports: [CommonModule, FormsModule, ReactiveFormsModule, ArtemisSharedModule, ArtemisSharedComponentModule, ProfilePictureComponent], + imports: [CommonModule, FormsModule, ReactiveFormsModule, ArtemisSharedModule, ArtemisSharedComponentModule, ProfilePictureComponent, CourseUsersSelectorComponent], exports: [CourseUsersSelectorComponent], - declarations: [CourseUsersSelectorComponent], }) export class CourseUsersSelectorModule {} diff --git a/src/main/webapp/app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.component.ts b/src/main/webapp/app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.component.ts index da1cc727af85..1b47574ca74d 100644 --- a/src/main/webapp/app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.component.ts +++ b/src/main/webapp/app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { TutorLeaderboardElement } from 'app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.model'; import { Course } from 'app/entities/course.model'; import { Exercise, getCourseFromExercise } from 'app/entities/exercise.model'; @@ -6,12 +6,23 @@ import { AccountService } from 'app/core/auth/account.service'; import { SortService } from 'app/shared/service/sort.service'; import { Exam } from 'app/entities/exam/exam.model'; import { faExclamationTriangle, faSort } from '@fortawesome/free-solid-svg-icons'; +import { SortDirective } from '../../sort/sort.directive'; +import { SortByDirective } from '../../sort/sort-by.directive'; +import { TranslateDirective } from '../../language/translate.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { RouterLink } from '@angular/router'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-tutor-leaderboard', templateUrl: './tutor-leaderboard.component.html', + imports: [SortDirective, SortByDirective, TranslateDirective, FaIconComponent, NgbTooltip, RouterLink, ArtemisTranslatePipe], }) export class TutorLeaderboardComponent implements OnInit { + private accountService = inject(AccountService); + private sortService = inject(SortService); + @Input() public tutorsData: TutorLeaderboardElement[] = []; @Input() public course?: Course; @Input() public exercise?: Exercise; @@ -26,11 +37,6 @@ export class TutorLeaderboardComponent implements OnInit { faSort = faSort; faExclamationTriangle = faExclamationTriangle; - constructor( - private accountService: AccountService, - private sortService: SortService, - ) {} - /** * Life cycle hook called by Angular to indicate that Angular is done creating the component */ diff --git a/src/main/webapp/app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.model.ts b/src/main/webapp/app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.model.ts index b1879e6a1565..703227c5c509 100644 --- a/src/main/webapp/app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.model.ts +++ b/src/main/webapp/app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.model.ts @@ -13,6 +13,4 @@ export class TutorLeaderboardElement { public averageRating = 0; public numberOfTutorRatings = 0; public hasIssuesWithPerformance = false; - - constructor() {} } diff --git a/src/main/webapp/app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.module.ts b/src/main/webapp/app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.module.ts index 2ae12d1ef528..e916a735f163 100644 --- a/src/main/webapp/app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.module.ts +++ b/src/main/webapp/app/shared/dashboards/tutor-leaderboard/tutor-leaderboard.module.ts @@ -4,8 +4,7 @@ import { TutorLeaderboardComponent } from 'app/shared/dashboards/tutor-leaderboa import { ArtemisSharedModule } from 'app/shared/shared.module'; @NgModule({ - imports: [ArtemisSharedModule, RouterModule.forChild([])], - declarations: [TutorLeaderboardComponent], + imports: [ArtemisSharedModule, RouterModule.forChild([]), TutorLeaderboardComponent], exports: [TutorLeaderboardComponent], }) export class ArtemisTutorLeaderboardModule {} diff --git a/src/main/webapp/app/shared/dashboards/tutor-participation-graph/progress-bar/progress-bar.component.ts b/src/main/webapp/app/shared/dashboards/tutor-participation-graph/progress-bar/progress-bar.component.ts index 1da8f8762db0..1ef2547dff79 100644 --- a/src/main/webapp/app/shared/dashboards/tutor-participation-graph/progress-bar/progress-bar.component.ts +++ b/src/main/webapp/app/shared/dashboards/tutor-participation-graph/progress-bar/progress-bar.component.ts @@ -1,14 +1,20 @@ -import { ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core'; +import { ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, SimpleChanges, inject } from '@angular/core'; import { round } from 'app/shared/util/utils'; import { Theme, ThemeService } from 'app/core/theme/theme.service'; import { Subscription } from 'rxjs'; import { toObservable } from '@angular/core/rxjs-interop'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { NgClass } from '@angular/common'; @Component({ selector: 'jhi-progress-bar', templateUrl: './progress-bar.component.html', + imports: [NgbTooltip, NgClass], }) export class ProgressBarComponent implements OnChanges, OnDestroy { + private themeService = inject(ThemeService); + private ref = inject(ChangeDetectorRef); + @Input() public tooltip: string; @Input() public percentage: number; @Input() public numerator: number; @@ -18,10 +24,7 @@ export class ProgressBarComponent implements OnChanges, OnDestroy { backgroundColorClass: string; themeSubscription: Subscription; - constructor( - private themeService: ThemeService, - private ref: ChangeDetectorRef, - ) { + constructor() { this.themeSubscription = toObservable(this.themeService.currentTheme).subscribe(() => { this.chooseProgressBarTextColor(); diff --git a/src/main/webapp/app/shared/dashboards/tutor-participation-graph/tutor-participation-graph.component.ts b/src/main/webapp/app/shared/dashboards/tutor-participation-graph/tutor-participation-graph.component.ts index e1da8a6b0498..f287c64dbf9b 100644 --- a/src/main/webapp/app/shared/dashboards/tutor-participation-graph/tutor-participation-graph.component.ts +++ b/src/main/webapp/app/shared/dashboards/tutor-participation-graph/tutor-participation-graph.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnChanges, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core'; +import { Component, Input, OnChanges, OnInit, SimpleChanges, ViewEncapsulation, inject } from '@angular/core'; import { Router } from '@angular/router'; import { get } from 'lodash-es'; import { Exercise, ExerciseType } from 'app/entities/exercise.model'; @@ -6,14 +6,22 @@ import { TutorParticipation, TutorParticipationStatus } from 'app/entities/parti import { DueDateStat } from 'app/course/dashboards/due-date-stat.model'; import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model'; import { faBook, faChalkboardTeacher } from '@fortawesome/free-solid-svg-icons'; +import { NgClass } from '@angular/common'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ProgressBarComponent } from './progress-bar/progress-bar.component'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-tutor-participation-graph', templateUrl: './tutor-participation-graph.component.html', styleUrls: ['./tutor-participation-graph.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [NgClass, NgbTooltip, FaIconComponent, ProgressBarComponent, ArtemisTranslatePipe], }) export class TutorParticipationGraphComponent implements OnInit, OnChanges { + private router = inject(Router); + @Input() public tutorParticipation: TutorParticipation; @Input() public numberOfSubmissions?: DueDateStat; @Input() public totalNumberOfAssessments?: DueDateStat; @@ -45,8 +53,6 @@ export class TutorParticipationGraphComponent implements OnInit, OnChanges { faBook = faBook; faChalkboardTeacher = faChalkboardTeacher; - constructor(private router: Router) {} - /** * Life cycle hook called by Angular to indicate that Angular is done creating the component */ diff --git a/src/main/webapp/app/shared/dashboards/tutor-participation-graph/tutor-participation-graph.module.ts b/src/main/webapp/app/shared/dashboards/tutor-participation-graph/tutor-participation-graph.module.ts index 924d1309a53e..2d89e4d91c0a 100644 --- a/src/main/webapp/app/shared/dashboards/tutor-participation-graph/tutor-participation-graph.module.ts +++ b/src/main/webapp/app/shared/dashboards/tutor-participation-graph/tutor-participation-graph.module.ts @@ -4,8 +4,7 @@ import { TutorParticipationGraphComponent } from 'app/shared/dashboards/tutor-pa import { ArtemisSharedModule } from 'app/shared/shared.module'; @NgModule({ - imports: [ArtemisSharedModule], - declarations: [ProgressBarComponent, TutorParticipationGraphComponent], + imports: [ArtemisSharedModule, ProgressBarComponent, TutorParticipationGraphComponent], exports: [TutorParticipationGraphComponent, ProgressBarComponent], }) export class ArtemisTutorParticipationGraphModule {} diff --git a/src/main/webapp/app/shared/data-table/data-table.component.ts b/src/main/webapp/app/shared/data-table/data-table.component.ts index 60c93ef5d313..33370b27379c 100644 --- a/src/main/webapp/app/shared/data-table/data-table.component.ts +++ b/src/main/webapp/app/shared/data-table/data-table.component.ts @@ -1,4 +1,18 @@ -import { Component, ContentChild, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core'; +import { + Component, + ContentChild, + ElementRef, + EventEmitter, + Input, + OnChanges, + OnInit, + Output, + SimpleChanges, + TemplateRef, + ViewChild, + ViewEncapsulation, + inject, +} from '@angular/core'; import { debounceTime, distinctUntilChanged, map, tap } from 'rxjs/operators'; import { Observable } from 'rxjs'; import { ColumnMode, SortType } from '@siemens/ngx-datatable'; @@ -7,6 +21,11 @@ import { BaseEntity, StringBaseEntity } from 'app/shared/model/base-entity'; import { LocalStorageService } from 'ngx-webstorage'; import { SortService } from 'app/shared/service/sort.service'; import { faCircleNotch, faSort, faSortDown, faSortUp } from '@fortawesome/free-solid-svg-icons'; +import { NgbDropdown, NgbDropdownButtonItem, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle, NgbTypeahead } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from '../language/translate.directive'; +import { NgTemplateOutlet } from '@angular/common'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; /** * Enum for ascending and descending order. @@ -46,8 +65,23 @@ type PagingValue = number | 'all'; templateUrl: './data-table.component.html', styleUrls: ['data-table.component.scss'], encapsulation: ViewEncapsulation.None, + imports: [ + NgbDropdown, + NgbDropdownToggle, + NgbDropdownMenu, + NgbDropdownButtonItem, + NgbDropdownItem, + NgbTypeahead, + FaIconComponent, + TranslateDirective, + NgTemplateOutlet, + ArtemisTranslatePipe, + ], }) export class DataTableComponent implements OnInit, OnChanges { + private sortService = inject(SortService); + private localStorage = inject(LocalStorageService); + /** * @property templateRef Ref to the content child of this component (which is ngx-datatable) */ @@ -145,10 +179,7 @@ export class DataTableComponent implements OnInit, OnChanges { // Icons faCircleNotch = faCircleNotch; - constructor( - private sortService: SortService, - private localStorage: LocalStorageService, - ) { + constructor() { this.entities = []; this.entityCriteria = { textSearch: [], diff --git a/src/main/webapp/app/shared/data-table/data-table.module.ts b/src/main/webapp/app/shared/data-table/data-table.module.ts index 1740b6af5d49..067d3c6f1b20 100644 --- a/src/main/webapp/app/shared/data-table/data-table.module.ts +++ b/src/main/webapp/app/shared/data-table/data-table.module.ts @@ -4,8 +4,7 @@ import { NgxDatatableModule } from '@siemens/ngx-datatable'; import { DataTableComponent } from './data-table.component'; @NgModule({ - imports: [ArtemisSharedModule, NgxDatatableModule], - declarations: [DataTableComponent], + imports: [ArtemisSharedModule, NgxDatatableModule, DataTableComponent], exports: [DataTableComponent], }) export class ArtemisDataTableModule {} diff --git a/src/main/webapp/app/shared/date-time-picker/date-time-picker.component.ts b/src/main/webapp/app/shared/date-time-picker/date-time-picker.component.ts index 78d1f46b9a11..8a685019ece1 100644 --- a/src/main/webapp/app/shared/date-time-picker/date-time-picker.component.ts +++ b/src/main/webapp/app/shared/date-time-picker/date-time-picker.component.ts @@ -1,7 +1,13 @@ import { Component, ViewChild, computed, forwardRef, input, model, output, signal } from '@angular/core'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR, NgModel } from '@angular/forms'; +import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR, NgModel } from '@angular/forms'; import { faCalendarAlt, faCircleXmark, faClock, faGlobe, faQuestionCircle, faTriangleExclamation } from '@fortawesome/free-solid-svg-icons'; import dayjs from 'dayjs/esm'; +import { FaIconComponent, FaStackComponent, FaStackItemSizeDirective } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { OwlDateTimeModule } from '@danielmoncada/angular-datetime-picker'; +import { NgClass, NgTemplateOutlet } from '@angular/common'; +import { TranslateDirective } from '../language/translate.directive'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; export enum DateTimePickerType { CALENDAR, @@ -20,6 +26,18 @@ export enum DateTimePickerType { useExisting: forwardRef(() => FormDateTimePickerComponent), }, ], + imports: [ + FaStackComponent, + NgbTooltip, + FaIconComponent, + FaStackItemSizeDirective, + FormsModule, + OwlDateTimeModule, + NgClass, + NgTemplateOutlet, + TranslateDirective, + ArtemisTranslatePipe, + ], }) export class FormDateTimePickerComponent implements ControlValueAccessor { protected readonly faCalendarAlt = faCalendarAlt; diff --git a/src/main/webapp/app/shared/date-time-picker/date-time-picker.module.ts b/src/main/webapp/app/shared/date-time-picker/date-time-picker.module.ts index 682a28393f44..8c4b84c7b3d9 100644 --- a/src/main/webapp/app/shared/date-time-picker/date-time-picker.module.ts +++ b/src/main/webapp/app/shared/date-time-picker/date-time-picker.module.ts @@ -15,9 +15,17 @@ export const MY_NATIVE_FORMATS = { monthYearA11yLabel: { year: 'numeric', month: 'long' }, }; @NgModule({ - imports: [CommonModule, FormsModule, OwlDateTimeModule, OwlNativeDateTimeModule, ReactiveFormsModule, ArtemisSharedModule, ArtemisSharedComponentModule], + imports: [ + CommonModule, + FormsModule, + OwlDateTimeModule, + OwlNativeDateTimeModule, + ReactiveFormsModule, + ArtemisSharedModule, + ArtemisSharedComponentModule, + FormDateTimePickerComponent, + ], exports: [FormDateTimePickerComponent], - declarations: [FormDateTimePickerComponent], providers: [{ provide: OWL_DATE_TIME_FORMATS, useValue: MY_NATIVE_FORMATS }], }) export class FormDateTimePickerModule {} diff --git a/src/main/webapp/app/shared/delete-dialog/delete-button.directive.ts b/src/main/webapp/app/shared/delete-dialog/delete-button.directive.ts index 6fe508245dc8..adcd403a4243 100644 --- a/src/main/webapp/app/shared/delete-dialog/delete-button.directive.ts +++ b/src/main/webapp/app/shared/delete-dialog/delete-button.directive.ts @@ -1,5 +1,5 @@ import { DeleteDialogService } from 'app/shared/delete-dialog/delete-dialog.service'; -import { Directive, ElementRef, EventEmitter, HostListener, Input, OnInit, Output, Renderer2 } from '@angular/core'; +import { Directive, ElementRef, EventEmitter, HostListener, Input, OnInit, Output, Renderer2, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { ActionType, DeleteDialogData, EntitySummary } from 'app/shared/delete-dialog/delete-dialog.model'; import { Observable } from 'rxjs'; @@ -7,6 +7,11 @@ import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; @Directive({ selector: '[jhiDeleteButton]' }) export class DeleteButtonDirective implements OnInit { + private deleteDialogService = inject(DeleteDialogService); + private renderer = inject(Renderer2); + private elementRef = inject(ElementRef); + private translateService = inject(TranslateService); + @Input() entityTitle?: string; @Input() deleteQuestion: string; @Input() entitySummaryTitle?: string; @@ -26,13 +31,6 @@ export class DeleteButtonDirective implements OnInit { deleteTextSpan: HTMLElement; - constructor( - private deleteDialogService: DeleteDialogService, - private renderer: Renderer2, - private elementRef: ElementRef, - private translateService: TranslateService, - ) {} - /** * This method appends classes and type property to the button on which directive was used, additionally adds a span tag with delete text. * We can't use component, as Angular would wrap it in its own tag and this will break button grouping that we are using for other buttons. diff --git a/src/main/webapp/app/shared/delete-dialog/delete-dialog.component.ts b/src/main/webapp/app/shared/delete-dialog/delete-dialog.component.ts index 0a85965d0b38..f7e1756c0ca8 100644 --- a/src/main/webapp/app/shared/delete-dialog/delete-dialog.component.ts +++ b/src/main/webapp/app/shared/delete-dialog/delete-dialog.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; +import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { mapValues } from 'lodash-es'; import { ActionType, EntitySummary } from 'app/shared/delete-dialog/delete-dialog.model'; @@ -6,13 +6,22 @@ import { Observable, Subscription } from 'rxjs'; import { AlertService } from 'app/core/util/alert.service'; import { faBan, faCheck, faSpinner, faTimes, faTrash, faUndo } from '@fortawesome/free-solid-svg-icons'; import { ButtonType } from 'app/shared/components/button.component'; -import { NgForm } from '@angular/forms'; +import { FormsModule, NgForm } from '@angular/forms'; +import { TranslateDirective } from '../language/translate.directive'; +import { ConfirmEntityNameComponent } from '../confirm-entity-name/confirm-entity-name.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgClass } from '@angular/common'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-delete-dialog', templateUrl: './delete-dialog.component.html', + imports: [FormsModule, TranslateDirective, ConfirmEntityNameComponent, FaIconComponent, NgClass, ArtemisTranslatePipe], }) export class DeleteDialogComponent implements OnInit, OnDestroy { + private activeModal = inject(NgbActiveModal); + private alertService = inject(AlertService); + readonly actionTypes = ActionType; private dialogErrorSubscription: Subscription; dialogError: Observable; @@ -47,11 +56,6 @@ export class DeleteDialogComponent implements OnInit, OnDestroy { faUndo = faUndo; warningTextColor: string; - constructor( - private activeModal: NgbActiveModal, - private alertService: AlertService, - ) {} - /** * Life cycle hook called by Angular to indicate that Angular is done creating the component */ diff --git a/src/main/webapp/app/shared/delete-dialog/delete-dialog.service.ts b/src/main/webapp/app/shared/delete-dialog/delete-dialog.service.ts index 02ab549f82a8..1ee27173cf78 100644 --- a/src/main/webapp/app/shared/delete-dialog/delete-dialog.service.ts +++ b/src/main/webapp/app/shared/delete-dialog/delete-dialog.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component'; import { DeleteDialogData, EntitySummary } from 'app/shared/delete-dialog/delete-dialog.model'; @@ -8,12 +8,10 @@ import { HttpErrorResponse } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class DeleteDialogService { - modalRef: NgbModalRef | null; + private modalService = inject(NgbModal); + alertService = inject(AlertService); - constructor( - private modalService: NgbModal, - public alertService: AlertService, - ) {} + modalRef: NgbModalRef | null; /** * Opens delete dialog diff --git a/src/main/webapp/app/shared/detail-overview-navigation-bar/detail-overview-navigation-bar.component.ts b/src/main/webapp/app/shared/detail-overview-navigation-bar/detail-overview-navigation-bar.component.ts index e9eb25918015..60627b646794 100644 --- a/src/main/webapp/app/shared/detail-overview-navigation-bar/detail-overview-navigation-bar.component.ts +++ b/src/main/webapp/app/shared/detail-overview-navigation-bar/detail-overview-navigation-bar.component.ts @@ -1,10 +1,12 @@ import { AfterViewInit, Component, HostListener, Input } from '@angular/core'; import { updateHeaderHeight } from 'app/shared/util/navbar.util'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-detail-overview-navigation-bar', templateUrl: './detail-overview-navigation-bar.component.html', styleUrls: ['./detail-overview-navigation-bar.scss'], + imports: [ArtemisTranslatePipe], }) export class DetailOverviewNavigationBarComponent implements AfterViewInit { @Input() diff --git a/src/main/webapp/app/shared/difficulty-level/difficulty-level.component.ts b/src/main/webapp/app/shared/difficulty-level/difficulty-level.component.ts index 69af618315e3..b2cd741d3ea2 100644 --- a/src/main/webapp/app/shared/difficulty-level/difficulty-level.component.ts +++ b/src/main/webapp/app/shared/difficulty-level/difficulty-level.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { DifficultyLevel } from 'app/entities/exercise.model'; import { Subscription } from 'rxjs'; @@ -13,16 +13,15 @@ export interface ColoredDifficultyLevel { selector: 'jhi-difficulty-level', templateUrl: './difficulty-level.component.html', styleUrls: ['./difficulty-level.component.scss'], - standalone: true, imports: [ArtemisSharedModule, ArtemisSharedComponentModule], }) export class DifficultyLevelComponent implements OnInit, OnDestroy { + private translateService = inject(TranslateService); + private translateSubscription: Subscription; @Input() difficultyLevel: string; coloredDifficultyLevel: ColoredDifficultyLevel = { label: '', color: [] }; - constructor(private translateService: TranslateService) {} - ngOnInit(): void { this.translateSubscription = this.translateService.onLangChange.subscribe(() => { this.mapDifficultyLevelToColors(this.difficultyLevel); diff --git a/src/main/webapp/app/shared/exercise-categories/custom-exercise-category-badge/custom-exercise-category-badge.component.ts b/src/main/webapp/app/shared/exercise-categories/custom-exercise-category-badge/custom-exercise-category-badge.component.ts index aec203a26946..b31e224a9caa 100644 --- a/src/main/webapp/app/shared/exercise-categories/custom-exercise-category-badge/custom-exercise-category-badge.component.ts +++ b/src/main/webapp/app/shared/exercise-categories/custom-exercise-category-badge/custom-exercise-category-badge.component.ts @@ -11,7 +11,6 @@ type CategoryFontSize = 'default' | 'small'; selector: 'jhi-custom-exercise-category-badge', templateUrl: './custom-exercise-category-badge.component.html', styleUrls: ['custom-exercise-category-badge.component.scss'], - standalone: true, imports: [CommonModule, FontAwesomeModule], }) export class CustomExerciseCategoryBadgeComponent { diff --git a/src/main/webapp/app/shared/exercise-categories/exercise-categories.component.ts b/src/main/webapp/app/shared/exercise-categories/exercise-categories.component.ts index 065c59b801fc..c6834e1b0a1c 100644 --- a/src/main/webapp/app/shared/exercise-categories/exercise-categories.component.ts +++ b/src/main/webapp/app/shared/exercise-categories/exercise-categories.component.ts @@ -2,6 +2,13 @@ import { Component, Input } from '@angular/core'; import { Exercise, IncludedInOverallScore } from 'app/entities/exercise.model'; import dayjs from 'dayjs/esm'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; +import { NgClass, NgStyle } from '@angular/common'; +import { RouterLink } from '@angular/router'; +import { NotReleasedTagComponent } from '../components/not-released-tag.component'; +import { TranslateDirective } from '../language/translate.directive'; +import { IncludedInScoreBadgeComponent } from '../../exercises/shared/exercise-headers/included-in-score-badge.component'; +import { DifficultyBadgeComponent } from '../../exercises/shared/exercise-headers/difficulty-badge.component'; +import { TruncatePipe } from 'app/shared/pipes/truncate.pipe'; interface ShowTagsConfig { notReleased?: boolean; @@ -15,6 +22,7 @@ interface ShowTagsConfig { selector: 'jhi-exercise-categories', templateUrl: './exercise-categories.component.html', styleUrls: ['./exercise-categories.component.scss'], + imports: [NgClass, RouterLink, NotReleasedTagComponent, TranslateDirective, IncludedInScoreBadgeComponent, NgStyle, DifficultyBadgeComponent, TruncatePipe], }) export class ExerciseCategoriesComponent { readonly IncludedInOverallScore = IncludedInOverallScore; diff --git a/src/main/webapp/app/shared/exercise-categories/exercise-categories.module.ts b/src/main/webapp/app/shared/exercise-categories/exercise-categories.module.ts index f0f8877ffdec..2502f21738c2 100644 --- a/src/main/webapp/app/shared/exercise-categories/exercise-categories.module.ts +++ b/src/main/webapp/app/shared/exercise-categories/exercise-categories.module.ts @@ -6,8 +6,7 @@ import { ExerciseCategoriesComponent } from 'app/shared/exercise-categories/exer import { CustomExerciseCategoryBadgeComponent } from 'app/shared/exercise-categories/custom-exercise-category-badge/custom-exercise-category-badge.component'; @NgModule({ - imports: [ArtemisSharedModule, RouterModule, ArtemisSharedComponentModule, CustomExerciseCategoryBadgeComponent], - declarations: [ExerciseCategoriesComponent], + imports: [ArtemisSharedModule, RouterModule, ArtemisSharedComponentModule, CustomExerciseCategoryBadgeComponent, ExerciseCategoriesComponent], exports: [ExerciseCategoriesComponent], }) export class ExerciseCategoriesModule {} diff --git a/src/main/webapp/app/shared/exercise-filter/exercise-filter-modal.component.ts b/src/main/webapp/app/shared/exercise-filter/exercise-filter-modal.component.ts index 8b1bf7c58488..9f9b38240092 100644 --- a/src/main/webapp/app/shared/exercise-filter/exercise-filter-modal.component.ts +++ b/src/main/webapp/app/shared/exercise-filter/exercise-filter-modal.component.ts @@ -1,5 +1,5 @@ -import { Component, EventEmitter, OnInit, Output, ViewChild } from '@angular/core'; -import { NgbActiveModal, NgbTypeahead } from '@ng-bootstrap/ng-bootstrap'; +import { Component, EventEmitter, OnInit, Output, ViewChild, inject } from '@angular/core'; +import { NgbActiveModal, NgbModule, NgbTypeahead } from '@ng-bootstrap/ng-bootstrap'; import { faBackward, faFilter } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; @@ -29,7 +29,6 @@ import { isRangeFilterApplied } from 'app/shared/sidebar/sidebar.helper'; selector: 'jhi-exercise-filter-modal', templateUrl: './exercise-filter-modal.component.html', styleUrls: ['./exercise-filter-modal.component.scss'], - standalone: true, imports: [ FormsModule, ReactiveFormsModule, @@ -38,9 +37,12 @@ import { isRangeFilterApplied } from 'app/shared/sidebar/sidebar.helper'; ArtemisSharedComponentModule, CustomExerciseCategoryBadgeComponent, RangeSliderComponent, + NgbModule, ], }) export class ExerciseFilterModalComponent implements OnInit { + private activeModal = inject(NgbActiveModal); + readonly faFilter = faFilter; readonly faBackward = faBackward; @@ -70,8 +72,6 @@ export class ExerciseFilterModalComponent implements OnInit { exerciseFilters?: ExerciseFilterOptions; - constructor(private activeModal: NgbActiveModal) {} - ngOnInit() { this.categoryFilter = this.exerciseFilters?.categoryFilter; this.typeFilter = this.exerciseFilters?.exerciseTypesFilter; diff --git a/src/main/webapp/app/shared/export/export-button.component.ts b/src/main/webapp/app/shared/export/export-button.component.ts index 4d5de6b7d49f..94f8c4f4cd62 100644 --- a/src/main/webapp/app/shared/export/export-button.component.ts +++ b/src/main/webapp/app/shared/export/export-button.component.ts @@ -1,14 +1,18 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, EventEmitter, Input, Output, inject } from '@angular/core'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { ButtonSize, ButtonType } from 'app/shared/components/button.component'; import { CsvExportOptions, ExportModalComponent } from 'app/shared/export/export-modal.component'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; +import { ButtonComponent } from '../components/button.component'; @Component({ selector: 'jhi-csv-export-button', template: ` `, + imports: [ButtonComponent], }) export class ExportButtonComponent { + private modalService = inject(NgbModal); + ButtonType = ButtonType; ButtonSize = ButtonSize; @@ -19,8 +23,6 @@ export class ExportButtonComponent { @Output() onExport: EventEmitter = new EventEmitter(); - constructor(private modalService: NgbModal) {} - /** * Open up export option modal * @param {Event} event - Mouse Event which invoked the opening diff --git a/src/main/webapp/app/shared/export/export-modal.component.ts b/src/main/webapp/app/shared/export/export-modal.component.ts index d5e35b1594bd..10974e03f5b3 100644 --- a/src/main/webapp/app/shared/export/export-modal.component.ts +++ b/src/main/webapp/app/shared/export/export-modal.component.ts @@ -1,7 +1,12 @@ -import { Component, OnInit } from '@angular/core'; -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { Component, OnInit, inject } from '@angular/core'; +import { NgbActiveModal, NgbNav, NgbNavContent, NgbNavItem, NgbNavLink, NgbNavLinkBase, NgbNavOutlet } from '@ng-bootstrap/ng-bootstrap'; import { TranslateService } from '@ngx-translate/core'; import { faBan, faDownload } from '@fortawesome/free-solid-svg-icons'; +import { FormsModule } from '@angular/forms'; +import { TranslateDirective } from '../language/translate.directive'; +import { KeyValuePipe, NgClass } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; export enum CsvFieldSeparator { TAB = '\t', @@ -33,8 +38,25 @@ export interface CsvExportOptions { selector: 'jhi-csv-export-modal', templateUrl: './export-modal.component.html', styleUrls: ['./export-modal.component.scss'], + imports: [ + FormsModule, + TranslateDirective, + NgbNav, + NgbNavItem, + NgbNavLink, + NgbNavLinkBase, + NgbNavContent, + NgClass, + NgbNavOutlet, + FaIconComponent, + KeyValuePipe, + ArtemisTranslatePipe, + ], }) export class ExportModalComponent implements OnInit { + private activeModal = inject(NgbActiveModal); + private translateService = inject(TranslateService); + readonly CsvFieldSeparator = CsvFieldSeparator; readonly CsvQuoteStrings = CsvQuoteStrings; readonly CsvDecimalSeparator = CsvDecimalSeparator; @@ -46,11 +68,6 @@ export class ExportModalComponent implements OnInit { faBan = faBan; faDownload = faDownload; - constructor( - private activeModal: NgbActiveModal, - private translateService: TranslateService, - ) {} - ngOnInit(): void { // set default csv export options based on the current language switch (this.translateService.currentLang) { diff --git a/src/main/webapp/app/shared/export/export.module.ts b/src/main/webapp/app/shared/export/export.module.ts index 19f79a14389e..939b5356f0cf 100644 --- a/src/main/webapp/app/shared/export/export.module.ts +++ b/src/main/webapp/app/shared/export/export.module.ts @@ -5,8 +5,7 @@ import { ArtemisSharedComponentModule } from 'app/shared/components/shared-compo import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; @NgModule({ - imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule], - declarations: [ExportModalComponent, ExportButtonComponent], + imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule, ExportModalComponent, ExportButtonComponent], exports: [ExportModalComponent, ExportButtonComponent], }) export class ExportModule {} diff --git a/src/main/webapp/app/shared/extension-point/extension-point.directive.ts b/src/main/webapp/app/shared/extension-point/extension-point.directive.ts index ce0fad03beb7..27296cda1632 100644 --- a/src/main/webapp/app/shared/extension-point/extension-point.directive.ts +++ b/src/main/webapp/app/shared/extension-point/extension-point.directive.ts @@ -1,4 +1,4 @@ -import { Directive, EmbeddedViewRef, Input, OnChanges, SimpleChanges, TemplateRef, ViewContainerRef } from '@angular/core'; +import { Directive, EmbeddedViewRef, Input, OnChanges, SimpleChanges, TemplateRef, ViewContainerRef, inject } from '@angular/core'; /** * @whatItDoes marks parts of a (parent) template as extendable to allow other (child) components to override them. @@ -27,16 +27,14 @@ import { Directive, EmbeddedViewRef, Input, OnChanges, SimpleChanges, TemplateRe */ @Directive({ selector: '[jhiExtensionPoint]' }) export class ExtensionPointDirective implements OnChanges { + private viewContainerRef = inject(ViewContainerRef); + private templateRef = inject>(TemplateRef); + private viewRef: EmbeddedViewRef | undefined = undefined; @Input() public jhiExtensionPoint: TemplateRef | undefined = undefined; @Input() public jhiExtensionPointContext?: any = undefined; - constructor( - private viewContainerRef: ViewContainerRef, - private templateRef: TemplateRef, - ) {} - ngOnChanges(changes: SimpleChanges) { if (changes['jhiExtensionPoint']) { const viewContainerRef = this.viewContainerRef; diff --git a/src/main/webapp/app/shared/feature-toggle/feature-toggle-hide.directive.ts b/src/main/webapp/app/shared/feature-toggle/feature-toggle-hide.directive.ts index e77255d5bca5..9a17d2c0f6b6 100644 --- a/src/main/webapp/app/shared/feature-toggle/feature-toggle-hide.directive.ts +++ b/src/main/webapp/app/shared/feature-toggle/feature-toggle-hide.directive.ts @@ -1,19 +1,17 @@ -import { Directive, HostBinding, Input, OnDestroy, OnInit } from '@angular/core'; +import { Directive, HostBinding, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { FeatureToggle, FeatureToggleService } from 'app/shared/feature-toggle/feature-toggle.service'; import { Subscription } from 'rxjs/internal/Subscription'; -@Directive({ - selector: '[jhiFeatureToggleHide]', -}) +@Directive({ selector: '[jhiFeatureToggleHide]' }) export class FeatureToggleHideDirective implements OnInit, OnDestroy { + private featureToggleService = inject(FeatureToggleService); + @Input('jhiFeatureToggleHide') feature?: FeatureToggle; private featureActive = true; private featureToggleActiveSubscription: Subscription; - constructor(private featureToggleService: FeatureToggleService) {} - ngOnInit() { if (this.feature) { this.featureToggleActiveSubscription = this.featureToggleService.getFeatureToggleActive(this.feature).subscribe((active) => { diff --git a/src/main/webapp/app/shared/feature-toggle/feature-toggle-link.directive.ts b/src/main/webapp/app/shared/feature-toggle/feature-toggle-link.directive.ts index f29b25e1792e..26e8de642d86 100644 --- a/src/main/webapp/app/shared/feature-toggle/feature-toggle-link.directive.ts +++ b/src/main/webapp/app/shared/feature-toggle/feature-toggle-link.directive.ts @@ -1,12 +1,12 @@ -import { Directive, HostBinding, Input, OnDestroy, OnInit } from '@angular/core'; +import { Directive, HostBinding, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { FeatureToggle, FeatureToggleService } from 'app/shared/feature-toggle/feature-toggle.service'; import { tap } from 'rxjs/operators'; import { Subscription } from 'rxjs'; -@Directive({ - selector: '[jhiFeatureToggleLink]', -}) +@Directive({ selector: '[jhiFeatureToggleLink]' }) export class FeatureToggleLinkDirective implements OnInit, OnDestroy { + private featureToggleService = inject(FeatureToggleService); + @Input('jhiFeatureToggleLink') feature: FeatureToggle; /** * This input must be used to overwrite the disabled state given that the feature toggle is inactive. @@ -23,8 +23,6 @@ export class FeatureToggleLinkDirective implements OnInit, OnDestroy { private featureToggleActiveSubscription: Subscription; - constructor(private featureToggleService: FeatureToggleService) {} - /** * Life cycle hook called by Angular to indicate that Angular is done creating the component */ diff --git a/src/main/webapp/app/shared/feature-toggle/feature-toggle.directive.ts b/src/main/webapp/app/shared/feature-toggle/feature-toggle.directive.ts index 3a8d02976f44..dffc86cbe69a 100644 --- a/src/main/webapp/app/shared/feature-toggle/feature-toggle.directive.ts +++ b/src/main/webapp/app/shared/feature-toggle/feature-toggle.directive.ts @@ -1,12 +1,12 @@ -import { Directive, HostBinding, Input, OnDestroy, OnInit } from '@angular/core'; +import { Directive, HostBinding, Input, OnDestroy, OnInit, inject } from '@angular/core'; import { FeatureToggle, FeatureToggleService } from 'app/shared/feature-toggle/feature-toggle.service'; import { tap } from 'rxjs/operators'; import { Subscription } from 'rxjs'; -@Directive({ - selector: '[jhiFeatureToggle]', -}) +@Directive({ selector: '[jhiFeatureToggle]' }) export class FeatureToggleDirective implements OnInit, OnDestroy { + private featureToggleService = inject(FeatureToggleService); + @Input('jhiFeatureToggle') features: FeatureToggle | FeatureToggle[]; /** * This input must be used to overwrite the disabled state given that the feature toggle is inactive. @@ -23,8 +23,6 @@ export class FeatureToggleDirective implements OnInit, OnDestroy { private featureToggleActiveSubscription: Subscription; - constructor(private featureToggleService: FeatureToggleService) {} - /** * Life cycle hook called by Angular to indicate that Angular is done creating the component */ diff --git a/src/main/webapp/app/shared/feature-toggle/feature-toggle.module.ts b/src/main/webapp/app/shared/feature-toggle/feature-toggle.module.ts deleted file mode 100644 index 64b19d937f81..000000000000 --- a/src/main/webapp/app/shared/feature-toggle/feature-toggle.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { NgModule } from '@angular/core'; -import { FeatureToggleDirective } from 'app/shared/feature-toggle/feature-toggle.directive'; -import { FeatureToggleLinkDirective } from 'app/shared/feature-toggle/feature-toggle-link.directive'; -import { FeatureToggleHideDirective } from 'app/shared/feature-toggle/feature-toggle-hide.directive'; - -@NgModule({ - declarations: [FeatureToggleDirective, FeatureToggleLinkDirective, FeatureToggleHideDirective], - exports: [FeatureToggleDirective, FeatureToggleLinkDirective, FeatureToggleHideDirective], -}) -export class FeatureToggleModule {} diff --git a/src/main/webapp/app/shared/feature-toggle/feature-toggle.service.ts b/src/main/webapp/app/shared/feature-toggle/feature-toggle.service.ts index 43cc4ce4d6b5..283f60e2d313 100644 --- a/src/main/webapp/app/shared/feature-toggle/feature-toggle.service.ts +++ b/src/main/webapp/app/shared/feature-toggle/feature-toggle.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; import { distinctUntilChanged, map, tap } from 'rxjs/operators'; @@ -25,14 +25,14 @@ const defaultActiveFeatureState: ActiveFeatureToggles = Object.values(FeatureTog @Injectable({ providedIn: 'root' }) export class FeatureToggleService { + private websocketService = inject(JhiWebsocketService); + private http = inject(HttpClient); + private readonly TOPIC = `/topic/management/feature-toggles`; private subject: BehaviorSubject; private subscriptionInitialized = false; - constructor( - private websocketService: JhiWebsocketService, - private http: HttpClient, - ) { + constructor() { this.subject = new BehaviorSubject(defaultActiveFeatureState); } diff --git a/src/main/webapp/app/shared/fingerprint/browser-fingerprint.service.ts b/src/main/webapp/app/shared/fingerprint/browser-fingerprint.service.ts index 1cd278a86da9..8088c0b38320 100644 --- a/src/main/webapp/app/shared/fingerprint/browser-fingerprint.service.ts +++ b/src/main/webapp/app/shared/fingerprint/browser-fingerprint.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { LocalStorageService } from 'ngx-webstorage'; import FingerprintJS, { GetResult } from '@fingerprintjs/fingerprintjs'; @@ -6,13 +6,13 @@ import { v4 as uuid } from 'uuid'; @Injectable({ providedIn: 'root' }) export class BrowserFingerprintService { + private localStorage = inject(LocalStorageService); + private readonly BROWSER_INSTANCE_KEY = 'instanceIdentifier'; public fingerprint = new BehaviorSubject(undefined); public instanceIdentifier = new BehaviorSubject(undefined); - constructor(private localStorage: LocalStorageService) {} - public initialize(browserFingerprintsEnabled: boolean | undefined) { // If undefined, still enable it to not break older configurations without the field in profile info if (browserFingerprintsEnabled !== false) { diff --git a/src/main/webapp/app/shared/fireworks/fireworks.module.ts b/src/main/webapp/app/shared/fireworks/fireworks.module.ts deleted file mode 100644 index cfb28a586b87..000000000000 --- a/src/main/webapp/app/shared/fireworks/fireworks.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FireworksComponent } from 'app/shared/fireworks/fireworks.component'; - -@NgModule({ - imports: [CommonModule], - declarations: [FireworksComponent], - exports: [FireworksComponent], -}) -export class FireworksModule {} diff --git a/src/main/webapp/app/shared/form/title-channel-name/title-channel-name.component.ts b/src/main/webapp/app/shared/form/title-channel-name/title-channel-name.component.ts index b7f139bc5182..47ea9fd3f883 100644 --- a/src/main/webapp/app/shared/form/title-channel-name/title-channel-name.component.ts +++ b/src/main/webapp/app/shared/form/title-channel-name/title-channel-name.component.ts @@ -1,12 +1,16 @@ import { AfterViewInit, Component, Input, OnDestroy, OnInit, ViewChild, computed, effect, input, output, signal, viewChild } from '@angular/core'; -import { ControlContainer, NgForm, NgModel } from '@angular/forms'; +import { ControlContainer, FormsModule, NgForm, NgModel } from '@angular/forms'; import { Subject, Subscription } from 'rxjs'; import { ProgrammingExerciseInputField } from 'app/exercises/programming/manage/update/programming-exercise-update.helper'; +import { TranslateDirective } from '../../language/translate.directive'; +import { CustomNotIncludedInValidatorDirective } from '../../validators/custom-not-included-in-validator.directive'; +import { HelpIconComponent } from '../../components/help-icon.component'; @Component({ selector: 'jhi-title-channel-name', templateUrl: './title-channel-name.component.html', viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], + imports: [TranslateDirective, FormsModule, CustomNotIncludedInValidatorDirective, HelpIconComponent], }) export class TitleChannelNameComponent implements AfterViewInit, OnDestroy, OnInit { @Input() title?: string; diff --git a/src/main/webapp/app/shared/form/title-channel-name/title-channel-name.module.ts b/src/main/webapp/app/shared/form/title-channel-name/title-channel-name.module.ts index 70849d7bf364..a45e45df2530 100644 --- a/src/main/webapp/app/shared/form/title-channel-name/title-channel-name.module.ts +++ b/src/main/webapp/app/shared/form/title-channel-name/title-channel-name.module.ts @@ -7,8 +7,7 @@ import { CustomNotIncludedInValidatorDirective } from 'app/shared/validators/cus import { TranslateDirective } from 'app/shared/language/translate.directive'; @NgModule({ - imports: [FormsModule, CommonModule, ArtemisSharedComponentModule, CustomNotIncludedInValidatorDirective, TranslateDirective], - declarations: [TitleChannelNameComponent], + imports: [FormsModule, CommonModule, ArtemisSharedComponentModule, CustomNotIncludedInValidatorDirective, TranslateDirective, TitleChannelNameComponent], exports: [TitleChannelNameComponent], }) export class TitleChannelNameModule {} diff --git a/src/main/webapp/app/shared/fullscreen/fullscreen.component.ts b/src/main/webapp/app/shared/fullscreen/fullscreen.component.ts index fdcf2046080b..f81b5459bf10 100644 --- a/src/main/webapp/app/shared/fullscreen/fullscreen.component.ts +++ b/src/main/webapp/app/shared/fullscreen/fullscreen.component.ts @@ -1,13 +1,19 @@ -import { Component, ElementRef, Input } from '@angular/core'; +import { Component, ElementRef, Input, inject } from '@angular/core'; import { faCompress } from '@fortawesome/free-solid-svg-icons'; import { enterFullscreen, exitFullscreen, isFullScreen } from 'app/shared/util/fullscreen.util'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { ArtemisTranslatePipe } from '../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-fullscreen', templateUrl: './fullscreen.component.html', styleUrls: ['./fullscreen.scss'], + imports: [NgbTooltip, FaIconComponent, ArtemisTranslatePipe], }) export class FullscreenComponent { + private fullScreenWrapper = inject(ElementRef); + @Input() position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' = 'top-right'; @@ -17,8 +23,6 @@ export class FullscreenComponent { // Icons faCompress = faCompress; - constructor(private fullScreenWrapper: ElementRef) {} - /** * check current state and toggle fullscreen */ diff --git a/src/main/webapp/app/shared/fullscreen/fullscreen.module.ts b/src/main/webapp/app/shared/fullscreen/fullscreen.module.ts index db982626257d..29d28ad26f97 100644 --- a/src/main/webapp/app/shared/fullscreen/fullscreen.module.ts +++ b/src/main/webapp/app/shared/fullscreen/fullscreen.module.ts @@ -3,8 +3,7 @@ import { NgModule } from '@angular/core'; import { ArtemisSharedModule } from 'app/shared/shared.module'; @NgModule({ - imports: [ArtemisSharedModule], - declarations: [FullscreenComponent], + imports: [ArtemisSharedModule, FullscreenComponent], exports: [FullscreenComponent], }) export class ArtemisFullscreenModule {} diff --git a/src/main/webapp/app/shared/grading-instruction-link-icon/grading-instruction-link-icon.component.ts b/src/main/webapp/app/shared/grading-instruction-link-icon/grading-instruction-link-icon.component.ts index 5702a3ce76c7..3147e1f0d1b6 100644 --- a/src/main/webapp/app/shared/grading-instruction-link-icon/grading-instruction-link-icon.component.ts +++ b/src/main/webapp/app/shared/grading-instruction-link-icon/grading-instruction-link-icon.component.ts @@ -1,22 +1,27 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { GradingInstruction } from 'app/exercises/shared/structured-grading-criterion/grading-instruction.model'; import { Feedback } from 'app/entities/feedback.model'; import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; import { faLink, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { NgClass } from '@angular/common'; @Component({ selector: 'jhi-grading-instruction-link-icon', templateUrl: './grading-instruction-link-icon.component.html', + imports: [FaIconComponent, NgbTooltip, NgClass, ArtemisTranslatePipe], }) export class GradingInstructionLinkIconComponent implements OnInit { + private artemisTranslatePipe = inject(ArtemisTranslatePipe); + @Input() linkIcon = faLink; @Input() feedback: Feedback; + instruction: GradingInstruction | undefined; confirmIcon = faTrash; showConfirm = false; - constructor(private artemisTranslatePipe: ArtemisTranslatePipe) {} - ngOnInit(): void { this.instruction = this.feedback.gradingInstruction; } diff --git a/src/main/webapp/app/shared/grading-instruction-link-icon/grading-instruction-link-icon.module.ts b/src/main/webapp/app/shared/grading-instruction-link-icon/grading-instruction-link-icon.module.ts index 2225649438f7..46a830041367 100644 --- a/src/main/webapp/app/shared/grading-instruction-link-icon/grading-instruction-link-icon.module.ts +++ b/src/main/webapp/app/shared/grading-instruction-link-icon/grading-instruction-link-icon.module.ts @@ -4,8 +4,7 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; import { GradingInstructionLinkIconComponent } from 'app/shared/grading-instruction-link-icon/grading-instruction-link-icon.component'; @NgModule({ - imports: [ArtemisSharedModule], - declarations: [GradingInstructionLinkIconComponent], + imports: [ArtemisSharedModule, GradingInstructionLinkIconComponent], exports: [GradingInstructionLinkIconComponent], }) export class ArtemisGradingInstructionLinkIconModule {} diff --git a/src/main/webapp/app/shared/guard/pending-changes.guard.ts b/src/main/webapp/app/shared/guard/pending-changes.guard.ts index 294023cd6e42..34332f264bdf 100644 --- a/src/main/webapp/app/shared/guard/pending-changes.guard.ts +++ b/src/main/webapp/app/shared/guard/pending-changes.guard.ts @@ -1,11 +1,11 @@ import { CanDeactivate } from '@angular/router'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { ComponentCanDeactivate } from 'app/shared/guard/can-deactivate.model'; @Injectable({ providedIn: 'root' }) export class PendingChangesGuard implements CanDeactivate { - constructor(private translateService: TranslateService) {} + private translateService = inject(TranslateService); /** * Function which returns whether a component can be deactivated diff --git a/src/main/webapp/app/shared/http/file.service.ts b/src/main/webapp/app/shared/http/file.service.ts index f739c44014ed..e4beba479b45 100644 --- a/src/main/webapp/app/shared/http/file.service.ts +++ b/src/main/webapp/app/shared/http/file.service.ts @@ -1,5 +1,5 @@ import { HttpClient, HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { lastValueFrom } from 'rxjs'; import { v4 as uuid } from 'uuid'; import { Observable } from 'rxjs'; @@ -8,10 +8,9 @@ import { ProgrammingLanguage, ProjectType } from 'app/entities/programming/progr @Injectable({ providedIn: 'root' }) export class FileService { + private http = inject(HttpClient); private resourceUrl = 'api/files'; - constructor(private http: HttpClient) {} - /** * Fetches the template file for the given programming language * @param {ProgrammingLanguage} language diff --git a/src/main/webapp/app/shared/http/secure-link.directive.ts b/src/main/webapp/app/shared/http/secure-link.directive.ts index 8dbc4d75ac03..7253670e0bb3 100644 --- a/src/main/webapp/app/shared/http/secure-link.directive.ts +++ b/src/main/webapp/app/shared/http/secure-link.directive.ts @@ -1,13 +1,13 @@ -import { Directive, ElementRef } from '@angular/core'; +import { Directive, ElementRef, inject } from '@angular/core'; /** * Avoid Reverse Tabnabbing vulnerability: https://www.owasp.org/index.php/Reverse_Tabnabbing. */ -@Directive({ - selector: '[jhiSecureLink]', -}) +@Directive({ selector: '[jhiSecureLink]' }) export class SecureLinkDirective { - constructor(el: ElementRef) { + constructor() { + const el = inject(ElementRef); + el.nativeElement.target = '_blank'; el.nativeElement.rel = 'noopener noreferrer'; } diff --git a/src/main/webapp/app/shared/icon-card/icon-card.component.ts b/src/main/webapp/app/shared/icon-card/icon-card.component.ts index dc0c603000a2..a2222eaa8f7d 100644 --- a/src/main/webapp/app/shared/icon-card/icon-card.component.ts +++ b/src/main/webapp/app/shared/icon-card/icon-card.component.ts @@ -8,7 +8,6 @@ import { ArtemisSharedPipesModule } from 'app/shared/pipes/shared-pipes.module'; selector: 'jhi-icon-card', templateUrl: './icon-card.component.html', styleUrl: './icon-card.component.scss', - standalone: true, imports: [ArtemisSharedCommonModule, ArtemisSharedPipesModule], }) export class IconCardComponent { diff --git a/src/main/webapp/app/shared/image-cropper/component/image-cropper.component.ts b/src/main/webapp/app/shared/image-cropper/component/image-cropper.component.ts index b9d50c821e92..bc8fb40ba3a5 100644 --- a/src/main/webapp/app/shared/image-cropper/component/image-cropper.component.ts +++ b/src/main/webapp/app/shared/image-cropper/component/image-cropper.component.ts @@ -12,6 +12,7 @@ import { Output, SimpleChanges, ViewChild, + inject, } from '@angular/core'; import { DomSanitizer, SafeStyle, SafeUrl } from '@angular/platform-browser'; import { OutputFormat } from '../interfaces/cropper-options.interface'; @@ -31,13 +32,18 @@ import { ImageCroppedEvent } from 'app/shared/image-cropper/interfaces/image-cro // Note: Partially adapted to fit Artemis needs @Component({ - // eslint-disable-next-line @angular-eslint/component-selector selector: 'image-cropper', templateUrl: './image-cropper.component.html', styleUrls: ['./image-cropper.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) export class ImageCropperComponent implements OnChanges, OnInit { + private cropService = inject(CropService); + private cropperPositionService = inject(CropperPositionService); + private loadImageService = inject(LoadImageService); + private sanitizer = inject(DomSanitizer); + private changeDetector = inject(ChangeDetectorRef); + settings = new CropperSettings(); setImageMaxSizeRetries = 0; moveStart: MoveStart; @@ -98,13 +104,7 @@ export class ImageCropperComponent implements OnChanges, OnInit { @Output() cropperReady = new EventEmitter(); @Output() loadImageFailed = new EventEmitter(); - constructor( - private cropService: CropService, - private cropperPositionService: CropperPositionService, - private loadImageService: LoadImageService, - private sanitizer: DomSanitizer, - private changeDetector: ChangeDetectorRef, - ) { + constructor() { this.reset(); } diff --git a/src/main/webapp/app/shared/image-cropper/image-cropper.module.ts b/src/main/webapp/app/shared/image-cropper/image-cropper.module.ts deleted file mode 100644 index 157ca1d3c2dc..000000000000 --- a/src/main/webapp/app/shared/image-cropper/image-cropper.module.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { ImageCropperComponent } from './component/image-cropper.component'; - -@NgModule({ - imports: [CommonModule], - declarations: [ImageCropperComponent], - exports: [ImageCropperComponent], -}) -export class ImageCropperModule {} diff --git a/src/main/webapp/app/shared/image/cacheable-image.service.ts b/src/main/webapp/app/shared/image/cacheable-image.service.ts index d6e0341a115f..159edc2e8965 100644 --- a/src/main/webapp/app/shared/image/cacheable-image.service.ts +++ b/src/main/webapp/app/shared/image/cacheable-image.service.ts @@ -1,4 +1,4 @@ -import { Injectable, OnDestroy } from '@angular/core'; +import { Injectable, OnDestroy, inject } from '@angular/core'; import { Cacheable, LocalStorageStrategy } from 'ts-cacheable'; import { HttpClient } from '@angular/common/http'; import { Observable, Subject, Subscription, UnaryFunction, pipe } from 'rxjs'; @@ -29,12 +29,12 @@ export interface ICacheableImageService { @Injectable({ providedIn: 'root' }) export class CacheableImageService implements ICacheableImageService, OnDestroy { + private accountService = inject(AccountService); + private httpClient = inject(HttpClient); + private userChangeSubscription: Subscription; - constructor( - private accountService: AccountService, - private httpClient: HttpClient, - ) { + constructor() { this.init(); } diff --git a/src/main/webapp/app/shared/image/secured-image.component.ts b/src/main/webapp/app/shared/image/secured-image.component.ts index c8390288cba2..aad048ee2a99 100644 --- a/src/main/webapp/app/shared/image/secured-image.component.ts +++ b/src/main/webapp/app/shared/image/secured-image.component.ts @@ -1,9 +1,10 @@ -import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; +import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, inject } from '@angular/core'; import { BehaviorSubject, Observable, isObservable, of } from 'rxjs'; import { catchError, filter, map, switchMap, tap } from 'rxjs/operators'; import { DomSanitizer } from '@angular/platform-browser'; import { CacheableImageService } from 'app/shared/image/cacheable-image.service'; import { base64StringToBlob } from 'app/utils/blob-util'; +import { AsyncPipe } from '@angular/common'; // Status that is emitted to the client to describe the loading status of the picture export const enum ImageLoadingStatus { @@ -36,8 +37,13 @@ export enum CachingStrategy { alt } `, + imports: [AsyncPipe], }) export class SecuredImageComponent implements OnChanges, OnInit { + private domSanitizer = inject(DomSanitizer); + private cacheableImageService = inject(CacheableImageService); + element = inject(ElementRef); + // This part just creates an rxjs stream from the src // this makes sure that we can handle it when the src changes // or even when the component gets destroyed @@ -69,11 +75,6 @@ export class SecuredImageComponent implements OnChanges, OnInit { } // we need HttpClient to load the image and DomSanitizer to trust the url - constructor( - private domSanitizer: DomSanitizer, - private cacheableImageService: CacheableImageService, - public element: ElementRef, - ) {} // triggers the reload of the picture when the user clicks on a button retryLoadImage() { diff --git a/src/main/webapp/app/shared/import-list/import-table.component.ts b/src/main/webapp/app/shared/import-list/import-table.component.ts index 2a0a3ee92269..70aa1aac4fcb 100644 --- a/src/main/webapp/app/shared/import-list/import-table.component.ts +++ b/src/main/webapp/app/shared/import-list/import-table.component.ts @@ -8,6 +8,7 @@ import { onError } from 'app/shared/util/global.utils'; import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; import { faSort, faSortDown, faSortUp, faSpinner } from '@fortawesome/free-solid-svg-icons'; import { BaseApiHttpService } from 'app/course/learning-paths/services/base-api-http.service'; +import { NgbPagination } from '@ng-bootstrap/ng-bootstrap'; /** * An abstract component intended for cases where a resource needs to be imported from one course into another. @@ -21,8 +22,7 @@ export type Column = { @Component({ selector: 'jhi-import-table', - standalone: true, - imports: [ArtemisSharedCommonModule], + imports: [ArtemisSharedCommonModule, NgbPagination], templateUrl: './import-table.component.html', styleUrl: './import-table.component.scss', }) @@ -37,9 +37,9 @@ export class ImportTableComponent { private readonly alertService = inject(AlertService); private readonly pagingService = inject(PagingService); - readonly columns = input.required[]>(); + columns = input.required[]>(); readonly columnBaseTranslationKey = input.required(); - readonly disabledIds = input([]); + disabledIds = input([]); readonly numberOfColumns = computed(() => this.columns().length + 2); readonly onRowSelection = output(); diff --git a/src/main/webapp/app/shared/import/import.component.ts b/src/main/webapp/app/shared/import/import.component.ts index d8440b6a57d9..abf4a5f3b94d 100644 --- a/src/main/webapp/app/shared/import/import.component.ts +++ b/src/main/webapp/app/shared/import/import.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnInit, inject } from '@angular/core'; import { Router } from '@angular/router'; import { faCheck, faSort } from '@fortawesome/free-solid-svg-icons'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; @@ -19,8 +19,14 @@ export type Column = { getProperty(entity: T): string | undefined; }; -@Component({ template: '' }) +@Component({ + template: '', +}) export abstract class ImportComponent implements OnInit { + protected router = inject(Router); + private sortService = inject(SortService); + protected activeModal = inject(NgbActiveModal); + loading = false; content: SearchResult; total = 0; @@ -44,12 +50,7 @@ export abstract class ImportComponent implements OnInit { protected readonly search = new Subject(); protected readonly sort = new Subject(); - protected constructor( - protected router: Router, - private sortService: SortService, - protected activeModal: NgbActiveModal, - protected pagingService?: PagingService, - ) {} + protected constructor(protected pagingService?: PagingService) {} get page(): number { return this.state.page; @@ -106,11 +107,11 @@ export abstract class ImportComponent implements OnInit { * Gives the ID for any item in the table, so that it can be tracked/identified by ngFor * * @template T - * @param index The index of the element in the ngFor + * @param _index The index of the element in the ngFor * @param {T} item The item itself * @returns The ID of the item */ - trackId(index: number, item: T): number { + trackId(_index: number, item: T): number { return item.id!; } diff --git a/src/main/webapp/app/shared/info-panel/info-panel.component.ts b/src/main/webapp/app/shared/info-panel/info-panel.component.ts index 617fc3e63c0a..c12faca7744d 100644 --- a/src/main/webapp/app/shared/info-panel/info-panel.component.ts +++ b/src/main/webapp/app/shared/info-panel/info-panel.component.ts @@ -8,6 +8,4 @@ import { Component, Input } from '@angular/core'; export class InfoPanelComponent { @Input() panelHeader: string; @Input() panelDescriptionHeader: string; - - constructor() {} } diff --git a/src/main/webapp/app/shared/info-panel/info-panel.module.ts b/src/main/webapp/app/shared/info-panel/info-panel.module.ts index ab86f1339853..0411c3dbf043 100644 --- a/src/main/webapp/app/shared/info-panel/info-panel.module.ts +++ b/src/main/webapp/app/shared/info-panel/info-panel.module.ts @@ -4,8 +4,7 @@ import { ArtemisSharedModule } from 'app/shared/shared.module'; import { InfoPanelComponent } from './info-panel.component'; @NgModule({ - imports: [ArtemisSharedModule], - declarations: [InfoPanelComponent], + imports: [ArtemisSharedModule, InfoPanelComponent], exports: [InfoPanelComponent], }) export class ArtemisInfoPanelModule {} diff --git a/src/main/webapp/app/shared/information-box/information-box.component.ts b/src/main/webapp/app/shared/information-box/information-box.component.ts index 5be6212f7277..c4ed7d387507 100644 --- a/src/main/webapp/app/shared/information-box/information-box.component.ts +++ b/src/main/webapp/app/shared/information-box/information-box.component.ts @@ -42,7 +42,6 @@ export interface StringNumberContent { export type InformationBoxContent = StudentExamContent | DateContent | ExerciseContent | DifficultyLevelContent | StringNumberContent; @Component({ - standalone: true, imports: [ArtemisSharedModule, ArtemisSharedComponentModule], selector: 'jhi-information-box', templateUrl: './information-box.component.html', diff --git a/src/main/webapp/app/shared/language/translate.directive.ts b/src/main/webapp/app/shared/language/translate.directive.ts index cb40182df64f..bd46673c6733 100644 --- a/src/main/webapp/app/shared/language/translate.directive.ts +++ b/src/main/webapp/app/shared/language/translate.directive.ts @@ -1,4 +1,4 @@ -import { Directive, ElementRef, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; +import { Directive, ElementRef, Input, OnChanges, OnDestroy, OnInit, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { translationNotFoundMessage } from 'app/core/config/translation.config'; import { Subject } from 'rxjs'; @@ -9,19 +9,16 @@ import { takeUntil } from 'rxjs/operators'; */ @Directive({ selector: '[jhiTranslate]', - standalone: true, }) export class TranslateDirective implements OnChanges, OnInit, OnDestroy { + private el = inject(ElementRef); + private translateService = inject(TranslateService); + @Input() jhiTranslate!: string; @Input() translateValues?: { [key: string]: unknown }; private readonly directiveDestroyed = new Subject(); - constructor( - private el: ElementRef, - private translateService: TranslateService, - ) {} - ngOnInit(): void { this.translateService.onLangChange.pipe(takeUntil(this.directiveDestroyed)).subscribe(() => { this.getTranslation(); diff --git a/src/main/webapp/app/shared/layouts/error/error.component.ts b/src/main/webapp/app/shared/layouts/error/error.component.ts index d6a2dd358cc3..f408c980c7fa 100644 --- a/src/main/webapp/app/shared/layouts/error/error.component.ts +++ b/src/main/webapp/app/shared/layouts/error/error.component.ts @@ -1,17 +1,19 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; +import { TranslateDirective } from '../../language/translate.directive'; @Component({ selector: 'jhi-error', templateUrl: './error.component.html', + imports: [TranslateDirective], }) export class ErrorComponent implements OnInit { + private route = inject(ActivatedRoute); + errorMessage: string; error403: boolean; error404: boolean; - constructor(private route: ActivatedRoute) {} - ngOnInit() { this.route.data.subscribe((routeData) => { if (routeData.error403) { diff --git a/src/main/webapp/app/shared/layouts/error/error.route.ts b/src/main/webapp/app/shared/layouts/error/error.route.ts index ac642f572bff..67e1e2ad0bea 100644 --- a/src/main/webapp/app/shared/layouts/error/error.route.ts +++ b/src/main/webapp/app/shared/layouts/error/error.route.ts @@ -1,12 +1,9 @@ import { Routes } from '@angular/router'; -import { ErrorComponent } from './error.component'; -import { OrionOutdatedComponent } from 'app/shared/orion/outdated-plugin-warning/orion-outdated.component'; - export const errorRoute: Routes = [ { path: 'error', - component: ErrorComponent, + loadComponent: () => import('./error.component').then((m) => m.ErrorComponent), data: { authorities: [], pageTitle: 'error.title', @@ -14,7 +11,7 @@ export const errorRoute: Routes = [ }, { path: 'accessdenied', - component: ErrorComponent, + loadComponent: () => import('./error.component').then((m) => m.ErrorComponent), data: { authorities: [], pageTitle: 'error.title', @@ -23,7 +20,7 @@ export const errorRoute: Routes = [ }, { path: 'orion-outdated', - component: OrionOutdatedComponent, + loadComponent: () => import('app/shared/orion/outdated-plugin-warning/orion-outdated.component').then((m) => m.OrionOutdatedComponent), data: { authorities: [], pageTitle: 'Outdated Orion Version', diff --git a/src/main/webapp/app/shared/layouts/footer/footer.component.ts b/src/main/webapp/app/shared/layouts/footer/footer.component.ts index 84aec9857263..64cc8e3420b0 100644 --- a/src/main/webapp/app/shared/layouts/footer/footer.component.ts +++ b/src/main/webapp/app/shared/layouts/footer/footer.component.ts @@ -1,12 +1,18 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; +import { TranslateDirective } from '../../language/translate.directive'; +import { RouterLink } from '@angular/router'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-footer', templateUrl: './footer.component.html', styleUrls: ['./footer.scss'], + imports: [TranslateDirective, RouterLink, ArtemisTranslatePipe], }) export class FooterComponent implements OnInit { + private profileService = inject(ProfileService); + readonly RELEASE_URL = 'https://github.com/ls1intum/Artemis/releases'; readonly FEEDBACK_URL = 'https://github.com/ls1intum/Artemis/issues/new/choose'; @@ -18,8 +24,6 @@ export class FooterComponent implements OnInit { isTestServer: boolean; isProduction: boolean; - constructor(private profileService: ProfileService) {} - ngOnInit(): void { this.profileService.getProfileInfo().subscribe((profileInfo) => { this.contact = profileInfo.contact; diff --git a/src/main/webapp/app/shared/layouts/navbar/active-menu.directive.ts b/src/main/webapp/app/shared/layouts/navbar/active-menu.directive.ts index de4296e68ebb..41d8a8ae10f2 100644 --- a/src/main/webapp/app/shared/layouts/navbar/active-menu.directive.ts +++ b/src/main/webapp/app/shared/layouts/navbar/active-menu.directive.ts @@ -1,17 +1,13 @@ -import { Directive, ElementRef, Input, OnInit, Renderer2 } from '@angular/core'; +import { Directive, ElementRef, Input, OnInit, Renderer2, inject } from '@angular/core'; import { LangChangeEvent, TranslateService } from '@ngx-translate/core'; -@Directive({ - selector: '[jhiActiveMenu]', -}) +@Directive({ selector: '[jhiActiveMenu]' }) export class ActiveMenuDirective implements OnInit { - @Input() jhiActiveMenu: string; + private element = inject(ElementRef); + private renderer = inject(Renderer2); + private translateService = inject(TranslateService); - constructor( - private element: ElementRef, - private renderer: Renderer2, - private translateService: TranslateService, - ) {} + @Input() jhiActiveMenu: string; ngOnInit() { this.translateService.onLangChange.subscribe((event: LangChangeEvent) => { diff --git a/src/main/webapp/app/shared/layouts/navbar/entity-title.service.ts b/src/main/webapp/app/shared/layouts/navbar/entity-title.service.ts index 3ab54964001f..938562e912a4 100644 --- a/src/main/webapp/app/shared/layouts/navbar/entity-title.service.ts +++ b/src/main/webapp/app/shared/layouts/navbar/entity-title.service.ts @@ -1,5 +1,5 @@ import { HttpClient, HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { captureException } from '@sentry/angular'; import { Exercise } from 'app/entities/exercise.model'; import { EMPTY, Observable, ReplaySubject, Subject } from 'rxjs'; @@ -22,9 +22,9 @@ const FETCH_FALLBACK_TIMEOUT = 3000; */ @Injectable({ providedIn: 'root' }) export class EntityTitleService { - private readonly titleSubjects = new Map; timeout?: ReturnType }>(); + private http = inject(HttpClient); - constructor(private http: HttpClient) {} + private readonly titleSubjects = new Map; timeout?: ReturnType }>(); /** * Returns an observable that will provide the title of the entity. diff --git a/src/main/webapp/app/shared/layouts/navbar/navbar.component.html b/src/main/webapp/app/shared/layouts/navbar/navbar.component.html index 209186817f17..e51a5a10990c 100644 --- a/src/main/webapp/app/shared/layouts/navbar/navbar.component.html +++ b/src/main/webapp/app/shared/layouts/navbar/navbar.component.html @@ -337,7 +337,7 @@
} - - @if (similarPosts.length > 0) { -
-
-
-
- -
-
-
- @for (post of similarPosts; track post; let i = $index) { -
- - @if (i < similarPosts.length - 1) { -
- } -
- } -
-
-
-
-
- } -
diff --git a/src/main/webapp/app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-create-edit-modal.component.ts b/src/main/webapp/app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-create-edit-modal.component.ts index c88234f1e65b..b01123d53dd9 100644 --- a/src/main/webapp/app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-create-edit-modal.component.ts +++ b/src/main/webapp/app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-create-edit-modal.component.ts @@ -1,17 +1,20 @@ import { Component, Input, OnChanges, OnInit } from '@angular/core'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { PostingButtonComponent } from 'app/shared/metis/posting-button/posting-button.component'; import { PostingCreateEditModalDirective } from 'app/shared/metis/posting-create-edit-modal/posting-create-edit-modal.directive'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { Post } from 'app/entities/metis/post.model'; -import { MetisService } from 'app/shared/metis/metis.service'; -import { FormBuilder, Validators } from '@angular/forms'; +import { FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; import { Lecture } from 'app/entities/lecture.model'; import { Exercise } from 'app/entities/exercise.model'; import { Course } from 'app/entities/course.model'; -import { Router } from '@angular/router'; import { faAngleDown, faAngleUp } from '@fortawesome/free-solid-svg-icons'; import { PageType, PostContentValidationPattern, PostTitleValidationPattern, PostingEditType } from 'app/shared/metis/metis.util'; import { Conversation } from 'app/entities/metis/conversation/conversation.model'; import { getAsChannelDTO } from 'app/entities/metis/conversation/channel.model'; +import { PostingMarkdownEditorComponent } from 'app/shared/metis/posting-markdown-editor/posting-markdown-editor.component'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { PostTagSelectorComponent } from './post-tag-selector/post-tag-selector.component'; const TITLE_MAX_LENGTH = 200; @@ -23,6 +26,16 @@ export interface ContextSelectorOption { selector: 'jhi-post-create-edit-modal', templateUrl: './post-create-edit-modal.component.html', styleUrls: ['../../metis.component.scss'], + imports: [ + FormsModule, + ReactiveFormsModule, + TranslateDirective, + HelpIconComponent, + PostTagSelectorComponent, + PostingMarkdownEditorComponent, + PostingButtonComponent, + ArtemisTranslatePipe, + ], }) export class PostCreateEditModalComponent extends PostingCreateEditModalDirective implements OnInit, OnChanges { @Input() isCommunicationPage: boolean; @@ -45,15 +58,6 @@ export class PostCreateEditModalComponent extends PostingCreateEditModalDirectiv faAngleUp = faAngleUp; faAngleDown = faAngleDown; - constructor( - protected metisService: MetisService, - protected modalService: NgbModal, - protected formBuilder: FormBuilder, - private router: Router, - ) { - super(metisService, modalService, formBuilder); - } - /** * on initialization: reset all input field of the modal, determine the post context; * subscribe to the form control changes of the context selector in order to show the Announcement info box on selection; diff --git a/src/main/webapp/app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-tag-selector/post-tag-selector.component.ts b/src/main/webapp/app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-tag-selector/post-tag-selector.component.ts index 15902d087305..5fd10b24fbef 100644 --- a/src/main/webapp/app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-tag-selector/post-tag-selector.component.ts +++ b/src/main/webapp/app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-tag-selector/post-tag-selector.component.ts @@ -1,18 +1,41 @@ -import { AfterContentChecked, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; +import { AfterContentChecked, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, ViewChild, inject } from '@angular/core'; import { Observable, Subscription, map, startWith } from 'rxjs'; import { MetisService } from 'app/shared/metis/metis.service'; import { COMMA, ENTER, TAB } from '@angular/cdk/keycodes'; -import { FormControl } from '@angular/forms'; -import { MatChipInputEvent } from '@angular/material/chips'; -import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; +import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { MatChipGrid, MatChipInput, MatChipInputEvent, MatChipRemove, MatChipRow } from '@angular/material/chips'; +import { MatAutocomplete, MatAutocompleteSelectedEvent, MatAutocompleteTrigger } from '@angular/material/autocomplete'; import { faTimes } from '@fortawesome/free-solid-svg-icons'; +import { MatFormField } from '@angular/material/form-field'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { MatOption } from '@angular/material/core'; +import { AsyncPipe } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-post-tag-selector', templateUrl: './post-tag-selector.component.html', styleUrls: ['./post-tag-selector.component.scss'], + imports: [ + MatFormField, + MatChipGrid, + MatChipRow, + MatChipRemove, + FaIconComponent, + FormsModule, + MatAutocompleteTrigger, + MatChipInput, + ReactiveFormsModule, + MatAutocomplete, + MatOption, + AsyncPipe, + ArtemisTranslatePipe, + ], }) export class PostTagSelectorComponent implements OnInit, OnChanges, OnDestroy, AfterContentChecked { + private metisService = inject(MetisService); + private changeDetector = inject(ChangeDetectorRef); + @Input() postTags?: string[]; @Output() postTagsChange = new EventEmitter(); @@ -30,11 +53,6 @@ export class PostTagSelectorComponent implements OnInit, OnChanges, OnDestroy, A // Icons faTimes = faTimes; - constructor( - private metisService: MetisService, - private changeDetector: ChangeDetectorRef, - ) {} - /** * on initialization: subscribes to existing post tags used in this course (will be shown in dropdown of tag selector), * copies the input post tags to string tags, so that they are shown in the selector diff --git a/src/main/webapp/app/shared/metis/posting-create-edit-modal/posting-create-edit-modal.directive.ts b/src/main/webapp/app/shared/metis/posting-create-edit-modal/posting-create-edit-modal.directive.ts index 9461099accd6..ab4c34dc9bf5 100644 --- a/src/main/webapp/app/shared/metis/posting-create-edit-modal/posting-create-edit-modal.directive.ts +++ b/src/main/webapp/app/shared/metis/posting-create-edit-modal/posting-create-edit-modal.directive.ts @@ -1,8 +1,5 @@ import { Directive, OnChanges, OnInit, TemplateRef, ViewChild } from '@angular/core'; -import { FormBuilder } from '@angular/forms'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { Posting } from 'app/entities/metis/posting.model'; -import { MetisService } from 'app/shared/metis/metis.service'; import { PostingCreateEditDirective } from 'app/shared/metis/posting-create-edit.directive'; @Directive() @@ -10,14 +7,6 @@ export abstract class PostingCreateEditModalDirective extends @ViewChild('postingEditor') postingEditor: TemplateRef; modalTitle: string; - protected constructor( - protected metisService: MetisService, - protected modalService: NgbModal, - protected formBuilder: FormBuilder, - ) { - super(metisService, modalService, formBuilder); - } - /** * on initialization: sets the content, and the modal title (edit or create) */ diff --git a/src/main/webapp/app/shared/metis/posting-create-edit.directive.ts b/src/main/webapp/app/shared/metis/posting-create-edit.directive.ts index 5d327cbe390e..13403a64e08a 100644 --- a/src/main/webapp/app/shared/metis/posting-create-edit.directive.ts +++ b/src/main/webapp/app/shared/metis/posting-create-edit.directive.ts @@ -1,4 +1,4 @@ -import { Directive, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core'; +import { Directive, EventEmitter, Input, OnChanges, OnInit, Output, inject } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { Posting } from 'app/entities/metis/posting.model'; @@ -12,6 +12,10 @@ const MAX_CONTENT_LENGTH = 5000; @Directive() export abstract class PostingCreateEditDirective implements OnInit, OnChanges { + protected metisService = inject(MetisService); + protected modalService = inject(NgbModal); + protected formBuilder = inject(FormBuilder); + @Input() posting: T; @Output() onCreate: EventEmitter = new EventEmitter(); @Output() isModalOpen = new EventEmitter(); @@ -22,13 +26,8 @@ export abstract class PostingCreateEditDirective implements O editorHeight = MarkdownEditorHeight.INLINE; content: string; formGroup: FormGroup; - readonly EditType = PostingEditType; - protected constructor( - protected metisService: MetisService, - protected modalService: NgbModal, - protected formBuilder: FormBuilder, - ) {} + readonly EditType = PostingEditType; get editType(): PostingEditType { return this.posting.id ? PostingEditType.UPDATE : PostingEditType.CREATE; diff --git a/src/main/webapp/app/shared/metis/posting-footer/posting-footer.component.ts b/src/main/webapp/app/shared/metis/posting-footer/posting-footer.component.ts index ae10785f2ff9..af14fe112083 100644 --- a/src/main/webapp/app/shared/metis/posting-footer/posting-footer.component.ts +++ b/src/main/webapp/app/shared/metis/posting-footer/posting-footer.component.ts @@ -7,6 +7,8 @@ import { AnswerPost } from 'app/entities/metis/answer-post.model'; import dayjs from 'dayjs/esm'; import { User } from 'app/core/user/user.model'; import { Posting } from 'app/entities/metis/posting.model'; +import { AnswerPostComponent } from '../answer-post/answer-post.component'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; interface PostGroup { author: User | undefined; @@ -16,6 +18,7 @@ interface PostGroup { @Component({ selector: 'jhi-posting-footer', templateUrl: './posting-footer.component.html', + imports: [AnswerPostComponent, AnswerPostCreateEditModalComponent, ArtemisTranslatePipe], }) export class PostingFooterComponent implements OnInit, OnDestroy, AfterContentChecked, OnChanges { lastReadDate = input(); @@ -165,7 +168,7 @@ export class PostingFooterComponent implements OnInit, OnDestroy, AfterContentCh this.createAnswerPostModalComponent?.close(); } - protected postsTrackByFn(index: number, post: Post): number { + protected postsTrackByFn(_index: number, post: Post): number { return post.id!; } } diff --git a/src/main/webapp/app/shared/metis/posting-header/posting-header.component.ts b/src/main/webapp/app/shared/metis/posting-header/posting-header.component.ts index fe3aaee9cef7..aa0b52f97c2f 100644 --- a/src/main/webapp/app/shared/metis/posting-header/posting-header.component.ts +++ b/src/main/webapp/app/shared/metis/posting-header/posting-header.component.ts @@ -13,11 +13,19 @@ import { faUser, faUserCheck, faUserGraduate } from '@fortawesome/free-solid-svg import { UserRole } from 'app/shared/metis/metis.util'; import { AnswerPost } from 'app/entities/metis/answer-post.model'; import { Post } from 'app/entities/metis/post.model'; +import { ProfilePictureComponent } from '../../profile-picture/profile-picture.component'; +import { NgClass } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateDirective } from '../../language/translate.directive'; +import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-posting-header', templateUrl: './posting-header.component.html', styleUrls: ['../metis.component.scss'], + imports: [ProfilePictureComponent, NgClass, FaIconComponent, NgbTooltip, TranslateDirective, ArtemisDatePipe, ArtemisTranslatePipe], }) export class PostingHeaderComponent implements OnInit, OnDestroy, OnChanges { readOnlyMode = input(false); diff --git a/src/main/webapp/app/shared/metis/posting-markdown-editor/posting-markdown-editor.component.ts b/src/main/webapp/app/shared/metis/posting-markdown-editor/posting-markdown-editor.component.ts index c176eed51aa0..4814aa39cf87 100644 --- a/src/main/webapp/app/shared/metis/posting-markdown-editor/posting-markdown-editor.component.ts +++ b/src/main/webapp/app/shared/metis/posting-markdown-editor/posting-markdown-editor.component.ts @@ -44,6 +44,8 @@ import { Overlay, OverlayPositionBuilder } from '@angular/cdk/overlay'; import { BulletedListAction } from 'app/shared/monaco-editor/model/actions/bulleted-list.action'; import { OrderedListAction } from 'app/shared/monaco-editor/model/actions/ordered-list.action'; import { StrikethroughAction } from 'app/shared/monaco-editor/model/actions/strikethrough.action'; +import { PostingContentComponent } from '../posting-content/posting-content.components'; +import { NgStyle } from '@angular/common'; @Component({ selector: 'jhi-posting-markdown-editor', @@ -57,8 +59,17 @@ import { StrikethroughAction } from 'app/shared/monaco-editor/model/actions/stri ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, + imports: [MarkdownEditorMonacoComponent, PostingContentComponent, NgStyle], }) export class PostingMarkdownEditorComponent implements OnInit, ControlValueAccessor, AfterContentChecked, AfterViewInit { + private cdref = inject(ChangeDetectorRef); + private metisService = inject(MetisService); + private courseManagementService = inject(CourseManagementService); + private lectureService = inject(LectureService); + private channelService = inject(ChannelService); + viewContainerRef = inject(ViewContainerRef); + private positionBuilder = inject(OverlayPositionBuilder); + @ViewChild(MarkdownEditorMonacoComponent, { static: true }) markdownEditor: MarkdownEditorMonacoComponent; @Input() maxContentLength: number; @@ -80,16 +91,6 @@ export class PostingMarkdownEditorComponent implements OnInit, ControlValueAcces protected readonly MarkdownEditorHeight = MarkdownEditorHeight; private overlay = inject(Overlay); - constructor( - private cdref: ChangeDetectorRef, - private metisService: MetisService, - private courseManagementService: CourseManagementService, - private lectureService: LectureService, - private channelService: ChannelService, - public viewContainerRef: ViewContainerRef, - private positionBuilder: OverlayPositionBuilder, - ) {} - /** * on initialization: sets commands that will be available as formatting buttons during creation/editing of postings */ @@ -172,7 +173,7 @@ export class PostingMarkdownEditorComponent implements OnInit, ControlValueAcces * the callback function to register on UI change */ // eslint-disable-next-line @typescript-eslint/no-unused-vars - onChange = (val: string) => {}; + onChange = (_val: string) => {}; /** * emits the value change from component diff --git a/src/main/webapp/app/shared/metis/posting-reactions-bar/answer-post-reactions-bar/answer-post-reactions-bar.component.ts b/src/main/webapp/app/shared/metis/posting-reactions-bar/answer-post-reactions-bar/answer-post-reactions-bar.component.ts index 8a843639365a..a9fcce9ead64 100644 --- a/src/main/webapp/app/shared/metis/posting-reactions-bar/answer-post-reactions-bar/answer-post-reactions-bar.component.ts +++ b/src/main/webapp/app/shared/metis/posting-reactions-bar/answer-post-reactions-bar/answer-post-reactions-bar.component.ts @@ -1,39 +1,58 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Output, output } from '@angular/core'; import { Reaction } from 'app/entities/metis/reaction.model'; +import { ConfirmIconComponent } from 'app/shared/confirm-icon/confirm-icon.component'; +import { EmojiPickerComponent } from 'app/shared/metis/emoji/emoji-picker.component'; +import { EmojiComponent } from 'app/shared/metis/emoji/emoji.component'; import { PostingsReactionsBarDirective } from 'app/shared/metis/posting-reactions-bar/posting-reactions-bar.directive'; import { AnswerPost } from 'app/entities/metis/answer-post.model'; import { faCheck, faPencilAlt, faSmile } from '@fortawesome/free-solid-svg-icons'; -import { MetisService } from 'app/shared/metis/metis.service'; import { getAsChannelDTO } from 'app/entities/metis/conversation/channel.model'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { AsyncPipe, KeyValuePipe, NgClass } from '@angular/common'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { ReactingUsersOnPostingPipe } from 'app/shared/pipes/reacting-users-on-posting.pipe'; @Component({ selector: 'jhi-answer-post-reactions-bar', templateUrl: './answer-post-reactions-bar.component.html', styleUrls: ['../posting-reactions-bar.component.scss'], + imports: [ + NgbTooltip, + EmojiComponent, + CdkOverlayOrigin, + FaIconComponent, + CdkConnectedOverlay, + EmojiPickerComponent, + NgClass, + ConfirmIconComponent, + AsyncPipe, + KeyValuePipe, + ArtemisTranslatePipe, + ReactingUsersOnPostingPipe, + ], }) export class AnswerPostReactionsBarComponent extends PostingsReactionsBarDirective implements OnInit, OnChanges { - @Input() - isReadOnlyMode = false; - + @Input() isReadOnlyMode = false; + @Input() isEmojiCount: boolean = false; @Input() isLastAnswer = false; + + @Output() openPostingCreateEditModal = new EventEmitter(); + @Output() postingUpdated = new EventEmitter(); + // Icons readonly farSmile = faSmile; readonly faCheck = faCheck; + readonly faPencilAlt = faPencilAlt; - @Output() openPostingCreateEditModal = new EventEmitter(); isAuthorOfOriginalPost: boolean; isAnswerOfAnnouncement: boolean; - mayDeleteOutput = output(); mayDelete: boolean; - mayEditOutput = output(); mayEdit: boolean; - readonly faPencilAlt = faPencilAlt; - @Input() isEmojiCount: boolean = false; - @Output() postingUpdated = new EventEmitter(); - constructor(metisService: MetisService) { - super(metisService); - } + mayDeleteOutput = output(); + mayEditOutput = output(); ngOnInit() { super.ngOnInit(); diff --git a/src/main/webapp/app/shared/metis/posting-reactions-bar/post-reactions-bar/post-reactions-bar.component.ts b/src/main/webapp/app/shared/metis/posting-reactions-bar/post-reactions-bar/post-reactions-bar.component.ts index 9213fcaeae56..29a3a5543a7c 100644 --- a/src/main/webapp/app/shared/metis/posting-reactions-bar/post-reactions-bar/post-reactions-bar.component.ts +++ b/src/main/webapp/app/shared/metis/posting-reactions-bar/post-reactions-bar/post-reactions-bar.component.ts @@ -1,12 +1,16 @@ -import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, ViewChild, output } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, ViewChild, inject, output } from '@angular/core'; import { Reaction } from 'app/entities/metis/reaction.model'; import { Post } from 'app/entities/metis/post.model'; +import { ConfirmIconComponent } from 'app/shared/confirm-icon/confirm-icon.component'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { EmojiPickerComponent } from 'app/shared/metis/emoji/emoji-picker.component'; +import { EmojiComponent } from 'app/shared/metis/emoji/emoji.component'; import { PostingsReactionsBarDirective } from 'app/shared/metis/posting-reactions-bar/posting-reactions-bar.directive'; import { DisplayPriority } from 'app/shared/metis/metis.util'; -import { MetisService } from 'app/shared/metis/metis.service'; import { faTrashAlt } from '@fortawesome/free-regular-svg-icons'; import { faArrowRight, faPencilAlt, faSmile } from '@fortawesome/free-solid-svg-icons'; import { AnswerPost } from 'app/entities/metis/answer-post.model'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; import dayjs from 'dayjs/esm'; import { getAsChannelDTO, isChannelDTO } from 'app/entities/metis/conversation/channel.model'; import { isGroupChatDTO } from 'app/entities/metis/conversation/group-chat.model'; @@ -14,13 +18,35 @@ import { AccountService } from 'app/core/auth/account.service'; import { isOneToOneChatDTO } from 'app/entities/metis/conversation/one-to-one-chat.model'; import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model'; import { PostCreateEditModalComponent } from 'app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-create-edit-modal.component'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; +import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay'; +import { AsyncPipe, KeyValuePipe } from '@angular/common'; +import { ReactingUsersOnPostingPipe } from 'app/shared/pipes/reacting-users-on-posting.pipe'; @Component({ selector: 'jhi-post-reactions-bar', templateUrl: './post-reactions-bar.component.html', styleUrls: ['../posting-reactions-bar.component.scss'], + imports: [ + FaIconComponent, + TranslateDirective, + EmojiComponent, + NgbTooltip, + CdkOverlayOrigin, + CdkConnectedOverlay, + EmojiPickerComponent, + PostCreateEditModalComponent, + ConfirmIconComponent, + AsyncPipe, + KeyValuePipe, + ArtemisTranslatePipe, + ReactingUsersOnPostingPipe, + ], }) export class PostReactionsBarComponent extends PostingsReactionsBarDirective implements OnInit, OnChanges, OnDestroy { + private accountService = inject(AccountService); + pinTooltip: string; displayPriority: DisplayPriority; canPin = false; @@ -32,35 +58,29 @@ export class PostReactionsBarComponent extends PostingsReactionsBarDirective(); @Output() openPostingCreateEditModal = new EventEmitter(); @Output() closePostingCreateEditModal = new EventEmitter(); @Output() openThread = new EventEmitter(); - @Input() previewMode: boolean; + @Output() canPinOutput = new EventEmitter(); + + @ViewChild(PostCreateEditModalComponent) postCreateEditModal?: PostCreateEditModalComponent; + @ViewChild('createEditModal') createEditModal!: PostCreateEditModalComponent; + isAtLeastInstructorInCourse: boolean; mayDeleteOutput = output(); mayEditOutput = output(); - @Output() canPinOutput = new EventEmitter(); mayEdit: boolean; mayDelete: boolean; - @ViewChild(PostCreateEditModalComponent) postCreateEditModal?: PostCreateEditModalComponent; - @Input() isEmojiCount = false; - @Input() hoverBar: boolean = true; - @ViewChild('createEditModal') createEditModal!: PostCreateEditModalComponent; - - constructor( - metisService: MetisService, - private accountService: AccountService, - ) { - super(metisService); - } isAnyReactionCountAboveZero(): boolean { return Object.values(this.reactionMetaDataMap).some((reaction) => reaction.count >= 1); diff --git a/src/main/webapp/app/shared/metis/posting-reactions-bar/posting-reactions-bar.directive.ts b/src/main/webapp/app/shared/metis/posting-reactions-bar/posting-reactions-bar.directive.ts index c8877be83b9c..c59cff91c678 100644 --- a/src/main/webapp/app/shared/metis/posting-reactions-bar/posting-reactions-bar.directive.ts +++ b/src/main/webapp/app/shared/metis/posting-reactions-bar/posting-reactions-bar.directive.ts @@ -1,4 +1,4 @@ -import { Directive, EventEmitter, Input, OnChanges, OnInit, Output, output } from '@angular/core'; +import { Directive, EventEmitter, Input, OnChanges, OnInit, Output, inject, output } from '@angular/core'; import { Posting } from 'app/entities/metis/posting.model'; import { MetisService } from 'app/shared/metis/metis.service'; import { EmojiData } from '@ctrl/ngx-emoji-mart/ngx-emoji'; @@ -9,7 +9,6 @@ import { faBookmark as farBookmark } from '@fortawesome/free-regular-svg-icons'; const PIN_EMOJI_ID = 'pushpin'; const ARCHIVE_EMOJI_ID = 'open_file_folder'; -const SPEECH_BALLOON_ID = 'speech_balloon'; const HEAVY_MULTIPLICATION_ID = 'heavy_multiplication_x'; const SPEECH_BALLOON_UNICODE = '1F4AC'; @@ -44,21 +43,24 @@ interface ReactionMetaDataMap { @Directive() export abstract class PostingsReactionsBarDirective implements OnInit, OnChanges { + protected metisService = inject(MetisService); + pinEmojiId: string = PIN_EMOJI_ID; archiveEmojiId: string = ARCHIVE_EMOJI_ID; - speechBalloonId: string = SPEECH_BALLOON_ID; closeCrossId: string = HEAVY_MULTIPLICATION_ID; @Input() posting: T; @Input() isThreadSidebar: boolean; + @Output() openPostingCreateEditModal = new EventEmitter(); @Output() reactionsUpdated = new EventEmitter(); + @Output() isModalOpen = new EventEmitter(); showReactionSelector = false; currentUserIsAtLeastTutor: boolean; isAtLeastTutorInCourse: boolean; isAuthorOfPosting: boolean; - @Output() isModalOpen = new EventEmitter(); + isDeleteEvent = output(); readonly onBookmarkClicked = output(); @@ -104,8 +106,6 @@ export abstract class PostingsReactionsBarDirective implement */ reactionMetaDataMap: ReactionMetaDataMap = {}; - protected constructor(protected metisService: MetisService) {} - /** * on initialization: updates the current posting and its reactions, * invokes metis service to check user authority diff --git a/src/main/webapp/app/shared/metis/posting-thread/posting-thread.component.ts b/src/main/webapp/app/shared/metis/posting-thread/posting-thread.component.ts index 8cb7db55b963..5aa17e0db43c 100644 --- a/src/main/webapp/app/shared/metis/posting-thread/posting-thread.component.ts +++ b/src/main/webapp/app/shared/metis/posting-thread/posting-thread.component.ts @@ -1,12 +1,14 @@ import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, inject } from '@angular/core'; import { Post } from 'app/entities/metis/post.model'; import dayjs from 'dayjs/esm'; +import { PostComponent } from '../post/post.component'; @Component({ selector: 'jhi-posting-thread', templateUrl: './posting-thread.component.html', styleUrls: ['../metis.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, + imports: [PostComponent], }) export class PostingThreadComponent { @Input() lastReadDate?: dayjs.Dayjs; diff --git a/src/main/webapp/app/shared/metis/reaction.service.ts b/src/main/webapp/app/shared/metis/reaction.service.ts index b91bb9ef145f..78402334d69b 100644 --- a/src/main/webapp/app/shared/metis/reaction.service.ts +++ b/src/main/webapp/app/shared/metis/reaction.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -9,9 +9,9 @@ type EntityResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class ReactionService { - public resourceUrl = 'api/courses/'; + protected http = inject(HttpClient); - constructor(protected http: HttpClient) {} + public resourceUrl = 'api/courses/'; /** * creates a reaction diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.ts b/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.ts index bd234e45cdec..79c35c876751 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.ts +++ b/src/main/webapp/app/shared/monaco-editor/monaco-diff-editor.component.ts @@ -1,14 +1,13 @@ import { ChangeDetectionStrategy, Component, ElementRef, OnDestroy, Renderer2, ViewEncapsulation, effect, inject, input, output } from '@angular/core'; +import { Disposable } from 'app/shared/monaco-editor/model/actions/monaco-editor.util'; import * as monaco from 'monaco-editor'; -import { Disposable } from 'app/shared/monaco-editor/model/actions/monaco-editor.util'; import { MonacoEditorService } from './monaco-editor.service'; export type MonacoEditorDiffText = { original: string; modified: string }; @Component({ selector: 'jhi-monaco-diff-editor', template: '', - standalone: true, styleUrls: ['monaco-diff-editor.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-editor-option.helper.ts b/src/main/webapp/app/shared/monaco-editor/monaco-editor-option.helper.ts index ddc632613694..c91207997e13 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-editor-option.helper.ts +++ b/src/main/webapp/app/shared/monaco-editor/monaco-editor-option.helper.ts @@ -1,5 +1,5 @@ -import { MonacoEditorOptionPreset } from 'app/shared/monaco-editor/model/monaco-editor-option-preset.model'; import { EditorOptions } from 'app/shared/monaco-editor/model/actions/monaco-editor.util'; +import { MonacoEditorOptionPreset } from 'app/shared/monaco-editor/model/monaco-editor-option-preset.model'; export const SHORT_ANSWER_QUIZ_QUESTION_EDITOR_OPTIONS = new MonacoEditorOptionPreset({ // Hide the gutter diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-editor.component.ts b/src/main/webapp/app/shared/monaco-editor/monaco-editor.component.ts index ad49c129270f..e297d51310ea 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-editor.component.ts +++ b/src/main/webapp/app/shared/monaco-editor/monaco-editor.component.ts @@ -1,26 +1,25 @@ import { ChangeDetectionStrategy, Component, ElementRef, OnDestroy, OnInit, Renderer2, ViewEncapsulation, effect, inject, input, output } from '@angular/core'; -import * as monaco from 'monaco-editor'; -import { MonacoEditorLineWidget } from 'app/shared/monaco-editor/model/monaco-editor-inline-widget.model'; -import { MonacoEditorBuildAnnotation, MonacoEditorBuildAnnotationType } from 'app/shared/monaco-editor/model/monaco-editor-build-annotation.model'; -import { MonacoEditorLineHighlight } from 'app/shared/monaco-editor/model/monaco-editor-line-highlight.model'; +import { TranslateService } from '@ngx-translate/core'; import { Annotation } from 'app/exercises/programming/shared/code-editor/monaco/code-editor-monaco.component'; -import { MonacoEditorLineDecorationsHoverButton } from './model/monaco-editor-line-decorations-hover-button.model'; +import { MonacoTextEditorAdapter } from 'app/shared/monaco-editor/model/actions/adapter/monaco-text-editor.adapter'; +import { Disposable, EditorPosition, EditorRange, MonacoEditorTextModel } from 'app/shared/monaco-editor/model/actions/monaco-editor.util'; import { TextEditorAction } from 'app/shared/monaco-editor/model/actions/text-editor-action.model'; -import { TranslateService } from '@ngx-translate/core'; +import { MonacoEditorBuildAnnotation, MonacoEditorBuildAnnotationType } from 'app/shared/monaco-editor/model/monaco-editor-build-annotation.model'; +import { MonacoEditorLineWidget } from 'app/shared/monaco-editor/model/monaco-editor-inline-widget.model'; +import { MonacoEditorLineHighlight } from 'app/shared/monaco-editor/model/monaco-editor-line-highlight.model'; import { MonacoEditorOptionPreset } from 'app/shared/monaco-editor/model/monaco-editor-option-preset.model'; -import { Disposable, EditorPosition, EditorRange, MonacoEditorTextModel } from 'app/shared/monaco-editor/model/actions/monaco-editor.util'; -import { MonacoTextEditorAdapter } from 'app/shared/monaco-editor/model/actions/adapter/monaco-text-editor.adapter'; import { MonacoEditorService } from 'app/shared/monaco-editor/monaco-editor.service'; import { getOS } from 'app/shared/util/os-detector.util'; import { EmojiConvertor } from 'emoji-js'; +import * as monaco from 'monaco-editor'; +import { MonacoEditorLineDecorationsHoverButton } from './model/monaco-editor-line-decorations-hover-button.model'; export const MAX_TAB_SIZE = 8; @Component({ selector: 'jhi-monaco-editor', template: '', - standalone: true, styleUrls: ['monaco-editor.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, diff --git a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts index 52a2b40a3693..dac8db723a9a 100644 --- a/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts +++ b/src/main/webapp/app/shared/monaco-editor/monaco-editor.service.ts @@ -1,10 +1,10 @@ import { Injectable, effect, inject } from '@angular/core'; -import * as monaco from 'monaco-editor'; -import { CUSTOM_MARKDOWN_CONFIG, CUSTOM_MARKDOWN_LANGUAGE, CUSTOM_MARKDOWN_LANGUAGE_ID } from 'app/shared/monaco-editor/model/languages/monaco-custom-markdown.language'; import { Theme, ThemeService } from 'app/core/theme/theme.service'; -import { MONACO_LIGHT_THEME_DEFINITION } from 'app/shared/monaco-editor/model/themes/monaco-light.theme'; -import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco-editor-theme.model'; +import { CUSTOM_MARKDOWN_CONFIG, CUSTOM_MARKDOWN_LANGUAGE, CUSTOM_MARKDOWN_LANGUAGE_ID } from 'app/shared/monaco-editor/model/languages/monaco-custom-markdown.language'; import { MONACO_DARK_THEME_DEFINITION } from 'app/shared/monaco-editor/model/themes/monaco-dark.theme'; +import { MonacoEditorTheme } from 'app/shared/monaco-editor/model/themes/monaco-editor-theme.model'; +import { MONACO_LIGHT_THEME_DEFINITION } from 'app/shared/monaco-editor/model/themes/monaco-light.theme'; +import * as monaco from 'monaco-editor'; /** * Service providing shared functionality for the Monaco editor. diff --git a/src/main/webapp/app/shared/no-data-component.ts b/src/main/webapp/app/shared/no-data-component.ts index 2b037e18eed7..752bd5da10e8 100644 --- a/src/main/webapp/app/shared/no-data-component.ts +++ b/src/main/webapp/app/shared/no-data-component.ts @@ -3,6 +3,5 @@ import { Component } from '@angular/core'; @Component({ selector: 'jhi-no-data', template: `-`, - standalone: true, }) export class NoDataComponent {} diff --git a/src/main/webapp/app/shared/notification/loading-notification/loading-notification.component.ts b/src/main/webapp/app/shared/notification/loading-notification/loading-notification.component.ts index 73a3f7f6c7f6..14a95ad86fa0 100644 --- a/src/main/webapp/app/shared/notification/loading-notification/loading-notification.component.ts +++ b/src/main/webapp/app/shared/notification/loading-notification/loading-notification.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { Subscription } from 'rxjs'; import { LoadingNotificationService } from 'app/shared/notification/loading-notification/loading-notification.service'; import { debounceTime } from 'rxjs/operators'; @@ -12,11 +12,11 @@ import { debounceTime } from 'rxjs/operators'; `, }) export class LoadingNotificationComponent implements OnInit, OnDestroy { + private loadingNotificationService = inject(LoadingNotificationService); + isLoading = false; loadingSubscription: Subscription; - constructor(private loadingNotificationService: LoadingNotificationService) {} - ngOnInit() { /** * wait 1000 ms before updating isLoading value to ensure the loading screen will not be visible for fast HttpRequests diff --git a/src/main/webapp/app/shared/notification/loading-notification/loading-notification.interceptor.ts b/src/main/webapp/app/shared/notification/loading-notification/loading-notification.interceptor.ts index cdd569df913f..52d4cba10e71 100644 --- a/src/main/webapp/app/shared/notification/loading-notification/loading-notification.interceptor.ts +++ b/src/main/webapp/app/shared/notification/loading-notification/loading-notification.interceptor.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; import { Observable } from 'rxjs'; import { finalize } from 'rxjs/operators'; @@ -6,9 +6,9 @@ import { LoadingNotificationService } from 'app/shared/notification/loading-noti @Injectable() export class LoadingNotificationInterceptor implements HttpInterceptor { - activeRequests = 0; + private loadingNotificationService = inject(LoadingNotificationService); - constructor(private loadingNotificationService: LoadingNotificationService) {} + activeRequests = 0; /** * Identifies and handles a given HTTP request. If any HTTP request is sent we enable the loading screen and count up the active requests. diff --git a/src/main/webapp/app/shared/notification/notification-popup/notification-popup.component.ts b/src/main/webapp/app/shared/notification/notification-popup/notification-popup.component.ts index b1f5f7d184bb..e6435f9469ae 100644 --- a/src/main/webapp/app/shared/notification/notification-popup/notification-popup.component.ts +++ b/src/main/webapp/app/shared/notification/notification-popup/notification-popup.component.ts @@ -1,4 +1,4 @@ -import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; +import { Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; import { ActivatedRoute, IsActiveMatchOptions, Params, Router, UrlTree } from '@angular/router'; import { NotificationService } from 'app/shared/notification/notification.service'; import { @@ -24,6 +24,8 @@ import { RouteComponents } from 'app/shared/metis/metis.util'; import { NotificationSettingsService } from 'app/shared/user-settings/notification-settings/notification-settings.service'; import { translationNotFoundMessage } from 'app/core/config/translation.config'; import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { TranslateDirective } from '../../language/translate.directive'; const conversationMessageNotificationTitles = [ MENTIONED_IN_MESSAGE_TITLE, @@ -44,8 +46,15 @@ const conversationMessageNotificationTitles = [ selector: 'jhi-notification-popup', templateUrl: './notification-popup.component.html', styleUrls: ['./notification-popup.scss'], + imports: [FaIconComponent, TranslateDirective, ArtemisTranslatePipe], }) export class NotificationPopupComponent implements OnInit { + private notificationService = inject(NotificationService); + private router = inject(Router); + private activatedRoute = inject(ActivatedRoute); + private notificationSettingsService = inject(NotificationSettingsService); + private artemisTranslatePipe = inject(ArtemisTranslatePipe); + notifications: Notification[] = []; QuizNotificationTitleHtmlConst = 'Quiz started'; @@ -62,14 +71,6 @@ export class NotificationPopupComponent implements OnInit { faCheckDouble = faCheckDouble; faExclamationTriangle = faExclamationTriangle; - constructor( - private notificationService: NotificationService, - private router: Router, - private activatedRoute: ActivatedRoute, - private notificationSettingsService: NotificationSettingsService, - private artemisTranslatePipe: ArtemisTranslatePipe, - ) {} - ngOnInit(): void { this.notificationService.subscribeToSingleIncomingNotifications().subscribe((notification: Notification) => { this.addNotification(notification); diff --git a/src/main/webapp/app/shared/notification/notification-sidebar/notification-sidebar.component.ts b/src/main/webapp/app/shared/notification/notification-sidebar/notification-sidebar.component.ts index 273905012c2c..be35beceb820 100644 --- a/src/main/webapp/app/shared/notification/notification-sidebar/notification-sidebar.component.ts +++ b/src/main/webapp/app/shared/notification/notification-sidebar/notification-sidebar.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core'; import { User } from 'app/core/user/user.model'; import { UserService } from 'app/core/user/user.service'; import dayjs from 'dayjs/esm'; @@ -12,6 +12,12 @@ import { SessionStorageService } from 'ngx-webstorage'; import { DocumentationType } from 'app/shared/components/documentation-button/documentation-button.component'; import { translationNotFoundMessage } from 'app/core/config/translation.config'; import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { DatePipe, NgClass } from '@angular/common'; +import { DocumentationButtonComponent } from '../../components/documentation-button/documentation-button.component'; +import { RouterLink } from '@angular/router'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; export const LAST_READ_STORAGE_KEY = 'lastNotificationRead'; const IRRELEVANT_NOTIFICATION_TITLES = [NEW_MESSAGE_TITLE, LIVE_EXAM_EXERCISE_UPDATE_NOTIFICATION_TITLE]; @@ -20,8 +26,16 @@ const IRRELEVANT_NOTIFICATION_TITLES = [NEW_MESSAGE_TITLE, LIVE_EXAM_EXERCISE_UP selector: 'jhi-notification-sidebar', templateUrl: './notification-sidebar.component.html', styleUrls: ['./notification-sidebar.scss'], + imports: [FaIconComponent, NgClass, DocumentationButtonComponent, RouterLink, TranslateDirective, NgbTooltip, DatePipe, ArtemisTranslatePipe], }) export class NotificationSidebarComponent implements OnInit, OnDestroy { + private notificationService = inject(NotificationService); + private userService = inject(UserService); + private accountService = inject(AccountService); + private sessionStorageService = inject(SessionStorageService); + private changeDetector = inject(ChangeDetectorRef); + private artemisTranslatePipe = inject(ArtemisTranslatePipe); + // HTML template related showSidebar = false; showButtonToHideCurrentlyDisplayedNotifications = true; @@ -47,15 +61,6 @@ export class NotificationSidebarComponent implements OnInit, OnDestroy { faArchive = faArchive; faEye = faEye; - constructor( - private notificationService: NotificationService, - private userService: UserService, - private accountService: AccountService, - private sessionStorageService: SessionStorageService, - private changeDetector: ChangeDetectorRef, - private artemisTranslatePipe: ArtemisTranslatePipe, - ) {} - ngOnDestroy(): void { this.subscriptions.forEach((subscription) => subscription.unsubscribe()); } diff --git a/src/main/webapp/app/shared/notification/notification.service.ts b/src/main/webapp/app/shared/notification/notification.service.ts index 6c4b4c01efbc..fb009fdab982 100644 --- a/src/main/webapp/app/shared/notification/notification.service.ts +++ b/src/main/webapp/app/shared/notification/notification.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; import { BehaviorSubject, Observable, ReplaySubject, Subject, Subscription } from 'rxjs'; import dayjs from 'dayjs/esm'; @@ -65,6 +65,15 @@ const MESSAGING_NOTIFICATION_TEXTS = [ @Injectable({ providedIn: 'root' }) export class NotificationService { + private jhiWebsocketService = inject(JhiWebsocketService); + private router = inject(Router); + private http = inject(HttpClient); + private accountService = inject(AccountService); + private activatedRoute = inject(ActivatedRoute); + private courseManagementService = inject(CourseManagementService); + private notificationSettingsService = inject(NotificationSettingsService); + private artemisTranslatePipe = inject(ArtemisTranslatePipe); + public resourceUrl = 'api/notifications'; notificationSubject: ReplaySubject; singleNotificationSubject: Subject; @@ -85,16 +94,7 @@ export class NotificationService { private mutedConversations: number[] = []; private loadedMutedConversations = false; - constructor( - private jhiWebsocketService: JhiWebsocketService, - private router: Router, - private http: HttpClient, - private accountService: AccountService, - private activatedRoute: ActivatedRoute, - private courseManagementService: CourseManagementService, - private notificationSettingsService: NotificationSettingsService, - private artemisTranslatePipe: ArtemisTranslatePipe, - ) { + constructor() { this.initNotificationObserver(); this.notificationSettingsService.getNotificationSettingsUpdates().subscribe(() => { diff --git a/src/main/webapp/app/shared/notification/system-notification/admin-system-notification.service.ts b/src/main/webapp/app/shared/notification/system-notification/admin-system-notification.service.ts index 17637a71b2a3..f9b71c4feb16 100644 --- a/src/main/webapp/app/shared/notification/system-notification/admin-system-notification.service.ts +++ b/src/main/webapp/app/shared/notification/system-notification/admin-system-notification.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -10,13 +10,11 @@ type EntityResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class AdminSystemNotificationService { - public resourceUrl = 'api/admin/system-notifications'; + private router = inject(Router); + private http = inject(HttpClient); + private systemNotificationService = inject(SystemNotificationService); - constructor( - private router: Router, - private http: HttpClient, - private systemNotificationService: SystemNotificationService, - ) {} + public resourceUrl = 'api/admin/system-notifications'; /** * Create a notification on the server using a POST request. diff --git a/src/main/webapp/app/shared/notification/system-notification/system-notification.component.ts b/src/main/webapp/app/shared/notification/system-notification/system-notification.component.ts index 7b7ba4b4c81b..ac58b07ae861 100644 --- a/src/main/webapp/app/shared/notification/system-notification/system-notification.component.ts +++ b/src/main/webapp/app/shared/notification/system-notification/system-notification.component.ts @@ -1,4 +1,4 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import dayjs from 'dayjs/esm'; import { SystemNotification, SystemNotificationType } from 'app/entities/system-notification.model'; @@ -9,6 +9,8 @@ import { SystemNotificationService } from 'app/shared/notification/system-notifi import { faExclamationTriangle, faInfoCircle, faTimes } from '@fortawesome/free-solid-svg-icons'; import { Subscription, filter } from 'rxjs'; import { convertDateFromServer } from 'app/utils/date.utils'; +import { NgClass } from '@angular/common'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; export const WEBSOCKET_CHANNEL = '/topic/system-notification'; @@ -16,8 +18,14 @@ export const WEBSOCKET_CHANNEL = '/topic/system-notification'; selector: 'jhi-system-notification', templateUrl: './system-notification.component.html', styleUrls: ['system-notification.scss'], + imports: [NgClass, FaIconComponent], }) export class SystemNotificationComponent implements OnInit, OnDestroy { + private route = inject(ActivatedRoute); + private accountService = inject(AccountService); + private jhiWebsocketService = inject(JhiWebsocketService); + private systemNotificationService = inject(SystemNotificationService); + readonly INFO = SystemNotificationType.INFO; readonly WARNING = SystemNotificationType.WARNING; @@ -33,13 +41,6 @@ export class SystemNotificationComponent implements OnInit, OnDestroy { faInfoCircle = faInfoCircle; faTimes = faTimes; - constructor( - private route: ActivatedRoute, - private accountService: AccountService, - private jhiWebsocketService: JhiWebsocketService, - private systemNotificationService: SystemNotificationService, - ) {} - ngOnInit() { this.loadActiveNotification(); this.accountService.getAuthenticationState().subscribe((user: User | undefined) => { diff --git a/src/main/webapp/app/shared/notification/system-notification/system-notification.service.ts b/src/main/webapp/app/shared/notification/system-notification/system-notification.service.ts index f14958916768..2be4f0a39d85 100644 --- a/src/main/webapp/app/shared/notification/system-notification/system-notification.service.ts +++ b/src/main/webapp/app/shared/notification/system-notification/system-notification.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpResponse } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -12,14 +12,12 @@ type EntityArrayResponseType = HttpResponse; @Injectable({ providedIn: 'root' }) export class SystemNotificationService { + private router = inject(Router); + private http = inject(HttpClient); + public resourceUrl = 'api/system-notifications'; public publicResourceUrl = 'api/public/system-notifications'; - constructor( - private router: Router, - private http: HttpClient, - ) {} - /** * Find a notification on the server using a GET request. * @param systemNotificationId The id of the notification to get. diff --git a/src/main/webapp/app/shared/organization-selector/organization-selector.component.ts b/src/main/webapp/app/shared/organization-selector/organization-selector.component.ts index 690fa11797e3..5c4f0858aa08 100644 --- a/src/main/webapp/app/shared/organization-selector/organization-selector.component.ts +++ b/src/main/webapp/app/shared/organization-selector/organization-selector.component.ts @@ -1,25 +1,25 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { OrganizationManagementService } from 'app/admin/organization-management/organization-management.service'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { TranslateService } from '@ngx-translate/core'; import { AlertService } from 'app/core/util/alert.service'; import { Organization } from 'app/entities/organization.model'; +import { TranslateDirective } from '../language/translate.directive'; @Component({ selector: 'jhi-organization-selector', templateUrl: './organization-selector.component.html', + imports: [TranslateDirective], }) export class OrganizationSelectorComponent implements OnInit { + private activeModal = inject(NgbActiveModal); + private translateService = inject(TranslateService); + private alertService = inject(AlertService); + private organizationService = inject(OrganizationManagementService); + organizations: Organization[]; availableOrganizations: Organization[]; - constructor( - private activeModal: NgbActiveModal, - private translateService: TranslateService, - private alertService: AlertService, - private organizationService: OrganizationManagementService, - ) {} - ngOnInit(): void { this.organizationService.getOrganizations().subscribe((data) => { this.availableOrganizations = data; diff --git a/src/main/webapp/app/shared/orion/modal-confirm-autofocus/modal-confirm-autofocus.component.ts b/src/main/webapp/app/shared/orion/modal-confirm-autofocus/modal-confirm-autofocus.component.ts index 45d5ddb20587..820c6585e477 100644 --- a/src/main/webapp/app/shared/orion/modal-confirm-autofocus/modal-confirm-autofocus.component.ts +++ b/src/main/webapp/app/shared/orion/modal-confirm-autofocus/modal-confirm-autofocus.component.ts @@ -1,13 +1,15 @@ -import { Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-modal-confirm-autofocus', templateUrl: './modal-confirm-autofocus.component.html', + imports: [ArtemisTranslatePipe], }) export class ModalConfirmAutofocusComponent { + modal = inject(NgbActiveModal); + title: string; text: string; - - constructor(public modal: NgbActiveModal) {} } diff --git a/src/main/webapp/app/shared/orion/orion-build-and-test.service.ts b/src/main/webapp/app/shared/orion/orion-build-and-test.service.ts index d46ee941b24a..7219393e345e 100644 --- a/src/main/webapp/app/shared/orion/orion-build-and-test.service.ts +++ b/src/main/webapp/app/shared/orion/orion-build-and-test.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { ProgrammingSubmissionService } from 'app/exercises/programming/participate/programming-submission.service'; import { ParticipationWebsocketService } from 'app/overview/participation-websocket.service'; import { filter, map, tap } from 'rxjs/operators'; @@ -20,18 +20,16 @@ import { ProgrammingSubmission } from 'app/entities/programming/programming-subm providedIn: 'root', }) export class OrionBuildAndTestService { + private submissionService = inject(ProgrammingSubmissionService); + private participationWebsocketService = inject(ParticipationWebsocketService); + private orionConnectorService = inject(OrionConnectorService); + private buildLogService = inject(BuildLogService); + private buildFinished = new Subject(); private resultSubscription: Subscription; private buildLogSubscription: Subscription; private latestResult: Result; - constructor( - private submissionService: ProgrammingSubmissionService, - private participationWebsocketService: ParticipationWebsocketService, - private orionConnectorService: OrionConnectorService, - private buildLogService: BuildLogService, - ) {} - /** * Trigger a new build for a participation for an exercise and notify the IDE * diff --git a/src/main/webapp/app/shared/orion/orion-button/orion-button.component.ts b/src/main/webapp/app/shared/orion/orion-button/orion-button.component.ts index a04d94a99b08..1f730d4bed2f 100644 --- a/src/main/webapp/app/shared/orion/orion-button/orion-button.component.ts +++ b/src/main/webapp/app/shared/orion/orion-button/orion-button.component.ts @@ -2,6 +2,8 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { faCircleNotch, faDownload, faRotateRight, faUpload } from '@fortawesome/free-solid-svg-icons'; import { FeatureToggle } from 'app/shared/feature-toggle/feature-toggle.service'; +import { FeatureToggleDirective } from '../../feature-toggle/feature-toggle.directive'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; export enum OrionButtonType { Other = 'Other', @@ -13,6 +15,7 @@ export enum OrionButtonType { @Component({ selector: 'jhi-ide-button', templateUrl: './orion-button.component.html', + imports: [FeatureToggleDirective, FaIconComponent], }) export class OrionButtonComponent { @Input() buttonLabel: string; @@ -34,8 +37,6 @@ export class OrionButtonComponent { faUpload = faUpload; faDownload = faDownload; - constructor() {} - public get btnPrimary(): boolean { return !this.outlined; } diff --git a/src/main/webapp/app/shared/orion/orion-connector.service.ts b/src/main/webapp/app/shared/orion/orion-connector.service.ts index 61c8a0933cec..d8fcc62a01aa 100644 --- a/src/main/webapp/app/shared/orion/orion-connector.service.ts +++ b/src/main/webapp/app/shared/orion/orion-connector.service.ts @@ -1,4 +1,4 @@ -import { Injectable, Injector } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { BehaviorSubject, Observable } from 'rxjs'; import { ExerciseView, OrionState } from 'app/shared/orion/orion'; import { Router } from '@angular/router'; @@ -34,33 +34,21 @@ function theWindow(): any { providedIn: 'root', }) export class OrionConnectorService { + private router = inject(Router); + private alertService = inject(AlertService); + private orionState: OrionState; private orionStateSubject: BehaviorSubject; // When loaded, the AssessmentComponent registers here to receive updates from the plugin activeAssessmentComponent: OrionTutorAssessmentComponent | undefined = undefined; - constructor( - private injector: Injector, - private alertService: AlertService, - ) {} - static initConnector(connector: OrionConnectorService) { theWindow().artemisClientConnector = connector; connector.orionState = { opened: -1, view: ExerciseView.STUDENT, cloning: false, building: false }; connector.orionStateSubject = new BehaviorSubject(connector.orionState); } - /** - * Yes, this is not best practice. But since this bridge service is an APP_INITIALIZER and has to be set on - * the window object right in the beginning (so that the IDE can interact with Artemis as soon as the page has been - * loaded), it should be fine to actually load the router only when it is needed later in the process. - * Otherwise we would have a cyclic dependency problem on app startup - */ - get router(): Router { - return this.injector.get(Router); - } - /** * Login to the Git client within the IDE with the same credentials as used for Artemis * @@ -260,10 +248,10 @@ export class OrionConnectorService { * * @param submissionId id of the submission, used to navigate to the corresponding URL * @param correctionRound correction round, also needed to navigate to the correct URL - * @param testRun test run flag, also needed for navigation + * @param _testRun test run flag, also needed for navigation * @param base64data the student's submission as base64 */ - downloadSubmission(submissionId: number, correctionRound: number, testRun: boolean, base64data: string) { + downloadSubmission(submissionId: number, correctionRound: number, _testRun: boolean, base64data: string) { // Uncomment this line to also transfer the testRun flag. // THIS IS A BREAKING CHANGE that will require all users to upgrade their Orion to a compatible version! // Also change in orion.ts diff --git a/src/main/webapp/app/shared/orion/orion-filter.directive.ts b/src/main/webapp/app/shared/orion/orion-filter.directive.ts index 630aedb51340..935657d3e10c 100644 --- a/src/main/webapp/app/shared/orion/orion-filter.directive.ts +++ b/src/main/webapp/app/shared/orion/orion-filter.directive.ts @@ -1,13 +1,11 @@ -import { Directive, ElementRef, Input, OnInit } from '@angular/core'; +import { Directive, ElementRef, Input, OnInit, inject } from '@angular/core'; import { isOrion } from 'app/shared/orion/orion'; -@Directive({ - selector: '[jhiOrionFilter]', -}) +@Directive({ selector: '[jhiOrionFilter]' }) export class OrionFilterDirective implements OnInit { - @Input() showInOrionWindow: boolean; + private el = inject(ElementRef); - constructor(private el: ElementRef) {} + @Input() showInOrionWindow: boolean; ngOnInit(): void { if ((!this.showInOrionWindow && isOrion) || (this.showInOrionWindow && !isOrion)) { diff --git a/src/main/webapp/app/shared/orion/orion.module.ts b/src/main/webapp/app/shared/orion/orion.module.ts index 21d7f6096452..d54d85370436 100644 --- a/src/main/webapp/app/shared/orion/orion.module.ts +++ b/src/main/webapp/app/shared/orion/orion.module.ts @@ -1,23 +1,17 @@ -import { APP_INITIALIZER, NgModule } from '@angular/core'; +import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { OrionButtonComponent } from 'app/shared/orion/orion-button/orion-button.component'; -import { OrionConnectorService } from 'app/shared/orion/orion-connector.service'; import { ModalConfirmAutofocusComponent } from './modal-confirm-autofocus/modal-confirm-autofocus.component'; import { TranslateModule } from '@ngx-translate/core'; import { OrionFilterDirective } from './orion-filter.directive'; import { OrionBuildAndTestService } from 'app/shared/orion/orion-build-and-test.service'; -import { FeatureToggleModule } from 'app/shared/feature-toggle/feature-toggle.module'; + import { ArtemisSharedModule } from 'app/shared/shared.module'; import { OrionAssessmentService } from 'app/orion/assessment/orion-assessment.service'; -export function initOrionConnector(connector: OrionConnectorService) { - return () => OrionConnectorService.initConnector(connector); -} - @NgModule({ - declarations: [OrionButtonComponent, ModalConfirmAutofocusComponent, OrionFilterDirective], - imports: [CommonModule, ArtemisSharedModule, TranslateModule, FeatureToggleModule], + imports: [CommonModule, ArtemisSharedModule, TranslateModule, OrionButtonComponent, ModalConfirmAutofocusComponent, OrionFilterDirective], exports: [OrionButtonComponent, OrionFilterDirective], - providers: [{ provide: APP_INITIALIZER, useFactory: initOrionConnector, deps: [OrionConnectorService], multi: true }, OrionBuildAndTestService, OrionAssessmentService], + providers: [OrionBuildAndTestService, OrionAssessmentService], }) export class OrionModule {} diff --git a/src/main/webapp/app/shared/orion/outdated-plugin-warning/orion-outdated.component.ts b/src/main/webapp/app/shared/orion/outdated-plugin-warning/orion-outdated.component.ts index ec9c3692b0d3..dffe9d76c97f 100644 --- a/src/main/webapp/app/shared/orion/outdated-plugin-warning/orion-outdated.component.ts +++ b/src/main/webapp/app/shared/orion/outdated-plugin-warning/orion-outdated.component.ts @@ -1,6 +1,8 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, inject } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; +import { TranslateDirective } from '../../language/translate.directive'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; @Component({ selector: 'jhi-orion-outdated', @@ -14,16 +16,15 @@ import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; {{ 'artemisApp.orion.version.allowedVersion' | artemisTranslate }}{{ allowedMinimumVersion }}
`, + imports: [TranslateDirective, ArtemisTranslatePipe], }) export class OrionOutdatedComponent implements OnInit { + private activatedRoute = inject(ActivatedRoute); + private profileService = inject(ProfileService); + versionString: string; allowedMinimumVersion: string; - constructor( - private activatedRoute: ActivatedRoute, - private profileService: ProfileService, - ) {} - /** * On initialization, sets the values of the used version and the minimum allowed version of orion. */ diff --git a/src/main/webapp/app/shared/orion/outdated-plugin-warning/orion-version-validator.service.ts b/src/main/webapp/app/shared/orion/outdated-plugin-warning/orion-version-validator.service.ts index b70cca47f4bf..3e762a5c3933 100644 --- a/src/main/webapp/app/shared/orion/outdated-plugin-warning/orion-version-validator.service.ts +++ b/src/main/webapp/app/shared/orion/outdated-plugin-warning/orion-version-validator.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { isOrion } from 'app/shared/orion/orion'; import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { Router } from '@angular/router'; @@ -11,15 +11,13 @@ import { ProfileInfo } from 'app/shared/layouts/profiles/profile-info.model'; providedIn: 'root', }) export class OrionVersionValidator { + private profileService = inject(ProfileService); + private router = inject(Router); + isOrion = isOrion; private minVersion: string; private isValidVersion: boolean; - constructor( - private profileService: ProfileService, - private router: Router, - ) {} - /** * Validates the installed Orion plugin version against the allowed version range. This will not validate anything * if Artemis is not opened by Orion and just return true in this case! diff --git a/src/main/webapp/app/shared/pagination/item-count.component.ts b/src/main/webapp/app/shared/pagination/item-count.component.ts index bf49e62fd0cd..f64b51d0df8f 100644 --- a/src/main/webapp/app/shared/pagination/item-count.component.ts +++ b/src/main/webapp/app/shared/pagination/item-count.component.ts @@ -1,4 +1,5 @@ import { Component, Input } from '@angular/core'; +import { TranslateDirective } from '../language/translate.directive'; /** * A component that will take care of item count statistics of a pagination. @@ -6,6 +7,7 @@ import { Component, Input } from '@angular/core'; @Component({ selector: 'jhi-item-count', template: `
`, + imports: [TranslateDirective], }) export class ItemCountComponent { /** diff --git a/src/main/webapp/app/shared/participant-scores/participant-scores-distribution/participant-scores-distribution.component.ts b/src/main/webapp/app/shared/participant-scores/participant-scores-distribution/participant-scores-distribution.component.ts index 0fdfaba04ed4..0dc4f8eb50cd 100644 --- a/src/main/webapp/app/shared/participant-scores/participant-scores-distribution/participant-scores-distribution.component.ts +++ b/src/main/webapp/app/shared/participant-scores/participant-scores-distribution/participant-scores-distribution.component.ts @@ -1,11 +1,14 @@ -import { Component, EventEmitter, HostListener, Input, OnChanges, OnInit, Output } from '@angular/core'; -import { Color, ScaleType } from '@swimlane/ngx-charts'; +import { Component, EventEmitter, HostListener, Input, OnChanges, OnInit, Output, inject } from '@angular/core'; +import { BarChartModule, Color, ScaleType } from '@swimlane/ngx-charts'; import { NgxChartsSingleSeriesDataEntry } from 'app/shared/chart/ngx-charts-datatypes'; import { GradeType, GradingScale } from 'app/entities/grading-scale.model'; import { GradingSystemService } from 'app/grading-system/grading-system.service'; import { TranslateService } from '@ngx-translate/core'; import { GradeStep } from 'app/entities/grade-step.model'; import { GraphColors } from 'app/entities/statistics.model'; +import { TranslateDirective } from '../../language/translate.directive'; +import { HelpIconComponent } from '../../components/help-icon.component'; +import { ArtemisTranslatePipe } from '../../pipes/artemis-translate.pipe'; interface NgxClickEvent { name: string; @@ -17,8 +20,12 @@ interface NgxClickEvent { selector: 'jhi-participant-scores-distribution', templateUrl: './participant-scores-distribution.component.html', styleUrls: ['./participant-score-distribution.component.scss', '../../chart/vertical-bar-chart.scss'], + imports: [BarChartModule, TranslateDirective, HelpIconComponent, ArtemisTranslatePipe], }) export class ParticipantScoresDistributionComponent implements OnInit, OnChanges { + private gradingSystemService = inject(GradingSystemService); + private translateService = inject(TranslateService); + @Input() scores?: number[]; @@ -62,11 +69,6 @@ export class ParticipantScoresDistributionComponent implements OnInit, OnChanges } as Color; backupDomain: string[]; - constructor( - private gradingSystemService: GradingSystemService, - private translateService: TranslateService, - ) {} - ngOnInit() { this.setupAxisLabels(); diff --git a/src/main/webapp/app/shared/participant-scores/participant-scores.module.ts b/src/main/webapp/app/shared/participant-scores/participant-scores.module.ts index 13427531310c..30551dafe00d 100644 --- a/src/main/webapp/app/shared/participant-scores/participant-scores.module.ts +++ b/src/main/webapp/app/shared/participant-scores/participant-scores.module.ts @@ -7,8 +7,7 @@ import { ArtemisSharedComponentModule } from 'app/shared/components/shared-compo import { BarChartModule } from '@swimlane/ngx-charts'; @NgModule({ - imports: [ArtemisSharedModule, ArtemisDataTableModule, NgxDatatableModule, ArtemisSharedComponentModule, BarChartModule], - declarations: [ParticipantScoresDistributionComponent], + imports: [ArtemisSharedModule, ArtemisDataTableModule, NgxDatatableModule, ArtemisSharedComponentModule, BarChartModule, ParticipantScoresDistributionComponent], exports: [ParticipantScoresDistributionComponent], }) export class ArtemisParticipantScoresModule {} diff --git a/src/main/webapp/app/shared/participant-scores/participant-scores.service.ts b/src/main/webapp/app/shared/participant-scores/participant-scores.service.ts index 8038424d57cc..89553fba01e1 100644 --- a/src/main/webapp/app/shared/participant-scores/participant-scores.service.ts +++ b/src/main/webapp/app/shared/participant-scores/participant-scores.service.ts @@ -1,5 +1,5 @@ import { HttpClient, HttpResponse } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { Injectable, inject } from '@angular/core'; import { Observable } from 'rxjs'; export class ScoresDTO { @@ -12,9 +12,9 @@ export class ScoresDTO { @Injectable({ providedIn: 'root' }) export class ParticipantScoresService { - public resourceUrl = 'api'; + private http = inject(HttpClient); - constructor(private http: HttpClient) {} + public resourceUrl = 'api'; findCourseScores(courseId: number): Observable> { return this.http.get(`${this.resourceUrl}/courses/${courseId}/course-scores`, { diff --git a/src/main/webapp/app/shared/pipes/artemis-date-range.pipe.ts b/src/main/webapp/app/shared/pipes/artemis-date-range.pipe.ts index d372709977b1..3b7d8575dd4b 100644 --- a/src/main/webapp/app/shared/pipes/artemis-date-range.pipe.ts +++ b/src/main/webapp/app/shared/pipes/artemis-date-range.pipe.ts @@ -1,4 +1,4 @@ -import { Pipe, PipeTransform } from '@angular/core'; +import { Pipe, PipeTransform, inject } from '@angular/core'; import { ArtemisDatePipe, DateFormat, DateType } from 'app/shared/pipes/artemis-date.pipe'; @Pipe({ @@ -6,7 +6,8 @@ import { ArtemisDatePipe, DateFormat, DateType } from 'app/shared/pipes/artemis- pure: false, }) export class ArtemisDateRangePipe implements PipeTransform { - constructor(private artemisDatePipe: ArtemisDatePipe) {} + private artemisDatePipe = inject(ArtemisDatePipe); + transform(range: [DateType, DateType] | undefined | null, format: DateFormat = 'long-date', timeZone: string | undefined = undefined, weekDay = false): string { if (!range) { return ''; diff --git a/src/main/webapp/app/shared/pipes/artemis-date.pipe.ts b/src/main/webapp/app/shared/pipes/artemis-date.pipe.ts index cd3749e9ede0..d6197dcc566e 100644 --- a/src/main/webapp/app/shared/pipes/artemis-date.pipe.ts +++ b/src/main/webapp/app/shared/pipes/artemis-date.pipe.ts @@ -1,4 +1,4 @@ -import { OnDestroy, Pipe, PipeTransform } from '@angular/core'; +import { OnDestroy, Pipe, PipeTransform, inject } from '@angular/core'; import { LangChangeEvent, TranslateService } from '@ngx-translate/core'; import { Subscription } from 'rxjs'; import dayjs from 'dayjs/esm'; @@ -27,6 +27,8 @@ export type DateFormat = 'short' | 'long' | 'short-date' | 'long-date' | 'time'; pure: false, }) export class ArtemisDatePipe implements PipeTransform, OnDestroy { + private translateService = inject(TranslateService); + private dateTime: dayjs.Dayjs; private locale: string; private localizedDateTime: string; @@ -39,8 +41,6 @@ export class ArtemisDatePipe implements PipeTransform, OnDestroy { private showMilliSeconds = false; private static mobileDeviceSize = 768; - constructor(private translateService: TranslateService) {} - /** * Format a given dateTime to a localized date time string based on the current language setting. * @param dateTime The date time that should be formatted. Must be convertible to dayjs(). diff --git a/src/main/webapp/app/shared/pipes/artemis-time-ago.pipe.ts b/src/main/webapp/app/shared/pipes/artemis-time-ago.pipe.ts index 2b669b1f0b57..a999d73651cf 100644 --- a/src/main/webapp/app/shared/pipes/artemis-time-ago.pipe.ts +++ b/src/main/webapp/app/shared/pipes/artemis-time-ago.pipe.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, NgZone, OnDestroy, Pipe, PipeTransform } from '@angular/core'; +import { ChangeDetectorRef, NgZone, OnDestroy, Pipe, PipeTransform, inject } from '@angular/core'; import dayjs from 'dayjs/esm'; import { isDate } from 'app/shared/util/utils'; import { TranslateService } from '@ngx-translate/core'; @@ -8,6 +8,10 @@ import { TranslateService } from '@ngx-translate/core'; pure: false, }) export class ArtemisTimeAgoPipe implements PipeTransform, OnDestroy { + private cdRef = inject(ChangeDetectorRef); + private ngZone = inject(NgZone); + private translateService = inject(TranslateService); + private currentTimer: number | null; private lastTime: number; @@ -17,12 +21,6 @@ export class ArtemisTimeAgoPipe implements PipeTransform, OnDestroy { private lastText: string; private formatFn: (m: dayjs.Dayjs) => string; - constructor( - private cdRef: ChangeDetectorRef, - private ngZone: NgZone, - private translateService: TranslateService, - ) {} - format(date: dayjs.Dayjs) { return date.locale(this.lastLocale).from(dayjs(), this.lastOmitSuffix); } diff --git a/src/main/webapp/app/shared/pipes/artemis-translate.pipe.ts b/src/main/webapp/app/shared/pipes/artemis-translate.pipe.ts index 10a216f58635..c78b4d9a97e1 100644 --- a/src/main/webapp/app/shared/pipes/artemis-translate.pipe.ts +++ b/src/main/webapp/app/shared/pipes/artemis-translate.pipe.ts @@ -4,7 +4,6 @@ import { TranslatePipe, TranslateService } from '@ngx-translate/core'; @Pipe({ name: 'artemisTranslate', pure: false, - standalone: true, }) /** * a simple wrapper to prevent compile errors in IntelliJ @@ -17,6 +16,7 @@ export class ArtemisTranslatePipe implements PipeTransform, OnDestroy { * However, in this case due to being a wrapper class for TranslatePipe, which implements the same constructor * this exception should be okay. */ + // NOTE: we cannot use inject() here because of a limitation as this pipe is a wrapper constructor(translateService: TranslateService, changeDetectorRef: ChangeDetectorRef) { this.translatePipe = new TranslatePipe(translateService, changeDetectorRef); } diff --git a/src/main/webapp/app/shared/pipes/duration.pipe.ts b/src/main/webapp/app/shared/pipes/duration.pipe.ts index 16de8dcb3a4d..9d26069f6b65 100644 --- a/src/main/webapp/app/shared/pipes/duration.pipe.ts +++ b/src/main/webapp/app/shared/pipes/duration.pipe.ts @@ -2,9 +2,7 @@ import { Pipe, PipeTransform } from '@angular/core'; import dayjs from 'dayjs/esm'; -@Pipe({ - name: 'duration', -}) +@Pipe({ name: 'duration' }) // create a duration with the length of time in milliseconds // Note: if you want to create a duration with a unit of measurement other than milliseconds, you need to use a separate (custom) pipe https://day.js.org/docs/en/durations/creating export class DurationPipe implements PipeTransform { diff --git a/src/main/webapp/app/shared/pipes/exercise-course-title.pipe.ts b/src/main/webapp/app/shared/pipes/exercise-course-title.pipe.ts index 1a8c9dd15a74..2a6c482e182d 100644 --- a/src/main/webapp/app/shared/pipes/exercise-course-title.pipe.ts +++ b/src/main/webapp/app/shared/pipes/exercise-course-title.pipe.ts @@ -1,9 +1,7 @@ import { Pipe, PipeTransform } from '@angular/core'; import { Exercise } from 'app/entities/exercise.model'; -@Pipe({ - name: 'courseTitle', -}) +@Pipe({ name: 'courseTitle' }) export class ExerciseCourseTitlePipe implements PipeTransform { /** * Returns the course title of the exercise via the exerciseGroup or the usual course member diff --git a/src/main/webapp/app/shared/pipes/exercise-type.pipe.ts b/src/main/webapp/app/shared/pipes/exercise-type.pipe.ts index b71eea99542d..4707359ad762 100644 --- a/src/main/webapp/app/shared/pipes/exercise-type.pipe.ts +++ b/src/main/webapp/app/shared/pipes/exercise-type.pipe.ts @@ -1,9 +1,7 @@ import { Pipe, PipeTransform } from '@angular/core'; import { ExerciseType } from 'app/entities/exercise.model'; -@Pipe({ - name: 'exerciseTypeLabel', -}) +@Pipe({ name: 'exerciseTypeLabel' }) export class ExerciseTypePipe implements PipeTransform { /** * Returns the type of the exercise as a string. diff --git a/src/main/webapp/app/shared/pipes/feedback-content.pipe.ts b/src/main/webapp/app/shared/pipes/feedback-content.pipe.ts index 115cb9ecf263..fe87aa52b2b9 100644 --- a/src/main/webapp/app/shared/pipes/feedback-content.pipe.ts +++ b/src/main/webapp/app/shared/pipes/feedback-content.pipe.ts @@ -2,7 +2,6 @@ import { Pipe, PipeTransform } from '@angular/core'; import { Feedback } from 'app/entities/feedback.model'; @Pipe({ - standalone: true, name: 'feedbackContent', // impure: we need to detect changes in attributes of the feedback pure: false, diff --git a/src/main/webapp/app/shared/pipes/grade-step-bounds.pipe.ts b/src/main/webapp/app/shared/pipes/grade-step-bounds.pipe.ts index 6e9ece61b74b..b589911fa98b 100644 --- a/src/main/webapp/app/shared/pipes/grade-step-bounds.pipe.ts +++ b/src/main/webapp/app/shared/pipes/grade-step-bounds.pipe.ts @@ -6,7 +6,6 @@ import { round } from 'app/shared/util/utils'; @Pipe({ name: 'gradeStepBounds', pure: false, - standalone: true, }) export class GradeStepBoundsPipe implements PipeTransform { /** diff --git a/src/main/webapp/app/shared/pipes/html-for-markdown.pipe.ts b/src/main/webapp/app/shared/pipes/html-for-markdown.pipe.ts index 89403223abe9..23343b63563f 100644 --- a/src/main/webapp/app/shared/pipes/html-for-markdown.pipe.ts +++ b/src/main/webapp/app/shared/pipes/html-for-markdown.pipe.ts @@ -5,7 +5,6 @@ import type { PluginSimple } from 'markdown-it'; @Pipe({ name: 'htmlForMarkdown', - standalone: true, }) export class HtmlForMarkdownPipe implements PipeTransform { private readonly markdownService = inject(ArtemisMarkdownService); diff --git a/src/main/webapp/app/shared/pipes/html-for-posting-markdown.pipe.ts b/src/main/webapp/app/shared/pipes/html-for-posting-markdown.pipe.ts index 3cdfd3cf09a7..7def62f3817f 100644 --- a/src/main/webapp/app/shared/pipes/html-for-posting-markdown.pipe.ts +++ b/src/main/webapp/app/shared/pipes/html-for-posting-markdown.pipe.ts @@ -4,7 +4,6 @@ import { ArtemisMarkdownService } from 'app/shared/markdown.service'; @Pipe({ name: 'htmlForPostingMarkdown', - standalone: true, }) export class HtmlForPostingMarkdownPipe implements PipeTransform { private readonly markdownService = inject(ArtemisMarkdownService); diff --git a/src/main/webapp/app/shared/pipes/quote.pipe.ts b/src/main/webapp/app/shared/pipes/quote.pipe.ts index c74ca81c2ed8..0fafba66c64f 100644 --- a/src/main/webapp/app/shared/pipes/quote.pipe.ts +++ b/src/main/webapp/app/shared/pipes/quote.pipe.ts @@ -1,7 +1,6 @@ import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ - standalone: true, name: 'quoted', }) export class QuotePipe implements PipeTransform { diff --git a/src/main/webapp/app/shared/pipes/reacting-users-on-posting.pipe.ts b/src/main/webapp/app/shared/pipes/reacting-users-on-posting.pipe.ts index 85d82230ba25..2fb5050d4906 100644 --- a/src/main/webapp/app/shared/pipes/reacting-users-on-posting.pipe.ts +++ b/src/main/webapp/app/shared/pipes/reacting-users-on-posting.pipe.ts @@ -1,4 +1,4 @@ -import { Pipe, PipeTransform } from '@angular/core'; +import { Pipe, PipeTransform, inject } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs'; @@ -8,11 +8,9 @@ export const PLACEHOLDER_USER_REACTED = 'REPLACE_WITH_TRANSLATED_YOU'; /** * Pipe to show list of reacting users when hovering over emojis. */ -@Pipe({ - name: 'reactingUsersOnPosting', -}) +@Pipe({ name: 'reactingUsersOnPosting' }) export class ReactingUsersOnPostingPipe implements PipeTransform { - constructor(private translateService: TranslateService) {} + private translateService = inject(TranslateService); /** * Transforms a given name list of reacting users to a prosaic, translated string diff --git a/src/main/webapp/app/shared/pipes/safe-html.pipe.ts b/src/main/webapp/app/shared/pipes/safe-html.pipe.ts index 56d9728cb387..4ea5b1c88b50 100644 --- a/src/main/webapp/app/shared/pipes/safe-html.pipe.ts +++ b/src/main/webapp/app/shared/pipes/safe-html.pipe.ts @@ -1,9 +1,9 @@ -import { Pipe, PipeTransform } from '@angular/core'; +import { Pipe, PipeTransform, inject } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; -@Pipe({ name: 'safeHtml', standalone: true }) +@Pipe({ name: 'safeHtml' }) export class SafeHtmlPipe implements PipeTransform { - constructor(private sanitizer: DomSanitizer) {} + private sanitizer = inject(DomSanitizer); /** * Bypasses the security checks for a specified HTML. diff --git a/src/main/webapp/app/shared/pipes/safe-resource-url.pipe.ts b/src/main/webapp/app/shared/pipes/safe-resource-url.pipe.ts index f2392f5701b8..9f5b8f67939d 100644 --- a/src/main/webapp/app/shared/pipes/safe-resource-url.pipe.ts +++ b/src/main/webapp/app/shared/pipes/safe-resource-url.pipe.ts @@ -1,9 +1,9 @@ -import { Pipe, PipeTransform } from '@angular/core'; +import { Pipe, PipeTransform, inject } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; @Pipe({ name: 'safeResourceUrl' }) export class SafeResourceUrlPipe implements PipeTransform { - constructor(private sanitizer: DomSanitizer) {} + private sanitizer = inject(DomSanitizer); /** * Pipe that can be used to bypass security for a resource url, e.g. for `