diff --git a/build.gradle b/build.gradle index 1375d3298583..676cfebf43b5 100644 --- a/build.gradle +++ b/build.gradle @@ -252,6 +252,8 @@ dependencies { implementation "de.jplag:swift:${jplag_version}" implementation "de.jplag:java:${jplag_version}" implementation "de.jplag:python-3:${jplag_version}" + implementation "de.jplag:rust:${jplag_version}" + implementation "de.jplag:javascript:${jplag_version}" implementation "de.jplag:text:${jplag_version}" // those are transitive dependencies of JPlag Text --> Stanford NLP @@ -270,7 +272,7 @@ dependencies { } } - implementation "org.apache.logging.log4j:log4j-to-slf4j:2.24.0" + implementation "org.apache.logging.log4j:log4j-to-slf4j:2.24.1" // Note: spring-security-lti13 does not work with jakarta yet, so we built our own custom version and declare its transitive dependencies below // implementation "uk.ac.ox.ctl:spring-security-lti13:0.1.11" @@ -342,7 +344,7 @@ dependencies { implementation "tech.jhipster:jhipster-framework:${jhipster_dependencies_version}" implementation "org.springframework.boot:spring-boot-starter-cache:${spring_boot_version}" - implementation "io.micrometer:micrometer-registry-prometheus:1.13.4" + implementation "io.micrometer:micrometer-registry-prometheus:1.13.5" implementation "net.logstash.logback:logstash-logback-encoder:8.0" // Defines low-level streaming API, and includes JSON-specific implementations @@ -405,7 +407,7 @@ dependencies { implementation "org.springframework.cloud:spring-cloud-starter-config:4.1.3" implementation "org.springframework.cloud:spring-cloud-commons:4.1.4" - implementation "io.netty:netty-all:4.1.113.Final" + implementation "io.netty:netty-all:4.1.114.Final" implementation "io.projectreactor.netty:reactor-netty:1.1.22" implementation "org.springframework:spring-messaging:6.1.13" implementation "org.springframework.retry:spring-retry:2.0.9" @@ -416,7 +418,7 @@ dependencies { implementation "org.springframework.security:spring-security-oauth2-core:${spring_security_version}" implementation "org.springframework.security:spring-security-oauth2-client:${spring_security_version}" // use newest version of nimbus-jose-jwt to avoid security issues through outdated dependencies - implementation "com.nimbusds:nimbus-jose-jwt:9.41.1" + implementation "com.nimbusds:nimbus-jose-jwt:9.41.2" implementation "org.springframework.security:spring-security-oauth2-jose:${spring_security_version}" implementation "org.springframework.security:spring-security-crypto:${spring_security_version}" @@ -464,7 +466,7 @@ dependencies { implementation "com.google.code.gson:gson:2.11.0" - implementation "com.google.errorprone:error_prone_annotations:2.32.0" + implementation "com.google.errorprone:error_prone_annotations:2.33.0" // NOTE: we want to keep the same unique version for all configurations, implementation and annotationProcessor implementation("net.bytebuddy:byte-buddy") { @@ -528,7 +530,7 @@ dependencies { testImplementation "org.mockito:mockito-core:${mockito_version}" testImplementation "org.mockito:mockito-junit-jupiter:${mockito_version}" - testImplementation "io.github.classgraph:classgraph:4.8.176" + testImplementation "io.github.classgraph:classgraph:4.8.177" testImplementation "org.awaitility:awaitility:4.2.2" testImplementation "org.apache.maven.shared:maven-invoker:3.3.0" testImplementation "org.gradle:gradle-tooling-api:8.10.2" diff --git a/docs/user/exercises/programming-exercise-features.inc b/docs/user/exercises/programming-exercise-features.inc index 6d0b257dd96e..7bccf1596315 100644 --- a/docs/user/exercises/programming-exercise-features.inc +++ b/docs/user/exercises/programming-exercise-features.inc @@ -67,9 +67,9 @@ Instructors can still use those templates to generate programming exercises and +----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+ | OCaml | no | no | no | no | n/a | yes | no | L: yes, J: no | +----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+ - | Rust | no | no | no | no | n/a | no | no | L: yes, J: no | + | Rust | no | no | yes | no | n/a | no | no | L: yes, J: no | +----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+ - | JavaScript | no | no | no | no | n/a | no | no | L: yes, J: no | + | JavaScript | no | no | yes | no | n/a | no | no | L: yes, J: no | +----------------------+----------------------+----------------------+---------------------+--------------+------------------------------------------+------------------------------+----------------------------+------------------------+ - *Sequential Test Runs*: ``Artemis`` can generate a build plan which first executes structural and then behavioral tests. This feature can help students to better concentrate on the immediate challenge at hand. diff --git a/gradle.properties b/gradle.properties index fc54fad2849b..46526dddaf56 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,8 +18,8 @@ jaxb_runtime_version=4.0.5 hazelcast_version=5.5.0 fasterxml_version=2.18.0 jgit_version=7.0.0.202409031743-r -sshd_version=2.13.2 -checkstyle_version=10.18.1 +sshd_version=2.14.0 +checkstyle_version=10.18.2 jplag_version=5.1.0 # not really used in Artemis, nor Jplag, nor the used version of Stanford CoreNLP, but we use the latest to avoid security vulnerabilities # NOTE: we do not need to use the latest version 9.x here as long as Stanford CoreNLP does not reference it @@ -36,11 +36,11 @@ byte_buddy_version=1.15.3 # make sure both versions are compatible junit_version=5.11.0 junit_platform_version=1.11.1 -mockito_version=5.13.0 +mockito_version=5.14.1 # gradle plugin version -gradle_node_plugin_version=7.0.2 +gradle_node_plugin_version=7.1.0 apt_plugin_version=0.21 liquibase_plugin_version=2.1.1 modernizer_plugin_version=1.9.3 diff --git a/jest.config.js b/jest.config.js index 41354957ab0d..3dab49d4b7e0 100644 --- a/jest.config.js +++ b/jest.config.js @@ -102,10 +102,10 @@ module.exports = { coverageThreshold: { global: { // TODO: in the future, the following values should increase to at least 90% - statements: 87.35, - branches: 73.57, - functions: 81.91, - lines: 87.41, + statements: 87.37, + branches: 73.68, + functions: 81.93, + lines: 87.42, }, }, coverageReporters: ['clover', 'json', 'lcov', 'text-summary'], diff --git a/package-lock.json b/package-lock.json index bc1d3b7dff03..4df008b09a23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,18 +10,18 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@angular/animations": "18.2.6", - "@angular/cdk": "18.2.6", - "@angular/common": "18.2.6", - "@angular/compiler": "18.2.6", - "@angular/core": "18.2.6", - "@angular/forms": "18.2.6", - "@angular/localize": "18.2.6", - "@angular/material": "18.2.6", - "@angular/platform-browser": "18.2.6", - "@angular/platform-browser-dynamic": "18.2.6", - "@angular/router": "18.2.6", - "@angular/service-worker": "18.2.6", + "@angular/animations": "18.2.7", + "@angular/cdk": "18.2.7", + "@angular/common": "18.2.7", + "@angular/compiler": "18.2.7", + "@angular/core": "18.2.7", + "@angular/forms": "18.2.7", + "@angular/localize": "18.2.7", + "@angular/material": "18.2.7", + "@angular/platform-browser": "18.2.7", + "@angular/platform-browser-dynamic": "18.2.7", + "@angular/router": "18.2.7", + "@angular/service-worker": "18.2.7", "@ctrl/ngx-emoji-mart": "9.2.0", "@danielmoncada/angular-datetime-picker": "18.1.0", "@fingerprintjs/fingerprintjs": "4.5.0", @@ -33,7 +33,7 @@ "@ng-bootstrap/ng-bootstrap": "17.0.1", "@ngx-translate/core": "15.0.0", "@ngx-translate/http-loader": "8.0.0", - "@sentry/angular": "8.32.0", + "@sentry/angular": "8.33.1", "@siemens/ngx-datatable": "22.4.1", "@swimlane/ngx-charts": "20.5.0", "@swimlane/ngx-graph": "8.4.0", @@ -60,7 +60,7 @@ "ngx-webstorage": "18.0.0", "papaparse": "5.4.1", "pdfjs-dist": "4.6.82", - "posthog-js": "1.165.0", + "posthog-js": "1.166.1", "rxjs": "7.8.1", "showdown": "2.1.0", "showdown-highlight": "3.1.0", @@ -78,29 +78,29 @@ }, "devDependencies": { "@angular-builders/jest": "18.0.0", - "@angular-devkit/build-angular": "18.2.6", + "@angular-devkit/build-angular": "18.2.7", "@angular-eslint/builder": "18.3.1", "@angular-eslint/eslint-plugin": "18.3.1", "@angular-eslint/eslint-plugin-template": "18.3.1", "@angular-eslint/schematics": "18.3.1", "@angular-eslint/template-parser": "18.3.1", - "@angular/cli": "18.2.6", - "@angular/compiler-cli": "18.2.6", - "@angular/language-service": "18.2.6", - "@sentry/types": "8.32.0", + "@angular/cli": "18.2.7", + "@angular/compiler-cli": "18.2.7", + "@angular/language-service": "18.2.7", + "@sentry/types": "8.33.1", "@types/crypto-js": "4.2.2", "@types/d3-shape": "3.1.6", "@types/dompurify": "3.0.5", "@types/jest": "29.5.13", "@types/lodash-es": "4.17.12", - "@types/node": "22.7.3", + "@types/node": "22.7.4", "@types/papaparse": "5.3.14", "@types/showdown": "2.0.6", "@types/smoothscroll-polyfill": "0.3.4", "@types/sockjs-client": "1.5.4", "@types/uuid": "10.0.0", - "@typescript-eslint/eslint-plugin": "8.7.0", - "@typescript-eslint/parser": "8.7.0", + "@typescript-eslint/eslint-plugin": "8.8.0", + "@typescript-eslint/parser": "8.8.0", "eslint": "9.11.1", "eslint-config-prettier": "9.1.0", "eslint-plugin-deprecation": "3.0.0", @@ -113,7 +113,7 @@ "jest-canvas-mock": "2.5.2", "jest-date-mock": "1.0.10", "jest-extended": "4.0.2", - "jest-fail-on-console": "3.3.0", + "jest-fail-on-console": "3.3.1", "jest-junit": "16.0.0", "jest-preset-angular": "14.2.4", "lint-staged": "15.2.10", @@ -121,7 +121,7 @@ "ngxtension": "4.0.0", "prettier": "3.3.3", "rimraf": "6.0.1", - "sass": "1.79.3", + "sass": "1.79.4", "ts-jest": "29.2.5", "typescript": "5.5.4", "weak-napi": "2.0.2" @@ -212,13 +212,13 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1802.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.6.tgz", - "integrity": "sha512-oF7cPFdTLxeuvXkK/opSdIxZ1E4LrBbmuytQ/nCoAGOaKBWdqvwagRZ6jVhaI0Gwu48rkcV7Zhesg/ESNnROdw==", + "version": "0.1802.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.7.tgz", + "integrity": "sha512-kpcgXnepEXcoxDTbqbGj7Hg1WJLWj1HLR3/FKmC5TbpBf1xiLxiqfkQNwz3BbE/W9JWMLdrXr3GI9O3O2gWPLg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.6", + "@angular-devkit/core": "18.2.7", "rxjs": "7.8.1" }, "engines": { @@ -228,17 +228,17 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.6.tgz", - "integrity": "sha512-u12cJZttgs5j7gICHWSmcaTCu0EFXEzKqI8nkYCwq2MtuJlAXiMQSXYuEP9OU3Go4vMAPtQh2kShyOWCX5b4EQ==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.7.tgz", + "integrity": "sha512-u8PriYdgddK7k+OS/pOFPD1v4Iu5bztUJZXZVcGeXBZFFdnGFFzKmQw9mfcyGvTMJp2ABgBuuJT0YqYgNfAhzw==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1802.6", - "@angular-devkit/build-webpack": "0.1802.6", - "@angular-devkit/core": "18.2.6", - "@angular/build": "18.2.6", + "@angular-devkit/architect": "0.1802.7", + "@angular-devkit/build-webpack": "0.1802.7", + "@angular-devkit/core": "18.2.7", + "@angular/build": "18.2.7", "@babel/core": "7.25.2", "@babel/generator": "7.25.0", "@babel/helper-annotate-as-pure": "7.24.7", @@ -249,7 +249,7 @@ "@babel/preset-env": "7.25.3", "@babel/runtime": "7.25.0", "@discoveryjs/json-ext": "0.6.1", - "@ngtools/webpack": "18.2.6", + "@ngtools/webpack": "18.2.7", "@vitejs/plugin-basic-ssl": "1.1.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.20", @@ -382,13 +382,13 @@ "license": "0BSD" }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1802.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.6.tgz", - "integrity": "sha512-JMLcXFaitJplwZMKkqhbYirINCRD6eOPZuIGaIOVynXYGWgvJkLT9t5C2wm9HqSLtp1K7NcYG2Y7PtTVR4krnQ==", + "version": "0.1802.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.7.tgz", + "integrity": "sha512-VrtbrhZ+dht3f0GjtfRLRGRN4XHN/W+/bA9DqckdxVS6SydsrCWNHonvEPmOs4jJmGIGXIu6tUBMcWleTao2sg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1802.6", + "@angular-devkit/architect": "0.1802.7", "rxjs": "7.8.1" }, "engines": { @@ -402,9 +402,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.6.tgz", - "integrity": "sha512-la4CFvs5PcRWSkQ/H7TB5cPZirFVA9GoWk5LzIk8si6VjWBJRm8b3keKJoC9LlNeABRUIR5z0ocYkyQQUhdMfg==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.7.tgz", + "integrity": "sha512-1ZTi4A6tEC2bkJ/puCIdIPYhesnlCVOMSDJL/lZAd0hC6X22T4pwu0AEvue7mcP5NbXpQDiBaXOZ3MmCA8PwOA==", "dev": true, "license": "MIT", "dependencies": { @@ -430,13 +430,13 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.6.tgz", - "integrity": "sha512-uIttrQ2cQ2PWAFFVPeCoNR8xvs7tPJ2i8gzqsIwYdge107xDC6u9CqfgmBqPDSFpWj+IiC2Jwcm8Z4HYKU4+7A==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.7.tgz", + "integrity": "sha512-j7198lpkOXMG+Gyfln/5aDgBZV7m4pWMzHFhkO3+w3cbCNUN1TVZW0SyJcF+CYaxANzTbuumfvpsYc/fTeAGLw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.6", + "@angular-devkit/core": "18.2.7", "jsonc-parser": "3.3.1", "magic-string": "0.30.11", "ora": "5.4.1", @@ -549,9 +549,9 @@ } }, "node_modules/@angular/animations": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.6.tgz", - "integrity": "sha512-vy9wy+Q9beiRxkEO8wNxFQ63AqAujGvk8AUHepxxIT7QNNc512TNKz8uH+feWDPO38Dm2obwYQHMGzs3WO7pUA==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.7.tgz", + "integrity": "sha512-5B7qD1K+kKOf9lgJT4VNMft3IK2BnRHjN1S6l38ywzQ/nxpmCG7f+qKAAU6CpCywhNUBeXW0hVXTMuMNPVOcQQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -560,18 +560,18 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.6" + "@angular/core": "18.2.7" } }, "node_modules/@angular/build": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.6.tgz", - "integrity": "sha512-TQzX6Mi7uXFvmz7+OVl4Za7WawYPcx+B5Ewm6IY/DdMyB9P/Z4tbKb1LO+ynWUXYwm7avXo6XQQ4m5ArDY5F/A==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.7.tgz", + "integrity": "sha512-oq6JsVxLP9/w9F2IjKroJwPB9CdlMblu2Xhfq/qQZRSUuM8Ppt1svr2FBTo1HrLIbosqukkVcSSdmKYDneo+cg==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1802.6", + "@angular-devkit/architect": "0.1802.7", "@babel/core": "7.25.2", "@babel/helper-annotate-as-pure": "7.24.7", "@babel/helper-split-export-declaration": "7.24.7", @@ -651,9 +651,9 @@ } }, "node_modules/@angular/cdk": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.2.6.tgz", - "integrity": "sha512-Gfq/iv4zhlKYpdQkDaBRwxI71NHNUHM1Cs1XhnZ0/oFct5HXvSv1RHRGTKqBJLLACaAPzZKXJ/UglLoyO5CNiQ==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-18.2.7.tgz", + "integrity": "sha512-Dfl37WBLeEUURQrDeuMcOgX2bkQJ+BGMOlr1qsFXzUWHH+qgYW2YwO1rbna/rjxyeFzc2Sy569dYRzNPqMewzg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -668,18 +668,18 @@ } }, "node_modules/@angular/cli": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.6.tgz", - "integrity": "sha512-tdXsnV/w+Rgu8q0zFsLU5L9ImTVqrTol1vppHaQkJ/vuoHy+s8ZEbBqhVrO/ffosNb2xseUybGYvqMS4zkNQjg==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.7.tgz", + "integrity": "sha512-KoWgSvhRsU05A2m6B7jw1kdpyoS+Ce5GGLW6xcnX7VF2AckW54vYd/8ZkgpzQrKfvIpVblYd4KJGizKoaLZ5jA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1802.6", - "@angular-devkit/core": "18.2.6", - "@angular-devkit/schematics": "18.2.6", + "@angular-devkit/architect": "0.1802.7", + "@angular-devkit/core": "18.2.7", + "@angular-devkit/schematics": "18.2.7", "@inquirer/prompts": "5.3.8", "@listr2/prompt-adapter-inquirer": "2.0.15", - "@schematics/angular": "18.2.6", + "@schematics/angular": "18.2.7", "@yarnpkg/lockfile": "1.1.0", "ini": "4.1.3", "jsonc-parser": "3.3.1", @@ -702,9 +702,9 @@ } }, "node_modules/@angular/common": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.6.tgz", - "integrity": "sha512-89793ow+wrI1c7C6kyMbnweLNIZHzXthosxAEjipRZGBrqBYjvTtkE45Fl+5yBa3JO7bAhyGkUnEoyvWtZIAEA==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.7.tgz", + "integrity": "sha512-5vDBmBR2JcIxHVEDunKXNU+T+OvTGiHZTSo35GFOHJxKFgX5g6+0tJBZunK04oBZGbJQUmp3pg2kMvuKKjZnkQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -713,14 +713,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.6", + "@angular/core": "18.2.7", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.6.tgz", - "integrity": "sha512-3tX2/Qw+bZ8XzKitviH8jzNGyY0uohhehhBB57OJOCc+yr4ojy/7SYFnun1lSsRnDztdCE461641X4iQLCQ94w==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.7.tgz", + "integrity": "sha512-XemlYyRGnu/HrICtXwTPmGtyOrI8BhbGg/HMiJ7sVx40AeEIX0uyDgnu9Gc5OjmtDqZZ8Qftg1sQAxaCVjLb1w==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -729,7 +729,7 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.6" + "@angular/core": "18.2.7" }, "peerDependenciesMeta": { "@angular/core": { @@ -738,9 +738,9 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.6.tgz", - "integrity": "sha512-b5x9STfjNiNM/S0D+CnqRP9UOxPtSz1+RlCH5WdOMiW/p8j5p6dBix8YYgTe6Wg3OD7eItD2pnFQKgF/dWiopA==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.7.tgz", + "integrity": "sha512-U7cveObj+rrXH5EC8egAhATCeAAcOceEQDTVIOWmBa0qMR4hOMjtI2XUS2QRuI1Q+fQZ2hVEOW95WVLvEMsANA==", "license": "MIT", "dependencies": { "@babel/core": "7.25.2", @@ -761,14 +761,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "18.2.6", + "@angular/compiler": "18.2.7", "typescript": ">=5.4 <5.6" } }, "node_modules/@angular/core": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.6.tgz", - "integrity": "sha512-PjFad2j4YBwLVTw+0Te8CJCa/tV0W8caTHG8aOjj3ObdL6ihGI+FKnwerLc9RVzDFd14BOO4C6/+LbOQAh3Ltw==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.7.tgz", + "integrity": "sha512-hLOxgxLiyWm9iVHBsUsJfx1hDsXWZnfJBlr+N7cev53f0CDoPfbshqq6KV+JFqXFDguzR9dKHm1ewT1jK3e6Tw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -782,9 +782,9 @@ } }, "node_modules/@angular/forms": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.6.tgz", - "integrity": "sha512-quGkUqTxlBaLB8C/RnpfFG57fdmNF5RQ+368N89Ma++2lpIsVAHaGZZn4yOyo3wNYaM2jBxNqaYxOzZNUl5Tig==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.7.tgz", + "integrity": "sha512-WO3c9/OA7ekBnDBgmvi5TlHshOt5S4NREIP+/VVyuRgg28BwUWyO/Nqh19nguE1UNNRt6OMLkT6NSV2ewhcXUg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -793,16 +793,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.6", - "@angular/core": "18.2.6", - "@angular/platform-browser": "18.2.6", + "@angular/common": "18.2.7", + "@angular/core": "18.2.7", + "@angular/platform-browser": "18.2.7", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.2.6.tgz", - "integrity": "sha512-GBvBvS2llh+/l2YhO7UO5o3GftlvQQoXnw3v0hcNoHKwcnvqXV4CCi+T2WOaZyK0iB8Is4QRbMrpJUC66HokZg==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.2.7.tgz", + "integrity": "sha512-gFsme3y5uC/dQGBBX05VnmT2KAEAZ6gsNk8m1b226LYvh8Oc+JQ4sXv7THGq1x5VnrTzRcCIELbkNHCiFdvL1Q==", "dev": true, "license": "MIT", "engines": { @@ -810,9 +810,9 @@ } }, "node_modules/@angular/localize": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-18.2.6.tgz", - "integrity": "sha512-4NZwh5EAyXItmwv6hqilV+JyN8DT+d+S1rW+M1IwJqC9asCDfpFqipKpuQF81LQKeLH0mn/phNfVbnJCLP0Tkw==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-18.2.7.tgz", + "integrity": "sha512-qYozomhO+1BlvtoMEEgKhaKz8thoztqNZEYPq9RmfkTB5uW7Q8h6rr1Sc2YAzJ6+ZA0McwabdJSX1TDxWyZx0Q==", "license": "MIT", "dependencies": { "@babel/core": "7.25.2", @@ -829,21 +829,21 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "18.2.6", - "@angular/compiler-cli": "18.2.6" + "@angular/compiler": "18.2.7", + "@angular/compiler-cli": "18.2.7" } }, "node_modules/@angular/material": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-18.2.6.tgz", - "integrity": "sha512-ObxC/vomSb9QF3vIztuiInQzws+D6u09Dhfx6uNFjtyICqxEFpF7+Qx7QVDWrsuXOgxZTKgacK8f46iV8hWUfg==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-18.2.7.tgz", + "integrity": "sha512-mgPj2TCIrsngmu3iNnoaPc6su7uPv+NPCv9HaiKhTx4QGae8EW+RvUxEZJvh4Qaym1fJTi3hjnVeWvQDLQt4CA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { "@angular/animations": "^18.0.0 || ^19.0.0", - "@angular/cdk": "18.2.6", + "@angular/cdk": "18.2.7", "@angular/common": "^18.0.0 || ^19.0.0", "@angular/core": "^18.0.0 || ^19.0.0", "@angular/forms": "^18.0.0 || ^19.0.0", @@ -852,9 +852,9 @@ } }, "node_modules/@angular/platform-browser": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.6.tgz", - "integrity": "sha512-RA8UMiYNLga+QMwpKcDw1357gYPfPyY/rmLeezMak//BbsENFYQOJ4Z6DBOBNiPlHxmBsUJMGaKdlpQhfCROyQ==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.7.tgz", + "integrity": "sha512-xgj2DH/isFrMZ73dJJm89NRnWBI3AHtugQrZbIapkKBdEt/C1o4SR2W2cV4mPb9o+ELnWurfrxFt9o/q2vnVLw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -863,9 +863,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "18.2.6", - "@angular/common": "18.2.6", - "@angular/core": "18.2.6" + "@angular/animations": "18.2.7", + "@angular/common": "18.2.7", + "@angular/core": "18.2.7" }, "peerDependenciesMeta": { "@angular/animations": { @@ -874,9 +874,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.6.tgz", - "integrity": "sha512-kGBU3FNc+DF9r33hwHZqiWoZgQbCDdEIucU0NCLCIg0Hw6/Q9Hr2ndjxQI+WynCPg0JeBn34jpouvpeJer3YDQ==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.7.tgz", + "integrity": "sha512-BDldzUKjnUjo0NW5gHjBY6CeJP1bWVfF1h/T3idyYG+F4Lxlb3aykRgLWXg4srNLY1KqE7XOYUmgc5cV613bgw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -885,16 +885,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.6", - "@angular/compiler": "18.2.6", - "@angular/core": "18.2.6", - "@angular/platform-browser": "18.2.6" + "@angular/common": "18.2.7", + "@angular/compiler": "18.2.7", + "@angular/core": "18.2.7", + "@angular/platform-browser": "18.2.7" } }, "node_modules/@angular/router": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.6.tgz", - "integrity": "sha512-t57Sqja8unHhZlPr+4CWnQacuox2M4p2pMHps+31wt337qH6mKf4jqDmK0dE/MFdRyKjT2a2E/2NwtxXxcWNuw==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.7.tgz", + "integrity": "sha512-TXE8Aw63hDp3PEaNu4B1DMNvlS0uCzs36o/OSCCmewmLnzyJygkgi4jeEj20FsWPAQOUj5g5tnCYgxz1IRrCUg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -903,16 +903,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.6", - "@angular/core": "18.2.6", - "@angular/platform-browser": "18.2.6", + "@angular/common": "18.2.7", + "@angular/core": "18.2.7", + "@angular/platform-browser": "18.2.7", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/service-worker": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-18.2.6.tgz", - "integrity": "sha512-KNqRAunG0yj3jVA/YYKH9wbAe261gAIwKeQsJyeMHGR48H88tSKdcstttNZZ3S6wdhp7tcyUC526Fc4phXnSJw==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-18.2.7.tgz", + "integrity": "sha512-1t8PUWmZi32i/SG/r12vz+cfn0l3xVEa0FY7GXaZK7hlfDL34js1HZXHkvGUuRZRw/4L1jl7AwPoxwGeWr2ldg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -924,17 +924,17 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.6", - "@angular/core": "18.2.6" + "@angular/common": "18.2.7", + "@angular/core": "18.2.7" } }, "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", "license": "MIT", "dependencies": { - "@babel/highlight": "^7.24.7", + "@babel/highlight": "^7.25.7", "picocolors": "^1.0.0" }, "engines": { @@ -942,9 +942,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", - "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", + "integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1014,28 +1014,28 @@ } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", - "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.7.tgz", + "integrity": "sha512-12xfNeKNH7jubQNm7PAkzlLwEmCs1tfuX3UjIw6vP6QXi+leKh6+LyC/+Ed4EIQermwd58wsyh070yjDHFlNGg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", - "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", + "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", + "@babel/compat-data": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -1044,18 +1044,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz", - "integrity": "sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.7.tgz", + "integrity": "sha512-bD4WQhbkx80mAyj/WCm4ZHcF4rDxkoLFO6ph8/5/mQ3z4vAzltQXAmbc7GvVJx5H+lk5Mi5EmbTeox5nMGCsbw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.25.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/traverse": "^7.25.4", + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/traverse": "^7.25.7", "semver": "^6.3.1" }, "engines": { @@ -1065,15 +1065,28 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", - "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.7.tgz", + "integrity": "sha512-byHhumTj/X47wJ6C6eLpK7wW/WBEcnUeb7D0FNc/jFQnQVw7DOso3Zz5u9x/zLrFVkHa89ZGDbkAa1D54NdrCQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "regexpu-core": "^5.3.1", + "@babel/helper-annotate-as-pure": "^7.25.7", + "regexpu-core": "^6.1.1", "semver": "^6.3.1" }, "engines": { @@ -1083,6 +1096,19 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-define-polyfill-provider": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", @@ -1101,42 +1127,42 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", - "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.7.tgz", + "integrity": "sha512-O31Ssjd5K6lPbTX9AAYpSKrZmLeagt9uwschJd+Ixo6QiRyfpvgtVQp8qrDR9UNFjZ8+DO34ZkdrN+BnPXemeA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.8" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", + "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", - "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", + "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.2" + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1146,37 +1172,37 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.7.tgz", + "integrity": "sha512-VAwcwuYhv/AT+Vfr28c9y6SHzTan1ryqrydSTFGjU0uDJHw3uZ+PduI8plCLkRsDnqK2DMEDmwrOQRsK/Ykjng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", + "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", - "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.7.tgz", + "integrity": "sha512-kRGE89hLnPfcz6fTrlNU+uhgcwv0mBE4Gv3P9Ke9kLVJYpi4AMVVEElXvB5CabrPZW4nCM8P8UyyjrzCM0O2sw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-wrap-function": "^7.25.0", - "@babel/traverse": "^7.25.0" + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-wrap-function": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1185,16 +1211,29 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-replace-supers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", - "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.7.tgz", + "integrity": "sha512-iy8JhqlUW9PtZkd4pHM96v6BdJ66Ba9yWSE4z0W4TvSZwLBPkyDsiIU3ENe4SmrzRBs76F7rQXTy1lYC49n6Lw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/traverse": "^7.25.0" + "@babel/helper-member-expression-to-functions": "^7.25.7", + "@babel/helper-optimise-call-expression": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1204,27 +1243,27 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", + "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.7.tgz", + "integrity": "sha512-pPbNbchZBkPMD50K0p3JGcFMNLVUCuU/ABybm/PGNj4JiHrpmNyqqCphBk4i19xXtNV0JhldQJJtbSW5aUvbyA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1244,67 +1283,67 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", + "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", - "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.7.tgz", + "integrity": "sha512-MA0roW3JF2bD1ptAaJnvcabsVlNQShUaThyJbCDD4bCp8NEgiFvpoqRI2YS22hHlc2thjO/fTg2ShLMC3jygAg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", - "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", + "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", "license": "MIT", "dependencies": { - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6" + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-validator-identifier": "^7.25.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -1314,12 +1353,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", - "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", + "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6" + "@babel/types": "^7.25.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -1329,14 +1368,14 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", - "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.7.tgz", + "integrity": "sha512-UV9Lg53zyebzD1DwQoT9mzkEKa922LNUp5YkTJ6Uta0RbyXaQNUgcvSt7qIu1PpPzVb6rd10OVNTzkyBGeVmxQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/traverse": "^7.25.3" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1346,13 +1385,13 @@ } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", - "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.7.tgz", + "integrity": "sha512-GDDWeVLNxRIkQTnJn2pDOM1pkCgYdSqPeT1a9vh9yIqu2uzzgw1zcqEb+IJOhy+dTBMlNdThrDIksr2o09qrrQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1362,13 +1401,13 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", - "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.7.tgz", + "integrity": "sha512-wxyWg2RYaSUYgmd9MR0FyRGyeOMQE/Uzr1wzd/g5cf5bwi9A4v6HFdDm7y1MgDtod/fLOSTZY6jDgV0xU9d5bA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1378,15 +1417,15 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", - "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.7.tgz", + "integrity": "sha512-Xwg6tZpLxc4iQjorYsyGMyfJE7nP5MV8t/Ka58BgiA7Jw0fRqQNcANlLfdJ/yvBt9z9LD2We+BEkT7vLqZRWng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", + "@babel/plugin-transform-optional-chaining": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1396,14 +1435,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", - "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.7.tgz", + "integrity": "sha512-UVATLMidXrnH+GMUIuxq55nejlj02HP7F5ETyBONzP6G87fPBogG4CH6kxrSrdIuAjdwNO9VzyaYsrZPscWUrw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/traverse": "^7.25.0" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1507,13 +1546,13 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz", - "integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.7.tgz", + "integrity": "sha512-ZvZQRmME0zfJnDQnVBKYzHxXT7lYBB3Revz1GuS7oLXWMgqUPX4G+DDbT30ICClht9WKV34QVrZhSw6WdklwZQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1565,12 +1604,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.7.tgz", + "integrity": "sha512-ruZOnKO+ajVL/MVx+PwNBPOkrnXTXoWMtte1MBpegfCArhqOe3Bj52avVj1huLLxNKYKXYaSxZ2F+woK1ekXfw==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1690,13 +1729,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", - "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.7.tgz", + "integrity": "sha512-rR+5FDjpCHqqZN2bzZm18bVYGaejGq5ZkpVCJLXor/+zlSrSoc4KWcHI0URVWjl/68Dyr1uwZUz/1njycEAv9g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1723,13 +1762,13 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", - "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.7.tgz", + "integrity": "sha512-EJN2mKxDwfOUCPxMO6MUI58RN3ganiRAG/MS/S3HfB6QFNjroAMelQo/gybyYq97WerCBAZoyrAoW8Tzdq2jWg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1776,13 +1815,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", - "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.7.tgz", + "integrity": "sha512-xHttvIM9fvqW+0a3tZlYcZYSBpSWzGBFIt/sYG3tcdSzBB8ZeVgz2gBP7Df+sM0N1850jrviYSSeUuc+135dmQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1792,13 +1831,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", - "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.7.tgz", + "integrity": "sha512-ZEPJSkVZaeTFG/m2PARwLZQ+OG0vFIhPlKHK/JdIMy8DbRJ/htz6LRrTFtdzxi9EHmcwbNPAKDnadpNSIW+Aow==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1808,14 +1847,14 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", - "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.7.tgz", + "integrity": "sha512-mhyfEW4gufjIqYFo9krXHJ3ElbFLIze5IDp+wQTxoPd+mwFb1NxatNAwmv8Q8Iuxv7Zc+q8EkiMQwc9IhyGf4g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.4", - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1825,14 +1864,14 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", - "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.7.tgz", + "integrity": "sha512-rvUUtoVlkDWtDWxGAiiQj0aNktTPn3eFynBcMC2IhsXweehwgdI9ODe+XjWw515kEmv22sSOTp/rxIRuTiB7zg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -1843,17 +1882,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz", - "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.7.tgz", + "integrity": "sha512-9j9rnl+YCQY0IGoeipXvnk3niWicIB6kCsWRGLwX241qSXpbA4MKxtp/EdvFxsc4zI5vqfLxzOd0twIJ7I99zg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-replace-supers": "^7.25.0", - "@babel/traverse": "^7.25.4", + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7", + "@babel/traverse": "^7.25.7", "globals": "^11.1.0" }, "engines": { @@ -1863,15 +1902,28 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", - "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.7.tgz", + "integrity": "sha512-QIv+imtM+EtNxg/XBKL3hiWjgdLjMOmZ+XzQwSgmBfKbfxUjBzGgVPklUuE55eq5/uVoh8gg3dqlrwR/jw3ZeA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/template": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/template": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1881,13 +1933,13 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", - "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.7.tgz", + "integrity": "sha512-xKcfLTlJYUczdaM1+epcdh1UGewJqr9zATgrNHcLBcV2QmfvPPEixo/sK/syql9cEmbr7ulu5HMFG5vbbt/sEA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1897,14 +1949,14 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", - "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.7.tgz", + "integrity": "sha512-kXzXMMRzAtJdDEgQBLF4oaiT6ZCU3oWHgpARnTKDAqPkDJ+bs3NrZb310YYevR5QlRo3Kn7dzzIdHbZm1VzJdQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1914,13 +1966,13 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", - "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.7.tgz", + "integrity": "sha512-by+v2CjoL3aMnWDOyCIg+yxU9KXSRa9tN6MbqggH5xvymmr9p4AMjYkNlQy4brMceBnUyHZ9G8RnpvT8wP7Cfg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1930,14 +1982,14 @@ } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", - "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.7.tgz", + "integrity": "sha512-HvS6JF66xSS5rNKXLqkk7L9c/jZ/cdIVIcoPVrnl8IsVpLggTjXs8OWekbLHs/VtYDDh5WXnQyeE3PPUGm22MA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.0", - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1947,13 +1999,13 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", - "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.7.tgz", + "integrity": "sha512-UvcLuual4h7/GfylKm2IAA3aph9rwvAM2XBA0uPKU3lca+Maai4jBjjEVUS568ld6kJcgbouuumCBhMd/Yz17w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" }, "engines": { @@ -1964,14 +2016,14 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", - "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.7.tgz", + "integrity": "sha512-yjqtpstPfZ0h/y40fAXRv2snciYr0OAoMXY/0ClC7tm4C/nG5NJKmIItlaYlLbIVAWNfrYuy9dq1bE0SbX0PEg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -1981,13 +2033,13 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", - "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.7.tgz", + "integrity": "sha512-h3MDAP5l34NQkkNulsTNyjdaR+OiB0Im67VU//sFupouP8Q6m9Spy7l66DcaAQxtmCqGdanPByLsnwFttxKISQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" }, "engines": { @@ -1998,14 +2050,14 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", - "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.7.tgz", + "integrity": "sha512-n/TaiBGJxYFWvpJDfsxSj9lEEE44BFM1EPGz4KEiTipTgkoFVVcCmzAL3qA7fdQU96dpo4gGf5HBx/KnDvqiHw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2015,15 +2067,15 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", - "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.7.tgz", + "integrity": "sha512-5MCTNcjCMxQ63Tdu9rxyN6cAWurqfrDZ76qvVPrGYdBxIj+EawuuxTu/+dgJlhK5eRz3v1gLwp6XwS8XaX2NiQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/traverse": "^7.25.1" + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2033,13 +2085,13 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", - "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.7.tgz", + "integrity": "sha512-Ot43PrL9TEAiCe8C/2erAjXMeVSnE/BLEx6eyrKLNFCCw5jvhTHKyHxdI1pA0kz5njZRYAnMO2KObGqOCRDYSA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-json-strings": "^7.8.3" }, "engines": { @@ -2050,13 +2102,13 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", - "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.7.tgz", + "integrity": "sha512-fwzkLrSu2fESR/cm4t6vqd7ebNIopz2QHGtjoU+dswQo/P6lwAG04Q98lliE3jkz/XqnbGFLnUcE0q0CVUf92w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2066,13 +2118,13 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", - "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.7.tgz", + "integrity": "sha512-iImzbA55BjiovLyG2bggWS+V+OLkaBorNvc/yJoeeDQGztknRnDdYfp2d/UPmunZYEnZi6Lg8QcTmNMHOB0lGA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -2083,13 +2135,13 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", - "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.7.tgz", + "integrity": "sha512-Std3kXwpXfRV0QtQy5JJcRpkqP8/wG4XL7hSKZmGlxPlDqmpXtEPRmhF7ztnlTCtUN3eXRUJp+sBEZjaIBVYaw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2099,14 +2151,14 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", - "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.7.tgz", + "integrity": "sha512-CgselSGCGzjQvKzghCvDTxKHP3iooenLpJDO842ehn5D2G5fJB222ptnDwQho0WjEvg7zyoxb9P+wiYxiJX5yA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2116,15 +2168,15 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", - "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.7.tgz", + "integrity": "sha512-L9Gcahi0kKFYXvweO6n0wc3ZG1ChpSFdgG+eV1WYZ3/dGbJK7vvk91FgGgak8YwRgrCuihF8tE/Xg07EkL5COg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-simple-access": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2134,16 +2186,16 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", - "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.7.tgz", + "integrity": "sha512-t9jZIvBmOXJsiuyOwhrIGs8dVcD6jDyg2icw1VL4A/g+FnWyJKwUfSSU2nwJuMV2Zqui856El9u+ElB+j9fV1g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.0", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "@babel/traverse": "^7.25.0" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2153,14 +2205,14 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", - "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.7.tgz", + "integrity": "sha512-p88Jg6QqsaPh+EB7I9GJrIqi1Zt4ZBHUQtjw3z1bzEXcLh6GfPqzZJ6G+G1HBGKUNukT58MnKG7EN7zXQBCODw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2170,14 +2222,14 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", - "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.7.tgz", + "integrity": "sha512-BtAT9LzCISKG3Dsdw5uso4oV1+v2NlVXIIomKJgQybotJY3OwCwJmkongjHgwGKoZXd0qG5UZ12JUlDQ07W6Ow==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2187,13 +2239,13 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", - "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.7.tgz", + "integrity": "sha512-CfCS2jDsbcZaVYxRFo2qtavW8SpdzmBXC2LOI4oO0rP+JSRDxxF3inF4GcPsLgfb5FjkhXG5/yR/lxuRs2pySA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2203,13 +2255,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", - "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.7.tgz", + "integrity": "sha512-FbuJ63/4LEL32mIxrxwYaqjJxpbzxPVQj5a+Ebrc8JICV6YX8nE53jY+K0RZT3um56GoNWgkS2BQ/uLGTjtwfw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" }, "engines": { @@ -2220,13 +2272,13 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", - "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.7.tgz", + "integrity": "sha512-8CbutzSSh4hmD+jJHIA8vdTNk15kAzOnFLVVgBSMGr28rt85ouT01/rezMecks9pkU939wDInImwCKv4ahU4IA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" }, "engines": { @@ -2237,16 +2289,16 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", - "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.7.tgz", + "integrity": "sha512-1JdVKPhD7Y5PvgfFy0Mv2brdrolzpzSoUq2pr6xsR+m+3viGGeHEokFKsCgOkbeFOQxfB1Vt2F0cPJLRpFI4Zg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.7" + "@babel/plugin-transform-parameters": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2256,14 +2308,14 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", - "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.7.tgz", + "integrity": "sha512-pWT6UXCEW3u1t2tcAGtE15ornCBvopHj9Bps9D2DsH15APgNVOTwwczGckX+WkAvBmuoYKRCFa4DK+jM8vh5AA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-replace-supers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2273,13 +2325,13 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", - "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.7.tgz", + "integrity": "sha512-m9obYBA39mDPN7lJzD5WkGGb0GO54PPLXsbcnj1Hyeu8mSRz7Gb4b1A6zxNX32ZuUySDK4G6it8SDFWD1nCnqg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" }, "engines": { @@ -2290,14 +2342,14 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", - "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.7.tgz", + "integrity": "sha512-h39agClImgPWg4H8mYVAbD1qP9vClFbEjqoJmt87Zen8pjqK8FTPUwrOXAvqu5soytwxrLMd2fx2KSCp2CHcNg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -2308,13 +2360,13 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", - "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.7.tgz", + "integrity": "sha512-FYiTvku63me9+1Nz7TOx4YMtW3tWXzfANZtrzHhUZrz4d47EEtMQhzFoZWESfXuAMMT5mwzD4+y1N8ONAX6lMQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2324,14 +2376,14 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", - "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.7.tgz", + "integrity": "sha512-KY0hh2FluNxMLwOCHbxVOKfdB5sjWG4M183885FmaqWWiGMhRZq4DQRKH6mHdEucbJnyDyYiZNwNG424RymJjA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.4", - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2341,15 +2393,15 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", - "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.7.tgz", + "integrity": "sha512-LzA5ESzBy7tqj00Yjey9yWfs3FKy4EmJyKOSWld144OxkTji81WWnUT8nkLUn+imN/zHL8ZQlOu/MTUAhHaX3g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-annotate-as-pure": "^7.25.7", + "@babel/helper-create-class-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -2359,14 +2411,27 @@ "@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.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.7.tgz", + "integrity": "sha512-4xwU8StnqnlIhhioZf1tqnVWeQ9pvH/ujS8hRfw/WOza+/a+1qv69BWNy+oY231maTCWgKWhfBU7kDpsds6zAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", - "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.7.tgz", + "integrity": "sha512-lQEeetGKfFi0wHbt8ClQrUSUMfEeI3MMm74Z73T9/kuz990yYVtfofjf3NuA42Jy3auFOpbjDyCSiIkTs1VIYw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2376,13 +2441,13 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", - "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.7.tgz", + "integrity": "sha512-mgDoQCRjrY3XK95UuV60tZlFCQGXEtMg8H+IsW72ldw1ih1jZhzYXbJvghmAEpg5UVhhnCeia1CkGttUvCkiMQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.25.7", "regenerator-transform": "^0.15.2" }, "engines": { @@ -2393,13 +2458,13 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", - "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.7.tgz", + "integrity": "sha512-3OfyfRRqiGeOvIWSagcwUTVk2hXBsr/ww7bLn6TRTuXnexA+Udov2icFOxFX9abaj4l96ooYkcNN1qi2Zvqwng==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2430,13 +2495,13 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", - "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.7.tgz", + "integrity": "sha512-uBbxNwimHi5Bv3hUccmOFlUy3ATO6WagTApenHz9KzoIdn0XeACdB12ZJ4cjhuB2WSi80Ez2FWzJnarccriJeA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2446,14 +2511,14 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", - "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.7.tgz", + "integrity": "sha512-Mm6aeymI0PBh44xNIv/qvo8nmbkpZze1KvR8MkEqbIREDxoiWTi18Zr2jryfRMwDfVZF9foKh060fWgni44luw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2463,13 +2528,13 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", - "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.7.tgz", + "integrity": "sha512-ZFAeNkpGuLnAQ/NCsXJ6xik7Id+tHuS+NT+ue/2+rn/31zcdnupCdmunOizEaP0JsUmTFSTOPoQY7PkK2pttXw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2479,13 +2544,13 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", - "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.7.tgz", + "integrity": "sha512-SI274k0nUsFFmyQupiO7+wKATAmMFf8iFgq2O+vVFXZ0SV9lNfT1NGzBEhjquFmD8I9sqHLguH+gZVN3vww2AA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2495,13 +2560,13 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", - "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.7.tgz", + "integrity": "sha512-OmWmQtTHnO8RSUbL0NTdtpbZHeNTnm68Gj5pA4Y2blFNh+V4iZR68V1qL9cI37J21ZN7AaCnkfdHtLExQPf2uA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2511,13 +2576,13 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", - "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.7.tgz", + "integrity": "sha512-BN87D7KpbdiABA+t3HbVqHzKWUDN3dymLaTnPFAMyc8lV+KN3+YzNhVRNdinaCPA4AUqx7ubXbQ9shRjYBl3SQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2527,14 +2592,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", - "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.7.tgz", + "integrity": "sha512-IWfR89zcEPQGB/iB408uGtSPlQd3Jpq11Im86vUgcmSTcoWAiQMCTOa2K2yNNqFJEBVICKhayctee65Ka8OB0w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2544,14 +2609,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", - "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.7.tgz", + "integrity": "sha512-8JKfg/hiuA3qXnlLx8qtv5HWRbgyFx2hMMtpDDuU2rTckpKkGu4ycK5yYHwuEa16/quXfoxHBIApEsNyMWnt0g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2561,14 +2626,14 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz", - "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.7.tgz", + "integrity": "sha512-YRW8o9vzImwmh4Q3Rffd09bH5/hvY0pxg+1H1i0f7APoUeg12G7+HhLj9ZFNIrYkgBXhIijPJ+IXypN0hLTIbw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8" + "@babel/helper-create-regexp-features-plugin": "^7.25.7", + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -2690,13 +2755,6 @@ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true, - "license": "MIT" - }, "node_modules/@babel/runtime": { "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", @@ -2710,30 +2768,30 @@ } }, "node_modules/@babel/template": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", - "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", - "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", + "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.6", - "@babel/parser": "^7.25.6", - "@babel/template": "^7.25.0", - "@babel/types": "^7.25.6", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2742,28 +2800,40 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", - "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", + "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", "license": "MIT", "dependencies": { - "@babel/types": "^7.25.6", + "@babel/types": "^7.25.7", "@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/traverse/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@babel/types": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", - "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", + "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -5265,9 +5335,9 @@ } }, "node_modules/@ngtools/webpack": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.6.tgz", - "integrity": "sha512-7HwOPE1EOgcHnpt4brSiT8G2CcXB50G0+CbCBaKGy4LYCG3Y3mrlzF5Fup9HvMJ6Tzqd62RqzpKKYBiGUT7hxg==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.7.tgz", + "integrity": "sha512-BmnFxss6zGobGyq9Mi7736golbK8RLgF+zYCQZ+4/OfMMA1jKVoELnyJqNyAx+DQn3m1qKVBjtGEL7pTNpPzOw==", "dev": true, "license": "MIT", "engines": { @@ -5597,23 +5667,23 @@ } }, "node_modules/@nrwl/devkit": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.6.5.tgz", - "integrity": "sha512-KaQeVyYaWBQwQSITtumPvx+P7IpKFReETx4gLTcOpQ/a3QD/AZFGbNjiG+xDLbgo1FDh9dRt9k7eWhGk6oPWKQ==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.8.3.tgz", + "integrity": "sha512-67vZJRMCEA543A0uz8dPTZ5lX4wsAlgsr24KJafsUxBC2WCf9z4BqcLj0jVWfmRdKJmu2UwaxtD2UB1bekt3sg==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "19.6.5" + "@nx/devkit": "19.8.3" } }, "node_modules/@nrwl/tao": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.6.5.tgz", - "integrity": "sha512-EoUN/kE6CMWJ4ZZgcXAyiOzn8BSshG2DhC5PNwzLTAxRBus8FgXR/9c0XOzchaP46Kq3hoBGFgeyW434tfuv5w==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.8.3.tgz", + "integrity": "sha512-byjBtOXx+xGjMu1wKopJSJbrR3gKqTsCEgp1+YSZ45+iFKxFdXLJrGsyhVqBovCKVBM+5/KtGuEkZoUPlP8JWg==", "dev": true, "license": "MIT", "dependencies": { - "nx": "19.6.5", + "nx": "19.8.3", "tslib": "^2.3.0" }, "bin": { @@ -5621,13 +5691,13 @@ } }, "node_modules/@nx/devkit": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.6.5.tgz", - "integrity": "sha512-AEaMSr55Ar48QHU8TBi/gzLtjeT100zdyfLmk0RoiLzjjC8pWmm3Xfvqxyt1WsUUf4oQhlHlolJuoM41qKsdZw==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.8.3.tgz", + "integrity": "sha512-uX50CAM11tzhwswf0ftN0QfzW2FM3M4Mf/pD/nRRnmsTkcPTdMXVu4LHuLVTp4CMsaO+cOQlqgHXujHYfOIctg==", "dev": true, "license": "MIT", "dependencies": { - "@nrwl/devkit": "19.6.5", + "@nrwl/devkit": "19.8.3", "ejs": "^3.1.7", "enquirer": "~2.3.6", "ignore": "^5.0.4", @@ -5668,9 +5738,9 @@ } }, "node_modules/@nx/nx-darwin-arm64": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.6.5.tgz", - "integrity": "sha512-sFU2k0BaklM17206F2E5C3866y0SICb0xyuPeD6D07a6hB4IstjIUkldUJJN70wEsJ5I3VP4yZ2oJcwnb1TTRQ==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.8.3.tgz", + "integrity": "sha512-ORHFFWMZcvFi0xcpCaXccXVEhFwAevSHOIKfW359+12H9w7VW2O42B+2NcVMK1mrDTOjlXTd+0AmAu7P4NzWFA==", "cpu": [ "arm64" ], @@ -5685,9 +5755,9 @@ } }, "node_modules/@nx/nx-darwin-x64": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.6.5.tgz", - "integrity": "sha512-EJmTbUPmlksgOap6xkQl89+zXwHpaAnZLsyLHUd7i00eVRa21FRhdKFnVsRxtwPDZp/YCG84IzMUye/IrwDFTQ==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.8.3.tgz", + "integrity": "sha512-Ji9DPA0tuzygMcypD/FHRDQSPipcRqMNmSaNKxVpcCbozVTWHvqXFk0rloDIUnxnE0+zvE9LN71H2sS4ZHdTQA==", "cpu": [ "x64" ], @@ -5702,9 +5772,9 @@ } }, "node_modules/@nx/nx-freebsd-x64": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.6.5.tgz", - "integrity": "sha512-rR8NJCskoEmIbK96uxaevHm146WDTA0V3jId+X1joITqjj3E2DMm0U4r5v/OgI5+iqbhFV4S83LrMxP6gBLTsQ==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.8.3.tgz", + "integrity": "sha512-Ys+PqtBZCS+QBNs7he3fnxVhMWz/lSSaBVUlVHoQcV1Y4clEpP2TWNQSsbaVnnpcB7pdmKN5ymWdaCaAQuqCMw==", "cpu": [ "x64" ], @@ -5719,9 +5789,9 @@ } }, "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.6.5.tgz", - "integrity": "sha512-OUHFV6iLlJN7b7qFnqLfa0Yj/aoylEiRXcEhV1bhPm0Ryt1bOeGDmLYScVN8n5t+AVmrwwYHk+ajXMzCOLLeZw==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.8.3.tgz", + "integrity": "sha512-hGOlML60ELXkgkqLHB/w/sXbTbXFhOQGSXC72CjaP5G0u1gj8eTQKJ7WEsqPAFMk5SLFFxqM7eid0LmAYYuZWQ==", "cpu": [ "arm" ], @@ -5736,9 +5806,9 @@ } }, "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.6.5.tgz", - "integrity": "sha512-CzbJfb24poaJgBHt4aKLaL8a7bO9KXCLls+TX0SZfmzA9AWX6YuiX9lhxwBv6cqsViXTDB4KnXndMDB/H0Gk4g==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.8.3.tgz", + "integrity": "sha512-K/5iVbLbhsx28YtZHvveJgF41rbr2kMdabooZeFqy6VReN7U/zGJMjpV1FzDlf3TNr9jyjPDZgVQRS+qXau2qA==", "cpu": [ "arm64" ], @@ -5753,9 +5823,9 @@ } }, "node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.6.5.tgz", - "integrity": "sha512-MgidKilQ0KWxQbTnaqXGjASu7wtAC9q6zAwFNKFENkwJq3nThaQH6jQVlnINE4lL9NSgyyg0AS/ix31hiqAgvA==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.8.3.tgz", + "integrity": "sha512-zqzWjFniZDXiI/3MYxbJ0yIenUKr56apLy70oABTBHx++dsUA3/DxLMNypMA82a8KQtsbePWUi3Pgtr+JIMNXw==", "cpu": [ "arm64" ], @@ -5770,9 +5840,9 @@ } }, "node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.6.5.tgz", - "integrity": "sha512-rGDylAoslIlk5TDbEJ6YoQOYxxYP9gCpi6FLke2mFgXVzOmVlLKHfVsegIHYVMYYF26h3NJh0NLGGzGdoBjWgQ==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.8.3.tgz", + "integrity": "sha512-W1RRCqsQvpur4BxP5g5cQwjZB6jhxYLSSXi3QQDaU5ITkaV5Pdj/L7D/G6YgRB8lzKZrXc57aLJ5UKY/Z+di7w==", "cpu": [ "x64" ], @@ -5787,9 +5857,9 @@ } }, "node_modules/@nx/nx-linux-x64-musl": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.6.5.tgz", - "integrity": "sha512-C/pNjDL/bDEcrDypgBo4r1AOiPTk8gWJwBsFE1QHIvg7//5WFSreqRj34rJu/GZ95eLYJH5tje1VW6z+atEGkQ==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.8.3.tgz", + "integrity": "sha512-waTo0zBBGnmU7fS87IpOnVGx7EHa0umzSMlGG0LUoU6swOeNODezsBn1Vbvaw1o7sStWBzdEBlxLxHOQXRAidg==", "cpu": [ "x64" ], @@ -5804,9 +5874,9 @@ } }, "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.6.5.tgz", - "integrity": "sha512-mMi8i16OFux17xed2iLPWwUdCbS1mYA9Ny/gnoNUCosmihmXX9wrzaGBkNAMsHA28huYQtPhGormsEs+zuiVFg==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.8.3.tgz", + "integrity": "sha512-lio7ulblEMs1otMtVIrdfdMTBqKRZEHim57AcMHSVnwmtl2ENP6TR3YIgyigjfLlkPanNU7i0QQ4h6Nk2I/FRw==", "cpu": [ "arm64" ], @@ -5821,9 +5891,9 @@ } }, "node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.6.5.tgz", - "integrity": "sha512-jjhbDYNBkyz9Fg1jf0KZTrgdf/yx4v+k0ifukDIHZjva+jko0Ve5WzdkQ2K07M9ZxxYibDtTDqX9uX6+eFZtoA==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.8.3.tgz", + "integrity": "sha512-RU11iXJzdrw5CmogT2AwsjxK7g8vWf6Oy23NlrvsQFODtavjqAWoD5qpUY/H16s9lVDwrpzCbGbAXph0lbgLKA==", "cpu": [ "x64" ], @@ -6153,14 +6223,14 @@ ] }, "node_modules/@schematics/angular": { - "version": "18.2.6", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.6.tgz", - "integrity": "sha512-Y988EoOEQDLEyHu3414T6AeVUyx21AexBHQNbUNQkK8cxlxyB6m1eH1cx6vFgLRFUTsLVv+C6Ln/ICNTfLcG4A==", + "version": "18.2.7", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.7.tgz", + "integrity": "sha512-WOBzO11qstznHbC9tZXQf6/8+PqmaRI6QYcdTspqXNh9q9nNglvi43Xn4tSIpEhW8aSHea9hgWZV8sG+i/4W9Q==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.6", - "@angular-devkit/schematics": "18.2.6", + "@angular-devkit/core": "18.2.7", + "@angular-devkit/schematics": "18.2.7", "jsonc-parser": "3.3.1" }, "engines": { @@ -6170,73 +6240,73 @@ } }, "node_modules/@sentry-internal/browser-utils": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.32.0.tgz", - "integrity": "sha512-DpUGhk5O1OVjT0fo9wsbEdO1R/S9gGBRDtn9+FFVeRtieJHwXpeZiLK+tZhTOvaILmtSoTPUEY3L5sK4j5Xq9g==", + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.33.1.tgz", + "integrity": "sha512-TW6/r+Gl5jiXv54iK1xZ3mlVgTS/jaBp4vcQ0xGMdgiQ3WchEPcFSeYovL+YHT3tSud0GZqVtDQCz+5i76puqA==", "license": "MIT", "dependencies": { - "@sentry/core": "8.32.0", - "@sentry/types": "8.32.0", - "@sentry/utils": "8.32.0" + "@sentry/core": "8.33.1", + "@sentry/types": "8.33.1", + "@sentry/utils": "8.33.1" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/feedback": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.32.0.tgz", - "integrity": "sha512-XB7hiVJQW1tNzpoXIHbvm3rjipIt7PZiJJtFg2vxaqu/FzdgOcYqQiwIKivJVAKuRZ9rIeJtK1jdXQFOc/TRJA==", + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.33.1.tgz", + "integrity": "sha512-qauMRTm3qDaLqZ3ibI03cj4gLF40y0ij65nj+cns6iWxGCtPrO8tjvXFWuQsE7Aye9dGMnBgmv7uN+NTUtC3RA==", "license": "MIT", "dependencies": { - "@sentry/core": "8.32.0", - "@sentry/types": "8.32.0", - "@sentry/utils": "8.32.0" + "@sentry/core": "8.33.1", + "@sentry/types": "8.33.1", + "@sentry/utils": "8.33.1" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.32.0.tgz", - "integrity": "sha512-yiEUnn2yyo1AIQIFNeRX3tdK8fmyKIkxdFS1WiVQmeYI/hFwYBTZPly0FcO/g3xnRMSA2tvrS+hZEaaXfK4WhA==", + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.33.1.tgz", + "integrity": "sha512-fm4coIOjmanU29NOVN9MyaP4fUCOYytbtFqVSKRFNZQ/xAgNeySiBIbUd6IjujMmnOk9bY0WEUMcdm3Uotjdog==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "8.32.0", - "@sentry/core": "8.32.0", - "@sentry/types": "8.32.0", - "@sentry/utils": "8.32.0" + "@sentry-internal/browser-utils": "8.33.1", + "@sentry/core": "8.33.1", + "@sentry/types": "8.33.1", + "@sentry/utils": "8.33.1" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.32.0.tgz", - "integrity": "sha512-oBbhtDBkD+5z/T0NVJ5VenBWAid/S9QdVrod/UqxVqU7F8N+E9/INFQI48zCWr4iVlUMcszJPDElvJEsMDvvBQ==", + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.33.1.tgz", + "integrity": "sha512-nsxTFTPCT10Ty/v6+AiST3+yotGP1sUb8xqfKB9fPnS1hZHFryp0NnEls7xFjBsBbZPU1GpFkzrk/E6JFzixDQ==", "license": "MIT", "dependencies": { - "@sentry-internal/replay": "8.32.0", - "@sentry/core": "8.32.0", - "@sentry/types": "8.32.0", - "@sentry/utils": "8.32.0" + "@sentry-internal/replay": "8.33.1", + "@sentry/core": "8.33.1", + "@sentry/types": "8.33.1", + "@sentry/utils": "8.33.1" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry/angular": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@sentry/angular/-/angular-8.32.0.tgz", - "integrity": "sha512-HgdpLFTdAMgTG4yz6mb9umg+yGlCkuRDqC4Wv1zNW7ARoSioavyz4kMRkKqJR6hxgGh2vPoXCz6E+w8L4k9oPg==", + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@sentry/angular/-/angular-8.33.1.tgz", + "integrity": "sha512-jt4oViLMl/eqOALQmD0dPzXsy75Xp8amfRExgXoPdyDg6sLDNdEzpzrX2p7nGl7vsW/0Vm8NZ2TkbEBCll5wfQ==", "license": "MIT", "dependencies": { - "@sentry/browser": "8.32.0", - "@sentry/core": "8.32.0", - "@sentry/types": "8.32.0", - "@sentry/utils": "8.32.0", + "@sentry/browser": "8.33.1", + "@sentry/core": "8.33.1", + "@sentry/types": "8.33.1", + "@sentry/utils": "8.33.1", "tslib": "^2.4.1" }, "engines": { @@ -6250,52 +6320,52 @@ } }, "node_modules/@sentry/browser": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.32.0.tgz", - "integrity": "sha512-AEKFj64g4iYwEMRvVcxiY0FswmClRXCP1IEvCqujn8OBS8AjMOr1z/RwYieEs0D90yNNB3YEqF8adrKENblJmw==", + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.33.1.tgz", + "integrity": "sha512-c6zI/igexkLwZuGk+u8Rj26ChjxGgkhe6ZbKFsXCYaKAp5ep5X7HQRkkqgbxApiqlC0LduHdd/ymzh139JLg8w==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "8.32.0", - "@sentry-internal/feedback": "8.32.0", - "@sentry-internal/replay": "8.32.0", - "@sentry-internal/replay-canvas": "8.32.0", - "@sentry/core": "8.32.0", - "@sentry/types": "8.32.0", - "@sentry/utils": "8.32.0" + "@sentry-internal/browser-utils": "8.33.1", + "@sentry-internal/feedback": "8.33.1", + "@sentry-internal/replay": "8.33.1", + "@sentry-internal/replay-canvas": "8.33.1", + "@sentry/core": "8.33.1", + "@sentry/types": "8.33.1", + "@sentry/utils": "8.33.1" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry/core": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.32.0.tgz", - "integrity": "sha512-+xidTr0lZ0c755tq4k75dXPEb8PA+qvIefW3U9+dQMORLokBrYoKYMf5zZTG2k/OfSJS6OSxatUj36NFuCs3aA==", + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.33.1.tgz", + "integrity": "sha512-3SS41suXLFzxL3OQvTMZ6q92ZapELVq2l2SoWlZopcamWhog2Ru0dp2vkunq97kFHb2TzKRTlFH4+4gbT8SJug==", "license": "MIT", "dependencies": { - "@sentry/types": "8.32.0", - "@sentry/utils": "8.32.0" + "@sentry/types": "8.33.1", + "@sentry/utils": "8.33.1" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry/types": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.32.0.tgz", - "integrity": "sha512-hxckvN2MzS5SgGDgVQ0/QpZXk13Vrq4BtZLwXhPhyeTmZtUiUfWvcL5TFQqLinfKdTKPe9q2MxeAJ0D4LalhMg==", + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.33.1.tgz", + "integrity": "sha512-GjoAMvwtpIemoF/IiwZ7A60g4nQv3qwzR21GvJqDVUoKD0e8pv9OLX+HyXoUat4wEDGSuDUcUyUKD2G+od73QA==", "license": "MIT", "engines": { "node": ">=14.18" } }, "node_modules/@sentry/utils": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.32.0.tgz", - "integrity": "sha512-t1WVERhgmYURxbBj9J4/H2P2X+VKqm7B3ce9iQyrZbdf5NekhcU4jHIecPUWCPHjQkFIqkVTorqeBmDTlg/UmQ==", + "version": "8.33.1", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.33.1.tgz", + "integrity": "sha512-uzuYpiiJuFY3N4WNHMBWUQX5oNv2t/TbG0OHRp3Rr7yeu+HSfD542TIp9/gMZ+G0Cxd8AmVO3wkKIFbk0TL4Qg==", "license": "MIT", "dependencies": { - "@sentry/types": "8.32.0" + "@sentry/types": "8.33.1" }, "engines": { "node": ">=14.18" @@ -6909,9 +6979,9 @@ "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.9", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.9.tgz", - "integrity": "sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w==", + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==", "dev": true, "license": "MIT" }, @@ -6943,9 +7013,9 @@ } }, "node_modules/@types/node": { - "version": "22.7.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.3.tgz", - "integrity": "sha512-qXKfhXXqGTyBskvWEzJZPUxSslAiLaB6JGP1ic/XTH9ctGgzdgYguuLP1C601aRTSDNlLb0jbKqXjZ48GNraSA==", + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", "dev": true, "license": "MIT", "dependencies": { @@ -6993,9 +7063,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.9", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.9.tgz", - "integrity": "sha512-+BpAVyTpJkNWWSSnaLBk6ePpHLOGJKnEQNbINNovPWzvEUyAe3e+/d494QdEh71RekM/qV7lw6jzf1HGrJyAtQ==", + "version": "18.3.11", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz", + "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==", "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -7149,17 +7219,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz", - "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", + "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/type-utils": "8.7.0", - "@typescript-eslint/utils": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/type-utils": "8.8.0", + "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -7183,16 +7253,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz", - "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", + "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4" }, "engines": { @@ -7212,14 +7282,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", - "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", + "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0" + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7230,14 +7300,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz", - "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", + "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/utils": "8.7.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/utils": "8.8.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -7255,9 +7325,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz", - "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", + "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", "dev": true, "license": "MIT", "engines": { @@ -7269,14 +7339,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", - "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", + "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -7298,16 +7368,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", - "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", + "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0" + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7321,13 +7391,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", - "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", + "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/types": "8.8.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -8691,9 +8761,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001664", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz", - "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==", + "version": "1.0.30001666", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001666.tgz", + "integrity": "sha512-gD14ICmoV5ZZM1OdzPWmpx+q4GyefaK06zi8hmfHV5xe4/2nOQX3+Dw5o+fSqOws2xVwL9j+anOPFwHzdEdV4g==", "funding": [ { "type": "opencollective", @@ -8851,9 +8921,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", "dev": true, "license": "MIT", "engines": { @@ -10416,9 +10486,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.29", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz", - "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==", + "version": "1.5.32", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.32.tgz", + "integrity": "sha512-M+7ph0VGBQqqpTT2YrabjNKSQ2fEl9PVx6AK3N558gDH9NO8O6XN9SXXFWRo9u9PbEg/bWq+tjXQr+eXmxubCw==", "license": "ISC" }, "node_modules/emittery": { @@ -11157,9 +11227,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -11281,9 +11351,9 @@ } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -11350,15 +11420,15 @@ } }, "node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" + "eslint-visitor-keys": "^4.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -11368,9 +11438,9 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", "dev": true, "license": "Apache-2.0", "engines": { @@ -12048,31 +12118,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs-extra/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/fs-minipass": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", @@ -14254,9 +14299,9 @@ } }, "node_modules/jest-fail-on-console": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/jest-fail-on-console/-/jest-fail-on-console-3.3.0.tgz", - "integrity": "sha512-J9rnFQvQwkcGJw01zCEKe2Uag+E926lFgIyaQGep2LqhQH7OCRHyD+tm/jnNoKlSRnOBO60DmzMjeQAVI3f5cw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jest-fail-on-console/-/jest-fail-on-console-3.3.1.tgz", + "integrity": "sha512-dmq/dmh5OBgJlD1MJdpznzwFQP8S7msf3ghTGWQLGhagWwHKzGtqXza76nuJUKOK7BdwqcTK6CCE49Xxv4ckUQ==", "dev": true, "license": "MIT" }, @@ -15583,29 +15628,6 @@ "dev": true, "license": "MIT" }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonfile/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -15849,11 +15871,14 @@ } }, "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", + "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } }, "node_modules/lint-staged": { "version": "15.2.10", @@ -17589,22 +17614,22 @@ } }, "node_modules/nwsapi": { - "version": "2.2.12", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", - "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", "dev": true, "license": "MIT" }, "node_modules/nx": { - "version": "19.6.5", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.6.5.tgz", - "integrity": "sha512-igPYPsBF1BM1YxEiGDvaLOz0CWWoEvxzR7yQg3iULjGG9zKgDFNHHIHJwkyHsCBTtMhhkgeUl16PsTVgDuil3A==", + "version": "19.8.3", + "resolved": "https://registry.npmjs.org/nx/-/nx-19.8.3.tgz", + "integrity": "sha512-/3FF4tgwPGRu4bV6O+aHqhTnOGHKF0/HNVkApUwjimSC+YzOX9VH1uBx2eReb4XC1scxDWkIzVi9gkFSXSQDjQ==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { "@napi-rs/wasm-runtime": "0.2.4", - "@nrwl/tao": "19.6.5", + "@nrwl/tao": "19.8.3", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "3.0.0-rc.46", "@zkochan/js-yaml": "0.0.7", @@ -17619,11 +17644,10 @@ "figures": "3.2.0", "flat": "^5.0.2", "front-matter": "^4.0.2", - "fs-extra": "^11.1.0", "ignore": "^5.0.4", "jest-diff": "^29.4.1", "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", + "lines-and-columns": "2.0.3", "minimatch": "9.0.3", "node-machine-id": "1.1.12", "npm-run-path": "^4.0.1", @@ -17644,16 +17668,16 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.6.5", - "@nx/nx-darwin-x64": "19.6.5", - "@nx/nx-freebsd-x64": "19.6.5", - "@nx/nx-linux-arm-gnueabihf": "19.6.5", - "@nx/nx-linux-arm64-gnu": "19.6.5", - "@nx/nx-linux-arm64-musl": "19.6.5", - "@nx/nx-linux-x64-gnu": "19.6.5", - "@nx/nx-linux-x64-musl": "19.6.5", - "@nx/nx-win32-arm64-msvc": "19.6.5", - "@nx/nx-win32-x64-msvc": "19.6.5" + "@nx/nx-darwin-arm64": "19.8.3", + "@nx/nx-darwin-x64": "19.8.3", + "@nx/nx-freebsd-x64": "19.8.3", + "@nx/nx-linux-arm-gnueabihf": "19.8.3", + "@nx/nx-linux-arm64-gnu": "19.8.3", + "@nx/nx-linux-arm64-musl": "19.8.3", + "@nx/nx-linux-x64-gnu": "19.8.3", + "@nx/nx-linux-x64-musl": "19.8.3", + "@nx/nx-win32-arm64-msvc": "19.8.3", + "@nx/nx-win32-x64-msvc": "19.8.3" }, "peerDependencies": { "@swc-node/register": "^1.8.0", @@ -17714,19 +17738,6 @@ "node": ">=8" } }, - "node_modules/nx/node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/nx/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -17820,16 +17831,6 @@ "dev": true, "license": "MIT" }, - "node_modules/nx/node_modules/lines-and-columns": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, "node_modules/nx/node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -18388,6 +18389,13 @@ "dev": true, "license": "MIT" }, + "node_modules/parse-json/node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, "node_modules/parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", @@ -18885,9 +18893,9 @@ "license": "MIT" }, "node_modules/posthog-js": { - "version": "1.165.0", - "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.165.0.tgz", - "integrity": "sha512-rUfRJobvOz3Q9Er+zwb32Eq2qs+ToBe/B4k4IoKzmyszI7240Rf4xVWRB0ky8LvmdZfCeYX5knS2Uv3pnn/d5A==", + "version": "1.166.1", + "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.166.1.tgz", + "integrity": "sha512-K8IpV8FJTCdwhsXFSbKj5vZ6IXNV079lukpG3cRtst2q5vMmUXRQiks7W3lOZLrjWyuJLKZDUiCeeDIUFORRuQ==", "license": "MIT", "dependencies": { "fflate": "^0.4.8", @@ -19439,16 +19447,16 @@ "license": "MIT" }, "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", + "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.11.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" }, @@ -19456,26 +19464,37 @@ "node": ">=4" } }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true, + "license": "MIT" + }, "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.0.tgz", + "integrity": "sha512-vTbzVAjQDzwQdKuvj7qEq6OlAprCjE656khuGQ4QaBLg7abQ9I9ISpmLuc6inWe7zP75AECjqUa4g4sdQvOXhg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "jsesc": "~0.5.0" + "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" } }, "node_modules/require-directory": { @@ -19877,9 +19896,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.79.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.3.tgz", - "integrity": "sha512-m7dZxh0W9EZ3cw50Me5GOuYm/tVAJAn91SUnohLRo9cXBixGUOdvmryN+dXpwR831bhoY3Zv7rEFt85PUwTmzA==", + "version": "1.79.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.4.tgz", + "integrity": "sha512-K0QDSNPXgyqO4GZq2HO5Q70TLxTH6cIT59RdoCHMivrC8rqzaTw5ab9prjz9KUN1El4FLXrBXJhik61JR4HcGg==", "dev": true, "license": "MIT", "dependencies": { @@ -19952,9 +19971,9 @@ } }, "node_modules/sass/node_modules/readdirp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz", - "integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==", + "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": { @@ -21412,22 +21431,22 @@ "license": "MIT" }, "node_modules/tldts": { - "version": "6.1.47", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.47.tgz", - "integrity": "sha512-R/K2tZ5MiY+mVrnSkNJkwqYT2vUv1lcT6wJvd2emGaMJ7PHUGRY4e3tUsdFCXgqxi2QgbHjL3yJgXCo40v9Hxw==", + "version": "6.1.50", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.50.tgz", + "integrity": "sha512-q9GOap6q3KCsLMdOjXhWU5jVZ8/1dIib898JBRLsN+tBhENpBDcAVQbE0epADOjw11FhQQy9AcbqKGBQPUfTQA==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.47" + "tldts-core": "^6.1.50" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.47", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.47.tgz", - "integrity": "sha512-6SWyFMnlst1fEt7GQVAAu16EGgFK0cLouH/2Mk6Ftlwhv3Ol40L0dlpGMcnnNiiOMyD2EV/aF3S+U2nKvvLvrA==", + "version": "6.1.50", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.50.tgz", + "integrity": "sha512-na2EcZqmdA2iV9zHV7OHQDxxdciEpxrjbkp+aHmZgnZKHzoElLajP59np5/4+sare9fQBfixgvXKx8ev1d7ytw==", "dev": true, "license": "MIT" }, @@ -21945,9 +21964,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "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==", "funding": [ { "type": "opencollective", @@ -21964,8 +21983,8 @@ ], "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" diff --git a/package.json b/package.json index 03ab87fb7b80..6e0c9d16ee0e 100644 --- a/package.json +++ b/package.json @@ -13,18 +13,18 @@ "node_modules" ], "dependencies": { - "@angular/animations": "18.2.6", - "@angular/cdk": "18.2.6", - "@angular/common": "18.2.6", - "@angular/compiler": "18.2.6", - "@angular/core": "18.2.6", - "@angular/forms": "18.2.6", - "@angular/localize": "18.2.6", - "@angular/material": "18.2.6", - "@angular/platform-browser": "18.2.6", - "@angular/platform-browser-dynamic": "18.2.6", - "@angular/router": "18.2.6", - "@angular/service-worker": "18.2.6", + "@angular/animations": "18.2.7", + "@angular/cdk": "18.2.7", + "@angular/common": "18.2.7", + "@angular/compiler": "18.2.7", + "@angular/core": "18.2.7", + "@angular/forms": "18.2.7", + "@angular/localize": "18.2.7", + "@angular/material": "18.2.7", + "@angular/platform-browser": "18.2.7", + "@angular/platform-browser-dynamic": "18.2.7", + "@angular/router": "18.2.7", + "@angular/service-worker": "18.2.7", "@ctrl/ngx-emoji-mart": "9.2.0", "@danielmoncada/angular-datetime-picker": "18.1.0", "@fingerprintjs/fingerprintjs": "4.5.0", @@ -36,7 +36,7 @@ "@ng-bootstrap/ng-bootstrap": "17.0.1", "@ngx-translate/core": "15.0.0", "@ngx-translate/http-loader": "8.0.0", - "@sentry/angular": "8.32.0", + "@sentry/angular": "8.33.1", "@siemens/ngx-datatable": "22.4.1", "@swimlane/ngx-charts": "20.5.0", "@swimlane/ngx-graph": "8.4.0", @@ -63,7 +63,7 @@ "ngx-webstorage": "18.0.0", "papaparse": "5.4.1", "pdfjs-dist": "4.6.82", - "posthog-js": "1.165.0", + "posthog-js": "1.166.1", "rxjs": "7.8.1", "showdown": "2.1.0", "showdown-highlight": "3.1.0", @@ -116,29 +116,29 @@ }, "devDependencies": { "@angular-builders/jest": "18.0.0", - "@angular-devkit/build-angular": "18.2.6", + "@angular-devkit/build-angular": "18.2.7", "@angular-eslint/builder": "18.3.1", "@angular-eslint/eslint-plugin": "18.3.1", "@angular-eslint/eslint-plugin-template": "18.3.1", "@angular-eslint/schematics": "18.3.1", "@angular-eslint/template-parser": "18.3.1", - "@angular/cli": "18.2.6", - "@angular/compiler-cli": "18.2.6", - "@angular/language-service": "18.2.6", - "@sentry/types": "8.32.0", + "@angular/cli": "18.2.7", + "@angular/compiler-cli": "18.2.7", + "@angular/language-service": "18.2.7", + "@sentry/types": "8.33.1", "@types/crypto-js": "4.2.2", "@types/d3-shape": "3.1.6", "@types/dompurify": "3.0.5", "@types/jest": "29.5.13", "@types/lodash-es": "4.17.12", - "@types/node": "22.7.3", + "@types/node": "22.7.4", "@types/papaparse": "5.3.14", "@types/showdown": "2.0.6", "@types/smoothscroll-polyfill": "0.3.4", "@types/sockjs-client": "1.5.4", "@types/uuid": "10.0.0", - "@typescript-eslint/eslint-plugin": "8.7.0", - "@typescript-eslint/parser": "8.7.0", + "@typescript-eslint/eslint-plugin": "8.8.0", + "@typescript-eslint/parser": "8.8.0", "eslint": "9.11.1", "eslint-config-prettier": "9.1.0", "eslint-plugin-deprecation": "3.0.0", @@ -151,7 +151,7 @@ "jest-canvas-mock": "2.5.2", "jest-date-mock": "1.0.10", "jest-extended": "4.0.2", - "jest-fail-on-console": "3.3.0", + "jest-fail-on-console": "3.3.1", "jest-junit": "16.0.0", "jest-preset-angular": "14.2.4", "lint-staged": "15.2.10", @@ -159,7 +159,7 @@ "ng-mocks": "14.13.1", "prettier": "3.3.3", "rimraf": "6.0.1", - "sass": "1.79.3", + "sass": "1.79.4", "ts-jest": "29.2.5", "typescript": "5.5.4", "weak-napi": "2.0.2" diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java b/src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java index 7cd32bdd957a..00e0cdfa3d31 100644 --- a/src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java +++ b/src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java @@ -39,6 +39,7 @@ import de.tum.cit.aet.artemis.core.repository.CourseRepository; import de.tum.cit.aet.artemis.core.repository.UserRepository; import de.tum.cit.aet.artemis.core.security.Role; +import de.tum.cit.aet.artemis.core.security.annotations.EnforceAtLeastStudent; import de.tum.cit.aet.artemis.core.security.annotations.enforceRoleInCourse.EnforceAtLeastEditorInCourse; import de.tum.cit.aet.artemis.core.security.annotations.enforceRoleInCourse.EnforceAtLeastInstructorInCourse; import de.tum.cit.aet.artemis.core.security.annotations.enforceRoleInCourse.EnforceAtLeastStudentInCourse; @@ -97,7 +98,7 @@ public PrerequisiteResource(CourseRepository courseRepository, AuthorizationChec * @return the ResponseEntity with status 200 (OK) and with body the found prerequisites */ @GetMapping("courses/{courseId}/prerequisites") - @EnforceAtLeastStudentInCourse + @EnforceAtLeastStudent public ResponseEntity> getPrerequisitesWithProgress(@PathVariable long courseId) { log.debug("REST request to get prerequisites for course with id: {}", courseId); User user = userRepository.getUserWithGroupsAndAuthorities(); diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/domain/Faq.java b/src/main/java/de/tum/cit/aet/artemis/communication/domain/Faq.java new file mode 100644 index 000000000000..fd7ce4fca468 --- /dev/null +++ b/src/main/java/de/tum/cit/aet/artemis/communication/domain/Faq.java @@ -0,0 +1,99 @@ +package de.tum.cit.aet.artemis.communication.domain; + +import java.util.HashSet; +import java.util.Set; + +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +import de.tum.cit.aet.artemis.core.domain.AbstractAuditingEntity; +import de.tum.cit.aet.artemis.core.domain.Course; + +/** + * A FAQ. + */ +@Entity +@Table(name = "faq") +@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class Faq extends AbstractAuditingEntity { + + @Column(name = "question_title") + private String questionTitle; + + @Column(name = "question_answer") + private String questionAnswer; + + @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable(name = "faq_category", joinColumns = @JoinColumn(name = "faq_id")) + @Column(name = "category") + private Set categories = new HashSet<>(); + + @Enumerated(EnumType.STRING) + @Column(name = "faq_state") + private FaqState faqState; + + @ManyToOne + @JsonIgnoreProperties(value = { "faqs" }, allowSetters = true) + private Course course; + + public String getQuestionTitle() { + return questionTitle; + } + + public void setQuestionTitle(String questionTitle) { + this.questionTitle = questionTitle; + } + + public String getQuestionAnswer() { + return questionAnswer; + } + + public void setQuestionAnswer(String questionAnswer) { + this.questionAnswer = questionAnswer; + } + + public Course getCourse() { + return course; + } + + public void setCourse(Course course) { + this.course = course; + } + + public Set getCategories() { + return categories; + } + + public void setCategories(Set categories) { + this.categories = categories; + } + + public FaqState getFaqState() { + return faqState; + } + + public void setFaqState(FaqState faqState) { + this.faqState = faqState; + } + + @Override + public String toString() { + return "Faq{" + "id=" + getId() + ", questionTitle='" + getQuestionTitle() + "'" + ", questionAnswer='" + getQuestionAnswer() + "'" + ", faqState='" + getFaqState() + "}"; + } + +} diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/domain/FaqState.java b/src/main/java/de/tum/cit/aet/artemis/communication/domain/FaqState.java new file mode 100644 index 000000000000..9018a3be3a12 --- /dev/null +++ b/src/main/java/de/tum/cit/aet/artemis/communication/domain/FaqState.java @@ -0,0 +1,5 @@ +package de.tum.cit.aet.artemis.communication.domain; + +public enum FaqState { + ACCEPTED, REJECTED, PROPOSED +} diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/dto/FaqDTO.java b/src/main/java/de/tum/cit/aet/artemis/communication/dto/FaqDTO.java new file mode 100644 index 000000000000..efab02ad1bf9 --- /dev/null +++ b/src/main/java/de/tum/cit/aet/artemis/communication/dto/FaqDTO.java @@ -0,0 +1,17 @@ +package de.tum.cit.aet.artemis.communication.dto; + +import java.util.Set; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import de.tum.cit.aet.artemis.communication.domain.Faq; +import de.tum.cit.aet.artemis.communication.domain.FaqState; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public record FaqDTO(Long id, String questionTitle, String questionAnswer, Set categories, FaqState faqState) { + + public FaqDTO(Faq faq) { + this(faq.getId(), faq.getQuestionTitle(), faq.getQuestionAnswer(), faq.getCategories(), faq.getFaqState()); + } + +} diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java b/src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java new file mode 100644 index 000000000000..bd8bb8989995 --- /dev/null +++ b/src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java @@ -0,0 +1,37 @@ +package de.tum.cit.aet.artemis.communication.repository; + +import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE; + +import java.util.Set; + +import org.springframework.context.annotation.Profile; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import de.tum.cit.aet.artemis.communication.domain.Faq; +import de.tum.cit.aet.artemis.core.repository.base.ArtemisJpaRepository; + +/** + * Spring Data repository for the Faq entity. + */ +@Profile(PROFILE_CORE) +@Repository +public interface FaqRepository extends ArtemisJpaRepository { + + Set findAllByCourseId(Long courseId); + + @Query(""" + SELECT DISTINCT faq.categories + FROM Faq faq + WHERE faq.course.id = :courseId + """) + Set findAllCategoriesByCourseId(@Param("courseId") Long courseId); + + @Transactional + @Modifying + void deleteAllByCourseId(Long courseId); + +} diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java b/src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java new file mode 100644 index 000000000000..91a542aaa220 --- /dev/null +++ b/src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java @@ -0,0 +1,194 @@ +package de.tum.cit.aet.artemis.communication.web; + +import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Profile; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import de.tum.cit.aet.artemis.communication.domain.Faq; +import de.tum.cit.aet.artemis.communication.dto.FaqDTO; +import de.tum.cit.aet.artemis.communication.repository.FaqRepository; +import de.tum.cit.aet.artemis.core.domain.Course; +import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException; +import de.tum.cit.aet.artemis.core.repository.CourseRepository; +import de.tum.cit.aet.artemis.core.security.Role; +import de.tum.cit.aet.artemis.core.security.annotations.EnforceAtLeastInstructor; +import de.tum.cit.aet.artemis.core.security.annotations.EnforceAtLeastStudent; +import de.tum.cit.aet.artemis.core.service.AuthorizationCheckService; +import de.tum.cit.aet.artemis.core.util.HeaderUtil; + +/** + * REST controller for managing Faqs. + */ +@Profile(PROFILE_CORE) +@RestController +@RequestMapping("api/") +public class FaqResource { + + private static final Logger log = LoggerFactory.getLogger(FaqResource.class); + + private static final String ENTITY_NAME = "faq"; + + @Value("${jhipster.clientApp.name}") + private String applicationName; + + private final CourseRepository courseRepository; + + private final AuthorizationCheckService authCheckService; + + private final FaqRepository faqRepository; + + public FaqResource(CourseRepository courseRepository, AuthorizationCheckService authCheckService, FaqRepository faqRepository) { + + this.courseRepository = courseRepository; + this.authCheckService = authCheckService; + this.faqRepository = faqRepository; + } + + /** + * POST /courses/:courseId/faqs : Create a new faq. + * + * @param faq the faq to create * + * @param courseId the id of the course the faq belongs to + * @return the ResponseEntity with status 201 (Created) and with body the new faq, or with status 400 (Bad Request) + * if the faq has already an ID or if the faq course id does not match with the path variable + * @throws URISyntaxException if the Location URI syntax is incorrect + */ + @PostMapping("courses/{courseId}/faqs") + @EnforceAtLeastInstructor + public ResponseEntity createFaq(@RequestBody Faq faq, @PathVariable Long courseId) throws URISyntaxException { + log.debug("REST request to save Faq : {}", faq); + if (faq.getId() != null) { + throw new BadRequestAlertException("A new faq cannot already have an ID", ENTITY_NAME, "idExists"); + } + + if (faq.getCourse() == null || !faq.getCourse().getId().equals(courseId)) { + throw new BadRequestAlertException("Course ID in path and FAQ do not match", ENTITY_NAME, "courseIdMismatch"); + } + authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.INSTRUCTOR, faq.getCourse(), null); + + Faq savedFaq = faqRepository.save(faq); + FaqDTO dto = new FaqDTO(savedFaq); + return ResponseEntity.created(new URI("/api/courses/" + courseId + "/faqs/" + savedFaq.getId())).body(dto); + } + + /** + * PUT /courses/:courseId/faqs/:faqId : Updates an existing faq. + * + * @param faq the faq to update + * @param faqId id of the faq to be updated * + * @param courseId the id of the course the faq belongs to + * @return the ResponseEntity with status 200 (OK) and with body the updated faq, or with status 400 (Bad Request) + * if the faq is not valid or if the faq course id does not match with the path variable + */ + @PutMapping("courses/{courseId}/faqs/{faqId}") + @EnforceAtLeastInstructor + public ResponseEntity updateFaq(@RequestBody Faq faq, @PathVariable Long faqId, @PathVariable Long courseId) { + log.debug("REST request to update Faq : {}", faq); + if (faqId == null || !faqId.equals(faq.getId())) { + throw new BadRequestAlertException("Id of FAQ and path must match", ENTITY_NAME, "idNull"); + } + authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.INSTRUCTOR, faq.getCourse(), null); + Faq existingFaq = faqRepository.findByIdElseThrow(faqId); + if (!Objects.equals(existingFaq.getCourse().getId(), courseId)) { + throw new BadRequestAlertException("Course ID of the FAQ provided courseID must match", ENTITY_NAME, "idNull"); + } + Faq updatedFaq = faqRepository.save(faq); + FaqDTO dto = new FaqDTO(updatedFaq); + return ResponseEntity.ok().body(dto); + } + + /** + * GET /courses/:courseId/faqs/:faqId : get the faq with the id faqId. + * + * @param faqId the faqId of the faq to retrieve * + * @param courseId the id of the course the faq belongs to + * @return the ResponseEntity with status 200 (OK) and with body the faq, or with status 404 (Not Found) + */ + @GetMapping("courses/{courseId}/faqs/{faqId}") + @EnforceAtLeastStudent + public ResponseEntity getFaq(@PathVariable Long faqId, @PathVariable Long courseId) { + log.debug("REST request to get faq {}", faqId); + Faq faq = faqRepository.findByIdElseThrow(faqId); + if (faq.getCourse() == null || !faq.getCourse().getId().equals(courseId)) { + throw new BadRequestAlertException("Course ID in path and FAQ do not match", ENTITY_NAME, "courseIdMismatch"); + } + authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.STUDENT, faq.getCourse(), null); + FaqDTO dto = new FaqDTO(faq); + return ResponseEntity.ok(dto); + } + + /** + * DELETE /courses/:courseId/faqs/:faqId : delete the "id" faq. + * + * @param faqId the id of the faq to delete + * @param courseId the id of the course the faq belongs to + * @return the ResponseEntity with status 200 (OK) + */ + @DeleteMapping("courses/{courseId}/faqs/{faqId}") + @EnforceAtLeastInstructor + public ResponseEntity deleteFaq(@PathVariable Long faqId, @PathVariable Long courseId) { + + log.debug("REST request to delete faq {}", faqId); + Faq existingFaq = faqRepository.findByIdElseThrow(faqId); + authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.INSTRUCTOR, existingFaq.getCourse(), null); + if (!Objects.equals(existingFaq.getCourse().getId(), courseId)) { + throw new BadRequestAlertException("Course ID of the FAQ provided courseID must match", ENTITY_NAME, "idNull"); + } + faqRepository.deleteById(faqId); + return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, faqId.toString())).build(); + } + + /** + * GET /courses/:courseId/faqs : get all the faqs of a course + * + * @param courseId the courseId of the course for which all faqs should be returned + * @return the ResponseEntity with status 200 (OK) and the list of faqs in body + */ + @GetMapping("courses/{courseId}/faqs") + @EnforceAtLeastStudent + public ResponseEntity> getFaqForCourse(@PathVariable Long courseId) { + log.debug("REST request to get all Faqs for the course with id : {}", courseId); + + Course course = courseRepository.findByIdElseThrow(courseId); + authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.STUDENT, course, null); + Set faqs = faqRepository.findAllByCourseId(courseId); + Set faqDTOS = faqs.stream().map(FaqDTO::new).collect(Collectors.toSet()); + return ResponseEntity.ok().body(faqDTOS); + } + + /** + * GET /courses/:courseId/faq-categories : get all the faq categories of a course + * + * @param courseId the courseId of the course for which all faq categories should be returned + * @return the ResponseEntity with status 200 (OK) and the list of faqs in body + */ + @GetMapping("courses/{courseId}/faq-categories") + @EnforceAtLeastStudent + public ResponseEntity> getFaqCategoriesForCourse(@PathVariable Long courseId) { + log.debug("REST request to get all Faq Categories for the course with id : {}", courseId); + + Course course = courseRepository.findByIdElseThrow(courseId); + authCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.STUDENT, course, null); + Set faqs = faqRepository.findAllCategoriesByCourseId(courseId); + + return ResponseEntity.ok().body(faqs); + } +} diff --git a/src/main/java/de/tum/cit/aet/artemis/core/domain/Course.java b/src/main/java/de/tum/cit/aet/artemis/core/domain/Course.java index beacc4af0aa0..8000a24c0b55 100644 --- a/src/main/java/de/tum/cit/aet/artemis/core/domain/Course.java +++ b/src/main/java/de/tum/cit/aet/artemis/core/domain/Course.java @@ -37,6 +37,7 @@ import de.tum.cit.aet.artemis.atlas.domain.competency.Competency; import de.tum.cit.aet.artemis.atlas.domain.competency.LearningPath; import de.tum.cit.aet.artemis.atlas.domain.competency.Prerequisite; +import de.tum.cit.aet.artemis.communication.domain.Faq; import de.tum.cit.aet.artemis.communication.domain.Post; import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException; import de.tum.cit.aet.artemis.exam.domain.Exam; @@ -187,6 +188,9 @@ public class Course extends DomainObject { @Column(name = "unenrollment_enabled") private boolean unenrollmentEnabled = false; + @Column(name = "faq_enabled") + private boolean faqEnabled = false; + @Column(name = "presentation_score") private Integer presentationScore; @@ -260,6 +264,10 @@ public class Course extends DomainObject { @JsonIgnoreProperties("course") private TutorialGroupsConfiguration tutorialGroupsConfiguration; + @OneToMany(mappedBy = "course", cascade = CascadeType.REMOVE, orphanRemoval = true, fetch = FetchType.LAZY) + @JsonIgnoreProperties(value = "course", allowSetters = true) + private Set faqs = new HashSet<>(); + // NOTE: Helpers variable names must be different from Getter name, so that Jackson ignores the @Transient annotation, but Hibernate still respects it @Transient private Long numberOfInstructorsTransient; @@ -627,6 +635,14 @@ public void setEnrollmentEnabled(Boolean enrollmentEnabled) { this.enrollmentEnabled = enrollmentEnabled; } + public boolean isFaqEnabled() { + return faqEnabled; + } + + public void setFaqEnabled(boolean faqEnabled) { + this.faqEnabled = faqEnabled; + } + public String getEnrollmentConfirmationMessage() { return enrollmentConfirmationMessage; } @@ -717,7 +733,7 @@ public String toString() { + "'" + ", enrollmentStartDate='" + getEnrollmentStartDate() + "'" + ", enrollmentEndDate='" + getEnrollmentEndDate() + "'" + ", unenrollmentEndDate='" + getUnenrollmentEndDate() + "'" + ", semester='" + getSemester() + "'" + "'" + ", onlineCourse='" + isOnlineCourse() + "'" + ", color='" + getColor() + "'" + ", courseIcon='" + getCourseIcon() + "'" + ", enrollmentEnabled='" + isEnrollmentEnabled() + "'" + ", unenrollmentEnabled='" + isUnenrollmentEnabled() + "'" - + ", presentationScore='" + getPresentationScore() + "'" + "}"; + + ", presentationScore='" + getPresentationScore() + "'" + ", faqEnabled='" + isFaqEnabled() + "'" + "}"; } public void setNumberOfInstructors(Long numberOfInstructors) { @@ -1057,4 +1073,17 @@ public String getMappedColumnName() { return mappedColumnName; } } + + public Set getFaqs() { + return faqs; + } + + public void setFaqs(Set faqs) { + this.faqs = faqs; + } + + public void addFaq(Faq faq) { + this.faqs.add(faq); + faq.setCourse(this); + } } diff --git a/src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java b/src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java index 9e3b69f269cc..01bb68edc441 100644 --- a/src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java +++ b/src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java @@ -59,6 +59,7 @@ import de.tum.cit.aet.artemis.atlas.service.learningpath.LearningPathService; import de.tum.cit.aet.artemis.communication.domain.NotificationType; import de.tum.cit.aet.artemis.communication.domain.notification.GroupNotification; +import de.tum.cit.aet.artemis.communication.repository.FaqRepository; import de.tum.cit.aet.artemis.communication.repository.GroupNotificationRepository; import de.tum.cit.aet.artemis.communication.repository.conversation.ConversationRepository; import de.tum.cit.aet.artemis.communication.service.notifications.GroupNotificationService; @@ -117,6 +118,8 @@ public class CourseService { private static final Logger log = LoggerFactory.getLogger(CourseService.class); + private final FaqRepository faqRepository; + @Value("${artemis.course-archives-path}") private Path courseArchivesDirPath; @@ -210,7 +213,7 @@ public CourseService(CourseRepository courseRepository, ExerciseService exercise TutorialGroupRepository tutorialGroupRepository, PlagiarismCaseRepository plagiarismCaseRepository, ConversationRepository conversationRepository, LearningPathService learningPathService, Optional irisSettingsService, LectureRepository lectureRepository, TutorialGroupNotificationRepository tutorialGroupNotificationRepository, TutorialGroupChannelManagementService tutorialGroupChannelManagementService, - PrerequisiteRepository prerequisiteRepository, CompetencyRelationRepository competencyRelationRepository) { + PrerequisiteRepository prerequisiteRepository, CompetencyRelationRepository competencyRelationRepository, FaqRepository faqRepository) { this.courseRepository = courseRepository; this.exerciseService = exerciseService; this.exerciseDeletionService = exerciseDeletionService; @@ -250,6 +253,7 @@ public CourseService(CourseRepository courseRepository, ExerciseService exercise this.tutorialGroupChannelManagementService = tutorialGroupChannelManagementService; this.prerequisiteRepository = prerequisiteRepository; this.competencyRelationRepository = competencyRelationRepository; + this.faqRepository = faqRepository; } /** @@ -467,6 +471,7 @@ public void delete(Course course) { deleteDefaultGroups(course); deleteExamsOfCourse(course); deleteGradingScaleOfCourse(course); + deleteFaqsOfCourse(course); irisSettingsService.ifPresent(iss -> iss.deleteSettingsFor(course)); courseRepository.deleteById(course.getId()); log.debug("Successfully deleted course {}.", course.getTitle()); @@ -542,6 +547,10 @@ private void deleteCompetenciesOfCourse(Course course) { competencyRepository.deleteAll(course.getCompetencies()); } + private void deleteFaqsOfCourse(Course course) { + faqRepository.deleteAllByCourseId(course.getId()); + } + /** * If the exercise is part of an exam, retrieve the course through ExerciseGroup -> Exam -> Course. * Otherwise, the course is already set and the id can be used to retrieve the course from the database. diff --git a/src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java b/src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java index 10da69a96a5d..0cb3379e4f99 100644 --- a/src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java +++ b/src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java @@ -364,14 +364,14 @@ else if (courseUpdate.getCourseIcon() == null && existingCourse.getCourseIcon() } /** - * PUT courses/:courseId/onlineCourseConfiguration : Updates the onlineCourseConfiguration for the given course. + * PUT courses/:courseId/online-course-configuration : Updates the onlineCourseConfiguration for the given course. * * @param courseId the id of the course to update * @param onlineCourseConfiguration the online course configuration to update * @return the ResponseEntity with status 200 (OK) and with body the updated online course configuration */ // TODO: move into LTIResource - @PutMapping("courses/{courseId}/onlineCourseConfiguration") + @PutMapping("courses/{courseId}/online-course-configuration") @EnforceAtLeastInstructor @Profile(PROFILE_LTI) public ResponseEntity updateOnlineCourseConfiguration(@PathVariable Long courseId, @@ -821,12 +821,12 @@ public ResponseEntity getCourseWithOrganizations(@PathVariable Long cour } /** - * GET /courses/:courseId/lockedSubmissions Get locked submissions for course for user + * GET /courses/:courseId/locked-submissions Get locked submissions for course for user * * @param courseId the id of the course * @return the ResponseEntity with status 200 (OK) and with body the course, or with status 404 (Not Found) */ - @GetMapping("courses/{courseId}/lockedSubmissions") + @GetMapping("courses/{courseId}/locked-submissions") @EnforceAtLeastTutor public ResponseEntity> getLockedSubmissionsForCourse(@PathVariable Long courseId) { log.debug("REST request to get all locked submissions for course : {}", courseId); diff --git a/src/main/java/de/tum/cit/aet/artemis/exam/web/ExamResource.java b/src/main/java/de/tum/cit/aet/artemis/exam/web/ExamResource.java index 40be2685e58e..209f2a4fa040 100644 --- a/src/main/java/de/tum/cit/aet/artemis/exam/web/ExamResource.java +++ b/src/main/java/de/tum/cit/aet/artemis/exam/web/ExamResource.java @@ -1170,13 +1170,13 @@ public ResponseEntity getLatestIndividualEndDateOfExam(@Path } /** - * GET /courses/:courseId/exams/:examId/lockedSubmissions Get locked submissions for exam for user + * GET /courses/:courseId/exams/:examId/locked-submissions Get locked submissions for exam for user * * @param courseId - the id of the course * @param examId - the id of the exam * @return the ResponseEntity with status 200 (OK) and with body the course, or with status 404 (Not Found) */ - @GetMapping("courses/{courseId}/exams/{examId}/lockedSubmissions") + @GetMapping("courses/{courseId}/exams/{examId}/locked-submissions") @EnforceAtLeastInstructor public ResponseEntity> getLockedSubmissionsForExam(@PathVariable Long courseId, @PathVariable Long examId) { log.debug("REST request to get all locked submissions for course : {}", courseId); diff --git a/src/main/java/de/tum/cit/aet/artemis/exam/web/ExerciseGroupResource.java b/src/main/java/de/tum/cit/aet/artemis/exam/web/ExerciseGroupResource.java index 2593102ed063..97ebc25f858b 100644 --- a/src/main/java/de/tum/cit/aet/artemis/exam/web/ExerciseGroupResource.java +++ b/src/main/java/de/tum/cit/aet/artemis/exam/web/ExerciseGroupResource.java @@ -83,7 +83,7 @@ public ExerciseGroupResource(ExerciseGroupRepository exerciseGroupRepository, Ex } /** - * POST /courses/{courseId}/exams/{examId}/exerciseGroups : Create a new exercise group. + * POST /courses/{courseId}/exams/{examId}/exercise-groups : Create a new exercise group. * * @param courseId the course to which the exercise group belongs to * @param examId the exam to which the exercise group belongs to @@ -92,7 +92,7 @@ public ExerciseGroupResource(ExerciseGroupRepository exerciseGroupRepository, Ex * or with status 400 (Bad Request) if the exerciseGroup has already an ID * @throws URISyntaxException if the Location URI syntax is incorrect */ - @PostMapping("courses/{courseId}/exams/{examId}/exerciseGroups") + @PostMapping("courses/{courseId}/exams/{examId}/exercise-groups") @EnforceAtLeastEditor public ResponseEntity createExerciseGroup(@PathVariable Long courseId, @PathVariable Long examId, @RequestBody ExerciseGroup exerciseGroup) throws URISyntaxException { @@ -117,11 +117,11 @@ public ResponseEntity createExerciseGroup(@PathVariable Long cour Exam savedExam = examRepository.save(examFromDB); ExerciseGroup savedExerciseGroup = savedExam.getExerciseGroups().getLast(); - return ResponseEntity.created(new URI("/api/courses/" + courseId + "/exams/" + examId + "/exerciseGroups/" + savedExerciseGroup.getId())).body(savedExerciseGroup); + return ResponseEntity.created(new URI("/api/courses/" + courseId + "/exams/" + examId + "/exercise-groups/" + savedExerciseGroup.getId())).body(savedExerciseGroup); } /** - * PUT /courses/{courseId}/exams/{examId}/exerciseGroups : Update an existing exercise group. + * PUT /courses/{courseId}/exams/{examId}/exercise-groups : Update an existing exercise group. * * @param courseId the course to which the exercise group belongs to * @param examId the exam to which the exercise group belongs to @@ -129,7 +129,7 @@ public ResponseEntity createExerciseGroup(@PathVariable Long cour * @return the ResponseEntity with status 200 (OK) and with the body of the updated exercise group * @throws URISyntaxException if the Location URI syntax is incorrect */ - @PutMapping("courses/{courseId}/exams/{examId}/exerciseGroups") + @PutMapping("courses/{courseId}/exams/{examId}/exercise-groups") @EnforceAtLeastEditor public ResponseEntity updateExerciseGroup(@PathVariable Long courseId, @PathVariable Long examId, @RequestBody ExerciseGroup updatedExerciseGroup) throws URISyntaxException { @@ -170,14 +170,14 @@ public ResponseEntity> importExerciseGroup(@PathVariable Lon } /** - * GET /courses/{courseId}/exams/{examId}/exerciseGroups/{exerciseGroupId} : Find an exercise group by id. + * GET /courses/{courseId}/exams/{examId}/exercise-groups/{exerciseGroupId} : Find an exercise group by id. * * @param courseId the course to which the exercise group belongs to * @param examId the exam to which the exercise group belongs to * @param exerciseGroupId the id of the exercise group to find * @return the ResponseEntity with status 200 (OK) and with the found exercise group as body */ - @GetMapping("courses/{courseId}/exams/{examId}/exerciseGroups/{exerciseGroupId}") + @GetMapping("courses/{courseId}/exams/{examId}/exercise-groups/{exerciseGroupId}") @EnforceAtLeastEditor public ResponseEntity getExerciseGroup(@PathVariable Long courseId, @PathVariable Long examId, @PathVariable Long exerciseGroupId) { log.debug("REST request to get exercise group : {}", exerciseGroupId); @@ -189,13 +189,13 @@ public ResponseEntity getExerciseGroup(@PathVariable Long courseI } /** - * GET courses/{courseId}/exams/{examId}/exerciseGroups : Get all exercise groups of the given exam + * GET courses/{courseId}/exams/{examId}/exercise-groups : Get all exercise groups of the given exam * * @param courseId the course to which the exercise groups belong to * @param examId the exam to which the exercise groups belong to * @return the ResponseEntity with status 200 (OK) and a list of exercise groups. The list can be empty */ - @GetMapping("courses/{courseId}/exams/{examId}/exerciseGroups") + @GetMapping("courses/{courseId}/exams/{examId}/exercise-groups") @EnforceAtLeastEditor public ResponseEntity> getExerciseGroupsForExam(@PathVariable Long courseId, @PathVariable Long examId) { log.debug("REST request to get all exercise groups for exam : {}", examId); @@ -207,7 +207,7 @@ public ResponseEntity> getExerciseGroupsForExam(@PathVariabl } /** - * DELETE /courses/{courseId}/exams/{examId}/exerciseGroups/{exerciseGroupId} : Delete the exercise group with the given id. + * DELETE /courses/{courseId}/exams/{examId}/exercise-groups/{exerciseGroupId} : Delete the exercise group with the given id. * * @param courseId the course to which the exercise group belongs to * @param examId the exam to which the exercise group belongs to @@ -218,7 +218,7 @@ public ResponseEntity> getExerciseGroupsForExam(@PathVariabl * LocalCI, it does not make sense to keep these artifacts * @return the ResponseEntity with status 200 (OK) */ - @DeleteMapping("courses/{courseId}/exams/{examId}/exerciseGroups/{exerciseGroupId}") + @DeleteMapping("courses/{courseId}/exams/{examId}/exercise-groups/{exerciseGroupId}") @EnforceAtLeastInstructor public ResponseEntity deleteExerciseGroup(@PathVariable Long courseId, @PathVariable Long examId, @PathVariable Long exerciseGroupId, @RequestParam(defaultValue = "true") boolean deleteStudentReposBuildPlans, @RequestParam(defaultValue = "true") boolean deleteBaseReposBuildPlans) { diff --git a/src/main/java/de/tum/cit/aet/artemis/exercise/web/ParticipationResource.java b/src/main/java/de/tum/cit/aet/artemis/exercise/web/ParticipationResource.java index 6559c28b9d93..c6cdc6ee1730 100644 --- a/src/main/java/de/tum/cit/aet/artemis/exercise/web/ParticipationResource.java +++ b/src/main/java/de/tum/cit/aet/artemis/exercise/web/ParticipationResource.java @@ -718,7 +718,7 @@ public ResponseEntity> getAllParticipationsForCourse( * @param participationId the participationId of the participation to retrieve * @return the ResponseEntity with status 200 (OK) and with body the participation, or with status 404 (Not Found) */ - @GetMapping("participations/{participationId}/withLatestResult") + @GetMapping("participations/{participationId}/with-latest-result") @EnforceAtLeastStudent public ResponseEntity getParticipationWithLatestResult(@PathVariable Long participationId) { log.debug("REST request to get Participation : {}", participationId); @@ -756,7 +756,7 @@ public ResponseEntity getParticipationForCurrentUser(@Path * @param participationId The participationId of the participation * @return The latest build artifact (JAR/WAR) for the participation */ - @GetMapping("participations/{participationId}/buildArtifact") + @GetMapping("participations/{participationId}/build-artifact") @EnforceAtLeastStudent public ResponseEntity getParticipationBuildArtifact(@PathVariable Long participationId) { log.debug("REST request to get Participation build artifact: {}", participationId); @@ -931,14 +931,14 @@ private ResponseEntity deleteParticipation(StudentParticipation participat } /** - * DELETE /participations/:participationId : remove the build plan of the ProgrammingExerciseStudentParticipation of the "participationId". + * DELETE /participations/:participationId/cleanup-build-plan : remove the build plan of the ProgrammingExerciseStudentParticipation of the "participationId". * This only works for programming exercises. * * @param participationId the participationId of the ProgrammingExerciseStudentParticipation for which the build plan should be removed * @param principal The identity of the user accessing this resource * @return the ResponseEntity with status 200 (OK) */ - @PutMapping("participations/{participationId}/cleanupBuildPlan") + @PutMapping("participations/{participationId}/cleanup-build-plan") @EnforceAtLeastInstructor @FeatureToggle(Feature.ProgrammingExercises) public ResponseEntity cleanupBuildPlan(@PathVariable Long participationId, Principal principal) { diff --git a/src/main/java/de/tum/cit/aet/artemis/plagiarism/service/ProgrammingPlagiarismDetectionService.java b/src/main/java/de/tum/cit/aet/artemis/plagiarism/service/ProgrammingPlagiarismDetectionService.java index a3c2cec8e9df..9fe9b1cc0f8c 100644 --- a/src/main/java/de/tum/cit/aet/artemis/plagiarism/service/ProgrammingPlagiarismDetectionService.java +++ b/src/main/java/de/tum/cit/aet/artemis/plagiarism/service/ProgrammingPlagiarismDetectionService.java @@ -32,10 +32,12 @@ import de.jplag.clustering.ClusteringOptions; import de.jplag.exceptions.ExitException; import de.jplag.java.JavaLanguage; +import de.jplag.javascript.JavaScriptLanguage; import de.jplag.kotlin.KotlinLanguage; import de.jplag.options.JPlagOptions; import de.jplag.python3.PythonLanguage; import de.jplag.reporting.reportobject.ReportObjectFactory; +import de.jplag.rust.RustLanguage; import de.jplag.swift.SwiftLanguage; import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException; import de.tum.cit.aet.artemis.core.exception.GitException; @@ -313,8 +315,11 @@ private Language getJPlagProgrammingLanguage(ProgrammingExercise programmingExer case PYTHON -> new PythonLanguage(); case SWIFT -> new SwiftLanguage(); case KOTLIN -> new KotlinLanguage(); - default -> throw new BadRequestAlertException("Programming language " + programmingExercise.getProgrammingLanguage() + " not supported for plagiarism check.", - "ProgrammingExercise", "notSupported"); + case RUST -> new RustLanguage(); + case JAVASCRIPT -> new JavaScriptLanguage(); + case EMPTY, PHP, DART, HASKELL, ASSEMBLER, OCAML, C_SHARP, C_PLUS_PLUS, SQL, R, TYPESCRIPT, GO, MATLAB, BASH, VHDL, RUBY, POWERSHELL, ADA -> + throw new BadRequestAlertException("Programming language " + programmingExercise.getProgrammingLanguage() + " not supported for plagiarism check.", + "ProgrammingExercise", "notSupported"); }; } diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/gitlabci/GitLabCIProgrammingLanguageFeatureService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/gitlabci/GitLabCIProgrammingLanguageFeatureService.java index 7cd996e35cc4..a92bcdd26cb5 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/gitlabci/GitLabCIProgrammingLanguageFeatureService.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/gitlabci/GitLabCIProgrammingLanguageFeatureService.java @@ -25,7 +25,7 @@ public class GitLabCIProgrammingLanguageFeatureService extends ProgrammingLangua public GitLabCIProgrammingLanguageFeatureService() { programmingLanguageFeatures.put(EMPTY, new ProgrammingLanguageFeature(EMPTY, false, false, false, false, false, List.of(), false, false)); programmingLanguageFeatures.put(JAVA, new ProgrammingLanguageFeature(JAVA, false, false, false, true, false, List.of(PLAIN_MAVEN, MAVEN_MAVEN), false, false)); - programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, false, false, false, List.of(), false, false)); - programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, false, false, false, List.of(), false, false)); + programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, true, false, false, List.of(), false, false)); + programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, true, false, false, List.of(), false, false)); } } diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/jenkins/JenkinsProgrammingLanguageFeatureService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/jenkins/JenkinsProgrammingLanguageFeatureService.java index 94e6bf8d27fc..38893ea41093 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/jenkins/JenkinsProgrammingLanguageFeatureService.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/jenkins/JenkinsProgrammingLanguageFeatureService.java @@ -41,7 +41,7 @@ public JenkinsProgrammingLanguageFeatureService() { programmingLanguageFeatures.put(SWIFT, new ProgrammingLanguageFeature(SWIFT, false, true, true, true, false, List.of(PLAIN), false, false)); programmingLanguageFeatures.put(C, new ProgrammingLanguageFeature(C, false, false, true, false, false, List.of(FACT, GCC), false, false)); programmingLanguageFeatures.put(HASKELL, new ProgrammingLanguageFeature(HASKELL, false, false, false, false, true, List.of(), false, false)); - programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, false, false, false, List.of(), false, false)); - programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, false, false, false, List.of(), false, false)); + programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, true, false, false, List.of(), false, false)); + programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, true, false, false, List.of(), false, false)); } } diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIProgrammingLanguageFeatureService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIProgrammingLanguageFeatureService.java index 967e05604f30..525170cca334 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIProgrammingLanguageFeatureService.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIProgrammingLanguageFeatureService.java @@ -49,7 +49,7 @@ public LocalCIProgrammingLanguageFeatureService() { programmingLanguageFeatures.put(HASKELL, new ProgrammingLanguageFeature(HASKELL, true, false, false, false, true, List.of(), false, true)); programmingLanguageFeatures.put(OCAML, new ProgrammingLanguageFeature(OCAML, false, false, false, false, true, List.of(), false, true)); programmingLanguageFeatures.put(SWIFT, new ProgrammingLanguageFeature(SWIFT, false, false, true, true, false, List.of(PLAIN), false, true)); - programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, false, false, false, List.of(), false, true)); - programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, false, false, false, List.of(), false, true)); + programmingLanguageFeatures.put(RUST, new ProgrammingLanguageFeature(RUST, false, false, true, false, false, List.of(), false, true)); + programmingLanguageFeatures.put(JAVASCRIPT, new ProgrammingLanguageFeature(JAVASCRIPT, false, false, true, false, false, List.of(), false, true)); } } diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/web/localci/AeolusTemplateResource.java b/src/main/java/de/tum/cit/aet/artemis/programming/web/localci/AeolusTemplateResource.java index 9919c2440364..9e5530e94813 100644 --- a/src/main/java/de/tum/cit/aet/artemis/programming/web/localci/AeolusTemplateResource.java +++ b/src/main/java/de/tum/cit/aet/artemis/programming/web/localci/AeolusTemplateResource.java @@ -79,8 +79,8 @@ public ResponseEntity getAeolusTemplate(@PathVariable ProgrammingLanguag } /** - * GET /api/aeolus/templates/:language/:projectType : Get the aeolus template file with the given filename
- * GET /api/aeolus/templates/:language : Get the aeolus template file with the given filename + * GET /api/aeolus/template-scripts/:language/:projectType : Get the aeolus template file with the given filename
+ * GET /api/aeolus/template-scripts/:language : Get the aeolus template file with the given filename *

* The windfile contains the default build plan configuration for new programming exercises. * @@ -91,7 +91,7 @@ public ResponseEntity getAeolusTemplate(@PathVariable ProgrammingLanguag * @param testCoverage Whether the test coverage template should be used * @return The requested file, or 404 if the file doesn't exist */ - @GetMapping({ "templateScripts/{language}/{projectType}", "templateScripts/{language}" }) + @GetMapping({ "template-scripts/{language}/{projectType}", "template-scripts/{language}" }) @EnforceAtLeastEditor public ResponseEntity getAeolusTemplateScript(@PathVariable ProgrammingLanguage language, @PathVariable Optional projectType, @RequestParam(value = "staticAnalysis", defaultValue = "false") boolean staticAnalysis, diff --git a/src/main/java/de/tum/cit/aet/artemis/tutorialgroup/domain/TutorialGroup.java b/src/main/java/de/tum/cit/aet/artemis/tutorialgroup/domain/TutorialGroup.java index 5a4f4c4b2f45..448f97e9ea1e 100644 --- a/src/main/java/de/tum/cit/aet/artemis/tutorialgroup/domain/TutorialGroup.java +++ b/src/main/java/de/tum/cit/aet/artemis/tutorialgroup/domain/TutorialGroup.java @@ -104,6 +104,18 @@ public class TutorialGroup extends DomainObject { @Transient private String teachingAssistantName; + /** + * This transient fields is set to the name of the teaching assistant of this tutorial group + */ + @Transient + private Long teachingAssistantId; + + /** + * This transient fields is set to the name of the teaching assistant of this tutorial group + */ + @Transient + private String teachingAssistantImageUrl; + /** * This transient fields is set to the course title to which this tutorial group belongs */ @@ -290,10 +302,30 @@ public String getTeachingAssistantName() { return teachingAssistantName; } + @JsonIgnore(false) + @JsonProperty + public Long getTeachingAssistantId() { + return teachingAssistantId; + } + + @JsonIgnore(false) + @JsonProperty + public String getTeachingAssistantImageUrl() { + return teachingAssistantImageUrl; + } + public void setTeachingAssistantName(String teachingAssistantName) { this.teachingAssistantName = teachingAssistantName; } + public void setTeachingAssistantId(Long teachingAssistantId) { + this.teachingAssistantId = teachingAssistantId; + } + + public void setTeachingAssistantImageUrl(String teachingAssistantImageUrl) { + this.teachingAssistantImageUrl = teachingAssistantImageUrl; + } + @JsonIgnore(false) @JsonProperty public String getCourseTitle() { diff --git a/src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java b/src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java index e339fc473e52..4f8ef7279c1e 100644 --- a/src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java +++ b/src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java @@ -114,10 +114,14 @@ public void setTransientPropertiesForUser(User user, TutorialGroup tutorialGroup if (getPersistenceUtil().isLoaded(tutorialGroup, "teachingAssistant") && tutorialGroup.getTeachingAssistant() != null) { tutorialGroup.setTeachingAssistantName(tutorialGroup.getTeachingAssistant().getName()); + tutorialGroup.setTeachingAssistantId(tutorialGroup.getTeachingAssistant().getId()); + tutorialGroup.setTeachingAssistantImageUrl(tutorialGroup.getTeachingAssistant().getImageUrl()); tutorialGroup.setIsUserTutor(tutorialGroup.getTeachingAssistant().equals(user)); } else { tutorialGroup.setTeachingAssistantName(null); + tutorialGroup.setTeachingAssistantId(null); + tutorialGroup.setTeachingAssistantImageUrl(null); } if (tutorialGroup.getTutorialGroupChannel() != null) { diff --git a/src/main/resources/config/liquibase/changelog/20240902175045_changelog.xml b/src/main/resources/config/liquibase/changelog/20240902175045_changelog.xml new file mode 100644 index 000000000000..6344b448df92 --- /dev/null +++ b/src/main/resources/config/liquibase/changelog/20240902175045_changelog.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/config/liquibase/master.xml b/src/main/resources/config/liquibase/master.xml index 64295fe02504..49f3eeee4d63 100644 --- a/src/main/resources/config/liquibase/master.xml +++ b/src/main/resources/config/liquibase/master.xml @@ -23,6 +23,7 @@ + diff --git a/src/main/webapp/app/course/competencies/competency-card/competency-card.component.html b/src/main/webapp/app/course/competencies/competency-card/competency-card.component.html index ffddb7b4643a..27038983513a 100644 --- a/src/main/webapp/app/course/competencies/competency-card/competency-card.component.html +++ b/src/main/webapp/app/course/competencies/competency-card/competency-card.component.html @@ -1,19 +1,19 @@

- @if (courseId && !isPrerequisite) { - + @if (courseId() && !isPrerequisite()) { + }
@@ -22,45 +22,47 @@

- +

- {{ competency.title }} + {{ competency()?.title }} @if (isMastered) { } - @if (competency.optional) { + @if (competency()?.optional) { }

- @if (competency.description) { -

+ @if (competency()?.description) { +

} - @if (isPrerequisite && competency.linkedCourseCompetency?.course) { + @if (isPrerequisite() && competency()?.linkedCourseCompetency?.course) {
- @if (competency.linkedCourseCompetency!.course!.title) { - {{ competency.linkedCourseCompetency!.course!.title! }} + @if (competency()!.linkedCourseCompetency!.course!.title) { + {{ competency()!.linkedCourseCompetency!.course!.title! }} } - @if (competency.linkedCourseCompetency!.course!.semester) { - {{ competency.linkedCourseCompetency!.course!.semester! }} + @if (competency()!.linkedCourseCompetency!.course!.semester) { + {{ competency()!.linkedCourseCompetency!.course!.semester! }} }
}
- @if (competency.softDueDate) { + @if (competency()?.softDueDate) {
- {{ competency.softDueDate! | artemisTimeAgo }} + {{ competency()!.softDueDate! | artemisTimeAgo }}
} -
- -
+ @if (!noProgressRings()) { +
+ +
+ }
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 e7e8829c0680..462369931d12 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,7 +1,7 @@ import dayjs from 'dayjs/esm'; -import { Component, Input } from '@angular/core'; +import { Component, input } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; -import { Competency, CompetencyProgress, getIcon, getMastery, getProgress } from 'app/entities/competency.model'; +import { CompetencyProgress, CourseCompetency, getIcon, getMastery, getProgress } from 'app/entities/competency.model'; @Component({ selector: 'jhi-competency-card', @@ -9,22 +9,20 @@ import { Competency, CompetencyProgress, getIcon, getMastery, getProgress } from styleUrls: ['../../../overview/course-exercises/course-exercise-row.scss'], }) export class CompetencyCardComponent { - @Input() - courseId: number | undefined; - @Input() - competency: Competency; - @Input() - isPrerequisite: boolean; - @Input() - hideProgress = false; + courseId = input(); + competency = input(); + isPrerequisite = input(); + hideProgress = input(false); + noProgressRings = input(false); - getIcon = getIcon; + protected readonly getIcon = getIcon; constructor(public translateService: TranslateService) {} getUserProgress(): CompetencyProgress { - if (this.competency.userProgress?.length) { - return this.competency.userProgress.first()!; + const userProgress = this.competency()?.userProgress?.first(); + if (userProgress) { + return userProgress; } return { progress: 0, confidence: 1 } as CompetencyProgress; } @@ -42,6 +40,6 @@ export class CompetencyCardComponent { } get softDueDatePassed(): boolean { - return dayjs().isAfter(this.competency.softDueDate); + return dayjs().isAfter(this.competency()?.softDueDate); } } diff --git a/src/main/webapp/app/course/manage/course-management-tab-bar/course-management-tab-bar.component.html b/src/main/webapp/app/course/manage/course-management-tab-bar/course-management-tab-bar.component.html index 3c953bcf4e3a..abbfdaf7c010 100644 --- a/src/main/webapp/app/course/manage/course-management-tab-bar/course-management-tab-bar.component.html +++ b/src/main/webapp/app/course/manage/course-management-tab-bar/course-management-tab-bar.component.html @@ -72,6 +72,12 @@ } + @if (course.isAtLeastInstructor && course.faqEnabled) { + + + + + } @if (course.isAtLeastInstructor && localCIActive) { 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 c46c04bbcf5d..c25c182067e3 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 @@ -20,6 +20,7 @@ import { faNetworkWired, faPersonChalkboard, faPuzzlePiece, + faQuestion, faRobot, faTable, faTrash, @@ -73,6 +74,7 @@ export class CourseManagementTabBarComponent implements OnInit, OnDestroy, After faRobot = faRobot; faPuzzlePiece = faPuzzlePiece; faList = faList; + faQuestion = faQuestion; isCommunicationEnabled = false; 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 834a917d1c31..ad4507123d1a 100644 --- a/src/main/webapp/app/course/manage/course-management.route.ts +++ b/src/main/webapp/app/course/manage/course-management.route.ts @@ -33,6 +33,9 @@ import { ImportPrerequisitesComponent } from 'app/course/competencies/import/imp 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 { 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 = [ { @@ -334,6 +337,58 @@ export const courseManagementState: Routes = [ }, canActivate: [UserRouteAccessService, LocalCIGuard], }, + { + path: 'faqs', + children: [ + { + path: '', + component: FaqComponent, + resolve: { + course: CourseManagementResolve, + }, + data: { + authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], + pageTitle: 'artemisApp.faq.home.title', + }, + canActivate: [UserRouteAccessService], + }, + { + // Create a new path without a component defined to prevent the FAQ from being always rendered + path: '', + resolve: { + course: CourseManagementResolve, + }, + children: [ + { + path: 'new', + component: FaqUpdateComponent, + data: { + authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], + pageTitle: 'global.generic.create', + }, + canActivate: [UserRouteAccessService], + }, + { + path: ':faqId', + resolve: { + faq: FaqResolve, + }, + children: [ + { + path: 'edit', + component: FaqUpdateComponent, + data: { + authorities: [Authority.EDITOR, Authority.INSTRUCTOR, Authority.ADMIN], + pageTitle: 'global.generic.edit', + }, + canActivate: [UserRouteAccessService], + }, + ], + }, + ], + }, + ], + }, ], }, ], 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 0f442cada5ea..1db71b31aac3 100644 --- a/src/main/webapp/app/course/manage/course-management.service.ts +++ b/src/main/webapp/app/course/manage/course-management.service.ts @@ -41,6 +41,9 @@ export class CourseManagementService { private fetchingCoursesForNotifications = false; + private courseOverviewSubject = new BehaviorSubject(false); + isCourseOverview$ = this.courseOverviewSubject.asObservable(); + constructor( private http: HttpClient, private courseStorageService: CourseStorageService, @@ -77,7 +80,7 @@ export class CourseManagementService { * @param onlineCourseConfiguration - the updates to the online course configuration */ updateOnlineCourseConfiguration(courseId: number, onlineCourseConfiguration: OnlineCourseConfiguration): Observable { - return this.http.put(`${this.resourceUrl}/${courseId}/onlineCourseConfiguration`, onlineCourseConfiguration, { observe: 'response' }); + return this.http.put(`${this.resourceUrl}/${courseId}/online-course-configuration`, onlineCourseConfiguration, { observe: 'response' }); } findAllOnlineCoursesWithRegistrationId(clientId: string): Observable { @@ -442,7 +445,7 @@ export class CourseManagementService { * @param {number} courseId - The id of the course to be searched for */ findAllLockedSubmissionsOfCourse(courseId: number): Observable> { - return this.http.get(`${this.resourceUrl}/${courseId}/lockedSubmissions`, { observe: 'response' }).pipe( + return this.http.get(`${this.resourceUrl}/${courseId}/locked-submissions`, { observe: 'response' }).pipe( filter((res) => !!res.body), tap((res) => reconnectSubmissions(res.body!)), ); @@ -692,4 +695,12 @@ export class CourseManagementService { // Note: 0 is the default value in case the server returns something that does not make sense return this.http.get(`${this.resourceUrl}/${courseId}/allowed-complaints?teamMode=${teamMode}`) ?? 0; } + + enableCourseOverviewBackground() { + this.courseOverviewSubject.next(true); + } + + disableCourseOverviewBackground() { + this.courseOverviewSubject.next(false); + } } diff --git a/src/main/webapp/app/course/manage/course-update.component.html b/src/main/webapp/app/course/manage/course-update.component.html index 43b03f3f9040..e12c96946e15 100644 --- a/src/main/webapp/app/course/manage/course-update.component.html +++ b/src/main/webapp/app/course/manage/course-update.component.html @@ -309,6 +309,23 @@
}
+
+ + + +
0 || this.course.maxTeamComplaints! > 0) && @@ -192,6 +193,7 @@ export class CourseUpdateComponent implements OnInit { studentCourseAnalyticsDashboardEnabled: new FormControl(this.course.studentCourseAnalyticsDashboardEnabled), onlineCourse: new FormControl(this.course.onlineCourse), complaintsEnabled: new FormControl(this.complaintsEnabled), + faqEnabled: new FormControl(this.faqEnabled), requestMoreFeedbackEnabled: new FormControl(this.requestMoreFeedbackEnabled), maxPoints: new FormControl(this.course.maxPoints, { validators: [Validators.min(1)], @@ -284,7 +286,6 @@ export class CourseUpdateComponent implements OnInit { if (this.courseForm.controls['organizations'] !== undefined) { this.courseForm.controls['organizations'].setValue(this.courseOrganizations); } - let file = undefined; if (this.courseImageUploadFile && this.croppedImage) { const base64Data = this.croppedImage.replace('data:image/png;base64,', ''); @@ -506,6 +507,10 @@ export class CourseUpdateComponent implements OnInit { this.courseForm.controls['instructorGroupName'].setValue(instructorGroupName); } + changeFaqEnabled() { + this.faqEnabled = !this.faqEnabled; + this.courseForm.controls['faqEnabled'].setValue(this.faqEnabled); + } /** * Enable or disable test course */ diff --git a/src/main/webapp/app/course/manage/overview/course-management-card.component.html b/src/main/webapp/app/course/manage/overview/course-management-card.component.html index adf01ba9af77..d13dee53b6e5 100644 --- a/src/main/webapp/app/course/manage/overview/course-management-card.component.html +++ b/src/main/webapp/app/course/manage/overview/course-management-card.component.html @@ -338,5 +338,17 @@

} + + @if (course.isAtLeastInstructor && course.faqEnabled) { + + + + + }

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 32dca0a3fc2d..2fd25af861ed 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 @@ -19,6 +19,7 @@ import { faListAlt, faNetworkWired, faPersonChalkboard, + faQuestion, faSpinner, faTable, faUserCheck, @@ -77,6 +78,7 @@ export class CourseManagementCardComponent implements OnChanges { faAngleUp = faAngleUp; faPersonChalkboard = faPersonChalkboard; faSpinner = faSpinner; + faQuestion = faQuestion; courseColor: string; 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 af37a2946f91..65f3b52a53e4 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 @@ -11,6 +11,8 @@ import { TranslateService } from '@ngx-translate/core'; import { Detail } from 'app/detail-overview-list/detail.model'; import dayjs from 'dayjs/esm'; import { SortService } from 'app/shared/service/sort.service'; +import { getInitialsFromString } from 'app/utils/text.utils'; +import { getBackgroundColorHue } from 'app/utils/color.utils'; @Component({ selector: 'jhi-tutorial-group-detail', @@ -83,6 +85,20 @@ export class TutorialGroupDetailComponent implements OnChanges { { type: DetailType.Link, title: 'artemisApp.entities.tutorialGroup.course', data: { text: tutorialGroup.courseTitle, routerLink: ['../..'] } }, { type: DetailType.Text, title: 'artemisApp.entities.tutorialGroup.title', data: { text: tutorialGroup.title } }, { type: DetailType.Text, title: 'artemisApp.entities.tutorialGroup.teachingAssistant', data: { text: tutorialGroup.teachingAssistantName } }, + tutorialGroup.teachingAssistantImageUrl + ? { + type: DetailType.Image, + title: 'artemisApp.entities.tutorialGroup.profilePicture', + data: { imageUrl: tutorialGroup.teachingAssistantImageUrl, altText: 'Profile picture of ' + tutorialGroup.teachingAssistantName }, + } + : { + type: DetailType.DefaultProfilePicture, + title: 'artemisApp.entities.tutorialGroup.profilePicture', + data: { + color: getBackgroundColorHue(tutorialGroup.teachingAssistantId ? tutorialGroup.teachingAssistantId.toString() : 'default'), + initials: getInitialsFromString(tutorialGroup.teachingAssistantName ?? 'NA'), + }, + }, { type: DetailType.Text, title: 'artemisApp.entities.tutorialGroup.utilization', diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index 54cc218a7f3b..2500e4d9477a 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -124,6 +124,16 @@

{{ section /> } + @case (DetailType.Image) { +
+ +
+ } + @case (DetailType.DefaultProfilePicture) { +
+ {{ detail.data.initials }} +
+ } @default {
diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.scss b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.scss index e4a25e0c952d..3c4e566cec21 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.scss +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.scss @@ -1,3 +1,5 @@ +$details-image-height: 3rem; + .section-headline { margin-top: 1rem; margin-bottom: 0.5rem; @@ -11,3 +13,20 @@ .diff-view-modal .modal-dialog { max-width: 80vw; } + +.details-default-profile-picture { + width: $details-image-height; + height: $details-image-height; + font-size: 1.5rem; + display: inline-flex; + align-items: center; + justify-content: center; + background-color: var(--gray-400); + color: var(--white); +} + +.details-image { + width: $details-image-height; + height: $details-image-height; + object-fit: cover; +} 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 60ed25bd572a..25a5a6ca72e6 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 @@ -20,6 +20,8 @@ export interface DetailOverviewSection { export enum DetailType { Link = 'detail-link', Text = 'detail-text', + DefaultProfilePicture = 'detail-default-profile-picture', + Image = 'detail-image', Date = 'detail-date', Boolean = 'detail-boolean', Markdown = 'detail-markdown', diff --git a/src/main/webapp/app/detail-overview-list/detail.model.ts b/src/main/webapp/app/detail-overview-list/detail.model.ts index 4e80437fe3d2..b34f408ef435 100644 --- a/src/main/webapp/app/detail-overview-list/detail.model.ts +++ b/src/main/webapp/app/detail-overview-list/detail.model.ts @@ -22,6 +22,8 @@ export type ShownDetail = | TextDetail | DateDetail | LinkDetail + | ImageDetail + | DefaultProfilePicture | BooleanDetail | MarkdownDetail | GradingCriteriaDetail @@ -58,6 +60,16 @@ export interface LinkDetail extends DetailBase { data: { text?: string | number; href?: string | false; routerLink?: (string | number | undefined)[]; queryParams?: Record }; } +export interface ImageDetail extends DetailBase { + type: DetailType.Image; + data: { altText?: string; imageUrl?: string }; +} + +export interface DefaultProfilePicture extends DetailBase { + type: DetailType.DefaultProfilePicture; + data: { color: string; initials: string }; +} + export interface BooleanDetail extends DetailBase { type: DetailType.Boolean; data: { boolean?: boolean }; diff --git a/src/main/webapp/app/entities/course.model.ts b/src/main/webapp/app/entities/course.model.ts index 4f179de3a687..6cddcfe61040 100644 --- a/src/main/webapp/app/entities/course.model.ts +++ b/src/main/webapp/app/entities/course.model.ts @@ -62,6 +62,7 @@ export class Course implements BaseEntity { public color?: string; public courseIcon?: string; public onlineCourse?: boolean; + public faqEnabled?: boolean; public enrollmentEnabled?: boolean; public enrollmentConfirmationMessage?: string; public unenrollmentEnabled?: boolean; diff --git a/src/main/webapp/app/entities/faq-category.model.ts b/src/main/webapp/app/entities/faq-category.model.ts new file mode 100644 index 000000000000..4094ed34dc57 --- /dev/null +++ b/src/main/webapp/app/entities/faq-category.model.ts @@ -0,0 +1,29 @@ +export class FaqCategory { + public color?: string; + + public category?: string; + + constructor(category: string | undefined, color: string | undefined) { + this.color = color; + this.category = category; + } + + equals(otherFaqCategory: FaqCategory): boolean { + return this.color === otherFaqCategory.color && this.category === otherFaqCategory.category; + } + + /** + * @param otherFaqCategory + * @returns the alphanumerical order of the two categories based on their display text + */ + compare(otherFaqCategory: FaqCategory): number { + if (this.category === otherFaqCategory.category) { + return 0; + } + + const displayText = this.category?.toLowerCase() ?? ''; + const otherCategoryDisplayText = otherFaqCategory.category?.toLowerCase() ?? ''; + + return displayText < otherCategoryDisplayText ? -1 : 1; + } +} diff --git a/src/main/webapp/app/entities/faq.model.ts b/src/main/webapp/app/entities/faq.model.ts new file mode 100644 index 000000000000..ea6de090b2b2 --- /dev/null +++ b/src/main/webapp/app/entities/faq.model.ts @@ -0,0 +1,18 @@ +import { BaseEntity } from 'app/shared/model/base-entity'; +import { Course } from 'app/entities/course.model'; +import { FaqCategory } from './faq-category.model'; + +export enum FaqState { + ACCEPTED, + REJECTED, + PROPOSED, +} + +export class Faq implements BaseEntity { + public id?: number; + public questionTitle?: string; + public questionAnswer?: string; + public faqState?: FaqState; + public course?: Course; + public categories?: FaqCategory[]; +} diff --git a/src/main/webapp/app/entities/tutorial-group/tutorial-group.model.ts b/src/main/webapp/app/entities/tutorial-group/tutorial-group.model.ts index 1fe6b2a36dab..56f835b444a0 100644 --- a/src/main/webapp/app/entities/tutorial-group/tutorial-group.model.ts +++ b/src/main/webapp/app/entities/tutorial-group/tutorial-group.model.ts @@ -26,6 +26,8 @@ export class TutorialGroup implements BaseEntity { public isUserTutor?: boolean; public numberOfRegisteredUsers?: number; public teachingAssistantName?: string; + public teachingAssistantId?: number; + public teachingAssistantImageUrl?: string; public courseTitle?: string; public nextSession?: TutorialGroupSession; public averageAttendance?: number; 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 5f2d4c8f8397..ef0a74bd28fc 100644 --- a/src/main/webapp/app/exam/manage/exam-management.service.ts +++ b/src/main/webapp/app/exam/manage/exam-management.service.ts @@ -487,7 +487,7 @@ export class ExamManagementService { } findAllLockedSubmissionsOfExam(courseId: number, examId: number) { - return this.http.get(`${this.resourceUrl}/${courseId}/exams/${examId}/lockedSubmissions`, { observe: 'response' }).pipe( + return this.http.get(`${this.resourceUrl}/${courseId}/exams/${examId}/locked-submissions`, { observe: 'response' }).pipe( filter((res) => !!res.body), tap((res) => reconnectSubmissions(res.body!)), ); 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 0c5935f3be25..2481ccc98dbd 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 @@ -23,7 +23,7 @@ export class ExerciseGroupService { * @param exerciseGroup The exercise group to create. */ create(courseId: number, examId: number, exerciseGroup: ExerciseGroup): Observable { - return this.http.post(`${this.resourceUrl}/${courseId}/exams/${examId}/exerciseGroups`, exerciseGroup, { observe: 'response' }); + return this.http.post(`${this.resourceUrl}/${courseId}/exams/${examId}/exercise-groups`, exerciseGroup, { observe: 'response' }); } /** @@ -33,7 +33,7 @@ export class ExerciseGroupService { * @param exerciseGroup The exercise group to update. */ update(courseId: number, examId: number, exerciseGroup: ExerciseGroup): Observable { - return this.http.put(`${this.resourceUrl}/${courseId}/exams/${examId}/exerciseGroups`, exerciseGroup, { observe: 'response' }); + return this.http.put(`${this.resourceUrl}/${courseId}/exams/${examId}/exercise-groups`, exerciseGroup, { observe: 'response' }); } /** @@ -43,7 +43,7 @@ export class ExerciseGroupService { * @param exerciseGroupId The id of the exercise group to get. */ find(courseId: number, examId: number, exerciseGroupId: number): Observable { - return this.http.get(`${this.resourceUrl}/${courseId}/exams/${examId}/exerciseGroups/${exerciseGroupId}`, { observe: 'response' }); + return this.http.get(`${this.resourceUrl}/${courseId}/exams/${examId}/exercise-groups/${exerciseGroupId}`, { observe: 'response' }); } /** @@ -60,7 +60,7 @@ export class ExerciseGroupService { params = params.set('deleteStudentReposBuildPlans', deleteStudentReposBuildPlans.toString()); params = params.set('deleteBaseReposBuildPlans', deleteBaseReposBuildPlans.toString()); } - return this.http.delete(`${this.resourceUrl}/${courseId}/exams/${examId}/exerciseGroups/${exerciseGroupId}`, { params, observe: 'response' }); + return this.http.delete(`${this.resourceUrl}/${courseId}/exams/${examId}/exercise-groups/${exerciseGroupId}`, { params, observe: 'response' }); } /** @@ -69,6 +69,6 @@ export class ExerciseGroupService { * @param examId The exam id. */ findAllForExam(courseId: number, examId: number): Observable { - return this.http.get(`${this.resourceUrl}/${courseId}/exams/${examId}/exerciseGroups`, { observe: 'response' }); + return this.http.get(`${this.resourceUrl}/${courseId}/exams/${examId}/exercise-groups`, { observe: 'response' }); } } 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 1b468776d570..6c6fca8ee1c4 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 @@ -40,7 +40,7 @@ export class AeolusService { */ getAeolusTemplateScript(language: ProgrammingLanguage, projectType?: ProjectType, staticAnalysis?: boolean, sequentialRuns?: boolean, coverage?: boolean): Observable { const uriWithParams = this.buildURIWithParams(language, projectType, staticAnalysis, sequentialRuns, coverage); - return this.http.get(`${this.resourceUrl}/templateScripts/` + uriWithParams.uri, { + return this.http.get(`${this.resourceUrl}/template-scripts/` + uriWithParams.uri, { responseType: 'text' as 'json', params: uriWithParams.params, }); diff --git a/src/main/webapp/app/exercises/shared/participation/participation.service.ts b/src/main/webapp/app/exercises/shared/participation/participation.service.ts index d3e5909a01ce..424d03ac8597 100644 --- a/src/main/webapp/app/exercises/shared/participation/participation.service.ts +++ b/src/main/webapp/app/exercises/shared/participation/participation.service.ts @@ -99,12 +99,12 @@ export class ParticipationService { cleanupBuildPlan(participation: StudentParticipation): Observable { const copy = this.convertParticipationDatesFromClient(participation); return this.http - .put(`${this.resourceUrl}/${participation.id}/cleanupBuildPlan`, copy, { observe: 'response' }) + .put(`${this.resourceUrl}/${participation.id}/cleanup-build-plan`, copy, { observe: 'response' }) .pipe(map((res: EntityResponseType) => this.convertParticipationResponseDatesFromServer(res))); } downloadArtifact(participationId: number): Observable { - return this.http.get(`${this.resourceUrl}/${participationId}/buildArtifact`, { observe: 'response', responseType: 'blob' }).pipe( + return this.http.get(`${this.resourceUrl}/${participationId}/build-artifact`, { observe: 'response', responseType: 'blob' }).pipe( map((res: EntityBlobResponseType) => { const fileNameCandidate = (res.headers.get('content-disposition') || '').split('filename=')[1]; const fileName = fileNameCandidate ? fileNameCandidate.replace(/"/g, '') : 'artifact'; diff --git a/src/main/webapp/app/faq/faq-update.component.html b/src/main/webapp/app/faq/faq-update.component.html new file mode 100644 index 000000000000..51211a6bb77e --- /dev/null +++ b/src/main/webapp/app/faq/faq-update.component.html @@ -0,0 +1,53 @@ +
+
+
+
+
+
+

+
+
+
+
+
+ +
+ +
+
+
+ + +
+
+ + +
+ @if (faq.course) { +
+ +
+ +
+
+ } +
+
+ + +
+
+
+
+
+
diff --git a/src/main/webapp/app/faq/faq-update.component.scss b/src/main/webapp/app/faq/faq-update.component.scss new file mode 100644 index 000000000000..c8c63e8a710c --- /dev/null +++ b/src/main/webapp/app/faq/faq-update.component.scss @@ -0,0 +1,3 @@ +.markdown-editor { + height: 350px; +} diff --git a/src/main/webapp/app/faq/faq-update.component.ts b/src/main/webapp/app/faq/faq-update.component.ts new file mode 100644 index 000000000000..17e3bd2d16d9 --- /dev/null +++ b/src/main/webapp/app/faq/faq-update.component.ts @@ -0,0 +1,157 @@ +import { Component, OnInit, inject } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { AlertService } from 'app/core/util/alert.service'; +import { onError } from 'app/shared/util/global.utils'; +import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; +import { faBan, faQuestionCircle, faSave } from '@fortawesome/free-solid-svg-icons'; +import { FormulaAction } from 'app/shared/monaco-editor/model/actions/formula.action'; +import { Faq, FaqState } from 'app/entities/faq.model'; +import { FaqService } from 'app/faq/faq.service'; +import { TranslateService } from '@ngx-translate/core'; +import { FaqCategory } from 'app/entities/faq-category.model'; +import { loadCourseFaqCategories } from 'app/faq/faq.utils'; +import { ArtemisMarkdownEditorModule } from 'app/shared/markdown-editor/markdown-editor.module'; +import { ArtemisCategorySelectorModule } from 'app/shared/category-selector/category-selector.module'; +import { ArtemisSharedModule } from 'app/shared/shared.module'; +import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; + +@Component({ + selector: 'jhi-faq-update', + templateUrl: './faq-update.component.html', + styleUrls: ['./faq-update.component.scss'], + standalone: true, + imports: [ArtemisSharedModule, ArtemisSharedComponentModule, ArtemisMarkdownEditorModule, ArtemisCategorySelectorModule], +}) +export class FaqUpdateComponent implements OnInit { + faq: Faq; + isSaving: boolean; + isAllowedToSave: boolean; + existingCategories: FaqCategory[]; + faqCategories: FaqCategory[]; + courseId: number; + domainActionsDescription = [new FormulaAction()]; + + // Icons + faQuestionCircle = faQuestionCircle; + faSave = faSave; + faBan = faBan; + + private alertService = inject(AlertService); + private faqService = inject(FaqService); + private activatedRoute = inject(ActivatedRoute); + private navigationUtilService = inject(ArtemisNavigationUtilService); + private router = inject(Router); + private translateService = inject(TranslateService); + + ngOnInit() { + this.isSaving = false; + this.courseId = Number(this.activatedRoute.snapshot.paramMap.get('courseId')); + this.activatedRoute.parent?.data.subscribe((data) => { + // Create a new faq to use unless we fetch an existing faq + const faq = data['faq']; + this.faq = faq ?? new Faq(); + const course = data['course']; + if (course) { + this.faq.course = course; + this.loadCourseFaqCategories(course.id); + } + this.faqCategories = faq?.categories ? faq.categories : []; + }); + this.validate(); + } + + /** + * Revert to the previous state, equivalent with pressing the back button on your browser + * Returns to the detail page if there is no previous state and we edited an existing faq + * Returns to the overview page if there is no previous state and we created a new faq + */ + + previousState() { + this.navigationUtilService.navigateBack(['course-management', this.courseId, 'faqs']); + } + /** + * Save the changes on a faq + * This function is called by pressing save after creating or editing a faq + */ + save() { + this.isSaving = true; + if (this.faq.id !== undefined) { + this.subscribeToSaveResponse(this.faqService.update(this.courseId, this.faq)); + } else { + this.faq.faqState = FaqState.ACCEPTED; + this.subscribeToSaveResponse(this.faqService.create(this.courseId, this.faq)); + } + } + + /** + * @param result The Http response from the server + */ + protected subscribeToSaveResponse(result: Observable>) { + result.subscribe({ + next: (response: HttpResponse) => this.onSaveSuccess(response.body!), + error: (error: HttpErrorResponse) => this.onSaveError(error), + }); + } + + /** + * Action on successful faq creation or edit + */ + protected onSaveSuccess(faq: Faq) { + if (!this.faq.id) { + this.faqService.find(this.courseId, faq.id!).subscribe({ + next: (response: HttpResponse) => { + this.isSaving = false; + const faqBody = response.body; + if (faqBody) { + this.faq = faqBody; + } + this.alertService.success(this.translateService.instant('artemisApp.faq.created', { id: faq.id })); + this.router.navigate(['course-management', this.courseId, 'faqs']); + }, + }); + } else { + this.isSaving = false; + this.alertService.success(this.translateService.instant('artemisApp.faq.updated', { id: faq.id })); + this.router.navigate(['course-management', this.courseId, 'faqs']); + } + } + + /** + * Action on unsuccessful faq creation or edit + * @param errorRes the errorRes handed to the alert service + */ + protected onSaveError(errorRes: HttpErrorResponse) { + this.isSaving = false; + if (errorRes.error?.title) { + this.alertService.addErrorAlert(errorRes.error.title, errorRes.error.message, errorRes.error.params); + } else { + onError(this.alertService, errorRes); + } + } + + updateCategories(categories: FaqCategory[]) { + this.faq.categories = categories; + this.faqCategories = categories; + } + + private loadCourseFaqCategories(courseId: number) { + loadCourseFaqCategories(courseId, this.alertService, this.faqService).subscribe((existingCategories) => { + this.existingCategories = existingCategories; + }); + } + + validate() { + if (this.faq.questionTitle && this.faq.questionAnswer) { + this.isAllowedToSave = this.faq.questionTitle?.trim().length > 0 && this.faq.questionAnswer?.trim().length > 0; + } else { + this.isAllowedToSave = false; + } + } + + handleMarkdownChange(markdown: string): void { + this.faq.questionAnswer = markdown; + this.validate(); + } +} diff --git a/src/main/webapp/app/faq/faq.component.html b/src/main/webapp/app/faq/faq.component.html new file mode 100644 index 000000000000..94bdab39fb48 --- /dev/null +++ b/src/main/webapp/app/faq/faq.component.html @@ -0,0 +1,122 @@ +
+
+
+

+ +

+
+
+
+
+ + @if (hasCategories) { +
    + @for (category of existingCategories; track category) { +
  • + +
  • + } +
+ } +
+ +
+
+
+
+ +
+ + + + + + + + + + + + @for (faq of filteredFaqs; track faq.id; let i = $index) { + + + + + + + + + } + +
+ + + + + + + + + + + +
+ {{ faq.id }} + +

+
+

+
+
+ @for (category of faq.categories; track category) { + + } +
+
+
+
+ + + + + + +
+
+
+
+
diff --git a/src/main/webapp/app/faq/faq.component.ts b/src/main/webapp/app/faq/faq.component.ts new file mode 100644 index 000000000000..3790932a47a8 --- /dev/null +++ b/src/main/webapp/app/faq/faq.component.ts @@ -0,0 +1,124 @@ +import { Component, OnDestroy, OnInit, inject } from '@angular/core'; +import { Faq } from 'app/entities/faq.model'; +import { faEdit, faFilter, faPencilAlt, faPlus, faSort, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { Subject } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { AlertService } from 'app/core/util/alert.service'; +import { ActivatedRoute } from '@angular/router'; +import { FaqService } from 'app/faq/faq.service'; +import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; +import { onError } from 'app/shared/util/global.utils'; +import { FaqCategory } from 'app/entities/faq-category.model'; +import { loadCourseFaqCategories } from 'app/faq/faq.utils'; +import { SortService } from 'app/shared/service/sort.service'; +import { CustomExerciseCategoryBadgeComponent } from 'app/shared/exercise-categories/custom-exercise-category-badge/custom-exercise-category-badge.component'; +import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; +import { ArtemisSharedModule } from 'app/shared/shared.module'; +import { ArtemisMarkdownModule } from 'app/shared/markdown.module'; + +@Component({ + selector: 'jhi-faq', + templateUrl: './faq.component.html', + styleUrls: [], + standalone: true, + imports: [ArtemisSharedModule, CustomExerciseCategoryBadgeComponent, ArtemisSharedComponentModule, ArtemisMarkdownModule], +}) +export class FaqComponent implements OnInit, OnDestroy { + faqs: Faq[]; + filteredFaqs: Faq[]; + existingCategories: FaqCategory[]; + courseId: number; + hasCategories: boolean = false; + + private dialogErrorSource = new Subject(); + dialogError$ = this.dialogErrorSource.asObservable(); + + activeFilters = new Set(); + predicate: string; + ascending: boolean; + + // Icons + faEdit = faEdit; + faPlus = faPlus; + faTrash = faTrash; + faPencilAlt = faPencilAlt; + faFilter = faFilter; + faSort = faSort; + + private faqService = inject(FaqService); + private route = inject(ActivatedRoute); + private alertService = inject(AlertService); + private sortService = inject(SortService); + + constructor() { + this.predicate = 'id'; + this.ascending = true; + } + + ngOnInit() { + this.courseId = Number(this.route.snapshot.paramMap.get('courseId')); + this.loadAll(); + this.loadCourseFaqCategories(this.courseId); + } + + ngOnDestroy(): void { + this.dialogErrorSource.complete(); + } + + deleteFaq(courseId: number, faqId: number) { + this.faqService.delete(courseId, faqId).subscribe({ + next: () => this.handleDeleteSuccess(faqId), + error: (error: HttpErrorResponse) => this.dialogErrorSource.next(error.message), + }); + } + + private handleDeleteSuccess(faqId: number) { + this.faqs = this.faqs.filter((faq) => faq.id !== faqId); + this.dialogErrorSource.next(''); + this.loadCourseFaqCategories(this.courseId); + } + + toggleFilters(category: string) { + this.activeFilters = this.faqService.toggleFilter(category, this.activeFilters); + this.applyFilters(); + } + + private applyFilters(): void { + this.filteredFaqs = this.faqService.applyFilters(this.activeFilters, this.faqs); + } + + sortRows() { + this.sortService.sortByProperty(this.filteredFaqs, this.predicate, this.ascending); + } + + private loadAll() { + this.faqService + .findAllByCourseId(this.courseId) + .pipe(map((res: HttpResponse) => res.body)) + .subscribe({ + next: (res: Faq[]) => { + this.faqs = res; + this.applyFilters(); + this.sortRows(); + }, + error: (res: HttpErrorResponse) => onError(this.alertService, res), + }); + } + + private loadCourseFaqCategories(courseId: number) { + loadCourseFaqCategories(courseId, this.alertService, this.faqService).subscribe((existingCategories) => { + this.existingCategories = existingCategories; + this.hasCategories = existingCategories.length > 0; + this.checkAppliedFilter(this.activeFilters, this.existingCategories); + }); + } + + private checkAppliedFilter(activeFilters: Set, existingCategories: FaqCategory[]) { + activeFilters.forEach((activeFilter) => { + if (!existingCategories.some((category) => category.category === activeFilter)) { + activeFilters.delete(activeFilter); + } + }); + this.applyFilters(); + } +} diff --git a/src/main/webapp/app/faq/faq.routes.ts b/src/main/webapp/app/faq/faq.routes.ts new file mode 100644 index 000000000000..0b756a8c28ff --- /dev/null +++ b/src/main/webapp/app/faq/faq.routes.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@angular/core'; +import { HttpResponse } from '@angular/common/http'; +import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; +import { Observable, of } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; +import { FaqService } from 'app/faq/faq.service'; +import { Faq } from 'app/entities/faq.model'; + +@Injectable({ providedIn: 'root' }) +export class FaqResolve implements Resolve { + constructor(private faqService: FaqService) {} + + resolve(route: ActivatedRouteSnapshot): Observable { + const faqId = route.params['faqId']; + const courseId = route.params['courseId']; + if (faqId) { + return this.faqService.find(courseId, faqId).pipe( + filter((response: HttpResponse) => response.ok), + map((faq: HttpResponse) => faq.body!), + ); + } + return of(new Faq()); + } +} diff --git a/src/main/webapp/app/faq/faq.service.ts b/src/main/webapp/app/faq/faq.service.ts new file mode 100644 index 000000000000..d0c80cf72e94 --- /dev/null +++ b/src/main/webapp/app/faq/faq.service.ts @@ -0,0 +1,140 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { Faq, FaqState } from 'app/entities/faq.model'; +import { FaqCategory } from 'app/entities/faq-category.model'; + +type EntityResponseType = HttpResponse; +type EntityArrayResponseType = HttpResponse; + +@Injectable({ providedIn: 'root' }) +export class FaqService { + public resourceUrl = 'api/courses'; + + constructor(protected http: HttpClient) {} + + create(courseId: number, faq: Faq): Observable { + const copy = FaqService.convertFaqFromClient(faq); + copy.faqState = FaqState.ACCEPTED; + return this.http.post(`${this.resourceUrl}/${courseId}/faqs`, copy, { observe: 'response' }).pipe( + map((res: EntityResponseType) => { + return res; + }), + ); + } + + update(courseId: number, faq: Faq): Observable { + const copy = FaqService.convertFaqFromClient(faq); + return this.http.put(`${this.resourceUrl}/${courseId}/faqs/${faq.id}`, copy, { observe: 'response' }).pipe( + map((res: EntityResponseType) => { + return res; + }), + ); + } + + find(courseId: number, faqId: number): Observable { + return this.http + .get(`${this.resourceUrl}/${courseId}/faqs/${faqId}`, { observe: 'response' }) + .pipe(map((res: EntityResponseType) => FaqService.convertFaqCategoriesFromServer(res))); + } + + findAllByCourseId(courseId: number): Observable { + return this.http + .get(`${this.resourceUrl}/${courseId}/faqs`, { + observe: 'response', + }) + .pipe(map((res: EntityArrayResponseType) => FaqService.convertFaqCategoryArrayFromServer(res))); + } + + delete(courseId: number, faqId: number): Observable> { + return this.http.delete(`${this.resourceUrl}/${courseId}/faqs/${faqId}`, { observe: 'response' }); + } + + findAllCategoriesByCourseId(courseId: number) { + return this.http.get(`${this.resourceUrl}/${courseId}/faq-categories`, { + observe: 'response', + }); + } + /** + * Converts the faq category json string into FaqCategory objects (if it exists). + * @param res the response + */ + static convertFaqCategoriesFromServer(res: ERT): ERT { + if (res.body?.categories) { + FaqService.parseFaqCategories(res.body); + } + return res; + } + + /** + * Converts a faqs categories into a json string (to send them to the server). Does nothing if no categories exist + * @param faq the faq + */ + static stringifyFaqCategories(faq: Faq) { + return faq.categories?.map((category) => JSON.stringify(category) as unknown as FaqCategory); + } + + convertFaqCategoriesAsStringFromServer(categories: string[]): FaqCategory[] { + return categories.map((category) => JSON.parse(category)); + } + + /** + * Converts the faq category json strings into FaqCategory objects (if it exists). + * @param res the response + */ + static convertFaqCategoryArrayFromServer(res: EART): EART { + if (res.body) { + res.body.forEach((faq: E) => FaqService.parseFaqCategories(faq)); + } + return res; + } + + /** + * Parses the faq categories JSON string into {@link FaqCategory} objects. + * @param faq - the faq + */ + static parseFaqCategories(faq?: Faq) { + if (faq?.categories) { + faq.categories = faq.categories.map((category) => { + const categoryObj = JSON.parse(category as unknown as string); + return new FaqCategory(categoryObj.category, categoryObj.color); + }); + } + } + + /** + * Prepare client-faq to be uploaded to the server + * @param { Faq } faq - faq that will be modified + */ + static convertFaqFromClient(faq: F): Faq { + const copy = Object.assign({}, faq); + copy.categories = FaqService.stringifyFaqCategories(copy); + return copy; + } + + toggleFilter(category: string, activeFilters: Set) { + if (activeFilters.has(category)) { + activeFilters.delete(category); + } else { + activeFilters.add(category); + } + return activeFilters; + } + + applyFilters(activeFilters: Set, faqs: Faq[]): Faq[] { + if (activeFilters.size === 0) { + // If no filters selected, show all faqs + return faqs; + } else { + return faqs.filter((faq) => this.hasFilteredCategory(faq, activeFilters)); + } + } + + hasFilteredCategory(faq: Faq, filteredCategory: Set) { + const categories = faq.categories?.map((category) => category.category); + if (categories) { + return categories.some((category) => filteredCategory.has(category!)); + } + } +} diff --git a/src/main/webapp/app/faq/faq.utils.ts b/src/main/webapp/app/faq/faq.utils.ts new file mode 100644 index 000000000000..f96bffdbb575 --- /dev/null +++ b/src/main/webapp/app/faq/faq.utils.ts @@ -0,0 +1,23 @@ +import { onError } from 'app/shared/util/global.utils'; +import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; +import { AlertService } from 'app/core/util/alert.service'; +import { Observable, catchError, map, of } from 'rxjs'; +import { FaqService } from 'app/faq/faq.service'; +import { FaqCategory } from 'app/entities/faq-category.model'; + +export function loadCourseFaqCategories(courseId: number | undefined, alertService: AlertService, faqService: FaqService): Observable { + if (courseId === undefined) { + return of([]); + } + + return faqService.findAllCategoriesByCourseId(courseId).pipe( + map((categoryRes: HttpResponse) => { + const existingCategories = faqService.convertFaqCategoriesAsStringFromServer(categoryRes.body || []); + return existingCategories; + }), + catchError((error: HttpErrorResponse) => { + onError(alertService, error); + return of([]); + }), + ); +} diff --git a/src/main/webapp/app/guided-tour/tours/course-overview-tour.ts b/src/main/webapp/app/guided-tour/tours/course-overview-tour.ts index a76c25357da2..5e5a82fe2fd5 100644 --- a/src/main/webapp/app/guided-tour/tours/course-overview-tour.ts +++ b/src/main/webapp/app/guided-tour/tours/course-overview-tour.ts @@ -60,7 +60,7 @@ export const courseOverviewTour: GuidedTour = { orientation: Orientation.RIGHT, }), new TextTourStep({ - highlightSelector: '.guided-tour .card-footer', + highlightSelector: '.guided-tour .exercise-guided-tour', headlineTranslateKey: 'tour.courseOverview.courseFooter.headline', contentTranslateKey: 'tour.courseOverview.courseFooter.content', orientation: Orientation.TOPLEFT, diff --git a/src/main/webapp/app/overview/course-card.component.html b/src/main/webapp/app/overview/course-card.component.html index 0ab968d60075..4b69401c3d85 100644 --- a/src/main/webapp/app/overview/course-card.component.html +++ b/src/main/webapp/app/overview/course-card.component.html @@ -1,102 +1,97 @@ -
-
- -
-
-
- @if (course.courseIcon) { - - } +
+
+
+ @if (course.courseIcon) { +
+
-
-
- {{ course.title }} -
-
-
-
- @if (exerciseCount === 0) { - Exercises: {{ exerciseCount }} - } - @if (exerciseCount > 0) { - Exercises: {{ exerciseCount }} - } - @if (lectureCount === 0) { - Lectures: {{ lectureCount }} - } - @if (lectureCount > 0) { - Lectures: {{ lectureCount }} - } - @if (examCount === 0) { - Exams: {{ examCount }} - } - @if (examCount > 0) { - Exams: {{ examCount }} - } -
+ } @else { +
+ {{ course.title | slice: 0 : 1 }}
+ } +
+
+ {{ course.title }} +
+
+
+
-
+
- @if (exerciseCount > 0 && (totalReachableScore > 0 || totalAbsoluteScore > 0)) { -
-
-

{{ totalRelativeScore }}%

-
{{ totalAbsoluteScore }} / {{ totalReachableScore }} Pts
-
- - - - : {{ model.value }} - - -
- } @else { -
- } -
- @if (nextRelevantExercise) { -