From: Ivo Almeida Date: Wed, 13 Nov 2024 12:16:23 +0000 (+0000) Subject: mgr/dashboard: fixed unit tests X-Git-Tag: v20.0.0~222^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=3f16e0c593156a03729e3478f7b97482f9eff71b;p=ceph.git mgr/dashboard: fixed unit tests * fixed unit tests due to upgrade to angular v18 * run npm fix in order to fix code style violations * upgraded eslint/* packages' versions * fixed eslint errors and warnings Fixes: https://tracker.ceph.com/issues/68896 Signed-off-by: Ivo Almeida --- diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000000..e711a88fc5715 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "ceph", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/src/pybind/mgr/dashboard/frontend/cypress/tsconfig.json b/src/pybind/mgr/dashboard/frontend/cypress/tsconfig.json index 0d1f6b468206e..c418e11247688 100644 --- a/src/pybind/mgr/dashboard/frontend/cypress/tsconfig.json +++ b/src/pybind/mgr/dashboard/frontend/cypress/tsconfig.json @@ -6,6 +6,10 @@ "plugins/index.js" ], "compilerOptions": { + "typeRoots": [ + "../node_modules", + "../node_modules/@types" + ], "sourceMap": false, "types": [ "cypress", @@ -14,4 +18,4 @@ ], "target": "es6" } -} +} \ No newline at end of file diff --git a/src/pybind/mgr/dashboard/frontend/jest.config.cjs b/src/pybind/mgr/dashboard/frontend/jest.config.cjs index 6777546d96312..218f9f4c23912 100644 --- a/src/pybind/mgr/dashboard/frontend/jest.config.cjs +++ b/src/pybind/mgr/dashboard/frontend/jest.config.cjs @@ -9,32 +9,38 @@ const esModules = [ '@ng-bootstrap' ]; const jestConfig = { - globals: { - 'ts-jest': { - useESM: true, - stringifyContentPathRegex: '\\.(html|svg)$', - tsconfig: '/tsconfig.spec.json', - isolatedModules: true - } - }, - globalSetup: 'jest-preset-angular/global-setup', moduleNameMapper: { '\\.scss$': 'identity-obj-proxy', '~/(.*)$': '/src/$1', - '^@carbon/icons/es/(.*)$': '@carbon/icons/lib/$1.js', + '^@carbon/icons/es/(.*)$': '@carbon/icons/lib/$1.js' }, moduleFileExtensions: ['ts', 'html', 'js', 'json', 'mjs', 'cjs'], preset: 'jest-preset-angular', setupFilesAfterEnv: ['/src/setupJest.ts'], transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$|'.concat(esModules.join('|'), ')')], transform: { - '^.+\\.(ts|html|mjs)$': 'jest-preset-angular', + '^.+\\.(ts|html|mjs)$': [ + 'jest-preset-angular', + { + useESM: true, + stringifyContentPathRegex: '\\.(html|svg)$', + tsconfig: '/tsconfig.spec.json', + isolatedModules: true + } + ], '^.+\\.(js)$': 'babel-jest' }, setupFiles: ['jest-canvas-mock'], coverageReporters: ['cobertura', 'html'], - modulePathIgnorePatterns: ['/coverage/', '/node_modules/simplebar-angular', '/cypress'], + modulePathIgnorePatterns: [ + '/coverage/', + '/node_modules/simplebar-angular', + '/cypress' + ], testMatch: ['**/*.spec.ts'], - testRunner: 'jest-jasmine2' + testRunner: 'jest-jasmine2', + testEnvironmentOptions: { + detectOpenHandles: true + } }; module.exports = jestConfig; diff --git a/src/pybind/mgr/dashboard/frontend/package-lock.json b/src/pybind/mgr/dashboard/frontend/package-lock.json index 536db275af8d8..975c3f74c69ec 100644 --- a/src/pybind/mgr/dashboard/frontend/package-lock.json +++ b/src/pybind/mgr/dashboard/frontend/package-lock.json @@ -27,9 +27,9 @@ "@popperjs/core": "2.10.2", "@types/file-saver": "2.0.1", "async-mutex": "0.2.4", - "bootstrap": "5.2.3", + "bootstrap": "5.3.2", "carbon-components-angular": "5.56.2", - "chart.js": "4.4.0", + "chart.js": "4.4.7", "chartjs-adapter-moment": "1.0.1", "detect-browser": "5.2.0", "file-saver": "2.0.2", @@ -38,7 +38,7 @@ "moment": "2.29.4", "ng-block-ui": "4.0.1", "ng-click-outside": "9.0.1", - "ng2-charts": "4.1.1", + "ng2-charts": "7.0.0", "ngx-cookie-service": "18.0.0", "ngx-toastr": "17.0.2", "rxjs": "6.6.3", @@ -52,43 +52,46 @@ }, "devDependencies": { "@angular-devkit/build-angular": "18.2.11", - "@angular-eslint/builder": "13.5.0", - "@angular-eslint/eslint-plugin": "13.5.0", - "@angular-eslint/eslint-plugin-template": "13.5.0", - "@angular-eslint/schematics": "18.3.1", - "@angular-eslint/template-parser": "13.5.0", + "@angular-eslint/builder": "18.4.0", + "@angular-eslint/eslint-plugin": "18.4.0", + "@angular-eslint/eslint-plugin-template": "18.4.0", + "@angular-eslint/schematics": "18.4.0", + "@angular-eslint/template-parser": "18.4.0", "@angular/cli": "18.2.11", "@angular/compiler-cli": "18.2.11", "@angular/language-service": "18.2.11", "@applitools/eyes-cypress": "3.22.5", "@compodoc/compodoc": "1.1.18", "@cypress/browserify-preprocessor": "3.0.2", + "@juggle/resize-observer": "3.4.0", "@types/brace-expansion": "1.1.0", + "@types/cypress": "0.1.6", + "@types/cypress-axe": "0.8.0", "@types/cypress-cucumber-preprocessor": "4.0.1", "@types/jest": "29.5.4", "@types/lodash": "4.14.161", "@types/node": "18.17.12", "@types/swagger-ui": "3.52.0", "@types/xml2js": "0.4.14", - "@typescript-eslint/eslint-plugin": "5.27.1", - "@typescript-eslint/parser": "5.27.1", + "@typescript-eslint/eslint-plugin": "8.14.0", + "@typescript-eslint/parser": "8.14.0", "axe-core": "4.4.3", "cypress": "12.17.4", "cypress-axe": "1.5.0", "cypress-cucumber-preprocessor": "4.3.1", "cypress-iframe": "1.0.1", "cypress-multi-reporters": "1.5.0", - "eslint": "8.17.0", + "eslint": "9.14.0", "gherkin-lint": "4.2.2", "html-linter": "1.1.1", "htmllint-cli": "0.0.7", "identity-obj-proxy": "3.0.0", "isomorphic-form-data": "2.0.0", - "jest": "29.6.4", + "jest": "29.7.0", "jest-canvas-mock": "2.4.0", "jest-jasmine2": "28.1.3", "jest-preset-angular": "14.2.4", - "jest-silent-reporter": "0.5.0", + "jest-silent-reporter": "0.6.0", "mocha-junit-reporter": "2.1.0", "ng-mocks": "14.13.1", "npm-run-all": "4.1.5", @@ -621,62 +624,62 @@ } }, "node_modules/@angular-eslint/builder": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-13.5.0.tgz", - "integrity": "sha512-IYY/HYS4fSddJLs2pAkMkKhHL07driUILPxGnGLblfWuoJBhRspyrVL3uZc3Q4iJXc1RJfaOno9oRw11FGyL6Q==", + "version": "18.4.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-18.4.0.tgz", + "integrity": "sha512-FOzGHX/nHSV1wSduSsabsx3aqC1nfde0opEpEDSOJhxExDxKCwoS1XPy1aERGyKip4ZVA6phC3dLtoBH3QMkVQ==", "dev": true, - "dependencies": { - "@nrwl/devkit": "13.1.3" - }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-13.5.0.tgz", - "integrity": "sha512-7M/5ilxqPD3ydgqqdLsYs3kBwZgNg2Y6C01B5SEHZNLqLT9kAJa7I4y6GlxCZqejCIh554kdXGeV3abIxFccSg==", + "version": "18.4.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-18.4.0.tgz", + "integrity": "sha512-HlFHt2qgdd+jqyVIkCXmrjHauXo/XY3Rp0UNabk83ejGi/raM/6lEFI7iFWzHxLyiAKk4OgGI5W26giSQw991A==", "dev": true }, "node_modules/@angular-eslint/eslint-plugin": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-13.5.0.tgz", - "integrity": "sha512-k9o9WIqUkdO8tdYFCJ54PUWsNd9HHflih/GmA13EWciBYx8QxciwBh0u4NSAnbtOwp4Y7juGZ/Dta5ZrT/2VBA==", + "version": "18.4.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-18.4.0.tgz", + "integrity": "sha512-Saz9lkWPN3da7ZKW17UsOSN7DeY+TPh+wz/6GCNZCh67Uw2wvMC9agb+4hgpZNXYCP5+u7erqzxQmBoWnS/A+A==", "dev": true, "dependencies": { - "@angular-eslint/utils": "13.5.0", - "@typescript-eslint/experimental-utils": "5.27.1" + "@angular-eslint/bundled-angular-compiler": "18.4.0", + "@angular-eslint/utils": "18.4.0" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0", + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/eslint-plugin-template": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-13.5.0.tgz", - "integrity": "sha512-ZVSXayn8MqYOhYomH2Cjc0azhuUQbY9fp9dKjJZOD64KhP8BYHw8+Ogc9E/FU5oZQ9fKw6A+23NAYKmLNqSAgA==", + "version": "18.4.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-18.4.0.tgz", + "integrity": "sha512-n3uZFCy76DnggPqjSVFV3gYD1ik7jCG28o2/HO4kobcMNKnwW8XAlFUagQ4TipNQh7fQiAefsEqvv2quMsYDVw==", "dev": true, "dependencies": { - "@angular-eslint/bundled-angular-compiler": "13.5.0", - "@typescript-eslint/experimental-utils": "5.27.1", - "aria-query": "^4.2.2", - "axobject-query": "^2.2.0" + "@angular-eslint/bundled-angular-compiler": "18.4.0", + "@angular-eslint/utils": "18.4.0", + "aria-query": "5.3.2", + "axobject-query": "4.1.0" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0", + "@typescript-eslint/types": "^7.11.0 || ^8.0.0", + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/schematics": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-18.3.1.tgz", - "integrity": "sha512-BTsQHDu7LjvXannJTb5BqMPCFIHRNN94eRyb60VfjJxB/ZFtsbAQDFFOi5lEZsRsd4mBeUMuL9mW4IMcPtUQ9Q==", + "version": "18.4.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-18.4.0.tgz", + "integrity": "sha512-ssqe+0YCfekbWIXNdCrHfoPK/bPZAWybs0Bn/b99dfd8h8uyXkERo9AzIOx4Uyj/08SkP9aPL/0uOOEHDsRGwQ==", "dev": true, "dependencies": { - "@angular-eslint/eslint-plugin": "18.3.1", - "@angular-eslint/eslint-plugin-template": "18.3.1", + "@angular-eslint/eslint-plugin": "18.4.0", + "@angular-eslint/eslint-plugin-template": "18.4.0", "ignore": "5.3.2", "semver": "7.6.3", "strip-json-comments": "3.1.1" @@ -686,76 +689,6 @@ "@angular-devkit/schematics": ">= 18.0.0 < 19.0.0" } }, - "node_modules/@angular-eslint/schematics/node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-18.3.1.tgz", - "integrity": "sha512-sikmkjfsXPpPTku1aQkQ1MNNEKGBgGGRvUN/WeNS9dhCJ4dxU3O7dZctt1aQWj+W3nbuUtDiimAWF5fZHGFE2Q==", - "dev": true - }, - "node_modules/@angular-eslint/schematics/node_modules/@angular-eslint/eslint-plugin": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-18.3.1.tgz", - "integrity": "sha512-MP4Nm+SHboF8KdnN0KpPEGAaTTzDLPm3+S/4W3Mg8onqWCyadyd4mActh9mK/pvCj8TVlb/SW1zeTtdMYhwonw==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "18.3.1", - "@angular-eslint/utils": "18.3.1" - }, - "peerDependencies": { - "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/schematics/node_modules/@angular-eslint/eslint-plugin-template": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-18.3.1.tgz", - "integrity": "sha512-hBJ3+f7VSidvrtYaXH7Vp0sWvblA9jLK2c6uQzhYGWdEDUcTg7g7VI9ThW39WvMbHqkyzNE4PPOynK69cBEDGg==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "18.3.1", - "@angular-eslint/utils": "18.3.1", - "aria-query": "5.3.0", - "axobject-query": "4.1.0" - }, - "peerDependencies": { - "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/schematics/node_modules/@angular-eslint/utils": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-18.3.1.tgz", - "integrity": "sha512-sd9niZI7h9H2FQ7OLiQsLFBhjhRQTASh+Q0+4+hyjv9idbSHBJli8Gsi2fqj9zhtMKpAZFTrWzuLUpubJ9UYbA==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "18.3.1" - }, - "peerDependencies": { - "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/schematics/node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/@angular-eslint/schematics/node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/@angular-eslint/schematics/node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -781,30 +714,55 @@ } }, "node_modules/@angular-eslint/template-parser": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-13.5.0.tgz", - "integrity": "sha512-k+24+kBjaOuthfp9RBQB0zH6UqeizZuFQFEuZEQbvirPbdQ2SqNBw7IcmW2Qw1v7fjFe6/6gqK7wm2g7o9ZZvA==", + "version": "18.4.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-18.4.0.tgz", + "integrity": "sha512-VTep3Xd3IOaRIPL+JN/TV4/2DqUPbjtF3TNY15diD/llnrEhqFnmsvMihexbQyTqzOG+zU554oK44YfvAtHOrw==", "dev": true, "dependencies": { - "@angular-eslint/bundled-angular-compiler": "13.5.0", - "eslint-scope": "^5.1.0" + "@angular-eslint/bundled-angular-compiler": "18.4.0", + "eslint-scope": "^8.0.2" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, + "node_modules/@angular-eslint/template-parser/node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@angular-eslint/template-parser/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/@angular-eslint/utils": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-13.5.0.tgz", - "integrity": "sha512-wX3W6STSDJDJ7ZyEsUdBp4HUPwmillMmKcdnFsy+qxbpJFzFOxOFpK1zet4ELsq1XpB89i9vRvC3vYbpHn3CSw==", + "version": "18.4.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-18.4.0.tgz", + "integrity": "sha512-At1yS8GRviGBoaupiQwEOL4/IcZJCE/+2vpXdItMWPGB1HWetxlKAUZTMmIBX/r5Z7CoXxl+LbqpGhrhyzIQAg==", "dev": true, "dependencies": { - "@angular-eslint/bundled-angular-compiler": "13.5.0", - "@typescript-eslint/experimental-utils": "5.27.1" + "@angular-eslint/bundled-angular-compiler": "18.4.0" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0", + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, @@ -5937,16 +5895,88 @@ "node": ">=18" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/core": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", + "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -5954,7 +5984,7 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -5987,15 +6017,12 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6031,6 +6058,70 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@eslint/js": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz", + "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==", + "dev": true, + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/@fastify/busboy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", @@ -6129,47 +6220,66 @@ "@hapi/hoek": "^9.0.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, "engines": { - "node": ">=10.10.0" + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" + "engines": { + "node": ">=18.18" }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, "engines": { - "node": "*" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@ibm/plex": { "version": "6.4.0", @@ -6257,7 +6367,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", "dev": true, - "license": "MIT", "dependencies": { "undici-types": "~6.19.8" } @@ -7557,10 +7666,18 @@ "tslib": "2" } }, + "node_modules/@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/@kurkle/color": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", - "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", + "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", + "license": "MIT" }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.5", @@ -8173,686 +8290,6 @@ "node": "^16.13.0 || >=18.0.0" } }, - "node_modules/@nrwl/cli": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/@nrwl/cli/-/cli-15.9.3.tgz", - "integrity": "sha512-qiAKHkov3iBx6hroPTitUrkRSUZFQqVgNJiF9gXRFC6pNJe9RS4rlmcIaoUFOboi9CnH5jwblNJVcz8YSVYOvA==", - "dev": true, - "dependencies": { - "nx": "15.9.3" - } - }, - "node_modules/@nrwl/cli/node_modules/@nrwl/tao": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-15.9.3.tgz", - "integrity": "sha512-NcjFCbuMa53C3fBrK7qLUImUBySyr9EVwmiZuAv9sZZtm4eILK8w3qihjrB4FFUuLjPU/SViriYXi+hF2tbP4w==", - "dev": true, - "dependencies": { - "nx": "15.9.3" - }, - "bin": { - "tao": "index.js" - } - }, - "node_modules/@nrwl/cli/node_modules/@zkochan/js-yaml": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", - "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@nrwl/cli/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@nrwl/cli/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@nrwl/cli/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@nrwl/cli/node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@nrwl/cli/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/@nrwl/cli/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@nrwl/cli/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@nrwl/cli/node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nrwl/cli/node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@nrwl/cli/node_modules/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@nrwl/cli/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nrwl/cli/node_modules/lines-and-columns": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", - "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/@nrwl/cli/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nrwl/cli/node_modules/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@nrwl/cli/node_modules/nx": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/nx/-/nx-15.9.3.tgz", - "integrity": "sha512-GLwbykfTABc7/UZjQEEnV1bQbTVC53W+Zj4xWY640/45I4iZf/TUqKMBCgtLZ9v89gEsKOM4zsx55CqHT3bekA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nrwl/cli": "15.9.3", - "@nrwl/tao": "15.9.3", - "@parcel/watcher": "2.0.4", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "^3.0.0-rc.18", - "@zkochan/js-yaml": "0.0.6", - "axios": "^1.0.0", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^7.0.2", - "dotenv": "~10.0.0", - "enquirer": "~2.3.6", - "fast-glob": "3.2.7", - "figures": "3.2.0", - "flat": "^5.0.2", - "fs-extra": "^11.1.0", - "glob": "7.1.4", - "ignore": "^5.0.4", - "js-yaml": "4.1.0", - "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", - "minimatch": "3.0.5", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "semver": "7.3.4", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "v8-compile-cache": "2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js" - }, - "optionalDependencies": { - "@nrwl/nx-darwin-arm64": "15.9.3", - "@nrwl/nx-darwin-x64": "15.9.3", - "@nrwl/nx-linux-arm-gnueabihf": "15.9.3", - "@nrwl/nx-linux-arm64-gnu": "15.9.3", - "@nrwl/nx-linux-arm64-musl": "15.9.3", - "@nrwl/nx-linux-x64-gnu": "15.9.3", - "@nrwl/nx-linux-x64-musl": "15.9.3", - "@nrwl/nx-win32-arm64-msvc": "15.9.3", - "@nrwl/nx-win32-x64-msvc": "15.9.3" - }, - "peerDependencies": { - "@swc-node/register": "^1.4.2", - "@swc/core": "^1.2.173" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nrwl/cli/node_modules/semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nrwl/cli/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nrwl/cli/node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/@nrwl/cli/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@nrwl/devkit": { - "version": "13.1.3", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-13.1.3.tgz", - "integrity": "sha512-TAAsZJvVc/obeH0rZKY6miVhyM2GHGb8qIWp9MAIdLlXf4VDcNC7rxwb5OrGVSwuTTjqGYBGPUx0yEogOOJthA==", - "dev": true, - "dependencies": { - "@nrwl/tao": "13.1.3", - "ejs": "^3.1.5", - "ignore": "^5.0.4", - "rxjs": "^6.5.4", - "semver": "7.3.4", - "tslib": "^2.0.0" - } - }, - "node_modules/@nrwl/devkit/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nrwl/devkit/node_modules/semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nrwl/devkit/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@nrwl/nx-darwin-arm64": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/@nrwl/nx-darwin-arm64/-/nx-darwin-arm64-15.9.3.tgz", - "integrity": "sha512-2htJzVa+S/uLg5tj4nbO/tRz2SRMQIpT6EeWMgDGuEKQdpuRLVj2ez9hMpkRn9tl1tBUwR05hbV28DnOLRESVA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/nx-darwin-x64": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/@nrwl/nx-darwin-x64/-/nx-darwin-x64-15.9.3.tgz", - "integrity": "sha512-p+8UkfC6KTLOX4XRt7NSP8DoTzEgs73+SN0csoXT9VsNO35+F0Z5zMZxpEc7RVo5Wen/4PGh2OWA+8gtgntsJQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/nx-linux-arm-gnueabihf": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-15.9.3.tgz", - "integrity": "sha512-xwW7bZtggrxhFbYvvWWArtcSWwoxWzi/4wNgP3wPbcZFNZiraahVQSpIyJXrS9aajGbdvuDBM8cbDsMj9v7mwg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/nx-linux-arm64-gnu": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-15.9.3.tgz", - "integrity": "sha512-KNxDL2OAHxhFqztEjv2mNwXD6xrzoUury7NsYZYqlxJUNc3YYBfRSLEatnw491crvMBndbxfGVTWEO9S4YmRuw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/nx-linux-arm64-musl": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-arm64-musl/-/nx-linux-arm64-musl-15.9.3.tgz", - "integrity": "sha512-AxoZzfsXH7ZqDE+WrQtRumufIcSIBw4U/LikiDLaWWoGtNpAfKLkD/PHirZiNxHIeGy1Toi4ccMUolXbafLVFw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/nx-linux-x64-gnu": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-x64-gnu/-/nx-linux-x64-gnu-15.9.3.tgz", - "integrity": "sha512-P8AOPRufvV4a5cSczNsw84zFAI7NgAiEBTybYcyymdNJmo0iArJXEmvj/G4mB20O8VCsCkwqMYAu6nQEnES1Kw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/nx-linux-x64-musl": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/@nrwl/nx-linux-x64-musl/-/nx-linux-x64-musl-15.9.3.tgz", - "integrity": "sha512-4ZYDp7T319+xbw7Z7KVtRefzaXJipZfgrM49r+Y1FAfYDc8y18zvKz3slK26wfWz+EUZwKsa/DfA2KmyRG3DvQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/nx-win32-arm64-msvc": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/@nrwl/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-15.9.3.tgz", - "integrity": "sha512-UhgxIPgTZBKN1oxlLPSklkSzVL3hA4lAiVc9A0Utumpbp0ob/Xx+2vHzg3cnmNH3jWkZ+9OsC2dKyeMB6gAbSw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/nx-win32-x64-msvc": { - "version": "15.9.3", - "resolved": "https://registry.npmjs.org/@nrwl/nx-win32-x64-msvc/-/nx-win32-x64-msvc-15.9.3.tgz", - "integrity": "sha512-gdnvqURKnu0EQGOFJ6NUKq6wSB+viNb7Z8qtKhzSmFwVjT8akOnLWn7ZhL9v28TAjLM7/s1Mwvmz/IMj1PGlcQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/tao": { - "version": "13.1.3", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-13.1.3.tgz", - "integrity": "sha512-/IwJgSgCBD1SaF+n8RuXX2OxDAh8ut/+P8pMswjm8063ac30UlAHjQ4XTYyskLH8uoUmNi2hNaGgHUrkwt7tQA==", - "dev": true, - "dependencies": { - "chalk": "4.1.0", - "enquirer": "~2.3.6", - "fs-extra": "^9.1.0", - "jsonc-parser": "3.0.0", - "nx": "13.1.3", - "rxjs": "^6.5.4", - "rxjs-for-await": "0.0.2", - "semver": "7.3.4", - "tmp": "~0.2.1", - "tslib": "^2.0.0", - "yargs-parser": "20.0.0" - }, - "bin": { - "tao": "index.js" - } - }, - "node_modules/@nrwl/tao/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@nrwl/tao/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@nrwl/tao/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@nrwl/tao/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@nrwl/tao/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nrwl/tao/node_modules/jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true - }, - "node_modules/@nrwl/tao/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nrwl/tao/node_modules/semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nrwl/tao/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nrwl/tao/node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/@nrwl/tao/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@nrwl/tao/node_modules/yargs-parser": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.0.0.tgz", - "integrity": "sha512-8eblPHTL7ZWRkyjIZJjnGf+TijiKJSwA24svzLRVvtgoi/RZiKa9fFQTrlx0OKLnyHSdt/enrdadji6WFfESVA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@parcel/watcher": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.4.tgz", - "integrity": "sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^3.2.1", - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -9831,22 +9268,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/@tufjs/models/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -9933,6 +9354,33 @@ "@types/node": "*" } }, + "node_modules/@types/cypress": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@types/cypress/-/cypress-0.1.6.tgz", + "integrity": "sha512-FYKQLvCsRYxZ3fp+XsoCiJZ1aK3x17RmaZjHI4Ou43khFkXPycrQaXo9b1J07PNlEfWnRtUc9loxHXzKjSsbYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/cypress-axe": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@types/cypress-axe/-/cypress-axe-0.8.0.tgz", + "integrity": "sha512-4sTqNsXUXnl/CqmSI+xCCmYwml+/zZ66uBExMLqnF1dn3wd+BIyrLL8fJ81O/AJePuh08igR2VjZqWuZaoqWaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "axe-core": "^3.4.1" + } + }, + "node_modules/@types/cypress-axe/node_modules/axe-core": { + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-3.5.6.tgz", + "integrity": "sha512-LEUDjgmdJoA3LqklSTwKYqkjcZ4HKc4ddIYGSAiSkr46NTjzg2L9RNB+lekO9P7Dlpa87+hBtzc2Fzn/+GUWMQ==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, "node_modules/@types/cypress-cucumber-preprocessor": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/cypress-cucumber-preprocessor/-/cypress-cucumber-preprocessor-4.0.1.tgz", @@ -10383,31 +9831,31 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.1.tgz", - "integrity": "sha512-6dM5NKT57ZduNnJfpY81Phe9nc9wolnMCnknb1im6brWi1RYv84nbMS3olJa27B6+irUVV1X/Wb+Am0FjJdGFw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.27.1", - "@typescript-eslint/type-utils": "5.27.1", - "@typescript-eslint/utils": "5.27.1", - "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.2.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.14.0.tgz", + "integrity": "sha512-tqp8H7UWFaZj0yNO6bycd5YjMwxa6wIHOLZvWPkidwbgLCsBMetQoGj7DPuAlWa2yGO3H48xmPwjhsSPPCGU5w==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/type-utils": "8.14.0", + "@typescript-eslint/utils": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -10415,78 +9863,27 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.27.1.tgz", - "integrity": "sha512-Vd8uewIixGP93sEnmTRIH6jHZYRQRkGPDPpapACMvitJKX8335VHNyqKTE+mZ+m3E2c5VznTZfSsSsS5IF7vUA==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "5.27.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, "node_modules/@typescript-eslint/parser": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.1.tgz", - "integrity": "sha512-7Va2ZOkHi5NP+AZwb5ReLgNF6nWLGTeUJfxdkVUAPPSaAdbWNnFZzLZ4EGGmmiCTg+AwlbE1KyUYTBglosSLHQ==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz", + "integrity": "sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.27.1", - "@typescript-eslint/types": "5.27.1", - "@typescript-eslint/typescript-estree": "5.27.1", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/typescript-estree": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -10495,16 +9892,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.1.tgz", - "integrity": "sha512-fQEOSa/QroWE6fAEg+bJxtRZJTH8NTskggybogHt4H9Da8zd4cJji76gA5SBlR0MgtwF7rebxTbDKB49YUCpAg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.14.0.tgz", + "integrity": "sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.27.1", - "@typescript-eslint/visitor-keys": "5.27.1" + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -10512,25 +9909,23 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.27.1.tgz", - "integrity": "sha512-+UC1vVUWaDHRnC2cQrCJ4QtVjpjjCgjNFpg8b03nERmkHv9JV9X5M19D7UFMd+/G7T/sgFwX2pGmWK38rqyvXw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.14.0.tgz", + "integrity": "sha512-Xcz9qOtZuGusVOH5Uk07NGs39wrKkf3AxlkK79RBK6aJC1l03CobXjJbwBPSidetAOV+5rEVuiT1VSBUOAsanQ==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "5.27.1", + "@typescript-eslint/typescript-estree": "8.14.0", + "@typescript-eslint/utils": "8.14.0", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "eslint": "*" - }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -10538,12 +9933,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.1.tgz", - "integrity": "sha512-LgogNVkBhCTZU/m8XgEYIWICD6m4dmEDbKXESCbqOXfKZxRKeqpiJXQIErv66sdopRKZPo5l32ymNqibYEH/xg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.14.0.tgz", + "integrity": "sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -10551,21 +9946,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.1.tgz", - "integrity": "sha512-DnZvvq3TAJ5ke+hk0LklvxwYsnXpRdqUY5gaVS0D4raKtbznPz71UJGnPTHEFo0GDxqLOLdMkkmVZjSpET1hFw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.14.0.tgz", + "integrity": "sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.27.1", - "@typescript-eslint/visitor-keys": "5.27.1", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -10577,46 +9973,11 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -10624,56 +9985,39 @@ "node": ">=10" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@typescript-eslint/utils": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.27.1.tgz", - "integrity": "sha512-mZ9WEn1ZLDaVrhRaYgzbkXBkTPghPFsup8zDbbsYTxC5OmqrFE7skkKS/sraVsLP3TcT3Ki5CSyEFBRkLH/H/w==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.14.0.tgz", + "integrity": "sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.27.1", - "@typescript-eslint/types": "5.27.1", - "@typescript-eslint/typescript-estree": "5.27.1", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/typescript-estree": "8.14.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.1.tgz", - "integrity": "sha512-xYs6ffo01nhdJgPieyk7HAOpjhTsx7r/oB9LWEhwAXgwn33tkr+W8DI2ChboqhZlC4q3TC6geDYPoiX8ROqyOQ==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.14.0.tgz", + "integrity": "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.27.1", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "8.14.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -10874,47 +10218,6 @@ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", "dev": true }, - "node_modules/@yarnpkg/parsers": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0.tgz", - "integrity": "sha512-jVZa3njBv6tcOUw34nlUdUM/40wwtm/gnVF8rtk0tA6vNcokqYI8CFU1BZjlpFwUSZaXxYkrtuPE/f2MMFlTxQ==", - "dev": true, - "dependencies": { - "js-yaml": "^3.10.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=18.12.0" - } - }, - "node_modules/@yarnpkg/parsers/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@yarnpkg/parsers/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@yarnpkg/parsers/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -10958,9 +10261,9 @@ } }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -11312,16 +10615,12 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, - "dependencies": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - }, "engines": { - "node": ">=6.0" + "node": ">= 0.4" } }, "node_modules/arr-diff": { @@ -11769,10 +11068,13 @@ } }, "node_modules/axobject-query": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", - "dev": true + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } }, "node_modules/babel-jest": { "version": "29.7.0", @@ -12275,9 +11577,9 @@ "dev": true }, "node_modules/bootstrap": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz", - "integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.2.tgz", + "integrity": "sha512-D32nmNWiQHo94BKHLmOrdjlL05q1c8oxbtBphQFb9Z5to6eGRDCm0QgeaZ4zFBHzfg2++rqa2JkqCcxDy0sH0g==", "funding": [ { "type": "github", @@ -12288,8 +11590,9 @@ "url": "https://opencollective.com/bootstrap" } ], + "license": "MIT", "peerDependencies": { - "@popperjs/core": "^2.11.6" + "@popperjs/core": "^2.11.8" } }, "node_modules/brace-expansion": { @@ -13122,14 +12425,15 @@ } }, "node_modules/chart.js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.0.tgz", - "integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==", + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.7.tgz", + "integrity": "sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==", + "license": "MIT", "dependencies": { "@kurkle/color": "^0.3.0" }, "engines": { - "pnpm": ">=7" + "pnpm": ">=8" } }, "node_modules/chartjs-adapter-moment": { @@ -15559,15 +14863,6 @@ "deps-sort": "bin/cmd.js" } }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/des.js": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", @@ -15710,18 +15005,6 @@ "node": ">=6" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -15824,15 +15107,6 @@ "integrity": "sha512-kxM7fSnNQTXOmaeGuBSXM8O3fEsBb7XSDBllkGbRwa0lJSJTxxDE/4eSNGLKZUmlFw0f1vJ5qSV2BljrgQtgIA==", "dev": true }, - "node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/drange": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz", @@ -15919,21 +15193,6 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true }, - "node_modules/ejs": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", - "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", - "dev": true, - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/electron-to-chromium": { "version": "1.5.55", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.55.tgz", @@ -16426,55 +15685,63 @@ } }, "node_modules/eslint": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.17.0.tgz", - "integrity": "sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.7.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.14.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.0", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "optionator": "^0.9.3", + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-scope": { @@ -16490,33 +15757,6 @@ "node": ">=8.0.0" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", @@ -16617,16 +15857,28 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -16641,33 +15893,59 @@ "node": ">=4.0" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/eslint/node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "is-glob": "^4.0.3" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=16.0.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint/node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/eslint/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -16696,6 +15974,21 @@ "node": ">= 0.8.0" } }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -16725,27 +16018,45 @@ "node": ">= 0.8.0" } }, - "node_modules/eslint/node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint/node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -16771,17 +16082,29 @@ } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -17531,15 +16854,6 @@ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dev": true, - "dependencies": { - "minimatch": "^5.0.1" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -18131,7 +17445,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "devOptional": true + "optional": true }, "node_modules/fs-extra": { "version": "9.1.0", @@ -18207,12 +17521,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -18533,22 +17841,6 @@ "dev": true, "license": "BSD-2-Clause" }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/global-dirs": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", @@ -18710,6 +18002,12 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -19912,22 +19210,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/ignore-walk/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/image-size": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", @@ -21039,126 +20321,17 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jake": { - "version": "10.8.7", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", - "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", - "dev": true, - "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jake/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jake/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/jake/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jake/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jake/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jake/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jake/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jake/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.4.tgz", - "integrity": "sha512-tEFhVQFF/bzoYV1YuGyzLPZ6vlPrdfvDmmAxudA1dLEuiztqg2Rkx20vkKY32xiDROcD2KXlgZ7Cu8RPeEHRKw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, + "license": "MIT", "dependencies": { - "@jest/core": "^29.6.4", + "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.6.4" + "jest-cli": "^29.7.0" }, "bin": { "jest": "bin/jest.js" @@ -23278,10 +22451,11 @@ } }, "node_modules/jest-silent-reporter": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jest-silent-reporter/-/jest-silent-reporter-0.5.0.tgz", - "integrity": "sha512-epdLt8Oj0a1AyRiR6F8zx/1SVT1Mi7VU3y4wB2uOBHs/ohIquC7v2eeja7UN54uRPyHInIKWdL+RdG228n5pJQ==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/jest-silent-reporter/-/jest-silent-reporter-0.6.0.tgz", + "integrity": "sha512-4nmS+5o7ycVlvbQOTx7CnGdbBtP2646hnDgQpQLaVhjHcQNHD+gqBAetyjRDlgpZ8+8N82MWI59K+EX2LsVk7g==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "jest-util": "^26.0.0" @@ -24404,12 +23578,6 @@ "node": ">=6" } }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -25784,15 +24952,18 @@ "dev": true }, "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -26070,6 +25241,7 @@ "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.1.0.tgz", "integrity": "sha512-Zhz1J+XqJUaAOuSFtHgi2+b+W3rP1SZtaU3HHNNp1iEKMSeoC1/EQUVkGknkLNOBxJhXJ4xLgOr8TbYAZOkUIw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^2.2.0", "md5": "^2.1.0", @@ -26086,6 +25258,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -26095,6 +25268,7 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.6" }, @@ -26106,7 +25280,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/module-deps": { "version": "6.2.3", @@ -26528,17 +25703,19 @@ } }, "node_modules/ng2-charts": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-4.1.1.tgz", - "integrity": "sha512-iHwXDbmX86lfeH8VRcsaW2tJATsuAZo4kvvC/Yk2l35zOHjevja1qBvO6BAibiDazi9r9aS6ZRJOqWPsz1pP2w==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-7.0.0.tgz", + "integrity": "sha512-HofyPPkz7yOX6Dr9JfV/SDddzmmqCFYCKbn71jeDiyWPRjrj99yTBCyqYtjzzNrnlTfWwbdvynYZ4GAhu/lbgQ==", + "license": "MIT", "dependencies": { "lodash-es": "^4.17.15", "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/cdk": ">=14.0.0", - "@angular/common": ">=14.0.0", - "@angular/core": ">=14.0.0", + "@angular/cdk": ">=18.0.0", + "@angular/common": ">=18.0.0", + "@angular/core": ">=18.0.0", + "@angular/platform-browser": ">=18.0.0", "chart.js": "^3.4.0 || ^4.0.0", "rxjs": "^6.5.3 || ^7.4.0" } @@ -26658,7 +25835,8 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true + "dev": true, + "optional": true }, "node_modules/node-domexception": { "version": "1.0.0", @@ -26754,6 +25932,7 @@ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.7.0.tgz", "integrity": "sha512-PbZERfeFdrHQOOXiAKOY0VPbykZy90ndPKk0d+CFDegTKmWp1VgOTz2xACVbr1BjCWxrQp68CXtvNsveFhqDJg==", "dev": true, + "optional": true, "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -27193,18 +26372,6 @@ "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", "dev": true }, - "node_modules/nx": { - "version": "13.1.3", - "resolved": "https://registry.npmjs.org/nx/-/nx-13.1.3.tgz", - "integrity": "sha512-clM0NQhQKYkqcNz2E3uYRMLwhp2L/9dBhJhQi9XBX4IAyA2gWAomhRIlLm5Xxg3g4h1xwSpP3eJ5t89VikY8Pw==", - "dev": true, - "dependencies": { - "@nrwl/cli": "*" - }, - "bin": { - "nx": "bin/nx.js" - } - }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -27415,24 +26582,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/opencollective-postinstall": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", @@ -30057,18 +29206,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/regexpu-core": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", @@ -30676,15 +29813,6 @@ "npm": ">=2.0.0" } }, - "node_modules/rxjs-for-await": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/rxjs-for-await/-/rxjs-for-await-0.0.2.tgz", - "integrity": "sha512-IJ8R/ZCFMHOcDIqoABs82jal00VrZx8Xkgfe7TOKoaRPAW5nH/VFlG23bXpeGdrmtqI9UobFPgUKgCuFc7Lncw==", - "dev": true, - "peerDependencies": { - "rxjs": "^6.0.0" - } - }, "node_modules/rxjs/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -32515,23 +31643,6 @@ "node": ">=0.10.0" } }, - "node_modules/strong-log-transformer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", - "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", - "dev": true, - "dependencies": { - "duplexer": "^0.1.1", - "minimist": "^1.2.0", - "through": "^2.3.4" - }, - "bin": { - "sl-log-transformer": "bin/sl-log-transformer.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", @@ -33179,7 +32290,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "devOptional": true, + "optional": true, "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -33766,6 +32877,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/ts-api-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-jest": { "version": "29.1.1", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", @@ -33891,46 +33014,11 @@ "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz", "integrity": "sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==" }, - "node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, - "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/tty-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", @@ -34221,8 +33309,7 @@ "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", diff --git a/src/pybind/mgr/dashboard/frontend/package.json b/src/pybind/mgr/dashboard/frontend/package.json index f55d409f03988..aa950f4cf60a6 100644 --- a/src/pybind/mgr/dashboard/frontend/package.json +++ b/src/pybind/mgr/dashboard/frontend/package.json @@ -19,7 +19,7 @@ "i18n:merge": "npx i18ntool merge -c i18n.config.json", "i18n:token": "npx i18ntool config token", "test": "jest --watch", - "test:ci": "jest --clearCache && JEST_SILENT_REPORTER_DOTS=true jest --coverage --reporters jest-silent-reporter", + "test:ci": "jest --clearCache && JEST_SILENT_REPORTER_DOTS=true jest --detectOpenHandles --coverage --reporters jest-silent-reporter", "pree2e": "rm -f cypress/reports/results-*.xml || true", "e2e": "start-test 4200 'cypress open'", "pree2e:ci": "npm run pree2e", @@ -28,7 +28,6 @@ "lint:gherkin": "gherkin-lint -c .gherkin-lintrc cypress/e2e", "lint:prettier": "prettier --list-different \"{src,cypress}/**/*.{ts,scss}\"", "lint:html": "htmllint src/app/**/*.html && html-linter --config html-linter.config.json", - "prelint:tsc": "npm run postinstall", "lint:tsc": "tsc -p tsconfig.app.json --noEmit && tsc -p tsconfig.spec.json --noEmit && tsc -p cypress/tsconfig.json --noEmit", "lint:scss": "stylelint '**/*.scss'", "lint": "run-p -csl --aggregate-output lint:*", @@ -61,9 +60,9 @@ "@popperjs/core": "2.10.2", "@types/file-saver": "2.0.1", "async-mutex": "0.2.4", - "bootstrap": "5.2.3", + "bootstrap": "5.3.2", "carbon-components-angular": "5.56.2", - "chart.js": "4.4.0", + "chart.js": "4.4.7", "chartjs-adapter-moment": "1.0.1", "detect-browser": "5.2.0", "file-saver": "2.0.2", @@ -72,7 +71,7 @@ "moment": "2.29.4", "ng-block-ui": "4.0.1", "ng-click-outside": "9.0.1", - "ng2-charts": "4.1.1", + "ng2-charts": "7.0.0", "ngx-cookie-service": "18.0.0", "ngx-toastr": "17.0.2", "rxjs": "6.6.3", @@ -86,43 +85,46 @@ }, "devDependencies": { "@angular-devkit/build-angular": "18.2.11", - "@angular-eslint/builder": "13.5.0", - "@angular-eslint/eslint-plugin": "13.5.0", - "@angular-eslint/eslint-plugin-template": "13.5.0", - "@angular-eslint/schematics": "18.3.1", - "@angular-eslint/template-parser": "13.5.0", + "@angular-eslint/builder": "18.4.0", + "@angular-eslint/eslint-plugin": "18.4.0", + "@angular-eslint/eslint-plugin-template": "18.4.0", + "@angular-eslint/schematics": "18.4.0", + "@angular-eslint/template-parser": "18.4.0", "@angular/cli": "18.2.11", "@angular/compiler-cli": "18.2.11", "@angular/language-service": "18.2.11", "@applitools/eyes-cypress": "3.22.5", "@compodoc/compodoc": "1.1.18", "@cypress/browserify-preprocessor": "3.0.2", + "@juggle/resize-observer": "3.4.0", "@types/brace-expansion": "1.1.0", + "@types/cypress": "0.1.6", + "@types/cypress-axe": "0.8.0", "@types/cypress-cucumber-preprocessor": "4.0.1", "@types/jest": "29.5.4", "@types/lodash": "4.14.161", "@types/node": "18.17.12", "@types/swagger-ui": "3.52.0", "@types/xml2js": "0.4.14", - "@typescript-eslint/eslint-plugin": "5.27.1", - "@typescript-eslint/parser": "5.27.1", + "@typescript-eslint/eslint-plugin": "8.14.0", + "@typescript-eslint/parser": "8.14.0", "axe-core": "4.4.3", "cypress": "12.17.4", "cypress-axe": "1.5.0", "cypress-cucumber-preprocessor": "4.3.1", "cypress-iframe": "1.0.1", "cypress-multi-reporters": "1.5.0", - "eslint": "8.17.0", + "eslint": "9.14.0", "gherkin-lint": "4.2.2", "html-linter": "1.1.1", "htmllint-cli": "0.0.7", "identity-obj-proxy": "3.0.0", "isomorphic-form-data": "2.0.0", - "jest": "29.6.4", + "jest": "29.7.0", "jest-canvas-mock": "2.4.0", "jest-jasmine2": "28.1.3", "jest-preset-angular": "14.2.4", - "jest-silent-reporter": "0.5.0", + "jest-silent-reporter": "0.6.0", "mocha-junit-reporter": "2.1.0", "ng-mocks": "14.13.1", "npm-run-all": "4.1.5", diff --git a/src/pybind/mgr/dashboard/frontend/src/app/app.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/app.module.ts index e60ed5cb8b74a..6b7134bd213ef 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/app.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/app.module.ts @@ -14,32 +14,38 @@ import { ApiInterceptorService } from './shared/services/api-interceptor.service import { JsErrorHandler } from './shared/services/js-error-handler.service'; import { SharedModule } from './shared/shared.module'; -@NgModule({ declarations: [AppComponent], - exports: [SharedModule], - bootstrap: [AppComponent], imports: [BrowserModule, - BrowserAnimationsModule, - ToastrModule.forRoot({ - positionClass: 'toast-top-right', - preventDuplicates: true, - enableHtml: true - }), - AppRoutingModule, - CoreModule, - SharedModule, - CephModule], providers: [ - { - provide: ErrorHandler, - useClass: JsErrorHandler - }, - { - provide: HTTP_INTERCEPTORS, - useClass: ApiInterceptorService, - multi: true - }, - { - provide: APP_BASE_HREF, - useValue: '/' + (window.location.pathname.split('/', 1)[1] || '') - }, - provideHttpClient(withInterceptorsFromDi()) - ] }) +@NgModule({ + declarations: [AppComponent], + exports: [SharedModule], + bootstrap: [AppComponent], + imports: [ + BrowserModule, + BrowserAnimationsModule, + ToastrModule.forRoot({ + positionClass: 'toast-top-right', + preventDuplicates: true, + enableHtml: true + }), + AppRoutingModule, + CoreModule, + SharedModule, + CephModule + ], + providers: [ + { + provide: ErrorHandler, + useClass: JsErrorHandler + }, + { + provide: HTTP_INTERCEPTORS, + useClass: ApiInterceptorService, + multi: true + }, + { + provide: APP_BASE_HREF, + useValue: '/' + (window.location.pathname.split('/', 1)[1] || '') + }, + provideHttpClient(withInterceptorsFromDi()) + ] +}) export class AppModule {} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts index 59aac44272851..4ddaea985b568 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts @@ -6,7 +6,6 @@ import { RouterTestingModule } from '@angular/router/testing'; import { ToastrModule } from 'ngx-toastr'; -import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component'; import { SelectOption } from '~/app/shared/components/select/select-option.model'; import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; import { SharedModule } from '~/app/shared/shared.module'; @@ -137,25 +136,22 @@ describe('IscsiTargetFormComponent', () => { } ]; - configureTestBed( - { - declarations: [IscsiTargetFormComponent], - imports: [ - SharedModule, - ReactiveFormsModule, - HttpClientTestingModule, - RouterTestingModule, - ToastrModule.forRoot() - ], - providers: [ - { - provide: ActivatedRoute, - useValue: new ActivatedRouteStub({ target_iqn: undefined }) - } - ] - }, - [LoadingPanelComponent] - ); + configureTestBed({ + declarations: [IscsiTargetFormComponent], + imports: [ + SharedModule, + ReactiveFormsModule, + HttpClientTestingModule, + RouterTestingModule, + ToastrModule.forRoot() + ], + providers: [ + { + provide: ActivatedRoute, + useValue: new ActivatedRouteStub({ target_iqn: undefined }) + } + ] + }); beforeEach(() => { fixture = TestBed.createComponent(IscsiTargetFormComponent); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-gateway/nvmeof-gateway.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-gateway/nvmeof-gateway.component.ts index 0ddb8e2f611f6..468fc2c4026ca 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-gateway/nvmeof-gateway.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-gateway/nvmeof-gateway.component.ts @@ -1,4 +1,4 @@ -import { Component, TemplateRef, ViewChild } from '@angular/core'; +import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; import _ from 'lodash'; @@ -28,7 +28,7 @@ type Gateway = { templateUrl: './nvmeof-gateway.component.html', styleUrls: ['./nvmeof-gateway.component.scss'] }) -export class NvmeofGatewayComponent { +export class NvmeofGatewayComponent implements OnInit { @ViewChild('statusTpl', { static: true }) statusTpl: TemplateRef; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts index c09ec7858c598..f4064f0cae84e 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-configuration-list/rbd-configuration-list.component.spec.ts @@ -4,7 +4,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { RouterTestingModule } from '@angular/router/testing'; import { NgbDropdownModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; -import { NgChartsModule } from 'ng2-charts'; +import { BaseChartDirective } from 'ng2-charts'; import { ComponentsModule } from '~/app/shared/components/components.module'; import { RbdConfigurationEntry } from '~/app/shared/models/configuration'; @@ -25,7 +25,7 @@ describe('RbdConfigurationListComponent', () => { RouterTestingModule, ComponentsModule, NgbDropdownModule, - NgChartsModule, + BaseChartDirective, SharedModule, NgbTooltipModule ], diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.spec.ts index 10b8c09fabd45..924feb6cf4331 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.spec.ts @@ -10,7 +10,6 @@ import { Subject, throwError as observableThrowError } from 'rxjs'; import { RbdService } from '~/app/shared/api/rbd.service'; import { ComponentsModule } from '~/app/shared/components/components.module'; -import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component'; import { ActionLabelsI18n } from '~/app/shared/constants/app.constants'; import { DataTableModule } from '~/app/shared/datatable/datatable.module'; import { TableActionsComponent } from '~/app/shared/datatable/table-actions/table-actions.component'; @@ -55,38 +54,35 @@ describe('RbdSnapshotListComponent', () => { } }; - configureTestBed( - { - declarations: [ - RbdSnapshotListComponent, - RbdTabsComponent, - MockComponent(RbdSnapshotFormModalComponent), - BaseModal - ], - imports: [ - BrowserAnimationsModule, - ComponentsModule, - DataTableModule, - HttpClientTestingModule, - PipesModule, - RouterTestingModule, - NgbNavModule, - ToastrModule.forRoot(), - ModalModule, - PlaceholderModule, - CoreModule - ], - providers: [ - { provide: AuthStorageService, useValue: fakeAuthStorageService }, - TaskListService, - ModalService, - PlaceholderService, - BaseModalService - ], - schemas: [NO_ERRORS_SCHEMA] - }, - [CriticalConfirmationModalComponent] - ); + configureTestBed({ + declarations: [ + RbdSnapshotListComponent, + RbdTabsComponent, + MockComponent(RbdSnapshotFormModalComponent), + BaseModal + ], + imports: [ + BrowserAnimationsModule, + ComponentsModule, + DataTableModule, + HttpClientTestingModule, + PipesModule, + RouterTestingModule, + NgbNavModule, + ToastrModule.forRoot(), + ModalModule, + PlaceholderModule, + CoreModule + ], + providers: [ + { provide: AuthStorageService, useValue: fakeAuthStorageService }, + TaskListService, + ModalService, + PlaceholderService, + BaseModalService + ], + schemas: [NO_ERRORS_SCHEMA] + }); beforeEach(() => { fixture = TestBed.createComponent(RbdSnapshotListComponent); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-auth-modal/cephfs-auth-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-auth-modal/cephfs-auth-modal.component.html index c501a15f9b1fb..5e59faf6bdafb 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-auth-modal/cephfs-auth-modal.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-auth-modal/cephfs-auth-modal.component.html @@ -90,7 +90,6 @@ formControlName="directory" [skeleton]="directoryStore.isLoading" [invalid]="!form.controls['directory'].valid && (form.controls['directory'].dirty)" - [disabled]="directoryStore.isLoading" [ngbTypeahead]="search"> diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-auth-modal/cephfs-auth-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-auth-modal/cephfs-auth-modal.component.ts index 435cdb9644fdf..e626ec6f210d7 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-auth-modal/cephfs-auth-modal.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-auth-modal/cephfs-auth-modal.component.ts @@ -83,6 +83,11 @@ export class CephfsAuthModalComponent extends CdForm implements OnInit, AfterVie this.directoryStore.loadDirectories(this.id, '/', 3); this.createForm(); this.loadingReady(); + if (this.directoryStore?.isLoading) { + this.form.get('directory').disable(); + } else { + this.form.get('directory').disable(); + } } createForm() { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.spec.ts index 070f8ef98e822..9537d7284df18 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.spec.ts @@ -1,6 +1,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { NgChartsModule } from 'ng2-charts'; +import { BaseChartDirective } from 'ng2-charts'; import { configureTestBed } from '~/testing/unit-test-helper'; import { CephfsChartComponent } from './cephfs-chart.component'; @@ -18,7 +18,7 @@ describe('CephfsChartComponent', () => { ]; configureTestBed({ - imports: [NgChartsModule], + imports: [BaseChartDirective], declarations: [CephfsChartComponent] }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.ts index 7a161f076842b..5c728d8cda259 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-chart/cephfs-chart.component.ts @@ -3,6 +3,7 @@ import { Component, ElementRef, Input, OnChanges, OnInit, ViewChild } from '@ang import _ from 'lodash'; import moment from 'moment'; import 'chartjs-adapter-moment'; +import { Chart, registerables } from 'chart.js'; import { ChartTooltip } from '~/app/shared/models/chart-tooltip'; @@ -102,6 +103,10 @@ export class CephfsChartComponent implements OnChanges, OnInit { chartType: 'line' }; + constructor() { + Chart.register(...registerables); + } + ngOnInit() { if (_.isUndefined(this.mdsCounter)) { return; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-directories/cephfs-directories.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-directories/cephfs-directories.component.spec.ts index bdc54f783f000..08751aee17dbb 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-directories/cephfs-directories.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-directories/cephfs-directories.component.spec.ts @@ -12,7 +12,6 @@ import _ from 'lodash'; import { CephfsService } from '~/app/shared/api/cephfs.service'; import { ConfirmationModalComponent } from '~/app/shared/components/confirmation-modal/confirmation-modal.component'; -import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component'; import { FormModalComponent } from '~/app/shared/components/form-modal/form-modal.component'; import { NotificationType } from '~/app/shared/enum/notification-type.enum'; import { CdValidators } from '~/app/shared/forms/cd-validators'; @@ -388,21 +387,18 @@ describe('CephfsDirectoriesComponent', () => { } }; - configureTestBed( - { - imports: [ - HttpClientTestingModule, - SharedModule, - RouterTestingModule, - TreeviewModule, - ToastrModule.forRoot(), - NgbModalModule - ], - declarations: [CephfsDirectoriesComponent], - providers: [NgbActiveModal] - }, - [CriticalConfirmationModalComponent, FormModalComponent, ConfirmationModalComponent] - ); + configureTestBed({ + imports: [ + HttpClientTestingModule, + SharedModule, + RouterTestingModule, + TreeviewModule, + ToastrModule.forRoot(), + NgbModalModule + ], + declarations: [CephfsDirectoriesComponent], + providers: [NgbActiveModal] + }); beforeEach(() => { noAsyncUpdate = false; @@ -674,7 +670,6 @@ describe('CephfsDirectoriesComponent', () => { mockLib.selectNode('/a/c'); mockLib.selectNode('/a/c/a'); component.selectOrigin('/a'); - console.debug('component.selectedDir', component.selectedDir); expect(component.selectedDir.path).toBe('/a'); }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.ts index c711babdd6f4e..b61b9574a1b5d 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.ts @@ -68,26 +68,7 @@ export class CephfsSnapshotscheduleListComponent errorMessage: string = ''; selectedName: string = ''; icons = Icons; - tableActions: CdTableAction[] = [ - { - name: this.actionLabels.CREATE, - permission: 'create', - icon: Icons.add, - click: () => this.openModal(false) - }, - { - name: this.actionLabels.EDIT, - permission: 'update', - icon: Icons.edit, - click: () => this.openModal(true) - }, - { - name: this.actionLabels.DELETE, - permission: 'delete', - icon: Icons.trash, - click: () => this.deleteSnapshotSchedule() - } - ]; + tableActions!: CdTableAction[]; MODULE_NAME = 'snap_schedule'; ENABLE_MODULE_TIMER = 2 * 1000; @@ -112,6 +93,27 @@ export class CephfsSnapshotscheduleListComponent } ngOnInit(): void { + this.tableActions = [ + { + name: this.actionLabels.CREATE, + permission: 'create', + icon: Icons.add, + click: () => this.openModal(false) + }, + { + name: this.actionLabels.EDIT, + permission: 'update', + icon: Icons.edit, + click: () => this.openModal(true) + }, + { + name: this.actionLabels.DELETE, + permission: 'delete', + icon: Icons.trash, + click: () => this.deleteSnapshotSchedule() + } + ]; + this.moduleServiceListSub = this.mgrModuleService .list() .pipe( diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs.module.ts index 99b239eb2a467..55f957c59c6c1 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs.module.ts @@ -9,7 +9,7 @@ import { NgbTooltipModule, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap'; -import { NgChartsModule } from 'ng2-charts'; +import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts'; import { AppRoutingModule } from '~/app/app-routing.module'; import { SharedModule } from '~/app/shared/shared.module'; @@ -59,7 +59,6 @@ import Trash from '@carbon/icons/es/trash-can/32'; CommonModule, SharedModule, AppRoutingModule, - NgChartsModule, TreeviewModule, NgbNavModule, FormsModule, @@ -83,7 +82,8 @@ import Trash from '@carbon/icons/es/trash-can/32'; NumberModule, LayoutModule, ComboBoxModule, - IconModule + IconModule, + BaseChartDirective ], declarations: [ CephfsDetailComponent, @@ -104,7 +104,8 @@ import Trash from '@carbon/icons/es/trash-can/32'; CephfsSubvolumeSnapshotsFormComponent, CephfsMountDetailsComponent, CephfsAuthModalComponent - ] + ], + providers: [provideCharts(withDefaultRegisterables())] }) export class CephfsModule { constructor(private iconService: IconService) { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.html index 4e30931c1b09e..2051e61568c45 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.html @@ -45,7 +45,7 @@
-

Add Hosts

@@ -56,7 +56,7 @@ [showGeneralActionsOnly]="true" [showExpandClusterBtn]="false">
-

Create OSDs

@@ -68,7 +68,7 @@ (emitMode)="setDeploymentMode($event)">
-

Create Services

@@ -77,7 +77,7 @@ [hiddenColumns]="['status.running', 'status.size', 'status.last_refresh']" [routedModal]="false">
-
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.spec.ts index b847517790981..4301c23d8e443 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.spec.ts @@ -10,7 +10,6 @@ import { CoreModule } from '~/app/core/core.module'; import { HostService } from '~/app/shared/api/host.service'; import { OsdService } from '~/app/shared/api/osd.service'; import { ConfirmationModalComponent } from '~/app/shared/components/confirmation-modal/confirmation-modal.component'; -import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component'; import { AppConstants } from '~/app/shared/constants/app.constants'; import { ModalService } from '~/app/shared/services/modal.service'; import { WizardStepsService } from '~/app/shared/services/wizard-steps.service'; @@ -27,19 +26,16 @@ describe('CreateClusterComponent', () => { let modalServiceShowSpy: jasmine.Spy; const projectConstants: typeof AppConstants = AppConstants; - configureTestBed( - { - imports: [ - HttpClientTestingModule, - RouterTestingModule, - ToastrModule.forRoot(), - SharedModule, - CoreModule, - CephModule - ] - }, - [LoadingPanelComponent] - ); + configureTestBed({ + imports: [ + HttpClientTestingModule, + RouterTestingModule, + ToastrModule.forRoot(), + SharedModule, + CoreModule, + CephModule + ] + }); beforeEach(() => { fixture = TestBed.createComponent(CreateClusterComponent); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.ts index fc0ce5823aab3..892bd3fe49f7c 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/create-cluster/create-cluster.component.ts @@ -1,4 +1,6 @@ import { + AfterViewInit, + ChangeDetectorRef, Component, EventEmitter, OnDestroy, @@ -39,7 +41,7 @@ import { Step } from 'carbon-components-angular'; templateUrl: './create-cluster.component.html', styleUrls: ['./create-cluster.component.scss'] }) -export class CreateClusterComponent implements OnInit, OnDestroy { +export class CreateClusterComponent implements OnInit, OnDestroy, AfterViewInit { @ViewChild('skipConfirmTpl', { static: true }) skipConfirmTpl: TemplateRef; currentStep: WizardStepModel; @@ -88,7 +90,8 @@ export class CreateClusterComponent implements OnInit, OnDestroy { private taskWrapper: TaskWrapperService, private osdService: OsdService, private route: ActivatedRoute, - private location: Location + private location: Location, + private changeDetectorRef: ChangeDetectorRef ) { this.permissions = this.authStorageService.getPermissions(); this.currentStepSub = this.wizardStepsService @@ -98,6 +101,9 @@ export class CreateClusterComponent implements OnInit, OnDestroy { }); this.currentStep.stepIndex = 0; } + ngAfterViewInit(): void { + this.changeDetectorRef.detectChanges(); + } ngOnInit(): void { this.stepTitles.forEach((steps, index) => { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-form/host-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-form/host-form.component.spec.ts index 8097bb260182b..97194e74fd412 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-form/host-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/host-form/host-form.component.spec.ts @@ -6,7 +6,6 @@ import { RouterTestingModule } from '@angular/router/testing'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { ToastrModule } from 'ngx-toastr'; -import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component'; import { SharedModule } from '~/app/shared/shared.module'; import { configureTestBed, FormHelper } from '~/testing/unit-test-helper'; import { HostFormComponent } from './host-form.component'; @@ -17,22 +16,19 @@ describe('HostFormComponent', () => { let fixture: ComponentFixture; let formHelper: FormHelper; - configureTestBed( - { - imports: [ - SharedModule, - HttpClientTestingModule, - RouterTestingModule, - ReactiveFormsModule, - ToastrModule.forRoot(), - InputModule, - ModalModule - ], - declarations: [HostFormComponent], - providers: [NgbActiveModal] - }, - [LoadingPanelComponent] - ); + configureTestBed({ + imports: [ + SharedModule, + HttpClientTestingModule, + RouterTestingModule, + ReactiveFormsModule, + ToastrModule.forRoot(), + InputModule, + ModalModule + ], + declarations: [HostFormComponent], + providers: [NgbActiveModal] + }); beforeEach(() => { fixture = TestBed.createComponent(HostFormComponent); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html index 8a92776b8be13..e474fb854cde5 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/hosts/hosts.component.html @@ -18,8 +18,7 @@ [maxLimit]="25" (setExpandedRow)="setExpandedRow($event)" (updateSelection)="updateSelection($event)" - [toolHeader]="!hideToolHeader" - [showMenu]="showMenu"> + [toolHeader]="!hideToolHeader">
{ let component: MgrModuleFormComponent; let fixture: ComponentFixture; - configureTestBed( - { - declarations: [MgrModuleFormComponent], - imports: [ - HttpClientTestingModule, - ReactiveFormsModule, - RouterTestingModule, - SharedModule, - ToastrModule.forRoot() - ] - }, - [LoadingPanelComponent] - ); + configureTestBed({ + declarations: [MgrModuleFormComponent], + imports: [ + HttpClientTestingModule, + ReactiveFormsModule, + RouterTestingModule, + SharedModule, + ToastrModule.forRoot() + ] + }); beforeEach(() => { fixture = TestBed.createComponent(MgrModuleFormComponent); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.spec.ts index b4d8a86526dc5..acff1a473d28a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/prometheus/silence-form/silence-form.component.spec.ts @@ -86,7 +86,7 @@ describe('SilenceFormComponent', () => { }); const changeAction = (action: string) => { - const modes = { + const modes: Record = { add: '/monitoring/silences/add', alertAdd: '/monitoring/silences/add/alert0', recreate: '/monitoring/silences/recreate/someExpiredId', @@ -180,7 +180,7 @@ describe('SilenceFormComponent', () => { let navigateSpy: jasmine.Spy; const expectError = (action: string, redirected: boolean) => { - Object.defineProperty(router, 'url', { value: action }); + Object.defineProperty(router, 'url', { value: action, configurable: true }); if (redirected) { expect(() => callInit()).toThrowError(DashboardNotFoundError); } else { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/telemetry/telemetry.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/telemetry/telemetry.component.spec.ts index e2d93c4b4526d..576a6f0e64f0c 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/telemetry/telemetry.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/telemetry/telemetry.component.spec.ts @@ -9,8 +9,6 @@ import { ToastrModule } from 'ngx-toastr'; import { of as observableOf } from 'rxjs'; import { MgrModuleService } from '~/app/shared/api/mgr-module.service'; -import { DownloadButtonComponent } from '~/app/shared/components/download-button/download-button.component'; -import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component'; import { SharedModule } from '~/app/shared/shared.module'; import { configureTestBed } from '~/testing/unit-test-helper'; import { TelemetryComponent } from './telemetry.component'; @@ -46,19 +44,16 @@ describe('TelemetryComponent', () => { 'url' ]; - configureTestBed( - { - declarations: [TelemetryComponent], - imports: [ - HttpClientTestingModule, - ReactiveFormsModule, - RouterTestingModule, - SharedModule, - ToastrModule.forRoot() - ] - }, - [LoadingPanelComponent, DownloadButtonComponent] - ); + configureTestBed({ + declarations: [TelemetryComponent], + imports: [ + HttpClientTestingModule, + ReactiveFormsModule, + RouterTestingModule, + SharedModule, + ToastrModule.forRoot() + ] + }); describe('configForm', () => { beforeEach(() => { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-area-chart/dashboard-area-chart.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-area-chart/dashboard-area-chart.component.ts index 8f61791f225e4..7f5cd05f9071c 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-area-chart/dashboard-area-chart.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-area-chart/dashboard-area-chart.component.ts @@ -1,4 +1,11 @@ -import { Component, Input, ViewChild, OnChanges, SimpleChanges } from '@angular/core'; +import { + Component, + Input, + ViewChild, + OnChanges, + SimpleChanges, + AfterViewInit +} from '@angular/core'; import { CssHelper } from '~/app/shared/classes/css-helper'; import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe'; @@ -14,7 +21,7 @@ import 'chartjs-adapter-moment'; templateUrl: './dashboard-area-chart.component.html', styleUrls: ['./dashboard-area-chart.component.scss'] }) -export class DashboardAreaChartComponent implements OnChanges { +export class DashboardAreaChartComponent implements OnChanges, AfterViewInit { @ViewChild(BaseChartDirective) chart: BaseChartDirective; @Input() @@ -44,32 +51,7 @@ export class DashboardAreaChartComponent implements OnChanges { options: any = {}; currentChartData: any = {}; - chartColors: any[] = [ - [ - this.cssHelper.propertyValue('chart-color-strong-blue'), - this.cssHelper.propertyValue('chart-color-translucent-blue') - ], - [ - this.cssHelper.propertyValue('chart-color-orange'), - this.cssHelper.propertyValue('chart-color-translucent-orange') - ], - [ - this.cssHelper.propertyValue('chart-color-green'), - this.cssHelper.propertyValue('chart-color-translucent-green') - ], - [ - this.cssHelper.propertyValue('chart-color-cyan'), - this.cssHelper.propertyValue('chart-color-translucent-cyan') - ], - [ - this.cssHelper.propertyValue('chart-color-purple'), - this.cssHelper.propertyValue('chart-color-translucent-purple') - ], - [ - this.cssHelper.propertyValue('chart-color-red'), - this.cssHelper.propertyValue('chart-color-translucent-red') - ] - ]; + chartColors!: any[]; public chartAreaBorderPlugin: any[] = [ { @@ -100,6 +82,33 @@ export class DashboardAreaChartComponent implements OnChanges { private formatter: FormatterService, private numberFormatter: NumberFormatterService ) { + this.chartColors = [ + [ + this.cssHelper.propertyValue('chart-color-strong-blue'), + this.cssHelper.propertyValue('chart-color-translucent-blue') + ], + [ + this.cssHelper.propertyValue('chart-color-orange'), + this.cssHelper.propertyValue('chart-color-translucent-orange') + ], + [ + this.cssHelper.propertyValue('chart-color-green'), + this.cssHelper.propertyValue('chart-color-translucent-green') + ], + [ + this.cssHelper.propertyValue('chart-color-cyan'), + this.cssHelper.propertyValue('chart-color-translucent-cyan') + ], + [ + this.cssHelper.propertyValue('chart-color-purple'), + this.cssHelper.propertyValue('chart-color-translucent-purple') + ], + [ + this.cssHelper.propertyValue('chart-color-red'), + this.cssHelper.propertyValue('chart-color-translucent-red') + ] + ]; + this.options = { plugins: { legend: { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-v3.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-v3.module.ts index 82843289b3834..d437855b8fd87 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-v3.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard-v3/dashboard-v3.module.ts @@ -4,7 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { RouterModule } from '@angular/router'; import { NgbNavModule, NgbPopoverModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; -import { NgChartsModule } from 'ng2-charts'; +import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts'; import { SimplebarAngularModule } from 'simplebar-angular'; import { SharedModule } from '~/app/shared/shared.module'; @@ -21,15 +21,14 @@ import { PgSummaryPipe } from './pg-summary.pipe'; CommonModule, NgbNavModule, SharedModule, - NgChartsModule, RouterModule, NgbPopoverModule, NgbTooltipModule, FormsModule, ReactiveFormsModule, - SimplebarAngularModule + SimplebarAngularModule, + BaseChartDirective ], - declarations: [ DashboardV3Component, DashboardPieComponent, @@ -37,12 +36,12 @@ import { PgSummaryPipe } from './pg-summary.pipe'; DashboardAreaChartComponent, DashboardTimeSelectorComponent ], - exports: [ DashboardV3Component, DashboardAreaChartComponent, DashboardTimeSelectorComponent, DashboardPieComponent - ] + ], + providers: [provideCharts(withDefaultRegisterables())] }) export class DashboardV3Module {} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts index c779feb3156ff..e610134396674 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/dashboard.module.ts @@ -4,7 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { RouterModule } from '@angular/router'; import { NgbNavModule, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'; -import { NgChartsModule } from 'ng2-charts'; +import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts'; import { SharedModule } from '~/app/shared/shared.module'; import { DashboardV3Module } from '../dashboard-v3/dashboard-v3.module'; @@ -15,10 +15,10 @@ import { HealthPieComponent } from './health-pie/health-pie.component'; import { HealthComponent } from './health/health.component'; import { InfoCardComponent } from './info-card/info-card.component'; import { InfoGroupComponent } from './info-group/info-group.component'; -import { MdsSummaryPipe } from './mds-summary.pipe'; -import { MgrSummaryPipe } from './mgr-summary.pipe'; +import { MdsDashboardSummaryPipe } from './mds-dashboard-summary.pipe'; +import { MgrDashboardSummaryPipe } from './mgr-dashboard-summary.pipe'; import { MonSummaryPipe } from './mon-summary.pipe'; -import { OsdSummaryPipe } from './osd-summary.pipe'; +import { osdDashboardSummaryPipe } from './osd-dashboard-summary.pipe'; @NgModule({ imports: [ @@ -26,25 +26,25 @@ import { OsdSummaryPipe } from './osd-summary.pipe'; CommonModule, NgbNavModule, SharedModule, - NgChartsModule, RouterModule, NgbPopoverModule, FormsModule, ReactiveFormsModule, - DashboardV3Module + DashboardV3Module, + BaseChartDirective ], - declarations: [ HealthComponent, DashboardComponent, MonSummaryPipe, - OsdSummaryPipe, - MgrSummaryPipe, - MdsSummaryPipe, + osdDashboardSummaryPipe, + MgrDashboardSummaryPipe, + MdsDashboardSummaryPipe, HealthPieComponent, InfoCardComponent, InfoGroupComponent, FeedbackComponent - ] + ], + providers: [provideCharts(withDefaultRegisterables())] }) export class DashboardModule {} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.html index 9e68fc22ca0ad..d115951458329 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.html @@ -2,36 +2,36 @@ class="container-fluid"> + *ngIf="healthData?.health?.status + || healthData?.mon_status + || healthData?.osd_map + || healthData?.mgr_map + || healthData?.hosts != null + || healthData?.rgw != null + || healthData?.fs_map + || healthData?.iscsi_daemons != null"> - + *ngIf="healthData?.health?.status"> +
- {{ healthData.health.status | healthLabel | uppercase }} -
- -
- {{ healthData.health.status | healthLabel | uppercase }} + +
+ {{ healthData?.health.status | healthLabel | uppercase }}
@@ -41,8 +41,8 @@ link="/hosts" class="cd-status-card" contentClass="content-highlight" - *ngIf="healthData.hosts != null"> - {{ healthData.hosts }} total + *ngIf="healthData?.hosts != null"> + {{ healthData?.hosts }} total - {{ healthData.mon_status | monSummary }} + *ngIf="healthData?.mon_status"> + {{ healthData?.mon_status | monSummary }} @@ -70,8 +70,8 @@ i18n-cardTitle class="cd-status-card" contentClass="content-highlight" - *ngIf="healthData.mgr_map"> - + {{ result.content }} @@ -83,14 +83,14 @@ link="/rgw/daemon" class="cd-status-card" contentClass="content-highlight" - *ngIf="enabledFeature.rgw && healthData?.rgw != null"> - {{ healthData.rgw }} total + *ngIf="enabledFeature?.rgw && healthData?.rgw != null"> + {{ healthData?.rgw }} total - {{ healthData.iscsi_daemons.up + healthData.iscsi_daemons.down }} total + *ngIf="enabledFeature?.iscsi && healthData?.iscsi_daemons != null"> + {{ healthData?.iscsi_daemons.up + healthData?.iscsi_daemons.down }} total - {{ healthData.iscsi_daemons.up }} up, - {{ healthData.iscsi_daemons.down }} + {{ healthData?.iscsi_daemons.up }} up, + {{ healthData?.iscsi_daemons.down }} down + *ngIf="healthData?.pools + || healthData?.df + || healthData?.pg_info"> + *ngIf="healthData?.df"> + *ngIf="healthData?.pg_info?.object_stats?.num_objects != null"> @@ -145,11 +145,11 @@ i18n-cardTitle class="cd-capacity-card cd-chart-card" contentClass="content-chart" - *ngIf="healthData.pg_info"> + *ngIf="healthData?.pg_info">
    -
  • +
  • {{ pgStatesText.key }}: {{ pgStatesText.value }}
@@ -169,27 +169,27 @@ link="/pool" class="cd-capacity-card" contentClass="content-highlight" - *ngIf="healthData.pools"> - {{ healthData.pools.length }} + *ngIf="healthData?.pools"> + {{ healthData?.pools.length }}
- {{ healthData.pg_info.pgs_per_osd | dimless }} + *ngIf="healthData?.pg_info"> + {{ healthData?.pg_info.pgs_per_osd | dimless }}
+ *ngIf="healthData?.client_perf || healthData?.scrub_status"> + *ngIf="healthData?.client_perf"> @@ -200,7 +200,7 @@ i18n-cardTitle class="cd-performance-card cd-chart-card" contentClass="content-chart" - *ngIf="healthData.client_perf"> + *ngIf="healthData?.client_perf"> @@ -211,21 +211,21 @@ i18n-cardTitle class="cd-performance-card" contentClass="content-highlight" - *ngIf="healthData.client_perf"> - {{ (healthData.client_perf.recovering_bytes_per_sec | dimlessBinary) + '/s' }} + *ngIf="healthData?.client_perf"> + {{ (healthData?.client_perf.recovering_bytes_per_sec | dimlessBinary) + '/s' }} - {{ healthData.scrub_status }} + *ngIf="healthData?.scrub_status"> + {{ healthData?.scrub_status }} - + diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.spec.ts index 3e25e92287837..4b8a4167ad2fb 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/health/health.component.spec.ts @@ -16,10 +16,10 @@ import { RefreshIntervalService } from '~/app/shared/services/refresh-interval.s import { SharedModule } from '~/app/shared/shared.module'; import { configureTestBed } from '~/testing/unit-test-helper'; import { HealthPieComponent } from '../health-pie/health-pie.component'; -import { MdsSummaryPipe } from '../mds-summary.pipe'; -import { MgrSummaryPipe } from '../mgr-summary.pipe'; +import { MdsDashboardSummaryPipe } from '../mds-dashboard-summary.pipe'; +import { MgrDashboardSummaryPipe } from '../mgr-dashboard-summary.pipe'; import { MonSummaryPipe } from '../mon-summary.pipe'; -import { OsdSummaryPipe } from '../osd-summary.pipe'; +import { osdDashboardSummaryPipe } from '../osd-dashboard-summary.pipe'; import { HealthComponent } from './health.component'; describe('HealthComponent', () => { @@ -54,9 +54,9 @@ describe('HealthComponent', () => { HealthComponent, HealthPieComponent, MonSummaryPipe, - OsdSummaryPipe, - MdsSummaryPipe, - MgrSummaryPipe + osdDashboardSummaryPipe, + MdsDashboardSummaryPipe, + MgrDashboardSummaryPipe ], schemas: [NO_ERRORS_SCHEMA], providers: [ diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-dashboard-summary.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-dashboard-summary.pipe.spec.ts new file mode 100644 index 0000000000000..c091a35544b86 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-dashboard-summary.pipe.spec.ts @@ -0,0 +1,72 @@ +import { TestBed } from '@angular/core/testing'; + +import { configureTestBed } from '~/testing/unit-test-helper'; +import { MdsDashboardSummaryPipe } from './mds-dashboard-summary.pipe'; + +describe('MdsDashboardSummaryPipe', () => { + let pipe: MdsDashboardSummaryPipe; + + configureTestBed({ + providers: [MdsDashboardSummaryPipe] + }); + + beforeEach(() => { + pipe = TestBed.inject(MdsDashboardSummaryPipe); + }); + + it('create an instance', () => { + expect(pipe).toBeTruthy(); + }); + + it('transforms with 0 active and 2 standy', () => { + const payload = { + standbys: [{ name: 'a' }], + filesystems: [{ mdsmap: { info: [{ state: 'up:standby-replay' }] } }] + }; + const expected = [ + { class: 'popover-info', content: '0 active', titleText: '1 standbyReplay' }, + { class: 'card-text-line-break', content: '', titleText: '' }, + { class: 'popover-info', content: '2 standby', titleText: 'standby daemons: a' } + ]; + + expect(pipe.transform(payload)).toEqual(expected); + }); + + it('transforms with 1 active and 1 standy', () => { + const payload = { + standbys: [{ name: 'b' }], + filesystems: [{ mdsmap: { info: [{ state: 'up:active', name: 'a' }] } }] + }; + const expected = [ + { class: 'popover-info', content: '1 active', titleText: 'active daemon: a' }, + { class: 'card-text-line-break', content: '', titleText: '' }, + { class: 'popover-info', content: '1 standby', titleText: 'standby daemons: b' } + ]; + expect(pipe.transform(payload)).toEqual(expected); + }); + + it('transforms with 0 filesystems', () => { + const payload: Record = { + standbys: [0], + filesystems: [] + }; + const expected = [{ class: 'popover-info', content: 'no filesystems', titleText: '' }]; + + expect(pipe.transform(payload)).toEqual(expected); + }); + + it('transforms without filesystem', () => { + const payload = { standbys: [{ name: 'a' }] }; + const expected = [ + { class: 'popover-info', content: '1 up', titleText: '' }, + { class: 'card-text-line-break', content: '', titleText: '' }, + { class: 'popover-info', content: 'no filesystems', titleText: 'standby daemons: a' } + ]; + + expect(pipe.transform(payload)).toEqual(expected); + }); + + it('transforms without value', () => { + expect(pipe.transform(undefined)).toBe(''); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-dashboard-summary.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-dashboard-summary.pipe.ts new file mode 100644 index 0000000000000..2b4a899eebd0b --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-dashboard-summary.pipe.ts @@ -0,0 +1,78 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +import _ from 'lodash'; + +@Pipe({ + name: 'mdsDashboardSummary' +}) +export class MdsDashboardSummaryPipe implements PipeTransform { + transform(value: any): any { + if (!value) { + return ''; + } + + let contentLine1 = ''; + let contentLine2 = ''; + let standbys = 0; + let active = 0; + let standbyReplay = 0; + _.each(value.standbys, () => { + standbys += 1; + }); + + if (value.standbys && !value.filesystems) { + contentLine1 = `${standbys} ${$localize`up`}`; + contentLine2 = $localize`no filesystems`; + } else if (value.filesystems.length === 0) { + contentLine1 = $localize`no filesystems`; + } else { + _.each(value.filesystems, (fs) => { + _.each(fs.mdsmap.info, (mds) => { + if (mds.state === 'up:standby-replay') { + standbyReplay += 1; + } else { + active += 1; + } + }); + }); + + contentLine1 = `${active} ${$localize`active`}`; + contentLine2 = `${standbys + standbyReplay} ${$localize`standby`}`; + } + const standbyHoverText = value.standbys.map((s: any): string => s.name).join(', '); + const standbyTitleText = !standbyHoverText + ? '' + : `${$localize`standby daemons`}: ${standbyHoverText}`; + const fsLength = value.filesystems ? value.filesystems.length : 0; + const infoObject = fsLength > 0 ? value.filesystems[0].mdsmap.info : {}; + const activeHoverText = Object.values(infoObject) + .map((info: any): string => info.name) + .join(', '); + let activeTitleText = !activeHoverText ? '' : `${$localize`active daemon`}: ${activeHoverText}`; + // There is always one standbyreplay to replace active daemon, if active one is down + if (!active && fsLength > 0) { + activeTitleText = `${standbyReplay} ${$localize`standbyReplay`}`; + } + const mgrSummary = [ + { + content: contentLine1, + class: 'popover-info', + titleText: activeTitleText + } + ]; + if (contentLine2) { + mgrSummary.push({ + content: '', + class: 'card-text-line-break', + titleText: '' + }); + mgrSummary.push({ + content: contentLine2, + class: 'popover-info', + titleText: standbyTitleText + }); + } + + return mgrSummary; + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.spec.ts deleted file mode 100644 index c62b35c548e59..0000000000000 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.spec.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { configureTestBed } from '~/testing/unit-test-helper'; -import { MdsSummaryPipe } from './mds-summary.pipe'; - -describe('MdsSummaryPipe', () => { - let pipe: MdsSummaryPipe; - - configureTestBed({ - providers: [MdsSummaryPipe] - }); - - beforeEach(() => { - pipe = TestBed.inject(MdsSummaryPipe); - }); - - it('create an instance', () => { - expect(pipe).toBeTruthy(); - }); - - it('transforms with 0 active and 2 standy', () => { - const payload = { - standbys: [{ name: 'a' }], - filesystems: [{ mdsmap: { info: [{ state: 'up:standby-replay' }] } }] - }; - const expected = [ - { class: 'popover-info', content: '0 active', titleText: '1 standbyReplay' }, - { class: 'card-text-line-break', content: '', titleText: '' }, - { class: 'popover-info', content: '2 standby', titleText: 'standby daemons: a' } - ]; - - expect(pipe.transform(payload)).toEqual(expected); - }); - - it('transforms with 1 active and 1 standy', () => { - const payload = { - standbys: [{ name: 'b' }], - filesystems: [{ mdsmap: { info: [{ state: 'up:active', name: 'a' }] } }] - }; - const expected = [ - { class: 'popover-info', content: '1 active', titleText: 'active daemon: a' }, - { class: 'card-text-line-break', content: '', titleText: '' }, - { class: 'popover-info', content: '1 standby', titleText: 'standby daemons: b' } - ]; - expect(pipe.transform(payload)).toEqual(expected); - }); - - it('transforms with 0 filesystems', () => { - const payload: Record = { - standbys: [0], - filesystems: [] - }; - const expected = [{ class: 'popover-info', content: 'no filesystems', titleText: '' }]; - - expect(pipe.transform(payload)).toEqual(expected); - }); - - it('transforms without filesystem', () => { - const payload = { standbys: [{ name: 'a' }] }; - const expected = [ - { class: 'popover-info', content: '1 up', titleText: '' }, - { class: 'card-text-line-break', content: '', titleText: '' }, - { class: 'popover-info', content: 'no filesystems', titleText: 'standby daemons: a' } - ]; - - expect(pipe.transform(payload)).toEqual(expected); - }); - - it('transforms without value', () => { - expect(pipe.transform(undefined)).toBe(''); - }); -}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.ts deleted file mode 100644 index 9cc72ac96ad75..0000000000000 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mds-summary.pipe.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core'; - -import _ from 'lodash'; - -@Pipe({ - name: 'mdsSummary' -}) -export class MdsSummaryPipe implements PipeTransform { - transform(value: any): any { - if (!value) { - return ''; - } - - let contentLine1 = ''; - let contentLine2 = ''; - let standbys = 0; - let active = 0; - let standbyReplay = 0; - _.each(value.standbys, () => { - standbys += 1; - }); - - if (value.standbys && !value.filesystems) { - contentLine1 = `${standbys} ${$localize`up`}`; - contentLine2 = $localize`no filesystems`; - } else if (value.filesystems.length === 0) { - contentLine1 = $localize`no filesystems`; - } else { - _.each(value.filesystems, (fs) => { - _.each(fs.mdsmap.info, (mds) => { - if (mds.state === 'up:standby-replay') { - standbyReplay += 1; - } else { - active += 1; - } - }); - }); - - contentLine1 = `${active} ${$localize`active`}`; - contentLine2 = `${standbys + standbyReplay} ${$localize`standby`}`; - } - const standbyHoverText = value.standbys.map((s: any): string => s.name).join(', '); - const standbyTitleText = !standbyHoverText - ? '' - : `${$localize`standby daemons`}: ${standbyHoverText}`; - const fsLength = value.filesystems ? value.filesystems.length : 0; - const infoObject = fsLength > 0 ? value.filesystems[0].mdsmap.info : {}; - const activeHoverText = Object.values(infoObject) - .map((info: any): string => info.name) - .join(', '); - let activeTitleText = !activeHoverText ? '' : `${$localize`active daemon`}: ${activeHoverText}`; - // There is always one standbyreplay to replace active daemon, if active one is down - if (!active && fsLength > 0) { - activeTitleText = `${standbyReplay} ${$localize`standbyReplay`}`; - } - const mgrSummary = [ - { - content: contentLine1, - class: 'popover-info', - titleText: activeTitleText - } - ]; - if (contentLine2) { - mgrSummary.push({ - content: '', - class: 'card-text-line-break', - titleText: '' - }); - mgrSummary.push({ - content: contentLine2, - class: 'popover-info', - titleText: standbyTitleText - }); - } - - return mgrSummary; - } -} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-dashboard-summary.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-dashboard-summary.pipe.spec.ts new file mode 100644 index 0000000000000..3bd9242e3c301 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-dashboard-summary.pipe.spec.ts @@ -0,0 +1,52 @@ +import { TestBed } from '@angular/core/testing'; + +import { configureTestBed } from '~/testing/unit-test-helper'; +import { MgrDashboardSummaryPipe } from './mgr-dashboard-summary.pipe'; + +describe('MgrDashboardSummaryPipe', () => { + let pipe: MgrDashboardSummaryPipe; + + configureTestBed({ + providers: [MgrDashboardSummaryPipe] + }); + + beforeEach(() => { + pipe = TestBed.inject(MgrDashboardSummaryPipe); + }); + + it('create an instance', () => { + expect(pipe).toBeTruthy(); + }); + + it('transforms without value', () => { + expect(pipe.transform(undefined)).toBe(''); + }); + + it('transforms with active_name undefined', () => { + const payload: Record = { + active_name: undefined, + standbys: [] + }; + const expected = [ + { class: 'popover-info', content: 'n/a active', titleText: '' }, + { class: 'card-text-line-break', content: '', titleText: '' }, + { class: 'popover-info', content: '0 standby', titleText: '' } + ]; + + expect(pipe.transform(payload)).toEqual(expected); + }); + + it('transforms with 1 active and 2 standbys', () => { + const payload = { + active_name: 'x', + standbys: [{ name: 'y' }, { name: 'z' }] + }; + const expected = [ + { class: 'popover-info', content: '1 active', titleText: 'active daemon: x' }, + { class: 'card-text-line-break', content: '', titleText: '' }, + { class: 'popover-info', content: '2 standby', titleText: 'standby daemons: y, z' } + ]; + + expect(pipe.transform(payload)).toEqual(expected); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-dashboard-summary.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-dashboard-summary.pipe.ts new file mode 100644 index 0000000000000..b82e5d852fc26 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-dashboard-summary.pipe.ts @@ -0,0 +1,48 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +import _ from 'lodash'; + +@Pipe({ + name: 'mgrDashboardSummary' +}) +export class MgrDashboardSummaryPipe implements PipeTransform { + transform(value: any): any { + if (!value) { + return ''; + } + + let activeCount = $localize`n/a`; + const activeTitleText = _.isUndefined(value.active_name) + ? '' + : `${$localize`active daemon`}: ${value.active_name}`; + // There is always one standbyreplay to replace active daemon, if active one is down + if (activeTitleText.length > 0) { + activeCount = '1'; + } + const standbyHoverText = value.standbys.map((s: any): string => s.name).join(', '); + const standbyTitleText = !standbyHoverText + ? '' + : `${$localize`standby daemons`}: ${standbyHoverText}`; + const standbyCount = value.standbys.length; + const mgrSummary = [ + { + content: `${activeCount} ${$localize`active`}`, + class: 'popover-info', + titleText: activeTitleText + } + ]; + + mgrSummary.push({ + content: '', + class: 'card-text-line-break', + titleText: '' + }); + mgrSummary.push({ + content: `${standbyCount} ${$localize`standby`}`, + class: 'popover-info', + titleText: standbyTitleText + }); + + return mgrSummary; + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.spec.ts deleted file mode 100644 index 8bc2753808e5e..0000000000000 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { configureTestBed } from '~/testing/unit-test-helper'; -import { MgrSummaryPipe } from './mgr-summary.pipe'; - -describe('MgrSummaryPipe', () => { - let pipe: MgrSummaryPipe; - - configureTestBed({ - providers: [MgrSummaryPipe] - }); - - beforeEach(() => { - pipe = TestBed.inject(MgrSummaryPipe); - }); - - it('create an instance', () => { - expect(pipe).toBeTruthy(); - }); - - it('transforms without value', () => { - expect(pipe.transform(undefined)).toBe(''); - }); - - it('transforms with active_name undefined', () => { - const payload: Record = { - active_name: undefined, - standbys: [] - }; - const expected = [ - { class: 'popover-info', content: 'n/a active', titleText: '' }, - { class: 'card-text-line-break', content: '', titleText: '' }, - { class: 'popover-info', content: '0 standby', titleText: '' } - ]; - - expect(pipe.transform(payload)).toEqual(expected); - }); - - it('transforms with 1 active and 2 standbys', () => { - const payload = { - active_name: 'x', - standbys: [{ name: 'y' }, { name: 'z' }] - }; - const expected = [ - { class: 'popover-info', content: '1 active', titleText: 'active daemon: x' }, - { class: 'card-text-line-break', content: '', titleText: '' }, - { class: 'popover-info', content: '2 standby', titleText: 'standby daemons: y, z' } - ]; - - expect(pipe.transform(payload)).toEqual(expected); - }); -}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.ts deleted file mode 100644 index ffdee7300991d..0000000000000 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/mgr-summary.pipe.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core'; - -import _ from 'lodash'; - -@Pipe({ - name: 'mgrSummary' -}) -export class MgrSummaryPipe implements PipeTransform { - transform(value: any): any { - if (!value) { - return ''; - } - - let activeCount = $localize`n/a`; - const activeTitleText = _.isUndefined(value.active_name) - ? '' - : `${$localize`active daemon`}: ${value.active_name}`; - // There is always one standbyreplay to replace active daemon, if active one is down - if (activeTitleText.length > 0) { - activeCount = '1'; - } - const standbyHoverText = value.standbys.map((s: any): string => s.name).join(', '); - const standbyTitleText = !standbyHoverText - ? '' - : `${$localize`standby daemons`}: ${standbyHoverText}`; - const standbyCount = value.standbys.length; - const mgrSummary = [ - { - content: `${activeCount} ${$localize`active`}`, - class: 'popover-info', - titleText: activeTitleText - } - ]; - - mgrSummary.push({ - content: '', - class: 'card-text-line-break', - titleText: '' - }); - mgrSummary.push({ - content: `${standbyCount} ${$localize`standby`}`, - class: 'popover-info', - titleText: standbyTitleText - }); - - return mgrSummary; - } -} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-dashboard-summary.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-dashboard-summary.pipe.spec.ts new file mode 100644 index 0000000000000..f5af99b446860 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-dashboard-summary.pipe.spec.ts @@ -0,0 +1,193 @@ +import { TestBed } from '@angular/core/testing'; + +import { configureTestBed } from '~/testing/unit-test-helper'; +import { osdDashboardSummaryPipe } from './osd-dashboard-summary.pipe'; + +describe('osdDashboardSummaryPipe', () => { + let pipe: osdDashboardSummaryPipe; + + configureTestBed({ + providers: [osdDashboardSummaryPipe] + }); + + beforeEach(() => { + pipe = TestBed.inject(osdDashboardSummaryPipe); + }); + + it('create an instance', () => { + expect(pipe).toBeTruthy(); + }); + + it('transforms without value', () => { + expect(pipe.transform(undefined)).toBe(''); + }); + + it('transforms having 3 osd with 3 up, 3 in, 0 down, 0 out', () => { + const value = { + osds: [ + { up: 1, in: 1, state: ['up', 'exists'] }, + { up: 1, in: 1, state: ['up', 'exists'] }, + { up: 1, in: 1, state: ['up', 'exists'] } + ] + }; + expect(pipe.transform(value)).toEqual([ + { + content: '3 total', + class: '' + }, + { + content: '', + class: 'card-text-line-break' + }, + { + content: '3 up, 3 in', + class: '' + } + ]); + }); + + it('transforms having 3 osd with 2 up, 1 in, 1 down, 2 out', () => { + const value = { + osds: [ + { up: 1, in: 1, state: ['up', 'exists'] }, + { up: 1, in: 0, state: ['up', 'exists'] }, + { up: 0, in: 0, state: ['exists'] } + ] + }; + expect(pipe.transform(value)).toEqual([ + { + content: '3 total', + class: '' + }, + { + content: '', + class: 'card-text-line-break' + }, + { + content: '2 up, 1 in', + class: '' + }, + { + content: '', + class: 'card-text-line-break' + }, + { + content: '1 down, 2 out', + class: 'card-text-error' + } + ]); + }); + + it('transforms having 3 osd with 2 up, 3 in, 1 full, 1 nearfull, 1 down, 0 out', () => { + const value = { + osds: [ + { up: 1, in: 1, state: ['up', 'nearfull'] }, + { up: 1, in: 1, state: ['up', 'exists'] }, + { up: 0, in: 1, state: ['full'] } + ] + }; + expect(pipe.transform(value)).toEqual([ + { + content: '3 total', + class: '' + }, + { + content: '', + class: 'card-text-line-break' + }, + { + content: '2 up, 3 in', + class: '' + }, + { + content: '', + class: 'card-text-line-break' + }, + { + content: '1 down', + class: 'card-text-error' + }, + { + content: '', + class: 'card-text-line-break' + }, + { + content: '1 near full', + class: 'card-text-error' + }, + { + content: '', + class: 'card-text-line-break' + }, + { + content: '1 full', + class: 'card-text-error' + } + ]); + }); + + it('transforms having 3 osd with 3 up, 2 in, 0 down, 1 out', () => { + const value = { + osds: [ + { up: 1, in: 1, state: ['up', 'exists'] }, + { up: 1, in: 1, state: ['up', 'exists'] }, + { up: 1, in: 0, state: ['up', 'exists'] } + ] + }; + expect(pipe.transform(value)).toEqual([ + { + content: '3 total', + class: '' + }, + { + content: '', + class: 'card-text-line-break' + }, + { + content: '3 up, 2 in', + class: '' + }, + { + content: '', + class: 'card-text-line-break' + }, + { + content: '1 out', + class: 'card-text-error' + } + ]); + }); + + it('transforms having 4 osd with 3 up, 2 in, 1 down, another 2 out', () => { + const value = { + osds: [ + { up: 1, in: 1, state: ['up', 'exists'] }, + { up: 1, in: 0, state: ['up', 'exists'] }, + { up: 1, in: 0, state: ['up', 'exists'] }, + { up: 0, in: 1, state: ['exists'] } + ] + }; + expect(pipe.transform(value)).toEqual([ + { + content: '4 total', + class: '' + }, + { + content: '', + class: 'card-text-line-break' + }, + { + content: '3 up, 2 in', + class: '' + }, + { + content: '', + class: 'card-text-line-break' + }, + { + content: '1 down, 2 out', + class: 'card-text-error' + } + ]); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-dashboard-summary.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-dashboard-summary.pipe.ts new file mode 100644 index 0000000000000..a3e292f073e31 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-dashboard-summary.pipe.ts @@ -0,0 +1,91 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +import _ from 'lodash'; + +@Pipe({ + name: 'osdDashboardSummary' +}) +export class osdDashboardSummaryPipe implements PipeTransform { + transform(value: any): any { + if (!value) { + return ''; + } + + let inCount = 0; + let upCount = 0; + let nearFullCount = 0; + let fullCount = 0; + _.each(value.osds, (osd) => { + if (osd.in) { + inCount++; + } + if (osd.up) { + upCount++; + } + if (osd.state.includes('nearfull')) { + nearFullCount++; + } + if (osd.state.includes('full')) { + fullCount++; + } + }); + + const osdSummary = [ + { + content: `${value.osds.length} ${$localize`total`}`, + class: '' + } + ]; + osdSummary.push({ + content: '', + class: 'card-text-line-break' + }); + osdSummary.push({ + content: `${upCount} ${$localize`up`}, ${inCount} ${$localize`in`}`, + class: '' + }); + + const downCount = value.osds.length - upCount; + const outCount = value.osds.length - inCount; + if (downCount > 0 || outCount > 0) { + osdSummary.push({ + content: '', + class: 'card-text-line-break' + }); + + const downText = downCount > 0 ? `${downCount} ${$localize`down`}` : ''; + const separator = downCount > 0 && outCount > 0 ? ', ' : ''; + const outText = outCount > 0 ? `${outCount} ${$localize`out`}` : ''; + osdSummary.push({ + content: `${downText}${separator}${outText}`, + class: 'card-text-error' + }); + } + + if (nearFullCount > 0) { + osdSummary.push( + { + content: '', + class: 'card-text-line-break' + }, + { + content: `${nearFullCount} ${$localize`near full`}`, + class: 'card-text-error' + }, + { + content: '', + class: 'card-text-line-break' + } + ); + } + + if (fullCount > 0) { + osdSummary.push({ + content: `${fullCount} ${$localize`full`}`, + class: 'card-text-error' + }); + } + + return osdSummary; + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.spec.ts deleted file mode 100644 index 22f5eeff3853b..0000000000000 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.spec.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { configureTestBed } from '~/testing/unit-test-helper'; -import { OsdSummaryPipe } from './osd-summary.pipe'; - -describe('OsdSummaryPipe', () => { - let pipe: OsdSummaryPipe; - - configureTestBed({ - providers: [OsdSummaryPipe] - }); - - beforeEach(() => { - pipe = TestBed.inject(OsdSummaryPipe); - }); - - it('create an instance', () => { - expect(pipe).toBeTruthy(); - }); - - it('transforms without value', () => { - expect(pipe.transform(undefined)).toBe(''); - }); - - it('transforms having 3 osd with 3 up, 3 in, 0 down, 0 out', () => { - const value = { - osds: [ - { up: 1, in: 1, state: ['up', 'exists'] }, - { up: 1, in: 1, state: ['up', 'exists'] }, - { up: 1, in: 1, state: ['up', 'exists'] } - ] - }; - expect(pipe.transform(value)).toEqual([ - { - content: '3 total', - class: '' - }, - { - content: '', - class: 'card-text-line-break' - }, - { - content: '3 up, 3 in', - class: '' - } - ]); - }); - - it('transforms having 3 osd with 2 up, 1 in, 1 down, 2 out', () => { - const value = { - osds: [ - { up: 1, in: 1, state: ['up', 'exists'] }, - { up: 1, in: 0, state: ['up', 'exists'] }, - { up: 0, in: 0, state: ['exists'] } - ] - }; - expect(pipe.transform(value)).toEqual([ - { - content: '3 total', - class: '' - }, - { - content: '', - class: 'card-text-line-break' - }, - { - content: '2 up, 1 in', - class: '' - }, - { - content: '', - class: 'card-text-line-break' - }, - { - content: '1 down, 2 out', - class: 'card-text-error' - } - ]); - }); - - it('transforms having 3 osd with 2 up, 3 in, 1 full, 1 nearfull, 1 down, 0 out', () => { - const value = { - osds: [ - { up: 1, in: 1, state: ['up', 'nearfull'] }, - { up: 1, in: 1, state: ['up', 'exists'] }, - { up: 0, in: 1, state: ['full'] } - ] - }; - expect(pipe.transform(value)).toEqual([ - { - content: '3 total', - class: '' - }, - { - content: '', - class: 'card-text-line-break' - }, - { - content: '2 up, 3 in', - class: '' - }, - { - content: '', - class: 'card-text-line-break' - }, - { - content: '1 down', - class: 'card-text-error' - }, - { - content: '', - class: 'card-text-line-break' - }, - { - content: '1 near full', - class: 'card-text-error' - }, - { - content: '', - class: 'card-text-line-break' - }, - { - content: '1 full', - class: 'card-text-error' - } - ]); - }); - - it('transforms having 3 osd with 3 up, 2 in, 0 down, 1 out', () => { - const value = { - osds: [ - { up: 1, in: 1, state: ['up', 'exists'] }, - { up: 1, in: 1, state: ['up', 'exists'] }, - { up: 1, in: 0, state: ['up', 'exists'] } - ] - }; - expect(pipe.transform(value)).toEqual([ - { - content: '3 total', - class: '' - }, - { - content: '', - class: 'card-text-line-break' - }, - { - content: '3 up, 2 in', - class: '' - }, - { - content: '', - class: 'card-text-line-break' - }, - { - content: '1 out', - class: 'card-text-error' - } - ]); - }); - - it('transforms having 4 osd with 3 up, 2 in, 1 down, another 2 out', () => { - const value = { - osds: [ - { up: 1, in: 1, state: ['up', 'exists'] }, - { up: 1, in: 0, state: ['up', 'exists'] }, - { up: 1, in: 0, state: ['up', 'exists'] }, - { up: 0, in: 1, state: ['exists'] } - ] - }; - expect(pipe.transform(value)).toEqual([ - { - content: '4 total', - class: '' - }, - { - content: '', - class: 'card-text-line-break' - }, - { - content: '3 up, 2 in', - class: '' - }, - { - content: '', - class: 'card-text-line-break' - }, - { - content: '1 down, 2 out', - class: 'card-text-error' - } - ]); - }); -}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.ts deleted file mode 100644 index 46d2eda6bb79b..0000000000000 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/dashboard/osd-summary.pipe.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core'; - -import _ from 'lodash'; - -@Pipe({ - name: 'osdSummary' -}) -export class OsdSummaryPipe implements PipeTransform { - transform(value: any): any { - if (!value) { - return ''; - } - - let inCount = 0; - let upCount = 0; - let nearFullCount = 0; - let fullCount = 0; - _.each(value.osds, (osd) => { - if (osd.in) { - inCount++; - } - if (osd.up) { - upCount++; - } - if (osd.state.includes('nearfull')) { - nearFullCount++; - } - if (osd.state.includes('full')) { - fullCount++; - } - }); - - const osdSummary = [ - { - content: `${value.osds.length} ${$localize`total`}`, - class: '' - } - ]; - osdSummary.push({ - content: '', - class: 'card-text-line-break' - }); - osdSummary.push({ - content: `${upCount} ${$localize`up`}, ${inCount} ${$localize`in`}`, - class: '' - }); - - const downCount = value.osds.length - upCount; - const outCount = value.osds.length - inCount; - if (downCount > 0 || outCount > 0) { - osdSummary.push({ - content: '', - class: 'card-text-line-break' - }); - - const downText = downCount > 0 ? `${downCount} ${$localize`down`}` : ''; - const separator = downCount > 0 && outCount > 0 ? ', ' : ''; - const outText = outCount > 0 ? `${outCount} ${$localize`out`}` : ''; - osdSummary.push({ - content: `${downText}${separator}${outText}`, - class: 'card-text-error' - }); - } - - if (nearFullCount > 0) { - osdSummary.push( - { - content: '', - class: 'card-text-line-break' - }, - { - content: `${nearFullCount} ${$localize`near full`}`, - class: 'card-text-error' - }, - { - content: '', - class: 'card-text-line-break' - } - ); - } - - if (fullCount > 0) { - osdSummary.push({ - content: `${fullCount} ${$localize`full`}`, - class: 'card-text-error' - }); - } - - return osdSummary; - } -} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts index 1024f00adc5d8..7f5888f15c1c6 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts @@ -11,7 +11,6 @@ import { Observable, of } from 'rxjs'; import { NfsFormClientComponent } from '~/app/ceph/nfs/nfs-form-client/nfs-form-client.component'; import { NfsFormComponent } from '~/app/ceph/nfs/nfs-form/nfs-form.component'; import { Directory } from '~/app/shared/api/nfs.service'; -import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component'; import { SharedModule } from '~/app/shared/shared.module'; import { ActivatedRouteStub } from '~/testing/activated-route-stub'; import { configureTestBed, RgwHelper } from '~/testing/unit-test-helper'; @@ -23,26 +22,23 @@ describe('NfsFormComponent', () => { let activatedRoute: ActivatedRouteStub; let router: Router; - configureTestBed( - { - declarations: [NfsFormComponent, NfsFormClientComponent], - imports: [ - HttpClientTestingModule, - ReactiveFormsModule, - RouterTestingModule, - SharedModule, - ToastrModule.forRoot(), - NgbTypeaheadModule - ], - providers: [ - { - provide: ActivatedRoute, - useValue: new ActivatedRouteStub({ cluster_id: 'mynfs', export_id: '1' }) - } - ] - }, - [LoadingPanelComponent] - ); + configureTestBed({ + declarations: [NfsFormComponent, NfsFormClientComponent], + imports: [ + HttpClientTestingModule, + ReactiveFormsModule, + RouterTestingModule, + SharedModule, + ToastrModule.forRoot(), + NgbTypeaheadModule + ], + providers: [ + { + provide: ActivatedRoute, + useValue: new ActivatedRouteStub({ cluster_id: 'mynfs', export_id: '1' }) + } + ] + }); const matchSquash = (backendSquashValue: string, uiSquashValue: string) => { component.ngOnInit(); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/crush-rule-form-modal/crush-rule-form-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/crush-rule-form-modal/crush-rule-form-modal.component.ts index 308b09d721641..0afb2442735cf 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/crush-rule-form-modal/crush-rule-form-modal.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/crush-rule-form-modal/crush-rule-form-modal.component.ts @@ -23,7 +23,7 @@ export class CrushRuleFormModalComponent extends CrushNodeSelectionClass impleme @Output() submitAction = new EventEmitter(); - tooltips = this.crushRuleService.formTooltips; + tooltips!: Record; form: CdFormGroup; names: string[]; @@ -67,6 +67,8 @@ export class CrushRuleFormModalComponent extends CrushNodeSelectionClass impleme } ngOnInit() { + this.tooltips = this.crushRuleService.formTooltips; + this.crushRuleService .getInfo() .subscribe(({ names, nodes }: { names: string[]; nodes: CrushNode[] }) => { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form-modal.component.ts index 1521ae83f1b20..b78b5d483f520 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form-modal.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/erasure-code-profile-form/erasure-code-profile-form-modal.component.ts @@ -26,7 +26,7 @@ export class ErasureCodeProfileFormModalComponent @Output() submitAction = new EventEmitter(); - tooltips = this.ecpService.formTooltips; + tooltips!: Record; PLUGIN = { LRC: 'lrc', // Locally Repairable Erasure Code SHEC: 'shec', // Shingled Erasure Code @@ -365,6 +365,8 @@ export class ErasureCodeProfileFormModalComponent } ngOnInit() { + this.tooltips = this.ecpService.formTooltips; + this.ecpService .getInfo() .subscribe( diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts index caf8c0b6a71a6..d831c59ca2f20 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts @@ -135,28 +135,25 @@ describe('PoolFormComponent', () => { const routes: Routes = [{ path: '404', component: ErrorComponent }]; - configureTestBed( - { - declarations: [ErrorComponent], - imports: [ - BrowserAnimationsModule, - HttpClientTestingModule, - RouterTestingModule.withRoutes(routes), - ToastrModule.forRoot(), - NgbNavModule, - PoolModule, - SharedModule, - NgbModalModule - ], - providers: [ - ErasureCodeProfileService, - NgbActiveModal, - SelectBadgesComponent, - { provide: ActivatedRoute, useValue: { params: of({ name: 'somePoolName' }) } } - ] - }, - [CriticalConfirmationModalComponent] - ); + configureTestBed({ + declarations: [ErrorComponent], + imports: [ + BrowserAnimationsModule, + HttpClientTestingModule, + RouterTestingModule.withRoutes(routes), + ToastrModule.forRoot(), + NgbNavModule, + PoolModule, + SharedModule, + NgbModalModule + ], + providers: [ + ErasureCodeProfileService, + NgbActiveModal, + SelectBadgesComponent, + { provide: ActivatedRoute, useValue: { params: of({ name: 'somePoolName' }) } } + ] + }); let navigationSpy: jasmine.Spy; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/bucket-tag-modal/bucket-tag-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/bucket-tag-modal/bucket-tag-modal.component.spec.ts index a54e7eeee0825..d6104930e35e0 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/bucket-tag-modal/bucket-tag-modal.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/bucket-tag-modal/bucket-tag-modal.component.spec.ts @@ -4,6 +4,7 @@ import { BucketTagModalComponent } from './bucket-tag-modal.component'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ReactiveFormsModule } from '@angular/forms'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; describe('BucketTagModalComponent', () => { let component: BucketTagModalComponent; @@ -13,6 +14,7 @@ describe('BucketTagModalComponent', () => { await TestBed.configureTestingModule({ declarations: [BucketTagModalComponent], imports: [HttpClientTestingModule, ReactiveFormsModule], + schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA], providers: [NgbActiveModal] }).compileComponents(); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-realm-form/rgw-multisite-realm-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-realm-form/rgw-multisite-realm-form.component.html index 5ca36f4bd2fc4..c2c775d128241 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-realm-form/rgw-multisite-realm-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-realm-form/rgw-multisite-realm-form.component.html @@ -62,7 +62,6 @@ for="default_realm" formControlName="default_realm" name="default_realm" - [disabled]="action === actionLabels.EDIT" i18n >Default diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-realm-form/rgw-multisite-realm-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-realm-form/rgw-multisite-realm-form.component.ts index 1e18598b0dbb1..98ad92b98b8ab 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-realm-form/rgw-multisite-realm-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-realm-form/rgw-multisite-realm-form.component.ts @@ -93,6 +93,12 @@ export class RgwMultisiteRealmFormComponent extends BaseModal implements OnInit this.defaultRealmDisabled = true; } this.docUrl = this.docService.urlGenerator('rgw-multisite'); + + if (this.action === this.actionLabels?.EDIT) { + this.multisiteRealmForm.get('default_realm').disable(); + } else { + this.multisiteRealmForm.get('default_realm').enable(); + } } submit() { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-flow-modal/rgw-multisite-sync-flow-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-flow-modal/rgw-multisite-sync-flow-modal.component.spec.ts index 2efdbfb8c9db4..1aa21f437eaca 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-flow-modal/rgw-multisite-sync-flow-modal.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-flow-modal/rgw-multisite-sync-flow-modal.component.spec.ts @@ -8,6 +8,7 @@ import { ReactiveFormsModule } from '@angular/forms'; import { CommonModule } from '@angular/common'; import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service'; import { of } from 'rxjs'; +import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; enum FlowType { symmetrical = 'symmetrical', @@ -33,6 +34,7 @@ describe('RgwMultisiteSyncFlowModalComponent', () => { ReactiveFormsModule, CommonModule ], + schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA], providers: [NgbActiveModal, { provide: RgwMultisiteService, useClass: MultisiteServiceMock }] }).compileComponents(); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-pipe-modal/rgw-multisite-sync-pipe-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-pipe-modal/rgw-multisite-sync-pipe-modal.component.spec.ts index 1127db1c59a59..faf382b78028e 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-pipe-modal/rgw-multisite-sync-pipe-modal.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-pipe-modal/rgw-multisite-sync-pipe-modal.component.spec.ts @@ -9,6 +9,7 @@ import { CommonModule } from '@angular/common'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { of } from 'rxjs'; import { RgwMultisiteService } from '~/app/shared/api/rgw-multisite.service'; +import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; class MultisiteServiceMock { createEditSyncPipe = jest.fn().mockReturnValue(of(null)); @@ -29,6 +30,7 @@ describe('RgwMultisiteSyncPipeModalComponent', () => { ReactiveFormsModule, CommonModule ], + schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA], providers: [NgbActiveModal, { provide: RgwMultisiteService, useClass: MultisiteServiceMock }] }).compileComponents(); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-policy-form/rgw-multisite-sync-policy-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-policy-form/rgw-multisite-sync-policy-form.component.spec.ts index b886ad1d5e57b..c09e7392a0b63 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-policy-form/rgw-multisite-sync-policy-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-sync-policy-form/rgw-multisite-sync-policy-form.component.spec.ts @@ -6,6 +6,7 @@ import { ReactiveFormsModule } from '@angular/forms'; import { PipesModule } from '~/app/shared/pipes/pipes.module'; import { ComponentsModule } from '~/app/shared/components/components.module'; import { RouterTestingModule } from '@angular/router/testing'; +import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; describe('RgwMultisiteSyncPolicyFormComponent', () => { let component: RgwMultisiteSyncPolicyFormComponent; @@ -22,6 +23,7 @@ describe('RgwMultisiteSyncPolicyFormComponent', () => { ComponentsModule, RouterTestingModule ], + schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA], providers: [] }).compileComponents(); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-wizard/rgw-multisite-wizard.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-wizard/rgw-multisite-wizard.component.spec.ts index 9047eef2d1771..21f36f9d0b318 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-wizard/rgw-multisite-wizard.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-wizard/rgw-multisite-wizard.component.spec.ts @@ -7,6 +7,7 @@ import { SharedModule } from '~/app/shared/shared.module'; import { ReactiveFormsModule } from '@angular/forms'; import { ToastrModule } from 'ngx-toastr'; import { RouterTestingModule } from '@angular/router/testing'; +import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; describe('RgwMultisiteWizardComponent', () => { let component: RgwMultisiteWizardComponent; @@ -22,6 +23,7 @@ describe('RgwMultisiteWizardComponent', () => { ToastrModule.forRoot(), RouterTestingModule ], + schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA], providers: [NgbActiveModal] }).compileComponents(); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-sync-data-info/rgw-sync-data-info.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-sync-data-info/rgw-sync-data-info.component.spec.ts index 944435cba16ac..ebcb017ece4be 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-sync-data-info/rgw-sync-data-info.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-sync-data-info/rgw-sync-data-info.component.spec.ts @@ -62,8 +62,8 @@ describe('RgwSyncDataInfoComponent', () => { const syncStatus = fixture.debugElement.query(By.css('.text-primary')); expect(syncStatus).toBeTruthy(); expect(syncStatus.nativeElement.textContent).toEqual('Syncing'); - const syncPopover = fixture.debugElement.query(By.css('a')); - syncPopover.triggerEventHandler('click', null); + const syncPopover = fixture.nativeElement.querySelector('a'); + syncPopover.dispatchEvent(new Event('click')); fixture.detectChanges(); expect(syncPopover).toBeTruthy(); const syncPopoverText = fixture.debugElement.query(By.css('.text-center')); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-sync-metadata-info/rgw-sync-metadata-info.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-sync-metadata-info/rgw-sync-metadata-info.component.spec.ts index 0b7e4ede377dc..0457fe2a98348 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-sync-metadata-info/rgw-sync-metadata-info.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-sync-metadata-info/rgw-sync-metadata-info.component.spec.ts @@ -65,8 +65,8 @@ describe('RgwSyncMetadataInfoComponent', () => { const syncStatus = fixture.debugElement.query(By.css('.text-primary')); expect(syncStatus).toBeTruthy(); expect(syncStatus.nativeElement.textContent).toEqual('Syncing'); - const syncPopover = fixture.debugElement.query(By.css('a')); - syncPopover.triggerEventHandler('click', null); + const syncPopover = fixture.nativeElement.querySelector('a'); + syncPopover.dispatchEvent(new Event('click')); fixture.detectChanges(); expect(syncPopover).toBeTruthy(); const syncPopoverText = fixture.debugElement.query(By.css('.text-center')); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.spec.ts index e9a4da80fd6c8..43633dc37895b 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/shared/health-checks/health-checks.component.spec.ts @@ -4,6 +4,7 @@ import { HealthChecksComponent } from './health-checks.component'; import { HealthColorPipe } from '~/app/shared/pipes/health-color.pipe'; import { By } from '@angular/platform-browser'; import { CssHelper } from '~/app/shared/classes/css-helper'; +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; describe('HealthChecksComponent', () => { let component: HealthChecksComponent; @@ -12,7 +13,8 @@ describe('HealthChecksComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [HealthChecksComponent, HealthColorPipe], - providers: [CssHelper] + providers: [CssHelper], + schemas: [CUSTOM_ELEMENTS_SCHEMA] }).compileComponents(); fixture = TestBed.createComponent(HealthChecksComponent); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-form/smb-cluster-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-form/smb-cluster-form.component.ts index 1acbb8efec337..da7b05713faa8 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-form/smb-cluster-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-cluster-form/smb-cluster-form.component.ts @@ -49,7 +49,7 @@ export class SmbClusterFormComponent extends CdForm implements OnInit { resource: string; icons = Icons; domainSettingsObject: DomainSettings; - modalData$ = this.smbService.modalData$; + modalData$!: Observable; constructor( private hostService: HostService, @@ -63,6 +63,7 @@ export class SmbClusterFormComponent extends CdForm implements OnInit { ) { super(); this.resource = $localize`Cluster`; + this.modalData$ = this.smbService.modalData$; } ngOnInit() { this.action = this.actionLabels.CREATE; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-domain-setting-modal/smb-domain-setting-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-domain-setting-modal/smb-domain-setting-modal.component.spec.ts index 44a9ca555d543..7bb5e131d5ae8 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-domain-setting-modal/smb-domain-setting-modal.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb-domain-setting-modal/smb-domain-setting-modal.component.spec.ts @@ -8,6 +8,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { NgbActiveModal, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap'; import { InputModule, ModalModule, SelectModule } from 'carbon-components-angular'; +import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; describe('SmbDomainSettingModalComponent', () => { let component: SmbDomainSettingModalComponent; @@ -27,6 +28,7 @@ describe('SmbDomainSettingModalComponent', () => { InputModule, SelectModule ], + schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA], providers: [NgbActiveModal, { provide: 'domainSettingsObject', useValue: [[]] }] }).compileComponents(); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb.module.ts index 9caadd5a97cdf..a3a9816e93e60 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/smb/smb.module.ts @@ -2,7 +2,7 @@ import Close from '@carbon/icons/es/close/32'; import { SmbClusterListComponent } from './smb-cluster-list/smb-cluster-list.component'; import { SmbClusterFormComponent } from './smb-cluster-form/smb-cluster-form.component'; import { AppRoutingModule } from '~/app/app-routing.module'; -import { NgChartsModule } from 'ng2-charts'; +import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts'; import { DataTableModule } from '~/app/shared/datatable/datatable.module'; import { SmbDomainSettingModalComponent } from './smb-domain-setting-modal/smb-domain-setting-modal.component'; import { @@ -33,7 +33,7 @@ import { NgModule } from '@angular/core'; CommonModule, SharedModule, AppRoutingModule, - NgChartsModule, + BaseChartDirective, CommonModule, FormsModule, ReactiveFormsModule, @@ -53,7 +53,8 @@ import { NgModule } from '@angular/core'; IconModule ], exports: [SmbClusterListComponent, SmbClusterFormComponent], - declarations: [SmbClusterListComponent, SmbClusterFormComponent, SmbDomainSettingModalComponent] + declarations: [SmbClusterListComponent, SmbClusterFormComponent, SmbDomainSettingModalComponent], + providers: [provideCharts(withDefaultRegisterables())] }) export class SmbModule { constructor(private iconService: IconService) { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts index f4e8e1d0bce0f..7eb708d6e7953 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts @@ -10,7 +10,6 @@ import { of } from 'rxjs'; import { RoleService } from '~/app/shared/api/role.service'; import { ScopeService } from '~/app/shared/api/scope.service'; -import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component'; import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; import { NotificationService } from '~/app/shared/services/notification.service'; import { SharedModule } from '~/app/shared/shared.module'; @@ -32,19 +31,16 @@ describe('RoleFormComponent', () => { const routes: Routes = [{ path: 'roles', component: FakeComponent }]; - configureTestBed( - { - imports: [ - RouterTestingModule.withRoutes(routes), - HttpClientTestingModule, - ReactiveFormsModule, - ToastrModule.forRoot(), - SharedModule - ], - declarations: [RoleFormComponent, FakeComponent] - }, - [LoadingPanelComponent] - ); + configureTestBed({ + imports: [ + RouterTestingModule.withRoutes(routes), + HttpClientTestingModule, + ReactiveFormsModule, + ToastrModule.forRoot(), + SharedModule + ], + declarations: [RoleFormComponent, FakeComponent] + }); beforeEach(() => { fixture = TestBed.createComponent(RoleFormComponent); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts index 943fc033ede05..efe5a819e8091 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/user-form/user-form.component.spec.ts @@ -13,7 +13,6 @@ import { RoleService } from '~/app/shared/api/role.service'; import { SettingsService } from '~/app/shared/api/settings.service'; import { UserService } from '~/app/shared/api/user.service'; import { ComponentsModule } from '~/app/shared/components/components.module'; -import { LoadingPanelComponent } from '~/app/shared/components/loading-panel/loading-panel.component'; import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; import { NotificationService } from '~/app/shared/services/notification.service'; @@ -44,21 +43,18 @@ describe('UserFormComponent', () => { { path: 'users', component: FakeComponent } ]; - configureTestBed( - { - imports: [ - RouterTestingModule.withRoutes(routes), - HttpClientTestingModule, - ReactiveFormsModule, - ComponentsModule, - ToastrModule.forRoot(), - SharedModule, - NgbPopoverModule - ], - declarations: [UserFormComponent, FakeComponent] - }, - [LoadingPanelComponent] - ); + configureTestBed({ + imports: [ + RouterTestingModule.withRoutes(routes), + HttpClientTestingModule, + ReactiveFormsModule, + ComponentsModule, + ToastrModule.forRoot(), + SharedModule, + NgbPopoverModule + ], + declarations: [UserFormComponent, FakeComponent] + }); beforeEach(() => { spyOn(TestBed.inject(PasswordPolicyService), 'getHelpText').and.callFake(() => of('')); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts index 4c966f42bfbf4..47657aedf6177 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts @@ -13,7 +13,7 @@ import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; import { ClickOutsideModule } from 'ng-click-outside'; -import { NgChartsModule } from 'ng2-charts'; +import { provideCharts, withDefaultRegisterables, BaseChartDirective } from 'ng2-charts'; import { SimplebarAngularModule } from 'simplebar-angular'; import { UIShellModule, @@ -93,7 +93,6 @@ import InfoIcon from '@carbon/icons/es/information/16'; NgbPopoverModule, NgbProgressbarModule, NgbTooltipModule, - NgChartsModule, ReactiveFormsModule, PipesModule, DirectivesModule, @@ -121,7 +120,8 @@ import InfoIcon from '@carbon/icons/es/information/16'; DropdownModule, SelectModule, ComboBoxModule, - ProgressIndicatorModule + ProgressIndicatorModule, + BaseChartDirective ], declarations: [ SparklineComponent, @@ -165,7 +165,7 @@ import InfoIcon from '@carbon/icons/es/information/16'; UpgradableComponent, ProgressComponent ], - providers: [], + providers: [provideCharts(withDefaultRegisterables())], exports: [ SparklineComponent, HelperComponent, diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts index 97080a62ae484..2e0706786e38f 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component.spec.ts @@ -1,4 +1,4 @@ -import { Component, NgModule, NO_ERRORS_SCHEMA, TemplateRef, ViewChild } from '@angular/core'; +import { Component, NgModule, TemplateRef, ViewChild } from '@angular/core'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { NgForm, ReactiveFormsModule } from '@angular/forms'; @@ -9,7 +9,7 @@ import { configureTestBed, modalServiceShow } from '~/testing/unit-test-helper'; import { AlertPanelComponent } from '../alert-panel/alert-panel.component'; import { LoadingPanelComponent } from '../loading-panel/loading-panel.component'; import { CriticalConfirmationModalComponent } from './critical-confirmation-modal.component'; -import { ModalService, PlaceholderService } from 'carbon-components-angular'; +import { CheckboxModule, ModalService, PlaceholderService } from 'carbon-components-angular'; import { ModalCdsService } from '../../services/modal-cds.service'; @NgModule({}) @@ -88,26 +88,22 @@ describe('CriticalConfirmationModalComponent', () => { let component: CriticalConfirmationModalComponent; let mockFixture: ComponentFixture; - configureTestBed( - { - declarations: [ - MockComponent, - CriticalConfirmationModalComponent, - LoadingPanelComponent, - AlertPanelComponent - ], - schemas: [NO_ERRORS_SCHEMA], - imports: [ReactiveFormsModule, MockModule, DirectivesModule], - providers: [ - ModalService, - PlaceholderService, - { provide: 'itemNames', useValue: [] }, - { provide: 'itemDescription', useValue: 'entry' }, - { provide: 'actionDescription', useValue: 'delete' } - ] - }, - [CriticalConfirmationModalComponent] - ); + configureTestBed({ + declarations: [ + MockComponent, + CriticalConfirmationModalComponent, + LoadingPanelComponent, + AlertPanelComponent + ], + imports: [ReactiveFormsModule, MockModule, DirectivesModule, CheckboxModule], + providers: [ + ModalService, + PlaceholderService, + { provide: 'itemNames', useValue: [] }, + { provide: 'itemDescription', useValue: 'entry' }, + { provide: 'actionDescription', useValue: 'delete' } + ] + }); beforeEach(() => { mockFixture = TestBed.createComponent(MockComponent); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/form-advanced-fieldset/form-advanced-fieldset.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/form-advanced-fieldset/form-advanced-fieldset.component.spec.ts index de2c48c48d74c..901105aff3fe0 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/form-advanced-fieldset/form-advanced-fieldset.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/form-advanced-fieldset/form-advanced-fieldset.component.spec.ts @@ -1,6 +1,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { FormAdvancedFieldsetComponent } from './form-advanced-fieldset.component'; +import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; describe('FormAdvancedFieldsetComponent', () => { let component: FormAdvancedFieldsetComponent; @@ -8,7 +9,8 @@ describe('FormAdvancedFieldsetComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [FormAdvancedFieldsetComponent] + declarations: [FormAdvancedFieldsetComponent], + schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA] }).compileComponents(); fixture = TestBed.createComponent(FormAdvancedFieldsetComponent); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/form-modal/form-modal.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/form-modal/form-modal.component.html index 163890abf6bb0..a32b687470752 100755 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/form-modal/form-modal.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/form-modal/form-modal.component.html @@ -18,10 +18,9 @@
{{ field.label }} @@ -34,18 +33,15 @@ autofocus> { let component: ProgressComponent; @@ -8,7 +9,8 @@ describe('ProgressComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ProgressComponent] + declarations: [ProgressComponent], + schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA] }).compileComponents(); fixture = TestBed.createComponent(ProgressComponent); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/upgradable/upgradable.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/upgradable/upgradable.component.ts index d478df25d8a91..39e006f3b29bd 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/upgradable/upgradable.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/upgradable/upgradable.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { Observable, Subscription } from 'rxjs'; import { UpgradeService } from '../../api/upgrade.service'; @@ -13,7 +13,7 @@ import { ExecutingTask } from '../../models/executing-task'; templateUrl: './upgradable.component.html', styleUrls: ['./upgradable.component.scss'] }) -export class UpgradableComponent { +export class UpgradableComponent implements OnInit, OnDestroy { orchAvailable: boolean = false; upgradeInfo$: Observable; upgradeStatus$: Observable; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts index e6b176710b421..62caa51315ce1 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-key-value/table-key-value.component.spec.ts @@ -26,7 +26,7 @@ describe('TableKeyValueComponent', () => { RouterTestingModule, NgbDropdownModule, PipesModule, - NgbTooltipModule, + NgbTooltipModule ] }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-loading.directive.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-loading.directive.spec.ts index dc0e174c1e887..2713bbfec69f6 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-loading.directive.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/form-loading.directive.spec.ts @@ -5,8 +5,6 @@ import { By } from '@angular/platform-browser'; import { NgbAlertModule } from '@ng-bootstrap/ng-bootstrap'; import { configureTestBed } from '~/testing/unit-test-helper'; -import { AlertPanelComponent } from '../components/alert-panel/alert-panel.component'; -import { LoadingPanelComponent } from '../components/loading-panel/loading-panel.component'; import { CdForm } from '../forms/cd-form'; import { SharedModule } from '../shared.module'; import { FormLoadingDirective } from './form-loading.directive'; @@ -28,13 +26,10 @@ describe('FormLoadingDirective', () => { expect(fixture.debugElement.queryAll(By.css('cd-loading-panel')).length).toEqual(loading); }; - configureTestBed( - { - declarations: [TestComponent], - imports: [SharedModule, NgbAlertModule] - }, - [LoadingPanelComponent, AlertPanelComponent] - ); + configureTestBed({ + declarations: [TestComponent], + imports: [SharedModule, NgbAlertModule] + }); afterEach(() => { fixture = null; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/required-field.directive.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/required-field.directive.ts index a14a983f54bd2..7257bf9240a5e 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/required-field.directive.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/required-field.directive.ts @@ -5,7 +5,7 @@ import { AfterViewInit, Directive, ElementRef, Input, Renderer2 } from '@angular }) export class RequiredFieldDirective implements AfterViewInit { @Input('cdRequiredField') label: string; - @Input('skeleton') skeleton: boolean; + @Input() skeleton: boolean; constructor(private elementRef: ElementRef, private renderer: Renderer2) {} ngAfterViewInit() { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/stateful-tab.directive.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/stateful-tab.directive.spec.ts index 295bb008c3617..0a703d7f0e4de 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/stateful-tab.directive.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/directives/stateful-tab.directive.spec.ts @@ -1,15 +1,29 @@ -import { NgbConfig, NgbNav, NgbNavChangeEvent, NgbNavConfig } from '@ng-bootstrap/ng-bootstrap'; +import { NgbNav, NgbNavChangeEvent } from '@ng-bootstrap/ng-bootstrap'; +import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; import { StatefulTabDirective } from './stateful-tab.directive'; +import { TestBed } from '@angular/core/testing'; + +class NgbNavMock { + select() {} +} describe('StatefulTabDirective', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [StatefulTabDirective], + providers: [{ provide: NgbNav, useClass: NgbNavMock }], + schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA] + }).compileComponents(); + }); + it('should create an instance', () => { const directive = new StatefulTabDirective(null); expect(directive).toBeTruthy(); }); it('should get and select active tab', () => { - const nav = new NgbNav('tablist', new NgbNavConfig(new NgbConfig()), null, null); + const nav = TestBed.inject(NgbNav); spyOn(nav, 'select'); const directive = new StatefulTabDirective(nav); directive.cdStatefulTab = 'bar'; @@ -27,7 +41,7 @@ describe('StatefulTabDirective', () => { }); it('should select the default tab if provided', () => { - const nav = new NgbNav('tablist', new NgbNavConfig(new NgbConfig()), null, null); + const nav = TestBed.inject(NgbNav); spyOn(nav, 'select'); const directive = new StatefulTabDirective(nav); directive.cdStatefulTab = 'bar'; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/breadcrumbs.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/breadcrumbs.ts index 14361cceeb745..586b477f6465a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/models/breadcrumbs.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/models/breadcrumbs.ts @@ -26,7 +26,7 @@ import { ActivatedRouteSnapshot, UrlSegment } from '@angular/router'; import { Observable, of } from 'rxjs'; -export class BreadcrumbsResolver { +export class BreadcrumbsResolver { public resolve( route: ActivatedRouteSnapshot ): Observable | Promise | IBreadcrumb[] { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/pipes.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/pipes.module.ts index 22e17acf63dce..d08132f4120c5 100755 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/pipes.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/pipes/pipes.module.ts @@ -125,7 +125,8 @@ import { PipeFunctionPipe } from './pipe-function.pipe'; PathPipe, PluralizePipe, XmlPipe, - MbpersecondPipe + MbpersecondPipe, + PipeFunctionPipe ], providers: [ ArrayPipe, diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.ts index 2a663c49a46b0..84a630346d476 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/api-interceptor.service.ts @@ -1,4 +1,10 @@ -import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; +import { + HttpErrorResponse, + HttpEvent, + HttpHandler, + HttpInterceptor, + HttpRequest +} from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-guard.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-guard.service.ts index b75b730a1b842..1f1c3adf2bb21 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-guard.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/auth-guard.service.ts @@ -6,7 +6,7 @@ import { AuthStorageService } from './auth-storage.service'; @Injectable({ providedIn: 'root' }) -export class AuthGuardService { +export class AuthGuardService { constructor(private router: Router, private authStorageService: AuthStorageService) {} canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/change-password-guard.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/change-password-guard.service.ts index 92de27690b6f0..8e577687c14b9 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/change-password-guard.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/change-password-guard.service.ts @@ -10,7 +10,7 @@ import { AuthStorageService } from './auth-storage.service'; @Injectable({ providedIn: 'root' }) -export class ChangePasswordGuardService { +export class ChangePasswordGuardService { constructor(private router: Router, private authStorageService: AuthStorageService) {} canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles-guard.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles-guard.service.ts index 791826aeff649..ab4416bb3fd4a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles-guard.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/feature-toggles-guard.service.ts @@ -9,7 +9,7 @@ import { FeatureTogglesMap, FeatureTogglesService } from './feature-toggles.serv @Injectable({ providedIn: 'root' }) -export class FeatureTogglesGuardService { +export class FeatureTogglesGuardService { constructor(private featureToggles: FeatureTogglesService) {} canActivate(route: ActivatedRouteSnapshot) { diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/modal.service.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/modal.service.spec.ts index 4e5ed061d830c..d1f14160da13e 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/modal.service.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/modal.service.spec.ts @@ -19,7 +19,7 @@ describe('ModalService', () => { let service: ModalService; let ngbModal: NgbModal; - configureTestBed({ declarations: [MockComponent], imports: [NgbModalModule] }, [MockComponent]); + configureTestBed({ declarations: [MockComponent], imports: [NgbModalModule] }); beforeEach(() => { service = TestBed.inject(ModalService); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts index d511b12a1cb87..e828a5ba523cf 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/module-status-guard.service.ts @@ -36,7 +36,7 @@ import { Icons } from '~/app/shared/enum/icons.enum'; @Injectable({ providedIn: 'root' }) -export class ModuleStatusGuardService { +export class ModuleStatusGuardService { // TODO: Hotfix - remove ALLOWLIST'ing when a generic ErrorComponent is implemented static readonly ALLOWLIST: string[] = ['501']; diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/no-sso-guard.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/no-sso-guard.service.ts index 4907b971fb3a8..d5f2f642fbae4 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/services/no-sso-guard.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/services/no-sso-guard.service.ts @@ -1,6 +1,5 @@ import { Injectable } from '@angular/core'; - import { DashboardUserDeniedError } from '~/app/core/error/error'; import { AuthStorageService } from './auth-storage.service'; @@ -11,7 +10,7 @@ import { AuthStorageService } from './auth-storage.service'; @Injectable({ providedIn: 'root' }) -export class NoSsoGuardService { +export class NoSsoGuardService { constructor(private authStorageService: AuthStorageService) {} canActivate() { diff --git a/src/pybind/mgr/dashboard/frontend/src/testing/unit-test-helper.ts b/src/pybind/mgr/dashboard/frontend/src/testing/unit-test-helper.ts index 21e94e9996cc6..fabbe22c7b945 100644 --- a/src/pybind/mgr/dashboard/frontend/src/testing/unit-test-helper.ts +++ b/src/pybind/mgr/dashboard/frontend/src/testing/unit-test-helper.ts @@ -1,8 +1,7 @@ -import { DebugElement, Type } from '@angular/core'; +import { CUSTOM_ELEMENTS_SCHEMA, DebugElement, NO_ERRORS_SCHEMA, Type } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { AbstractControl } from '@angular/forms'; import { By } from '@angular/platform-browser'; -import { BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing'; import { NgbModal, NgbNav, NgbNavItem, NgbNavLink } from '@ng-bootstrap/ng-bootstrap'; import _ from 'lodash'; @@ -29,20 +28,12 @@ import { PrometheusRule } from '~/app/shared/models/prometheus-alerts'; -export function configureTestBed(configuration: any, entryComponents?: any) { - beforeEach(async () => { - if (entryComponents) { - // Declare entryComponents without having to add them to a module - // This is needed since Jest doesn't yet support not declaring entryComponents - await TestBed.configureTestingModule(configuration).overrideModule( - BrowserDynamicTestingModule, - { - set: { entryComponents: entryComponents } - } - ); - } else { - await TestBed.configureTestingModule(configuration); - } +export function configureTestBed(configuration: any) { + beforeEach(() => { + TestBed.configureTestingModule({ + ...configuration, + schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA] + }); }); } diff --git a/src/pybind/mgr/dashboard/frontend/tsconfig.json b/src/pybind/mgr/dashboard/frontend/tsconfig.json index 9433b2e67f6af..eda40c3953ac4 100644 --- a/src/pybind/mgr/dashboard/frontend/tsconfig.json +++ b/src/pybind/mgr/dashboard/frontend/tsconfig.json @@ -18,8 +18,8 @@ "noImplicitAny": true, "ignoreDeprecations": "5.0", "suppressImplicitAnyIndexErrors": true, - "target": "ES2020", - "module": "es2020", + "target": "ES2022", + "module": "ES2022", "baseUrl": "./", "resolveJsonModule": true, "paths": {