diff --git a/angular.json b/angular.json index c3b5a667717..117431c2345 100644 --- a/angular.json +++ b/angular.json @@ -97,7 +97,7 @@ "baseHref": "/" }, "development": { - "optimization": false, + "optimization": true, "outputHashing": "all", "sourceMap": true, "namedChunks": true, diff --git a/package-lock.json b/package-lock.json index 5ae3709da45..fa4053d11a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -127,42 +127,58 @@ "url-loader": "^4.1.1" } }, + "node_modules/@algolia/abtesting": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.1.0.tgz", + "integrity": "sha512-sEyWjw28a/9iluA37KLGu8vjxEIlb60uxznfTUmXImy7H5NvbpSO6yYgmgH5KiD7j+zTUUihiST0jEP12IoXow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/@algolia/client-abtesting": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.32.0.tgz", - "integrity": "sha512-HG/6Eib6DnJYm/B2ijWFXr4txca/YOuA4K7AsEU0JBrOZSB+RU7oeDyNBPi3c0v0UDDqlkBqM3vBU/auwZlglA==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.35.0.tgz", + "integrity": "sha512-uUdHxbfHdoppDVflCHMxRlj49/IllPwwQ2cQ8DLC4LXr3kY96AHBpW0dMyi6ygkn2MtFCc6BxXCzr668ZRhLBQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.32.0", - "@algolia/requester-browser-xhr": "5.32.0", - "@algolia/requester-fetch": "5.32.0", - "@algolia/requester-node-http": "5.32.0" + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-analytics": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.32.0.tgz", - "integrity": "sha512-8Y9MLU72WFQOW3HArYv16+Wvm6eGmsqbxxM1qxtm0hvSASJbxCm+zQAZe5stqysTlcWo4BJ82KEH1PfgHbJAmQ==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.35.0.tgz", + "integrity": "sha512-SunAgwa9CamLcRCPnPHx1V2uxdQwJGqb1crYrRWktWUdld0+B2KyakNEeVn5lln4VyeNtW17Ia7V7qBWyM/Skw==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.32.0", - "@algolia/requester-browser-xhr": "5.32.0", - "@algolia/requester-fetch": "5.32.0", - "@algolia/requester-node-http": "5.32.0" + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-common": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.32.0.tgz", - "integrity": "sha512-w8L+rgyXMCPBKmEdOT+RfgMrF0mT6HK60vPYWLz8DBs/P7yFdGo7urn99XCJvVLMSKXrIbZ2FMZ/i50nZTXnuQ==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.35.0.tgz", + "integrity": "sha512-ipE0IuvHu/bg7TjT2s+187kz/E3h5ssfTtjpg1LbWMgxlgiaZIgTTbyynM7NfpSJSKsgQvCQxWjGUO51WSCu7w==", "dev": true, "license": "MIT", "engines": { @@ -170,151 +186,151 @@ } }, "node_modules/@algolia/client-insights": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.32.0.tgz", - "integrity": "sha512-AdWfynhUeX7jz/LTiFU3wwzJembTbdLkQIOLs4n7PyBuxZ3jz4azV1CWbIP8AjUOFmul6uXbmYza+KqyS5CzOA==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.35.0.tgz", + "integrity": "sha512-UNbCXcBpqtzUucxExwTSfAe8gknAJ485NfPN6o1ziHm6nnxx97piIbcBQ3edw823Tej2Wxu1C0xBY06KgeZ7gA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.32.0", - "@algolia/requester-browser-xhr": "5.32.0", - "@algolia/requester-fetch": "5.32.0", - "@algolia/requester-node-http": "5.32.0" + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.32.0.tgz", - "integrity": "sha512-bTupJY4xzGZYI4cEQcPlSjjIEzMvv80h7zXGrXY1Y0KC/n/SLiMv84v7Uy+B6AG1Kiy9FQm2ADChBLo1uEhGtQ==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.35.0.tgz", + "integrity": "sha512-/KWjttZ6UCStt4QnWoDAJ12cKlQ+fkpMtyPmBgSS2WThJQdSV/4UWcqCUqGH7YLbwlj3JjNirCu3Y7uRTClxvA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.32.0", - "@algolia/requester-browser-xhr": "5.32.0", - "@algolia/requester-fetch": "5.32.0", - "@algolia/requester-node-http": "5.32.0" + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-query-suggestions": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.32.0.tgz", - "integrity": "sha512-if+YTJw1G3nDKL2omSBjQltCHUQzbaHADkcPQrGFnIGhVyHU3Dzq4g46uEv8mrL5sxL8FjiS9LvekeUlL2NRqw==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.35.0.tgz", + "integrity": "sha512-8oCuJCFf/71IYyvQQC+iu4kgViTODbXDk3m7yMctEncRSRV+u2RtDVlpGGfPlJQOrAY7OONwJlSHkmbbm2Kp/w==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.32.0", - "@algolia/requester-browser-xhr": "5.32.0", - "@algolia/requester-fetch": "5.32.0", - "@algolia/requester-node-http": "5.32.0" + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.32.0.tgz", - "integrity": "sha512-kmK5nVkKb4DSUgwbveMKe4X3xHdMsPsOVJeEzBvFJ+oS7CkBPmpfHAEq+CcmiPJs20YMv6yVtUT9yPWL5WgAhg==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.35.0.tgz", + "integrity": "sha512-FfmdHTrXhIduWyyuko1YTcGLuicVbhUyRjO3HbXE4aP655yKZgdTIfMhZ/V5VY9bHuxv/fGEh3Od1Lvv2ODNTg==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.32.0", - "@algolia/requester-browser-xhr": "5.32.0", - "@algolia/requester-fetch": "5.32.0", - "@algolia/requester-node-http": "5.32.0" + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/ingestion": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.32.0.tgz", - "integrity": "sha512-PZTqjJbx+fmPuT2ud1n4vYDSF1yrT//vOGI9HNYKNA0PM0xGUBWigf5gRivHsXa3oBnUlTyHV9j7Kqx5BHbVHQ==", + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.35.0.tgz", + "integrity": "sha512-gPzACem9IL1Co8mM1LKMhzn1aSJmp+Vp434An4C0OBY4uEJRcqsLN3uLBlY+bYvFg8C8ImwM9YRiKczJXRk0XA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.32.0", - "@algolia/requester-browser-xhr": "5.32.0", - "@algolia/requester-fetch": "5.32.0", - "@algolia/requester-node-http": "5.32.0" + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/monitoring": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.32.0.tgz", - "integrity": "sha512-kYYoOGjvNQAmHDS1v5sBj+0uEL9RzYqH/TAdq8wmcV+/22weKt/fjh+6LfiqkS1SCZFYYrwGnirrUhUM36lBIQ==", + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.35.0.tgz", + "integrity": "sha512-w9MGFLB6ashI8BGcQoVt7iLgDIJNCn4OIu0Q0giE3M2ItNrssvb8C0xuwJQyTy1OFZnemG0EB1OvXhIHOvQwWw==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.32.0", - "@algolia/requester-browser-xhr": "5.32.0", - "@algolia/requester-fetch": "5.32.0", - "@algolia/requester-node-http": "5.32.0" + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/recommend": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.32.0.tgz", - "integrity": "sha512-jyIBLdskjPAL7T1g57UMfUNx+PzvYbxKslwRUKBrBA6sNEsYCFdxJAtZSLUMmw6MC98RDt4ksmEl5zVMT5bsuw==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.35.0.tgz", + "integrity": "sha512-AhrVgaaXAb8Ue0u2nuRWwugt0dL5UmRgS9LXe0Hhz493a8KFeZVUE56RGIV3hAa6tHzmAV7eIoqcWTQvxzlJeQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.32.0", - "@algolia/requester-browser-xhr": "5.32.0", - "@algolia/requester-fetch": "5.32.0", - "@algolia/requester-node-http": "5.32.0" + "@algolia/client-common": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.32.0.tgz", - "integrity": "sha512-eDp14z92Gt6JlFgiexImcWWH+Lk07s/FtxcoDaGrE4UVBgpwqOO6AfQM6dXh1pvHxlDFbMJihHc/vj3gBhPjqQ==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.35.0.tgz", + "integrity": "sha512-diY415KLJZ6x1Kbwl9u96Jsz0OstE3asjXtJ9pmk1d+5gPuQ5jQyEsgC+WmEXzlec3iuVszm8AzNYYaqw6B+Zw==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.32.0" + "@algolia/client-common": "5.35.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-fetch": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.32.0.tgz", - "integrity": "sha512-rnWVglh/K75hnaLbwSc2t7gCkbq1ldbPgeIKDUiEJxZ4mlguFgcltWjzpDQ/t1LQgxk9HdIFcQfM17Hid3aQ6Q==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.35.0.tgz", + "integrity": "sha512-uydqnSmpAjrgo8bqhE9N1wgcB98psTRRQXcjc4izwMB7yRl9C8uuAQ/5YqRj04U0mMQ+fdu2fcNF6m9+Z1BzDQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.32.0" + "@algolia/client-common": "5.35.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.32.0.tgz", - "integrity": "sha512-LbzQ04+VLkzXY4LuOzgyjqEv/46Gwrk55PldaglMJ4i4eDXSRXGKkwJpXFwsoU+c1HMQlHIyjJBhrfsfdyRmyQ==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.35.0.tgz", + "integrity": "sha512-RgLX78ojYOrThJHrIiPzT4HW3yfQa0D7K+MQ81rhxqaNyNBu4F1r+72LNHYH/Z+y9I1Mrjrd/c/Ue5zfDgAEjQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.32.0" + "@algolia/client-common": "5.35.0" }, "engines": { "node": ">= 14.0.0" @@ -348,13 +364,13 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.2001.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2001.6.tgz", - "integrity": "sha512-CGFDfqPvKw1Ekuk7eSYMdhBv26LiwBrnZEUnrloC8fnuT8G+s46WMj/uH3tTcQ9MHYbhOSAHynNwpnwX71wghg==", + "version": "0.2002.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2002.0.tgz", + "integrity": "sha512-PaBXFP1kdUuNtMie0lWnitlYbq8o1gz/s0YIa8oY1X3swOJ7bP6kBfxTb9opV5uXAOkXg2zCdnZ4Eu1aVkgPGw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "20.1.6", + "@angular-devkit/core": "20.2.0", "rxjs": "7.8.2" }, "engines": { @@ -364,54 +380,54 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "20.1.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-20.1.6.tgz", - "integrity": "sha512-T9sAN6rj1eDrWTDrX2Tb5FS07vkxIqbp0L3ON8DsbOo68+I4whBSBrCyacqanuL8O6HUkPrlLc2Hl0CFdV6tIg==", + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-20.2.0.tgz", + "integrity": "sha512-B3dlR9AnANyT8yfESODFYEDEGV6pMwozsfjsH0NFxrdrfB1BYTBKpgYkQWg2I1j48hf7YmetZgA1sa3gYOt1QQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2001.6", - "@angular-devkit/build-webpack": "0.2001.6", - "@angular-devkit/core": "20.1.6", - "@angular/build": "20.1.6", - "@babel/core": "7.27.7", - "@babel/generator": "7.27.5", + "@angular-devkit/architect": "0.2002.0", + "@angular-devkit/build-webpack": "0.2002.0", + "@angular-devkit/core": "20.2.0", + "@angular/build": "20.2.0", + "@babel/core": "7.28.3", + "@babel/generator": "7.28.3", "@babel/helper-annotate-as-pure": "7.27.3", "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-transform-async-generator-functions": "7.27.1", + "@babel/plugin-transform-async-generator-functions": "7.28.0", "@babel/plugin-transform-async-to-generator": "7.27.1", - "@babel/plugin-transform-runtime": "7.27.4", - "@babel/preset-env": "7.27.2", - "@babel/runtime": "7.27.6", + "@babel/plugin-transform-runtime": "7.28.3", + "@babel/preset-env": "7.28.3", + "@babel/runtime": "7.28.3", "@discoveryjs/json-ext": "0.6.3", - "@ngtools/webpack": "20.1.6", + "@ngtools/webpack": "20.2.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.21", "babel-loader": "10.0.0", "browserslist": "^4.21.5", - "copy-webpack-plugin": "13.0.0", + "copy-webpack-plugin": "13.0.1", "css-loader": "7.1.2", - "esbuild-wasm": "0.25.5", + "esbuild-wasm": "0.25.9", "fast-glob": "3.3.3", "http-proxy-middleware": "3.0.5", "istanbul-lib-instrument": "6.0.3", "jsonc-parser": "3.3.1", "karma-source-map-support": "1.4.0", - "less": "4.3.0", + "less": "4.4.0", "less-loader": "12.3.0", "license-webpack-plugin": "4.0.2", "loader-utils": "3.3.1", - "mini-css-extract-plugin": "2.9.2", - "open": "10.1.2", + "mini-css-extract-plugin": "2.9.4", + "open": "10.2.0", "ora": "8.2.0", - "picomatch": "4.0.2", - "piscina": "5.1.2", + "picomatch": "4.0.3", + "piscina": "5.1.3", "postcss": "8.5.6", "postcss-loader": "8.1.1", "resolve-url-loader": "5.0.0", "rxjs": "7.8.2", - "sass": "1.89.2", + "sass": "1.90.0", "sass-loader": "16.0.5", "semver": "7.7.2", "source-map-loader": "5.0.0", @@ -419,7 +435,7 @@ "terser": "5.43.1", "tree-kill": "1.2.2", "tslib": "2.8.1", - "webpack": "5.99.9", + "webpack": "5.101.2", "webpack-dev-middleware": "7.4.2", "webpack-dev-server": "5.2.2", "webpack-merge": "6.0.1", @@ -431,7 +447,7 @@ "yarn": ">= 1.13.0" }, "optionalDependencies": { - "esbuild": "0.25.5" + "esbuild": "0.25.9" }, "peerDependencies": { "@angular/compiler-cli": "^20.0.0", @@ -440,7 +456,7 @@ "@angular/platform-browser": "^20.0.0", "@angular/platform-server": "^20.0.0", "@angular/service-worker": "^20.0.0", - "@angular/ssr": "^20.1.6", + "@angular/ssr": "^20.2.0", "@web/test-runner": "^0.20.0", "browser-sync": "^3.0.2", "jest": "^29.5.0", @@ -449,7 +465,7 @@ "ng-packagr": "^20.0.0", "protractor": "^7.0.0", "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", - "typescript": ">=5.8 <5.9" + "typescript": ">=5.8 <6.0" }, "peerDependenciesMeta": { "@angular/core": { @@ -496,141 +512,6 @@ } } }, - "node_modules/@angular-devkit/build-angular/node_modules/@babel/core": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.7.tgz", - "integrity": "sha512-BU2f9tlKQ5CAthiMIgpzAh4eDTLWo1mqi9jqE2OxMG0E/OM199VJt2q8BztTxpnSW0i1ymdwLXRJnYzvDM5r2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.27.7", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.27.7", - "@babel/types": "^7.27.7", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@babel/preset-env": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.27.2.tgz", - "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.27.1", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.27.1", - "@babel/plugin-syntax-import-attributes": "^7.27.1", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.27.1", - "@babel/plugin-transform-async-to-generator": "^7.27.1", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.27.1", - "@babel/plugin-transform-class-properties": "^7.27.1", - "@babel/plugin-transform-class-static-block": "^7.27.1", - "@babel/plugin-transform-classes": "^7.27.1", - "@babel/plugin-transform-computed-properties": "^7.27.1", - "@babel/plugin-transform-destructuring": "^7.27.1", - "@babel/plugin-transform-dotall-regex": "^7.27.1", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-exponentiation-operator": "^7.27.1", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.27.1", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.27.1", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@babel/plugin-transform-modules-systemjs": "^7.27.1", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", - "@babel/plugin-transform-numeric-separator": "^7.27.1", - "@babel/plugin-transform-object-rest-spread": "^7.27.2", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1", - "@babel/plugin-transform-parameters": "^7.27.1", - "@babel/plugin-transform-private-methods": "^7.27.1", - "@babel/plugin-transform-private-property-in-object": "^7.27.1", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.27.1", - "@babel/plugin-transform-regexp-modifiers": "^7.27.1", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.27.1", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.27.1", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.11.0", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.40.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@angular-devkit/build-angular/node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -644,6 +525,19 @@ "node": ">=0.4.0" } }, + "node_modules/@angular-devkit/build-angular/node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, "node_modules/@angular-devkit/build-angular/node_modules/ajv-formats": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", @@ -717,13 +611,6 @@ "webpack": ">=5.61.0" } }, - "node_modules/@angular-devkit/build-angular/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, "node_modules/@angular-devkit/build-angular/node_modules/enhanced-resolve": { "version": "5.18.3", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", @@ -847,27 +734,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@angular-devkit/build-angular/node_modules/sass": { - "version": "1.89.2", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.89.2.tgz", - "integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" - } - }, "node_modules/@angular-devkit/build-angular/node_modules/schema-utils": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", @@ -889,22 +755,23 @@ } }, "node_modules/@angular-devkit/build-angular/node_modules/webpack": { - "version": "5.99.9", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz", - "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==", + "version": "5.101.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.2.tgz", + "integrity": "sha512-4JLXU0tD6OZNVqlwzm3HGEhAHufSiyv+skb7q0d2367VDMzrU1Q/ZeepvkcHH0rZie6uqEtTQQe0OEOOluH3Mg==", "dev": true, "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", + "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.14.0", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", + "enhanced-resolve": "^5.17.3", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -918,7 +785,7 @@ "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" + "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" @@ -937,13 +804,13 @@ } }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.2001.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.2001.6.tgz", - "integrity": "sha512-rOzDLQYWuSoZ9FpavHR9ld+D+C1JJfOystVLufvzhLVlwZn4IYclWJe7BT0wGME92fXrwz4ubjZrZW+fgB3LXg==", + "version": "0.2002.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.2002.0.tgz", + "integrity": "sha512-sON0IFOaZW5/bLXlMuKXOV5viaa7SAGHhdM4PXM6Fa0PPqPI6zZp2iqYpwETKpN8DfnLNxefdysvCn9DbHuNhQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.2001.6", + "@angular-devkit/architect": "0.2002.0", "rxjs": "7.8.2" }, "engines": { @@ -957,18 +824,18 @@ } }, "node_modules/@angular-devkit/core": { - "version": "20.1.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.1.6.tgz", - "integrity": "sha512-Wooe+nTmHOLvveBQWDmSsdKg39re5BUMGVkwKlPHTQ/YU9aYshvPEBu1K0l4gSqe3qtqVVAx0HlPb53bEFFa8w==", + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.2.0.tgz", + "integrity": "sha512-3CM6Zsr09Kf92ItFkxijlnC4+ZOgkxdCk0vFYvuw9UuvTDNwyIqJi6693PRPRbcXgpdY2vs6u99elSvQVmoEEw==", "dev": true, "license": "MIT", "dependencies": { "ajv": "8.17.1", "ajv-formats": "3.0.1", "jsonc-parser": "3.3.1", - "picomatch": "4.0.2", + "picomatch": "4.0.3", "rxjs": "7.8.2", - "source-map": "0.7.4" + "source-map": "0.7.6" }, "engines": { "node": "^20.19.0 || ^22.12.0 || >=24.0.0", @@ -985,13 +852,13 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "20.1.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-20.1.6.tgz", - "integrity": "sha512-Maj/yCkn3Qjum2kCYUOYMw8VYh/8725XN8/4cae9VllMwkN5D8jYDvX40qmfgQve2x0x6r3L8rmaIHn8227cHg==", + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-20.2.0.tgz", + "integrity": "sha512-TCPIN6Bd04oGuNocETmsd9hzGYrjrivisbMKb0WOuDi3OnCkmWqsPR+QA2kYwTOGqG3HXkz/z3CA0g04M2fgrQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "20.1.6", + "@angular-devkit/core": "20.2.0", "jsonc-parser": "3.3.1", "magic-string": "0.30.17", "ora": "8.2.0", @@ -1004,9 +871,9 @@ } }, "node_modules/@angular/animations": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-20.1.7.tgz", - "integrity": "sha512-ykzx6cKqGkKbtE2CbHBukIgM2Wk8+BmYTEqwRZRVqskxbIGvEuLmLJrvmwpqqvo4MypgvbLEtJyviSCYQkZYvA==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-20.2.1.tgz", + "integrity": "sha512-g4yLXwXCF7OAahx1xI4FXRwG4dIXfBqHsvlpx2TappaMRpiPp7PfP2cW6l3ox+KRpTWhSvcRqbJyIOWad0f7Rw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1015,42 +882,42 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.1.7", - "@angular/core": "20.1.7" + "@angular/common": "20.2.1", + "@angular/core": "20.2.1" } }, "node_modules/@angular/build": { - "version": "20.1.6", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-20.1.6.tgz", - "integrity": "sha512-xAC9uGeRmvCKNLr7D0XUK+KWixlRl9nnfZbB9MIDe00ulmHy5duVWILUwBEOeq1/wRrrJc133NAPTTEBWImwnA==", + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-20.2.0.tgz", + "integrity": "sha512-/Yhqhg01UvX0E+tx4WAeK3AnwpZLqcw+XKTmsPsH5rbqpLKNRR9XsC3PJ4qBFU1u9/Lh13mmmr1+pG2p8ixMug==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2001.6", - "@babel/core": "7.27.7", + "@angular-devkit/architect": "0.2002.0", + "@babel/core": "7.28.3", "@babel/helper-annotate-as-pure": "7.27.3", "@babel/helper-split-export-declaration": "7.24.7", - "@inquirer/confirm": "5.1.13", + "@inquirer/confirm": "5.1.14", "@vitejs/plugin-basic-ssl": "2.1.0", - "beasties": "0.3.4", + "beasties": "0.3.5", "browserslist": "^4.23.0", - "esbuild": "0.25.5", + "esbuild": "0.25.9", "https-proxy-agent": "7.0.6", "istanbul-lib-instrument": "6.0.3", "jsonc-parser": "3.3.1", - "listr2": "8.3.3", + "listr2": "9.0.1", "magic-string": "0.30.17", "mrmime": "2.0.1", - "parse5-html-rewriting-stream": "7.1.0", - "picomatch": "4.0.2", - "piscina": "5.1.2", - "rollup": "4.44.1", - "sass": "1.89.2", + "parse5-html-rewriting-stream": "8.0.0", + "picomatch": "4.0.3", + "piscina": "5.1.3", + "rolldown": "1.0.0-beta.32", + "sass": "1.90.0", "semver": "7.7.2", "source-map-support": "0.5.21", "tinyglobby": "0.2.14", - "vite": "7.0.6", + "vite": "7.1.2", "watchpack": "2.4.4" }, "engines": { @@ -1059,7 +926,7 @@ "yarn": ">= 1.13.0" }, "optionalDependencies": { - "lmdb": "3.4.1" + "lmdb": "3.4.2" }, "peerDependencies": { "@angular/compiler": "^20.0.0", @@ -1069,14 +936,14 @@ "@angular/platform-browser": "^20.0.0", "@angular/platform-server": "^20.0.0", "@angular/service-worker": "^20.0.0", - "@angular/ssr": "^20.1.6", + "@angular/ssr": "^20.2.0", "karma": "^6.4.0", "less": "^4.2.0", "ng-packagr": "^20.0.0", "postcss": "^8.4.0", "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", "tslib": "^2.3.0", - "typescript": ">=5.8 <5.9", + "typescript": ">=5.8 <6.0", "vitest": "^3.1.1" }, "peerDependenciesMeta": { @@ -1118,79 +985,10 @@ } } }, - "node_modules/@angular/build/node_modules/@babel/core": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.7.tgz", - "integrity": "sha512-BU2f9tlKQ5CAthiMIgpzAh4eDTLWo1mqi9jqE2OxMG0E/OM199VJt2q8BztTxpnSW0i1ymdwLXRJnYzvDM5r2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.27.7", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.27.7", - "@babel/types": "^7.27.7", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@angular/build/node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@angular/build/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular/build/node_modules/sass": { - "version": "1.89.2", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.89.2.tgz", - "integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" - } - }, "node_modules/@angular/cdk": { - "version": "20.1.6", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.1.6.tgz", - "integrity": "sha512-GKxCS/GOAOQCNTnrvYia9wR4Z9rRWjzNRE0989LXwWLYcmiG7+ku30PolGV7zhmlgUu/qx8P6BbxZgUvK34X/A==", + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.2.0.tgz", + "integrity": "sha512-BZkhRMr3nEOHHCzEgKZM537G4aq0VAwoejhYn7oIvY0UU+arHKz+U7Gc44KH5GaAgVLojtJtkFXsArifzYUwzw==", "license": "MIT", "dependencies": { "parse5": "^8.0.0", @@ -1203,31 +1001,30 @@ } }, "node_modules/@angular/cli": { - "version": "20.1.6", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-20.1.6.tgz", - "integrity": "sha512-kqncVmYtlDYLwt4l5lFBz4uEnoheMH+teSqAAD/zaDxn41KvpoRLHiEVurQhsNP/GDHxGu+8wg0s4gX3kaFOzg==", + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-20.2.0.tgz", + "integrity": "sha512-p62hkuQOxf5kJsVq6AT7B1MHYo1uPGoZV4lf47qOrLjl0WANwfxEgLvyuVgL47ylnINbPnITeeUdoadVn4t1sw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.2001.6", - "@angular-devkit/core": "20.1.6", - "@angular-devkit/schematics": "20.1.6", - "@inquirer/prompts": "7.6.0", - "@listr2/prompt-adapter-inquirer": "2.0.22", - "@modelcontextprotocol/sdk": "1.13.3", - "@schematics/angular": "20.1.6", + "@angular-devkit/architect": "0.2002.0", + "@angular-devkit/core": "20.2.0", + "@angular-devkit/schematics": "20.2.0", + "@inquirer/prompts": "7.8.2", + "@listr2/prompt-adapter-inquirer": "3.0.1", + "@modelcontextprotocol/sdk": "1.17.3", + "@schematics/angular": "20.2.0", "@yarnpkg/lockfile": "1.1.0", - "algoliasearch": "5.32.0", + "algoliasearch": "5.35.0", "ini": "5.0.0", "jsonc-parser": "3.3.1", - "listr2": "8.3.3", - "npm-package-arg": "12.0.2", - "npm-pick-manifest": "10.0.0", + "listr2": "9.0.1", + "npm-package-arg": "13.0.0", "pacote": "21.0.0", "resolve": "1.22.10", "semver": "7.7.2", "yargs": "18.0.0", - "zod": "3.25.75" + "zod": "3.25.76" }, "bin": { "ng": "bin/ng.js" @@ -1239,9 +1036,9 @@ } }, "node_modules/@angular/common": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-20.1.7.tgz", - "integrity": "sha512-3eFxQ18613JpBQw53wMUZfqc2RvratWx6GqKs5A1JJpMs0qq26yc2PhJWer99u3mugpKavmKoKpXFBkuWg50Qw==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-20.2.1.tgz", + "integrity": "sha512-T6RYnDZA9TyYhj2hUz4set8p4RbBCg6IKUvy6qzdKTl4nn4xQ0XUV7aGBYN4LKiGrse9lzlVUAyXtkhmwuBbCQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1250,14 +1047,14 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/core": "20.1.7", + "@angular/core": "20.2.1", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.1.7.tgz", - "integrity": "sha512-IZPkFxXoJZy7aVBgcsYLKyfr1CreCqpqhlbiSVXgtleyTcReaMoQBHeEqyFxD7PeB4Lfmf1N6ncHCILg+wxTfw==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.2.1.tgz", + "integrity": "sha512-ghVt1E8xmwjMwqyGRwXYJkr7fz40VEreUSX1q+gEzbGTftVrK1foxPT8jcueIn0ztArDf7+zSMtu314FiJZyYA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1267,13 +1064,13 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-20.1.7.tgz", - "integrity": "sha512-YnSn/956+On0KaJqzikZ6Ot7lcYJRU06bhXAjGI7UdRoyYYbtnpG3jPspXDunycvuVxKFHMzjKlIoMohk6bPGA==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-20.2.1.tgz", + "integrity": "sha512-VpbcRqNPJvy1L9RDtGGQsQiOrMzxodUWklphbtnh9MrrK6lLuy6Qj2ROiW7vKL9WfLTCXWA24gBAcMAR76dq3Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "7.28.0", + "@babel/core": "7.28.3", "@jridgewell/sourcemap-codec": "^1.4.14", "chokidar": "^4.0.0", "convert-source-map": "^1.5.1", @@ -1290,8 +1087,8 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "20.1.7", - "typescript": ">=5.8 <5.9" + "@angular/compiler": "20.2.1", + "typescript": ">=5.8 <6.0" }, "peerDependenciesMeta": { "typescript": { @@ -1299,75 +1096,10 @@ } } }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", - "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@angular/core": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-20.1.7.tgz", - "integrity": "sha512-LL5nyCQ9yrMLQMfAPgambGCPEQmpuHrg3cTRI0P9EMySgFoyyPUsIfWYYz5w1VWxmkfcXSkpNtyaNB5P60p0rg==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-20.2.1.tgz", + "integrity": "sha512-/hl3AkmdQ62P9ttmfULEDg9GIz7BkzhGv9bSH2ssiU3Y4ax6eM8uQXEbMxBA8OUKOvg1Q4POcNHIiJQgO5t28Q==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1376,7 +1108,7 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "20.1.7", + "@angular/compiler": "20.2.1", "rxjs": "^6.5.3 || ^7.4.0", "zone.js": "~0.15.0" }, @@ -1390,9 +1122,9 @@ } }, "node_modules/@angular/elements": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@angular/elements/-/elements-20.1.7.tgz", - "integrity": "sha512-M5HRDbtIBGVtsO1Sq4/ijAr/sffPswGzMrJB7YIczKl6kHrdkbmCAzQ5cpmyAJ83YgSQBypgwEpW1R8CkRtrEw==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@angular/elements/-/elements-20.2.1.tgz", + "integrity": "sha512-06QU54ynFIyyg3LFIri7msVBa0mG53d1hn+QPIK5A7tuf13e+ZxUDfcK5xOHK1YoydlOXWyYZNi9fpPhzple8w==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1401,7 +1133,7 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/core": "20.1.7", + "@angular/core": "20.2.1", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -1423,9 +1155,9 @@ } }, "node_modules/@angular/forms": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-20.1.7.tgz", - "integrity": "sha512-gHfCeW7gp7GLjHfNOF+es8gAYph4+ZhgfvP9cdj9RmRy7ckQTuJ2OwrWmruqRcrB3J46uqENQyrNhJz0ubozYA==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-20.2.1.tgz", + "integrity": "sha512-SfkiHEIFPLtTKeaXUTpRfYnpJDxaeKiTi0YqfvzEjKE68qH0t+pQ4rL0Poch2/l4snP6JS1XzO/nDve1dk3vZw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1434,16 +1166,16 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.1.7", - "@angular/core": "20.1.7", - "@angular/platform-browser": "20.1.7", + "@angular/common": "20.2.1", + "@angular/core": "20.2.1", + "@angular/platform-browser": "20.2.1", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-20.1.7.tgz", - "integrity": "sha512-swePRWkE4OCJcxs+V4LMlkHUOwkzrcFqRZpwBzak2tI4d0kdPYpkU+4QIhRmMxxXf8GduW18lhAtt/Rfo5Og7w==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-20.2.1.tgz", + "integrity": "sha512-sXTm56QSPBXiSRYSPk1uHKmdDp94rNcUd6fqjgnbP2qz8IX0CrdQS/06JiXg1wB9Cg2YaiuuO/JyYjRazJDKQg==", "dev": true, "license": "MIT", "engines": { @@ -1451,13 +1183,13 @@ } }, "node_modules/@angular/localize": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-20.1.7.tgz", - "integrity": "sha512-xeltoDANgCd7nmVZ/LjEGG+v8wSp8lVW3jAPhhoXzfqXPg9w1dyTWEkzpc8X+orUqg7MZQdNPUqnm8AsKR5dLA==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-20.2.1.tgz", + "integrity": "sha512-vemzYcHt6YX4FutpgNXiXTpKCMVaJdOG/m2+oJyvnr8KvdlrJKczXraPVY4ER+WJiHC5IQSg24otdSFc0UH2JA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "7.28.0", + "@babel/core": "7.28.3", "@types/babel__core": "7.20.5", "tinyglobby": "^0.2.12", "yargs": "^18.0.0" @@ -1471,85 +1203,20 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "20.1.7", - "@angular/compiler-cli": "20.1.7" - } - }, - "node_modules/@angular/localize/node_modules/@babel/core": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", - "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@angular/localize/node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@angular/localize/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular/localize/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "@angular/compiler": "20.2.1", + "@angular/compiler-cli": "20.2.1" } }, "node_modules/@angular/material": { - "version": "20.1.6", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-20.1.6.tgz", - "integrity": "sha512-k2rjN6ABd5ahE4LWAJ5rv7Z3WAO6tgmjOrFZG7ED0xavhcGWyHroALFqdmlIkb2QFAAF186ifLIH+xgln9edqw==", + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-20.2.0.tgz", + "integrity": "sha512-lwkV1VP7PkC/dhPRXLeYaNtPaIAOjI8/zfpkPnmxJuGA7t7hkngtTxmY+6gElDAtfnle9ZJulW4KndKGr3ng/g==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/cdk": "20.1.6", + "@angular/cdk": "20.2.0", "@angular/common": "^20.0.0 || ^21.0.0", "@angular/core": "^20.0.0 || ^21.0.0", "@angular/forms": "^20.0.0 || ^21.0.0", @@ -1558,9 +1225,9 @@ } }, "node_modules/@angular/platform-browser": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-20.1.7.tgz", - "integrity": "sha512-z2dlsrar4XmDAIgin1O3zDztVWHUpdZzR65mqyvbaNKtQHcnL33wVBBNVnksBkpPq+Lou2Cih1AdsICKyRyRbQ==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-20.2.1.tgz", + "integrity": "sha512-oxDih/A8G7W+I6oAip+sev+kebioYmzhB/NMzF8C8zx/ieVDzatJ+YeEZQt7eDaJLH94S4sIC25SPq3OFIabxg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1569,9 +1236,9 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/animations": "20.1.7", - "@angular/common": "20.1.7", - "@angular/core": "20.1.7" + "@angular/animations": "20.2.1", + "@angular/common": "20.2.1", + "@angular/core": "20.2.1" }, "peerDependenciesMeta": { "@angular/animations": { @@ -1580,9 +1247,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-20.1.7.tgz", - "integrity": "sha512-Fl/AhG54DS1NRrTE8SLJ2vy8Dd1yYjfos+h4bdghP/HY5gRFtnzb662VeKfx6sL+KlG0jV4hMYhuczTF8BvhTg==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-20.2.1.tgz", + "integrity": "sha512-bzBeDnRZFzlA5w5q5GskuKhLgAeJ3pU0B3Ch7V2fhfaAZDOTEczBFvL7I1pcXhDg8Y/8aoz4/OwqnilKLO3FUg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1591,16 +1258,16 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.1.7", - "@angular/compiler": "20.1.7", - "@angular/core": "20.1.7", - "@angular/platform-browser": "20.1.7" + "@angular/common": "20.2.1", + "@angular/compiler": "20.2.1", + "@angular/core": "20.2.1", + "@angular/platform-browser": "20.2.1" } }, "node_modules/@angular/router": { - "version": "20.1.7", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-20.1.7.tgz", - "integrity": "sha512-Pcd5zmQxq2szGQwG9Gmmt92icBrAocEowOI9OBYeuwyhcR+pVrcc67mbrVFB+bspkbTDBxxtPV+SV21vDKROSQ==", + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-20.2.1.tgz", + "integrity": "sha512-f8KfG55EVnFDC9ud+MbxAP6voKi7hVQH4YaqPK0Lm6pyc1Xp0I5W25iRbg+Y1rO1csHKHauBPkUEESEuVGBGqg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1609,9 +1276,9 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.1.7", - "@angular/core": "20.1.7", - "@angular/platform-browser": "20.1.7", + "@angular/common": "20.2.1", + "@angular/core": "20.2.1", + "@angular/platform-browser": "20.2.1", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -1755,24 +1422,24 @@ } }, "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.864.0.tgz", - "integrity": "sha512-IH3RSg/Zy2+yXQ2d4jmMk2U8A+BuJ9uNUYPWAg144yUUxanN1Czb+GyFKeJO4NGhVnn5D+j1YoRLpJN8PW2B0g==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.873.0.tgz", + "integrity": "sha512-/nqCaiIT1VFGYM427i6SfvBiohC9qjD3JtGP3/hdg70V6RRN8VXNSQgpeFplBwXTOumbb4KxKZjTws+S+4yrig==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.864.0", - "@aws-sdk/credential-provider-node": "3.864.0", - "@aws-sdk/middleware-host-header": "3.862.0", - "@aws-sdk/middleware-logger": "3.862.0", - "@aws-sdk/middleware-recursion-detection": "3.862.0", - "@aws-sdk/middleware-user-agent": "3.864.0", - "@aws-sdk/region-config-resolver": "3.862.0", + "@aws-sdk/core": "3.873.0", + "@aws-sdk/credential-provider-node": "3.873.0", + "@aws-sdk/middleware-host-header": "3.873.0", + "@aws-sdk/middleware-logger": "3.873.0", + "@aws-sdk/middleware-recursion-detection": "3.873.0", + "@aws-sdk/middleware-user-agent": "3.873.0", + "@aws-sdk/region-config-resolver": "3.873.0", "@aws-sdk/types": "3.862.0", - "@aws-sdk/util-endpoints": "3.862.0", - "@aws-sdk/util-user-agent-browser": "3.862.0", - "@aws-sdk/util-user-agent-node": "3.864.0", + "@aws-sdk/util-endpoints": "3.873.0", + "@aws-sdk/util-user-agent-browser": "3.873.0", + "@aws-sdk/util-user-agent-node": "3.873.0", "@smithy/config-resolver": "^4.1.5", "@smithy/core": "^3.8.0", "@smithy/fetch-http-handler": "^5.1.1", @@ -1805,24 +1472,24 @@ } }, "node_modules/@aws-sdk/client-comprehend": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-comprehend/-/client-comprehend-3.864.0.tgz", - "integrity": "sha512-rvgU0spL70+4i9/0yFSzCdntmjkKn1u36uRYTg1NgT2ZA/wMCd6glNWK+B+VICZrUR7NsHbK23pjSeIH/uR9jA==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-comprehend/-/client-comprehend-3.873.0.tgz", + "integrity": "sha512-f6Wh8pq3DMXyEFzb0ihZIrumXJD0+sEQ6kNeg4ei/I1Wqj10mrFjC8EiMX0pv8OgoK1P+d2uSMQzJmEkPbVZKA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.864.0", - "@aws-sdk/credential-provider-node": "3.864.0", - "@aws-sdk/middleware-host-header": "3.862.0", - "@aws-sdk/middleware-logger": "3.862.0", - "@aws-sdk/middleware-recursion-detection": "3.862.0", - "@aws-sdk/middleware-user-agent": "3.864.0", - "@aws-sdk/region-config-resolver": "3.862.0", + "@aws-sdk/core": "3.873.0", + "@aws-sdk/credential-provider-node": "3.873.0", + "@aws-sdk/middleware-host-header": "3.873.0", + "@aws-sdk/middleware-logger": "3.873.0", + "@aws-sdk/middleware-recursion-detection": "3.873.0", + "@aws-sdk/middleware-user-agent": "3.873.0", + "@aws-sdk/region-config-resolver": "3.873.0", "@aws-sdk/types": "3.862.0", - "@aws-sdk/util-endpoints": "3.862.0", - "@aws-sdk/util-user-agent-browser": "3.862.0", - "@aws-sdk/util-user-agent-node": "3.864.0", + "@aws-sdk/util-endpoints": "3.873.0", + "@aws-sdk/util-user-agent-browser": "3.873.0", + "@aws-sdk/util-user-agent-node": "3.873.0", "@smithy/config-resolver": "^4.1.5", "@smithy/core": "^3.8.0", "@smithy/fetch-http-handler": "^5.1.1", @@ -1857,24 +1524,24 @@ } }, "node_modules/@aws-sdk/client-ses": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.864.0.tgz", - "integrity": "sha512-cmsOrJZsrNa892gD2cAsbVkweDulgmC8PE38cz//bM//1BW/R1MMFClapF+Q9gACtsRVTRBXNtsIsBq8Gm1Urw==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.873.0.tgz", + "integrity": "sha512-m133jrCWPtMLSRYadK5gc6B4HqSP9EKZjCyq+sTlerN0vUBI/Uf5eA+6ZG3/04lIA7nOje+wCB8dTSZmiId55w==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.864.0", - "@aws-sdk/credential-provider-node": "3.864.0", - "@aws-sdk/middleware-host-header": "3.862.0", - "@aws-sdk/middleware-logger": "3.862.0", - "@aws-sdk/middleware-recursion-detection": "3.862.0", - "@aws-sdk/middleware-user-agent": "3.864.0", - "@aws-sdk/region-config-resolver": "3.862.0", + "@aws-sdk/core": "3.873.0", + "@aws-sdk/credential-provider-node": "3.873.0", + "@aws-sdk/middleware-host-header": "3.873.0", + "@aws-sdk/middleware-logger": "3.873.0", + "@aws-sdk/middleware-recursion-detection": "3.873.0", + "@aws-sdk/middleware-user-agent": "3.873.0", + "@aws-sdk/region-config-resolver": "3.873.0", "@aws-sdk/types": "3.862.0", - "@aws-sdk/util-endpoints": "3.862.0", - "@aws-sdk/util-user-agent-browser": "3.862.0", - "@aws-sdk/util-user-agent-node": "3.864.0", + "@aws-sdk/util-endpoints": "3.873.0", + "@aws-sdk/util-user-agent-browser": "3.873.0", + "@aws-sdk/util-user-agent-node": "3.873.0", "@smithy/config-resolver": "^4.1.5", "@smithy/core": "^3.8.0", "@smithy/fetch-http-handler": "^5.1.1", @@ -1908,23 +1575,23 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.864.0.tgz", - "integrity": "sha512-THiOp0OpQROEKZ6IdDCDNNh3qnNn/kFFaTSOiugDpgcE5QdsOxh1/RXq7LmHpTJum3cmnFf8jG59PHcz9Tjnlw==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.873.0.tgz", + "integrity": "sha512-EmcrOgFODWe7IsLKFTeSXM9TlQ80/BO1MBISlr7w2ydnOaUYIiPGRRJnDpeIgMaNqT4Rr2cRN2RiMrbFO7gDdA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.864.0", - "@aws-sdk/middleware-host-header": "3.862.0", - "@aws-sdk/middleware-logger": "3.862.0", - "@aws-sdk/middleware-recursion-detection": "3.862.0", - "@aws-sdk/middleware-user-agent": "3.864.0", - "@aws-sdk/region-config-resolver": "3.862.0", + "@aws-sdk/core": "3.873.0", + "@aws-sdk/middleware-host-header": "3.873.0", + "@aws-sdk/middleware-logger": "3.873.0", + "@aws-sdk/middleware-recursion-detection": "3.873.0", + "@aws-sdk/middleware-user-agent": "3.873.0", + "@aws-sdk/region-config-resolver": "3.873.0", "@aws-sdk/types": "3.862.0", - "@aws-sdk/util-endpoints": "3.862.0", - "@aws-sdk/util-user-agent-browser": "3.862.0", - "@aws-sdk/util-user-agent-node": "3.864.0", + "@aws-sdk/util-endpoints": "3.873.0", + "@aws-sdk/util-user-agent-browser": "3.873.0", + "@aws-sdk/util-user-agent-node": "3.873.0", "@smithy/config-resolver": "^4.1.5", "@smithy/core": "^3.8.0", "@smithy/fetch-http-handler": "^5.1.1", @@ -1957,28 +1624,28 @@ } }, "node_modules/@aws-sdk/client-transcribe-streaming": { - "version": "3.866.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-transcribe-streaming/-/client-transcribe-streaming-3.866.0.tgz", - "integrity": "sha512-Dr1oWI1yRohe/5zTZikcc50g4RWgTpfKy3TLpt1yjUedbetPVFrWzfVkHxNTYO0REMdrCeGlQ9FUcpmyyUHBwg==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-transcribe-streaming/-/client-transcribe-streaming-3.873.0.tgz", + "integrity": "sha512-hczxoriyVLy+bI92W1rukQU7sC64SVUsiiwN9nIKT5x2dn+T0nhHWkfyW+xZ4keJWBa4y1hufmHq8xRd9Gi0/g==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.864.0", - "@aws-sdk/credential-provider-node": "3.864.0", - "@aws-sdk/eventstream-handler-node": "3.862.0", - "@aws-sdk/middleware-eventstream": "3.862.0", - "@aws-sdk/middleware-host-header": "3.862.0", - "@aws-sdk/middleware-logger": "3.862.0", - "@aws-sdk/middleware-recursion-detection": "3.862.0", - "@aws-sdk/middleware-sdk-transcribe-streaming": "3.862.0", - "@aws-sdk/middleware-user-agent": "3.864.0", - "@aws-sdk/middleware-websocket": "3.862.0", - "@aws-sdk/region-config-resolver": "3.862.0", + "@aws-sdk/core": "3.873.0", + "@aws-sdk/credential-provider-node": "3.873.0", + "@aws-sdk/eventstream-handler-node": "3.873.0", + "@aws-sdk/middleware-eventstream": "3.873.0", + "@aws-sdk/middleware-host-header": "3.873.0", + "@aws-sdk/middleware-logger": "3.873.0", + "@aws-sdk/middleware-recursion-detection": "3.873.0", + "@aws-sdk/middleware-sdk-transcribe-streaming": "3.873.0", + "@aws-sdk/middleware-user-agent": "3.873.0", + "@aws-sdk/middleware-websocket": "3.873.0", + "@aws-sdk/region-config-resolver": "3.873.0", "@aws-sdk/types": "3.862.0", - "@aws-sdk/util-endpoints": "3.862.0", - "@aws-sdk/util-user-agent-browser": "3.862.0", - "@aws-sdk/util-user-agent-node": "3.864.0", + "@aws-sdk/util-endpoints": "3.873.0", + "@aws-sdk/util-user-agent-browser": "3.873.0", + "@aws-sdk/util-user-agent-node": "3.873.0", "@smithy/config-resolver": "^4.1.5", "@smithy/core": "^3.8.0", "@smithy/eventstream-serde-browser": "^4.0.5", @@ -2014,24 +1681,24 @@ } }, "node_modules/@aws-sdk/client-translate": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-translate/-/client-translate-3.864.0.tgz", - "integrity": "sha512-rLwRd8hrHQime7QBw/3LgPxZGggS4FopdVvn8PiJtB6szyJHkNr9IYmeHE421CYCMWA9xmNV3U8HQGml3K6evg==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-translate/-/client-translate-3.873.0.tgz", + "integrity": "sha512-9TEfJ65oNCzMfeX4rTBRpKRouchTGGE262Udo5xzPp7bXpEK5rSL8p61KbJHzFp+zc/bfLUB94zW0ChAFiRRkA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.864.0", - "@aws-sdk/credential-provider-node": "3.864.0", - "@aws-sdk/middleware-host-header": "3.862.0", - "@aws-sdk/middleware-logger": "3.862.0", - "@aws-sdk/middleware-recursion-detection": "3.862.0", - "@aws-sdk/middleware-user-agent": "3.864.0", - "@aws-sdk/region-config-resolver": "3.862.0", + "@aws-sdk/core": "3.873.0", + "@aws-sdk/credential-provider-node": "3.873.0", + "@aws-sdk/middleware-host-header": "3.873.0", + "@aws-sdk/middleware-logger": "3.873.0", + "@aws-sdk/middleware-recursion-detection": "3.873.0", + "@aws-sdk/middleware-user-agent": "3.873.0", + "@aws-sdk/region-config-resolver": "3.873.0", "@aws-sdk/types": "3.862.0", - "@aws-sdk/util-endpoints": "3.862.0", - "@aws-sdk/util-user-agent-browser": "3.862.0", - "@aws-sdk/util-user-agent-node": "3.864.0", + "@aws-sdk/util-endpoints": "3.873.0", + "@aws-sdk/util-user-agent-browser": "3.873.0", + "@aws-sdk/util-user-agent-node": "3.873.0", "@smithy/config-resolver": "^4.1.5", "@smithy/core": "^3.8.0", "@smithy/fetch-http-handler": "^5.1.1", @@ -2066,13 +1733,13 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.864.0.tgz", - "integrity": "sha512-LFUREbobleHEln+Zf7IG83lAZwvHZG0stI7UU0CtwyuhQy5Yx0rKksHNOCmlM7MpTEbSCfntEhYi3jUaY5e5lg==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.873.0.tgz", + "integrity": "sha512-WrROjp8X1VvmnZ4TBzwM7RF+EB3wRaY9kQJLXw+Aes0/3zRjUXvGIlseobGJMqMEGnM0YekD2F87UaVfot1xeQ==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.862.0", - "@aws-sdk/xml-builder": "3.862.0", + "@aws-sdk/xml-builder": "3.873.0", "@smithy/core": "^3.8.0", "@smithy/node-config-provider": "^4.1.4", "@smithy/property-provider": "^4.0.5", @@ -2092,12 +1759,12 @@ } }, "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.864.0.tgz", - "integrity": "sha512-jF6xJS67nPvJ/ElvdA2Q/EDArTcd0fKS3R6zImupOkTMm9PwmEM/BM7hpQCUFkVcaUhtvPpYCtuolGq9ezuKng==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.873.0.tgz", + "integrity": "sha512-/FABOYGD5yU8+L1qjvsvEhwkzzvA9zincme7019oOhEoaGu4hsul3eEFTGBcY5je36ckIXoGD4QQepWi9Ysy4g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-cognito-identity": "3.864.0", + "@aws-sdk/client-cognito-identity": "3.873.0", "@aws-sdk/types": "3.862.0", "@smithy/property-provider": "^4.0.5", "@smithy/types": "^4.3.2", @@ -2108,12 +1775,12 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.864.0.tgz", - "integrity": "sha512-StJPOI2Rt8UE6lYjXUpg6tqSZaM72xg46ljPg8kIevtBAAfdtq9K20qT/kSliWGIBocMFAv0g2mC0hAa+ECyvg==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.873.0.tgz", + "integrity": "sha512-FWj1yUs45VjCADv80JlGshAttUHBL2xtTAbJcAxkkJZzLRKVkdyrepFWhv/95MvDyzfbT6PgJiWMdW65l/8ooA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.864.0", + "@aws-sdk/core": "3.873.0", "@aws-sdk/types": "3.862.0", "@smithy/property-provider": "^4.0.5", "@smithy/types": "^4.3.2", @@ -2124,12 +1791,12 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.864.0.tgz", - "integrity": "sha512-E/RFVxGTuGnuD+9pFPH2j4l6HvrXzPhmpL8H8nOoJUosjx7d4v93GJMbbl1v/fkDLqW9qN4Jx2cI6PAjohA6OA==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.873.0.tgz", + "integrity": "sha512-0sIokBlXIsndjZFUfr3Xui8W6kPC4DAeBGAXxGi9qbFZ9PWJjn1vt2COLikKH3q2snchk+AsznREZG8NW6ezSg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.864.0", + "@aws-sdk/core": "3.873.0", "@aws-sdk/types": "3.862.0", "@smithy/fetch-http-handler": "^5.1.1", "@smithy/node-http-handler": "^4.1.1", @@ -2145,18 +1812,18 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.864.0.tgz", - "integrity": "sha512-PlxrijguR1gxyPd5EYam6OfWLarj2MJGf07DvCx9MAuQkw77HBnsu6+XbV8fQriFuoJVTBLn9ROhMr/ROAYfUg==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.873.0.tgz", + "integrity": "sha512-bQdGqh47Sk0+2S3C+N46aNQsZFzcHs7ndxYLARH/avYXf02Nl68p194eYFaAHJSQ1re5IbExU1+pbums7FJ9fA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.864.0", - "@aws-sdk/credential-provider-env": "3.864.0", - "@aws-sdk/credential-provider-http": "3.864.0", - "@aws-sdk/credential-provider-process": "3.864.0", - "@aws-sdk/credential-provider-sso": "3.864.0", - "@aws-sdk/credential-provider-web-identity": "3.864.0", - "@aws-sdk/nested-clients": "3.864.0", + "@aws-sdk/core": "3.873.0", + "@aws-sdk/credential-provider-env": "3.873.0", + "@aws-sdk/credential-provider-http": "3.873.0", + "@aws-sdk/credential-provider-process": "3.873.0", + "@aws-sdk/credential-provider-sso": "3.873.0", + "@aws-sdk/credential-provider-web-identity": "3.873.0", + "@aws-sdk/nested-clients": "3.873.0", "@aws-sdk/types": "3.862.0", "@smithy/credential-provider-imds": "^4.0.7", "@smithy/property-provider": "^4.0.5", @@ -2169,17 +1836,17 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.864.0.tgz", - "integrity": "sha512-2BEymFeXURS+4jE9tP3vahPwbYRl0/1MVaFZcijj6pq+nf5EPGvkFillbdBRdc98ZI2NedZgSKu3gfZXgYdUhQ==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.873.0.tgz", + "integrity": "sha512-+v/xBEB02k2ExnSDL8+1gD6UizY4Q/HaIJkNSkitFynRiiTQpVOSkCkA0iWxzksMeN8k1IHTE5gzeWpkEjNwbA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.864.0", - "@aws-sdk/credential-provider-http": "3.864.0", - "@aws-sdk/credential-provider-ini": "3.864.0", - "@aws-sdk/credential-provider-process": "3.864.0", - "@aws-sdk/credential-provider-sso": "3.864.0", - "@aws-sdk/credential-provider-web-identity": "3.864.0", + "@aws-sdk/credential-provider-env": "3.873.0", + "@aws-sdk/credential-provider-http": "3.873.0", + "@aws-sdk/credential-provider-ini": "3.873.0", + "@aws-sdk/credential-provider-process": "3.873.0", + "@aws-sdk/credential-provider-sso": "3.873.0", + "@aws-sdk/credential-provider-web-identity": "3.873.0", "@aws-sdk/types": "3.862.0", "@smithy/credential-provider-imds": "^4.0.7", "@smithy/property-provider": "^4.0.5", @@ -2192,12 +1859,12 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.864.0.tgz", - "integrity": "sha512-Zxnn1hxhq7EOqXhVYgkF4rI9MnaO3+6bSg/tErnBQ3F8kDpA7CFU24G1YxwaJXp2X4aX3LwthefmSJHwcVP/2g==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.873.0.tgz", + "integrity": "sha512-ycFv9WN+UJF7bK/ElBq1ugWA4NMbYS//1K55bPQZb2XUpAM2TWFlEjG7DIyOhLNTdl6+CbHlCdhlKQuDGgmm0A==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.864.0", + "@aws-sdk/core": "3.873.0", "@aws-sdk/types": "3.862.0", "@smithy/property-provider": "^4.0.5", "@smithy/shared-ini-file-loader": "^4.0.5", @@ -2209,14 +1876,14 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.864.0.tgz", - "integrity": "sha512-UPyPNQbxDwHVGmgWdGg9/9yvzuedRQVF5jtMkmP565YX9pKZ8wYAcXhcYdNPWFvH0GYdB0crKOmvib+bmCuwkw==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.873.0.tgz", + "integrity": "sha512-SudkAOZmjEEYgUrqlUUjvrtbWJeI54/0Xo87KRxm4kfBtMqSx0TxbplNUAk8Gkg4XQNY0o7jpG8tK7r2Wc2+uw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.864.0", - "@aws-sdk/core": "3.864.0", - "@aws-sdk/token-providers": "3.864.0", + "@aws-sdk/client-sso": "3.873.0", + "@aws-sdk/core": "3.873.0", + "@aws-sdk/token-providers": "3.873.0", "@aws-sdk/types": "3.862.0", "@smithy/property-provider": "^4.0.5", "@smithy/shared-ini-file-loader": "^4.0.5", @@ -2228,13 +1895,13 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.864.0.tgz", - "integrity": "sha512-nNcjPN4SYg8drLwqK0vgVeSvxeGQiD0FxOaT38mV2H8cu0C5NzpvA+14Xy+W6vT84dxgmJYKk71Cr5QL2Oz+rA==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.873.0.tgz", + "integrity": "sha512-Gw2H21+VkA6AgwKkBtTtlGZ45qgyRZPSKWs0kUwXVlmGOiPz61t/lBX0vG6I06ZIz2wqeTJ5OA1pWZLqw1j0JQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.864.0", - "@aws-sdk/nested-clients": "3.864.0", + "@aws-sdk/core": "3.873.0", + "@aws-sdk/nested-clients": "3.873.0", "@aws-sdk/types": "3.862.0", "@smithy/property-provider": "^4.0.5", "@smithy/types": "^4.3.2", @@ -2245,9 +1912,9 @@ } }, "node_modules/@aws-sdk/eventstream-handler-node": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.862.0.tgz", - "integrity": "sha512-jbGpv5UaGPz5MNZxSVa4nujQUR7uQXnPIxzQc03ul1Ehd7Eh1x0egh9Nx40HFVOuuXWr864qVZQQSWGEOR2gnA==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.873.0.tgz", + "integrity": "sha512-c3j9Q3RSR4+/01oHgx8b4WuD2HinVAalbsL7rJKlw86sP6ef1Gq7rVYFn74Ooh+2fIVecvX3cla/tdkR8PwBtA==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.862.0", @@ -2260,9 +1927,9 @@ } }, "node_modules/@aws-sdk/middleware-eventstream": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.862.0.tgz", - "integrity": "sha512-PlnUSgqBHXttxGc1MaXGz02o6H4C9dxv+RS+1G7msUlcD4rl4fS1AkjOAHLCfzKvZdcEHygeN8levK6hZOCENg==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.873.0.tgz", + "integrity": "sha512-x/BFHxZcfL6siwAPILmF8bGuWAmxDhrXvTlxJZOwwozWnhgRSxgxX2sitpWGvS8pL64DoABwCWSgsgyoXJlMFw==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.862.0", @@ -2275,9 +1942,9 @@ } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.862.0.tgz", - "integrity": "sha512-jDje8dCFeFHfuCAxMDXBs8hy8q9NCTlyK4ThyyfAj3U4Pixly2mmzY2u7b7AyGhWsjJNx8uhTjlYq5zkQPQCYw==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.873.0.tgz", + "integrity": "sha512-KZ/W1uruWtMOs7D5j3KquOxzCnV79KQW9MjJFZM/M0l6KI8J6V3718MXxFHsTjUE4fpdV6SeCNLV1lwGygsjJA==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.862.0", @@ -2290,9 +1957,9 @@ } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.862.0.tgz", - "integrity": "sha512-N/bXSJznNBR/i7Ofmf9+gM6dx/SPBK09ZWLKsW5iQjqKxAKn/2DozlnE54uiEs1saHZWoNDRg69Ww4XYYSlG1Q==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.873.0.tgz", + "integrity": "sha512-QhNZ8X7pW68kFez9QxUSN65Um0Feo18ZmHxszQZNUhKDsXew/EG9NPQE/HgYcekcon35zHxC4xs+FeNuPurP2g==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.862.0", @@ -2304,9 +1971,9 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.862.0.tgz", - "integrity": "sha512-KVoo3IOzEkTq97YKM4uxZcYFSNnMkhW/qj22csofLegZi5fk90ztUnnaeKfaEJHfHp/tm1Y3uSoOXH45s++kKQ==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.873.0.tgz", + "integrity": "sha512-OtgY8EXOzRdEWR//WfPkA/fXl0+WwE8hq0y9iw2caNyKPtca85dzrrZWnPqyBK/cpImosrpR1iKMYr41XshsCg==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.862.0", @@ -2319,13 +1986,13 @@ } }, "node_modules/@aws-sdk/middleware-sdk-transcribe-streaming": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-transcribe-streaming/-/middleware-sdk-transcribe-streaming-3.862.0.tgz", - "integrity": "sha512-IXLUTFF5UlCtE12GSytEOfewq5S5yfWewslkoa5ATfOhI60i9Om4zBPSZ1T2OqInnmYbKj5txydypiynZyZaPw==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-transcribe-streaming/-/middleware-sdk-transcribe-streaming-3.873.0.tgz", + "integrity": "sha512-W37a7mNDg7i3RjtyhpH3CzJzz6hwVFdf2qYlp/sMlLALlKn2GYrGBgl8q4mTZgMqMG8GJ2ZXNWil8k40eq+U8Q==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.862.0", - "@aws-sdk/util-format-url": "3.862.0", + "@aws-sdk/util-format-url": "3.873.0", "@smithy/eventstream-serde-browser": "^4.0.5", "@smithy/protocol-http": "^5.1.3", "@smithy/signature-v4": "^5.1.3", @@ -2338,14 +2005,14 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.864.0.tgz", - "integrity": "sha512-wrddonw4EyLNSNBrApzEhpSrDwJiNfjxDm5E+bn8n32BbAojXASH8W8jNpxz/jMgNkkJNxCfyqybGKzBX0OhbQ==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.873.0.tgz", + "integrity": "sha512-gHqAMYpWkPhZLwqB3Yj83JKdL2Vsb64sryo8LN2UdpElpS+0fT4yjqSxKTfp7gkhN6TCIxF24HQgbPk5FMYJWw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.864.0", + "@aws-sdk/core": "3.873.0", "@aws-sdk/types": "3.862.0", - "@aws-sdk/util-endpoints": "3.862.0", + "@aws-sdk/util-endpoints": "3.873.0", "@smithy/core": "^3.8.0", "@smithy/protocol-http": "^5.1.3", "@smithy/types": "^4.3.2", @@ -2356,13 +2023,13 @@ } }, "node_modules/@aws-sdk/middleware-websocket": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.862.0.tgz", - "integrity": "sha512-EfdLqToN5VHbqvD9iBgs/fxYsHxsgJeFnTIv1XarRf3XYqO9UAf+PPSTTUxAKeqD65ZrKFwfmLwjXOwVT86zcw==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.873.0.tgz", + "integrity": "sha512-NLh9JmE460/WIVlsoP4vR5zbgPu50uVHXiEyr5lf34MatayiMTiC7Dd9KecKys8tppVVqahOMkOLb4/nl0hk6Q==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.862.0", - "@aws-sdk/util-format-url": "3.862.0", + "@aws-sdk/util-format-url": "3.873.0", "@smithy/eventstream-codec": "^4.0.5", "@smithy/eventstream-serde-browser": "^4.0.5", "@smithy/fetch-http-handler": "^5.1.1", @@ -2377,23 +2044,23 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.864.0.tgz", - "integrity": "sha512-H1C+NjSmz2y8Tbgh7Yy89J20yD/hVyk15hNoZDbCYkXg0M358KS7KVIEYs8E2aPOCr1sK3HBE819D/yvdMgokA==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.873.0.tgz", + "integrity": "sha512-yg8JkRHuH/xO65rtmLOWcd9XQhxX1kAonp2CliXT44eA/23OBds6XoheY44eZeHfCTgutDLTYitvy3k9fQY6ZA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.864.0", - "@aws-sdk/middleware-host-header": "3.862.0", - "@aws-sdk/middleware-logger": "3.862.0", - "@aws-sdk/middleware-recursion-detection": "3.862.0", - "@aws-sdk/middleware-user-agent": "3.864.0", - "@aws-sdk/region-config-resolver": "3.862.0", + "@aws-sdk/core": "3.873.0", + "@aws-sdk/middleware-host-header": "3.873.0", + "@aws-sdk/middleware-logger": "3.873.0", + "@aws-sdk/middleware-recursion-detection": "3.873.0", + "@aws-sdk/middleware-user-agent": "3.873.0", + "@aws-sdk/region-config-resolver": "3.873.0", "@aws-sdk/types": "3.862.0", - "@aws-sdk/util-endpoints": "3.862.0", - "@aws-sdk/util-user-agent-browser": "3.862.0", - "@aws-sdk/util-user-agent-node": "3.864.0", + "@aws-sdk/util-endpoints": "3.873.0", + "@aws-sdk/util-user-agent-browser": "3.873.0", + "@aws-sdk/util-user-agent-node": "3.873.0", "@smithy/config-resolver": "^4.1.5", "@smithy/core": "^3.8.0", "@smithy/fetch-http-handler": "^5.1.1", @@ -2426,9 +2093,9 @@ } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.862.0.tgz", - "integrity": "sha512-VisR+/HuVFICrBPY+q9novEiE4b3mvDofWqyvmxHcWM7HumTz9ZQSuEtnlB/92GVM3KDUrR9EmBHNRrfXYZkcQ==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.873.0.tgz", + "integrity": "sha512-q9sPoef+BBG6PJnc4x60vK/bfVwvRWsPgcoQyIra057S/QGjq5VkjvNk6H8xedf6vnKlXNBwq9BaANBXnldUJg==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.862.0", @@ -2443,13 +2110,13 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.864.0.tgz", - "integrity": "sha512-gTc2QHOBo05SCwVA65dUtnJC6QERvFaPiuppGDSxoF7O5AQNK0UR/kMSenwLqN8b5E1oLYvQTv3C1idJLRX0cg==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.873.0.tgz", + "integrity": "sha512-BWOCeFeV/Ba8fVhtwUw/0Hz4wMm9fjXnMb4Z2a5he/jFlz5mt1/rr6IQ4MyKgzOaz24YrvqsJW2a0VUKOaYDvg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.864.0", - "@aws-sdk/nested-clients": "3.864.0", + "@aws-sdk/core": "3.873.0", + "@aws-sdk/nested-clients": "3.873.0", "@aws-sdk/types": "3.862.0", "@smithy/property-provider": "^4.0.5", "@smithy/shared-ini-file-loader": "^4.0.5", @@ -2474,9 +2141,9 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.862.0.tgz", - "integrity": "sha512-eCZuScdE9MWWkHGM2BJxm726MCmWk/dlHjOKvkM0sN1zxBellBMw5JohNss1Z8/TUmnW2gb9XHTOiHuGjOdksA==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.873.0.tgz", + "integrity": "sha512-YByHrhjxYdjKRf/RQygRK1uh0As1FIi9+jXTcIEX/rBgN8mUByczr2u4QXBzw7ZdbdcOBMOkPnLRjNOWW1MkFg==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.862.0", @@ -2490,9 +2157,9 @@ } }, "node_modules/@aws-sdk/util-format-url": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.862.0.tgz", - "integrity": "sha512-4kd2PYUMA/fAnIcVVwBIDCa2KCuUPrS3ELgScLjBaESP0NN+K163m40U5RbzNec/elOcJHR8lEThzzSb7vXH6w==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.873.0.tgz", + "integrity": "sha512-v//b9jFnhzTKKV3HFTw2MakdM22uBAs2lBov51BWmFXuFtSTdBLrR7zgfetQPE3PVkFai0cmtJQPdc3MX+T/cQ==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.862.0", @@ -2505,9 +2172,9 @@ } }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.804.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.804.0.tgz", - "integrity": "sha512-zVoRfpmBVPodYlnMjgVjfGoEZagyRF5IPn3Uo6ZvOZp24chnW/FRstH7ESDHDDRga4z3V+ElUQHKpFDXWyBW5A==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.873.0.tgz", + "integrity": "sha512-xcVhZF6svjM5Rj89T1WzkjQmrTF6dpR2UvIHPMTnSZoNe6CixejPZ6f0JJ2kAhO8H+dUHwNBlsUgOTIKiK/Syg==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -2517,9 +2184,9 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.862.0.tgz", - "integrity": "sha512-BmPTlm0r9/10MMr5ND9E92r8KMZbq5ltYXYpVcUbAsnB1RJ8ASJuRoLne5F7mB3YMx0FJoOTuSq7LdQM3LgW3Q==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.873.0.tgz", + "integrity": "sha512-AcRdbK6o19yehEcywI43blIBhOCSo6UgyWcuOJX5CFF8k39xm1ILCjQlRRjchLAxWrm0lU0Q7XV90RiMMFMZtA==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.862.0", @@ -2529,12 +2196,12 @@ } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.864.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.864.0.tgz", - "integrity": "sha512-d+FjUm2eJEpP+FRpVR3z6KzMdx1qwxEYDz8jzNKwxYLBBquaBaP/wfoMtMQKAcbrR7aT9FZVZF7zDgzNxUvQlQ==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.873.0.tgz", + "integrity": "sha512-9MivTP+q9Sis71UxuBaIY3h5jxH0vN3/ZWGxO8ADL19S2OIfknrYSAfzE5fpoKROVBu0bS4VifHOFq4PY1zsxw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.864.0", + "@aws-sdk/middleware-user-agent": "3.873.0", "@aws-sdk/types": "3.862.0", "@smithy/node-config-provider": "^4.1.4", "@smithy/types": "^4.3.2", @@ -2553,9 +2220,9 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.862.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.862.0.tgz", - "integrity": "sha512-6Ed0kmC1NMbuFTEgNmamAUU1h5gShgxL1hBVLbEzUa3trX5aJBz1vU4bXaBTvOYUAnOHtiy1Ml4AMStd6hJnFA==", + "version": "3.873.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.873.0.tgz", + "integrity": "sha512-kLO7k7cGJ6KaHiExSJWojZurF7SnGMDHXRuQunFnEoD0n1yB6Lqy/S/zHiQ7oJnBhPr9q0TW9qFkrsZb1Uc54w==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.3.2", @@ -2741,23 +2408,6 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/core/node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -2776,16 +2426,16 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", - "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.5", - "@babel/types": "^7.27.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { @@ -3289,15 +2939,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz", - "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", + "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.28.0" }, "engines": { "node": ">=6.9.0" @@ -3981,17 +3631,17 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.27.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.27.4.tgz", - "integrity": "sha512-D68nR5zxU64EUzV8i7T3R5XP0Xhrou/amNnddsRQssx6GrTLdZl1rLxyjtVZBd+v/NVX4AbTPOB5aU8thAZV1A==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.3.tgz", + "integrity": "sha512-Y6ab1kGqZ0u42Zv/4a7l0l72n9DKP/MKoKWaUSBylrhNZO2prYuqFOLbn5aW5SIFXwSH93yfjbgllL8lxuGKLg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.11.0", - "babel-plugin-polyfill-regenerator": "^0.6.1", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", "semver": "^6.3.1" }, "engines": { @@ -4244,38 +3894,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", - "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.28.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", - "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5", - "core-js-compat": "^3.43.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -4302,9 +3920,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", - "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz", + "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==", "dev": true, "license": "MIT", "engines": { @@ -4345,23 +3963,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/types": { "version": "7.28.2", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", @@ -4436,9 +4037,9 @@ } }, "node_modules/@commitlint/load/node_modules/chalk": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", - "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", "dev": true, "license": "MIT", "optional": true, @@ -4484,9 +4085,9 @@ } }, "node_modules/@commitlint/types/node_modules/chalk": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", - "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", "dev": true, "license": "MIT", "optional": true, @@ -4535,10 +4136,44 @@ "node": ">=14.17.0" } }, + "node_modules/@emnapi/core": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", + "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.4", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", + "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", + "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", - "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", "cpu": [ "ppc64" ], @@ -4553,9 +4188,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", - "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", "cpu": [ "arm" ], @@ -4570,9 +4205,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", - "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", "cpu": [ "arm64" ], @@ -4587,9 +4222,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", - "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", "cpu": [ "x64" ], @@ -4604,9 +4239,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", - "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", "cpu": [ "arm64" ], @@ -4621,9 +4256,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", - "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", "cpu": [ "x64" ], @@ -4638,9 +4273,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", - "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", "cpu": [ "arm64" ], @@ -4655,9 +4290,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", - "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", "cpu": [ "x64" ], @@ -4672,9 +4307,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", - "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", "cpu": [ "arm" ], @@ -4689,9 +4324,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", - "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", "cpu": [ "arm64" ], @@ -4706,9 +4341,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", - "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", "cpu": [ "ia32" ], @@ -4723,9 +4358,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", - "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", "cpu": [ "loong64" ], @@ -4740,9 +4375,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", - "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", "cpu": [ "mips64el" ], @@ -4757,9 +4392,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", - "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", "cpu": [ "ppc64" ], @@ -4774,9 +4409,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", - "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", "cpu": [ "riscv64" ], @@ -4791,9 +4426,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", - "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", "cpu": [ "s390x" ], @@ -4808,9 +4443,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", - "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", "cpu": [ "x64" ], @@ -4825,9 +4460,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", - "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", "cpu": [ "arm64" ], @@ -4842,9 +4477,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", - "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", "cpu": [ "x64" ], @@ -4859,9 +4494,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", - "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", "cpu": [ "arm64" ], @@ -4876,9 +4511,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", - "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", "cpu": [ "x64" ], @@ -4892,10 +4527,27 @@ "node": ">=18" } }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", - "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", "cpu": [ "x64" ], @@ -4910,9 +4562,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", - "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", "cpu": [ "arm64" ], @@ -4927,9 +4579,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", - "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", "cpu": [ "ia32" ], @@ -4944,9 +4596,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", - "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", "cpu": [ "x64" ], @@ -5041,13 +4693,13 @@ } }, "node_modules/@inquirer/checkbox": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.2.1.tgz", - "integrity": "sha512-bevKGO6kX1eM/N+pdh9leS5L7TBF4ICrzi9a+cbWkrxeAeIcwlo/7OfWGCDERdRCI2/Q6tjltX4bt07ALHDwFw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.2.2.tgz", + "integrity": "sha512-E+KExNurKcUJJdxmjglTl141EwxWyAHplvsYJQgSwXf8qiNWkTxTuCCqmhFEmbIXd4zLaGMfQFJ6WrZ7fSeV3g==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.15", + "@inquirer/core": "^10.2.0", "@inquirer/figures": "^1.0.13", "@inquirer/type": "^3.0.8", "ansi-escapes": "^4.3.2", @@ -5066,14 +4718,14 @@ } }, "node_modules/@inquirer/confirm": { - "version": "5.1.13", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.13.tgz", - "integrity": "sha512-EkCtvp67ICIVVzjsquUiVSd+V5HRGOGQfsqA4E4vMWhYnB7InUL0pa0TIWt1i+OfP16Gkds8CdIu6yGZwOM1Yw==", + "version": "5.1.14", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.14.tgz", + "integrity": "sha512-5yR4IBfe0kXe59r1YCTG8WXkUbl7Z35HK87Sw+WUyGD8wNUx7JvY7laahzeytyE1oLn74bQnL7hstctQxisQ8Q==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.14", - "@inquirer/type": "^3.0.7" + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8" }, "engines": { "node": ">=18" @@ -5088,9 +4740,9 @@ } }, "node_modules/@inquirer/core": { - "version": "10.1.15", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.15.tgz", - "integrity": "sha512-8xrp836RZvKkpNbVvgWUlxjT4CraKk2q+I3Ksy+seI2zkcE+y6wNs1BVhgcv8VyImFecUhdQrYLdW32pAjwBdA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.2.0.tgz", + "integrity": "sha512-NyDSjPqhSvpZEMZrLCYUquWNl+XC/moEcVFqS55IEYIYsY0a1cUCevSqk7ctOlnm/RaSBU5psFryNlxcmGrjaA==", "dev": true, "license": "MIT", "dependencies": { @@ -5116,13 +4768,13 @@ } }, "node_modules/@inquirer/editor": { - "version": "4.2.17", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.17.tgz", - "integrity": "sha512-r6bQLsyPSzbWrZZ9ufoWL+CztkSatnJ6uSxqd6N+o41EZC51sQeWOzI6s5jLb+xxTWxl7PlUppqm8/sow241gg==", + "version": "4.2.18", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.18.tgz", + "integrity": "sha512-yeQN3AXjCm7+Hmq5L6Dm2wEDeBRdAZuyZ4I7tWSSanbxDzqM0KqzoDbKM7p4ebllAYdoQuPJS6N71/3L281i6w==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.15", + "@inquirer/core": "^10.2.0", "@inquirer/external-editor": "^1.0.1", "@inquirer/type": "^3.0.8" }, @@ -5139,13 +4791,13 @@ } }, "node_modules/@inquirer/expand": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.17.tgz", - "integrity": "sha512-PSqy9VmJx/VbE3CT453yOfNa+PykpKg/0SYP7odez1/NWBGuDXgPhp4AeGYYKjhLn5lUUavVS/JbeYMPdH50Mw==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.18.tgz", + "integrity": "sha512-xUjteYtavH7HwDMzq4Cn2X4Qsh5NozoDHCJTdoXg9HfZ4w3R6mxV1B9tL7DGJX2eq/zqtsFjhm0/RJIMGlh3ag==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.15", + "@inquirer/core": "^10.2.0", "@inquirer/type": "^3.0.8", "yoctocolors-cjs": "^2.1.2" }, @@ -5194,13 +4846,13 @@ } }, "node_modules/@inquirer/input": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.2.1.tgz", - "integrity": "sha512-tVC+O1rBl0lJpoUZv4xY+WGWY8V5b0zxU1XDsMsIHYregdh7bN5X5QnIONNBAl0K765FYlAfNHS2Bhn7SSOVow==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.2.2.tgz", + "integrity": "sha512-hqOvBZj/MhQCpHUuD3MVq18SSoDNHy7wEnQ8mtvs71K8OPZVXJinOzcvQna33dNYLYE4LkA9BlhAhK6MJcsVbw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.15", + "@inquirer/core": "^10.2.0", "@inquirer/type": "^3.0.8" }, "engines": { @@ -5216,13 +4868,13 @@ } }, "node_modules/@inquirer/number": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.17.tgz", - "integrity": "sha512-GcvGHkyIgfZgVnnimURdOueMk0CztycfC8NZTiIY9arIAkeOgt6zG57G+7vC59Jns3UX27LMkPKnKWAOF5xEYg==", + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.18.tgz", + "integrity": "sha512-7exgBm52WXZRczsydCVftozFTrrwbG5ySE0GqUd2zLNSBXyIucs2Wnm7ZKLe/aUu6NUg9dg7Q80QIHCdZJiY4A==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.15", + "@inquirer/core": "^10.2.0", "@inquirer/type": "^3.0.8" }, "engines": { @@ -5238,13 +4890,13 @@ } }, "node_modules/@inquirer/password": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.17.tgz", - "integrity": "sha512-DJolTnNeZ00E1+1TW+8614F7rOJJCM4y4BAGQ3Gq6kQIG+OJ4zr3GLjIjVVJCbKsk2jmkmv6v2kQuN/vriHdZA==", + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.18.tgz", + "integrity": "sha512-zXvzAGxPQTNk/SbT3carAD4Iqi6A2JS2qtcqQjsL22uvD+JfQzUrDEtPjLL7PLn8zlSNyPdY02IiQjzoL9TStA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.15", + "@inquirer/core": "^10.2.0", "@inquirer/type": "^3.0.8", "ansi-escapes": "^4.3.2" }, @@ -5261,22 +4913,22 @@ } }, "node_modules/@inquirer/prompts": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.6.0.tgz", - "integrity": "sha512-jAhL7tyMxB3Gfwn4HIJ0yuJ5pvcB5maYUcouGcgd/ub79f9MqZ+aVnBtuFf+VC2GTkCBF+R+eo7Vi63w5VZlzw==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.8.2.tgz", + "integrity": "sha512-nqhDw2ZcAUrKNPwhjinJny903bRhI0rQhiDz1LksjeRxqa36i3l75+4iXbOy0rlDpLJGxqtgoPavQjmmyS5UJw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/checkbox": "^4.1.9", - "@inquirer/confirm": "^5.1.13", - "@inquirer/editor": "^4.2.14", - "@inquirer/expand": "^4.0.16", - "@inquirer/input": "^4.2.0", - "@inquirer/number": "^3.0.16", - "@inquirer/password": "^4.0.16", - "@inquirer/rawlist": "^4.1.4", - "@inquirer/search": "^3.0.16", - "@inquirer/select": "^4.2.4" + "@inquirer/checkbox": "^4.2.1", + "@inquirer/confirm": "^5.1.14", + "@inquirer/editor": "^4.2.17", + "@inquirer/expand": "^4.0.17", + "@inquirer/input": "^4.2.1", + "@inquirer/number": "^3.0.17", + "@inquirer/password": "^4.0.17", + "@inquirer/rawlist": "^4.1.5", + "@inquirer/search": "^3.1.0", + "@inquirer/select": "^4.3.1" }, "engines": { "node": ">=18" @@ -5291,13 +4943,13 @@ } }, "node_modules/@inquirer/rawlist": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.5.tgz", - "integrity": "sha512-R5qMyGJqtDdi4Ht521iAkNqyB6p2UPuZUbMifakg1sWtu24gc2Z8CJuw8rP081OckNDMgtDCuLe42Q2Kr3BolA==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.6.tgz", + "integrity": "sha512-KOZqa3QNr3f0pMnufzL7K+nweFFCCBs6LCXZzXDrVGTyssjLeudn5ySktZYv1XiSqobyHRYYK0c6QsOxJEhXKA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.15", + "@inquirer/core": "^10.2.0", "@inquirer/type": "^3.0.8", "yoctocolors-cjs": "^2.1.2" }, @@ -5314,13 +4966,13 @@ } }, "node_modules/@inquirer/search": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.1.0.tgz", - "integrity": "sha512-PMk1+O/WBcYJDq2H7foV0aAZSmDdkzZB9Mw2v/DmONRJopwA/128cS9M/TXWLKKdEQKZnKwBzqu2G4x/2Nqx8Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.1.1.tgz", + "integrity": "sha512-TkMUY+A2p2EYVY3GCTItYGvqT6LiLzHBnqsU1rJbrpXUijFfM6zvUx0R4civofVwFCmJZcKqOVwwWAjplKkhxA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.15", + "@inquirer/core": "^10.2.0", "@inquirer/figures": "^1.0.13", "@inquirer/type": "^3.0.8", "yoctocolors-cjs": "^2.1.2" @@ -5338,13 +4990,13 @@ } }, "node_modules/@inquirer/select": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.3.1.tgz", - "integrity": "sha512-Gfl/5sqOF5vS/LIrSndFgOh7jgoe0UXEizDqahFRkq5aJBLegZ6WjuMh/hVEJwlFQjyLq1z9fRtvUMkb7jM1LA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.3.2.tgz", + "integrity": "sha512-nwous24r31M+WyDEHV+qckXkepvihxhnyIaod2MG7eCE6G0Zm/HUF6jgN8GXgf4U7AU6SLseKdanY195cwvU6w==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.15", + "@inquirer/core": "^10.2.0", "@inquirer/figures": "^1.0.13", "@inquirer/type": "^3.0.8", "ansi-escapes": "^4.3.2", @@ -5644,13 +5296,14 @@ } }, "node_modules/@jsonjoy.com/json-pointer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.1.tgz", - "integrity": "sha512-tJpwQfuBuxqZlyoJOSZcqf7OUmiYQ6MiPNmOv4KbZdXE/DdvBSSAwhos0zIlJU/AXxC8XpuO8p08bh2fIl+RKA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz", + "integrity": "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/util": "^1.3.0" + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/util": "^1.9.0" }, "engines": { "node": ">=10.0" @@ -5692,48 +5345,26 @@ "license": "MIT" }, "node_modules/@listr2/prompt-adapter-inquirer": { - "version": "2.0.22", - "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-2.0.22.tgz", - "integrity": "sha512-hV36ZoY+xKL6pYOt1nPNnkciFkn89KZwqLhAFzJvYysAvL5uBQdiADZx/8bIDXIukzzwG0QlPYolgMzQUtKgpQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-3.0.1.tgz", + "integrity": "sha512-3XFmGwm3u6ioREG+ynAQB7FoxfajgQnMhIu8wC5eo/Lsih4aKDg0VuIMGaOsYn7hJSJagSeaD4K8yfpkEoDEmA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/type": "^1.5.5" + "@inquirer/type": "^3.0.7" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" }, "peerDependencies": { - "@inquirer/prompts": ">= 3 < 8" - } - }, - "node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.5.tgz", - "integrity": "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mute-stream": "^1.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@listr2/prompt-adapter-inquirer/node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "@inquirer/prompts": ">= 3 < 8", + "listr2": "9.0.1" } }, "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.4.1.tgz", - "integrity": "sha512-kKeP5PaY3bFrrF6GY5aDd96iuh1eoS+5CHJ+7hIP629KIEwzGNwbIzBmEX9TAhRJOivSRDTHCIsbu//+NsYKkg==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.4.2.tgz", + "integrity": "sha512-NK80WwDoODyPaSazKbzd3NEJ3ygePrkERilZshxBViBARNz21rmediktGHExoj9n5t9+ChlgLlxecdFKLCuCKg==", "cpu": [ "arm64" ], @@ -5745,9 +5376,9 @@ ] }, "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.4.1.tgz", - "integrity": "sha512-9CMB3seTyHs3EOVWdKiB8IIEDBJ3Gq00Tqyi0V7DS3HL90BjM/AkbZGuhzXwPrfeFazR24SKaRrUQF74f+CmWw==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.4.2.tgz", + "integrity": "sha512-zevaowQNmrp3U7Fz1s9pls5aIgpKRsKb3dZWDINtLiozh3jZI9fBrI19lYYBxqdyiIyNdlyiidPnwPShj4aK+w==", "cpu": [ "x64" ], @@ -5759,9 +5390,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.4.1.tgz", - "integrity": "sha512-1Mi69vU0akHgCI7tF6YbimPaNEKJiBm/p5A+aM8egr0joj27cQmCCOm2mZQ+Ht2BqmCfZaIgQnMg4gFYNMlpCA==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.4.2.tgz", + "integrity": "sha512-OmHCULY17rkx/RoCoXlzU7LyR8xqrksgdYWwtYa14l/sseezZ8seKWXcogHcjulBddER5NnEFV4L/Jtr2nyxeg==", "cpu": [ "arm" ], @@ -5773,9 +5404,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.4.1.tgz", - "integrity": "sha512-d0vuXOdoKjHHJYZ/CRWopnkOiUpev+bgBBW+1tXtWsYWUj8uxl9ZmTBEmsL5mjUlpQDrlYiJSrhOU1hg5QWBSw==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.4.2.tgz", + "integrity": "sha512-ZBEfbNZdkneebvZs98Lq30jMY8V9IJzckVeigGivV7nTHJc+89Ctomp1kAIWKlwIG0ovCDrFI448GzFPORANYg==", "cpu": [ "arm64" ], @@ -5787,9 +5418,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-x64": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.4.1.tgz", - "integrity": "sha512-00RbEpvfnyPodlICiGFuiOmyvWaL9nzCRSqZz82BVFsGTiSQnnF0gpD1C8tO6OvtptELbtRuM7BS9f97LcowZw==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.4.2.tgz", + "integrity": "sha512-vL9nM17C77lohPYE4YaAQvfZCSVJSryE4fXdi8M7uWPBnU+9DJabgKVAeyDb84ZM2vcFseoBE4/AagVtJeRE7g==", "cpu": [ "x64" ], @@ -5801,9 +5432,9 @@ ] }, "node_modules/@lmdb/lmdb-win32-arm64": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.4.1.tgz", - "integrity": "sha512-4h8tm3i1ODf+28UyqQZLP7c2jmRM26AyEEyYp994B4GiBdGvGAsYUu3oiHANYK9xFpvLuFzyGeqFm1kdNC0D1A==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.4.2.tgz", + "integrity": "sha512-SXWjdBfNDze4ZPeLtYIzsIeDJDJ/SdsA0pEXcUBayUIMO0FQBHfVZZyHXQjjHr4cvOAzANBgIiqaXRwfMhzmLw==", "cpu": [ "arm64" ], @@ -5815,9 +5446,9 @@ ] }, "node_modules/@lmdb/lmdb-win32-x64": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.4.1.tgz", - "integrity": "sha512-HqqKIhTbq6piJhkJpTTf3w1m/CgrmwXRAL9R9j7Ru5xdZSeO7Mg4AWiBC9B00uXR+LvVZKtUyRMVZfhmIZztmQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.4.2.tgz", + "integrity": "sha512-IY+r3bxKW6Q6sIPiMC0L533DEfRJSXibjSI3Ft/w9Q8KQBNqEIvUFXt+09wV8S5BRk0a8uSF19YWxuRwEfI90g==", "cpu": [ "x64" ], @@ -5829,9 +5460,9 @@ ] }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.13.3.tgz", - "integrity": "sha512-bGwA78F/U5G2jrnsdRkPY3IwIwZeWUEfb5o764b79lb0rJmMT76TLwKhdNZOWakOQtedYefwIR4emisEMvInKA==", + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.17.3.tgz", + "integrity": "sha512-JPwUKWSsbzx+DLFznf/QZ32Qa+ptfbUlHhRLrBQBAFu9iI1iYvizM4p+zhhRDceSsPutXp4z+R/HPVphlIiclg==", "dev": true, "license": "MIT", "dependencies": { @@ -6283,10 +5914,23 @@ "node": ">= 10" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.3.tgz", + "integrity": "sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.5", + "@emnapi/runtime": "^1.4.5", + "@tybys/wasm-util": "^0.10.0" + } + }, "node_modules/@ng-select/ng-select": { - "version": "20.1.2", - "resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-20.1.2.tgz", - "integrity": "sha512-xPcIRUApj9KjuoYorPjTlq8ZUUI/MhuDAEV6LyUO+m9E/8xmpCgRLTvBD2VgB+qMsYBcJGvtwGzR5eVPGvNjcQ==", + "version": "20.1.3", + "resolved": "https://registry.npmjs.org/@ng-select/ng-select/-/ng-select-20.1.3.tgz", + "integrity": "sha512-hksDLWU4sdul7H/FTAFANEQkSZnOUeBYhGsY2EX4jKuBpQ1T7mxefp/v5NxiZVS97Hs0d21KFG4K+JAUmGyU5Q==", "license": "MIT", "dependencies": { "tslib": "^2.8.1" @@ -6328,9 +5972,9 @@ } }, "node_modules/@ngtools/webpack": { - "version": "20.1.6", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-20.1.6.tgz", - "integrity": "sha512-0AkmS/xhrXBRsgPJnh/AjWMebuFKK2uHb1LqcENedNzgxu96I+w8fIY8ByDZ0U7T3qsa72PSHbXK4lXeWmq8xw==", + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-20.2.0.tgz", + "integrity": "sha512-+oRNsB8RfmDd4Mnr8AyJwU3GUyXalQcI9r3Hoi4OSyFncWJeOnpTAWErx2JomqAYkm8WkE0PoRxKnD0RxKQ30Q==", "dev": true, "license": "MIT", "engines": { @@ -6340,7 +5984,7 @@ }, "peerDependencies": { "@angular/compiler-cli": "^20.0.0", - "typescript": ">=5.8 <5.9", + "typescript": ">=5.8 <6.0", "webpack": "^5.54.0" } }, @@ -6557,6 +6201,26 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@npmcli/package-json/node_modules/hosted-git-info": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", + "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/@npmcli/package-json/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -6833,6 +6497,26 @@ "@octokit/openapi-types": "^18.0.0" } }, + "node_modules/@oxc-project/runtime": { + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.81.0.tgz", + "integrity": "sha512-zm/LDVOq9FEmHiuM8zO4DWirv0VP2Tv2VsgaiHby9nvpq+FVrcqNYgv+TysLKOITQXWZj/roluTxFvpkHP0Iuw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.81.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.81.0.tgz", + "integrity": "sha512-CnOqkybZK8z6Gx7Wb1qF7AEnSzbol1WwcIzxYOr8e91LytGOjo0wCpgoYWZo8sdbpqX+X+TJayIzo4Pv0R/KjA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, "node_modules/@parcel/watcher": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", @@ -7225,10 +6909,216 @@ "node": ">=12" } }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.32.tgz", + "integrity": "sha512-Gs+313LfR4Ka3hvifdag9r44WrdKQaohya7ZXUXzARF7yx0atzFlVZjsvxtKAw1Vmtr4hB/RjUD1jf73SW7zDw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.32.tgz", + "integrity": "sha512-W8oMqzGcI7wKPXUtS3WJNXzbghHfNiuM1UBAGpVb+XlUCgYRQJd2PRGP7D3WGql3rR3QEhUvSyAuCBAftPQw6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.32.tgz", + "integrity": "sha512-pM4c4sKUk37noJrnnDkJknLhCsfZu7aWyfe67bD0GQHfzAPjV16wPeD9CmQg4/0vv+5IfHYaa4VE536xbA+W0Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.32.tgz", + "integrity": "sha512-M8SUgFlYb5kJJWcFC8gUMRiX4WLFxPKMed3SJ2YrxontgIrEcpizPU8nLNVsRYEStoSfKHKExpQw3OP6fm+5bw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.32.tgz", + "integrity": "sha512-FuQpbNC/hE//bvv29PFnk0AtpJzdPdYl5CMhlWPovd9g3Kc3lw9TrEPIbL7gRPUdhKAiq6rVaaGvOnXxsa0eww==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.32.tgz", + "integrity": "sha512-hRZygRlaGCjcNTNY9GV7dDI18sG1dK3cc7ujHq72LoDad23zFDUGMQjiSxHWK+/r92iMV+j2MiHbvzayxqynsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.32.tgz", + "integrity": "sha512-HzgT6h+CXLs+GKAU0Wvkt3rvcv0CmDBsDjlPhh4GHysOKbG9NjpKYX2zvjx671E9pGbTvcPpwy7gGsy7xpu+8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.32.tgz", + "integrity": "sha512-Ab/wbf6gdzphDbsg51UaxsC93foQ7wxhtg0SVCXd25BrV4MAJ1HoDtKN/f4h0maFmJobkqYub2DlmoasUzkvBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.32.tgz", + "integrity": "sha512-VoxqGEfh5A1Yx+zBp/FR5QwAbtzbuvky2SVc+ii4g1gLD4zww6mt/hPi5zG+b88zYPFBKHpxMtsz9cWqXU5V5Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.32.tgz", + "integrity": "sha512-qZ1ViyOUDGbiZrSAJ/FIAhYUElDfVxxFW6DLT/w4KeoZN3HsF4jmRP95mXtl51/oGrqzU9l9Q2f7/P4O/o2ZZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.32.tgz", + "integrity": "sha512-hEkG3wD+f3wytV0lqwb/uCrXc4r4Ny/DWJFJPfQR3VeMWplhWGgSHNwZc2Q7k86Yi36f9NNzzWmrIuvHI9lCVw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.32.tgz", + "integrity": "sha512-k3MvDf8SiA7uP2ikP0unNouJ2YCrnwi7xcVW+RDgMp5YXVr3Xu6svmT3HGn0tkCKUuPmf+uy8I5uiHt5qWQbew==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rolldown/binding-win32-ia32-msvc": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.32.tgz", + "integrity": "sha512-wAi/FxGh7arDOUG45UmnXE1sZUa0hY4cXAO2qWAjFa3f7bTgz/BqwJ7XN5SUezvAJPNkME4fEpInfnBvM25a0w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.32.tgz", + "integrity": "sha512-Ej0i4PZk8ltblZtzVK8ouaGUacUtxRmTm5S9794mdyU/tYxXjAJNseOfxrnHpMWKjMDrOKbqkPqJ52T9NR4LQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.32.tgz", + "integrity": "sha512-QReCdvxiUZAPkvp1xpAg62IeNzykOFA6syH2CnClif4YmALN1XKpB39XneL80008UbtMShthSVDKmrx05N1q/g==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz", - "integrity": "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.48.1.tgz", + "integrity": "sha512-rGmb8qoG/zdmKoYELCBwu7vt+9HxZ7Koos3pD0+sH5fR3u3Wb/jGcpnqxcnWsPEKDUyzeLSqksN8LJtgXjqBYw==", "cpu": [ "arm" ], @@ -7240,9 +7130,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz", - "integrity": "sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.48.1.tgz", + "integrity": "sha512-4e9WtTxrk3gu1DFE+imNJr4WsL13nWbD/Y6wQcyku5qadlKHY3OQ3LJ/INrrjngv2BJIHnIzbqMk1GTAC2P8yQ==", "cpu": [ "arm64" ], @@ -7254,9 +7144,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz", - "integrity": "sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.48.1.tgz", + "integrity": "sha512-+XjmyChHfc4TSs6WUQGmVf7Hkg8ferMAE2aNYYWjiLzAS/T62uOsdfnqv+GHRjq7rKRnYh4mwWb4Hz7h/alp8A==", "cpu": [ "arm64" ], @@ -7268,9 +7158,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz", - "integrity": "sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.48.1.tgz", + "integrity": "sha512-upGEY7Ftw8M6BAJyGwnwMw91rSqXTcOKZnnveKrVWsMTF8/k5mleKSuh7D4v4IV1pLxKAk3Tbs0Lo9qYmii5mQ==", "cpu": [ "x64" ], @@ -7282,9 +7172,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz", - "integrity": "sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.48.1.tgz", + "integrity": "sha512-P9ViWakdoynYFUOZhqq97vBrhuvRLAbN/p2tAVJvhLb8SvN7rbBnJQcBu8e/rQts42pXGLVhfsAP0k9KXWa3nQ==", "cpu": [ "arm64" ], @@ -7296,9 +7186,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz", - "integrity": "sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.48.1.tgz", + "integrity": "sha512-VLKIwIpnBya5/saccM8JshpbxfyJt0Dsli0PjXozHwbSVaHTvWXJH1bbCwPXxnMzU4zVEfgD1HpW3VQHomi2AQ==", "cpu": [ "x64" ], @@ -7310,9 +7200,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz", - "integrity": "sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.48.1.tgz", + "integrity": "sha512-3zEuZsXfKaw8n/yF7t8N6NNdhyFw3s8xJTqjbTDXlipwrEHo4GtIKcMJr5Ed29leLpB9AugtAQpAHW0jvtKKaQ==", "cpu": [ "arm" ], @@ -7324,9 +7214,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz", - "integrity": "sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.48.1.tgz", + "integrity": "sha512-leo9tOIlKrcBmmEypzunV/2w946JeLbTdDlwEZ7OnnsUyelZ72NMnT4B2vsikSgwQifjnJUbdXzuW4ToN1wV+Q==", "cpu": [ "arm" ], @@ -7338,9 +7228,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz", - "integrity": "sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.48.1.tgz", + "integrity": "sha512-Vy/WS4z4jEyvnJm+CnPfExIv5sSKqZrUr98h03hpAMbE2aI0aD2wvK6GiSe8Gx2wGp3eD81cYDpLLBqNb2ydwQ==", "cpu": [ "arm64" ], @@ -7352,9 +7242,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz", - "integrity": "sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.48.1.tgz", + "integrity": "sha512-x5Kzn7XTwIssU9UYqWDB9VpLpfHYuXw5c6bJr4Mzv9kIv242vmJHbI5PJJEnmBYitUIfoMCODDhR7KoZLot2VQ==", "cpu": [ "arm64" ], @@ -7366,9 +7256,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz", - "integrity": "sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.48.1.tgz", + "integrity": "sha512-yzCaBbwkkWt/EcgJOKDUdUpMHjhiZT/eDktOPWvSRpqrVE04p0Nd6EGV4/g7MARXXeOqstflqsKuXVM3H9wOIQ==", "cpu": [ "loong64" ], @@ -7379,10 +7269,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz", - "integrity": "sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.48.1.tgz", + "integrity": "sha512-UK0WzWUjMAJccHIeOpPhPcKBqax7QFg47hwZTp6kiMhQHeOYJeaMwzeRZe1q5IiTKsaLnHu9s6toSYVUlZ2QtQ==", "cpu": [ "ppc64" ], @@ -7394,9 +7284,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz", - "integrity": "sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.48.1.tgz", + "integrity": "sha512-3NADEIlt+aCdCbWVZ7D3tBjBX1lHpXxcvrLt/kdXTiBrOds8APTdtk2yRL2GgmnSVeX4YS1JIf0imFujg78vpw==", "cpu": [ "riscv64" ], @@ -7408,9 +7298,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz", - "integrity": "sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.48.1.tgz", + "integrity": "sha512-euuwm/QTXAMOcyiFCcrx0/S2jGvFlKJ2Iro8rsmYL53dlblp3LkUQVFzEidHhvIPPvcIsxDhl2wkBE+I6YVGzA==", "cpu": [ "riscv64" ], @@ -7422,9 +7312,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz", - "integrity": "sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.48.1.tgz", + "integrity": "sha512-w8mULUjmPdWLJgmTYJx/W6Qhln1a+yqvgwmGXcQl2vFBkWsKGUBRbtLRuKJUln8Uaimf07zgJNxOhHOvjSQmBQ==", "cpu": [ "s390x" ], @@ -7436,9 +7326,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz", - "integrity": "sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.48.1.tgz", + "integrity": "sha512-90taWXCWxTbClWuMZD0DKYohY1EovA+W5iytpE89oUPmT5O1HFdf8cuuVIylE6vCbrGdIGv85lVRzTcpTRZ+kA==", "cpu": [ "x64" ], @@ -7450,9 +7340,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz", - "integrity": "sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.48.1.tgz", + "integrity": "sha512-2Gu29SkFh1FfTRuN1GR1afMuND2GKzlORQUP3mNMJbqdndOg7gNsa81JnORctazHRokiDzQ5+MLE5XYmZW5VWg==", "cpu": [ "x64" ], @@ -7464,9 +7354,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz", - "integrity": "sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.48.1.tgz", + "integrity": "sha512-6kQFR1WuAO50bxkIlAVeIYsz3RUx+xymwhTo9j94dJ+kmHe9ly7muH23sdfWduD0BA8pD9/yhonUvAjxGh34jQ==", "cpu": [ "arm64" ], @@ -7478,9 +7368,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz", - "integrity": "sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.48.1.tgz", + "integrity": "sha512-RUyZZ/mga88lMI3RlXFs4WQ7n3VyU07sPXmMG7/C1NOi8qisUg57Y7LRarqoGoAiopmGmChUhSwfpvQ3H5iGSQ==", "cpu": [ "ia32" ], @@ -7492,9 +7382,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz", - "integrity": "sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.48.1.tgz", + "integrity": "sha512-8a/caCUN4vkTChxkaIJcMtwIVcBhi4X2PQRoT+yCK3qRYaZ7cURrmJFL5Ux9H9RaMIXj9RuihckdmkBX3zZsgg==", "cpu": [ "x64" ], @@ -7506,14 +7396,14 @@ ] }, "node_modules/@schematics/angular": { - "version": "20.1.6", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-20.1.6.tgz", - "integrity": "sha512-1dE+GkpSZbsQxnir/S24g3+pA5sE0XOMxa4Wxhon0dxArP/gH72hsinoVaLDfcQkYOtbbTw/Q8VV41uWBI9eGg==", + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-20.2.0.tgz", + "integrity": "sha512-7sZVj7hOcytQrPE17ixjzul9ih81IfXGcEZvr7fT77qy7Hm5rbMjxqSYxCTf3kAyBFRSLq/E8GTapPAjk2coOg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "20.1.6", - "@angular-devkit/schematics": "20.1.6", + "@angular-devkit/core": "20.2.0", + "@angular-devkit/schematics": "20.2.0", "jsonc-parser": "3.3.1" }, "engines": { @@ -8824,6 +8714,17 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", + "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -9042,9 +8943,9 @@ } }, "node_modules/@types/jquery": { - "version": "3.5.32", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.32.tgz", - "integrity": "sha512-b9Xbf4CkMqS02YH8zACqN1xzdxc3cO735Qe5AbSUFmyOiaWAbcpqh9Wna+Uk0vgACvoQHpWDg2rGdHkYPLmCiQ==", + "version": "3.5.33", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.33.tgz", + "integrity": "sha512-SeyVJXlCZpEki5F0ghuYe+L+PprQta6nRZqhONt9F13dWBtR/ftoaIbdRQ7cis7womE+X2LKhsDdDtkkDhJS6g==", "dev": true, "license": "MIT", "dependencies": { @@ -9066,9 +8967,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.17.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.17.2.tgz", - "integrity": "sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w==", + "version": "22.18.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.0.tgz", + "integrity": "sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9076,9 +8977,9 @@ } }, "node_modules/@types/node-forge": { - "version": "1.3.13", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.13.tgz", - "integrity": "sha512-zePQJSW5QkwSHKRApqWCVKeKoSOt4xvEnLENZPjyvm9Ezdf/EyDeJM7jqLzOwjVICQQzvLZ63T55MKdJB5H6ww==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", + "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", "dev": true, "license": "MIT", "dependencies": { @@ -9656,25 +9557,26 @@ } }, "node_modules/algoliasearch": { - "version": "5.32.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.32.0.tgz", - "integrity": "sha512-84xBncKNPBK8Ae89F65+SyVcOihrIbm/3N7to+GpRBHEUXGjA3ydWTMpcRW6jmFzkBQ/eqYy/y+J+NBpJWYjBg==", + "version": "5.35.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.35.0.tgz", + "integrity": "sha512-Y+moNhsqgLmvJdgTsO4GZNgsaDWv8AOGAaPeIeHKlDn/XunoAqYbA+XNpBd1dW8GOXAUDyxC9Rxc7AV4kpFcIg==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-abtesting": "5.32.0", - "@algolia/client-analytics": "5.32.0", - "@algolia/client-common": "5.32.0", - "@algolia/client-insights": "5.32.0", - "@algolia/client-personalization": "5.32.0", - "@algolia/client-query-suggestions": "5.32.0", - "@algolia/client-search": "5.32.0", - "@algolia/ingestion": "1.32.0", - "@algolia/monitoring": "1.32.0", - "@algolia/recommend": "5.32.0", - "@algolia/requester-browser-xhr": "5.32.0", - "@algolia/requester-fetch": "5.32.0", - "@algolia/requester-node-http": "5.32.0" + "@algolia/abtesting": "1.1.0", + "@algolia/client-abtesting": "5.35.0", + "@algolia/client-analytics": "5.35.0", + "@algolia/client-common": "5.35.0", + "@algolia/client-insights": "5.35.0", + "@algolia/client-personalization": "5.35.0", + "@algolia/client-query-suggestions": "5.35.0", + "@algolia/client-search": "5.35.0", + "@algolia/ingestion": "1.35.0", + "@algolia/monitoring": "1.35.0", + "@algolia/recommend": "5.35.0", + "@algolia/requester-browser-xhr": "5.35.0", + "@algolia/requester-fetch": "5.35.0", + "@algolia/requester-node-http": "5.35.0" }, "engines": { "node": ">= 14.0.0" @@ -9765,9 +9667,9 @@ } }, "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", "dev": true, "license": "MIT", "engines": { @@ -9800,6 +9702,16 @@ "node": ">=0.10.0" } }, + "node_modules/ansis": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.1.0.tgz", + "integrity": "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -10489,14 +10401,14 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", - "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3", - "core-js-compat": "^3.40.0" + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -10632,14 +10544,14 @@ } }, "node_modules/beasties": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.3.4.tgz", - "integrity": "sha512-NmzN1zN1cvGccXFyZ73335+ASXwBlVWcUPssiUDIlFdfyatHPRRufjCd5w8oPaQPvVnf9ELklaCGb1gi9FBwIw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.3.5.tgz", + "integrity": "sha512-NaWu+f4YrJxEttJSm16AzMIFtVldCvaJ68b1L098KpqXmxt9xOLtKoLkKxb8ekhOrLqEJAbvT6n6SEvB/sac7A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "css-select": "^5.1.0", - "css-what": "^6.1.0", + "css-select": "^6.0.0", + "css-what": "^7.0.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "htmlparser2": "^10.0.0", @@ -10820,9 +10732,9 @@ "license": "MIT" }, "node_modules/bowser": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.12.0.tgz", - "integrity": "sha512-HcOcTudTeEWgbHh0Y1Tyb6fdeR71m4b/QACf0D4KswGTsNeIJQmg38mRENZPAYPZvGFN3fk3604XbQEPdxXdKg==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.12.1.tgz", + "integrity": "sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw==", "license": "MIT" }, "node_modules/brace-expansion": { @@ -10850,9 +10762,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz", - "integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==", + "version": "4.25.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.3.tgz", + "integrity": "sha512-cDGv1kkDI4/0e5yON9yM5G/0A5u8sf5TnmdX5C9qHzI9PPu++sQ9zjm1k9NiOrf3riY4OkK0zSGqfvJyJsgCBQ==", "dev": true, "funding": [ { @@ -10870,8 +10782,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001733", - "electron-to-chromium": "^1.5.199", + "caniuse-lite": "^1.0.30001735", + "electron-to-chromium": "^1.5.204", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -11278,9 +11190,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001735", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001735.tgz", - "integrity": "sha512-EV/laoX7Wq2J9TQlyIXRxTJqIw4sxfXS4OYgudGxBYRuTv0q7AM6yMEpU/Vo1I94thg9U6EZ2NfZx9GJq83u7w==", + "version": "1.0.30001737", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001737.tgz", + "integrity": "sha512-BiloLiXtQNrY5UyF0+1nSJLXUENuhka2pzy2Fx5pGxqavdrxSCW4U6Pn/PoG3Efspi2frRbHpBV2XsrPE6EDlw==", "dev": true, "funding": [ { @@ -12487,9 +12399,9 @@ } }, "node_modules/copy-webpack-plugin": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-13.0.0.tgz", - "integrity": "sha512-FgR/h5a6hzJqATDGd9YG41SeDViH+0bkHn6WNXCi5zKAZkeESeSxLySSsFLHqLEVCh0E+rITmCf0dusXWYukeQ==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-13.0.1.tgz", + "integrity": "sha512-J+YV3WfhY6W/Xf9h+J1znYuqTye2xkBUIGyTPWuBAT27qajBa5mR4f8WBmfDY3YjRftT2kqZZiLi1qf0H+UOFw==", "dev": true, "license": "MIT", "dependencies": { @@ -12549,9 +12461,9 @@ } }, "node_modules/core-js": { - "version": "3.45.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.45.0.tgz", - "integrity": "sha512-c2KZL9lP4DjkN3hk/an4pWn5b5ZefhRJnAc42n6LJ19kSnbeRbdQZE5dSeE2LBol1OwJD3X1BQvFTAsa8ReeDA==", + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.45.1.tgz", + "integrity": "sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -12560,13 +12472,13 @@ } }, "node_modules/core-js-compat": { - "version": "3.45.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.45.0.tgz", - "integrity": "sha512-gRoVMBawZg0OnxaVv3zpqLLxaHmsubEGyTnqdpI/CEBvX4JadI1dMSHxagThprYRtSVbuQxvi6iUatdPxohHpA==", + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.45.1.tgz", + "integrity": "sha512-tqTt5T4PzsMIZ430XGviK4vzYSoeNJ6CXODi6c/voxOT6IZqBht5/EKaSNnYiEjjRYxjVz7DQIsOsY0XNi8PIA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.25.1" + "browserslist": "^4.25.3" }, "funding": { "type": "opencollective", @@ -12767,17 +12679,17 @@ } }, "node_modules/css-select": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", - "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-6.0.0.tgz", + "integrity": "sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" + "css-what": "^7.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "nth-check": "^2.1.1" }, "funding": { "url": "https://github.com/sponsors/fb55" @@ -12808,9 +12720,9 @@ } }, "node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-7.0.0.tgz", + "integrity": "sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -13632,9 +13544,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.202", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.202.tgz", - "integrity": "sha512-NxbYjRmiHcHXV1Ws3fWUW+SLb62isauajk45LUJ/HgIOkUA7jLZu/X2Iif+X9FBNK8QkF9Zb4Q2mcwXCcY30mg==", + "version": "1.5.208", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.208.tgz", + "integrity": "sha512-ozZyibehoe7tOhNaf16lKmljVf+3npZcJIEbJRVftVsmAg5TeA1mGS9dVCZzOwr2xT7xK15V0p7+GZqSPgkuPg==", "dev": true, "license": "ISC" }, @@ -14173,9 +14085,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", - "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -14186,37 +14098,38 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.5", - "@esbuild/android-arm": "0.25.5", - "@esbuild/android-arm64": "0.25.5", - "@esbuild/android-x64": "0.25.5", - "@esbuild/darwin-arm64": "0.25.5", - "@esbuild/darwin-x64": "0.25.5", - "@esbuild/freebsd-arm64": "0.25.5", - "@esbuild/freebsd-x64": "0.25.5", - "@esbuild/linux-arm": "0.25.5", - "@esbuild/linux-arm64": "0.25.5", - "@esbuild/linux-ia32": "0.25.5", - "@esbuild/linux-loong64": "0.25.5", - "@esbuild/linux-mips64el": "0.25.5", - "@esbuild/linux-ppc64": "0.25.5", - "@esbuild/linux-riscv64": "0.25.5", - "@esbuild/linux-s390x": "0.25.5", - "@esbuild/linux-x64": "0.25.5", - "@esbuild/netbsd-arm64": "0.25.5", - "@esbuild/netbsd-x64": "0.25.5", - "@esbuild/openbsd-arm64": "0.25.5", - "@esbuild/openbsd-x64": "0.25.5", - "@esbuild/sunos-x64": "0.25.5", - "@esbuild/win32-arm64": "0.25.5", - "@esbuild/win32-ia32": "0.25.5", - "@esbuild/win32-x64": "0.25.5" + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" } }, "node_modules/esbuild-wasm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.25.5.tgz", - "integrity": "sha512-V/rbdOws2gDcnCAECfPrajhuafI0WY4WumUgc8ZHwOLnvmM0doLQ+dqvVFI2qkVxQsvo6880aC9IjpyDqcwwTw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.25.9.tgz", + "integrity": "sha512-Jpv5tCSwQg18aCqCRD3oHIX/prBhXMDapIoG//A+6+dV0e7KQMGFg85ihJ5T1EeMjbZjON3TqFy0VrGAnIHLDA==", "dev": true, "license": "MIT", "bin": { @@ -14828,9 +14741,9 @@ } }, "node_modules/eventsource-parser": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.3.tgz", - "integrity": "sha512-nVpZkTMM9rF6AQ9gPJpFsNAMt48wIzB5TQgiTLdHiuO8XEDhUgZEhqKlZWXbIzo9VmJ/HvysHqEaVeD5v9TPvA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.5.tgz", + "integrity": "sha512-bSRG85ZrMdmWtm7qkF9He9TNRzc/Bm99gEJMaQoHJ9E6Kv9QBbsldh2oMj7iXmYNEAVvNgvv5vPorG6W+XtBhQ==", "dev": true, "license": "MIT", "engines": { @@ -15269,9 +15182,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "dev": true, "funding": [ { @@ -16118,6 +16031,23 @@ "node": ">=0.10.0" } }, + "node_modules/glob-to-regex.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.0.1.tgz", + "integrity": "sha512-CG/iEvgQqfzoVsMUbxSJcwbG2JwyZ3naEqPkeltwl0BSS8Bp83k3xlGms+0QdWFUAwV+uvo80wNswKF6FWEkKg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", @@ -17542,24 +17472,27 @@ } }, "node_modules/hosted-git-info": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", - "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.0.tgz", + "integrity": "sha512-gEf705MZLrDPkbbhi8PnoO4ZwYgKoNL+ISZ3AjZMht2r3N5tuTwncyDi6Fv2/qDnMmZxgs0yI8WDOyR8q3G+SQ==", "dev": true, "license": "ISC", "dependencies": { - "lru-cache": "^10.0.1" + "lru-cache": "^11.1.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", + "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", "dev": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "20 || >=22" + } }, "node_modules/hpack.js": { "version": "2.1.6", @@ -18905,9 +18838,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -19958,9 +19891,9 @@ } }, "node_modules/less": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/less/-/less-4.3.0.tgz", - "integrity": "sha512-X9RyH9fvemArzfdP8Pi3irr7lor2Ok4rOttDXBhlwDg+wKQsXOXgHWduAJE1EsF7JJx0w0bcO6BC6tCKKYnXKA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/less/-/less-4.4.0.tgz", + "integrity": "sha512-kdTwsyRuncDfjEs0DlRILWNvxhDG/Zij4YLO4TMJgDLW+8OzpfkdPnRgrsRuY1o+oaxJGWsps5f/RVBgGmmN0w==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -20294,9 +20227,9 @@ "license": "MIT" }, "node_modules/listr2": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", - "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.1.tgz", + "integrity": "sha512-SL0JY3DaxylDuo/MecFeiC+7pedM0zia33zl0vcjgwcq1q1FWWF1To9EIauPbl8GbMCU0R2e0uJ8bZunhYKD2g==", "dev": true, "license": "MIT", "dependencies": { @@ -20308,7 +20241,7 @@ "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/listr2/node_modules/ansi-styles": { @@ -20391,9 +20324,9 @@ } }, "node_modules/lmdb": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.4.1.tgz", - "integrity": "sha512-hoG9RIv42kdGJiieyElgWcKCTaw5S6Jqwyd1gLSVdsJ3+8MVm8e4yLronThiRJI9DazFAAs9xfB9nWeMQ2DWKA==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.4.2.tgz", + "integrity": "sha512-nwVGUfTBUwJKXd6lRV8pFNfnrCC1+l49ESJRM19t/tFb/97QfJEixe5DYRvug5JO7DSFKoKaVy7oGMt5rVqZvg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -20409,13 +20342,13 @@ "download-lmdb-prebuilds": "bin/download-prebuilds.js" }, "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "3.4.1", - "@lmdb/lmdb-darwin-x64": "3.4.1", - "@lmdb/lmdb-linux-arm": "3.4.1", - "@lmdb/lmdb-linux-arm64": "3.4.1", - "@lmdb/lmdb-linux-x64": "3.4.1", - "@lmdb/lmdb-win32-arm64": "3.4.1", - "@lmdb/lmdb-win32-x64": "3.4.1" + "@lmdb/lmdb-darwin-arm64": "3.4.2", + "@lmdb/lmdb-darwin-x64": "3.4.2", + "@lmdb/lmdb-linux-arm": "3.4.2", + "@lmdb/lmdb-linux-arm64": "3.4.2", + "@lmdb/lmdb-linux-x64": "3.4.2", + "@lmdb/lmdb-win32-arm64": "3.4.2", + "@lmdb/lmdb-win32-x64": "3.4.2" } }, "node_modules/load-json-file": { @@ -20623,9 +20556,9 @@ } }, "node_modules/log-symbols/node_modules/chalk": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", - "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", "dev": true, "license": "MIT", "engines": { @@ -21073,9 +21006,9 @@ } }, "node_modules/marked-terminal/node_modules/chalk": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", - "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", "dev": true, "license": "MIT", "peer": true, @@ -21314,15 +21247,17 @@ } }, "node_modules/memfs": { - "version": "4.36.0", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.36.0.tgz", - "integrity": "sha512-mfBfzGUdoEw5AZwG8E965ej3BbvW2F9LxEWj4uLxF6BEh1dO2N9eS3AGu9S6vfenuQYrVjsbUOOZK7y3vz4vyQ==", + "version": "4.38.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.38.1.tgz", + "integrity": "sha512-exfrOkkU3m0EpbQ0iQJP93HUbkprnIBU7IUnobSNAzHkBUzsklLwENGLEm8ZwJmMuLoFEfv1pYQ54wSpkay4kQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/json-pack": "^1.0.3", - "@jsonjoy.com/util": "^1.3.0", - "tree-dump": "^1.0.1", + "@jsonjoy.com/json-pack": "^1.11.0", + "@jsonjoy.com/util": "^1.9.0", + "glob-to-regex.js": "^1.0.1", + "thingies": "^2.5.0", + "tree-dump": "^1.0.3", "tslib": "^2.0.0" }, "engines": { @@ -21539,9 +21474,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", - "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.4.tgz", + "integrity": "sha512-ZWYT7ln73Hptxqxk2DxPU9MmapXRhxkJD6tkSR04dnQxm8BGu2hzgKLugK5yySD97u/8yy7Ma7E76k9ZdvtjkQ==", "dev": true, "license": "MIT", "dependencies": { @@ -22119,9 +22054,9 @@ } }, "node_modules/node-gyp": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.3.0.tgz", - "integrity": "sha512-9J0+C+2nt3WFuui/mC46z2XCZ21/cKlFDuywULmseD/LlmnOrSeEAE4c/1jw6aybXLmpZnQY3/LmOJfgyHIcng==", + "version": "11.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.4.1.tgz", + "integrity": "sha512-GiVxQ1e4TdZSSVmFDYUn6uUsrEUP68pa8C/xBzCfL/FcLHa4reWrxxTP7tRGhNdviYrNsL5kRolBL5LNYEutCw==", "dev": true, "license": "MIT", "dependencies": { @@ -22545,19 +22480,19 @@ } }, "node_modules/npm-package-arg": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.2.tgz", - "integrity": "sha512-f1NpFjNI9O4VbKMOlA5QoBq/vSQPORHcTZ2feJpFkTHJ9eQkdlmZEKSjcAhxTGInC7RlEyScT9ui67NaOsjFWA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.0.tgz", + "integrity": "sha512-+t2etZAGcB7TbbLHfDwooV9ppB2LhhcT6A+L9cahsf9mEUAoQ6CktLEVvEnpD0N5CkX7zJqnPGaFtoQDy9EkHQ==", "dev": true, "license": "ISC", "dependencies": { - "hosted-git-info": "^8.0.0", + "hosted-git-info": "^9.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^6.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/npm-packlist": { @@ -22589,6 +22524,42 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/npm-pick-manifest/node_modules/hosted-git-info": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", + "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-pick-manifest/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/npm-pick-manifest/node_modules/npm-package-arg": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.2.tgz", + "integrity": "sha512-f1NpFjNI9O4VbKMOlA5QoBq/vSQPORHcTZ2feJpFkTHJ9eQkdlmZEKSjcAhxTGInC7RlEyScT9ui67NaOsjFWA==", + "dev": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^6.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/npm-registry-fetch": { "version": "18.0.2", "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-18.0.2.tgz", @@ -22609,6 +22580,42 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/npm-registry-fetch/node_modules/hosted-git-info": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", + "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/npm-registry-fetch/node_modules/npm-package-arg": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.2.tgz", + "integrity": "sha512-f1NpFjNI9O4VbKMOlA5QoBq/vSQPORHcTZ2feJpFkTHJ9eQkdlmZEKSjcAhxTGInC7RlEyScT9ui67NaOsjFWA==", + "dev": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^6.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -25637,16 +25644,16 @@ } }, "node_modules/open": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", - "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", "dev": true, "license": "MIT", "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" + "wsl-utils": "^0.1.0" }, "engines": { "node": ">=18" @@ -25698,9 +25705,9 @@ } }, "node_modules/ora/node_modules/chalk": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz", - "integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", "dev": true, "license": "MIT", "engines": { @@ -26009,6 +26016,42 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/pacote/node_modules/hosted-git-info": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", + "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/pacote/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/pacote/node_modules/npm-package-arg": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.2.tgz", + "integrity": "sha512-f1NpFjNI9O4VbKMOlA5QoBq/vSQPORHcTZ2feJpFkTHJ9eQkdlmZEKSjcAhxTGInC7RlEyScT9ui67NaOsjFWA==", + "dev": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^6.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -26117,15 +26160,15 @@ } }, "node_modules/parse5-html-rewriting-stream": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.1.0.tgz", - "integrity": "sha512-2ifK6Jb+ONoqOy5f+cYHsqvx1obHQdvIk13Jmt/5ezxP0U9p+fqd+R6O73KblGswyuzBYfetmsfK9ThMgnuPPg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-8.0.0.tgz", + "integrity": "sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw==", "dev": true, "license": "MIT", "dependencies": { "entities": "^6.0.0", - "parse5": "^7.0.0", - "parse5-sax-parser": "^7.0.0" + "parse5": "^8.0.0", + "parse5-sax-parser": "^8.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -26144,19 +26187,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/parse5-html-rewriting-stream/node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/parse5-htmlparser2-tree-adapter": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", @@ -26177,39 +26207,13 @@ "peer": true }, "node_modules/parse5-sax-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", - "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-sax-parser/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/parse5-sax-parser/node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-8.0.0.tgz", + "integrity": "sha512-/dQ8UzHZwnrzs3EvDj6IkKrD/jIZyTlB+8XrHJvcjNgRdmWruNdN9i9RK/JtxakmlUdPwKubKPTCqvbTgzGhrw==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^6.0.0" + "parse5": "^8.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -26379,9 +26383,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -26435,16 +26439,16 @@ } }, "node_modules/piscina": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.1.2.tgz", - "integrity": "sha512-9cE/BTA/xhDiyNUEj6EKWLEQC17fh/24ydYzQwcA7QdYh75K6kzL2GHvxDF5i9rFGtUaaKk7/u4xp07qiKXccQ==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.1.3.tgz", + "integrity": "sha512-0u3N7H4+hbr40KjuVn2uNhOcthu/9usKhnw5vT3J7ply79v3D3M8naI00el9Klcy16x557VsEkkUQaHCWFXC/g==", "dev": true, "license": "MIT", "engines": { "node": ">=20.x" }, "optionalDependencies": { - "@napi-rs/nice": "^1.0.1" + "@napi-rs/nice": "^1.0.4" } }, "node_modules/pkce-challenge": { @@ -28673,10 +28677,42 @@ "rimraf": "bin.js" } }, + "node_modules/rolldown": { + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.32.tgz", + "integrity": "sha512-vxI2sPN07MMaoYKlFrVva5qZ1Y7DAZkgp7MQwTnyHt4FUMz9Sh+YeCzNFV9JYHI6ZNwoGWLCfCViE3XVsRC1cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/runtime": "=0.81.0", + "@oxc-project/types": "=0.81.0", + "@rolldown/pluginutils": "1.0.0-beta.32", + "ansis": "^4.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-beta.32", + "@rolldown/binding-darwin-arm64": "1.0.0-beta.32", + "@rolldown/binding-darwin-x64": "1.0.0-beta.32", + "@rolldown/binding-freebsd-x64": "1.0.0-beta.32", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.32", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.32", + "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.32", + "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.32", + "@rolldown/binding-linux-x64-musl": "1.0.0-beta.32", + "@rolldown/binding-openharmony-arm64": "1.0.0-beta.32", + "@rolldown/binding-wasm32-wasi": "1.0.0-beta.32", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.32", + "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.32", + "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.32" + } + }, "node_modules/rollup": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.1.tgz", - "integrity": "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==", + "version": "4.48.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.48.1.tgz", + "integrity": "sha512-jVG20NvbhTYDkGAty2/Yh7HK6/q3DGSRH4o8ALKGArmMuaauM9kLfoMZ+WliPwA5+JHr2lTn3g557FxBV87ifg==", "dev": true, "license": "MIT", "dependencies": { @@ -28690,26 +28726,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.44.1", - "@rollup/rollup-android-arm64": "4.44.1", - "@rollup/rollup-darwin-arm64": "4.44.1", - "@rollup/rollup-darwin-x64": "4.44.1", - "@rollup/rollup-freebsd-arm64": "4.44.1", - "@rollup/rollup-freebsd-x64": "4.44.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.44.1", - "@rollup/rollup-linux-arm-musleabihf": "4.44.1", - "@rollup/rollup-linux-arm64-gnu": "4.44.1", - "@rollup/rollup-linux-arm64-musl": "4.44.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.44.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1", - "@rollup/rollup-linux-riscv64-gnu": "4.44.1", - "@rollup/rollup-linux-riscv64-musl": "4.44.1", - "@rollup/rollup-linux-s390x-gnu": "4.44.1", - "@rollup/rollup-linux-x64-gnu": "4.44.1", - "@rollup/rollup-linux-x64-musl": "4.44.1", - "@rollup/rollup-win32-arm64-msvc": "4.44.1", - "@rollup/rollup-win32-ia32-msvc": "4.44.1", - "@rollup/rollup-win32-x64-msvc": "4.44.1", + "@rollup/rollup-android-arm-eabi": "4.48.1", + "@rollup/rollup-android-arm64": "4.48.1", + "@rollup/rollup-darwin-arm64": "4.48.1", + "@rollup/rollup-darwin-x64": "4.48.1", + "@rollup/rollup-freebsd-arm64": "4.48.1", + "@rollup/rollup-freebsd-x64": "4.48.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.48.1", + "@rollup/rollup-linux-arm-musleabihf": "4.48.1", + "@rollup/rollup-linux-arm64-gnu": "4.48.1", + "@rollup/rollup-linux-arm64-musl": "4.48.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.48.1", + "@rollup/rollup-linux-ppc64-gnu": "4.48.1", + "@rollup/rollup-linux-riscv64-gnu": "4.48.1", + "@rollup/rollup-linux-riscv64-musl": "4.48.1", + "@rollup/rollup-linux-s390x-gnu": "4.48.1", + "@rollup/rollup-linux-x64-gnu": "4.48.1", + "@rollup/rollup-linux-x64-musl": "4.48.1", + "@rollup/rollup-win32-arm64-msvc": "4.48.1", + "@rollup/rollup-win32-ia32-msvc": "4.48.1", + "@rollup/rollup-win32-x64-msvc": "4.48.1", "fsevents": "~2.3.2" } }, @@ -29546,6 +29582,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/semantic-release/node_modules/hosted-git-info": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", + "integrity": "sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/semantic-release/node_modules/human-signals": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", @@ -29614,6 +29664,14 @@ "node": "^18.17 || >=20.6.1" } }, + "node_modules/semantic-release/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC", + "peer": true + }, "node_modules/semantic-release/node_modules/mime": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.7.tgz", @@ -30810,13 +30868,13 @@ } }, "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", "dev": true, "license": "BSD-3-Clause", "engines": { - "node": ">= 8" + "node": ">= 12" } }, "node_modules/source-map-js": { @@ -31735,6 +31793,19 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/svgo/node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/svgo/node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -32153,13 +32224,17 @@ "peer": true }, "node_modules/tapable": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", + "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/tar": { @@ -33105,9 +33180,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, "license": "Apache-2.0", "bin": { @@ -33119,9 +33194,9 @@ } }, "node_modules/ua-parser-js": { - "version": "0.7.40", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.40.tgz", - "integrity": "sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ==", + "version": "0.7.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.41.tgz", + "integrity": "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==", "dev": true, "funding": [ { @@ -33898,9 +33973,9 @@ } }, "node_modules/vite": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.6.tgz", - "integrity": "sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.2.tgz", + "integrity": "sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==", "dev": true, "license": "MIT", "dependencies": { @@ -33908,7 +33983,7 @@ "fdir": "^6.4.6", "picomatch": "^4.0.3", "postcss": "^8.5.6", - "rollup": "^4.40.0", + "rollup": "^4.43.0", "tinyglobby": "^0.2.14" }, "bin": { @@ -33972,19 +34047,6 @@ } } }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/void-elements": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", @@ -34168,9 +34230,9 @@ "license": "BSD-2-Clause" }, "node_modules/webpack": { - "version": "5.101.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.2.tgz", - "integrity": "sha512-4JLXU0tD6OZNVqlwzm3HGEhAHufSiyv+skb7q0d2367VDMzrU1Q/ZeepvkcHH0rZie6uqEtTQQe0OEOOluH3Mg==", + "version": "5.101.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.3.tgz", + "integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==", "dev": true, "license": "MIT", "peer": true, @@ -35361,6 +35423,22 @@ } } }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/xml2js": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", @@ -35528,9 +35606,9 @@ } }, "node_modules/yoctocolors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", - "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", "dev": true, "license": "MIT", "peer": true, @@ -35542,9 +35620,9 @@ } }, "node_modules/yoctocolors-cjs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", - "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", "dev": true, "license": "MIT", "engines": { @@ -35555,9 +35633,9 @@ } }, "node_modules/zod": { - "version": "3.25.75", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.75.tgz", - "integrity": "sha512-OhpzAmVzabPOL6C3A3gpAifqr9MqihV/Msx3gor2b2kviCgcb+HM9SEOpMWwwNp9MRunWnhtAKUoo0AHhjyPPg==", + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "dev": true, "license": "MIT", "funding": { diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 85975acad2c..0e5ba41938f 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -78,7 +78,7 @@ export class XhrInterceptor implements HttpInterceptor { } @NgModule({ - imports: [RouterModule.forRoot(routes, {}), FormsModule], + imports: [RouterModule.forRoot(routes, { paramsInheritanceStrategy: 'always' }), FormsModule], exports: [RouterModule], providers: [{ provide: HTTP_INTERCEPTORS, useClass: XhrInterceptor, multi: true }] }) diff --git a/src/app/classroom-monitor/component-select/component-select.component.html b/src/app/classroom-monitor/component-select/component-select.component.html deleted file mode 100644 index 858342d923d..00000000000 --- a/src/app/classroom-monitor/component-select/component-select.component.html +++ /dev/null @@ -1,23 +0,0 @@ -@if (components.length == 1) { - -} @else if (components.length > 1) { - - - {{ getSelectedText() }} - - @for (component of components; track component.id; let i = $index) { - - {{ i + 1 }}: {{ getComponentTypeLabel(component.type) }} - - } - - - -} diff --git a/src/app/classroom-monitor/component-select/component-select.component.scss b/src/app/classroom-monitor/component-select/component-select.component.scss deleted file mode 100644 index 101bc930bf6..00000000000 --- a/src/app/classroom-monitor/component-select/component-select.component.scss +++ /dev/null @@ -1,28 +0,0 @@ -@use '@angular/material' as mat; -@use 'style/base/typography'; - -.component-select { - .mdc-line-ripple { - &:before, &:after { - display: none; - } - } - - .mdc-text-field--no-label:not(.mdc-text-field--outlined):not(.mdc-text-field--textarea) .mat-mdc-form-field-infix { - padding-top: 6px; - padding-bottom: 6px; - min-height: 28px; - } - - .mat-mdc-form-field-flex { - height: 36px; - } - - .mat-mdc-select-value-text, .mat-mdc-select-placeholder { - font-size: mat.m2-font-size(typography.$wise-typography, 'caption'); - } - - .mat-mdc-form-field-subscript-wrapper { - display: none; - } -} diff --git a/src/app/classroom-monitor/component-select/component-select.component.ts b/src/app/classroom-monitor/component-select/component-select.component.ts deleted file mode 100644 index ccbb174ef59..00000000000 --- a/src/app/classroom-monitor/component-select/component-select.component.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { - Component, - EventEmitter, - Input, - Output, - SimpleChanges, - ViewEncapsulation -} from '@angular/core'; -import { ComponentTypeService } from '../../../assets/wise5/services/componentTypeService'; -import { TeacherProjectService } from '../../../assets/wise5/services/teacherProjectService'; -import { FormsModule } from '@angular/forms'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatSelectModule } from '@angular/material/select'; -import { MatButtonModule } from '@angular/material/button'; - -@Component({ - encapsulation: ViewEncapsulation.None, - imports: [FormsModule, MatButtonModule, MatFormFieldModule, MatSelectModule], - selector: 'component-select', - styleUrl: 'component-select.component.scss', - templateUrl: 'component-select.component.html' -}) -export class ComponentSelectComponent { - protected components: any[]; - @Output() modelChange: EventEmitter = new EventEmitter(); - @Input() nodeId: string; - protected selectedComponents: any[]; - - constructor( - private componentTypeService: ComponentTypeService, - private projectService: TeacherProjectService - ) {} - - ngOnChanges(changes: SimpleChanges): void { - this.nodeId = changes.nodeId.currentValue; - this.components = this.projectService.getComponents(this.nodeId).filter((component) => { - return this.projectService.componentHasWork(component); - }); - this.selectedComponents = this.components.map((component) => { - return component.id; - }); - } - - protected getComponentTypeLabel(componentType: string): string { - return this.componentTypeService.getComponentTypeLabel(componentType); - } - - protected getSelectedText(): string { - return $localize`Showing ${this.selectedComponents.length}/${this.components.length} items`; - } - - protected selectedComponentsChange(): void { - const hiddenComponents = []; - for (const component of this.components) { - const id = component.id; - if (this.selectedComponents.indexOf(id) < 0) { - hiddenComponents.push(id); - } - } - this.modelChange.emit(hiddenComponents); - } -} diff --git a/src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.html b/src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.html deleted file mode 100644 index 568e63eaeca..00000000000 --- a/src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.html +++ /dev/null @@ -1,8 +0,0 @@ -

{{ stepNumberAndTitle }}

- - - - - - - diff --git a/src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.scss b/src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.scss deleted file mode 100644 index 713984189e2..00000000000 --- a/src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.mat-mdc-dialog-content { - border: 1px solid lightgrey; -} \ No newline at end of file diff --git a/src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.spec.ts b/src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.spec.ts deleted file mode 100644 index f4895ceea0d..00000000000 --- a/src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.spec.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; -import { ClassroomMonitorTestingModule } from '../../../assets/wise5/classroomMonitor/classroom-monitor-testing.module'; -import { NotebookService } from '../../../assets/wise5/services/notebookService'; -import { ProjectService } from '../../../assets/wise5/services/projectService'; -import { TeacherDataService } from '../../../assets/wise5/services/teacherDataService'; -import { TeacherProjectService } from '../../../assets/wise5/services/teacherProjectService'; -import { VLEProjectService } from '../../../assets/wise5/vle/vleProjectService'; -import { ShowNodeInfoDialogComponent } from './show-node-info-dialog.component'; -import { ComponentTypeServiceModule } from '../../../assets/wise5/services/componentTypeService.module'; - -let component: ShowNodeInfoDialogComponent; -const componentRubric: string = 'This is the component rubric.'; -let fixture: ComponentFixture; -const nodeId1: string = 'node1'; -const prompt: string = 'This is the prompt.'; -const stepRubric: string = 'This is the step rubric.'; -const stepTitle: string = 'This is the title'; -const node: any = { - components: [ - { - id: 'component1', - type: 'OpenResponse', - prompt: prompt, - rubric: componentRubric - } - ], - id: nodeId1, - rubric: stepRubric, - title: stepTitle -}; - -describe('ShowNodeInfoDialogComponents', () => { - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - ClassroomMonitorTestingModule, - ComponentTypeServiceModule, - ShowNodeInfoDialogComponent - ], - providers: [ - { provide: MAT_DIALOG_DATA, useValue: nodeId1 }, - { provide: MatDialogRef, useValue: {} } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(ShowNodeInfoDialogComponent); - component = fixture.componentInstance; - component.nodeId = nodeId1; - spyOn(TestBed.inject(TeacherDataService), 'getCurrentPeriodId').and.returnValue(1); - spyOn(TestBed.inject(TeacherProjectService), 'getNodeById').and.returnValue(node); - spyOn(TestBed.inject(ProjectService), 'getThemeSettings').and.returnValue({}); - spyOn(TestBed.inject(ProjectService), 'getNodeById').and.returnValue(node); - spyOn(TestBed.inject(ProjectService), 'getNodePositionById').and.returnValue('1.1'); - spyOn(TestBed.inject(VLEProjectService), 'getSpaces').and.returnValue([]); - spyOn(TestBed.inject(ProjectService), 'getSpeechToTextSettings').and.returnValue({}); - spyOn(TestBed.inject(NotebookService), 'isNotebookEnabled').and.returnValue(false); - fixture.detectChanges(); - }); - - it('should render the step content in the dialog', () => { - expect(fixture.debugElement.nativeElement.innerHTML).toContain(stepTitle); - expect(fixture.debugElement.nativeElement.innerHTML).toContain(prompt); - expect(fixture.debugElement.nativeElement.innerHTML).toContain(stepRubric); - expect(fixture.debugElement.nativeElement.innerHTML).toContain(componentRubric); - }); -}); diff --git a/src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.ts b/src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.ts deleted file mode 100644 index a6de55feae0..00000000000 --- a/src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core'; -import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; -import { MatButtonModule } from '@angular/material/button'; -import { ProjectService } from '../../../assets/wise5/services/projectService'; -import { NodeInfoComponent } from '../../../assets/wise5/classroomMonitor/classroomMonitorComponents/shared/node-info/node-info.component'; - -@Component({ - imports: [MatButtonModule, MatDialogModule, NodeInfoComponent], - selector: 'show-node-info-dialog', - templateUrl: './show-node-info-dialog.component.html', - styleUrl: './show-node-info-dialog.component.scss' -}) -export class ShowNodeInfoDialogComponent implements OnInit { - @ViewChild('nodeInfoDiv') nodeInfoDiv: ElementRef; - protected stepNumberAndTitle: string; - - constructor( - public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public nodeId: string, - private projectService: ProjectService - ) {} - - ngOnInit(): void { - this.stepNumberAndTitle = this.projectService.getNodePositionAndTitle(this.nodeId); - } - - protected openInNewWindow(): void { - const newWindow = window.open('', '_blank'); - newWindow.document.write(this.generateHtmlForNewWindow()); - } - - private generateHtmlForNewWindow(): string { - return ` - - - -
-

- ${this.stepNumberAndTitle} -

-
${this.nodeInfoDiv.nativeElement.innerHTML}
-
- `; - } - - protected close(): void { - this.dialogRef.close(); - } -} diff --git a/src/app/services/milestone/milestoneService.spec.ts b/src/app/services/milestone/milestoneService.spec.ts index 380b5c44dc2..6d36d983078 100644 --- a/src/app/services/milestone/milestoneService.spec.ts +++ b/src/app/services/milestone/milestoneService.spec.ts @@ -27,8 +27,8 @@ let teacherDataService: TeacherDataService; describe('MilestoneService', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [MatDialogModule, StudentTeacherCommonServicesModule], - providers: [ + imports: [MatDialogModule, StudentTeacherCommonServicesModule], + providers: [ ClassroomStatusService, CopyNodesService, MilestoneService, @@ -38,8 +38,8 @@ describe('MilestoneService', () => { TeacherWebSocketService, provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting() - ] -}); + ] + }); service = TestBed.inject(MilestoneService); achievementService = TestBed.inject(AchievementService); configService = TestBed.inject(ConfigService); @@ -48,7 +48,6 @@ describe('MilestoneService', () => { teacherDataService = TestBed.inject(TeacherDataService); }); getProjectMilestones(); - getMilestoneReportByNodeId(); getProjectMilestoneStatus(); insertMilestoneItems(); insertMilestoneCompletion(); @@ -85,63 +84,6 @@ function getProjectMilestones() { }); } -function getMilestoneReportByNodeId() { - describe('getMilestoneReportByNodeId()', () => { - it('should get project milestone report by node id when there is none', () => { - const achievements = { - isEnabled: true, - items: [ - { - id: 'milestone1', - type: 'milestone', - report: { - templates: [ - { - satisfyCriteria: [ - { - nodeId: 'node1', - componentId: 'component1' - } - ] - } - ] - } - } - ] - }; - spyOn(projectService, 'getAchievements').and.returnValue(achievements); - const milestoneReport = service.getMilestoneReportByNodeId('node2'); - expect(milestoneReport).toBeNull(); - }); - it('should get project milestone report by node id when there is one', () => { - const achievements = { - isEnabled: true, - items: [ - { - id: 'milestone1', - type: 'milestone', - report: { - templates: [ - { - satisfyCriteria: [ - { - nodeId: 'node1', - componentId: 'component1' - } - ] - } - ] - } - } - ] - }; - spyOn(projectService, 'getAchievements').and.returnValue(achievements); - const milestoneReport = service.getMilestoneReportByNodeId('node1'); - expect(milestoneReport).toBeDefined(); - }); - }); -} - function getProjectMilestoneStatus() { describe('getProjectMilestoneStatus()', () => { it('should get project milestone status', () => { diff --git a/src/app/services/workgroup.service.ts b/src/app/services/workgroup.service.ts index d8181f23c51..3edccefe95d 100644 --- a/src/app/services/workgroup.service.ts +++ b/src/app/services/workgroup.service.ts @@ -5,11 +5,14 @@ import { ConfigService } from '../../assets/wise5/services/configService'; @Injectable() export class WorkgroupService { - constructor(private ConfigService: ConfigService, private http: HttpClient) {} + constructor( + private ConfigService: ConfigService, + private http: HttpClient + ) {} getWorkgroupsInPeriod(periodId: number): Map { const workgroups = new Map(); for (const workgroup of this.getWorkgroupsSortedById()) { - if (workgroup.periodId === periodId && workgroup.workgroupId != null) { + if (periodId === -1 || (workgroup.periodId === periodId && workgroup.workgroupId != null)) { workgroup.displayNames = this.ConfigService.getDisplayUsernamesByWorkgroupId( workgroup.workgroupId ); diff --git a/src/app/teacher/classroom-monitor.module.ts b/src/app/teacher/classroom-monitor.module.ts index 3e9bead2055..f927ffde619 100644 --- a/src/app/teacher/classroom-monitor.module.ts +++ b/src/app/teacher/classroom-monitor.module.ts @@ -1,15 +1,12 @@ import { NgModule } from '@angular/core'; import { ComponentNewWorkBadgeComponent } from '../classroom-monitor/component-new-work-badge/component-new-work-badge.component'; -import { ComponentSelectComponent } from '../classroom-monitor/component-select/component-select.component'; import { PeerGroupGradingModule } from './peer-group-grading.module'; -import { TeacherSummaryDisplayComponent } from '../../assets/wise5/directives/teacher-summary-display/teacher-summary-display.component'; import { HighchartsChartModule } from 'highcharts-angular'; import { StudentTeacherCommonModule } from '../student-teacher-common.module'; import { ComponentStudentModule } from '../../assets/wise5/components/component/component-student.module'; import { NotebookWorkgroupGradingComponent } from '../../assets/wise5/classroomMonitor/classroomMonitorComponents/notebook/notebook-workgroup-grading/notebook-workgroup-grading.component'; import { PauseScreensMenuComponent } from '../../assets/wise5/classroomMonitor/classroomMonitorComponents/pause-screens-menu/pause-screens-menu.component'; import { StepItemComponent } from '../../assets/wise5/classroomMonitor/classroomMonitorComponents/studentGrading/step-item/step-item.component'; -import { NodeGradingViewComponent } from '../../assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component'; import { NotificationsMenuComponent } from '../../assets/wise5/classroomMonitor/classroomMonitorComponents/shared/notifications-menu/notifications-menu.component'; import { NavItemComponent } from '../../assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/nav-item/nav-item.component'; import { NodeProgressViewComponent } from '../../assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component'; @@ -17,7 +14,6 @@ import { NotebookGradingComponent } from '../../assets/wise5/classroomMonitor/no import { StudentGradingComponent } from '../../assets/wise5/classroomMonitor/student-grading/student-grading.component'; import { StudentProgressComponent } from '../../assets/wise5/classroomMonitor/student-progress/student-progress.component'; import { ClassroomMonitorComponent } from '../../assets/wise5/classroomMonitor/classroom-monitor.component'; -import { ShowNodeInfoDialogComponent } from '../classroom-monitor/show-node-info-dialog/show-node-info-dialog.component'; import { MilestoneModule } from './milestone/milestone.module'; import { GradingCommonModule } from './grading-common.module'; import { ManageStudentsModule } from '../../assets/wise5/classroomMonitor/classroomMonitorComponents/manageStudents/manage-students.module'; @@ -30,7 +26,6 @@ import { GradingNodeService } from '../../assets/wise5/services/gradingNodeServi @NgModule({ declarations: [ - NodeGradingViewComponent, NodeProgressViewComponent, NotebookGradingComponent, NotebookWorkgroupGradingComponent, @@ -40,7 +35,6 @@ import { GradingNodeService } from '../../assets/wise5/services/gradingNodeServi ClassroomMonitorComponent, ComponentGradingComponent, ComponentNewWorkBadgeComponent, - ComponentSelectComponent, ComponentStudentModule, DataExportModule, GradingCommonModule, @@ -54,11 +48,9 @@ import { GradingNodeService } from '../../assets/wise5/services/gradingNodeServi PreviewComponentComponent, RouterModule, SelectPeriodComponent, - ShowNodeInfoDialogComponent, StepItemComponent, StudentProgressComponent, - StudentTeacherCommonModule, - TeacherSummaryDisplayComponent + StudentTeacherCommonModule ], providers: [GradingNodeService] }) diff --git a/src/app/teacher/milestone/milestone.module.ts b/src/app/teacher/milestone/milestone.module.ts index 47b34e74d1c..368758d65ab 100644 --- a/src/app/teacher/milestone/milestone.module.ts +++ b/src/app/teacher/milestone/milestone.module.ts @@ -3,7 +3,7 @@ import { createCustomElement } from '@angular/elements'; import { HighchartsChartModule } from 'highcharts-angular'; import { MilestoneDetailsDialogComponent } from '../../../assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-details-dialog/milestone-details-dialog.component'; import { MilestoneDetailsComponent } from '../../../assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-details/milestone-details.component'; -import { MilestoneGradingViewComponent } from '../../../assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component'; +import { MilestoneClassResponsesComponent } from '../../../assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component'; import { MilestoneWorkgroupItemComponent } from '../../../assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-workgroup-item/milestone-workgroup-item.component'; import { MilestonesComponent } from '../../classroom-monitor/milestones/milestones.component'; import { StudentTeacherCommonModule } from '../../student-teacher-common.module'; @@ -23,7 +23,7 @@ import { SelectPeriodComponent } from '../../../assets/wise5/classroomMonitor/cl MilestonesComponent, MilestoneDetailsComponent, MilestoneDetailsDialogComponent, - MilestoneGradingViewComponent, + MilestoneClassResponsesComponent, MilestoneReportDataComponent, MilestoneReportGraphComponent, MilestoneWorkgroupItemComponent diff --git a/src/app/teacher/teacher-authoring.module.ts b/src/app/teacher/teacher-authoring.module.ts index 3cf872a6683..efbcbdd07a4 100644 --- a/src/app/teacher/teacher-authoring.module.ts +++ b/src/app/teacher/teacher-authoring.module.ts @@ -40,9 +40,10 @@ import { NotifyAuthorService } from '../../assets/wise5/services/notifyAuthorSer import { RemoveNodeIdFromTransitionsService } from '../../assets/wise5/services/removeNodeIdFromTransitionsService'; import { RegisterProjectService } from '../../assets/wise5/services/registerProjectService'; import { ComponentAuthoringModule } from './component-authoring.module'; +import { StudentTeacherCommonServicesModule } from '../student-teacher-common-services.module'; @NgModule({ - imports: [AuthoringRoutingModule, ComponentAuthoringModule], + imports: [AuthoringRoutingModule, ComponentAuthoringModule, StudentTeacherCommonServicesModule], providers: [ ClassroomStatusService, ComponentInfoService, diff --git a/src/app/teacher/teacher-tools-routing.module.ts b/src/app/teacher/teacher-tools-routing.module.ts index bd2909e17a0..1f7761f8f85 100644 --- a/src/app/teacher/teacher-tools-routing.module.ts +++ b/src/app/teacher/teacher-tools-routing.module.ts @@ -16,6 +16,7 @@ import { ExportRawDataComponent } from '../../assets/wise5/classroomMonitor/data import { ExportEventsComponent } from '../../assets/wise5/classroomMonitor/dataExport/export-events/export-events.component'; import { ExportOneWorkgroupPerRowComponent } from '../../assets/wise5/classroomMonitor/dataExport/export-one-workgroup-per-row/export-one-workgroup-per-row.component'; import { ExportStudentWorkComponent } from '../../assets/wise5/classroomMonitor/dataExport/export-student-work/export-student-work.component'; +import { NodeGradingComponent } from '../../assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component'; const routes: Routes = [ { @@ -33,7 +34,11 @@ const routes: Routes = [ { path: 'export/visits', component: ExportStepVisitsComponent }, { path: 'manage-students', component: ManageStudentsComponent }, { path: 'milestones', component: MilestonesComponent }, - { path: 'node/:nodeId', component: NodeProgressViewComponent }, + { path: 'group/:nodeId', component: NodeProgressViewComponent }, + { + path: 'node/:nodeId', + component: NodeGradingComponent + }, { path: 'notebook', component: NotebookGradingComponent }, { path: 'team', diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/AbstractClassResponsesComponent.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/AbstractClassResponsesComponent.ts new file mode 100644 index 00000000000..f515ba11ba6 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/AbstractClassResponsesComponent.ts @@ -0,0 +1,184 @@ +import { Directive } from '@angular/core'; +import { AnnotationService } from '../../services/annotationService'; +import { ClassroomStatusService } from '../../services/classroomStatusService'; +import { ConfigService } from '../../services/configService'; +import { NotificationService } from '../../services/notificationService'; +import { TeacherDataService } from '../../services/teacherDataService'; +import { TeacherProjectService } from '../../services/teacherProjectService'; +import { Node } from '../../common/Node'; +import { copy } from '../../common/object/object'; +import { CompletionStatus } from './shared/CompletionStatus'; + +@Directive() +export abstract class AbstractClassResponsesComponent { + protected allWorkgroupsExpanded: boolean; + protected component: any; + protected node: Node; + protected sortBy: string; + protected sortedWorkgroups: any[] = []; + protected workgroups: any[] = []; + protected workgroupExpanded: Record = {}; // workgroup is expanded or not + private workgroupInView: Record = {}; // workgroup is in view or not + protected workgroupsById: Record = {}; + + constructor( + protected annotationService: AnnotationService, + protected classroomStatusService: ClassroomStatusService, + protected configService: ConfigService, + protected dataService: TeacherDataService, + protected notificationService: NotificationService, + protected projectService: TeacherProjectService + ) {} + + protected retrieveStudentData(node: Node): void { + this.dataService.retrieveStudentDataForNode(node).subscribe(() => { + this.workgroups = copy(this.configService.getClassmateUserInfos()).filter( + (workgroup) => + workgroup.workgroupId != null && + this.classroomStatusService.hasStudentStatus(workgroup.workgroupId) + ); + this.setWorkgroupsById(); + this.sortBy = ''; + this.sortWorkgroups('workgroupId'); + document.body.scrollTop = document.documentElement.scrollTop = 0; + }); + } + + protected setWorkgroupsById(): void { + this.workgroups.forEach((workgroup) => { + this.workgroupsById[workgroup.workgroupId] = workgroup; + this.workgroupExpanded[workgroup.workgroupId] = false; + if (this.component) { + this.updateWorkgroup(workgroup); + } + }); + } + + protected updateWorkgroup(workgroup: any): void { + const alertNotifications = this.notificationService.getAlertNotifications({ + nodeId: this.node.id, + toWorkgroupId: workgroup.workgroupId + }); + workgroup.hasAlert = alertNotifications.length > 0; + workgroup.hasNewAlert = alertNotifications.some((alert) => !alert.timeDismissed); + const completionStatus = this.getCompletionStatus(workgroup.workgroupId); + workgroup.isVisible = completionStatus.isVisible ? 1 : 0; + workgroup.completionStatus = completionStatus.getStateNumber(); + const studentStatus = this.classroomStatusService.getStudentStatusForWorkgroupId( + workgroup.workgroupId + ); + workgroup.nodeStatus = studentStatus.nodeStatuses[this.node.id] || {}; + workgroup.score = this.getWorkgroupScore(workgroup.workgroupId); + } + + private getCompletionStatus(workgroupId: number): CompletionStatus { + const studentStatus = this.classroomStatusService.getStudentStatusForWorkgroupId(workgroupId); + return studentStatus != null && studentStatus.nodeStatuses[this.node.id] != null + ? this.createCompletionStatus(studentStatus.nodeStatuses[this.node.id], workgroupId) + : new CompletionStatus(); + } + + private createCompletionStatus(nodeStatus: any, workgroupId: number): CompletionStatus { + const completionStatus: CompletionStatus = new CompletionStatus(); + completionStatus.isVisible = nodeStatus.isVisible; + completionStatus.latestWorkTime = this.getLatestWorkTimeByWorkgroupId(workgroupId); + completionStatus.latestAnnotationTime = this.getLatestAnnotationTimeByWorkgroupId(workgroupId); + if (!this.hasWork()) { + completionStatus.isCompleted = nodeStatus.isVisited; + } + if (completionStatus.latestWorkTime) { + completionStatus.isCompleted = this.isCompleted(workgroupId, nodeStatus); + } + return completionStatus; + } + + protected abstract getWorkgroupScore(workgroupId: number): number; + + protected abstract hasWork(): boolean; + + protected abstract isCompleted(workgroupId: number, nodeStatus: any): boolean; + + private getLatestWorkTimeByWorkgroupId(workgroupId: number): string { + return ( + this.getComponentStates().findLast( + (componentState) => componentState.workgroupId === workgroupId + )?.serverSaveTime ?? null + ); + } + + protected abstract getComponentStates(): any[]; + + private getLatestAnnotationTimeByWorkgroupId(workgroupId: number): string { + return ( + this.dataService + .getAnnotationsByNodeId(this.node.id) + .findLast((annotation) => this.isAnnotationForWorkgroup(annotation, workgroupId)) + ?.serverSaveTime ?? null + ); + } + + protected isAnnotationForWorkgroup(annotation: any, workgroupId: number): boolean { + return ( + annotation.toWorkgroupId === workgroupId && + annotation.fromWorkgroupId === this.configService.getWorkgroupId() + ); + } + + protected sortWorkgroups(sortBy: string): void { + this.sortBy = this.sortBy === sortBy ? `-${sortBy}` : sortBy; + this.sortedWorkgroups = [...this.workgroups].sort(this.createSortFunction()); + } + + private createSortFunction(): (workgroupA: any, workgroupB: any) => number { + return (workgroupA: any, workgroupB: any) => { + const ascending = this.sortBy[0] !== '-'; + const fieldName = this.sortBy.replace('-', ''); + if (workgroupA.isVisible === workgroupB.isVisible) { + if (workgroupA[fieldName] === workgroupB[fieldName]) { + return workgroupA.workgroupId - workgroupB.workgroupId; + } else { + return ascending + ? workgroupA[fieldName] - workgroupB[fieldName] + : workgroupB[fieldName] - workgroupA[fieldName]; + } + } else { + return workgroupB.isVisible - workgroupA.isVisible; + } + }; + } + + protected onIntersection( + workgroupId: number, + intersectionObserverEntries: IntersectionObserverEntry[] + ): void { + intersectionObserverEntries.forEach((entry) => { + this.workgroupInView[workgroupId] = entry.isIntersecting; + if (this.allWorkgroupsExpanded && entry.isIntersecting) { + this.workgroupExpanded[workgroupId] = true; + } + }); + } + + protected onUpdateExpand({ workgroupId, value: expanded }): void { + this.workgroupExpanded[workgroupId] = expanded; + if (!expanded) { + this.allWorkgroupsExpanded = false; + } + } + + protected isWorkgroupShown(workgroup: any): boolean { + return this.dataService.isWorkgroupShown(workgroup); + } + + protected collapseAll(): void { + this.workgroups.forEach((workgroup) => (this.workgroupExpanded[workgroup.workgroupId] = false)); + this.allWorkgroupsExpanded = false; + } + + protected expandAll(): void { + this.workgroups + .filter((workgroup) => this.workgroupInView[workgroup.workgroupId]) + .forEach((workgroup) => (this.workgroupExpanded[workgroup.workgroupId] = true)); + this.allWorkgroupsExpanded = true; + } +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-completion/component-completion.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-completion/component-completion.component.html new file mode 100644 index 00000000000..a8cb48cccc8 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-completion/component-completion.component.html @@ -0,0 +1,13 @@ +
+
+ +
+
Responses: {{ numWorkgroupsCompleted }}
+
diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-completion/component-completion.component.spec.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-completion/component-completion.component.spec.ts new file mode 100644 index 00000000000..c5af15a40a9 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-completion/component-completion.component.spec.ts @@ -0,0 +1,83 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Node } from '../../../common/Node'; +import { MockProviders } from 'ng-mocks'; +import { WorkgroupService } from '../../../../../app/services/workgroup.service'; +import { ComponentServiceLookupService } from '../../../services/componentServiceLookupService'; +import { TeacherDataService } from '../../../services/teacherDataService'; +import { MultipleChoiceService } from '../../../components/multipleChoice/multipleChoiceService'; +import { ComponentCompletionComponent } from './component-completion.component'; +import { ClassroomStatusService } from '../../../services/classroomStatusService'; + +let component: ComponentCompletionComponent; +let fixture: ComponentFixture; +let workgroupService: WorkgroupService; +let componentServiceLookupService: ComponentServiceLookupService; +let teacherDataService: TeacherDataService; +let classroomStatusService: ClassroomStatusService; +describe('ComponentCompletionComponent', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ComponentCompletionComponent], + providers: [ + MockProviders( + ClassroomStatusService, + ComponentServiceLookupService, + MultipleChoiceService, + TeacherDataService, + WorkgroupService + ) + ] + }).compileComponents(); + + fixture = TestBed.createComponent(ComponentCompletionComponent); + component = fixture.componentInstance; + component.component = { id: 'component1', maxScore: 10 }; + component.node = { id: 'node1' } as Node; + component.periodId = 1; + workgroupService = TestBed.inject(WorkgroupService); + componentServiceLookupService = TestBed.inject(ComponentServiceLookupService); + teacherDataService = TestBed.inject(TeacherDataService); + classroomStatusService = TestBed.inject(ClassroomStatusService); + }); + ngOnChanges(); +}); + +function ngOnChanges() { + describe('ngOnChanges()', () => { + beforeEach(() => { + const workgroups = new Map(); + workgroups.set(1, {}); + workgroups.set(2, {}); + spyOn(workgroupService, 'getWorkgroupsInPeriod').and.returnValue(workgroups); + spyOn(componentServiceLookupService, 'getService').and.returnValue( + new MultipleChoiceService() + ); + spyOn(classroomStatusService, 'hasStudentStatus').and.returnValue(true); + }); + describe('no student completed this work', () => { + beforeEach(() => + spyOn(teacherDataService, 'getComponentStatesByWorkgroupIdAndComponentId').and.returnValue( + [] + ) + ); + it('shows "Responses: 0"', () => { + component.ngOnChanges(); + fixture.detectChanges(); + expect(fixture.nativeElement.textContent.trim()).toEqual('Responses: 0'); + }); + }); + describe('one of the students completed this work', () => { + beforeEach(() => + spyOn(teacherDataService, 'getComponentStatesByWorkgroupIdAndComponentId').and.returnValues( + [], + [{ studentData: { studentChoices: [{ id: 'choice1' }] } }] + ) + ); + it('shows "Responses: 1"', () => { + component.ngOnChanges(); + fixture.detectChanges(); + expect(fixture.nativeElement.textContent.trim()).toEqual('Responses: 1'); + }); + }); + }); +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-completion/component-completion.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-completion/component-completion.component.ts new file mode 100644 index 00000000000..7e5bf8f8d91 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-completion/component-completion.component.ts @@ -0,0 +1,64 @@ +import { Component, Input } from '@angular/core'; +import { Node } from '../../../common/Node'; +import { WorkgroupService } from '../../../../../app/services/workgroup.service'; +import { TeacherDataService } from '../../../services/teacherDataService'; +import { ComponentServiceLookupService } from '../../../services/componentServiceLookupService'; +import { ClassroomStatusService } from '../../../services/classroomStatusService'; +import { MatProgressBarModule } from '@angular/material/progress-bar'; +import { MatTooltipModule } from '@angular/material/tooltip'; + +@Component({ + imports: [MatProgressBarModule, MatTooltipModule], + selector: 'component-completion', + templateUrl: 'component-completion.component.html' +}) +export class ComponentCompletionComponent { + protected completion: number; + @Input() component: any; + @Input() node: Node; + protected numWorkgroupsCompleted: number; + @Input() periodId: number; + protected workgroups: Map; + + constructor( + private componentServiceLookupService: ComponentServiceLookupService, + private dataService: TeacherDataService, + private statusService: ClassroomStatusService, + private workgroupService: WorkgroupService + ) {} + + ngOnChanges(): void { + if (this.component && this.node) { + this.workgroups = new Map( + Array.from(this.workgroupService.getWorkgroupsInPeriod(this.periodId)).filter( + ([workgroupId]) => this.statusService.hasStudentStatus(workgroupId) + ) + ); + this.numWorkgroupsCompleted = Array.from(this.workgroups.keys()).filter((workgroupId) => + this.isCompleted(workgroupId) + ).length; + this.completion = + this.workgroups.size > 0 + ? Math.round((this.numWorkgroupsCompleted / this.workgroups.size) * 100) + : 0; + } + } + + private isCompleted(workgroupId: number): boolean { + const service = this.componentServiceLookupService.getService(this.component.type); + const componentStates = this.dataService.getComponentStatesByWorkgroupIdAndComponentId( + workgroupId, + this.component.id + ); + return ['OpenResponse', 'Discussion'].includes(this.component.type) + ? service.isCompletedV2(this.node, this.component, { + componentStates: componentStates + }) + : service.isCompleted( + this.component, + componentStates, + this.dataService.getEventsByNodeId(this.node.id), + this.node + ); + } +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.html new file mode 100644 index 00000000000..d55a651f101 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.html @@ -0,0 +1,78 @@ +
+
+
+
Prompt
+ @if (component.prompt) { +
+ } @else { +
-
+ } +
+ @if (hasStudentWork) { +
+ +
+ } +
+
+ + +
+ @if (hasSummaryData) { +
+ @if (hasScoresSummary && hasScoreAnnotation) { + + } + @if (component?.type === 'MultipleChoice' && hasStudentWork) { + + } + @if (hasIdeaRubricData) { + + + + + + } + @if (component?.type === 'Match') { + + + + + + } +
+ } +
diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.scss b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.scss new file mode 100644 index 00000000000..c45924fdabe --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.scss @@ -0,0 +1,28 @@ +.component-summary { + .notice { + max-width: none; + margin: 0; + } + + .mat-body-1 { + margin-bottom: 0; + } + + .mat-mdc-card-content:last-child { + padding-bottom: 12px; + } + + .mat-mdc-card-content:first-child { + padding-top: 12px; + } + + .mat-mdc-card-content { + padding: 0 12px; + } + + milestone-report-button > *, + peer-group-button > * { + margin-top: 12px; + margin-inline-end: 8px; + } +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.spec.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.spec.ts new file mode 100644 index 00000000000..3efa31d2f3a --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.spec.ts @@ -0,0 +1,79 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentSummaryComponent } from './component-summary.component'; +import { ActivatedRoute } from '@angular/router'; +import { of } from 'rxjs'; +import { MockComponents, MockProvider, MockProviders } from 'ng-mocks'; +import { MilestoneReportButtonComponent } from '../milestone-report-button/milestone-report-button.component'; +import { ComponentCompletionComponent } from '../component-completion/component-completion.component'; +import { By } from '@angular/platform-browser'; +import { AnnotationService } from '../../../services/annotationService'; +import { ComponentServiceLookupService } from '../../../services/componentServiceLookupService'; +import { CRaterService } from '../../../services/cRaterService'; +import { TeacherDataService } from '../../../services/teacherDataService'; +import { SummaryService } from '../../../components/summary/summaryService'; +import { PeerGroupButtonComponent } from '../peer-group-button/peer-group-button.component'; + +let component: ComponentSummaryComponent; +let fixture: ComponentFixture; +describe('ComponentSummaryComponent', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ + ComponentSummaryComponent, + MockComponents( + ComponentCompletionComponent, + MilestoneReportButtonComponent, + PeerGroupButtonComponent + ) + ], + providers: [ + MockProviders( + AnnotationService, + ComponentServiceLookupService, + CRaterService, + SummaryService + ), + MockProvider(TeacherDataService, { + currentPeriodChanged$: of({ currentPeriod: { periodId: 1 } }) + }), + { provide: ActivatedRoute, useValue: { parent: { params: of({ nodeId: 'node1' }) } } } + ] + }).compileComponents(); + + fixture = TestBed.createComponent(ComponentSummaryComponent); + component = fixture.componentInstance; + component.node = { id: 'node1', title: 'Node 1' } as any; + component.component = { id: 'abc', prompt: 'hi' } as any; + fixture.detectChanges(); + }); + testHasStudentWork(); + testNoStudentWork(); +}); + +function testHasStudentWork() { + describe('has student work', () => { + beforeEach(() => { + component['hasStudentWork'] = true; + fixture.detectChanges(); + }); + it('should show component completion', () => { + expect(getComponentCompletion()).toBeTruthy(); + }); + }); +} + +function testNoStudentWork() { + describe('no student work', () => { + beforeEach(() => { + component['hasStudentWork'] = false; + fixture.detectChanges(); + }); + it('should not show component completion', () => { + expect(getComponentCompletion()).toBeFalsy(); + }); + }); +} + +function getComponentCompletion() { + return fixture.debugElement.query(By.css('component-completion')); +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.ts new file mode 100644 index 00000000000..2fa2c1ff40b --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.ts @@ -0,0 +1,116 @@ +import { Component, Input, ViewEncapsulation } from '@angular/core'; +import { TeacherSummaryDisplayComponent } from '../../../directives/teacher-summary-display/teacher-summary-display.component'; +import { ComponentServiceLookupService } from '../../../services/componentServiceLookupService'; +import { SummaryService } from '../../../components/summary/summaryService'; +import { TeacherDataService } from '../../../services/teacherDataService'; +import { isMatchingPeriods } from '../../../common/period/period'; +import { AnnotationService } from '../../../services/annotationService'; +import { Node } from '../../../common/Node'; +import { MilestoneReportButtonComponent } from '../milestone-report-button/milestone-report-button.component'; +import { PeerGroupButtonComponent } from '../peer-group-button/peer-group-button.component'; +import { ComponentCompletionComponent } from '../component-completion/component-completion.component'; +import { ComponentContent } from '../../../common/ComponentContent'; +import { IdeasSummaryComponent } from '../../../directives/teacher-summary-display/ideas-summary-display/ideas-summary.component'; +import { MatchSummaryDisplayComponent } from '../../../directives/teacher-summary-display/match-summary-display/match-summary-display.component'; +import { MatCardModule } from '@angular/material/card'; +import { CRaterService } from '../../../services/cRaterService'; + +@Component({ + imports: [ + ComponentCompletionComponent, + IdeasSummaryComponent, + MatCardModule, + MatchSummaryDisplayComponent, + MilestoneReportButtonComponent, + PeerGroupButtonComponent, + TeacherSummaryDisplayComponent + ], + selector: 'component-summary', + styleUrl: './component-summary.component.scss', + templateUrl: './component-summary.component.html', + encapsulation: ViewEncapsulation.None +}) +export class ComponentSummaryComponent { + protected avgScore: number; + @Input() component: ComponentContent; + protected hasCorrectAnswer: boolean; + protected hasScoresSummary: boolean; + protected hasScoreAnnotation: boolean; + protected hasIdeaRubricData: boolean; + protected hasStudentWork: boolean; + protected hasSummaryData: boolean; + @Input() node: Node; + @Input() periodId: number; + protected source: 'allPeriods' | 'period'; + + constructor( + private annotationService: AnnotationService, + private componentServiceLookupService: ComponentServiceLookupService, + private cRaterService: CRaterService, + private dataService: TeacherDataService, + private summaryService: SummaryService + ) {} + + ngOnChanges(): void { + if (this.node && this.component) { + this.dataService.retrieveStudentDataForNode(this.node).subscribe(() => this.setComponent()); + this.setSource(); + const annotations = this.getLatestScoreAnnotations(); + const totalScore = annotations.reduce((sumSoFar, a) => sumSoFar + a.data.value, 0); + this.avgScore = totalScore / annotations.length; + } + } + + private setComponent(): void { + this.hasCorrectAnswer = this.componentHasCorrectAnswer(this.component); + this.hasScoresSummary = this.summaryService.isScoresSummaryAvailableForComponentType( + this.component.type + ); + this.hasScoreAnnotation = this.componentHasScoreAnnotation(this.component.id, this.periodId); + this.hasStudentWork = + this.dataService + .getComponentStatesByComponentId(this.component.id) + .filter((state) => state.periodId === this.periodId).length > 0; + this.hasIdeaRubricData = this.cRaterService + .getCRaterRubric(this.node.id, this.component.id) + .hasRubricData(); + this.hasSummaryData = + (this.component?.type === 'MultipleChoice' && this.hasStudentWork) || + (this.hasScoresSummary && this.hasScoreAnnotation) || + this.hasIdeaRubricData || + this.component?.type === 'Match'; + } + + private setSource(): void { + this.source = this.periodId === -1 ? 'allPeriods' : 'period'; + } + + private componentHasCorrectAnswer(component: any): boolean { + return this.componentServiceLookupService + .getService(component.type) + .componentHasCorrectAnswer(component); + } + + private componentHasScoreAnnotation(componentId: string, periodId: number): boolean { + return this.annotationService + .getAnnotationsByNodeIdComponentId(this.dataService.getCurrentNode().id, componentId) + .some( + (annotation) => + isMatchingPeriods(annotation.periodId, periodId) && + ['score', 'autoScore'].includes(annotation.type) + ); + } + + private getLatestScoreAnnotations() { + return this.annotationService + .getAnnotationsByNodeIdComponentId(this.node.id, this.component.id) + .filter((annotation) => this.periodId === -1 || annotation.periodId === this.periodId) + .filter((annotation) => ['score', 'autoScore'].includes(annotation.type)) + .reduceRight((soFar, currentA) => { + if (!soFar.some((soFarA) => soFarA.toWorkgroupId === currentA.toWorkgroupId)) { + soFar.push(currentA); + } + return soFar; + }, []); + } +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/grading-step-tools/grading-step-tools.component.spec.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/grading-step-tools/grading-step-tools.component.spec.ts index 899b356890c..1ddbf865bad 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/grading-step-tools/grading-step-tools.component.spec.ts +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/grading-step-tools/grading-step-tools.component.spec.ts @@ -1,6 +1,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { GradingStepToolsComponent } from './grading-step-tools.component'; -import { ClassroomMonitorTestingModule } from '../../classroom-monitor-testing.module'; +import { ActivatedRoute, Router } from '@angular/router'; +import { MockComponent, MockProvider, MockProviders } from 'ng-mocks'; +import { TeacherDataService } from '../../../services/teacherDataService'; +import { GradingNodeService } from '../../../services/gradingNodeService'; +import { TeacherProjectService } from '../../../services/teacherProjectService'; +import { of } from 'rxjs'; +import { NodeIconComponent } from '../../../vle/node-icon/node-icon.component'; describe('GradingStepToolsComponent', () => { let component: GradingStepToolsComponent; @@ -8,10 +14,25 @@ describe('GradingStepToolsComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [GradingStepToolsComponent, ClassroomMonitorTestingModule] + imports: [GradingStepToolsComponent, MockComponent(NodeIconComponent)], + providers: [ + MockProviders(GradingNodeService), + MockProvider(TeacherDataService, { + currentNodeChanged$: of() + }), + MockProvider(TeacherProjectService, { + idToOrder: {}, + projectParsed$: of() + }), + { + provide: ActivatedRoute, + useValue: { firstChild: { snapshot: { params: { nodeId: 'nodeId' } } } } + } + ] }).compileComponents(); fixture = TestBed.createComponent(GradingStepToolsComponent); + spyOn(TestBed.inject(Router), 'navigate'); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/grading-step-tools/grading-step-tools.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/grading-step-tools/grading-step-tools.component.ts index e64bedc8539..758a630de89 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/grading-step-tools/grading-step-tools.component.ts +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/grading-step-tools/grading-step-tools.component.ts @@ -14,35 +14,73 @@ import { NodeIconComponent } from '../../../vle/node-icon/node-icon.component'; import { TeacherDataService } from '../../../services/teacherDataService'; import { GradingNodeService } from '../../../services/gradingNodeService'; import { TeacherProjectService } from '../../../services/teacherProjectService'; +import { ActivatedRoute, Router } from '@angular/router'; @Component({ - encapsulation: ViewEncapsulation.None, - imports: [ - CommonModule, - FlexLayoutModule, - FormsModule, - MatButtonModule, - MatFormFieldModule, - MatIconModule, - MatInputModule, - MatSelectModule, - MatTooltipModule, - NodeIconComponent - ], - selector: 'grading-step-tools', - templateUrl: '../../../common/stepTools/step-tools.component.html', - styleUrl: '../../../common/stepTools/step-tools.component.scss' + encapsulation: ViewEncapsulation.None, + imports: [ + CommonModule, + FlexLayoutModule, + FormsModule, + MatButtonModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatSelectModule, + MatTooltipModule, + NodeIconComponent + ], + selector: 'grading-step-tools', + templateUrl: '../../../common/stepTools/step-tools.component.html', + styleUrl: '../../../common/stepTools/step-tools.component.scss' }) export class GradingStepToolsComponent extends StepToolsComponent { constructor( protected dataService: TeacherDataService, protected dir: Directionality, protected nodeService: GradingNodeService, - protected projectService: TeacherProjectService + protected projectService: TeacherProjectService, + private route: ActivatedRoute, + private router: Router ) { super(dataService, dir, nodeService, projectService); } + ngOnInit(): void { + super.ngOnInit(); + this.dataService.setCurrentNodeByNodeId(this.getNodeId()); + } + + protected getNodeId(): string { + return this.route.firstChild.snapshot.params['nodeId']; + } + + protected nodeChanged(): void { + this.navigateToNode(this.nodeId); + } + + protected goToPrevNode(): void { + super.goToPrevNode(); + this.navigateToNode(this.nodeId); + } + + protected goToNextNode(): Promise { + return super.goToNextNode().then(() => { + this.navigateToNode(this.nodeId); + }); + } + + private navigateToNode(nodeId: string): void { + this.router + .navigate(['node', nodeId], { + relativeTo: this.route + }) + .then(() => { + this.dataService.setCurrentNodeByNodeId(nodeId); + this.updateModel(); + }); + } + protected calculateNodeIds(): void { this.nodeIds = Object.keys(this.projectService.idToOrder); this.nodeIds = this.nodeIds.filter((nodeId) => { diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestone-report-button/milestone-report-button.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestone-report-button/milestone-report-button.component.html new file mode 100644 index 00000000000..38d4741d2e3 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestone-report-button/milestone-report-button.component.html @@ -0,0 +1,8 @@ +@if (report?.isReportAvailable) { + +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestone-report-button/milestone-report-button.component.spec.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestone-report-button/milestone-report-button.component.spec.ts new file mode 100644 index 00000000000..2ac5f9906e6 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestone-report-button/milestone-report-button.component.spec.ts @@ -0,0 +1,49 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { MilestoneReportButtonComponent } from './milestone-report-button.component'; +import { MockProvider } from 'ng-mocks'; +import { MilestoneService } from '../../../services/milestoneService'; +import { Node } from '../../../common/Node'; + +let component: MilestoneReportButtonComponent; +let fixture: ComponentFixture; +let milestoneService: MilestoneService; +describe('MilestoneReportButtonComponent', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MilestoneReportButtonComponent], + providers: [MockProvider(MilestoneService)] + }).compileComponents(); + + fixture = TestBed.createComponent(MilestoneReportButtonComponent); + component = fixture.componentInstance; + component.node = { id: 'node1' } as Node; + component.component = { id: 'abc' }; + milestoneService = TestBed.inject(MilestoneService); + fixture.detectChanges(); + }); + reportAvailable(); + reportNotAvailable(); +}); + +function reportAvailable() { + describe('report is available', () => { + it('should show button', () => { + spyOn(milestoneService, 'getMilestoneReport').and.returnValue({ + isReportAvailable: true + }); + component.ngOnChanges(); + fixture.detectChanges(); + const button = fixture.debugElement.nativeElement.querySelector('button'); + expect(button).toBeTruthy(); + }); + }); +} + +function reportNotAvailable() { + describe('report is not available', () => { + it('should hide button', () => { + const button = fixture.debugElement.nativeElement.querySelector('button'); + expect(button).toBeFalsy(); + }); + }); +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestone-report-button/milestone-report-button.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestone-report-button/milestone-report-button.component.ts new file mode 100644 index 00000000000..d82fe2282bd --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestone-report-button/milestone-report-button.component.ts @@ -0,0 +1,42 @@ +import { CommonModule } from '@angular/common'; +import { Component, Input } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; +import { MilestoneService } from '../../../services/milestoneService'; +import { Node } from '../../../common/Node'; +import { MatDialog } from '@angular/material/dialog'; +import { MilestoneDetailsDialogComponent } from '../milestones/milestone-details-dialog/milestone-details-dialog.component'; + +@Component({ + imports: [CommonModule, MatButtonModule, MatIconModule], + selector: 'milestone-report-button', + templateUrl: './milestone-report-button.component.html' +}) +export class MilestoneReportButtonComponent { + @Input() component: any; + @Input() node: Node; + @Input() periodId: number; + protected report: any; + + constructor( + private dialog: MatDialog, + private milestoneService: MilestoneService + ) {} + + ngOnChanges(): void { + if (this.node && this.component) { + this.setMilestoneReport(); + } + } + + private setMilestoneReport(): void { + this.report = this.milestoneService.getMilestoneReport(this.node.id, this.component.id); + } + + protected showReport(): void { + this.dialog.open(MilestoneDetailsDialogComponent, { + data: this.report, + panelClass: 'dialog-lg' + }); + } +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html new file mode 100644 index 00000000000..55ff2807d3e --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html @@ -0,0 +1,188 @@ +
+ + +
+ + +
+ + +
+
+
+ +
+ + + + + + +
+
+
+ + + + +
+
+
diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.scss b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.scss similarity index 100% rename from src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.scss rename to src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.scss diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.spec.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.spec.ts similarity index 67% rename from src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.spec.ts rename to src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.spec.ts index 92d1df2a8a2..e22c24638a8 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.spec.ts +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.spec.ts @@ -8,18 +8,18 @@ import { WorkgroupSelectAutocompleteComponent } from '../../../../../../app/clas import { ConfigService } from '../../../../services/configService'; import { TeacherDataService } from '../../../../services/teacherDataService'; import { ClassroomMonitorTestingModule } from '../../../classroom-monitor-testing.module'; -import { MilestoneGradingViewComponent } from './milestone-grading-view.component'; +import { MilestoneClassResponsesComponent } from './milestone-class-responses.component'; import { NodeGradingViewComponentTestHelper } from '../../nodeGrading/node-grading-view/node-grading-view.component.test.helper'; import { of } from 'rxjs'; +import { ClassroomStatusService } from '../../../../services/classroomStatusService'; -let component: MilestoneGradingViewComponent; -let fixture: ComponentFixture; +let component: MilestoneClassResponsesComponent; +let fixture: ComponentFixture; let testHelper: NodeGradingViewComponentTestHelper; - -describe('MilestoneGradingViewComponent', () => { +describe('MilestoneClassResponsesComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [MilestoneGradingViewComponent], + declarations: [MilestoneClassResponsesComponent], imports: [ ClassroomMonitorTestingModule, FormsModule, @@ -34,7 +34,7 @@ describe('MilestoneGradingViewComponent', () => { }); beforeEach(() => { - fixture = TestBed.createComponent(MilestoneGradingViewComponent); + fixture = TestBed.createComponent(MilestoneClassResponsesComponent); component = fixture.componentInstance; component.milestone = { nodeId: 'node1', @@ -47,20 +47,24 @@ describe('MilestoneGradingViewComponent', () => { canGradeStudentWork: true, canAuthorProject: true }); + testHelper = new NodeGradingViewComponentTestHelper(); + initializeWorkgroups(component); spyOn(TestBed.inject(TeacherDataService), 'getCurrentPeriodId').and.returnValue(1); + spyOn(TestBed.inject(TeacherDataService), 'isWorkgroupShown').and.returnValue(false); + spyOn(TestBed.inject(ClassroomStatusService), 'hasStudentStatus').and.returnValue(true); spyOn(TestBed.inject(TeacherDataService), 'getCurrentPeriod').and.returnValue({ periodId: 1 }); - spyOn(TestBed.inject(ConfigService), 'getClassmateUserInfos').and.returnValue([]); + spyOn(TestBed.inject(ConfigService), 'getClassmateUserInfos').and.returnValue( + component['workgroups'] + ); spyOn(TestBed.inject(TeacherDataService), 'retrieveStudentDataForNode').and.returnValue(of([])); - testHelper = new NodeGradingViewComponentTestHelper(); - initializeWorkgroups(component); fixture.detectChanges(); }); - setSort(); + sortByTeam(); }); -function initializeWorkgroups(component: MilestoneGradingViewComponent) { - component.workgroups = [ +function initializeWorkgroups(component: MilestoneClassResponsesComponent) { + component['workgroups'] = [ createWorkgroupForTesting( 3, testHelper.statusCompleted, @@ -97,47 +101,16 @@ function initializeWorkgroups(component: MilestoneGradingViewComponent) { null, testHelper.statusNoWork, null, - testHelper.notVisible, + testHelper.visible, null, testHelper.workgroupId5 ) ]; } -function setSort() { - it('should sort by initial score ascending', () => { - component.setSort('initialScore'); - testHelper.expectWorkgroupOrder(component.sortedWorkgroups, [ - testHelper.workgroupId1, - testHelper.workgroupId2, - testHelper.workgroupId4, - testHelper.workgroupId3, - testHelper.workgroupId5 - ]); - }); - it('should sort by initial score descending', () => { - component.setSort('-initialScore'); - testHelper.expectWorkgroupOrder(component.sortedWorkgroups, [ - testHelper.workgroupId3, - testHelper.workgroupId2, - testHelper.workgroupId4, - testHelper.workgroupId1, - testHelper.workgroupId5 - ]); - }); - it('should sort by change in score ascending', () => { - component.setSort('changeInScore'); - testHelper.expectWorkgroupOrder(component.sortedWorkgroups, [ - testHelper.workgroupId4, - testHelper.workgroupId2, - testHelper.workgroupId3, - testHelper.workgroupId1, - testHelper.workgroupId5 - ]); - }); - it('should sort by change in score descending', () => { - component.setSort('-changeInScore'); - testHelper.expectWorkgroupOrder(component.sortedWorkgroups, [ +function sortByTeam() { + it('should sort by team', () => { + testHelper.expectWorkgroupOrder(component['sortedWorkgroups'], [ testHelper.workgroupId1, testHelper.workgroupId2, testHelper.workgroupId3, diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.ts new file mode 100644 index 00000000000..69bcdad9409 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.ts @@ -0,0 +1,189 @@ +import { Component, Input, ViewEncapsulation } from '@angular/core'; +import { copy } from '../../../../common/object/object'; +import { Annotation } from '../../../../common/Annotation'; +import { filter, Subscription } from 'rxjs'; +import { AbstractClassResponsesComponent } from '../../AbstractClassResponsesComponent'; +import { Node } from '../../../../common/Node'; +import { Notification } from '../../../../../../app/domain/notification'; + +@Component({ + encapsulation: ViewEncapsulation.None, + selector: 'milestone-class-responses', + standalone: false, + styleUrl: './milestone-class-responses.component.scss', + templateUrl: './milestone-class-responses.component.html' +}) +export class MilestoneClassResponsesComponent extends AbstractClassResponsesComponent { + protected component: any; + private firstNodeId: string; + protected firstNodePosition: string; + private lastNodeId: string; + protected lastNodePosition: string; + @Input() milestone: any; + protected node: Node; + private subscriptions: Subscription = new Subscription(); + + ngOnInit(): void { + this.node = this.projectService.getNode(this.milestone.nodeId); + this.component = this.node.getComponent(this.milestone.componentId); + if (this.milestone.report.locations.length > 1) { + this.firstNodeId = this.milestone.report.locations[0].nodeId; + this.lastNodeId = + this.milestone.report.locations[this.milestone.report.locations.length - 1].nodeId; + } + this.retrieveStudentData(this.projectService.getNode(this.firstNodeId)); + if (this.milestone.report.locations.length > 1) { + this.retrieveStudentData(this.projectService.getNode(this.lastNodeId)); + } + this.subscribeToEvents(); + this.getNodePositions(); + } + + ngOnDestroy(): void { + this.subscriptions.unsubscribe(); + } + + private subscribeToEvents(): void { + this.subscriptions.add(this.subscribeToNotifications()); + this.subscriptions.add(this.subscribeToAnnotations()); + this.subscriptions.add(this.subscribeToStudentWork()); + if (this.milestone.report.locations.length > 1) { + this.subscriptions.add(this.subscribeToFirstNodeAnnotations()); + } + } + + private subscribeToNotifications(): Subscription { + return this.notificationService.notificationChanged$ + .pipe( + filter( + (notification: Notification) => + notification.type === 'CRaterResult' && this.workgroupsById[notification.toWorkgroupId] + ) + ) + .subscribe((notification) => + this.updateWorkgroup(this.getWorkgroup(notification.toWorkgroupId)) + ); + } + + private subscribeToAnnotations(): Subscription { + return this.annotationService.annotationReceived$ + .pipe( + filter( + (annotation: Annotation) => + annotation.nodeId === this.node.id && this.workgroupsById[annotation.toWorkgroupId] + ) + ) + .subscribe((annotation: Annotation) => + this.updateWorkgroup(this.getWorkgroup(annotation.toWorkgroupId)) + ); + } + + private subscribeToStudentWork(): Subscription { + return this.dataService.studentWorkReceived$ + .pipe( + filter( + ({ studentWork }) => + studentWork.nodeId === this.node.id && this.workgroupsById[studentWork.workgroupId] + ) + ) + .subscribe(({ studentWork }) => + this.updateWorkgroup(this.getWorkgroup(studentWork.workgroupId)) + ); + } + + private subscribeToFirstNodeAnnotations(): Subscription { + return this.annotationService.annotationReceived$ + .pipe( + filter( + (annotation: Annotation) => + annotation.nodeId === this.firstNodeId && this.workgroupsById[annotation.toWorkgroupId] + ) + ) + .subscribe((annotation: Annotation) => + this.updateWorkgroup(this.getWorkgroup(annotation.toWorkgroupId)) + ); + } + + private getWorkgroup(workgroupId: number): any { + return this.workgroupsById[workgroupId]; + } + + protected hasWork(): boolean { + return this.projectService.nodeHasWork(this.node.id); + } + + protected isCompleted(workgroupId: number, nodeStatus: any): boolean { + return nodeStatus.isCompleted; + } + + protected getComponentStates(): any[] { + return this.dataService.getComponentStatesByNodeId(this.node.id); + } + + private getNodePositions(): void { + if (this.milestone.report.locations.length > 1) { + this.firstNodePosition = this.projectService.getNodePositionById(this.firstNodeId); + this.lastNodePosition = this.projectService.getNodePositionById(this.lastNodeId); + } + } + + protected expandAll(): void { + super.expandAll(); + this.saveEvent('MilestoneStudentWorkExpandAllClicked', { + milestoneId: this.milestone.id + }); + } + + protected collapseAll(): void { + super.collapseAll(); + this.saveEvent('MilestoneStudentWorkCollapseAllClicked', { + milestoneId: this.milestone.id + }); + } + + protected onUpdateExpand({ workgroupId, value }): void { + super.onUpdateExpand({ workgroupId, value }); + this.saveEvent(value ? 'MilestoneStudentWorkOpened' : 'MilestoneStudentWorkClosed', { + milestoneId: this.milestone.id, + workgroupId: workgroupId + }); + } + + private saveEvent(event: string, data: any): void { + this.dataService.saveEvent('ClassroomMonitor', null, null, null, 'Navigation', event, data); + } + + protected updateWorkgroup(workgroup: any): void { + super.updateWorkgroup(workgroup); + if (this.milestone.report.locations.length > 1) { + const firstLocation = this.milestone.report.locations[0]; + workgroup.initialScore = this.getScoreByWorkgroupId( + workgroup.workgroupId, + firstLocation.nodeId, + firstLocation.componentId + ); + workgroup.changeInScore = this.getChangeInScore(workgroup.initialScore, workgroup.score); + } + this.workgroupsById[workgroup.workgroupId] = copy(workgroup); + } + + protected getWorkgroupScore(workgroupId: number): number { + return this.getScoreByWorkgroupId(workgroupId, this.node.id, this.component.id); + } + + private getScoreByWorkgroupId(workgroupId: number, nodeId: string, componentId: string): number { + const latestScoreAnnotation = this.annotationService.getLatestScoreAnnotation( + nodeId, + componentId, + workgroupId + ); + return latestScoreAnnotation + ? this.annotationService.getScoreValueFromScoreAnnotation(latestScoreAnnotation) + : null; + } + + private getChangeInScore(initialScore: number, revisedScore: number): number { + // returning -10000 ensures that this score appears as the lowest score + return initialScore != -1 && revisedScore != -1 ? revisedScore - initialScore : -10000; + } +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-details/milestone-details.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-details/milestone-details.component.html index 65584cc1d6e..fafa0eccc2a 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-details/milestone-details.component.html +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-details/milestone-details.component.html @@ -33,7 +33,7 @@

Item Location: {{ getNodeNumberAndTitleByNodeId(milestone.nodeId) }} - (Step Info) + (Step Info)

} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-details/milestone-details.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-details/milestone-details.component.ts index cbcf4458d18..13b653a524f 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-details/milestone-details.component.ts +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-details/milestone-details.component.ts @@ -6,14 +6,13 @@ import { MatTabChangeEvent } from '@angular/material/tabs'; import { ConfigService } from '../../../../services/configService'; import { Subscription } from 'rxjs'; import { MatDialog } from '@angular/material/dialog'; -import { ShowNodeInfoDialogComponent } from '../../../../../../app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component'; import { getAvatarColorForWorkgroupId } from '../../../../common/workgroup/workgroup'; @Component({ - selector: 'milestone-details', - styleUrls: ['./milestone-details.component.scss'], - templateUrl: './milestone-details.component.html', - standalone: false + selector: 'milestone-details', + styleUrls: ['./milestone-details.component.scss'], + templateUrl: './milestone-details.component.html', + standalone: false }) export class MilestoneDetailsComponent implements OnInit { currentPeriod: any; @@ -120,11 +119,10 @@ export class MilestoneDetailsComponent implements OnInit { this.dataService.saveEvent(context, nodeId, componentId, componentType, category, event, data); } - protected showMilestoneStepInfo(): void { - this.dialog.open(ShowNodeInfoDialogComponent, { - data: this.milestone.nodeId, - width: '100%' - }); + protected previewProject(): void { + window.open( + this.configService.getConfigParam('previewProjectURL') + `/${this.milestone.nodeId}` + ); } sortAchievementTimeDescending(workgroup: any[]): any[] { diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html deleted file mode 100644 index cb82aaf8aeb..00000000000 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html +++ /dev/null @@ -1,200 +0,0 @@ -
- - -
- - -
- - -
-
-
- -
- - @if (milestone.report.locations.length == 1) { - - } - @if (milestone.report.locations.length == 1) { - - } - @if (milestone.report.locations.length > 1) { - - } - @if (milestone.report.locations.length > 1) { - - } - @if (milestone.report.locations.length > 1) { - - } -
-
-
- @for (workgroup of sortedWorkgroups; track workgroup) { - @if (isWorkgroupShown(workgroup)) { - - - } - } -
-
-
diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.ts deleted file mode 100644 index aa9dc2b4143..00000000000 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { Component, Input, ViewEncapsulation } from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; -import { copy } from '../../../../common/object/object'; -import { AnnotationService } from '../../../../services/annotationService'; -import { ClassroomStatusService } from '../../../../services/classroomStatusService'; -import { ConfigService } from '../../../../services/configService'; -import { MilestoneService } from '../../../../services/milestoneService'; -import { NotificationService } from '../../../../services/notificationService'; -import { TeacherDataService } from '../../../../services/teacherDataService'; -import { TeacherPeerGroupService } from '../../../../services/teacherPeerGroupService'; -import { TeacherProjectService } from '../../../../services/teacherProjectService'; -import { NodeGradingViewComponent } from '../../nodeGrading/node-grading-view/node-grading-view.component'; -import { Annotation } from '../../../../common/Annotation'; - -@Component({ - selector: 'milestone-grading-view', - templateUrl: './milestone-grading-view.component.html', - styleUrls: ['./milestone-grading-view.component.scss'], - encapsulation: ViewEncapsulation.None, - standalone: false -}) -export class MilestoneGradingViewComponent extends NodeGradingViewComponent { - componentId: string; - firstNodeId: string; - firstNodePosition: string; - lastNodeId: string; - lastNodePosition: string; - @Input() milestone: any; - node: any; - nodeId: string; - - constructor( - protected annotationService: AnnotationService, - protected classroomStatusService: ClassroomStatusService, - protected configService: ConfigService, - protected dataService: TeacherDataService, - protected dialog: MatDialog, - protected milestoneService: MilestoneService, - protected notificationService: NotificationService, - protected peerGroupService: TeacherPeerGroupService, - protected projectService: TeacherProjectService - ) { - super( - annotationService, - classroomStatusService, - configService, - dataService, - dialog, - milestoneService, - notificationService, - peerGroupService, - projectService - ); - } - - ngOnInit(): void { - this.nodeId = this.milestone.nodeId; - this.node = this.projectService.getNode(this.nodeId); - if (this.milestone.report.locations.length > 1) { - this.firstNodeId = this.milestone.report.locations[0].nodeId; - this.lastNodeId = - this.milestone.report.locations[this.milestone.report.locations.length - 1].nodeId; - } - this.componentId = this.milestone.componentId; - this.retrieveStudentData(); - this.subscribeToEvents(); - this.getNodePositions(); - } - - protected subscribeToEvents(): void { - super.subscribeToEvents(); - if (this.milestone.report.locations.length > 1) { - this.subscriptions.add( - this.annotationService.annotationReceived$.subscribe((annotation: Annotation) => { - const workgroupId = annotation.toWorkgroupId; - if (annotation.nodeId === this.firstNodeId && this.workgroupsById[workgroupId]) { - this.updateWorkgroup(workgroupId); - } - }) - ); - } - } - - protected retrieveStudentData(): void { - const firstNode = this.projectService.getNode(this.firstNodeId); - super.retrieveStudentData(firstNode); - if (this.milestone.report.locations.length > 1) { - const lastNode = this.projectService.getNode(this.lastNodeId); - super.retrieveStudentData(lastNode); - } - } - - private getNodePositions(): void { - if (this.milestone.report.locations.length > 1) { - this.firstNodePosition = this.projectService.getNodePositionById(this.firstNodeId); - this.lastNodePosition = this.projectService.getNodePositionById(this.lastNodeId); - } - } - - private getScoreByWorkgroupId( - workgroupId: number, - nodeId: string = this.nodeId, - componentId: string = this.componentId - ): number { - let score = null; - const latestScoreAnnotation = this.annotationService.getLatestScoreAnnotation( - nodeId, - componentId, - workgroupId - ); - if (latestScoreAnnotation) { - score = this.annotationService.getScoreValueFromScoreAnnotation(latestScoreAnnotation); - } - return score; - } - - expandAll(): void { - super.expandAll(); - this.saveMilestoneStudentWorkExpandCollapseAllEvent('MilestoneStudentWorkExpandAllClicked'); - } - - collapseAll(): void { - super.collapseAll(); - this.saveMilestoneStudentWorkExpandCollapseAllEvent('MilestoneStudentWorkCollapseAllClicked'); - } - - private saveMilestoneStudentWorkExpandCollapseAllEvent(event: any): void { - const context = 'ClassroomMonitor', - nodeId = null, - componentId = null, - componentType = null, - category = 'Navigation', - data = { milestoneId: this.milestone.id }; - this.dataService.saveEvent(context, nodeId, componentId, componentType, category, event, data); - } - - onUpdateExpand({ workgroupId, value }): void { - super.onUpdateExpand({ workgroupId: workgroupId, value: value }); - this.saveMilestoneWorkgroupItemViewedEvent(workgroupId, value); - } - - updateWorkgroup(workgroupId: number, init = false): void { - super.updateWorkgroup(workgroupId, init); - const workgroup = this.workgroupsById[workgroupId]; - workgroup.score = this.getScoreByWorkgroupId(workgroupId); - if (this.milestone.report.locations.length > 1) { - const firstLocation = this.milestone.report.locations[0]; - workgroup.initialScore = this.getScoreByWorkgroupId( - workgroupId, - firstLocation.nodeId, - firstLocation.componentId - ); - workgroup.changeInScore = this.getChangeInScore(workgroup.initialScore, workgroup.score); - } - if (!init) { - this.workgroupsById[workgroupId] = copy(workgroup); - } - } - - private getChangeInScore(initialScore: number, revisedScore: number): number { - if (initialScore != -1 && revisedScore != -1) { - return revisedScore - initialScore; - } - return -10000; // this hack ensures that this score appears as the lowest score - } - - private saveMilestoneWorkgroupItemViewedEvent(workgroupId: number, isExpanded: boolean): void { - let event = ''; - if (isExpanded) { - event = 'MilestoneStudentWorkOpened'; - } else { - event = 'MilestoneStudentWorkClosed'; - } - const context = 'ClassroomMonitor', - nodeId = null, - componentId = null, - componentType = null, - category = 'Navigation', - data = { milestoneId: this.milestone.id, workgroupId: workgroupId }; - this.dataService.saveEvent(context, nodeId, componentId, componentType, category, event, data); - } - - protected sortWorkgroups(): void { - super.sortWorkgroups(); - switch (this.sort) { - case 'initialScore': - this.sortedWorkgroups.sort(this.createSortAscendingFunction('initialScore')); - break; - case '-initialScore': - this.sortedWorkgroups.sort(this.createSortDescendingFunction('initialScore')); - break; - case 'changeInScore': - this.sortedWorkgroups.sort(this.createSortAscendingFunction('changeInScore')); - break; - case '-changeInScore': - this.sortedWorkgroups.sort(this.createSortDescendingFunction('changeInScore')); - break; - } - } -} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.html new file mode 100644 index 00000000000..81801097bd0 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.html @@ -0,0 +1,20 @@ + + @if (components.length == 1) { + + } @else if (components.length > 1) { + + {{ selectedText }} + @for (component of components; track component.id; let i = $index) { + + {{ component.displayIndex }}: {{ getComponentTypeLabel(component.type) }} + + } + + } + diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.scss b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.scss new file mode 100644 index 00000000000..57fb684e54f --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.scss @@ -0,0 +1,18 @@ +@use '@angular/material' as mat; + +.component-select { + @include mat.form-field-overrides( + ( + container-vertical-padding: 8px, + container-height: 40px + ) + ); + + .mat-mdc-form-field-infix { + width: auto; + } + + .mat-mdc-select-value { + @apply me-1; + } +} \ No newline at end of file diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.spec.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.spec.ts new file mode 100644 index 00000000000..f2b9c28cf47 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.spec.ts @@ -0,0 +1,84 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FilterComponentsComponent } from './filter-components.component'; +import { MockProvider } from 'ng-mocks'; +import { ComponentTypeService } from '../../../../services/componentTypeService'; +import { ComponentContent } from '../../../../common/ComponentContent'; +import { HarnessLoader } from '@angular/cdk/testing'; +import { MatSelectHarness } from '@angular/material/select/testing'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; + +let component: FilterComponentsComponent; +let fixture: ComponentFixture; +let loader: HarnessLoader; +let select: MatSelectHarness; +describe('FilterComponentsComponent', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [FilterComponentsComponent], + providers: [MockProvider(ComponentTypeService)] + }).compileComponents(); + + fixture = TestBed.createComponent(FilterComponentsComponent); + loader = TestbedHarnessEnvironment.loader(fixture); + component = fixture.componentInstance; + }); + onlyOneComponent(); + moreThanOneComponent(); +}); + +function onlyOneComponent() { + describe('when there is only 1 component', () => { + beforeEach(async () => { + component.components = [ + { + id: 'c1', + type: 'MultipleChoice' + } as ComponentContent + ]; + fixture.detectChanges(); + select = await loader.getHarness(MatSelectHarness); + }); + it('should be disabled', async () => { + expect(await select.isDisabled()).toBe(true); + }); + }); +} + +function moreThanOneComponent() { + describe('when there is more than 1 component', () => { + beforeEach(async () => { + component.components = [ + { + id: 'c1', + type: 'MultipleChoice' + } as ComponentContent, + { + id: 'c2', + type: 'OpenResponse' + } as ComponentContent + ]; + component.ngOnChanges(); + fixture.detectChanges(); + select = await loader.getHarness(MatSelectHarness); + }); + it('should show options', async () => { + await select.open(); + const options = await select.getOptions(); + expect(options.length).toBe(2); + expect(await options[0].isSelected()).toBe(true); + expect(await options[1].isSelected()).toBe(true); + }); + it('clicking on an option should emit selected components', async () => { + const spy = spyOn(component.componentsChange, 'emit').and.callThrough(); + await select.open(); + const options = await select.getOptions(); + await options[0].click(); + expect(spy).toHaveBeenCalledWith([ + { + id: 'c2', + type: 'OpenResponse' + } as ComponentContent + ]); + }); + }); +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.ts new file mode 100644 index 00000000000..58872239791 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.ts @@ -0,0 +1,48 @@ +import { Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatSelectModule } from '@angular/material/select'; +import { MatButtonModule } from '@angular/material/button'; +import { FormsModule } from '@angular/forms'; +import { ComponentTypeService } from '../../../../services/componentTypeService'; +import { ComponentContent } from '../../../../common/ComponentContent'; + +@Component({ + imports: [CommonModule, FormsModule, MatButtonModule, MatFormFieldModule, MatSelectModule], + selector: 'filter-components', + styleUrl: './filter-components.component.scss', + templateUrl: './filter-components.component.html', + encapsulation: ViewEncapsulation.None +}) +export class FilterComponentsComponent { + @Input() components: ComponentContent[]; + @Output() componentsChange: EventEmitter = new EventEmitter< + ComponentContent[] + >(); + protected selectedComponents: ComponentContent[]; + protected selectedText: string; + + constructor(private componentTypeService: ComponentTypeService) {} + + ngOnChanges(): void { + this.selectedComponents = this.components; + this.updateSelectedText(); + } + + private updateSelectedText(): void { + this.selectedText = $localize`Showing ${this.selectedComponents.length}/${this.components.length} questions`; + } + + protected getComponentTypeLabel(componentType: string): string { + return this.componentTypeService.getComponentTypeLabel(componentType); + } + + protected compareById(component1: ComponentContent, component2: ComponentContent): boolean { + return component1?.id === component2?.id; + } + + protected updateSelectedComponents(): void { + this.updateSelectedText(); + this.componentsChange.emit(this.selectedComponents); + } +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html new file mode 100644 index 00000000000..ab80d92c8a4 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html @@ -0,0 +1,98 @@ + + +
+ + + + +
+
+ +
+ + + +
+
+
+ @for (workgroup of sortedWorkgroups; track workgroup.workgroupId) { + @if (isWorkgroupShown(workgroup)) { + + } + } +
+
diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.scss b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.scss new file mode 100644 index 00000000000..5f34e4a1459 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.scss @@ -0,0 +1,12 @@ +.user-list { + padding-top: 0; +} + +.table--list__thead__link { + padding: 0; +} + +.mdc-list-item.user-list-controls { + height: auto; + padding: 8px 16px; +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.spec.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.spec.ts new file mode 100644 index 00000000000..579a1fde24d --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.spec.ts @@ -0,0 +1,56 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NodeClassResponsesComponent } from './node-class-responses.component'; +import { AnnotationService } from '../../../../services/annotationService'; +import { MockComponent, MockProvider, MockProviders } from 'ng-mocks'; +import { ClassroomStatusService } from '../../../../services/classroomStatusService'; +import { ComponentServiceLookupService } from '../../../../services/componentServiceLookupService'; +import { ConfigService } from '../../../../services/configService'; +import { TeacherDataService } from '../../../../services/teacherDataService'; +import { NotificationService } from '../../../../services/notificationService'; +import { TeacherProjectService } from '../../../../services/teacherProjectService'; +import { of } from 'rxjs'; +import { WorkgroupSelectAutocompleteComponent } from '../../../../../../app/classroom-monitor/workgroup-select/workgroup-select-autocomplete/workgroup-select-autocomplete.component'; +import { MatButtonHarness } from '@angular/material/button/testing'; +import { HarnessLoader } from '@angular/cdk/testing'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; + +describe('NodeClassResponsesComponent', () => { + let component: NodeClassResponsesComponent; + let fixture: ComponentFixture; + let loader: HarnessLoader; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [MockComponent(WorkgroupSelectAutocompleteComponent)], + imports: [NodeClassResponsesComponent], + providers: [ + MockProviders( + AnnotationService, + ClassroomStatusService, + ComponentServiceLookupService, + ConfigService, + TeacherDataService, + NotificationService + ), + MockProvider(TeacherProjectService, { + projectSaved$: of() + }) + ] + }).compileComponents(); + + fixture = TestBed.createComponent(NodeClassResponsesComponent); + loader = TestbedHarnessEnvironment.loader(fixture); + component = fixture.componentInstance; + component['sortedWorkgroups'] = [ + { workgroupId: 1, name: 'Workgroup 1' }, + { workgroupId: 2, name: 'Workgroup 2' } + ]; + fixture.detectChanges(); + }); + + it('clicking on the expand all button should expand all teams', async () => { + expect(component['allWorkgroupsExpanded']).toBeFalsy(); + await (await loader.getHarness(MatButtonHarness.with({ text: '+ Expand all' }))).click(); + expect(component['allWorkgroupsExpanded']).toBeTrue(); + }); +}); diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.ts new file mode 100644 index 00000000000..90be65a0e18 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.ts @@ -0,0 +1,127 @@ +import { Component, Input } from '@angular/core'; +import { MatListModule } from '@angular/material/list'; +import { WorkgroupSelectAutocompleteComponent } from '../../../../../../app/classroom-monitor/workgroup-select/workgroup-select-autocomplete/workgroup-select-autocomplete.component'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; +import { IntersectionObserverModule } from '@ng-web-apis/intersection-observer'; +import { CommonModule } from '@angular/common'; +import { AbstractClassResponsesComponent } from '../../AbstractClassResponsesComponent'; +import { Node } from '../../../../common/Node'; +import { ComponentContent } from '../../../../common/ComponentContent'; +import { NodeWorkgroupItemComponent } from '../node-workgroup-item/node-workgroup-item.component'; +import { AnnotationService } from '../../../../services/annotationService'; +import { ClassroomStatusService } from '../../../../services/classroomStatusService'; +import { ComponentServiceLookupService } from '../../../../services/componentServiceLookupService'; +import { ConfigService } from '../../../../services/configService'; +import { TeacherDataService } from '../../../../services/teacherDataService'; +import { NotificationService } from '../../../../services/notificationService'; +import { TeacherProjectService } from '../../../../services/teacherProjectService'; +import { Subscription } from 'rxjs'; + +@Component({ + imports: [ + CommonModule, + IntersectionObserverModule, + MatButtonModule, + MatIconModule, + MatListModule, + NodeWorkgroupItemComponent, + WorkgroupSelectAutocompleteComponent + ], + selector: 'node-class-responses', + styleUrl: './node-class-responses.component.scss', + templateUrl: './node-class-responses.component.html' +}) +export class NodeClassResponsesComponent extends AbstractClassResponsesComponent { + @Input() components: ComponentContent[]; + protected maxScore: number; + @Input() node: Node; + private subscriptions: Subscription = new Subscription(); + + constructor( + protected annotationService: AnnotationService, + protected classroomStatusService: ClassroomStatusService, + private componentServiceLookupService: ComponentServiceLookupService, + protected configService: ConfigService, + protected dataService: TeacherDataService, + protected notificationService: NotificationService, + protected projectService: TeacherProjectService + ) { + super( + annotationService, + classroomStatusService, + configService, + dataService, + notificationService, + projectService + ); + } + + ngOnInit(): void { + this.subscriptions.add(this.projectService.projectSaved$.subscribe(() => this.setMaxScore())); + } + + ngOnChanges(): void { + if (this.node && this.components) { + this.retrieveStudentData(this.node); + this.setMaxScore(); + } + } + + ngOnDestroy(): void { + this.subscriptions.unsubscribe(); + } + + private setMaxScore(): void { + this.maxScore = this.components + .map( + (component) => this.projectService.getMaxScoreForComponent(this.node.id, component.id) ?? 0 + ) + .reduce((accumulator, currentValue) => accumulator + currentValue, 0); + } + + protected setWorkgroupsById(): void { + this.workgroups.forEach((workgroup) => { + this.workgroupsById[workgroup.workgroupId] = workgroup; + this.updateWorkgroup(workgroup); + }); + } + + protected getWorkgroupScore(workgroupId: number): number { + return this.annotationService.getTotalNodeScore(workgroupId, this.node, this.components); + } + + protected hasWork(): boolean { + return this.projectService.nodeHasWork(this.node.id); + } + + protected isCompleted(workgroupId: number, nodeStatus: any): boolean { + return this.components.every((component) => this.isComponentCompleted(workgroupId, component)); + } + + private isComponentCompleted(workgroupId: number, component: ComponentContent): boolean { + const service = this.componentServiceLookupService.getService(component.type); + const workgroupComponentStates = this.dataService.getComponentStatesByWorkgroupIdAndComponentId( + workgroupId, + component.id + ); + return ['OpenResponse', 'Discussion'].includes(component.type) + ? service.isCompletedV2(this.node, component, { + componentStates: workgroupComponentStates + }) + : service.isCompleted( + component, + workgroupComponentStates, + this.dataService.getEventsByNodeId(this.node.id), + this.node + ); + } + + protected getComponentStates(): any[] { + return this.dataService + .getComponentStatesByNodeId(this.node.id) + .filter((componentState) => + this.components.some((component) => component.id === componentState.componentId) + ); + } +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html deleted file mode 100644 index a4830eaca60..00000000000 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html +++ /dev/null @@ -1,189 +0,0 @@ -
-
-
-
-

- {{ getNodeCompletion(nodeId) }}% - Completion -

- @if (nodeHasWork) { -

- @if (getNodeAverageScore() !== 'N/A') { - {{ getNodeAverageScore() | number: '1.1' }} - } @else { - N/A - } - Mean Score -

- } -
-
- -
- - @if (milestoneReport) { - - } - @for (peerGroupingTag of peerGroupingTags; track peerGroupingTag) { - - } - -
-
- - -
- - - @if (nodeHasWork) { -
- - -
- } -
- @if (!nodeHasWork) { -
- - This step doesn't require any student work - -
- } -
- -
- - - @if (nodeHasWork) { - - } -
-
-
- @for (workgroup of sortedWorkgroups; track trackWorkgroup($index, workgroup)) { - @if (isWorkgroupShown(workgroup)) { - - - } - } -
-
-
diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.scss b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.scss deleted file mode 100644 index 85c5f2b83e7..00000000000 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.scss +++ /dev/null @@ -1,40 +0,0 @@ -.node-grading { - .content-head-label { - font-size: 50%; - } - - .user-list { - &.mat-mdc-list-base { - /* TODO(mdc-migration): The following rule targets internal classes of list that may no longer apply for the MDC version. */ - .mat-mdc-list-item .mat-list-item-content { - padding: 0 8px; - } - - workgroup-item { - /* TODO(mdc-migration): The following rule targets internal classes of list that may no longer apply for the MDC version. */ - .mat-mdc-list-item .mat-list-item-content { - padding: 0; - } - } - } - } - - workgroup-select-autocomplete { - width: 100%; - } - - .mat-mdc-list-base { - .mat-mdc-list-item.user-list-controls { - height: auto; - padding: 8px; - } - } - - .mdc-button__label { - width: 100%; - } - - .table--list__thead__link { - text-transform: none; - } -} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.spec.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.spec.ts deleted file mode 100644 index 843c2d47eef..00000000000 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.spec.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { ComponentSelectComponent } from '../../../../../../app/classroom-monitor/component-select/component-select.component'; -import { WorkgroupSelectAutocompleteComponent } from '../../../../../../app/classroom-monitor/workgroup-select/workgroup-select-autocomplete/workgroup-select-autocomplete.component'; -import { TeacherDataService } from '../../../../services/teacherDataService'; -import { TeacherProjectService } from '../../../../services/teacherProjectService'; -import { VLEProjectService } from '../../../../vle/vleProjectService'; -import { ClassroomMonitorTestingModule } from '../../../classroom-monitor-testing.module'; -import { NodeGradingViewComponent } from './node-grading-view.component'; -import { ConfigService } from '../../../../services/configService'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { NodeGradingViewComponentTestHelper } from '../../nodeGrading/node-grading-view/node-grading-view.component.test.helper'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { of } from 'rxjs'; -import { ComponentTypeServiceModule } from '../../../../services/componentTypeService.module'; - -let component: NodeGradingViewComponent; -let fixture: ComponentFixture; -let testHelper: NodeGradingViewComponentTestHelper; - -describe('NodeGradingViewComponent', () => { - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [NodeGradingViewComponent], - imports: [ - BrowserAnimationsModule, - ClassroomMonitorTestingModule, - ComponentSelectComponent, - ComponentTypeServiceModule, - WorkgroupSelectAutocompleteComponent - ], - schemas: [NO_ERRORS_SCHEMA] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(NodeGradingViewComponent); - component = fixture.componentInstance; - spyOn(TestBed.inject(ConfigService), 'getClassmateUserInfos').and.returnValue([]); - spyOn(TestBed.inject(ConfigService), 'getPermissions').and.returnValue({ - canViewStudentNames: true, - canGradeStudentWork: true, - canAuthorProject: true - }); - spyOn(TestBed.inject(TeacherProjectService), 'getMaxScoreForNode').and.returnValue(5); - spyOn(TestBed.inject(TeacherProjectService), 'nodeHasWork').and.returnValue(true); - spyOn(TestBed.inject(VLEProjectService), 'getAchievements').and.returnValue({}); - spyOn(TestBed.inject(TeacherDataService), 'retrieveStudentDataForNode').and.returnValue(of([])); - spyOn(TestBed.inject(TeacherDataService), 'getCurrentPeriodId').and.returnValue(1); - spyOn(TestBed.inject(TeacherDataService), 'getCurrentPeriod').and.returnValue({ periodId: 1 }); - testHelper = new NodeGradingViewComponentTestHelper(); - initializeWorkgroups(component); - fixture.detectChanges(); - }); - - setSort(); -}); - -function initializeWorkgroups(component: NodeGradingViewComponent) { - component.workgroups = [ - createWorkgroupForTesting( - testHelper.statusCompleted, - testHelper.visible, - 1, - testHelper.workgroupId1 - ), - createWorkgroupForTesting( - testHelper.statusNoWork, - testHelper.visible, - 3, - testHelper.workgroupId2 - ), - createWorkgroupForTesting( - testHelper.statusPartiallyCompleted, - testHelper.visible, - 5, - testHelper.workgroupId3 - ), - createWorkgroupForTesting( - testHelper.statusCompleted, - testHelper.visible, - 3, - testHelper.workgroupId4 - ), - createWorkgroupForTesting( - testHelper.statusNoWork, - testHelper.notVisible, - null, - testHelper.workgroupId5 - ) - ]; -} - -function setSort() { - it('should sort by workgroup id ascending', () => { - component.setSort('team'); - component.setSort('team'); - testHelper.expectWorkgroupOrder(component.sortedWorkgroups, [ - testHelper.workgroupId1, - testHelper.workgroupId2, - testHelper.workgroupId3, - testHelper.workgroupId4, - testHelper.workgroupId5 - ]); - }); - it('should sort by workgroup id descending', () => { - component.setSort('team'); - testHelper.expectWorkgroupOrder(component.sortedWorkgroups, [ - testHelper.workgroupId4, - testHelper.workgroupId3, - testHelper.workgroupId2, - testHelper.workgroupId1, - testHelper.workgroupId5 - ]); - }); - it('should sort by completion status ascending', () => { - component.setSort('status'); - testHelper.expectWorkgroupOrder(component.sortedWorkgroups, [ - testHelper.workgroupId2, - testHelper.workgroupId3, - testHelper.workgroupId1, - testHelper.workgroupId4, - testHelper.workgroupId5 - ]); - }); - it('should sort by completion status descending', () => { - component.setSort('status'); - component.setSort('status'); - testHelper.expectWorkgroupOrder(component.sortedWorkgroups, [ - testHelper.workgroupId1, - testHelper.workgroupId4, - testHelper.workgroupId3, - testHelper.workgroupId2, - testHelper.workgroupId5 - ]); - }); - it('should sort by score ascending', () => { - component.setSort('score'); - testHelper.expectWorkgroupOrder(component.sortedWorkgroups, [ - testHelper.workgroupId1, - testHelper.workgroupId2, - testHelper.workgroupId4, - testHelper.workgroupId3, - testHelper.workgroupId5 - ]); - }); - it('should sort by score descending', () => { - component.setSort('score'); - component.setSort('score'); - testHelper.expectWorkgroupOrder(component.sortedWorkgroups, [ - testHelper.workgroupId3, - testHelper.workgroupId2, - testHelper.workgroupId4, - testHelper.workgroupId1, - testHelper.workgroupId5 - ]); - }); -} - -function createWorkgroupForTesting( - completionStatus: number, - isVisible: number, - score: number, - workgroupId: number -): any { - return { - completionStatus: completionStatus, - isVisible: isVisible, - score: score, - workgroupId: workgroupId - }; -} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.ts deleted file mode 100644 index d90f1f4e36e..00000000000 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.ts +++ /dev/null @@ -1,441 +0,0 @@ -import { Component, Input, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core'; -import { Subscription, tap } from 'rxjs'; -import { Node } from '../../../../common/Node'; -import { AnnotationService } from '../../../../services/annotationService'; -import { ClassroomStatusService } from '../../../../services/classroomStatusService'; -import { ConfigService } from '../../../../services/configService'; -import { MilestoneService } from '../../../../services/milestoneService'; -import { NotificationService } from '../../../../services/notificationService'; -import { TeacherDataService } from '../../../../services/teacherDataService'; -import { TeacherPeerGroupService } from '../../../../services/teacherPeerGroupService'; -import { TeacherProjectService } from '../../../../services/teacherProjectService'; -import { Notification } from '../../../../../../app/domain/notification'; -import { CompletionStatus } from '../../shared/CompletionStatus'; -import { copy } from '../../../../common/object/object'; -import { ShowNodeInfoDialogComponent } from '../../../../../../app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component'; -import { MatDialog } from '@angular/material/dialog'; -import { MilestoneDetailsDialogComponent } from '../../milestones/milestone-details-dialog/milestone-details-dialog.component'; -import { Annotation } from '../../../../common/Annotation'; - -@Component({ - selector: 'node-grading-view', - templateUrl: './node-grading-view.component.html', - styleUrls: ['./node-grading-view.component.scss'], - encapsulation: ViewEncapsulation.None, - standalone: false -}) -export class NodeGradingViewComponent implements OnInit { - canViewStudentNames: boolean; - hiddenComponents: any = []; - isExpandAll: boolean; - maxScore: any; - milestone: any; - milestoneReport: any; - node: Node; - nodeContent: any = null; - nodeHasWork: boolean; - @Input() nodeId: string; - numRubrics: number; - peerGroupingTags: string[]; - sort: any; - sortedWorkgroups: any[]; - subscriptions: Subscription = new Subscription(); - teacherWorkgroupId: number; - workgroupInViewById: any = {}; // whether the workgroup is in view or not - workgroups: any; - workgroupsById: any = {}; - workVisibilityById: any = {}; // whether student work is visible for each workgroup - - constructor( - protected annotationService: AnnotationService, - protected classroomStatusService: ClassroomStatusService, - protected configService: ConfigService, - protected dataService: TeacherDataService, - protected dialog: MatDialog, - protected milestoneService: MilestoneService, - protected notificationService: NotificationService, - protected peerGroupService: TeacherPeerGroupService, - protected projectService: TeacherProjectService - ) {} - - ngOnInit(): void { - this.setupNode(); - this.subscribeToEvents(); - } - - setupNode(): void { - this.maxScore = this.getMaxScore(); - this.node = this.projectService.getNode(this.nodeId); - this.nodeHasWork = this.projectService.nodeHasWork(this.nodeId); - this.sort = this.dataService.nodeGradingSort; - this.nodeContent = this.projectService.getNodeById(this.nodeId); - this.milestoneReport = this.milestoneService.getMilestoneReportByNodeId(this.nodeId); - this.peerGroupingTags = Array.from(this.peerGroupService.getPeerGroupingTags(this.node)); - this.retrieveStudentData(); - } - - ngOnDestroy(): void { - this.subscriptions.unsubscribe(); - } - - ngOnChanges(changes: SimpleChanges): void { - if (changes.nodeId && !changes.nodeId.firstChange) { - this.nodeId = changes.nodeId.currentValue; - this.setupNode(); - } - } - - protected subscribeToEvents(): void { - this.subscriptions.add( - this.projectService.projectSaved$.subscribe(() => { - this.maxScore = this.getMaxScore(); - }) - ); - - this.subscriptions.add( - this.notificationService.notificationChanged$.subscribe((notification) => { - if (notification.type === 'CRaterResult') { - // TODO: expand to encompass other notification types that should be shown to teacher - const workgroupId = notification.toWorkgroupId; - if (this.workgroupsById[workgroupId]) { - this.updateWorkgroup(workgroupId); - } - } - }) - ); - - this.subscriptions.add( - this.annotationService.annotationReceived$.subscribe((annotation: Annotation) => { - const workgroupId = annotation.toWorkgroupId; - if (annotation.nodeId === this.nodeId && this.workgroupsById[workgroupId]) { - this.updateWorkgroup(workgroupId); - } - }) - ); - - this.subscriptions.add( - this.dataService.studentWorkReceived$.subscribe(({ studentWork }) => { - const workgroupId = studentWork.workgroupId; - if (studentWork.nodeId === this.nodeId && this.workgroupsById[workgroupId]) { - this.updateWorkgroup(workgroupId); - } - }) - ); - - this.subscriptions.add( - this.dataService.currentPeriodChanged$.subscribe(() => { - this.milestoneReport = this.milestoneService.getMilestoneReportByNodeId(this.nodeId); - }) - ); - } - - protected retrieveStudentData(node: Node = this.node): void { - this.dataService.retrieveStudentDataForNode(node).subscribe(() => { - this.teacherWorkgroupId = this.configService.getWorkgroupId(); - this.workgroups = copy(this.configService.getClassmateUserInfos()).filter( - (workgroup) => - workgroup.workgroupId != null && - this.classroomStatusService.hasStudentStatus(workgroup.workgroupId) - ); - this.canViewStudentNames = this.configService.getPermissions().canViewStudentNames; - this.setWorkgroupsById(); - this.sortWorkgroups(); - this.numRubrics = node.getNumRubrics(); - document.body.scrollTop = document.documentElement.scrollTop = 0; - }); - } - - private getMaxScore(nodeId = this.nodeId): number { - return this.projectService.getMaxScoreForNode(nodeId); - } - - private setWorkgroupsById(): void { - for (const workgroup of this.workgroups) { - const workgroupId = workgroup.workgroupId; - this.workgroupsById[workgroupId] = workgroup; - this.workVisibilityById[workgroupId] = false; - this.updateWorkgroup(workgroupId, true); - } - } - - protected sortWorkgroups(): void { - this.sortedWorkgroups = []; - for (const workgroup of this.workgroups) { - this.sortedWorkgroups.push(workgroup); - } - switch (this.sort) { - case 'team': - this.sortedWorkgroups.sort(this.sortTeamAscending); - break; - case '-team': - this.sortedWorkgroups.sort(this.sortTeamDescending); - break; - case 'status': - this.sortedWorkgroups.sort(this.createSortAscendingFunction('completionStatus')); - break; - case '-status': - this.sortedWorkgroups.sort(this.createSortDescendingFunction('completionStatus')); - break; - case 'score': - this.sortedWorkgroups.sort(this.createSortAscendingFunction('score')); - break; - case '-score': - this.sortedWorkgroups.sort(this.createSortDescendingFunction('score')); - break; - } - } - - /** - * Sort using this order hierarchy - * isVisible descending, workgroupId ascending - */ - private sortTeamAscending(workgroupA: any, workgroupB: any): number { - if (workgroupA.isVisible === workgroupB.isVisible) { - return workgroupA.workgroupId - workgroupB.workgroupId; - } else { - return workgroupB.isVisible - workgroupA.isVisible; - } - } - - /** - * Sort using this order hierarchy - * isVisible descending, workgroupId descending - */ - private sortTeamDescending(workgroupA: any, workgroupB: any): number { - if (workgroupA.isVisible === workgroupB.isVisible) { - return workgroupB.workgroupId - workgroupA.workgroupId; - } else { - return workgroupB.isVisible - workgroupA.isVisible; - } - } - - protected createSortAscendingFunction(fieldName: string): any { - return (workgroupA: any, workgroupB: any) => { - if (workgroupA.isVisible === workgroupB.isVisible) { - if (workgroupA[fieldName] === workgroupB[fieldName]) { - return workgroupA.workgroupId - workgroupB.workgroupId; - } else { - return workgroupA[fieldName] - workgroupB[fieldName]; - } - } else { - return workgroupB.isVisible - workgroupA.isVisible; - } - }; - } - - protected createSortDescendingFunction(fieldName: string): any { - return (workgroupA: any, workgroupB: any) => { - if (workgroupA.isVisible === workgroupB.isVisible) { - if (workgroupA[fieldName] === workgroupB[fieldName]) { - return workgroupA.workgroupId - workgroupB.workgroupId; - } else { - return workgroupB[fieldName] - workgroupA[fieldName]; - } - } else { - return workgroupB.isVisible - workgroupA.isVisible; - } - }; - } - - /** - * Update statuses, scores, notifications, etc. for a workgroup object. Also check if we need to - * hide student names because logged-in user does not have the right permissions - * @param workgroupID a workgroup ID number - * @param init Boolean whether we're in controller initialization or not - */ - protected updateWorkgroup(workgroupId: number, init = false): void { - const workgroup = this.workgroupsById[workgroupId]; - const alertNotifications = this.notificationService.getAlertNotifications({ - nodeId: this.nodeId, - toWorkgroupId: workgroupId - }); - workgroup.hasAlert = alertNotifications.length > 0; - workgroup.hasNewAlert = this.workgroupHasNewAlert(alertNotifications); - const completionStatus = this.getCompletionStatusByWorkgroupId(workgroupId); - workgroup.isVisible = completionStatus.isVisible ? 1 : 0; - workgroup.completionStatus = this.getWorkgroupCompletionStatus(completionStatus); - workgroup.score = this.annotationService.getTotalNodeScoreForWorkgroup( - workgroupId, - this.nodeId - ); - const studentStatus = this.classroomStatusService.getStudentStatusForWorkgroupId(workgroupId); - workgroup.nodeStatus = studentStatus.nodeStatuses[this.nodeId] || {}; - } - - private workgroupHasNewAlert(alertNotifications: Notification[]): boolean { - for (const alert of alertNotifications) { - if (!alert.timeDismissed) { - return true; - } - } - return false; - } - - private getCompletionStatusByWorkgroupId(workgroupId: number): CompletionStatus { - const completionStatus: CompletionStatus = { - isCompleted: false, - isVisible: false, - latestWorkTime: null, - latestAnnotationTime: null - }; - const studentStatus = this.classroomStatusService.getStudentStatusForWorkgroupId(workgroupId); - if (studentStatus != null) { - const nodeStatus = studentStatus.nodeStatuses[this.nodeId]; - if (nodeStatus) { - completionStatus.isVisible = nodeStatus.isVisible; - // TODO: store this info in the nodeStatus so we don't have to calculate every time? - completionStatus.latestWorkTime = this.getLatestWorkTimeByWorkgroupId(workgroupId); - completionStatus.latestAnnotationTime = - this.getLatestAnnotationTimeByWorkgroupId(workgroupId); - if (!this.projectService.nodeHasWork(this.nodeId)) { - completionStatus.isCompleted = nodeStatus.isVisited; - } - if (completionStatus.latestWorkTime) { - completionStatus.isCompleted = nodeStatus.isCompleted; - } - } - } - return completionStatus; - } - - private getLatestWorkTimeByWorkgroupId(workgroupId: number): string { - const componentStates = this.dataService.getComponentStatesByNodeId(this.nodeId); - for (const componentState of componentStates.reverse()) { - if (componentState.workgroupId === workgroupId) { - return componentState.serverSaveTime; - } - } - return null; - } - - private getLatestAnnotationTimeByWorkgroupId(workgroupId: number): string { - const annotations = this.dataService.getAnnotationsByNodeId(this.nodeId); - for (const annotation of annotations.reverse()) { - // TODO: support checking for annotations from shared teachers - if ( - annotation.toWorkgroupId === workgroupId && - annotation.fromWorkgroupId === this.configService.getWorkgroupId() - ) { - return annotation.serverSaveTime; - } - } - return null; - } - - /** - * Returns a numerical status value for a given completion status object depending on node - * completion - * Available status values are: 0 (not visited/no work; default), 1 (partially completed), - * 2 (completed) - * @param completionStatus Object - * @returns Integer status value - */ - private getWorkgroupCompletionStatus(completionStatus: CompletionStatus): number { - // TODO: store this info in the nodeStatus so we don't have to calculate every time (and can use - // more widely)? - let status = 0; - if (!completionStatus.isVisible) { - status = -1; - } else if (completionStatus.isCompleted) { - status = 2; - } else if (completionStatus.latestWorkTime !== null) { - status = 1; - } - return status; - } - - getNodeCompletion(nodeId: string): number { - return this.classroomStatusService.getNodeCompletion( - nodeId, - this.dataService.getCurrentPeriodId() - ).completionPct; - } - - getNodeAverageScore(): any { - const averageScore = this.classroomStatusService.getNodeAverageScore( - this.nodeId, - this.dataService.getCurrentPeriodId() - ); - if (averageScore === null) { - return 'N/A'; - } else { - return averageScore; - } - } - - isWorkgroupShown(workgroup: any): boolean { - return this.dataService.isWorkgroupShown(workgroup); - } - - protected showRubric(): void { - this.dialog.open(ShowNodeInfoDialogComponent, { - data: this.nodeId, - width: '90%' - }); - } - - setSort(value: string): void { - if (this.sort === value) { - this.sort = `-${value}`; - } else { - this.sort = value; - } - this.dataService.nodeGradingSort = this.sort; - this.sortWorkgroups(); - } - - expandAll(): void { - for (const workgroup of this.workgroups) { - const workgroupId = workgroup.workgroupId; - if (this.workgroupInViewById[workgroupId]) { - this.workVisibilityById[workgroupId] = true; - } - } - this.isExpandAll = true; - } - - collapseAll(): void { - for (const workgroup of this.workgroups) { - this.workVisibilityById[workgroup.workgroupId] = false; - } - this.isExpandAll = false; - } - - onUpdateExpand({ workgroupId, value }): void { - this.workVisibilityById[workgroupId] = value; - } - - onUpdateHiddenComponents(value: any): void { - this.hiddenComponents = copy(value); - } - - onIntersection( - workgroupId: number, - intersectionObserverEntries: IntersectionObserverEntry[] - ): void { - for (const entry of intersectionObserverEntries) { - this.workgroupInViewById[workgroupId] = entry.isIntersecting; - if (this.isExpandAll && entry.isIntersecting) { - this.workVisibilityById[workgroupId] = true; - } - } - } - - showReport(): void { - this.dialog.open(MilestoneDetailsDialogComponent, { - data: this.milestoneReport, - panelClass: 'dialog-lg' - }); - } - - showPeerGroupDetails(peerGroupingTag: string): void { - this.peerGroupService.showPeerGroupDetails(peerGroupingTag); - } - - trackWorkgroup(index: number, workgroup: any) { - return ( - `${workgroup.workgroupId}-${workgroup.completionStatus}-${workgroup.score}-` + - `${workgroup.hasAlert}-${workgroup.hasNewAlert}-${workgroup.isVisible}` - ); - } -} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.html index e69de29bb2d..a6297d513c9 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.html +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.html @@ -0,0 +1,64 @@ +
+
+
+
+

+ {{ nodeCompletionPercent }}% Step Completion +

+ @if (hasWork && nodeAverageScore != null) { +

+ {{ nodeAverageScore }}/{{ nodeMaxScore ?? '0' }} + Mean Step Score +

+ } +
+
+ +
+
+
+

Question Summaries

+ @if (summariesVisible) { + Hide + } @else { + Show + } +
+ @if (summariesVisible) { +
+ + @for (component of components; track component; let i = $index) { + + + + + + } + +
+ } +
+
+

Class Responses

+ +
+ +
+
diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.spec.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.spec.ts new file mode 100644 index 00000000000..f2327e47842 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.spec.ts @@ -0,0 +1,159 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NodeGradingComponent } from './node-grading.component'; +import { TeacherProjectService } from '../../../../services/teacherProjectService'; +import { TeacherDataService } from '../../../../services/teacherDataService'; +import { MockComponents, MockProviders } from 'ng-mocks'; +import { ClassroomStatusService } from '../../../../services/classroomStatusService'; +import { Node } from '../../../../common/Node'; +import { Observable, Subject } from 'rxjs'; +import { WorkgroupService } from '../../../../../../app/services/workgroup.service'; +import { FilterComponentsComponent } from '../filter-components/filter-components.component'; +import { ComponentTypeService } from '../../../../services/componentTypeService'; +import { ComponentSummaryComponent } from '../../component-summary/component-summary.component'; +import { NodeClassResponsesComponent } from '../node-class-responses/node-class-responses.component'; +import { AnnotationService } from '../../../../services/annotationService'; +import { Annotation } from '../../../../common/Annotation'; +import { BranchService } from '../../../../services/branchService'; +import { ComponentServiceLookupService } from '../../../../services/componentServiceLookupService'; +import { provideHttpClient } from '@angular/common/http'; +import { ConfigService } from '../../../../services/configService'; +import { PathService } from '../../../../services/pathService'; + +let classroomStatusService: ClassroomStatusService; +let component: NodeGradingComponent; +let dataService: TeacherDataService; +let fixture: ComponentFixture; +let nodeCompletionSpy; + +class MockDataService { + private currentNodeChangedSource: Subject = new Subject(); + public currentNodeChanged$ = this.currentNodeChangedSource.asObservable(); + private currentPeriodChangedSource: Subject = new Subject(); + public currentPeriodChanged$: Observable = this.currentPeriodChangedSource.asObservable(); + + getCurrentPeriodId(): number { + return 1; + } + + setCurrentNodeByNodeId(): void {} + + setCurrentPeriod(period: any): void { + this.currentPeriodChangedSource.next({ + previousPeriod: null, + currentPeriod: period + }); + } +} + +class MockAnnotationService { + private annotationReceivedSource: Subject = new Subject(); + public readonly annotationReceived$: Observable = + this.annotationReceivedSource.asObservable(); + broadcastAnnotationReceived(annotation: Annotation): void { + this.annotationReceivedSource.next(annotation); + } +} + +class MockProjectService { + private projectSavedSource: Subject = new Subject(); + public readonly projectSaved$: Observable = this.projectSavedSource.asObservable(); + broadcastProjectSaved() { + this.projectSavedSource.next({}); + } + nodeHasWork(): boolean { + return false; + } + getNode(): Node { + return null; + } + getComponents(): any[] { + return []; + } + componentHasWork(): boolean { + return false; + } +} + +describe('NodeGradingComponent', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + MockComponents( + ComponentSummaryComponent, + FilterComponentsComponent, + NodeClassResponsesComponent + ) + ], + imports: [NodeGradingComponent], + providers: [ + { provide: AnnotationService, useClass: MockAnnotationService }, + { provide: TeacherProjectService, MockProjectService }, + MockProviders( + BranchService, + ClassroomStatusService, + ComponentServiceLookupService, + ComponentTypeService, + ConfigService, + PathService, + WorkgroupService + ), + { provide: TeacherDataService, useClass: MockDataService }, + provideHttpClient() + ] + }).compileComponents(); + const projectService = TestBed.inject(TeacherProjectService); + classroomStatusService = TestBed.inject(ClassroomStatusService); + spyOn(projectService, 'nodeHasWork').and.returnValue(false); + const node = new Node(); + node.components = [{ id: 'component1' }]; + spyOn(projectService, 'getNode').and.returnValue(node); + spyOn(projectService, 'getComponents').and.returnValue([{ id: 'abc', type: 'MultipleChoice' }]); + spyOn(projectService, 'componentHasWork').and.returnValue(true); + spyOn(projectService, 'getMaxScoreForNode').and.returnValue(5); + dataService = TestBed.inject(TeacherDataService); + spyOn(dataService, 'getCurrentPeriodId').and.returnValue(1); + nodeCompletionSpy = spyOn(classroomStatusService, 'getNodeCompletion').and.returnValue({ + completionPct: 50 + }); + fixture = TestBed.createComponent(NodeGradingComponent); + component = fixture.componentInstance; + component.nodeId = 'node1'; + component.ngOnInit(); + }); + + annotationReceived_RecalculateNodeCompletion(); + periodChanged_RecalculateNodeCompletion(); + projectSaved_RecalculateNodeCompletion(); +}); + +function periodChanged_RecalculateNodeCompletion() { + describe('period changed', () => { + it('recalculates node completion', () => { + nodeCompletionSpy.calls.reset(); + dataService.setCurrentPeriod({ periodId: 1 }); + expect(nodeCompletionSpy).toHaveBeenCalledTimes(1); + }); + }); +} + +function annotationReceived_RecalculateNodeCompletion() { + describe('annotation received', () => { + it('recalculates node completion', () => { + nodeCompletionSpy.calls.reset(); + const annotationService = TestBed.inject(AnnotationService); + annotationService.broadcastAnnotationReceived({} as Annotation); + expect(nodeCompletionSpy).toHaveBeenCalledTimes(1); + }); + }); +} + +function projectSaved_RecalculateNodeCompletion() { + describe('project saved', () => { + it('recalculates node completion', () => { + nodeCompletionSpy.calls.reset(); + const projectService = TestBed.inject(TeacherProjectService); + projectService.broadcastProjectSaved(); + expect(nodeCompletionSpy).toHaveBeenCalledTimes(1); + }); + }); +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.ts new file mode 100644 index 00000000000..beb33082d38 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.ts @@ -0,0 +1,147 @@ +import { Component, Input, OnInit, OnDestroy, OnChanges } from '@angular/core'; +import { TeacherProjectService } from '../../../../services/teacherProjectService'; +import { ClassroomStatusService } from '../../../../services/classroomStatusService'; +import { TeacherDataService } from '../../../../services/teacherDataService'; +import { CommonModule } from '@angular/common'; +import { MatIconModule } from '@angular/material/icon'; +import { Node } from '../../../../common/Node'; +import { Subscription } from 'rxjs'; +import { MatButtonModule } from '@angular/material/button'; +import { FilterComponentsComponent } from '../filter-components/filter-components.component'; +import { ComponentContent } from '../../../../common/ComponentContent'; +import { NodeClassResponsesComponent } from '../node-class-responses/node-class-responses.component'; +import { MatTabsModule } from '@angular/material/tabs'; +import { ComponentTypeService } from '../../../../services/componentTypeService'; +import { ComponentSummaryComponent } from '../../component-summary/component-summary.component'; +import { FormControl } from '@angular/forms'; +import { AnnotationService } from '../../../../services/annotationService'; + +@Component({ + imports: [ + CommonModule, + ComponentSummaryComponent, + FilterComponentsComponent, + MatButtonModule, + MatIconModule, + MatTabsModule, + NodeClassResponsesComponent + ], + styles: [ + ` + .content-head-label { + font-size: 50%; + } + + .component-select { + padding: 6px 12px; + } + + .mat-body-1 { + margin: 0; + } + ` + ], + templateUrl: './node-grading.component.html' +}) +export class NodeGradingComponent implements OnInit, OnDestroy, OnChanges { + protected components: ComponentContent[]; + protected hasWork: boolean; + protected node: Node; + protected nodeAverageScore: number; + protected nodeCompletionPercent: number; + protected nodeMaxScore: number; + @Input() nodeId: string; + protected numRubrics: number; + protected periodId: number; + protected selectedComponent: FormControl = new FormControl(); + private subscriptions: Subscription = new Subscription(); + protected summariesVisible: boolean = true; + protected visibleComponents: ComponentContent[]; + + constructor( + private annotationService: AnnotationService, + private classroomStatusService: ClassroomStatusService, + private componentTypeService: ComponentTypeService, + private dataService: TeacherDataService, + private projectService: TeacherProjectService + ) {} + + ngOnInit(): void { + this.setFields(); + this.subscriptions.add( + this.dataService.currentPeriodChanged$.subscribe(() => this.setPeriod()) + ); + this.subscriptions.add( + this.annotationService.annotationReceived$.subscribe(() => this.setPeriod()) + ); + this.subscriptions.add(this.projectService.projectSaved$.subscribe(() => this.setFields())); + this.subscriptions.add( + this.dataService.currentNodeChanged$.subscribe(() => this.selectedComponent.setValue(0)) + ); + } + + ngOnDestroy(): void { + this.subscriptions.unsubscribe(); + } + + ngOnChanges(): void { + this.setFields(); + } + + private setFields(): void { + this.hasWork = this.projectService.nodeHasWork(this.nodeId); + this.node = this.projectService.getNode(this.nodeId); + this.nodeAverageScore = this.classroomStatusService.getNodeAverageScore( + this.nodeId, + this.dataService.getCurrentPeriodId() + ); + this.nodeMaxScore = this.projectService.getMaxScoreForNode(this.nodeId); + this.components = this.projectService + .getComponents(this.nodeId) + .filter((component) => this.projectService.componentHasWork(component)) + .map((component, index) => { + component['displayIndex'] = index + 1; + return component; + }); + this.visibleComponents = this.components; + this.numRubrics = this.node.getNumRubrics(); + this.setPeriod(); + } + + private setPeriod(): void { + this.periodId = this.dataService.getCurrentPeriodId(); + this.setNodeAverageScore(); + this.setNodeCompletionPercent(); + } + + private setNodeAverageScore(): void { + this.nodeAverageScore = this.classroomStatusService.getNodeAverageScore( + this.nodeId, + this.periodId + ); + } + + private setNodeCompletionPercent(): void { + this.nodeCompletionPercent = this.classroomStatusService.getNodeCompletion( + this.nodeId, + this.periodId + ).completionPct; + } + + protected setVisibleComponents(visibleComponents: ComponentContent[]): void { + this.visibleComponents = visibleComponents; + } + + protected previewProject(): void { + window.open(this.dataService.getPreviewUrl()); + } + + protected getComponentTypeLabel(componentType: string): string { + return this.componentTypeService.getComponentTypeLabel(componentType); + } + + protected toggleSummaries(event: Event): void { + event.preventDefault(); + this.summariesVisible = !this.summariesVisible; + } +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.html new file mode 100644 index 00000000000..1aefee35ce2 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.html @@ -0,0 +1,66 @@ +
+ + @if (expanded && !disabled) { + +
+ @for (component of components; track component.id; let i = $index) { + @if (componentIdToIsVisible[component.id]) { +
+
+

+ {{ component.displayIndex + '. ' + getComponentTypeLabel(component.type) }}  + +

+ +
+
+ } + } +
+
+ } +
diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.scss b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.scss new file mode 100644 index 00000000000..57e36e9976f --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.scss @@ -0,0 +1,24 @@ +.grading__item-container { + height: auto; +} + +.node-workgroup-item { + .team-button { + min-height: 56px; + text-transform: none; + text-align: initial; + } + + .mdc-button__label { + text-transform: none; + width: 100%; + } + + .mdc-list-item.mdc-list-item--with-one-line { + height: auto; + } + + .mat-headline-5 { + margin: 0; + } +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.spec.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.spec.ts new file mode 100644 index 00000000000..48803a537b6 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.spec.ts @@ -0,0 +1,40 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NodeWorkgroupItemComponent } from './node-workgroup-item.component'; +import { MockProvider, MockProviders } from 'ng-mocks'; +import { AnnotationService } from '../../../../services/annotationService'; +import { ComponentTypeService } from '../../../../services/componentTypeService'; +import { TeacherProjectService } from '../../../../services/teacherProjectService'; +import { Node } from '../../../../common/Node'; +import { Annotation } from '../../../../common/Annotation'; +import { of } from 'rxjs'; + +describe('NodeWorkgroupItemComponent', () => { + let component: NodeWorkgroupItemComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [NodeWorkgroupItemComponent], + providers: [ + MockProvider(AnnotationService, { + annotationReceived$: of({} as Annotation) + }), + MockProviders(ComponentTypeService, TeacherProjectService) + ] + }).compileComponents(); + + fixture = TestBed.createComponent(NodeWorkgroupItemComponent); + component = fixture.componentInstance; + component.node = { id: 'node1' } as Node; + component.components = []; + component.workgroup = { workgroupId: 1, nodeStatus: { componentStatus: {} } }; + fixture.detectChanges(); + }); + + it('should show team 1 with status', () => { + expect(component).toBeTruthy(); + const textContent = fixture.nativeElement.textContent; + expect(textContent).toContain('Team 1'); + expect(textContent).toContain('Not Visited'); + }); +}); diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.ts new file mode 100644 index 00000000000..41f7b6b1c3c --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.ts @@ -0,0 +1,163 @@ +import { + Component, + EventEmitter, + Input, + Output, + SimpleChanges, + ViewEncapsulation +} from '@angular/core'; +import { calculateComponentVisibility } from '../../shared/grading-helpers/grading-helpers'; +import { ComponentTypeService } from '../../../../services/componentTypeService'; +import { TeacherProjectService } from '../../../../services/teacherProjectService'; +import { WorkgroupComponentGradingComponent } from '../../workgroup-component-grading/workgroup-component-grading.component'; +import { ComponentNewWorkBadgeComponent } from '../../../../../../app/classroom-monitor/component-new-work-badge/component-new-work-badge.component'; +import { WorkgroupNodeScoreComponent } from '../../shared/workgroupNodeScore/workgroup-node-score.component'; +import { WorkgroupNodeStatusComponent } from '../../../../../../app/classroom-monitor/workgroup-node-status/workgroup-node-status.component'; +import { WorkgroupInfoComponent } from '../workgroupInfo/workgroup-info.component'; +import { FlexLayoutModule } from '@angular/flex-layout'; +import { MatListModule } from '@angular/material/list'; +import { MatButtonModule } from '@angular/material/button'; +import { CommonModule } from '@angular/common'; +import { Node } from '../../../../common/Node'; +import { ComponentContent } from '../../../../common/ComponentContent'; +import { filter, Subscription } from 'rxjs'; +import { AnnotationService } from '../../../../services/annotationService'; + +@Component({ + encapsulation: ViewEncapsulation.None, + imports: [ + CommonModule, + MatButtonModule, + MatListModule, + FlexLayoutModule, + WorkgroupInfoComponent, + WorkgroupNodeStatusComponent, + WorkgroupNodeScoreComponent, + ComponentNewWorkBadgeComponent, + WorkgroupComponentGradingComponent + ], + selector: 'node-workgroup-item', + styleUrl: './node-workgroup-item.component.scss', + templateUrl: './node-workgroup-item.component.html' +}) +export class NodeWorkgroupItemComponent { + private componentIdToHasWork: { [componentId: string]: boolean } = {}; + protected componentIdToIsVisible: { [componentId: string]: boolean } = {}; + @Input() components: ComponentContent[] = []; + protected disabled: boolean; + @Input() expanded: boolean; + protected hasAlert: boolean; + protected hasNewAlert: boolean; + @Input() maxScore: number; + private nodeHasWork: boolean; + @Input() node: Node; + @Output() onUpdateExpand: EventEmitter = new EventEmitter(); + protected score: any; + private status: any; + protected statusClass: string; + protected statusText: string = ''; + private subscriptions: Subscription = new Subscription(); + @Input() workgroup: any; + + constructor( + private annotationService: AnnotationService, + private componentTypeService: ComponentTypeService, + private projectService: TeacherProjectService + ) {} + + ngOnInit(): void { + this.updateNode(); + this.updateStatus(); + this.subscribeToAnnotations(); + } + + private subscribeToAnnotations(): void { + this.subscriptions.add( + this.annotationService.annotationReceived$ + .pipe( + filter( + (annotation) => + annotation.nodeId === this.node.id && + annotation.toWorkgroupId === this.workgroup.workgroupId + ) + ) + .subscribe( + () => + (this.score = this.annotationService.getTotalNodeScore( + this.workgroup.workgroupId, + this.node, + this.components + )) + ) + ); + } + + private updateNode(): void { + this.nodeHasWork = this.projectService.nodeHasWork(this.node.id); + this.componentIdToHasWork = this.projectService.calculateComponentIdToHasWork(this.components); + this.componentIdToIsVisible = calculateComponentVisibility( + this.componentIdToHasWork, + this.workgroup.nodeStatus.componentStatuses + ); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes.workgroup) { + const workgroup = changes.workgroup.currentValue; + this.hasAlert = workgroup.hasAlert; + this.hasNewAlert = workgroup.hasNewAlert; + this.status = workgroup.completionStatus; + this.score = workgroup.score != null ? workgroup.score : '-'; + this.workgroup = workgroup; + this.updateNode(); + this.updateStatus(); + } + if (changes.nodeId) { + this.updateNode(); + } + } + + ngOnDestroy(): void { + this.subscriptions.unsubscribe(); + } + + protected getComponentTypeLabel(componentType): string { + return this.componentTypeService.getComponentTypeLabel(componentType); + } + + private updateStatus(): void { + switch (this.status) { + case -1: + this.statusClass = ' '; + this.statusText = $localize`Not Assigned`; + break; + case 2: + this.statusClass = 'success'; + if (this.nodeHasWork) { + this.statusText = $localize`Completed`; + } else { + this.statusText = $localize`Visited`; + } + break; + case 1: + this.statusClass = 'text'; + this.statusText = $localize`Partially Completed`; + break; + default: + this.statusClass = 'text-secondary'; + if (this.nodeHasWork) { + this.statusText = $localize`No Work`; + } else { + this.statusText = $localize`Not Visited`; + } + } + if (this.hasNewAlert) { + this.statusClass = 'warn'; + } + this.disabled = this.status === -1; + } + + protected toggleExpand(): void { + this.onUpdateExpand.emit({ workgroupId: this.workgroup.workgroupId, value: !this.expanded }); + } +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.html index dbe481a7898..6faad79a21e 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.html +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.html @@ -43,7 +43,7 @@ id="component_{{ component.id }}_{{ workgroupId }}" class="component component--grading" > -
+

{{ i + 1 + '. ' + getComponentTypeLabel(component.type) }}  ; @@ -11,8 +12,8 @@ let teacherProjectService: TeacherProjectService; describe('WorkgroupItemComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [WorkgroupItemComponent, ClassroomMonitorTestingModule, ComponentTypeServiceModule], - providers: [TeacherProjectService] + imports: [WorkgroupItemComponent], + providers: [MockProviders(ComponentTypeService, TeacherProjectService)] }).compileComponents(); }); @@ -29,7 +30,8 @@ describe('WorkgroupItemComponent', () => { fixture.detectChanges(); }); - it('should create', () => { - expect(component).toBeTruthy(); + it('toggle expand button should be enabled', () => { + const button = fixture.debugElement.query(By.css('button')); + expect(button.nativeElement.disabled).toBe(false); }); }); diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.ts index d81b602ebd9..da1afeaaa56 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.ts +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.ts @@ -36,7 +36,6 @@ export class WorkgroupItemComponent { @Input() expanded: boolean; protected hasAlert: boolean; protected hasNewAlert: boolean; - @Input() hiddenComponents: string[] = []; @Input() maxScore: number; private nodeHasWork: boolean; @Input() nodeId: string; @@ -89,10 +88,6 @@ export class WorkgroupItemComponent { } } - protected isComponentVisible(componentId: string): boolean { - return !this.hiddenComponents.includes(componentId); - } - protected getComponentTypeLabel(componentType): string { return this.componentTypeService.getComponentTypeLabel(componentType); } diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component.html index 4ebe5e9fd58..4fb98aef40b 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component.html +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component.html @@ -27,8 +27,3 @@

} -@if (isApplicationNode(nodeId)) { -
- -
-} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component.spec.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component.spec.ts index e8c01283c64..7f4b232af72 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component.spec.ts +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component.spec.ts @@ -4,7 +4,6 @@ import { MatDialog } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; import { MatListModule } from '@angular/material/list'; import { Observable, Subject } from 'rxjs'; -import { ComponentSelectComponent } from '../../../../../../app/classroom-monitor/component-select/component-select.component'; import { DialogWithOpenInNewWindowComponent } from '../../../../directives/dialog-with-open-in-new-window/dialog-with-open-in-new-window.component'; import { MilestoneService } from '../../../../services/milestoneService'; import { TeacherDataService } from '../../../../services/teacherDataService'; @@ -100,13 +99,7 @@ describe('NodeProgressViewComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [NodeProgressViewComponent], - imports: [ - ClassroomMonitorTestingModule, - ComponentSelectComponent, - FlexLayoutModule, - MatIconModule, - MatListModule - ], + imports: [ClassroomMonitorTestingModule, FlexLayoutModule, MatIconModule, MatListModule], providers: [ { provide: MilestoneService, diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component.ts index ee2e5047afa..673ecd76f66 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component.ts +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeProgress/node-progress-view/node-progress-view.component.ts @@ -58,7 +58,7 @@ export class NodeProgressViewComponent implements OnInit { this.router.navigate([ '/teacher/manage/unit', this.configService.getRunId(), - 'node', + this.isApplicationNode(this.nodeId) ? 'node' : 'group', this.nodeId ]); }) diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/peer-group-button/peer-group-button.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/peer-group-button/peer-group-button.component.html new file mode 100644 index 00000000000..c195f340f01 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/peer-group-button/peer-group-button.component.html @@ -0,0 +1,8 @@ +@if (peerGroupingTag) { + +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/peer-group-button/peer-group-button.component.spec.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/peer-group-button/peer-group-button.component.spec.ts new file mode 100644 index 00000000000..03bd074fe68 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/peer-group-button/peer-group-button.component.spec.ts @@ -0,0 +1,46 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { PeerGroupButtonComponent } from './peer-group-button.component'; +import { MockService } from 'ng-mocks'; +import { TeacherPeerGroupService } from '../../../services/teacherPeerGroupService'; + +let component: PeerGroupButtonComponent; +let fixture: ComponentFixture; +describe('PeerGroupButtonComponent', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [PeerGroupButtonComponent], + providers: [ + { provide: TeacherPeerGroupService, useValue: MockService(TeacherPeerGroupService) } + ] + }).compileComponents(); + + fixture = TestBed.createComponent(PeerGroupButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + peerGroupAvailable(); + peerGroupNotAvailable(); +}); + +function peerGroupAvailable() { + describe('peer group is available', () => { + beforeEach(() => { + component.component = { peerGroupingTag: 'tag' }; + component.ngOnChanges(); + fixture.detectChanges(); + }); + it('should show button', () => { + const button = fixture.debugElement.nativeElement.querySelector('button'); + expect(button).toBeTruthy(); + }); + }); +} + +function peerGroupNotAvailable() { + describe('peer group is not available', () => { + it('should hide button', () => { + const button = fixture.debugElement.nativeElement.querySelector('button'); + expect(button).toBeFalsy(); + }); + }); +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/peer-group-button/peer-group-button.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/peer-group-button/peer-group-button.component.ts new file mode 100644 index 00000000000..6bc78e700d9 --- /dev/null +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/peer-group-button/peer-group-button.component.ts @@ -0,0 +1,27 @@ +import { CommonModule } from '@angular/common'; +import { Component, Input } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MatIconModule } from '@angular/material/icon'; +import { Node } from '../../../common/Node'; +import { TeacherPeerGroupService } from '../../../services/teacherPeerGroupService'; + +@Component({ + imports: [CommonModule, MatButtonModule, MatIconModule], + selector: 'peer-group-button', + templateUrl: './peer-group-button.component.html' +}) +export class PeerGroupButtonComponent { + @Input() component: any; + @Input() node: Node; + protected peerGroupingTag: string; + + constructor(private peerGroupService: TeacherPeerGroupService) {} + + ngOnChanges(): void { + this.peerGroupingTag = this.component?.peerGroupingTag; + } + + protected showPeerGroup(): void { + this.peerGroupService.showPeerGroupDetails(this.peerGroupingTag); + } +} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/CompletionStatus.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/CompletionStatus.ts index af358eda294..f6433f85b00 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/CompletionStatus.ts +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/CompletionStatus.ts @@ -1,6 +1,34 @@ -export interface CompletionStatus { +export class CompletionStatus { isCompleted: boolean; isVisible: boolean; latestWorkTime: string; latestAnnotationTime: string; + + constructor() { + this.isCompleted = false; + this.isVisible = false; + this.latestWorkTime = null; + this.latestAnnotationTime = null; + } + + /** + * Returns a numerical status value for this completion status object depending on node completion + * Available status values are: + * -1 (not visible) + * 0 (not visited/no work; default) + * 1 (partially completed) + * 2 (completed) + * @returns number status value + */ + getStateNumber(): number { + let status = 0; + if (!this.isVisible) { + status = -1; + } else if (this.isCompleted) { + status = 2; + } else if (this.latestWorkTime !== null) { + status = 1; + } + return status; + } } diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/node-info/node-info.component.html b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/node-info/node-info.component.html deleted file mode 100644 index e0d3f61227b..00000000000 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/node-info/node-info.component.html +++ /dev/null @@ -1,85 +0,0 @@ -@if (node.rubric) { - - - info - Step Info - - - -} - - - @for (component of node.components; track component.id; let isFirst = $first) { -
- @if (!isFirst) { - - } - @if (component.isStudentWorkGenerated) { -

- {{ component.assessmentItemIndex + '. ' + component.typeLabel }}  -

- } - - @if (component.rubric) { - - - info - Item Info - - - - } - @if (component.hasResponsesSummary && component.type === 'MultipleChoice') { - - } - @if (component.hasScoresSummary && component.hasScoreAnnotation) { - - } - @if ( - component.hasResponsesSummary && - ['DialogGuidance', 'OpenResponse'].includes(component.type) - ) { - - } - @if (component.type === 'Match') { - - } -
- } -
-
diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/node-info/node-info.component.scss b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/node-info/node-info.component.scss deleted file mode 100644 index a5f49abe6f3..00000000000 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/node-info/node-info.component.scss +++ /dev/null @@ -1,45 +0,0 @@ -@use 'style/abstracts/variables'; - -.rubric { - margin-bottom: 16px; -} - -.component { - padding-bottom: 16px; - - &:first-of-type { - .component-header { - border-top-left-radius: variables.$button-border-radius; - border-top-right-radius: variables.$button-border-radius; - } - } -} - -.component-header { - padding: 8px 12px; - margin: -16px -16px 0; -} - -.component-rubric { - padding: 8px; - - .mat-mdc-card-content { - padding: 8px; - border-radius: variables.$button-border-radius; - overflow: auto; - } -} - -.node-info { - .item-divider { - margin-left: -16px; - margin-right: -16px; - right: 0; - width: auto; - } -} - -.summary-display { - display: block; - margin: 16px 0; -} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/node-info/node-info.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/node-info/node-info.component.ts deleted file mode 100644 index 097579ad51a..00000000000 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/node-info/node-info.component.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { AnnotationService } from '../../../../services/annotationService'; -import { Component, Input } from '@angular/core'; -import { ComponentFactory } from '../../../../common/ComponentFactory'; -import { ComponentServiceLookupService } from '../../../../services/componentServiceLookupService'; -import { ComponentTypeService } from '../../../../services/componentTypeService'; -import { IdeasSummaryComponent } from '../../../../directives/teacher-summary-display/ideas-summary-display/ideas-summary.component'; -import { FlexLayoutModule } from '@angular/flex-layout'; -import { isMatchingPeriods } from '../../../../common/period/period'; -import { MatCardModule } from '@angular/material/card'; -import { MatchSummaryDisplayComponent } from '../../../../directives/teacher-summary-display/match-summary-display/match-summary-display.component'; -import { MatDividerModule } from '@angular/material/divider'; -import { MatIconModule } from '@angular/material/icon'; -import { Node } from '../../../../common/Node'; -import { PreviewComponentComponent } from '../../../../authoringTool/components/preview-component/preview-component.component'; -import { SummaryService } from '../../../../components/summary/summaryService'; -import { TeacherDataService } from '../../../../services/teacherDataService'; -import { TeacherProjectService } from '../../../../services/teacherProjectService'; -import { TeacherSummaryDisplayComponent } from '../../../../directives/teacher-summary-display/teacher-summary-display.component'; - -@Component({ - imports: [ - FlexLayoutModule, - IdeasSummaryComponent, - MatCardModule, - MatchSummaryDisplayComponent, - MatIconModule, - MatDividerModule, - PreviewComponentComponent, - TeacherSummaryDisplayComponent - ], - selector: 'node-info', - styleUrl: 'node-info.component.scss', - templateUrl: 'node-info.component.html' -}) -export class NodeInfoComponent { - protected node: Node; - @Input() nodeId: string; - protected periodId: number; - protected source: 'allPeriods' | 'period'; - - constructor( - private annotationService: AnnotationService, - private componentServiceLookupService: ComponentServiceLookupService, - private componentTypeService: ComponentTypeService, - private dataService: TeacherDataService, - private projectService: TeacherProjectService, - private summaryService: SummaryService - ) {} - - ngOnInit(): void { - this.periodId = this.dataService.getCurrentPeriodId(); - this.source = this.periodId === -1 ? 'allPeriods' : 'period'; - this.node = this.projectService.getNode(this.nodeId); - if (this.node.rubric != null) { - this.node.rubric = this.projectService.replaceAssetPaths(this.node.rubric); - } - this.populateComponentFields(); - } - - private populateComponentFields(): void { - let assessmentItemIndex = 1; - for (const component of this.node.components) { - component.typeLabel = this.componentTypeService.getComponentTypeLabel(component.type); - component.rubric = this.projectService.replaceAssetPaths(component.rubric); - component.hasCorrectAnswer = this.componentHasCorrectAnswer(component); - component.hasResponsesSummary = - this.summaryService.isResponsesSummaryAvailableForComponentType(component.type); - component.hasScoresSummary = this.summaryService.isScoresSummaryAvailableForComponentType( - component.type - ); - component.hasScoreAnnotation = this.hasScoreAnnotation( - this.nodeId, - component.id, - this.periodId - ); - component.isStudentWorkGenerated = this.projectService.componentHasWork(component); - if (component.isStudentWorkGenerated) { - component.assessmentItemIndex = assessmentItemIndex++; - } - component.component = new ComponentFactory().getComponent( - this.projectService.injectAssetPaths(component), - this.nodeId - ); - } - } - - private hasScoreAnnotation(nodeId: string, componentId: string, periodId: number): boolean { - return this.annotationService - .getAnnotationsByNodeIdComponentId(nodeId, componentId) - .some( - (annotation) => - isMatchingPeriods(annotation.periodId, periodId) && - ['score', 'autoScore'].includes(annotation.type) - ); - } - - private componentHasCorrectAnswer(component: any): boolean { - return this.componentServiceLookupService - .getService(component.type) - .componentHasCorrectAnswer(component); - } -} diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/tool-bar/tool-bar.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/tool-bar/tool-bar.component.ts index 8d5290a7bff..563fd6ac1b4 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/tool-bar/tool-bar.component.ts +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/tool-bar/tool-bar.component.ts @@ -67,7 +67,7 @@ export class ToolBarComponent implements OnInit { }[path] ?? $localize`Grade by Step`; this.showPeriodSelect = path != 'export'; this.showTeamTools = /\/team\/(\d+)$/.test(this.router.url); - this.showStepTools = /node\/node(\d+)$/.test(this.router.url); + this.showStepTools = /node\/node(\d+)/.test(this.router.url); } protected toggleMenu(): void { diff --git a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/top-bar/top-bar.component.ts b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/top-bar/top-bar.component.ts index 2acdf321cf5..218f580b165 100644 --- a/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/top-bar/top-bar.component.ts +++ b/src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/top-bar/top-bar.component.ts @@ -15,21 +15,23 @@ import { CommonModule } from '@angular/common'; import { FlexLayoutModule } from '@angular/flex-layout'; import { NotificationsMenuComponent } from '../notifications-menu/notifications-menu.component'; import { PauseScreensMenuComponent } from '../../pause-screens-menu/pause-screens-menu.component'; +import { MatTooltipModule } from '@angular/material/tooltip'; @Component({ - imports: [ - CommonModule, - FlexLayoutModule, - MatButtonModule, - MatIconModule, - MatMenuModule, - MatToolbarModule, - NotificationsMenuComponent, - PauseScreensMenuComponent - ], - selector: 'top-bar', - styleUrl: './top-bar.component.scss', - templateUrl: './top-bar.component.html' + imports: [ + CommonModule, + FlexLayoutModule, + MatButtonModule, + MatIconModule, + MatMenuModule, + MatToolbarModule, + MatTooltipModule, + NotificationsMenuComponent, + PauseScreensMenuComponent + ], + selector: 'top-bar', + styleUrl: './top-bar.component.scss', + templateUrl: './top-bar.component.html' }) export class TopBarComponent implements OnInit { protected avatarColor: any; @@ -106,21 +108,24 @@ export class TopBarComponent implements OnInit { $localize`Warning! You will be editing the content of a classroom unit. If students have already started working, this may result in lost data or other problems.\n\nAre you sure you want to proceed?` ) ) { - if (/unit\/(\d*)\/node\/(\w*)$/.test(this.router.url)) { - this.router.navigate([ - '/teacher/edit/unit', - this.projectId, - 'node', - this.router.url.match(/\/node\/(\w+)$/)[1] - ]); - } else { - this.router.navigate(['/teacher/edit/unit', this.projectId]); + const urlFragments = ['/teacher/edit/unit', this.projectId]; + if (this.isViewingNode()) { + urlFragments.push('node', this.getCurrentNodeId()); } + this.router.navigate(urlFragments); } } + private isViewingNode(): boolean { + return /unit\/(\d*)\/node\/(\w*)$/.test(this.router.url); + } + + private getCurrentNodeId(): string { + return this.router.url.match(/\/node\/(\w+)$/)[1]; + } + protected previewProject(): void { - window.open(`${this.configService.getConfigParam('previewProjectURL')}`); + window.open(this.dataService.getPreviewUrl()); } protected goHome(): void { diff --git a/src/assets/wise5/classroomMonitor/tsconfig.json b/src/assets/wise5/classroomMonitor/tsconfig.json index 5c18d0d290c..3cad346979c 100644 --- a/src/assets/wise5/classroomMonitor/tsconfig.json +++ b/src/assets/wise5/classroomMonitor/tsconfig.json @@ -10,8 +10,17 @@ "experimentalDecorators": true, "resolveJsonModule": true, "target": "es5", - "typeRoots": ["node_modules/@types"], - "lib": ["es2017", "dom"] + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2023", + "dom" + ] }, - "include": ["src/**/*.ts", "../services/projectService.ts", "**/*.ts"] -} + "include": [ + "src/**/*.ts", + "../services/projectService.ts", + "**/*.ts" + ] +} \ No newline at end of file diff --git a/src/assets/wise5/common/stepTools/step-tools.component.ts b/src/assets/wise5/common/stepTools/step-tools.component.ts index c3aab33b425..6464fc93672 100644 --- a/src/assets/wise5/common/stepTools/step-tools.component.ts +++ b/src/assets/wise5/common/stepTools/step-tools.component.ts @@ -16,22 +16,22 @@ import { TeacherDataService } from '../../services/teacherDataService'; import { TeacherProjectService } from '../../services/teacherProjectService'; @Component({ - encapsulation: ViewEncapsulation.None, - imports: [ - CommonModule, - FlexLayoutModule, - FormsModule, - MatButtonModule, - MatFormFieldModule, - MatIconModule, - MatInputModule, - MatSelectModule, - MatTooltipModule, - NodeIconComponent - ], - selector: 'step-tools', - styleUrl: 'step-tools.component.scss', - templateUrl: 'step-tools.component.html' + encapsulation: ViewEncapsulation.None, + imports: [ + CommonModule, + FlexLayoutModule, + FormsModule, + MatButtonModule, + MatFormFieldModule, + MatIconModule, + MatInputModule, + MatSelectModule, + MatTooltipModule, + NodeIconComponent + ], + selector: 'step-tools', + styleUrl: 'step-tools.component.scss', + templateUrl: 'step-tools.component.html' }) export class StepToolsComponent { protected icons: any; @@ -81,8 +81,8 @@ export class StepToolsComponent { this.dataService.setCurrentNodeByNodeId(this.nodeId); } - private updateModel(): void { - this.nodeId = this.dataService.getCurrentNodeId(); + protected updateModel(): void { + this.nodeId = this.getNodeId(); if (this.nodeId == null) { this.prevId = null; this.nextId = null; @@ -96,6 +96,10 @@ export class StepToolsComponent { } } + protected getNodeId(): string { + return this.dataService.getCurrentNodeId(); + } + protected getPrevNodeId(): string { return this.nodeService.getPrevNodeId(this.nodeId); } @@ -117,8 +121,8 @@ export class StepToolsComponent { this.nodeId = this.dataService.getCurrentNodeId(); } - protected goToNextNode(): void { - this.nodeService.goToNextNode().then((nodeId: string) => { + protected goToNextNode(): Promise { + return this.nodeService.goToNextNode().then((nodeId: string) => { this.nodeId = nodeId; }); } diff --git a/src/assets/wise5/components/aiChat/ai-chat.module.ts b/src/assets/wise5/components/aiChat/ai-chat.module.ts index f78ad211248..d74b5554857 100644 --- a/src/assets/wise5/components/aiChat/ai-chat.module.ts +++ b/src/assets/wise5/components/aiChat/ai-chat.module.ts @@ -1,12 +1,14 @@ import { NgModule } from '@angular/core'; import { AiChatMessagesComponent } from './ai-chat-messages/ai-chat-messages.component'; -import { StudentTeacherCommonModule } from '../../../../app/student-teacher-common.module'; import { AiChatBotMessageComponent } from './ai-chat-bot-message/ai-chat-bot-message.component'; import { AiChatStudentMessageComponent } from './ai-chat-student-message/ai-chat-student-message.component'; +import { MatIconModule } from '@angular/material/icon'; +import { CommonModule } from '@angular/common'; +import { FlexLayoutModule } from '@angular/flex-layout'; @NgModule({ declarations: [AiChatBotMessageComponent, AiChatStudentMessageComponent, AiChatMessagesComponent], - imports: [StudentTeacherCommonModule], + imports: [CommonModule, FlexLayoutModule, MatIconModule], exports: [AiChatBotMessageComponent, AiChatStudentMessageComponent, AiChatMessagesComponent] }) export class AiChatModule {} diff --git a/src/assets/wise5/components/dialogGuidance/dialog-response/dialog-response.component.html b/src/assets/wise5/components/dialogGuidance/dialog-response/dialog-response.component.html index b0a52efa80d..e3dbbb53f84 100644 --- a/src/assets/wise5/components/dialogGuidance/dialog-response/dialog-response.component.html +++ b/src/assets/wise5/components/dialogGuidance/dialog-response/dialog-response.component.html @@ -27,11 +27,11 @@ }
{{ displayNames }}
-
+
diff --git a/src/assets/wise5/components/dialogGuidance/dialog-response/dialog-response.component.scss b/src/assets/wise5/components/dialogGuidance/dialog-response/dialog-response.component.scss index 27375aa94ff..86c53f23dfa 100644 --- a/src/assets/wise5/components/dialogGuidance/dialog-response/dialog-response.component.scss +++ b/src/assets/wise5/components/dialogGuidance/dialog-response/dialog-response.component.scss @@ -2,7 +2,6 @@ .response-text { padding: 4px 8px; - display: inline-block; border-radius: variables.$card-border-radius; } diff --git a/src/assets/wise5/components/discussion/discussion-common.module.ts b/src/assets/wise5/components/discussion/discussion-common.module.ts index 5350c1ab3bf..b3c04b6d974 100644 --- a/src/assets/wise5/components/discussion/discussion-common.module.ts +++ b/src/assets/wise5/components/discussion/discussion-common.module.ts @@ -1,12 +1,32 @@ import { NgModule } from '@angular/core'; -import { StudentTeacherCommonModule } from '../../../../app/student-teacher-common.module'; import { StudentComponentModule } from '../../../../app/student/student.component.module'; import { ClassResponse } from './class-response/class-response.component'; import { SaveTimeMessageComponent } from '../../common/save-time-message/save-time-message.component'; +import { MatCardModule } from '@angular/material/card'; +import { MatIconModule } from '@angular/material/icon'; +import { FlexLayoutModule } from '@angular/flex-layout'; +import { CommonModule } from '@angular/common'; +import { MatButtonModule } from '@angular/material/button'; +import { MatDividerModule } from '@angular/material/divider'; +import { RouterModule } from '@angular/router'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { TextFieldModule } from '@angular/cdk/text-field'; @NgModule({ declarations: [ClassResponse], - imports: [SaveTimeMessageComponent, StudentComponentModule, StudentTeacherCommonModule], + imports: [ + CommonModule, + FlexLayoutModule, + MatButtonModule, + MatCardModule, + MatDividerModule, + MatIconModule, + MatTooltipModule, + RouterModule, + SaveTimeMessageComponent, + StudentComponentModule, + TextFieldModule + ], exports: [ClassResponse] }) export class DiscussionCommonModule {} diff --git a/src/assets/wise5/components/discussion/discussion-student/discussion-student.module.ts b/src/assets/wise5/components/discussion/discussion-student/discussion-student.module.ts index 06a579c4ac7..066a10f30e6 100644 --- a/src/assets/wise5/components/discussion/discussion-student/discussion-student.module.ts +++ b/src/assets/wise5/components/discussion/discussion-student/discussion-student.module.ts @@ -1,12 +1,32 @@ import { NgModule } from '@angular/core'; -import { StudentTeacherCommonModule } from '../../../../../app/student-teacher-common.module'; import { StudentComponentModule } from '../../../../../app/student/student.component.module'; import { DiscussionCommonModule } from '../discussion-common.module'; import { DiscussionStudent } from './discussion-student.component'; +import { CommonModule } from '@angular/common'; +import { FlexLayoutModule } from '@angular/flex-layout'; +import { ComponentHeaderComponent } from '../../../directives/component-header/component-header.component'; +import { MatCardModule } from '@angular/material/card'; +import { TextFieldModule } from '@angular/cdk/text-field'; +import { MatInputModule } from '@angular/material/input'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { FormsModule } from '@angular/forms'; +import { MatButtonModule } from '@angular/material/button'; @NgModule({ declarations: [DiscussionStudent], - imports: [StudentTeacherCommonModule, DiscussionCommonModule, StudentComponentModule], + imports: [ + CommonModule, + ComponentHeaderComponent, + DiscussionCommonModule, + FlexLayoutModule, + FormsModule, + MatButtonModule, + MatCardModule, + MatFormFieldModule, + MatInputModule, + StudentComponentModule, + TextFieldModule + ], exports: [DiscussionStudent] }) export class DiscussionStudentModule {} diff --git a/src/assets/wise5/components/peerChat/peer-chat.module.ts b/src/assets/wise5/components/peerChat/peer-chat.module.ts index 8c1cd28e3d0..6a3d404d73f 100644 --- a/src/assets/wise5/components/peerChat/peer-chat.module.ts +++ b/src/assets/wise5/components/peerChat/peer-chat.module.ts @@ -7,7 +7,14 @@ import { PeerChatMessageInputComponent } from './peer-chat-message-input/peer-ch import { PeerChatMessagesComponent } from './peer-chat-messages/peer-chat-messages.component'; import { PeerChatQuestionBankComponent } from './peer-chat-question-bank/peer-chat-question-bank.component'; import { QuestionBankService } from './peer-chat-question-bank/questionBank.service'; -import { StudentTeacherCommonModule } from '../../../../app/student-teacher-common.module'; +import { MatCardModule } from '@angular/material/card'; +import { CommonModule } from '@angular/common'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; +import { FormsModule } from '@angular/forms'; +import { MatInputModule } from '@angular/material/input'; +import { FlexLayoutModule } from '@angular/flex-layout'; +import { MatButtonModule } from '@angular/material/button'; @NgModule({ declarations: [ @@ -19,7 +26,16 @@ import { StudentTeacherCommonModule } from '../../../../app/student-teacher-comm PeerChatMessagesComponent, PeerChatQuestionBankComponent ], - imports: [StudentTeacherCommonModule], + imports: [ + CommonModule, + FlexLayoutModule, + FormsModule, + MatButtonModule, + MatCardModule, + MatFormFieldModule, + MatIconModule, + MatInputModule + ], exports: [ PeerChatChatBoxComponent, PeerChatMembersComponent, diff --git a/src/assets/wise5/components/showWork/show-work-student/show-work-student.module.ts b/src/assets/wise5/components/showWork/show-work-student/show-work-student.module.ts index 0b917fa57a6..7fac086111f 100644 --- a/src/assets/wise5/components/showWork/show-work-student/show-work-student.module.ts +++ b/src/assets/wise5/components/showWork/show-work-student/show-work-student.module.ts @@ -1,5 +1,4 @@ import { NgModule } from '@angular/core'; -import { StudentTeacherCommonModule } from '../../../../../app/student-teacher-common.module'; import { AnimationShowWorkModule } from '../../animation/animation-show-work/animation-show-work.module'; import { AudioOscillatorShowWorkModule } from '../../audioOscillator/audio-oscillator-show-work/audio-oscillator-show-work.module'; import { ConceptMapShowWorkModule } from '../../conceptMap/concept-map-show-work/concept-map-show-work.module'; @@ -13,12 +12,13 @@ import { ShowWorkStudentComponent } from './show-work-student.component'; import { MultipleChoiceShowWorkComponent } from '../../multipleChoice/multiple-choice-show-work/multiple-choice-show-work.component'; import { DialogGuidanceShowWorkComponent } from '../../dialogGuidance/dialog-guidance-show-work/dialog-guidance-show-work.component'; import { MatchShowWorkComponent } from '../../match/match-show-work/match-show-work.component'; +import { CommonModule } from '@angular/common'; import { LabelShowWorkComponent } from '../../label/label-show-work/label-show-work.component'; @NgModule({ declarations: [ShowWorkStudentComponent], imports: [ - StudentTeacherCommonModule, + CommonModule, AnimationShowWorkModule, AudioOscillatorShowWorkModule, ConceptMapShowWorkModule, diff --git a/src/assets/wise5/components/summary/summaryService.ts b/src/assets/wise5/components/summary/summaryService.ts index d9f46bb0a01..f28d143fc7c 100644 --- a/src/assets/wise5/components/summary/summaryService.ts +++ b/src/assets/wise5/components/summary/summaryService.ts @@ -16,6 +16,7 @@ export class SummaryService extends ComponentService { 'Animation', 'AudioOscillator', 'ConceptMap', + 'DialogGuidance', 'Discussion', 'Draw', 'Embedded', diff --git a/src/assets/wise5/components/table/table-show-work/table-show-work.component.html b/src/assets/wise5/components/table/table-show-work/table-show-work.component.html index c8181e754c9..d3487c86010 100644 --- a/src/assets/wise5/components/table/table-show-work/table-show-work.component.html +++ b/src/assets/wise5/components/table/table-show-work/table-show-work.component.html @@ -16,7 +16,7 @@ @if (componentContent.dataExplorerGraphTypes.length > 1) { Graph Type - + @for (graphType of componentContent.dataExplorerGraphTypes; track graphType) { {{ graphType.name }} @@ -28,7 +28,7 @@
X Data - + {{ noneText }} @for (columnName of columnNames; track columnName; let i = $index) { @@ -45,9 +45,7 @@ Y Data {{ dataExplorerSeries.length > 1 ? i + 1 : '' }} {{ noneText }} diff --git a/src/assets/wise5/components/table/table-show-work/table-show-work.module.ts b/src/assets/wise5/components/table/table-show-work/table-show-work.module.ts index 026b760f6ff..03578e8fee1 100644 --- a/src/assets/wise5/components/table/table-show-work/table-show-work.module.ts +++ b/src/assets/wise5/components/table/table-show-work/table-show-work.module.ts @@ -1,11 +1,12 @@ import { NgModule } from '@angular/core'; -import { StudentTeacherCommonModule } from '../../../../../app/student-teacher-common.module'; import { TableCommonModule } from '../table-common.module'; import { TableShowWorkComponent } from './table-show-work.component'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatSelectModule } from '@angular/material/select'; @NgModule({ declarations: [TableShowWorkComponent], - imports: [StudentTeacherCommonModule, TableCommonModule], + imports: [MatFormFieldModule, MatSelectModule, TableCommonModule], exports: [TableShowWorkComponent] }) export class TableShowWorkModule {} diff --git a/src/assets/wise5/directives/student-summary-display/student-summary-display.component.spec.ts b/src/assets/wise5/directives/student-summary-display/student-summary-display.component.spec.ts index 3838c79abfd..ed7dee671f3 100644 --- a/src/assets/wise5/directives/student-summary-display/student-summary-display.component.spec.ts +++ b/src/assets/wise5/directives/student-summary-display/student-summary-display.component.spec.ts @@ -3,10 +3,9 @@ import { Choice } from '../../components/multipleChoice/Choice'; import { ComponentContent } from '../../common/ComponentContent'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ConfigService } from '../../services/configService'; -import { MultipleChoiceSummaryData } from '../summary-display/summary-data/MultipleChoiceSummaryData'; import { MultipleChoiceSummaryDataPoint } from '../summary-display/summary-data/MultipleChoiceSummaryDataPoint'; import { ProjectService } from '../../services/projectService'; -import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; +import { provideHttpClient } from '@angular/common/http'; import { ScoreSummaryData } from '../summary-display/summary-data/ScoreSummaryData'; import { ScoreSummaryDataPoint } from '../summary-display/summary-data/ScoreSummaryDataPoint'; import { SeriesData } from '../../common/SeriesData'; @@ -17,12 +16,11 @@ import { SummaryData } from '../summary-display/summary-data/SummaryData'; let component: StudentSummaryDisplay; let fixture: ComponentFixture; - describe('StudentSummaryDisplayComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [StudentSummaryDisplay, StudentTeacherCommonServicesModule], - providers: [provideHttpClient(withInterceptorsFromDi())] + providers: [provideHttpClient()] }); fixture = TestBed.createComponent(StudentSummaryDisplay); component = fixture.componentInstance; @@ -40,9 +38,7 @@ describe('StudentSummaryDisplayComponent', () => { filterLatestScoreAnnotations(); getChartColors(); getGraphForSelf(); - getGraphTitleForPeriod(); getGraphTitleForClass(); - getPercentOfClassRespondedText(); getPercentResponded(); getTotalWorkgroups(); initializeOtherComponent(); @@ -66,21 +62,35 @@ function calculateCountsAndPercentage() { } function calculateMaxScore() { - describe('calculateMaxScore', () => { - it('should not update max score when there are no annotations', () => { + describe('setMinMaxScore', () => { + it('should not update min and max scores when there are no annotations', () => { const annotations = []; component.maxScore = 5; - expect(component.calculateMaxScore(annotations)).toEqual(5); + component.setMinMaxScore(annotations); + expect(component.studentMaxScore).toEqual(5); + expect(component.studentMinScore).toEqual(1); }); - it('should update max score when there are annotations', () => { - const annotation = new Annotation({ + it('should update min and max scores when there are annotations', () => { + const annotation1 = new Annotation({ data: { value: 6 } }); - const annotations = [annotation]; + const annotation2 = new Annotation({ + data: { + value: 0 + } + }); + const annotation3 = new Annotation({ + data: { + value: 2 + } + }); + const annotations = [annotation1, annotation2, annotation3]; component.maxScore = 5; - expect(component.calculateMaxScore(annotations)).toEqual(6); + component.setMinMaxScore(annotations); + expect(component.studentMaxScore).toEqual(6); + expect(component.studentMinScore).toEqual(0); }); }); } @@ -296,45 +306,28 @@ function setCustomLabelColors() { function getChartColors() { describe('getChartColors', () => { it('should get chart colors', () => { + component.studentMaxScore = 5; const colors = component.getChartColors(); expect(colors).toEqual(['#e7beda', '#d794c2', '#c86baa', '#b94192', '#a9177a']); }); }); } -function getGraphTitleForPeriod() { - describe('getGraphTitleForPeriod', () => { - it('should get graph title for period when student data type is responses', () => { - expectGraphTitleForX('Period', 'responses'); - }); - it('should get graph title for period when student data type is scores', () => { - expectGraphTitleForX('Period', 'scores'); - }); - }); -} - function getGraphTitleForClass() { describe('getGraphTitleForClass', () => { it('should get graph title for class when student data type is responses', () => { - expectGraphTitleForX('Class', 'responses'); + expectGraphTitleForX('responses', 'Responses'); }); it('should get graph title for class when student data type is scores', () => { - expectGraphTitleForX('Class', 'scores'); + expectGraphTitleForX('scores', 'Scores (Mean: 0)'); }); }); } -function expectGraphTitleForX(source: string, studentDataType: string) { +function expectGraphTitleForX(studentDataType: string, expectedTitle: string) { setResponseNumbers(component); component.studentDataType = studentDataType; - let title: string; - if (source === 'Period') { - title = component.getGraphTitleForPeriod(); - } else { - title = component.getGraphTitleForClass(); - } - const upperCaseStudentDataType = studentDataType[0].toUpperCase() + studentDataType.substring(1); - expect(title).toEqual(`${source} ${upperCaseStudentDataType} | 60% Responded (6/10)`); + expect(component.getGraphTitleForClass()).toEqual(expectedTitle); } function getGraphForSelf() { @@ -352,17 +345,6 @@ function getGraphForSelf() { }); } -function getPercentOfClassRespondedText() { - describe('getPercentOfClassRespondedText', () => { - it('should get percent of class responded text', () => { - setResponseNumbers(component); - component.studentDataType = 'responses'; - const text = component.getPercentOfClassRespondedText(); - expect(text).toEqual(`60% Responded (6/10)`); - }); - }); -} - function setResponseNumbers(component: any) { component.percentResponded = 60; component.numResponses = 6; diff --git a/src/assets/wise5/directives/student-summary-display/student-summary-display.component.ts b/src/assets/wise5/directives/student-summary-display/student-summary-display.component.ts index 319d8019a96..de2c0a729a0 100644 --- a/src/assets/wise5/directives/student-summary-display/student-summary-display.component.ts +++ b/src/assets/wise5/directives/student-summary-display/student-summary-display.component.ts @@ -17,6 +17,7 @@ import { DummyAnnotation } from '../../common/DummyAnnotation'; import { DummyComponentState } from '../../../../app/domain/dummyComponentState'; import { Choice } from '../../components/multipleChoice/Choice'; import { MultipleChoiceContent } from '../../components/multipleChoice/MultipleChoiceContent'; +import { CRaterService } from '../../services/cRaterService'; @Component({ imports: [CommonModule, HighchartsChartModule, MatCardModule], @@ -31,11 +32,19 @@ export class StudentSummaryDisplay extends SummaryDisplayComponent { constructor( protected annotationService: AnnotationService, protected configService: ConfigService, + protected cRaterService: CRaterService, protected dataService: StudentDataService, protected projectService: ProjectService, protected summaryService: SummaryService ) { - super(annotationService, configService, dataService, projectService, summaryService); + super( + annotationService, + configService, + cRaterService, + dataService, + projectService, + summaryService + ); } ngOnInit(): void { diff --git a/src/assets/wise5/directives/summary-display/summary-display.component.html b/src/assets/wise5/directives/summary-display/summary-display.component.html index 5cfd857cb7c..8e20ca5fadc 100644 --- a/src/assets/wise5/directives/summary-display/summary-display.component.html +++ b/src/assets/wise5/directives/summary-display/summary-display.component.html @@ -1,11 +1,11 @@ - - - @if (hasWarning) { -

{{ warningMessage }}

- } - @if (doRender && chartConfig != null) { - - - } -
-
+ +@if (hasWarning) { +

{{ warningMessage }}

+} +@if (doRender && chartConfig != null) { + + +} + diff --git a/src/assets/wise5/directives/summary-display/summary-display.component.scss b/src/assets/wise5/directives/summary-display/summary-display.component.scss index ec03009306b..5702e8c9abe 100644 --- a/src/assets/wise5/directives/summary-display/summary-display.component.scss +++ b/src/assets/wise5/directives/summary-display/summary-display.component.scss @@ -1,5 +1,5 @@ .highcharts-chart { display: block; - height: 400px; + height: 300px; width: 100%; } \ No newline at end of file diff --git a/src/assets/wise5/directives/summary-display/summary-display.component.ts b/src/assets/wise5/directives/summary-display/summary-display.component.ts index f08ed403f6e..30e2e25cf63 100644 --- a/src/assets/wise5/directives/summary-display/summary-display.component.ts +++ b/src/assets/wise5/directives/summary-display/summary-display.component.ts @@ -20,6 +20,7 @@ import { ScoreSummaryData } from './summary-data/ScoreSummaryData'; import { TableSummaryData } from './summary-data/TableSummaryData'; import { Choice } from '../../components/multipleChoice/Choice'; import { SummaryData } from './summary-data/SummaryData'; +import { CRaterService } from '../../services/cRaterService'; @Component({ imports: [MatCardModule], styleUrl: 'summary-display.component.scss', @@ -50,10 +51,13 @@ export abstract class SummaryDisplayComponent { correct: '#00C853', incorrect: '#C62828' }; - private defaultMaxScore: number = 5; + private defaultMaxScore: number = 0; hasCorrectness: boolean = false; protected Highcharts: typeof Highcharts = Highcharts; - maxScore: number = 5; + maxScore: number = 0; + studentMaxScore: number = 0; + studentMinScore: number = 1; + private meanScore: number = 0; numResponses: number; otherComponent: ComponentContent; @@ -76,6 +80,7 @@ export abstract class SummaryDisplayComponent { constructor( protected annotationService: AnnotationService, protected configService: ConfigService, + protected cRaterService: CRaterService, protected dataService: DataService, protected projectService: ProjectService, protected summaryService: SummaryService @@ -103,7 +108,11 @@ export abstract class SummaryDisplayComponent { } ngOnChanges(changes: SimpleChanges): void { - if (!changes.doRender.firstChange) { + if (changes.doRender != null && !changes.doRender.firstChange) { + this.renderDisplay(); + } else if (changes.componentId || changes.periodId) { + this.initializeOtherComponent(); + this.initializeCustomLabelColors(); this.renderDisplay(); } } @@ -171,13 +180,14 @@ export abstract class SummaryDisplayComponent { protected renderClassScores(): void { this.setMaxScore(); - this.getLatestScores().subscribe((annotations) => { - this.processScoreAnnotations(annotations); - }); + this.getLatestScores().subscribe((annotations) => this.processScoreAnnotations(annotations)); } protected setMaxScore(): void { - this.maxScore = this.otherComponent?.maxScore ?? this.defaultMaxScore; + const isCRaterEnabled = this.cRaterService.isCRaterEnabled( + this.projectService.getComponent(this.nodeId, this.componentId) + ); + this.maxScore = this.otherComponent?.maxScore ?? (isCRaterEnabled ? 5 : this.defaultMaxScore); } protected abstract getLatestWork(): Observable; @@ -258,24 +268,23 @@ export abstract class SummaryDisplayComponent { } protected processScoreAnnotations(annotations: Annotation[]): void { - this.updateMaxScoreIfNecessary(annotations); - const summaryData = new ScoreSummaryData(annotations, this.maxScore); + this.setMinMaxScore(annotations); + const summaryData = new ScoreSummaryData(annotations, this.studentMaxScore); const [seriesData, total] = this.createScoresSeriesData(summaryData); this.calculateCountsAndPercentage(annotations.length); this.renderGraph(seriesData, total); } - private updateMaxScoreIfNecessary(annotations: Annotation[]): void { - this.maxScore = this.calculateMaxScore(annotations); - } - - calculateMaxScore(annotations: Annotation[]): number { + setMinMaxScore(annotations: Annotation[]): void { let maxScoreSoFar = this.maxScore; + let minScoreSoFar = this.studentMinScore; for (const annotation of annotations) { const score = this.getScoreFromAnnotation(annotation); - maxScoreSoFar = Math.max(this.maxScore, score); + maxScoreSoFar = Math.max(maxScoreSoFar, score); + minScoreSoFar = Math.min(minScoreSoFar, score); } - return maxScoreSoFar; + this.studentMaxScore = maxScoreSoFar; + this.studentMinScore = minScoreSoFar; } createChoicesSeriesData( @@ -319,13 +328,16 @@ export abstract class SummaryDisplayComponent { private createScoresSeriesData(summaryData: ScoreSummaryData): [SeriesData, number] { const seriesData = new SeriesData(); + let sum = 0; let total = 0; - for (let scoreValue = 1; scoreValue <= this.maxScore; scoreValue++) { + for (let scoreValue = this.studentMinScore; scoreValue <= this.studentMaxScore; scoreValue++) { const count = this.getSummaryDataCount(summaryData, scoreValue); const dataPoint = new SeriesDataPoint(scoreValue, count); seriesData.addDataPoint(dataPoint); + sum += count * scoreValue; total += count; } + this.meanScore = Math.round((sum / total) * 100) / 100; return [seriesData, total]; } @@ -370,9 +382,6 @@ export abstract class SummaryDisplayComponent { case 'self': graphTitle = this.getGraphTitleForSelf(); break; - case 'period': - graphTitle = this.getGraphTitleForPeriod(); - break; default: graphTitle = this.getGraphTitleForClass(); } @@ -387,50 +396,25 @@ export abstract class SummaryDisplayComponent { } } - getGraphTitleForPeriod(): string { - if (this.isStudentDataTypeResponses()) { - return this.getGraphTitleWithLabelAndPercent( - $localize`Period Responses`, - this.getPercentOfClassRespondedText() - ); - } else if (this.isStudentDataTypeScores()) { - return this.getGraphTitleWithLabelAndPercent( - $localize`Period Scores`, - this.getPercentOfClassRespondedText() - ); - } - } - getGraphTitleForClass(): string { if (this.isStudentDataTypeResponses()) { - return this.getGraphTitleWithLabelAndPercent( - $localize`Class Responses`, - this.getPercentOfClassRespondedText() - ); + return $localize`Responses`; } else if (this.isStudentDataTypeScores()) { - return this.getGraphTitleWithLabelAndPercent( - $localize`Class Scores`, - this.getPercentOfClassRespondedText() - ); + return this.maxScore + ? `${$localize`Scores`} (${$localize`Mean: `}${this.meanScore}/${this.maxScore})` + : `${$localize`Scores`} (${$localize`Mean: `}${this.meanScore})`; } } - private getGraphTitleWithLabelAndPercent(label: string, percentDisplayText: string): string { - return `${label} | ${percentDisplayText}`; - } - - getPercentOfClassRespondedText(): string { - return $localize`${this.percentResponded}% Responded (${this.numResponses}/${this.totalWorkgroups})`; - } - getChartColors(): string[] { if (this.studentDataType === 'responses') { return this.colors.palette; } else { let colors: string[] = []; - const step = (100 / this.maxScore / 100) * 0.9; + const rangeMax = this.studentMinScore === 0 ? this.studentMaxScore + 1 : this.studentMaxScore; + const step = (100 / rangeMax / 100) * 0.9; let opacity = 0.1; - for (let i = 0; i < this.maxScore; i++) { + for (let i = 0; i < rangeMax; i++) { opacity = opacity + step; const color = rgbToHex(this.colors.singleHue, opacity); colors.push(color); @@ -496,7 +480,9 @@ export abstract class SummaryDisplayComponent { enabled: false }, legend: { - enabled: false + enabled: function () { + return chartType === 'pie' ? true : false; + } }, plotOptions: { series: { @@ -505,16 +491,26 @@ export abstract class SummaryDisplayComponent { formatter: function () { if (chartType === 'pie') { const pct = Math.round((this.y / this.total) * 100); - return this.key + ': ' + pct + '%'; + return pct + '%'; } else { - return this.y; + const pct = Math.round((this.y / thisSummaryDisplay.total) * 100); + return this.y + ' (' + pct + '%)'; } }, - style: { fontSize: '12px' } + style: { fontSize: '12px' }, + enabled: true } }, column: { maxPointWidth: 80 + }, + pie: { + allowPointSelect: true, + cursor: 'pointer', + showInLegend: true, + dataLabels: { + distance: -30 + } } }, series: series, @@ -529,10 +525,11 @@ export abstract class SummaryDisplayComponent { tooltip: { formatter: function (s, point) { if (chartType === 'pie') { - return '' + this.key + ': ' + this.y; + const pct = Math.round((this.y / this.total) * 100); + return this.key + '
' + this.y + ' (' + pct + '%)
'; } else { const pct = Math.round((this.y / thisSummaryDisplay.total) * 100); - return '' + this.key + ': ' + pct + '%'; + return '' + this.key + '
Count:' + this.y + ''; } } }, diff --git a/src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.html b/src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.html index 1293bf402bf..80b85af160d 100644 --- a/src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.html +++ b/src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.html @@ -1,65 +1,59 @@ -
+
{{ idea.id }}. {{ idea.text }} (person{{ idea.count }})
- - -

Student Ideas Detected

- @if (hasWarning) { -

{{ warningMessage }}

- } - @if (doRender) { -
-
-

Most Common:

-
    - @for (idea of mostCommonIdeas; track idea.id) { -
  • - -
  • - } -
-
-
-

Least Common:

-
    - @for (idea of leastCommonIdeas; track idea.id) { -
  • - -
  • - } -
-
-
- @if (seeAllIdeas) { -

All Ideas:

-
    - @for (idea of allIdeas; track idea.id) { -
  • - -
  • - } -
- Hide all ideas - } @else { - Show all ideas +

Student Ideas Detected

+@if (hasWarning) { +

{{ warningMessage }}

+} +@if (doRender) { +
+
+

Most Common:

+
    + @for (idea of mostCommonIdeas; track idea.id) { +
  • + +
  • + } +
+
+
+

Least Common:

+
    + @for (idea of leastCommonIdeas; track idea.id) { +
  • + +
  • + } +
+
+
+ @if (seeAllIdeas) { +

All Ideas:

+
    + @for (idea of allIdeas; track idea.id) { +
  • + +
  • } - } @else { -
    - Your students' ideas will show up here as they are detected in the activity. -
    - } - - +
+ Hide all ideas + } @else { + Show all ideas + } +} @else { +
Your students' ideas will show up here as they are detected in the activity.
+} diff --git a/src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.spec.ts b/src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.spec.ts index 6d3264206c0..a48e4e8f9b3 100644 --- a/src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.spec.ts +++ b/src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.spec.ts @@ -7,7 +7,7 @@ import { CRaterRubric } from '../../../components/common/cRater/CRaterRubric'; import { CRaterService } from '../../../services/cRaterService'; import { IdeasSummaryComponent } from './ideas-summary.component'; import { MockProviders } from 'ng-mocks'; -import { Observable, of } from 'rxjs'; +import { of } from 'rxjs'; import { SummaryService } from '../../../components/summary/summaryService'; import { TeacherDataService } from '../../../services/teacherDataService'; import { TeacherProjectService } from '../../../services/teacherProjectService'; @@ -38,10 +38,11 @@ describe('IdeasSummaryDisplayComponent for Dialog Guidance component', () => { component.componentType = 'DialogGuidance'; }); beforeEach(() => { - spyOn(TestBed.inject(ConfigService), 'isPreview').and.returnValue(false); - spyOn(TestBed.inject(ConfigService), 'isAuthoring').and.returnValue(false); - spyOn(TestBed.inject(ConfigService), 'isStudentRun').and.returnValue(false); - spyOn(TestBed.inject(ConfigService), 'getNumberOfWorkgroupsInPeriod').and.returnValue(1); + const configService = TestBed.inject(ConfigService); + spyOn(configService, 'isPreview').and.returnValue(false); + spyOn(configService, 'isAuthoring').and.returnValue(false); + spyOn(configService, 'isStudentRun').and.returnValue(false); + spyOn(configService, 'getNumberOfWorkgroupsInPeriod').and.returnValue(1); }); describe('ngOnChanges()', () => { @@ -73,10 +74,11 @@ describe('IdeasSummaryDisplayComponent for Open Response component', () => { component.componentType = 'OpenResponse'; }); beforeEach(() => { - spyOn(TestBed.inject(ConfigService), 'isPreview').and.returnValue(false); - spyOn(TestBed.inject(ConfigService), 'isAuthoring').and.returnValue(false); - spyOn(TestBed.inject(ConfigService), 'isStudentRun').and.returnValue(false); - spyOn(TestBed.inject(ConfigService), 'getNumberOfWorkgroupsInPeriod').and.returnValue(1); + const configService = TestBed.inject(ConfigService); + spyOn(configService, 'isPreview').and.returnValue(false); + spyOn(configService, 'isAuthoring').and.returnValue(false); + spyOn(configService, 'isStudentRun').and.returnValue(false); + spyOn(configService, 'getNumberOfWorkgroupsInPeriod').and.returnValue(1); }); describe('ngOnChanges()', () => { @@ -110,7 +112,7 @@ function showMessageToTeacher(componentType: string) { it('shows message to teacher (' + componentType + ')', () => { component.ngOnInit(); fixture.detectChanges(); - expect(fixture.nativeElement.querySelector('.notice').textContent).toContain( + expect(fixture.nativeElement.textContent).toContain( "Your students' ideas will show up here as they are detected in the activity." ); }); diff --git a/src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.ts b/src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.ts index 9daef828f41..099921f5479 100644 --- a/src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.ts +++ b/src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.ts @@ -9,7 +9,6 @@ import { DialogGuidanceSummaryData } from '../summary-data/DialogGuidanceSummary import { IdeaData } from '../../../components/common/cRater/IdeaData'; import { IdeasSortingService } from '../../../services/ideasSortingService'; import { IdeasSummaryData } from '../summary-data/IdeasSummaryData'; -import { MatCardModule } from '@angular/material/card'; import { MatIconModule } from '@angular/material/icon'; import { OpenResponseSummaryData } from '../summary-data/OpenResponseSummaryData'; import { SummaryService } from '../../../components/summary/summaryService'; @@ -18,18 +17,15 @@ import { TeacherProjectService } from '../../../services/teacherProjectService'; import { TeacherSummaryDisplayComponent } from '../teacher-summary-display.component'; @Component({ - imports: [CommonModule, MatCardModule, MatIconModule], + imports: [CommonModule, MatIconModule], providers: [IdeasSortingService], selector: 'ideas-summary', styles: ` - h3 { + h3, + .mat-subtitle-1 { margin-bottom: 8px; + margin-top: 0; } - - .idea { - @apply px-2 py-1 rounded-md bg-gray-100 my-1 text-sm; - } - .mat-icon { vertical-align: middle; } @@ -48,13 +44,20 @@ export class IdeasSummaryComponent extends TeacherSummaryDisplayComponent { constructor( protected annotationService: AnnotationService, protected configService: ConfigService, - private cRaterService: CRaterService, + protected cRaterService: CRaterService, protected dataService: TeacherDataService, private ideasSortingService: IdeasSortingService, protected projectService: TeacherProjectService, protected summaryService: SummaryService ) { - super(annotationService, configService, dataService, projectService, summaryService); + super( + annotationService, + configService, + cRaterService, + dataService, + projectService, + summaryService + ); } ngOnInit(): void { @@ -66,22 +69,18 @@ export class IdeasSummaryComponent extends TeacherSummaryDisplayComponent { this.generateIdeasSummary(); } - private generateIdeasSummary(): IdeasSummaryData { - let ideasSummaryData: IdeasSummaryData; + private generateIdeasSummary(): void { if (this.componentType === 'DialogGuidance') { - this.getLatestWork().subscribe((componentStates) => { - ideasSummaryData = new DialogGuidanceSummaryData(componentStates); - this.compileAndSortIdeas(ideasSummaryData); - }); + this.getLatestWork().subscribe((componentStates) => + this.compileAndSortIdeas(new DialogGuidanceSummaryData(componentStates)) + ); } else if (this.componentType === 'OpenResponse') { - const annotations = this.annotationService.getAnnotationsByNodeIdComponentId( - this.nodeId, - this.componentId + this.compileAndSortIdeas( + new OpenResponseSummaryData( + this.annotationService.getAnnotationsByNodeIdComponentId(this.nodeId, this.componentId) + ) ); - ideasSummaryData = new OpenResponseSummaryData(annotations); - this.compileAndSortIdeas(ideasSummaryData); } - return ideasSummaryData; } private compileAndSortIdeas(ideasSummaryData: IdeasSummaryData) { @@ -101,12 +100,13 @@ export class IdeasSummaryComponent extends TeacherSummaryDisplayComponent { .reverse(); } this.allIdeas = this.ideasSortingService.sortById(ideaCountArray); + this.doRender = true; } } private ideaCountMapToArray(ideaDescriptions: CRaterIdea[]): IdeaData[] { const ideaCountArray = []; - this.ideaCountMap.forEach((count, ideaId, map) => { + this.ideaCountMap.forEach((count, ideaId) => { const ideaDescription = ideaDescriptions.find( (ideaDescription) => ideaDescription.name === ideaId ); @@ -123,6 +123,11 @@ export class IdeasSummaryComponent extends TeacherSummaryDisplayComponent { return text ?? 'idea ' + id; } + protected renderDisplay(): void { + super.renderDisplay(); + this.generateIdeasSummary(); + } + protected toggleSeeAllIdeas(event: Event): void { event.preventDefault(); this.seeAllIdeas = !this.seeAllIdeas; diff --git a/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.html b/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.html index 134a651a3ae..7d5c9333408 100644 --- a/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.html +++ b/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.html @@ -1,6 +1,6 @@ -
-

+
+

{{ bucket.value }} @if (first) { (Source Bucket) @@ -34,38 +34,27 @@

- - -

Choice Frequency

- @if (bucketData.length > 0) { -

- This summary shows how many students moved each choice item into the different buckets - (categories). -

-
-
+

Choice Frequency

+@if (bucketData.length > 0) { +

Number of teams that moved each item (choice) into the different buckets (categories).

+
+ + @for (bucket of bucketData; track $index) { + @if ($index > 0) { +
-
- @for (bucket of bucketData; track $index) { - @if ($index > 0) { -
- -
- } - } -
-
- } @else { -
- Your students' choices will show up here when they complete the activity. -
+ } } - - +
+} @else { +
+ Your students' choices will show up here when they complete the activity. +
+} diff --git a/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.scss b/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.scss deleted file mode 100644 index e743620fcff..00000000000 --- a/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.scss +++ /dev/null @@ -1,21 +0,0 @@ -mat-icon { - padding-top: 4px; -} - -.bucket { - border: solid black 6px; - width: 35%; - display: inline-block; - padding: 20px; - margin: 20px; -} - -.match-item { - border: solid black 4px; - padding: 10px; - margin: 5px; -} - -.right-align { - float: right; -} \ No newline at end of file diff --git a/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.spec.ts b/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.spec.ts index 869530c4cc5..e905da49be1 100644 --- a/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.spec.ts +++ b/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.spec.ts @@ -7,6 +7,8 @@ import { of } from 'rxjs'; import { SummaryService } from '../../../components/summary/summaryService'; import { TeacherDataService } from '../../../services/teacherDataService'; import { TeacherProjectService } from '../../../services/teacherProjectService'; +import { CRaterService } from '../../../services/cRaterService'; +import { MatchContent } from '../../../components/match/MatchContent'; describe('MatchSummaryDisplayComponent', () => { let component: MatchSummaryDisplayComponent; @@ -19,21 +21,22 @@ describe('MatchSummaryDisplayComponent', () => { MockProviders( AnnotationService, ConfigService, + CRaterService, + SummaryService, TeacherDataService, - TeacherProjectService, - SummaryService + TeacherProjectService ) ] }).compileComponents(); - spyOn(TestBed.inject(TeacherProjectService), 'getComponentsFromStep').and.returnValue([ - { id: 'cId', type: 'Match', choiceReuseEnabled: false } - ] as any[]); - + spyOn(TestBed.inject(TeacherProjectService), 'getComponent').and.returnValue({ + id: 'cId', + type: 'Match', + choiceReuseEnabled: false + } as MatchContent); spyOn(TestBed.inject(SummaryService), 'getLatestClassmateStudentWork').and.returnValue( of(getComponentStates()) ); - fixture = TestBed.createComponent(MatchSummaryDisplayComponent); component = fixture.componentInstance; component.nodeId = 'nId'; diff --git a/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.ts b/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.ts index b08722436f4..aada417701a 100644 --- a/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.ts +++ b/src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.ts @@ -1,27 +1,25 @@ -import { AnnotationService } from '../../../services/annotationService'; import { CommonModule } from '@angular/common'; import { Component, OnInit } from '@angular/core'; -import { ConfigService } from '../../../services/configService'; import { MatchContent } from '../../../components/match/MatchContent'; import { MatchSummaryData } from '../summary-data/MatchSummaryData'; import { MatchSummaryDataPoint } from '../summary-data/MatchSummaryDataPoint'; import { MatIconModule } from '@angular/material/icon'; -import { SummaryDataPoint } from '../../summary-display/summary-data/SummaryDataPoint'; -import { SummaryService } from '../../../components/summary/summaryService'; -import { TeacherDataService } from '../../../services/teacherDataService'; -import { TeacherProjectService } from '../../../services/teacherProjectService'; import { TeacherSummaryDisplayComponent } from '../teacher-summary-display.component'; -import { MatCardModule } from '@angular/material/card'; @Component({ - imports: [CommonModule, MatCardModule, MatIconModule], + imports: [CommonModule, MatIconModule], selector: 'match-summary-display', styles: ` - h3 { + h3, + .mat-subtitle-1 { margin-bottom: 8px; + margin-top: 0; + } + .bucket { + @apply p-2 mb-2 rounded-md; } .choice { - @apply flex gap-1 px-2 py-1 rounded-md bg-gray-100 my-1 text-sm; + @apply flex gap-1 px-2 py-1 mt-1 rounded-md bg-white border border-neutral-200 text-sm; } .mat-icon { vertical-align: middle; @@ -31,24 +29,26 @@ import { MatCardModule } from '@angular/material/card'; }) export class MatchSummaryDisplayComponent extends TeacherSummaryDisplayComponent implements OnInit { protected bucketData: { value: string; choices: MatchSummaryDataPoint[] }[] = []; - protected bucketsShowMore: Map = new Map(); + private bucketsShowMore: Map = new Map(); private bucketValues: Set = new Set(); - protected matchSummaryData: MatchSummaryData; protected isChoiceReuseMatch: boolean; - - constructor( - protected annotationService: AnnotationService, - protected configService: ConfigService, - protected dataService: TeacherDataService, - protected projectService: TeacherProjectService, - protected summaryService: SummaryService - ) { - super(annotationService, configService, dataService, projectService, summaryService); - } + private matchSummaryData: MatchSummaryData; ngOnInit(): void { this.setIsChoiceReuseMatch(); + this.generateSummary(); + } + + private setIsChoiceReuseMatch(): void { + this.isChoiceReuseMatch = ( + this.projectService.getComponent(this.nodeId, this.componentId) as MatchContent + ).choiceReuseEnabled; + } + + private generateSummary(): void { this.getLatestWork().subscribe((componentStates) => { + this.bucketData = []; + this.bucketValues.clear(); this.matchSummaryData = new MatchSummaryData(componentStates); this.setBucketValues(); this.setBucketData(); @@ -56,14 +56,6 @@ export class MatchSummaryDisplayComponent extends TeacherSummaryDisplayComponent }); } - private setIsChoiceReuseMatch(): void { - this.isChoiceReuseMatch = ( - this.projectService - .getComponentsFromStep(this.nodeId) - .find((component) => component.id === this.componentId) as MatchContent - ).choiceReuseEnabled; - } - protected setBucketValues(): void { this.matchSummaryData .getBucketsData() @@ -80,15 +72,14 @@ export class MatchSummaryDisplayComponent extends TeacherSummaryDisplayComponent return this.matchSummaryData .getBucketsData() .find((bucket) => bucket.bucketValue === bucketValue) - .bucketDataPoints.map(this.asMatchSummaryDataPoint) - .sort(this.sortChoices); + .bucketDataPoints.sort(this.sortChoices); } - protected sortChoices(choiceA: MatchSummaryDataPoint, choiceB: MatchSummaryDataPoint): number { + private sortChoices(choiceA: MatchSummaryDataPoint, choiceB: MatchSummaryDataPoint): number { return choiceB.getCount() - choiceA.getCount(); } - protected setBucketShowMore(): void { + private setBucketShowMore(): void { this.bucketValues.forEach((value) => this.bucketsShowMore.set(value, false)); } @@ -101,7 +92,8 @@ export class MatchSummaryDisplayComponent extends TeacherSummaryDisplayComponent this.bucketsShowMore.set(bucketValue, !this.bucketsShowMore.get(bucketValue)); } - private asMatchSummaryDataPoint(dataPoint: SummaryDataPoint): MatchSummaryDataPoint { - return dataPoint as MatchSummaryDataPoint; + protected renderDisplay(): void { + super.renderDisplay(); + this.generateSummary(); } } diff --git a/src/assets/wise5/directives/teacher-summary-display/summary-data/MatchSummaryData.ts b/src/assets/wise5/directives/teacher-summary-display/summary-data/MatchSummaryData.ts index a2fe26557d0..9c2aa5cb1a1 100644 --- a/src/assets/wise5/directives/teacher-summary-display/summary-data/MatchSummaryData.ts +++ b/src/assets/wise5/directives/teacher-summary-display/summary-data/MatchSummaryData.ts @@ -16,7 +16,7 @@ export class MatchSummaryData extends SummaryData { this.extractBucketData(componentStates); } - getBucketsData() { + getBucketsData(): BucketData[] { return this.bucketsData; } diff --git a/src/assets/wise5/directives/teacher-summary-display/teacher-summary-display.component.ts b/src/assets/wise5/directives/teacher-summary-display/teacher-summary-display.component.ts index babefb1bb53..d1bf21ce44a 100644 --- a/src/assets/wise5/directives/teacher-summary-display/teacher-summary-display.component.ts +++ b/src/assets/wise5/directives/teacher-summary-display/teacher-summary-display.component.ts @@ -1,32 +1,55 @@ import { Component } from '@angular/core'; import { AnnotationService } from '../../services/annotationService'; import { ConfigService } from '../../services/configService'; -import { ProjectService } from '../../services/projectService'; import { SummaryService } from '../../components/summary/summaryService'; import { SummaryDisplayComponent } from '../summary-display/summary-display.component'; import { TeacherDataService } from '../../services/teacherDataService'; import { CommonModule } from '@angular/common'; import { MatCardModule } from '@angular/material/card'; import { HighchartsChartModule } from 'highcharts-angular'; -import { Observable } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { Annotation } from '../../common/Annotation'; import { ComponentState } from '../../../../app/domain/componentState'; +import { CRaterService } from '../../services/cRaterService'; +import { TeacherProjectService } from '../../services/teacherProjectService'; @Component({ - imports: [CommonModule, HighchartsChartModule, MatCardModule], - selector: 'teacher-summary-display', - styleUrl: '../summary-display/summary-display.component.scss', - templateUrl: '../summary-display/summary-display.component.html' + imports: [CommonModule, HighchartsChartModule, MatCardModule], + selector: 'teacher-summary-display', + styleUrl: '../summary-display/summary-display.component.scss', + templateUrl: '../summary-display/summary-display.component.html' }) export class TeacherSummaryDisplayComponent extends SummaryDisplayComponent { + private subscriptions = new Subscription(); + constructor( protected annotationService: AnnotationService, protected configService: ConfigService, + protected cRaterService: CRaterService, protected dataService: TeacherDataService, - protected projectService: ProjectService, + protected projectService: TeacherProjectService, protected summaryService: SummaryService ) { - super(annotationService, configService, dataService, projectService, summaryService); + super( + annotationService, + configService, + cRaterService, + dataService, + projectService, + summaryService + ); + } + + ngOnInit(): void { + super.ngOnInit(); + this.subscriptions.add(this.projectService.projectSaved$.subscribe(() => this.renderDisplay())); + this.subscriptions.add( + this.annotationService.annotationReceived$.subscribe(() => this.renderDisplay()) + ); + } + + ngOnDestroy(): void { + this.subscriptions.unsubscribe(); } protected getLatestScores(): Observable { diff --git a/src/assets/wise5/services/annotationService.ts b/src/assets/wise5/services/annotationService.ts index 8f9998c0e34..aa9b3fe024f 100644 --- a/src/assets/wise5/services/annotationService.ts +++ b/src/assets/wise5/services/annotationService.ts @@ -5,6 +5,8 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable, Subject } from 'rxjs'; import { generateRandomKey } from '../common/string/string'; import { Annotation } from '../common/Annotation'; +import { Node } from '../common/Node'; +import { ComponentContent } from '../common/ComponentContent'; @Injectable() export class AnnotationService { @@ -251,6 +253,17 @@ export class AnnotationService { return annotation.type === 'score' || annotation.type === 'autoScore'; } + getTotalNodeScore(workgroupId: number, node: Node, components: ComponentContent[]): number { + return this.getTotalScore( + this.annotations.filter( + (annotation) => + annotation.nodeId === node.id && + annotation.toWorkgroupId === workgroupId && + components.some((component) => component.id === annotation.componentId) + ) + ); + } + getTotalNodeScoreForWorkgroup(workgroupId: number, nodeId: string) { const annotationsForNodeAndWorkgroup = this.annotations.filter((annotation) => { return annotation.nodeId === nodeId && annotation.toWorkgroupId === workgroupId; diff --git a/src/assets/wise5/services/gradingNodeService.ts b/src/assets/wise5/services/gradingNodeService.ts index 4f568a11618..5e2d881eadb 100644 --- a/src/assets/wise5/services/gradingNodeService.ts +++ b/src/assets/wise5/services/gradingNodeService.ts @@ -12,10 +12,6 @@ export class GradingNodeService extends TeacherNodeService { }); } - goToPrevNode(): void { - this.setCurrentNode(this.getPrevNodeId()); - } - getPrevNodeId(currentId = null) { const prevNodeId = super.getPrevNodeId(currentId); if (!prevNodeId) return null; diff --git a/src/assets/wise5/services/milestoneService.ts b/src/assets/wise5/services/milestoneService.ts index e34b2957c54..214f08d6aa0 100644 --- a/src/assets/wise5/services/milestoneService.ts +++ b/src/assets/wise5/services/milestoneService.ts @@ -34,14 +34,14 @@ export class MilestoneService { return []; } - getMilestoneReportByNodeId(nodeId: string): any { - for (const milestoneReport of this.getProjectMilestoneReports()) { - const referencedComponent = this.getReferencedComponent(milestoneReport); - if (referencedComponent.nodeId === nodeId) { - return this.getProjectMilestoneStatus(milestoneReport.id); - } - } - return null; + getMilestoneReport(nodeId: string, componentId: string): any { + const milestoneReport = this.getProjectMilestoneReports().find((report) => { + const referencedComponent = this.getReferencedComponent(report); + return ( + referencedComponent.nodeId === nodeId && referencedComponent.componentId === componentId + ); + }); + return milestoneReport ? this.getProjectMilestoneStatus(milestoneReport.id) : null; } private getProjectMilestoneReports(): Milestone[] { diff --git a/src/assets/wise5/services/teacherDataService.ts b/src/assets/wise5/services/teacherDataService.ts index 3900a360bcc..4b40c973bfe 100644 --- a/src/assets/wise5/services/teacherDataService.ts +++ b/src/assets/wise5/services/teacherDataService.ts @@ -132,7 +132,7 @@ export class TeacherDataService extends DataService { .set('runId', this.configService.getRunId()) .set('getStudentWork', 'true') .set('getAnnotations', 'false') - .set('getEvents', 'false'); + .set('getEvents', 'true'); const components = node.getAllRelatedComponents(); if (components.length > 0) { params = params.set('components', compressToEncodedURIComponent(JSON.stringify(components))); @@ -442,4 +442,13 @@ export class TeacherDataService extends DataService { private isCurrentWorkgroup(workgroupId: number): boolean { return this.currentWorkgroup.workgroupId === workgroupId; } + + getPreviewUrl(): string { + let previewUrl = this.configService.getConfigParam('previewProjectURL'); + const currentNodeId = this.getCurrentNodeId(); + if (!this.projectService.isGroupNode(currentNodeId)) { + previewUrl += `/${currentNodeId}`; + } + return previewUrl; + } } diff --git a/src/messages.xlf b/src/messages.xlf index bbe61e76689..7b75b05e126 100644 --- a/src/messages.xlf +++ b/src/messages.xlf @@ -277,10 +277,6 @@ src/app/announcement/announcement-dialog.component.html 11,13 - - src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.html - 7,9 - src/app/modules/library/library-project-details/library-project-details.component.html 218,222 @@ -978,6 +974,10 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.src/assets/wise5/authoringTool/notebook-authoring/notebook-authoring.component.html 265,268 + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-summary/component-summary.component.html + 4,6 + Enter Prompt Here @@ -1809,31 +1809,6 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.12,16 - - Assessment items to show - - src/app/classroom-monitor/component-select/component-select.component.html - 2,5 - - - src/app/classroom-monitor/component-select/component-select.component.html - 14,15 - - - - 1 assessment item - - src/app/classroom-monitor/component-select/component-select.component.html - 3,6 - - - - Showing / items - - src/app/classroom-monitor/component-select/component-select.component.ts - 49 - - / teams completed @@ -1862,13 +1837,6 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.14,15 - - Open in New Window - - src/app/classroom-monitor/show-node-info-dialog/show-node-info-dialog.component.html - 6,8 - - Has new alert(s) @@ -2148,7 +2116,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/components/summary/summaryService.ts - 39 + 40 @@ -2472,12 +2440,12 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.29,30 - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 93,95 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 90,92 - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 157,159 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html + 71,73 src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html @@ -9551,9 +9519,13 @@ Click "Cancel" to keep the invalid JSON open so you can fix it.src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-workgroup-item/milestone-workgroup-item.component.ts 143 + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.ts + 137 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.ts - 109 + 104 src/assets/wise5/classroomMonitor/classroomMonitorComponents/studentGrading/step-item/step-item.component.ts @@ -10821,7 +10793,7 @@ Click "Cancel" to keep the invalid JSON open so you can fix it. src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/top-bar/top-bar.component.ts - 73 + 75 @@ -11717,8 +11689,8 @@ The branches will be removed but the steps will remain in the unit. 80 - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 38,42 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestone-report-button/milestone-report-button.component.html + 5,9 src/assets/wise5/services/notebookService.ts @@ -13116,7 +13088,7 @@ The branches will be removed but the steps will remain in the unit. 44,48 - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html 23,27 @@ -13639,6 +13611,24 @@ The branches will be removed but the steps will remain in the unit. 62 + + % completed + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-completion/component-completion.component.html + 4,5 + + + src/assets/wise5/vle/nav-item/nav-item.component.html + 53,54 + + + + Responses: + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/component-completion/component-completion.component.html + 12,14 + + No feedback given for this version @@ -14099,6 +14089,140 @@ The branches will be removed but the steps will remain in the unit. 17,21 + + Expand All + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 17,19 + + + src/assets/wise5/classroomMonitor/notebook-grading/notebook-grading.component.html + 18,21 + + + + Collapse All + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 28,30 + + + src/assets/wise5/classroomMonitor/notebook-grading/notebook-grading.component.html + 29,32 + + + + Sort by team + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 47,50 + + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html + 34,38 + + + + Team + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 50,52 + + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-details/milestone-details.component.html + 105,108 + + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html + 37,38 + + + src/assets/wise5/classroomMonitor/notebook-grading/notebook-grading.component.html + 52,54 + + + src/assets/wise5/classroomMonitor/student-progress/student-progress.component.ts + 40 + + + + Sort by completion + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 67,70 + + + src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html + 79,82 + + + + Status + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 70,72 + + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html + 54,55 + + + src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html + 82,84 + + + + Sort by score + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 87,90 + + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html + 68,72 + + + src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html + 99,102 + + + + Sort by score on Step + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 107,108 + + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 109,110 + + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 130,131 + + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 132,133 + + + + Sort by change in score + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 154,156 + + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 156,159 + + + + +/- + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-class-responses/milestone-class-responses.component.html + 160,162 + + Milestone: @@ -14134,12 +14258,8 @@ The branches will be removed but the steps will remain in the unit. 36,40 - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 54,57 - - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/node-info/node-info.component.html - 5,7 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.html + 20,22 src/assets/wise5/vle/node/node.component.html @@ -14199,29 +14319,6 @@ The branches will be removed but the steps will remain in the unit. 97,99 - - Team - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-details/milestone-details.component.html - 105,108 - - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 50,52 - - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 116,118 - - - src/assets/wise5/classroomMonitor/notebook-grading/notebook-grading.component.html - 52,54 - - - src/assets/wise5/classroomMonitor/student-progress/student-progress.component.ts - 40 - - Not Completed @@ -14233,123 +14330,16 @@ The branches will be removed but the steps will remain in the unit. 152 - - Expand All - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 17,19 - - - src/assets/wise5/classroomMonitor/notebook-grading/notebook-grading.component.html - 18,21 - - - - Collapse All - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 28,30 - - - src/assets/wise5/classroomMonitor/notebook-grading/notebook-grading.component.html - 29,32 - - - - Sort by team - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 47,50 - - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 113,116 - - - - Sort by completion - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 68,71 - - - src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html - 79,82 - - - - Status - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 71,73 - - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 136,138 - - - src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html - 82,84 - - - - Sort by score - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 90,93 - - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 154,157 - - - src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html - 99,102 - - - - Sort by score on Step - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 112,113 - - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 114,115 - - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 137,138 - - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 139,140 - - - - Sort by change in score - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 163,165 - - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 165,168 - - - - +/- - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-grading-view/milestone-grading-view.component.html - 169,170 - - Show/hide team's work for this step src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-workgroup-item/milestone-workgroup-item.component.html 11,13 + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.html + 12,14 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.html 12,14 @@ -14376,9 +14366,13 @@ The branches will be removed but the steps will remain in the unit. src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-workgroup-item/milestone-workgroup-item.component.ts 139 + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.ts + 132 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.ts - 104 + 99 src/assets/wise5/classroomMonitor/classroomMonitorComponents/studentGrading/step-item/step-item.component.ts @@ -14391,9 +14385,13 @@ The branches will be removed but the steps will remain in the unit. src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-workgroup-item/milestone-workgroup-item.component.ts 147 + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.ts + 144 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.ts - 116 + 111 src/assets/wise5/classroomMonitor/classroomMonitorComponents/studentGrading/step-item/step-item.component.ts @@ -14406,105 +14404,123 @@ The branches will be removed but the steps will remain in the unit. src/assets/wise5/classroomMonitor/classroomMonitorComponents/milestones/milestone-workgroup-item/milestone-workgroup-item.component.ts 154 + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.ts + 149 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.ts - 121 + 116 src/assets/wise5/classroomMonitor/classroomMonitorComponents/studentGrading/step-item/step-item.component.ts 108 - - Completion + + Showing / questions - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 12,15 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/filter-components/filter-components.component.ts + 33 + + + Expand all teams - src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html - 13,16 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html + 8,11 + + + + Expand all - src/assets/wise5/classroomMonitor/student-progress/student-progress.component.ts - 65 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html + 14,18 - - N/A + + Collapse all teams - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 19,21 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html + 18,21 - - Mean Score + + - Collapse all - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 21,26 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html + 24,28 - - Peer Groups + + Sorty by completion - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 46,50 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-class-responses/node-class-responses.component.html + 51,55 - - Info + Tips () + + Step Completion - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 57,58 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.html + 6,9 - - Expand all teams + + Mean Step Score - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 78,81 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.html + 11,15 - - + Expand all + + Info + Tips () - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 84,87 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.html + 22,23 - - Collapse all teams + + Question Summaries - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 88,91 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.html + 29,31 - - - Collapse all + + Hide - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 94,98 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.html + 32,33 + + + src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html + 574,575 - - This step doesn't require any student work + + Show - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 102,107 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.html + 34,37 - - Sorty by completion + + Class Responses - src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading-view/node-grading-view.component.html - 133,137 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-grading/node-grading.component.html + 56,59 Visited + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.ts + 139 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.ts - 111 + 106 src/assets/wise5/classroomMonitor/classroomMonitorComponents/studentGrading/step-item/step-item.component.ts @@ -14513,9 +14529,13 @@ The branches will be removed but the steps will remain in the unit. Not Visited + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/node-workgroup-item/node-workgroup-item.component.ts + 151 + src/assets/wise5/classroomMonitor/classroomMonitorComponents/nodeGrading/workgroup-item/workgroup-item.component.ts - 123 + 118 src/assets/wise5/classroomMonitor/classroomMonitorComponents/studentGrading/step-item/step-item.component.ts @@ -14655,6 +14675,13 @@ The branches will be removed but the steps will remain in the unit. 34,35 + + Peer Groups + + src/assets/wise5/classroomMonitor/classroomMonitorComponents/peer-group-button/peer-group-button.component.html + 5,9 + + Groupings for @@ -14753,13 +14780,6 @@ The branches will be removed but the steps will remain in the unit. 22,23 - - Item Info - - src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/node-info/node-info.component.html - 30,32 - - Alerts @@ -14834,7 +14854,7 @@ The branches will be removed but the steps will remain in the unit. Are you sure you want to proceed? src/assets/wise5/classroomMonitor/classroomMonitorComponents/shared/top-bar/top-bar.component.ts - 106 + 108 @@ -15634,6 +15654,17 @@ Are you sure you want to proceed? 91,94 + + Completion + + src/assets/wise5/classroomMonitor/student-grading/student-grading.component.html + 13,16 + + + src/assets/wise5/classroomMonitor/student-progress/student-progress.component.ts + 65 + + Total Score @@ -17586,7 +17617,7 @@ Are you ready to receive feedback on this answer? src/assets/wise5/directives/summary-display/summary-display.component.ts - 547 + 544 @@ -19767,11 +19798,11 @@ Warning: This will delete all existing choices and buckets in this component. src/assets/wise5/directives/summary-display/summary-display.component.ts - 292 + 301 src/assets/wise5/directives/summary-display/summary-display.component.ts - 355 + 367 @@ -19798,11 +19829,11 @@ Warning: This will delete all existing choices and buckets in this component. src/assets/wise5/directives/summary-display/summary-display.component.ts - 292 + 301 src/assets/wise5/directives/summary-display/summary-display.component.ts - 359 + 371 @@ -20362,13 +20393,6 @@ Warning: This will delete all existing choices in this component. 556,559 - - Hide - - src/assets/wise5/components/openResponse/edit-open-response-advanced/edit-open-response-advanced.component.html - 574,575 - - Show Idea Descriptions @@ -21547,7 +21571,7 @@ If this problem continues, let your teacher know and move on to the next activit X Axis Label src/assets/wise5/components/table/table-show-work/table-show-work.component.html - 66,67 + 64,65 src/assets/wise5/components/table/table-student/table-student.component.html @@ -21558,7 +21582,7 @@ If this problem continues, let your teacher know and move on to the next activit Y Axis Label src/assets/wise5/components/table/table-show-work/table-show-work.component.html - 76,77 + 74,75 src/assets/wise5/components/table/table-student/table-student.component.html @@ -21569,7 +21593,7 @@ If this problem continues, let your teacher know and move on to the next activit Y Axis Label src/assets/wise5/components/table/table-show-work/table-show-work.component.html - 93,94 + 91,92 src/assets/wise5/components/table/table-student/table-student.component.html @@ -21672,98 +21696,92 @@ If this problem continues, let your teacher know and move on to the next activit Your Response src/assets/wise5/directives/summary-display/summary-display.component.ts - 384 + 393 Your Score src/assets/wise5/directives/summary-display/summary-display.component.ts - 386 + 395 - - Period Responses + + Responses src/assets/wise5/directives/summary-display/summary-display.component.ts - 393 + 401 - - Period Scores + + Scores src/assets/wise5/directives/summary-display/summary-display.component.ts - 398 + 404 - - - Class Responses src/assets/wise5/directives/summary-display/summary-display.component.ts - 407 + 405 - - Class Scores + + Mean: src/assets/wise5/directives/summary-display/summary-display.component.ts - 412 + 404 - - - % Responded (/) src/assets/wise5/directives/summary-display/summary-display.component.ts - 423 + 405 Student Ideas Detected src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.html - 10,12 + 8,10 Most Common: src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.html - 17,19 + 15,17 Least Common: src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.html - 30,32 + 28,30 All Ideas: src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.html - 44,46 + 42,44 Hide all ideas src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.html - 55,57 + 53,55 Show all ideas src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.html - 57,61 + 55,58 - - Your students' ideas will show up here as they are detected in the activity. + + Your students' ideas will show up here as they are detected in the activity. src/assets/wise5/directives/teacher-summary-display/ideas-summary-display/ideas-summary.component.html - 61,66 + 58,60 @@ -21784,28 +21802,28 @@ If this problem continues, let your teacher know and move on to the next activit Choice Frequency src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.html - 39,42 + 37,39 - - This summary shows how many students moved each choice item into the different buckets (categories). + + Number of teams that moved each item (choice) into the different buckets (categories). src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.html - 42,45 + 39,42 Your students' choices will show up here when they complete the activity. src/assets/wise5/directives/teacher-summary-display/match-summary-display/match-summary-display.component.html - 67,72 + 58,61 The student will see a graph of their individual data here. src/assets/wise5/directives/teacher-summary-display/teacher-summary-display.component.ts - 46 + 69 @@ -22412,13 +22430,6 @@ If this problem continues, let your teacher know and move on to the next activit 13,17 - - % completed - - src/assets/wise5/vle/nav-item/nav-item.component.html - 53,54 - - / items