diff --git a/angular.json b/angular.json index 02fa9f6..362b608 100644 --- a/angular.json +++ b/angular.json @@ -27,7 +27,12 @@ "tsConfig": "tsconfig.app.json", "assets": [ "src/favicon.ico", - "src/assets" + "src/assets", + { + "glob": "**/*", + "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", + "output": "/assets/" + } ], "styles": [ "node_modules/ng-zorro-antd/src/ng-zorro-antd.min.css", diff --git a/package.json b/package.json index 4dfdab5..6e10842 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@loaders.gl/csv": "^4.3.4", "@primeuix/themes": "^2.0.2", "angular-plotly.js": "^20.0.0", + "appwrite": "^21.5.0", "bootstrap": "^5.3.8", "brand-colors": "^2.1.1", "d3-color": "^3.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c0454e4..33c8498 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,31 +22,31 @@ importers: dependencies: '@angular/animations': specifier: ^21.0.4 - version: 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) + version: 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) '@angular/common': specifier: ^21.0.4 - version: 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + version: 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) '@angular/compiler': specifier: '>=21.0.7' - version: 21.1.0 + version: 21.1.1 '@angular/core': specifier: '>=21.0.7' - version: 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) + version: 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) '@angular/forms': specifier: ^21.0.4 - version: 21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + version: 21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@angular/platform-browser': specifier: ^21.0.4 - version: 21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) + version: 21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) '@angular/platform-browser-dynamic': specifier: ^21.0.4 - version: 21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@21.1.0)(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))) + version: 21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@21.1.1)(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))) '@angular/router': specifier: ^21.0.4 - version: 21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + version: 21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@ant-design/icons-angular': specifier: 21.0.0 - version: 21.0.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + version: 21.0.0(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@date-fns/utc': specifier: ^2.1.1 version: 2.1.1 @@ -70,7 +70,10 @@ importers: version: 2.0.3 angular-plotly.js: specifier: ^20.0.0 - version: 20.0.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) + version: 20.0.0(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) + appwrite: + specifier: ^21.5.0 + version: 21.5.0 bootstrap: specifier: ^5.3.8 version: 5.3.8(@popperjs/core@2.11.8) @@ -103,10 +106,10 @@ importers: version: 2.30.1 ng-zorro-antd: specifier: ~21.0.1 - version: 21.0.1(aa0c172d237a76dfd030999360bc015e) + version: 21.0.2(3ffaf799d29488433d7e632450beace1) ngx-select-dropdown: specifier: ^3.3.2 - version: 3.3.2(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) + version: 3.3.2(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) papaparse: specifier: ^5.5.3 version: 5.5.3 @@ -131,7 +134,7 @@ importers: devDependencies: '@angular-eslint/builder': specifier: 21.1.0 - version: 21.1.0(@angular/cli@21.0.6(@types/node@25.0.9)(hono@4.11.4))(eslint@9.39.2)(typescript@5.9.3) + version: 21.1.0(@angular/cli@21.0.6(@types/node@25.0.10)(hono@4.11.5))(eslint@9.39.2)(typescript@5.9.3) '@angular-eslint/eslint-plugin': specifier: 21.1.0 version: 21.1.0(@typescript-eslint/utils@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) @@ -140,19 +143,19 @@ importers: version: 21.1.0(@angular-eslint/template-parser@21.1.0(eslint@9.39.2)(typescript@5.9.3))(@typescript-eslint/types@8.53.1)(@typescript-eslint/utils@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) '@angular-eslint/schematics': specifier: 21.1.0 - version: 21.1.0(@angular-eslint/template-parser@21.1.0(eslint@9.39.2)(typescript@5.9.3))(@angular/cli@21.0.6(@types/node@25.0.9)(hono@4.11.4))(@typescript-eslint/types@8.53.1)(@typescript-eslint/utils@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + version: 21.1.0(@angular-eslint/template-parser@21.1.0(eslint@9.39.2)(typescript@5.9.3))(@angular/cli@21.0.6(@types/node@25.0.10)(hono@4.11.5))(@typescript-eslint/types@8.53.1)(@typescript-eslint/utils@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) '@angular-eslint/template-parser': specifier: 21.1.0 version: 21.1.0(eslint@9.39.2)(typescript@5.9.3) '@angular/build': specifier: ^21.0.3 - version: 21.1.0(@angular/compiler-cli@21.1.0(@angular/compiler@21.1.0)(typescript@5.9.3))(@angular/compiler@21.1.0)(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@types/node@25.0.9)(karma@6.4.4)(postcss@8.5.6)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.0.17(@types/node@25.0.9)(jsdom@27.4.0)(sass@1.97.1)) + version: 21.1.1(@angular/compiler-cli@21.1.1(@angular/compiler@21.1.1)(typescript@5.9.3))(@angular/compiler@21.1.1)(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@types/node@25.0.10)(karma@6.4.4)(postcss@8.5.6)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.0.18(@types/node@25.0.10)(jsdom@27.4.0)(sass@1.97.1)) '@angular/cli': specifier: ~21.0.3 - version: 21.0.6(@types/node@25.0.9)(hono@4.11.4) + version: 21.0.6(@types/node@25.0.10)(hono@4.11.5) '@angular/compiler-cli': specifier: ^21.0.4 - version: 21.1.0(@angular/compiler@21.1.0)(typescript@5.9.3) + version: 21.1.1(@angular/compiler@21.1.1)(typescript@5.9.3) '@types/bootstrap': specifier: ^5.2.10 version: 5.2.10 @@ -185,7 +188,7 @@ importers: version: 8.53.1(eslint@9.39.2)(typescript@5.9.3) baseline-browser-mapping: specifier: ^2.9.16 - version: 2.9.16 + version: 2.9.17 eslint: specifier: ^9.39.1 version: 9.39.2 @@ -194,13 +197,13 @@ importers: version: 27.4.0 primeng: specifier: ^21.0.1 - version: 21.0.4(f5f9118e2d83aa9e57b7d3e1b08b23a5) + version: 21.0.4(ee84ac0261975de6e3068975b2af45d9) typescript: specifier: ~5.9.3 version: 5.9.3 vitest: specifier: ^4.0.17 - version: 4.0.17(@types/node@25.0.9)(jsdom@27.4.0)(sass@1.97.1) + version: 4.0.18(@types/node@25.0.10)(jsdom@27.4.0)(sass@1.97.1) webpack-bundle-analyzer: specifier: ^4.10.2 version: 4.10.2 @@ -274,8 +277,8 @@ packages: resolution: {integrity: sha512-RsCXULyyNNElRHDObVeEBhEOaLK8QaKu+DaYVhfkOOKvVeDoEI0i+0JomzPhGDjazXPPYG8BPOTgSOvhlEeWSA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - '@angular-devkit/architect@0.2101.0': - resolution: {integrity: sha512-vnNAzWXwSRGTHk2K7woIQsj7WDYZp69Z3DBdlxkK0H08ymkJ/ELbhN0/AnIJNNtYCqEb57AH7Ro98n422beDuw==} + '@angular-devkit/architect@0.2101.1': + resolution: {integrity: sha512-8x7hKcFs3hnpDaIj9fyzinh4X74oQaMxMsZzBf4dBL7EwokjPIf2fadQsZd8a5M+Ja4tIgTnXH9ySyaRFWGNXA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true @@ -288,8 +291,8 @@ packages: chokidar: optional: true - '@angular-devkit/core@21.1.0': - resolution: {integrity: sha512-dPfVy0CictDjWffRv4pGTPOFjdlJL3ZkGUqxzaosUjMbJW+Ai9cNn1VNr7zxYZ4kem3BxLBh1thzDsCPrkXlZA==} + '@angular-devkit/core@21.1.1': + resolution: {integrity: sha512-rCwfBUemyRoAfrO4c85b49lkPiD5WljWE+IK7vjUNIFFf4TXOS4tg4zxqopUDVE4zEjXORa5oHCEc5HCerjn1g==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: chokidar: ^5.0.0 @@ -301,8 +304,8 @@ packages: resolution: {integrity: sha512-0Zg4IeBoAjPNtGQobZEH010l1jQThq2lMdQZfqhLj4a3XoVdhGdzo9Xcn+GcA/z0zXy+rtAiqRazsk9mW1VcRA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - '@angular-devkit/schematics@21.1.0': - resolution: {integrity: sha512-sVgTntCZCOV7mOpHzj6V14KOAoy4B9Ur9yHNRFZVgL2yD77TYRrJ0qwq+l7Im9fSjMCar6csjboqCvyAEpfV1g==} + '@angular-devkit/schematics@21.1.1': + resolution: {integrity: sha512-3ptEOuALghEYEPVbhRa7g8a+YmvmHqHVNqF9XqCbG22nPGWkE58qfNNbXi3tF9iQxzKSGw5Iy5gYUvSvpsdcfw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} '@angular-eslint/builder@21.1.0': @@ -349,14 +352,14 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '*' - '@angular/animations@21.1.0': - resolution: {integrity: sha512-RTpRdWhwz1PsMJC8NuuYIKCgMFP9EyxOrSaI0bpCLIGtXCfmvvHiU2FkBksV86MqYOf+wurKATb71QcfGrV3Hg==} + '@angular/animations@21.1.1': + resolution: {integrity: sha512-OQRyNbFBCkuihdCegrpN/Np5YQ7uV9if48LAoXxT68tYhK3S/Qbyx2MzJpOMFEFNfpjXRg1BZr8hVcZVFnArpg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/core': 21.1.0 + '@angular/core': 21.1.1 - '@angular/build@21.1.0': - resolution: {integrity: sha512-ftms4F/TlkRNhf/4ykFO12zTG0f9sIRZ4fGFnaOVGmnKYkPKZklWvMCPoaoIligHS2pqKye1a5JSiTgTeUDp9w==} + '@angular/build@21.1.1': + resolution: {integrity: sha512-OqlfH7tkahw/lFT6ACU6mqt3AGgTxxT27JTqpzZOeGo1ferR9dq1O6/CT4GiNyr/Z1AMfs7rBWlQH68y1QZb2g==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: '@angular/compiler': '>=21.0.7' @@ -366,7 +369,7 @@ packages: '@angular/platform-browser': ^21.0.0 '@angular/platform-server': ^21.0.0 '@angular/service-worker': ^21.0.0 - '@angular/ssr': ^21.1.0 + '@angular/ssr': ^21.1.1 karma: ^6.4.0 less: ^4.2.0 ng-packagr: ^21.0.0 @@ -401,8 +404,8 @@ packages: vitest: optional: true - '@angular/cdk@21.1.0': - resolution: {integrity: sha512-zvV37HPKhtu0bOfuK0IhjKKq++Xb57Z11uZYZJI34BZnZ5y1TPhJpcmrHhjb2uKUNfDvePUqhlnIlKAXHSBIhw==} + '@angular/cdk@21.1.1': + resolution: {integrity: sha512-lzscv+A6FCQdyWIr0t0QHXEgkLzS9wJwgeOOOhtxbixxxuk7xVXdcK/jnswE1Maugh1m696jUkOhZpffks3psA==} peerDependencies: '@angular/common': ^21.0.0 || ^22.0.0 '@angular/core': '>=21.0.7' @@ -414,33 +417,33 @@ packages: engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true - '@angular/common@21.1.0': - resolution: {integrity: sha512-hL3Chp51TU9iBcIfkNtoBS1wuseP1gsyDW2IFtK5HUpAVhbso9B3fdCaDTFkU98A2unluo2YgzI6D/6IS6N+1g==} + '@angular/common@21.1.1': + resolution: {integrity: sha512-Di2I6TooHdKun3SqRr45o4LbWJq/ZdwUt3fg0X3obPYaP/f6TrFQ4TMjcl03EfPufPtoQx6O+d32rcWVLhDxyw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/core': 21.1.0 + '@angular/core': 21.1.1 rxjs: ^6.5.3 || ^7.4.0 - '@angular/compiler-cli@21.1.0': - resolution: {integrity: sha512-//BTtxJovsF0LaOWQkOVxWX4EVyNJaPus+IlwWxzmdRHpojIl1Zdyy9BJMVJOifvj3XQ16sZwR1PDWDI5DIWrg==} + '@angular/compiler-cli@21.1.1': + resolution: {integrity: sha512-CCB8SZS0BzqLOdOaMpPpOW256msuatYCFDRTaT+awYIY1vQp/eLXzkMTD2uqyHraQy8cReeH/P6optRP9A077Q==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} hasBin: true peerDependencies: - '@angular/compiler': 21.1.0 + '@angular/compiler': 21.1.1 typescript: '>=5.9 <6.0' peerDependenciesMeta: typescript: optional: true - '@angular/compiler@21.1.0': - resolution: {integrity: sha512-UprCiJwEU1Ilw1dVk+yLgNiHlbH81obAuh92lRKozUQRgtSCpOfCQUM79q5r+VdmCPxDshr79U2Ke0fRaiJfAQ==} + '@angular/compiler@21.1.1': + resolution: {integrity: sha512-Urd3bh0zv0MQ//S7RRTanIkOMAZH/A7vSMXUDJ3aflplNs7JNbVqBwDNj8NoX1V+os+fd8JRJOReCc1EpH4ZKQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - '@angular/core@21.1.0': - resolution: {integrity: sha512-QTl9s8GYNN0pt1k3GE6UVlfe6zWtfdykhfchinKq2YJywQ6LBM4UcZgoc56YkgscmyrRFYrr4JYUJjlzTF57+A==} + '@angular/core@21.1.1': + resolution: {integrity: sha512-KFRCEhsi02pY1EqJ5rnze4mzSaacqh14D8goDhtmARiUH0tefaHR+uKyu4bKSrWga2T/ExG0DJX52LhHRs2qSw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/compiler': 21.1.0 + '@angular/compiler': 21.1.1 rxjs: ^6.5.3 || ^7.4.0 zone.js: ~0.15.0 || ~0.16.0 peerDependenciesMeta: @@ -449,42 +452,42 @@ packages: zone.js: optional: true - '@angular/forms@21.1.0': - resolution: {integrity: sha512-1Qxsu2cQhraKe2dKzIVm7no1qWi76QsXVwY7+VGKRYG7p+fKaFmnr7oU5EbJL66TsFzCb8mDGxLGikS+YE+X/g==} + '@angular/forms@21.1.1': + resolution: {integrity: sha512-NBbJOynLOeMsPo03+3dfdxE0P7SB7SXRqoFJ7WP2sOgOIxODna/huo2blmRlnZAVPTn1iQEB9Q+UeyP5c4/1+w==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 21.1.0 - '@angular/core': 21.1.0 - '@angular/platform-browser': 21.1.0 + '@angular/common': 21.1.1 + '@angular/core': 21.1.1 + '@angular/platform-browser': 21.1.1 rxjs: ^6.5.3 || ^7.4.0 - '@angular/platform-browser-dynamic@21.1.0': - resolution: {integrity: sha512-NsjHxqgErrIIp96lWq5IqyuyJv5sb8L6pdINtY04kFh8bVWzS7+clr/P6emIi3N7d+pX+JGd4EOp8b8veQi8Lg==} + '@angular/platform-browser-dynamic@21.1.1': + resolution: {integrity: sha512-lawT3bdjXZVmVNXVoPS0UiB8Qxw5jEYXHx2m38JvHGv7/pl0Sgr+wa6f+/4pvTwu3VZb/8ohkVdFicPfrU21Jw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 21.1.0 - '@angular/compiler': 21.1.0 - '@angular/core': 21.1.0 - '@angular/platform-browser': 21.1.0 + '@angular/common': 21.1.1 + '@angular/compiler': 21.1.1 + '@angular/core': 21.1.1 + '@angular/platform-browser': 21.1.1 - '@angular/platform-browser@21.1.0': - resolution: {integrity: sha512-Drkal25x+OuRQosAE/cL4uM5WDmgFehanCpsjQ1jGp6Rxoad6Q5Do1uQAE3qgMKHL1aqCPZ+uWzcVVG+Bn1ddg==} + '@angular/platform-browser@21.1.1': + resolution: {integrity: sha512-d6liZjPz29GUZ6dhxytFL/W2nMsYwPpc/E/vZpr5yV+u+gI2VjbnLbl8SG+jjj0/Hyq7s4aGhEKsRrCJJMXgNw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/animations': 21.1.0 - '@angular/common': 21.1.0 - '@angular/core': 21.1.0 + '@angular/animations': 21.1.1 + '@angular/common': 21.1.1 + '@angular/core': 21.1.1 peerDependenciesMeta: '@angular/animations': optional: true - '@angular/router@21.1.0': - resolution: {integrity: sha512-Sneu0ePuH+bf8ZslRX3iQk1iLziindLskdTeHV1ZCrXdT0ZScsZyI/gjxQKBtsIU9692D2DnFQRLGnzTBYVGVw==} + '@angular/router@21.1.1': + resolution: {integrity: sha512-3ypbtH3KfzuVgebdEET9+bRwn1VzP//KI0tIqleCGi4rblP3WQ/HwIGa5Qhdcxmw/kbmABKLRXX2kRUvidKs/Q==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 21.1.0 - '@angular/core': 21.1.0 - '@angular/platform-browser': 21.1.0 + '@angular/common': 21.1.1 + '@angular/core': 21.1.1 + '@angular/platform-browser': 21.1.1 rxjs: ^6.5.3 || ^7.4.0 '@ant-design/colors@7.2.1': @@ -618,9 +621,8 @@ packages: peerDependencies: '@csstools/css-tokenizer': ^3.0.4 - '@csstools/css-syntax-patches-for-csstree@1.0.25': - resolution: {integrity: sha512-g0Kw9W3vjx5BEBAF8c5Fm2NcB/Fs8jJXh85aXqwEXiL+tqtOut07TWgyaGzAAfTM+gKckrrncyeGEZPcaRgm2Q==} - engines: {node: '>=18'} + '@csstools/css-syntax-patches-for-csstree@1.0.26': + resolution: {integrity: sha512-6boXK0KkzT5u5xOgF6TKB+CLq9SOpEGmkZw0g5n9/7yg85wab3UzSxB8TxhLJ31L4SGJ6BCFRw/iftTha1CJXA==} '@csstools/css-tokenizer@3.0.4': resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} @@ -878,8 +880,8 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@exodus/bytes@1.9.0': - resolution: {integrity: sha512-lagqsvnk09NKogQaN/XrtlWeUF8SRhT12odMvbTIIaVObqzwAogL6jhR4DAp0gPuKoM1AOVrKUshJpRdpMFrww==} + '@exodus/bytes@1.10.0': + resolution: {integrity: sha512-tf8YdcbirXdPnJ+Nd4UN1EXnz+IP2DI45YVEr3vvzcVTOyrApkmIB4zvOQVd3XPr7RXnfBtAx+PXImXOIU0Ajg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: '@noble/hashes': ^1.8.0 || ^2.0.0 @@ -1666,128 +1668,128 @@ packages: '@rolldown/pluginutils@1.0.0-beta.58': resolution: {integrity: sha512-qWhDs6yFGR5xDfdrwiSa3CWGIHxD597uGE/A9xGqytBjANvh4rLCTTkq7szhMV4+Ygh+PMS90KVJ8xWG/TkX4w==} - '@rollup/rollup-android-arm-eabi@4.55.3': - resolution: {integrity: sha512-qyX8+93kK/7R5BEXPC2PjUt0+fS/VO2BVHjEHyIEWiYn88rcRBHmdLgoJjktBltgAf+NY7RfCGB1SoyKS/p9kg==} + '@rollup/rollup-android-arm-eabi@4.56.0': + resolution: {integrity: sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.55.3': - resolution: {integrity: sha512-6sHrL42bjt5dHQzJ12Q4vMKfN+kUnZ0atHHnv4V0Wd9JMTk7FDzSY35+7qbz3ypQYMBPANbpGK7JpnWNnhGt8g==} + '@rollup/rollup-android-arm64@4.56.0': + resolution: {integrity: sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.55.3': - resolution: {integrity: sha512-1ht2SpGIjEl2igJ9AbNpPIKzb1B5goXOcmtD0RFxnwNuMxqkR6AUaaErZz+4o+FKmzxcSNBOLrzsICZVNYa1Rw==} + '@rollup/rollup-darwin-arm64@4.56.0': + resolution: {integrity: sha512-EgxD1ocWfhoD6xSOeEEwyE7tDvwTgZc8Bss7wCWe+uc7wO8G34HHCUH+Q6cHqJubxIAnQzAsyUsClt0yFLu06w==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.55.3': - resolution: {integrity: sha512-FYZ4iVunXxtT+CZqQoPVwPhH7549e/Gy7PIRRtq4t5f/vt54pX6eG9ebttRH6QSH7r/zxAFA4EZGlQ0h0FvXiA==} + '@rollup/rollup-darwin-x64@4.56.0': + resolution: {integrity: sha512-1vXe1vcMOssb/hOF8iv52A7feWW2xnu+c8BV4t1F//m9QVLTfNVpEdja5ia762j/UEJe2Z1jAmEqZAK42tVW3g==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.55.3': - resolution: {integrity: sha512-M/mwDCJ4wLsIgyxv2Lj7Len+UMHd4zAXu4GQ2UaCdksStglWhP61U3uowkaYBQBhVoNpwx5Hputo8eSqM7K82Q==} + '@rollup/rollup-freebsd-arm64@4.56.0': + resolution: {integrity: sha512-bof7fbIlvqsyv/DtaXSck4VYQ9lPtoWNFCB/JY4snlFuJREXfZnm+Ej6yaCHfQvofJDXLDMTVxWscVSuQvVWUQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.55.3': - resolution: {integrity: sha512-5jZT2c7jBCrMegKYTYTpni8mg8y3uY8gzeq2ndFOANwNuC/xJbVAoGKR9LhMDA0H3nIhvaqUoBEuJoICBudFrA==} + '@rollup/rollup-freebsd-x64@4.56.0': + resolution: {integrity: sha512-KNa6lYHloW+7lTEkYGa37fpvPq+NKG/EHKM8+G/g9WDU7ls4sMqbVRV78J6LdNuVaeeK5WB9/9VAFbKxcbXKYg==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.55.3': - resolution: {integrity: sha512-YeGUhkN1oA+iSPzzhEjVPS29YbViOr8s4lSsFaZKLHswgqP911xx25fPOyE9+khmN6W4VeM0aevbDp4kkEoHiA==} + '@rollup/rollup-linux-arm-gnueabihf@4.56.0': + resolution: {integrity: sha512-E8jKK87uOvLrrLN28jnAAAChNq5LeCd2mGgZF+fGF5D507WlG/Noct3lP/QzQ6MrqJ5BCKNwI9ipADB6jyiq2A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.55.3': - resolution: {integrity: sha512-eo0iOIOvcAlWB3Z3eh8pVM8hZ0oVkK3AjEM9nSrkSug2l15qHzF3TOwT0747omI6+CJJvl7drwZepT+re6Fy/w==} + '@rollup/rollup-linux-arm-musleabihf@4.56.0': + resolution: {integrity: sha512-jQosa5FMYF5Z6prEpTCCmzCXz6eKr/tCBssSmQGEeozA9tkRUty/5Vx06ibaOP9RCrW1Pvb8yp3gvZhHwTDsJw==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.55.3': - resolution: {integrity: sha512-DJay3ep76bKUDImmn//W5SvpjRN5LmK/ntWyeJs/dcnwiiHESd3N4uteK9FDLf0S0W8E6Y0sVRXpOCoQclQqNg==} + '@rollup/rollup-linux-arm64-gnu@4.56.0': + resolution: {integrity: sha512-uQVoKkrC1KGEV6udrdVahASIsaF8h7iLG0U0W+Xn14ucFwi6uS539PsAr24IEF9/FoDtzMeeJXJIBo5RkbNWvQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.55.3': - resolution: {integrity: sha512-BKKWQkY2WgJ5MC/ayvIJTHjy0JUGb5efaHCUiG/39sSUvAYRBaO3+/EK0AZT1RF3pSj86O24GLLik9mAYu0IJg==} + '@rollup/rollup-linux-arm64-musl@4.56.0': + resolution: {integrity: sha512-vLZ1yJKLxhQLFKTs42RwTwa6zkGln+bnXc8ueFGMYmBTLfNu58sl5/eXyxRa2RarTkJbXl8TKPgfS6V5ijNqEA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.55.3': - resolution: {integrity: sha512-Q9nVlWtKAG7ISW80OiZGxTr6rYtyDSkauHUtvkQI6TNOJjFvpj4gcH+KaJihqYInnAzEEUetPQubRwHef4exVg==} + '@rollup/rollup-linux-loong64-gnu@4.56.0': + resolution: {integrity: sha512-FWfHOCub564kSE3xJQLLIC/hbKqHSVxy8vY75/YHHzWvbJL7aYJkdgwD/xGfUlL5UV2SB7otapLrcCj2xnF1dg==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-loong64-musl@4.55.3': - resolution: {integrity: sha512-2H5LmhzrpC4fFRNwknzmmTvvyJPHwESoJgyReXeFoYYuIDfBhP29TEXOkCJE/KxHi27mj7wDUClNq78ue3QEBQ==} + '@rollup/rollup-linux-loong64-musl@4.56.0': + resolution: {integrity: sha512-z1EkujxIh7nbrKL1lmIpqFTc/sr0u8Uk0zK/qIEFldbt6EDKWFk/pxFq3gYj4Bjn3aa9eEhYRlL3H8ZbPT1xvA==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.55.3': - resolution: {integrity: sha512-9S542V0ie9LCTznPYlvaeySwBeIEa7rDBgLHKZ5S9DBgcqdJYburabm8TqiqG6mrdTzfV5uttQRHcbKff9lWtA==} + '@rollup/rollup-linux-ppc64-gnu@4.56.0': + resolution: {integrity: sha512-iNFTluqgdoQC7AIE8Q34R3AuPrJGJirj5wMUErxj22deOcY7XwZRaqYmB6ZKFHoVGqRcRd0mqO+845jAibKCkw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-ppc64-musl@4.55.3': - resolution: {integrity: sha512-ukxw+YH3XXpcezLgbJeasgxyTbdpnNAkrIlFGDl7t+pgCxZ89/6n1a+MxlY7CegU+nDgrgdqDelPRNQ/47zs0g==} + '@rollup/rollup-linux-ppc64-musl@4.56.0': + resolution: {integrity: sha512-MtMeFVlD2LIKjp2sE2xM2slq3Zxf9zwVuw0jemsxvh1QOpHSsSzfNOTH9uYW9i1MXFxUSMmLpeVeUzoNOKBaWg==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.55.3': - resolution: {integrity: sha512-Iauw9UsTTvlF++FhghFJjqYxyXdggXsOqGpFBylaRopVpcbfyIIsNvkf9oGwfgIcf57z3m8+/oSYTo6HutBFNw==} + '@rollup/rollup-linux-riscv64-gnu@4.56.0': + resolution: {integrity: sha512-in+v6wiHdzzVhYKXIk5U74dEZHdKN9KH0Q4ANHOTvyXPG41bajYRsy7a8TPKbYPl34hU7PP7hMVHRvv/5aCSew==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.55.3': - resolution: {integrity: sha512-3OqKAHSEQXKdq9mQ4eajqUgNIK27VZPW3I26EP8miIzuKzCJ3aW3oEn2pzF+4/Hj/Moc0YDsOtBgT5bZ56/vcA==} + '@rollup/rollup-linux-riscv64-musl@4.56.0': + resolution: {integrity: sha512-yni2raKHB8m9NQpI9fPVwN754mn6dHQSbDTwxdr9SE0ks38DTjLMMBjrwvB5+mXrX+C0npX0CVeCUcvvvD8CNQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.55.3': - resolution: {integrity: sha512-0CM8dSVzVIaqMcXIFej8zZrSFLnGrAE8qlNbbHfTw1EEPnFTg1U1ekI0JdzjPyzSfUsHWtodilQQG/RA55berA==} + '@rollup/rollup-linux-s390x-gnu@4.56.0': + resolution: {integrity: sha512-zhLLJx9nQPu7wezbxt2ut+CI4YlXi68ndEve16tPc/iwoylWS9B3FxpLS2PkmfYgDQtosah07Mj9E0khc3Y+vQ==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.55.3': - resolution: {integrity: sha512-+fgJE12FZMIgBaKIAGd45rxf+5ftcycANJRWk8Vz0NnMTM5rADPGuRFTYar+Mqs560xuART7XsX2lSACa1iOmQ==} + '@rollup/rollup-linux-x64-gnu@4.56.0': + resolution: {integrity: sha512-MVC6UDp16ZSH7x4rtuJPAEoE1RwS8N4oK9DLHy3FTEdFoUTCFVzMfJl/BVJ330C+hx8FfprA5Wqx4FhZXkj2Kw==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.55.3': - resolution: {integrity: sha512-tMD7NnbAolWPzQlJQJjVFh/fNH3K/KnA7K8gv2dJWCwwnaK6DFCYST1QXYWfu5V0cDwarWC8Sf/cfMHniNq21A==} + '@rollup/rollup-linux-x64-musl@4.56.0': + resolution: {integrity: sha512-ZhGH1eA4Qv0lxaV00azCIS1ChedK0V32952Md3FtnxSqZTBTd6tgil4nZT5cU8B+SIw3PFYkvyR4FKo2oyZIHA==} cpu: [x64] os: [linux] - '@rollup/rollup-openbsd-x64@4.55.3': - resolution: {integrity: sha512-u5KsqxOxjEeIbn7bUK1MPM34jrnPwjeqgyin4/N6e/KzXKfpE9Mi0nCxcQjaM9lLmPcHmn/xx1yOjgTMtu1jWQ==} + '@rollup/rollup-openbsd-x64@4.56.0': + resolution: {integrity: sha512-O16XcmyDeFI9879pEcmtWvD/2nyxR9mF7Gs44lf1vGGx8Vg2DRNx11aVXBEqOQhWb92WN4z7fW/q4+2NYzCbBA==} cpu: [x64] os: [openbsd] - '@rollup/rollup-openharmony-arm64@4.55.3': - resolution: {integrity: sha512-vo54aXwjpTtsAnb3ca7Yxs9t2INZg7QdXN/7yaoG7nPGbOBXYXQY41Km+S1Ov26vzOAzLcAjmMdjyEqS1JkVhw==} + '@rollup/rollup-openharmony-arm64@4.56.0': + resolution: {integrity: sha512-LhN/Reh+7F3RCgQIRbgw8ZMwUwyqJM+8pXNT6IIJAqm2IdKkzpCh/V9EdgOMBKuebIrzswqy4ATlrDgiOwbRcQ==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.55.3': - resolution: {integrity: sha512-HI+PIVZ+m+9AgpnY3pt6rinUdRYrGHvmVdsNQ4odNqQ/eRF78DVpMR7mOq7nW06QxpczibwBmeQzB68wJ+4W4A==} + '@rollup/rollup-win32-arm64-msvc@4.56.0': + resolution: {integrity: sha512-kbFsOObXp3LBULg1d3JIUQMa9Kv4UitDmpS+k0tinPBz3watcUiV2/LUDMMucA6pZO3WGE27P7DsfaN54l9ing==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.55.3': - resolution: {integrity: sha512-vRByotbdMo3Wdi+8oC2nVxtc3RkkFKrGaok+a62AT8lz/YBuQjaVYAS5Zcs3tPzW43Vsf9J0wehJbUY5xRSekA==} + '@rollup/rollup-win32-ia32-msvc@4.56.0': + resolution: {integrity: sha512-vSSgny54D6P4vf2izbtFm/TcWYedw7f8eBrOiGGecyHyQB9q4Kqentjaj8hToe+995nob/Wv48pDqL5a62EWtg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.55.3': - resolution: {integrity: sha512-POZHq7UeuzMJljC5NjKi8vKMFN6/5EOqcX1yGntNLp7rUTpBAXQ1hW8kWPFxYLv07QMcNM75xqVLGPWQq6TKFA==} + '@rollup/rollup-win32-x64-gnu@4.56.0': + resolution: {integrity: sha512-FeCnkPCTHQJFbiGG49KjV5YGW/8b9rrXAM2Mz2kiIoktq2qsJxRD5giEMEOD2lPdgs72upzefaUvS+nc8E3UzQ==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.55.3': - resolution: {integrity: sha512-aPFONczE4fUFKNXszdvnd2GqKEYQdV5oEsIbKPujJmWlCI9zEsv1Otig8RKK+X9bed9gFUN6LAeN4ZcNuu4zjg==} + '@rollup/rollup-win32-x64-msvc@4.56.0': + resolution: {integrity: sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g==} cpu: [x64] os: [win32] @@ -1896,8 +1898,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@25.0.9': - resolution: {integrity: sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==} + '@types/node@25.0.10': + resolution: {integrity: sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==} '@types/offscreencanvas@2019.7.3': resolution: {integrity: sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==} @@ -1982,11 +1984,11 @@ packages: peerDependencies: vite: ^6.0.0 || ^7.0.0 - '@vitest/expect@4.0.17': - resolution: {integrity: sha512-mEoqP3RqhKlbmUmntNDDCJeTDavDR+fVYkSOw8qRwJFaW/0/5zA9zFeTrHqNtcmwh6j26yMmwx2PqUDPzt5ZAQ==} + '@vitest/expect@4.0.18': + resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==} - '@vitest/mocker@4.0.17': - resolution: {integrity: sha512-+ZtQhLA3lDh1tI2wxe3yMsGzbp7uuJSWBM1iTIKCbppWTSBN09PUC+L+fyNlQApQoR+Ps8twt2pbSSXg2fQVEQ==} + '@vitest/mocker@4.0.18': + resolution: {integrity: sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0-0 @@ -1996,20 +1998,20 @@ packages: vite: optional: true - '@vitest/pretty-format@4.0.17': - resolution: {integrity: sha512-Ah3VAYmjcEdHg6+MwFE17qyLqBHZ+ni2ScKCiW2XrlSBV4H3Z7vYfPfz7CWQ33gyu76oc0Ai36+kgLU3rfF4nw==} + '@vitest/pretty-format@4.0.18': + resolution: {integrity: sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==} - '@vitest/runner@4.0.17': - resolution: {integrity: sha512-JmuQyf8aMWoo/LmNFppdpkfRVHJcsgzkbCA+/Bk7VfNH7RE6Ut2qxegeyx2j3ojtJtKIbIGy3h+KxGfYfk28YQ==} + '@vitest/runner@4.0.18': + resolution: {integrity: sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==} - '@vitest/snapshot@4.0.17': - resolution: {integrity: sha512-npPelD7oyL+YQM2gbIYvlavlMVWUfNNGZPcu0aEUQXt7FXTuqhmgiYupPnAanhKvyP6Srs2pIbWo30K0RbDtRQ==} + '@vitest/snapshot@4.0.18': + resolution: {integrity: sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==} - '@vitest/spy@4.0.17': - resolution: {integrity: sha512-I1bQo8QaP6tZlTomQNWKJE6ym4SHf3oLS7ceNjozxxgzavRAgZDc06T7kD8gb9bXKEgcLNt00Z+kZO6KaJ62Ew==} + '@vitest/spy@4.0.18': + resolution: {integrity: sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==} - '@vitest/utils@4.0.17': - resolution: {integrity: sha512-RG6iy+IzQpa9SB8HAFHJ9Y+pTzI+h8553MrciN9eC6TFBErqrQaTas4vG+MVj8S4uKk8uTT2p0vgZPnTdxd96w==} + '@vitest/utils@4.0.18': + resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} '@yarnpkg/lockfile@1.1.0': resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} @@ -2095,6 +2097,9 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + appwrite@21.5.0: + resolution: {integrity: sha512-643bMRZVYXMluXvSXbdaLAi9qqTJLWbVGguKH4vH6IdKHur6gGIirhCOqAEt33pV4TOFJ55VBu8c/+Ft1ke2SA==} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -2123,8 +2128,8 @@ packages: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} engines: {node: ^4.5.0 || >= 5.9} - baseline-browser-mapping@2.9.16: - resolution: {integrity: sha512-KeUZdBuxngy825i8xvzaK1Ncnkx0tBmb3k8DkEuqjKRkmtvNTjey2ZsNeh8Dw4lfKvbCOu9oeNx2TKm2vHqcRw==} + baseline-browser-mapping@2.9.17: + resolution: {integrity: sha512-agD0MgJFUP/4nvjqzIB29zRPUuCF7Ge6mEv9s8dHrtYD7QWXRcx75rOADE/d5ah1NI+0vkDl0yorDd5U852IQQ==} hasBin: true beasties@0.3.5: @@ -2471,8 +2476,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.267: - resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} + electron-to-chromium@1.5.277: + resolution: {integrity: sha512-wKXFZw4erWmmOz5N/grBoJ2XrNJGDFMu2+W5ACHza5rHtvsqrK4gb6rnLC7XxKB9WlJ+RmyQatuEXmtm86xbnw==} emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -2511,6 +2516,10 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -2816,8 +2825,8 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - hono@4.11.4: - resolution: {integrity: sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==} + hono@4.11.5: + resolution: {integrity: sha512-WemPi9/WfyMwZs+ZUXdiwcCh9Y+m7L+8vki9MzDw3jJ+W9Lc+12HGsd368Qc1vZi1xwW8BWMMsnK5efYKPdt4g==} engines: {node: '>=16.9.0'} hosted-git-info@9.0.2: @@ -2831,8 +2840,8 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - htmlparser2@10.0.0: - resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} + htmlparser2@10.1.0: + resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} http-cache-semantics@4.2.0: resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} @@ -3094,8 +3103,8 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + lodash@4.17.23: + resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} log-symbols@7.0.1: resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==} @@ -3279,8 +3288,8 @@ packages: resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} - ng-zorro-antd@21.0.1: - resolution: {integrity: sha512-YmtY+fs0enefvYgXJRfY125Qo3Oyx96t0fLGyRqVdNFaxXMYVoBIfyneMkxQt190sMsIaWB/z/QNcnWRbu+pNg==} + ng-zorro-antd@21.0.2: + resolution: {integrity: sha512-Nn6x8x3pUXBVTfab1c7BYPqiK8Bp9WLgHbJ6Fja5T9EKeMiCWj4zJOvFRT2JKSnNBGQtxLzHr2KOkehIfhmk/A==} peerDependencies: '@angular/common': ^21.0.0 '@angular/core': '>=21.0.7' @@ -3627,8 +3636,8 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - rollup@4.55.3: - resolution: {integrity: sha512-y9yUpfQvetAjiDLtNMf1hL9NXchIJgWt6zIKeoB+tCd3npX08Eqfzg60V9DhIGVMtQ0AlMkFw5xa+AQ37zxnAA==} + rollup@4.56.0: + resolution: {integrity: sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -4032,58 +4041,18 @@ packages: yaml: optional: true - vite@7.3.1: - resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - '@types/node': ^20.19.0 || >=22.12.0 - jiti: '>=1.21.0' - less: ^4.0.0 - lightningcss: ^1.21.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: '>=0.54.8' - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - - vitest@4.0.17: - resolution: {integrity: sha512-FQMeF0DJdWY0iOnbv466n/0BudNdKj1l5jYgl5JVTwjSsZSlqyXFt/9+1sEyhR6CLowbZpV7O1sCHrzBhucKKg==} + vitest@4.0.18: + resolution: {integrity: sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.0.17 - '@vitest/browser-preview': 4.0.17 - '@vitest/browser-webdriverio': 4.0.17 - '@vitest/ui': 4.0.17 + '@vitest/browser-playwright': 4.0.18 + '@vitest/browser-preview': 4.0.18 + '@vitest/browser-webdriverio': 4.0.18 + '@vitest/ui': 4.0.18 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -4208,18 +4177,6 @@ packages: utf-8-validate: optional: true - ws@8.19.0: - resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -4383,9 +4340,9 @@ snapshots: transitivePeerDependencies: - chokidar - '@angular-devkit/architect@0.2101.0': + '@angular-devkit/architect@0.2101.1': dependencies: - '@angular-devkit/core': 21.1.0 + '@angular-devkit/core': 21.1.1 rxjs: 7.8.2 transitivePeerDependencies: - chokidar @@ -4399,7 +4356,7 @@ snapshots: rxjs: 7.8.2 source-map: 0.7.6 - '@angular-devkit/core@21.1.0': + '@angular-devkit/core@21.1.1': dependencies: ajv: 8.17.1 ajv-formats: 3.0.1(ajv@8.17.1) @@ -4418,9 +4375,9 @@ snapshots: transitivePeerDependencies: - chokidar - '@angular-devkit/schematics@21.1.0': + '@angular-devkit/schematics@21.1.1': dependencies: - '@angular-devkit/core': 21.1.0 + '@angular-devkit/core': 21.1.1 jsonc-parser: 3.3.1 magic-string: 0.30.21 ora: 9.0.0 @@ -4428,11 +4385,11 @@ snapshots: transitivePeerDependencies: - chokidar - '@angular-eslint/builder@21.1.0(@angular/cli@21.0.6(@types/node@25.0.9)(hono@4.11.4))(eslint@9.39.2)(typescript@5.9.3)': + '@angular-eslint/builder@21.1.0(@angular/cli@21.0.6(@types/node@25.0.10)(hono@4.11.5))(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@angular-devkit/architect': 0.2101.0 - '@angular-devkit/core': 21.1.0 - '@angular/cli': 21.0.6(@types/node@25.0.9)(hono@4.11.4) + '@angular-devkit/architect': 0.2101.1 + '@angular-devkit/core': 21.1.1 + '@angular/cli': 21.0.6(@types/node@25.0.10)(hono@4.11.5) eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: @@ -4461,13 +4418,13 @@ snapshots: ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 - '@angular-eslint/schematics@21.1.0(@angular-eslint/template-parser@21.1.0(eslint@9.39.2)(typescript@5.9.3))(@angular/cli@21.0.6(@types/node@25.0.9)(hono@4.11.4))(@typescript-eslint/types@8.53.1)(@typescript-eslint/utils@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': + '@angular-eslint/schematics@21.1.0(@angular-eslint/template-parser@21.1.0(eslint@9.39.2)(typescript@5.9.3))(@angular/cli@21.0.6(@types/node@25.0.10)(hono@4.11.5))(@typescript-eslint/types@8.53.1)(@typescript-eslint/utils@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@angular-devkit/core': 21.1.0 - '@angular-devkit/schematics': 21.1.0 + '@angular-devkit/core': 21.1.1 + '@angular-devkit/schematics': 21.1.1 '@angular-eslint/eslint-plugin': 21.1.0(@typescript-eslint/utils@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) '@angular-eslint/eslint-plugin-template': 21.1.0(@angular-eslint/template-parser@21.1.0(eslint@9.39.2)(typescript@5.9.3))(@typescript-eslint/types@8.53.1)(@typescript-eslint/utils@8.53.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) - '@angular/cli': 21.0.6(@types/node@25.0.9)(hono@4.11.4) + '@angular/cli': 21.0.6(@types/node@25.0.10)(hono@4.11.5) ignore: 7.0.5 semver: 7.7.3 strip-json-comments: 3.1.1 @@ -4493,22 +4450,22 @@ snapshots: eslint: 9.39.2 typescript: 5.9.3 - '@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))': + '@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))': dependencies: - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) tslib: 2.8.1 - '@angular/build@21.1.0(@angular/compiler-cli@21.1.0(@angular/compiler@21.1.0)(typescript@5.9.3))(@angular/compiler@21.1.0)(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@types/node@25.0.9)(karma@6.4.4)(postcss@8.5.6)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.0.17(@types/node@25.0.9)(jsdom@27.4.0)(sass@1.97.1))': + '@angular/build@21.1.1(@angular/compiler-cli@21.1.1(@angular/compiler@21.1.1)(typescript@5.9.3))(@angular/compiler@21.1.1)(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@types/node@25.0.10)(karma@6.4.4)(postcss@8.5.6)(tslib@2.8.1)(typescript@5.9.3)(vitest@4.0.18(@types/node@25.0.10)(jsdom@27.4.0)(sass@1.97.1))': dependencies: '@ampproject/remapping': 2.3.0 - '@angular-devkit/architect': 0.2101.0 - '@angular/compiler': 21.1.0 - '@angular/compiler-cli': 21.1.0(@angular/compiler@21.1.0)(typescript@5.9.3) + '@angular-devkit/architect': 0.2101.1 + '@angular/compiler': 21.1.1 + '@angular/compiler-cli': 21.1.1(@angular/compiler@21.1.1)(typescript@5.9.3) '@babel/core': 7.28.5 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-split-export-declaration': 7.24.7 - '@inquirer/confirm': 5.1.21(@types/node@25.0.9) - '@vitejs/plugin-basic-ssl': 2.1.0(vite@7.3.0(@types/node@25.0.9)(sass@1.97.1)) + '@inquirer/confirm': 5.1.21(@types/node@25.0.10) + '@vitejs/plugin-basic-ssl': 2.1.0(vite@7.3.0(@types/node@25.0.10)(sass@1.97.1)) beasties: 0.3.5 browserslist: 4.28.1 esbuild: 0.27.2 @@ -4529,15 +4486,15 @@ snapshots: tslib: 2.8.1 typescript: 5.9.3 undici: 7.18.2 - vite: 7.3.0(@types/node@25.0.9)(sass@1.97.1) + vite: 7.3.0(@types/node@25.0.10)(sass@1.97.1) watchpack: 2.5.0 optionalDependencies: - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) karma: 6.4.4 lmdb: 3.4.4 postcss: 8.5.6 - vitest: 4.0.17(@types/node@25.0.9)(jsdom@27.4.0)(sass@1.97.1) + vitest: 4.0.18(@types/node@25.0.10)(jsdom@27.4.0)(sass@1.97.1) transitivePeerDependencies: - '@types/node' - chokidar @@ -4551,23 +4508,23 @@ snapshots: - tsx - yaml - '@angular/cdk@21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': + '@angular/cdk@21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': dependencies: - '@angular/common': 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/common': 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) parse5: 8.0.0 rxjs: 7.8.2 tslib: 2.8.1 - '@angular/cli@21.0.6(@types/node@25.0.9)(hono@4.11.4)': + '@angular/cli@21.0.6(@types/node@25.0.10)(hono@4.11.5)': dependencies: '@angular-devkit/architect': 0.2100.6 '@angular-devkit/core': 21.0.6 '@angular-devkit/schematics': 21.0.6 - '@inquirer/prompts': 7.9.0(@types/node@25.0.9) - '@listr2/prompt-adapter-inquirer': 3.0.5(@inquirer/prompts@7.9.0(@types/node@25.0.9))(@types/node@25.0.9)(listr2@9.0.5) - '@modelcontextprotocol/sdk': 1.25.2(hono@4.11.4)(zod@4.1.13) + '@inquirer/prompts': 7.9.0(@types/node@25.0.10) + '@listr2/prompt-adapter-inquirer': 3.0.5(@inquirer/prompts@7.9.0(@types/node@25.0.10))(@types/node@25.0.10)(listr2@9.0.5) + '@modelcontextprotocol/sdk': 1.25.2(hono@4.11.5)(zod@4.1.13) '@schematics/angular': 21.0.6 '@yarnpkg/lockfile': 1.1.0 algoliasearch: 5.40.1 @@ -4588,15 +4545,15 @@ snapshots: - hono - supports-color - '@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': + '@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2)': dependencies: - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/compiler-cli@21.1.0(@angular/compiler@21.1.0)(typescript@5.9.3)': + '@angular/compiler-cli@21.1.1(@angular/compiler@21.1.1)(typescript@5.9.3)': dependencies: - '@angular/compiler': 21.1.0 + '@angular/compiler': 21.1.1 '@babel/core': 7.28.5 '@jridgewell/sourcemap-codec': 1.5.5 chokidar: 5.0.0 @@ -4610,48 +4567,48 @@ snapshots: transitivePeerDependencies: - supports-color - '@angular/compiler@21.1.0': + '@angular/compiler@21.1.1': dependencies: tslib: 2.8.1 - '@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)': + '@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)': dependencies: rxjs: 7.8.2 tslib: 2.8.1 optionalDependencies: - '@angular/compiler': 21.1.0 + '@angular/compiler': 21.1.1 zone.js: 0.15.1 - '@angular/forms@21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': + '@angular/forms@21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': dependencies: - '@angular/common': 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/common': 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) '@standard-schema/spec': 1.1.0 rxjs: 7.8.2 tslib: 2.8.1 - '@angular/platform-browser-dynamic@21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@21.1.0)(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))': + '@angular/platform-browser-dynamic@21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/compiler@21.1.1)(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))': dependencies: - '@angular/common': 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/compiler': 21.1.0 - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/common': 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/compiler': 21.1.1 + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) tslib: 2.8.1 - '@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))': + '@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))': dependencies: - '@angular/common': 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/common': 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) tslib: 2.8.1 optionalDependencies: - '@angular/animations': 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/animations': 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) - '@angular/router@21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': + '@angular/router@21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': dependencies: - '@angular/common': 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/common': 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) rxjs: 7.8.2 tslib: 2.8.1 @@ -4663,11 +4620,11 @@ snapshots: dependencies: '@babel/runtime': 7.28.6 - '@ant-design/icons-angular@21.0.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': + '@ant-design/icons-angular@21.0.0(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2)': dependencies: - '@angular/common': 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/platform-browser': 21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/common': 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/platform-browser': 21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) '@ant-design/colors': 7.2.1 rxjs: 7.8.2 tslib: 2.8.1 @@ -4821,7 +4778,7 @@ snapshots: dependencies: '@csstools/css-tokenizer': 3.0.4 - '@csstools/css-syntax-patches-for-csstree@1.0.25': {} + '@csstools/css-syntax-patches-for-csstree@1.0.26': {} '@csstools/css-tokenizer@3.0.4': {} @@ -5056,11 +5013,11 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 - '@exodus/bytes@1.9.0': {} + '@exodus/bytes@1.10.0': {} - '@hono/node-server@1.19.9(hono@4.11.4)': + '@hono/node-server@1.19.9(hono@4.11.5)': dependencies: - hono: 4.11.4 + hono: 4.11.5 '@humanfs/core@0.19.1': {} @@ -5075,128 +5032,128 @@ snapshots: '@inquirer/ansi@1.0.2': {} - '@inquirer/checkbox@4.3.2(@types/node@25.0.9)': + '@inquirer/checkbox@4.3.2(@types/node@25.0.10)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@25.0.9) + '@inquirer/core': 10.3.2(@types/node@25.0.10) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@25.0.9) + '@inquirer/type': 3.0.10(@types/node@25.0.10) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 - '@inquirer/confirm@5.1.21(@types/node@25.0.9)': + '@inquirer/confirm@5.1.21(@types/node@25.0.10)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.0.9) - '@inquirer/type': 3.0.10(@types/node@25.0.9) + '@inquirer/core': 10.3.2(@types/node@25.0.10) + '@inquirer/type': 3.0.10(@types/node@25.0.10) optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 - '@inquirer/core@10.3.2(@types/node@25.0.9)': + '@inquirer/core@10.3.2(@types/node@25.0.10)': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@25.0.9) + '@inquirer/type': 3.0.10(@types/node@25.0.10) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 - '@inquirer/editor@4.2.23(@types/node@25.0.9)': + '@inquirer/editor@4.2.23(@types/node@25.0.10)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.0.9) - '@inquirer/external-editor': 1.0.3(@types/node@25.0.9) - '@inquirer/type': 3.0.10(@types/node@25.0.9) + '@inquirer/core': 10.3.2(@types/node@25.0.10) + '@inquirer/external-editor': 1.0.3(@types/node@25.0.10) + '@inquirer/type': 3.0.10(@types/node@25.0.10) optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 - '@inquirer/expand@4.0.23(@types/node@25.0.9)': + '@inquirer/expand@4.0.23(@types/node@25.0.10)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.0.9) - '@inquirer/type': 3.0.10(@types/node@25.0.9) + '@inquirer/core': 10.3.2(@types/node@25.0.10) + '@inquirer/type': 3.0.10(@types/node@25.0.10) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 - '@inquirer/external-editor@1.0.3(@types/node@25.0.9)': + '@inquirer/external-editor@1.0.3(@types/node@25.0.10)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 '@inquirer/figures@1.0.15': {} - '@inquirer/input@4.3.1(@types/node@25.0.9)': + '@inquirer/input@4.3.1(@types/node@25.0.10)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.0.9) - '@inquirer/type': 3.0.10(@types/node@25.0.9) + '@inquirer/core': 10.3.2(@types/node@25.0.10) + '@inquirer/type': 3.0.10(@types/node@25.0.10) optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 - '@inquirer/number@3.0.23(@types/node@25.0.9)': + '@inquirer/number@3.0.23(@types/node@25.0.10)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.0.9) - '@inquirer/type': 3.0.10(@types/node@25.0.9) + '@inquirer/core': 10.3.2(@types/node@25.0.10) + '@inquirer/type': 3.0.10(@types/node@25.0.10) optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 - '@inquirer/password@4.0.23(@types/node@25.0.9)': + '@inquirer/password@4.0.23(@types/node@25.0.10)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@25.0.9) - '@inquirer/type': 3.0.10(@types/node@25.0.9) + '@inquirer/core': 10.3.2(@types/node@25.0.10) + '@inquirer/type': 3.0.10(@types/node@25.0.10) optionalDependencies: - '@types/node': 25.0.9 - - '@inquirer/prompts@7.9.0(@types/node@25.0.9)': - dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@25.0.9) - '@inquirer/confirm': 5.1.21(@types/node@25.0.9) - '@inquirer/editor': 4.2.23(@types/node@25.0.9) - '@inquirer/expand': 4.0.23(@types/node@25.0.9) - '@inquirer/input': 4.3.1(@types/node@25.0.9) - '@inquirer/number': 3.0.23(@types/node@25.0.9) - '@inquirer/password': 4.0.23(@types/node@25.0.9) - '@inquirer/rawlist': 4.1.11(@types/node@25.0.9) - '@inquirer/search': 3.2.2(@types/node@25.0.9) - '@inquirer/select': 4.4.2(@types/node@25.0.9) + '@types/node': 25.0.10 + + '@inquirer/prompts@7.9.0(@types/node@25.0.10)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@25.0.10) + '@inquirer/confirm': 5.1.21(@types/node@25.0.10) + '@inquirer/editor': 4.2.23(@types/node@25.0.10) + '@inquirer/expand': 4.0.23(@types/node@25.0.10) + '@inquirer/input': 4.3.1(@types/node@25.0.10) + '@inquirer/number': 3.0.23(@types/node@25.0.10) + '@inquirer/password': 4.0.23(@types/node@25.0.10) + '@inquirer/rawlist': 4.1.11(@types/node@25.0.10) + '@inquirer/search': 3.2.2(@types/node@25.0.10) + '@inquirer/select': 4.4.2(@types/node@25.0.10) optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 - '@inquirer/rawlist@4.1.11(@types/node@25.0.9)': + '@inquirer/rawlist@4.1.11(@types/node@25.0.10)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.0.9) - '@inquirer/type': 3.0.10(@types/node@25.0.9) + '@inquirer/core': 10.3.2(@types/node@25.0.10) + '@inquirer/type': 3.0.10(@types/node@25.0.10) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 - '@inquirer/search@3.2.2(@types/node@25.0.9)': + '@inquirer/search@3.2.2(@types/node@25.0.10)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.0.9) + '@inquirer/core': 10.3.2(@types/node@25.0.10) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@25.0.9) + '@inquirer/type': 3.0.10(@types/node@25.0.10) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 - '@inquirer/select@4.4.2(@types/node@25.0.9)': + '@inquirer/select@4.4.2(@types/node@25.0.10)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@25.0.9) + '@inquirer/core': 10.3.2(@types/node@25.0.10) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@25.0.9) + '@inquirer/type': 3.0.10(@types/node@25.0.10) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 - '@inquirer/type@3.0.10(@types/node@25.0.9)': + '@inquirer/type@3.0.10(@types/node@25.0.10)': optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 '@isaacs/balanced-match@4.0.1': {} @@ -5229,10 +5186,10 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@listr2/prompt-adapter-inquirer@3.0.5(@inquirer/prompts@7.9.0(@types/node@25.0.9))(@types/node@25.0.9)(listr2@9.0.5)': + '@listr2/prompt-adapter-inquirer@3.0.5(@inquirer/prompts@7.9.0(@types/node@25.0.10))(@types/node@25.0.10)(listr2@9.0.5)': dependencies: - '@inquirer/prompts': 7.9.0(@types/node@25.0.9) - '@inquirer/type': 3.0.10(@types/node@25.0.9) + '@inquirer/prompts': 7.9.0(@types/node@25.0.10) + '@inquirer/type': 3.0.10(@types/node@25.0.10) listr2: 9.0.5 transitivePeerDependencies: - '@types/node' @@ -5516,9 +5473,9 @@ snapshots: dependencies: '@math.gl/core': 4.1.0 - '@modelcontextprotocol/sdk@1.25.2(hono@4.11.4)(zod@4.1.13)': + '@modelcontextprotocol/sdk@1.25.2(hono@4.11.5)(zod@4.1.13)': dependencies: - '@hono/node-server': 1.19.9(hono@4.11.4) + '@hono/node-server': 1.19.9(hono@4.11.5) ajv: 8.17.1 ajv-formats: 3.0.1(ajv@8.17.1) content-type: 1.0.5 @@ -5834,79 +5791,79 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.58': {} - '@rollup/rollup-android-arm-eabi@4.55.3': + '@rollup/rollup-android-arm-eabi@4.56.0': optional: true - '@rollup/rollup-android-arm64@4.55.3': + '@rollup/rollup-android-arm64@4.56.0': optional: true - '@rollup/rollup-darwin-arm64@4.55.3': + '@rollup/rollup-darwin-arm64@4.56.0': optional: true - '@rollup/rollup-darwin-x64@4.55.3': + '@rollup/rollup-darwin-x64@4.56.0': optional: true - '@rollup/rollup-freebsd-arm64@4.55.3': + '@rollup/rollup-freebsd-arm64@4.56.0': optional: true - '@rollup/rollup-freebsd-x64@4.55.3': + '@rollup/rollup-freebsd-x64@4.56.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.55.3': + '@rollup/rollup-linux-arm-gnueabihf@4.56.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.55.3': + '@rollup/rollup-linux-arm-musleabihf@4.56.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.55.3': + '@rollup/rollup-linux-arm64-gnu@4.56.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.55.3': + '@rollup/rollup-linux-arm64-musl@4.56.0': optional: true - '@rollup/rollup-linux-loong64-gnu@4.55.3': + '@rollup/rollup-linux-loong64-gnu@4.56.0': optional: true - '@rollup/rollup-linux-loong64-musl@4.55.3': + '@rollup/rollup-linux-loong64-musl@4.56.0': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.55.3': + '@rollup/rollup-linux-ppc64-gnu@4.56.0': optional: true - '@rollup/rollup-linux-ppc64-musl@4.55.3': + '@rollup/rollup-linux-ppc64-musl@4.56.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.55.3': + '@rollup/rollup-linux-riscv64-gnu@4.56.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.55.3': + '@rollup/rollup-linux-riscv64-musl@4.56.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.55.3': + '@rollup/rollup-linux-s390x-gnu@4.56.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.55.3': + '@rollup/rollup-linux-x64-gnu@4.56.0': optional: true - '@rollup/rollup-linux-x64-musl@4.55.3': + '@rollup/rollup-linux-x64-musl@4.56.0': optional: true - '@rollup/rollup-openbsd-x64@4.55.3': + '@rollup/rollup-openbsd-x64@4.56.0': optional: true - '@rollup/rollup-openharmony-arm64@4.55.3': + '@rollup/rollup-openharmony-arm64@4.56.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.55.3': + '@rollup/rollup-win32-arm64-msvc@4.56.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.55.3': + '@rollup/rollup-win32-ia32-msvc@4.56.0': optional: true - '@rollup/rollup-win32-x64-gnu@4.55.3': + '@rollup/rollup-win32-x64-gnu@4.56.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.55.3': + '@rollup/rollup-win32-x64-msvc@4.56.0': optional: true '@schematics/angular@21.0.6': @@ -5999,7 +5956,7 @@ snapshots: '@types/brotli@1.3.4': dependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 '@types/chai@5.2.3': dependencies: @@ -6008,7 +5965,7 @@ snapshots: '@types/cors@2.8.19': dependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 optional: true '@types/crypto-js@4.2.2': {} @@ -6035,7 +5992,7 @@ snapshots: '@types/json-schema@7.0.15': {} - '@types/node@25.0.9': + '@types/node@25.0.10': dependencies: undici-types: 7.16.0 @@ -6045,7 +6002,7 @@ snapshots: '@types/papaparse@5.5.2': dependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 '@types/plotly.js-basic-dist-min@2.12.4': dependencies: @@ -6148,47 +6105,47 @@ snapshots: '@typescript-eslint/types': 8.53.1 eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-basic-ssl@2.1.0(vite@7.3.0(@types/node@25.0.9)(sass@1.97.1))': + '@vitejs/plugin-basic-ssl@2.1.0(vite@7.3.0(@types/node@25.0.10)(sass@1.97.1))': dependencies: - vite: 7.3.0(@types/node@25.0.9)(sass@1.97.1) + vite: 7.3.0(@types/node@25.0.10)(sass@1.97.1) - '@vitest/expect@4.0.17': + '@vitest/expect@4.0.18': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.0.17 - '@vitest/utils': 4.0.17 + '@vitest/spy': 4.0.18 + '@vitest/utils': 4.0.18 chai: 6.2.2 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.17(vite@7.3.1(@types/node@25.0.9)(sass@1.97.1))': + '@vitest/mocker@4.0.18(vite@7.3.0(@types/node@25.0.10)(sass@1.97.1))': dependencies: - '@vitest/spy': 4.0.17 + '@vitest/spy': 4.0.18 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@25.0.9)(sass@1.97.1) + vite: 7.3.0(@types/node@25.0.10)(sass@1.97.1) - '@vitest/pretty-format@4.0.17': + '@vitest/pretty-format@4.0.18': dependencies: tinyrainbow: 3.0.3 - '@vitest/runner@4.0.17': + '@vitest/runner@4.0.18': dependencies: - '@vitest/utils': 4.0.17 + '@vitest/utils': 4.0.18 pathe: 2.0.3 - '@vitest/snapshot@4.0.17': + '@vitest/snapshot@4.0.18': dependencies: - '@vitest/pretty-format': 4.0.17 + '@vitest/pretty-format': 4.0.18 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.0.17': {} + '@vitest/spy@4.0.18': {} - '@vitest/utils@4.0.17': + '@vitest/utils@4.0.18': dependencies: - '@vitest/pretty-format': 4.0.17 + '@vitest/pretty-format': 4.0.18 tinyrainbow: 3.0.3 '@yarnpkg/lockfile@1.1.0': {} @@ -6257,10 +6214,10 @@ snapshots: '@algolia/requester-fetch': 5.40.1 '@algolia/requester-node-http': 5.40.1 - angular-plotly.js@20.0.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)): + angular-plotly.js@20.0.0(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)): dependencies: - '@angular/common': 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/common': 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) tslib: 2.8.1 ansi-escapes@7.2.0: @@ -6283,6 +6240,8 @@ snapshots: picomatch: 2.3.1 optional: true + appwrite@21.5.0: {} + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -6303,7 +6262,7 @@ snapshots: base64id@2.0.0: optional: true - baseline-browser-mapping@2.9.16: {} + baseline-browser-mapping@2.9.17: {} beasties@0.3.5: dependencies: @@ -6311,7 +6270,7 @@ snapshots: css-what: 7.0.0 dom-serializer: 2.0.0 domhandler: 5.0.3 - htmlparser2: 10.0.0 + htmlparser2: 10.1.0 picocolors: 1.1.1 postcss: 8.5.6 postcss-media-query-parser: 0.2.3 @@ -6384,9 +6343,9 @@ snapshots: browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.9.16 + baseline-browser-mapping: 2.9.17 caniuse-lite: 1.0.30001765 - electron-to-chromium: 1.5.267 + electron-to-chromium: 1.5.277 node-releases: 2.0.27 update-browserslist-db: 1.2.3(browserslist@4.28.1) @@ -6560,7 +6519,7 @@ snapshots: cssstyle@5.3.7: dependencies: '@asamuzakjp/css-color': 4.1.1 - '@csstools/css-syntax-patches-for-csstree': 1.0.25 + '@csstools/css-syntax-patches-for-csstree': 1.0.26 css-tree: 3.1.0 lru-cache: 11.2.4 @@ -6687,7 +6646,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.267: {} + electron-to-chromium@1.5.277: {} emoji-regex@10.6.0: {} @@ -6709,7 +6668,7 @@ snapshots: engine.io@6.6.5: dependencies: '@types/cors': 2.8.19 - '@types/node': 25.0.9 + '@types/node': 25.0.10 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.7.2 @@ -6735,6 +6694,8 @@ snapshots: entities@6.0.1: {} + entities@7.0.1: {} + env-paths@2.2.1: {} environment@1.1.0: {} @@ -7091,7 +7052,7 @@ snapshots: dependencies: function-bind: 1.1.2 - hono@4.11.4: {} + hono@4.11.5: {} hosted-git-info@9.0.2: dependencies: @@ -7099,18 +7060,18 @@ snapshots: html-encoding-sniffer@6.0.0: dependencies: - '@exodus/bytes': 1.9.0 + '@exodus/bytes': 1.10.0 transitivePeerDependencies: - '@noble/hashes' html-escaper@2.0.2: {} - htmlparser2@10.0.0: + htmlparser2@10.1.0: dependencies: domelementtype: 2.3.0 domhandler: 5.0.3 domutils: 3.2.2 - entities: 6.0.1 + entities: 7.0.1 http-cache-semantics@4.2.0: {} @@ -7276,7 +7237,7 @@ snapshots: dependencies: '@acemir/cssom': 0.9.31 '@asamuzakjp/dom-selector': 6.7.6 - '@exodus/bytes': 1.9.0 + '@exodus/bytes': 1.10.0 cssstyle: 5.3.7 data-urls: 6.0.1 decimal.js: 10.6.0 @@ -7292,7 +7253,7 @@ snapshots: webidl-conversions: 8.0.1 whatwg-mimetype: 4.0.0 whatwg-url: 15.1.0 - ws: 8.19.0 + ws: 8.18.3 xml-name-validator: 5.0.0 transitivePeerDependencies: - '@noble/hashes' @@ -7345,7 +7306,7 @@ snapshots: graceful-fs: 4.2.11 http-proxy: 1.18.1 isbinaryfile: 4.0.10 - lodash: 4.17.21 + lodash: 4.17.23 log4js: 6.9.1 mime: 2.6.0 minimatch: 3.1.2 @@ -7412,7 +7373,7 @@ snapshots: lodash.merge@4.6.2: {} - lodash@4.17.21: + lodash@4.17.23: optional: true log-symbols@7.0.1: @@ -7607,25 +7568,25 @@ snapshots: negotiator@1.0.0: {} - ng-zorro-antd@21.0.1(aa0c172d237a76dfd030999360bc015e): + ng-zorro-antd@21.0.2(3ffaf799d29488433d7e632450beace1): dependencies: - '@angular/cdk': 21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) - '@angular/common': 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/forms': 21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) - '@angular/platform-browser': 21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) - '@angular/router': 21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) - '@ant-design/icons-angular': 21.0.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + '@angular/cdk': 21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + '@angular/common': 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/forms': 21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + '@angular/platform-browser': 21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/router': 21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + '@ant-design/icons-angular': 21.0.0(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@ctrl/tinycolor': 3.6.1 date-fns: 2.30.0 tslib: 2.8.1 transitivePeerDependencies: - rxjs - ngx-select-dropdown@3.3.2(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)): + ngx-select-dropdown@3.3.2(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)): dependencies: - '@angular/common': 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/common': 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) tslib: 2.8.1 node-addon-api@6.1.0: @@ -7868,14 +7829,14 @@ snapshots: prelude-ls@1.2.1: {} - primeng@21.0.4(f5f9118e2d83aa9e57b7d3e1b08b23a5): + primeng@21.0.4(ee84ac0261975de6e3068975b2af45d9): dependencies: - '@angular/cdk': 21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) - '@angular/common': 21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) - '@angular/core': 21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1) - '@angular/forms': 21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) - '@angular/platform-browser': 21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)) - '@angular/router': 21.1.0(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.0(@angular/animations@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.0(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.0(@angular/compiler@21.1.0)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + '@angular/cdk': 21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + '@angular/common': 21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) + '@angular/core': 21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1) + '@angular/forms': 21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) + '@angular/platform-browser': 21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)) + '@angular/router': 21.1.1(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(@angular/platform-browser@21.1.1(@angular/animations@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(@angular/common@21.1.1(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2))(@angular/core@21.1.1(@angular/compiler@21.1.1)(rxjs@7.8.2)(zone.js@0.15.1)))(rxjs@7.8.2) '@primeuix/motion': 0.0.10 '@primeuix/styled': 0.7.4 '@primeuix/styles': 2.0.3 @@ -8004,35 +7965,35 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.58 '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.58 - rollup@4.55.3: + rollup@4.56.0: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.55.3 - '@rollup/rollup-android-arm64': 4.55.3 - '@rollup/rollup-darwin-arm64': 4.55.3 - '@rollup/rollup-darwin-x64': 4.55.3 - '@rollup/rollup-freebsd-arm64': 4.55.3 - '@rollup/rollup-freebsd-x64': 4.55.3 - '@rollup/rollup-linux-arm-gnueabihf': 4.55.3 - '@rollup/rollup-linux-arm-musleabihf': 4.55.3 - '@rollup/rollup-linux-arm64-gnu': 4.55.3 - '@rollup/rollup-linux-arm64-musl': 4.55.3 - '@rollup/rollup-linux-loong64-gnu': 4.55.3 - '@rollup/rollup-linux-loong64-musl': 4.55.3 - '@rollup/rollup-linux-ppc64-gnu': 4.55.3 - '@rollup/rollup-linux-ppc64-musl': 4.55.3 - '@rollup/rollup-linux-riscv64-gnu': 4.55.3 - '@rollup/rollup-linux-riscv64-musl': 4.55.3 - '@rollup/rollup-linux-s390x-gnu': 4.55.3 - '@rollup/rollup-linux-x64-gnu': 4.55.3 - '@rollup/rollup-linux-x64-musl': 4.55.3 - '@rollup/rollup-openbsd-x64': 4.55.3 - '@rollup/rollup-openharmony-arm64': 4.55.3 - '@rollup/rollup-win32-arm64-msvc': 4.55.3 - '@rollup/rollup-win32-ia32-msvc': 4.55.3 - '@rollup/rollup-win32-x64-gnu': 4.55.3 - '@rollup/rollup-win32-x64-msvc': 4.55.3 + '@rollup/rollup-android-arm-eabi': 4.56.0 + '@rollup/rollup-android-arm64': 4.56.0 + '@rollup/rollup-darwin-arm64': 4.56.0 + '@rollup/rollup-darwin-x64': 4.56.0 + '@rollup/rollup-freebsd-arm64': 4.56.0 + '@rollup/rollup-freebsd-x64': 4.56.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.56.0 + '@rollup/rollup-linux-arm-musleabihf': 4.56.0 + '@rollup/rollup-linux-arm64-gnu': 4.56.0 + '@rollup/rollup-linux-arm64-musl': 4.56.0 + '@rollup/rollup-linux-loong64-gnu': 4.56.0 + '@rollup/rollup-linux-loong64-musl': 4.56.0 + '@rollup/rollup-linux-ppc64-gnu': 4.56.0 + '@rollup/rollup-linux-ppc64-musl': 4.56.0 + '@rollup/rollup-linux-riscv64-gnu': 4.56.0 + '@rollup/rollup-linux-riscv64-musl': 4.56.0 + '@rollup/rollup-linux-s390x-gnu': 4.56.0 + '@rollup/rollup-linux-x64-gnu': 4.56.0 + '@rollup/rollup-linux-x64-musl': 4.56.0 + '@rollup/rollup-openbsd-x64': 4.56.0 + '@rollup/rollup-openharmony-arm64': 4.56.0 + '@rollup/rollup-win32-arm64-msvc': 4.56.0 + '@rollup/rollup-win32-ia32-msvc': 4.56.0 + '@rollup/rollup-win32-x64-gnu': 4.56.0 + '@rollup/rollup-win32-x64-msvc': 4.56.0 fsevents: 2.3.3 router@2.2.0: @@ -8439,41 +8400,28 @@ snapshots: vary@1.1.2: {} - vite@7.3.0(@types/node@25.0.9)(sass@1.97.1): + vite@7.3.0(@types/node@25.0.10)(sass@1.97.1): dependencies: esbuild: 0.27.2 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.55.3 + rollup: 4.56.0 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 fsevents: 2.3.3 sass: 1.97.1 - vite@7.3.1(@types/node@25.0.9)(sass@1.97.1): + vitest@4.0.18(@types/node@25.0.10)(jsdom@27.4.0)(sass@1.97.1): dependencies: - esbuild: 0.27.2 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.55.3 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 25.0.9 - fsevents: 2.3.3 - sass: 1.97.1 - - vitest@4.0.17(@types/node@25.0.9)(jsdom@27.4.0)(sass@1.97.1): - dependencies: - '@vitest/expect': 4.0.17 - '@vitest/mocker': 4.0.17(vite@7.3.1(@types/node@25.0.9)(sass@1.97.1)) - '@vitest/pretty-format': 4.0.17 - '@vitest/runner': 4.0.17 - '@vitest/snapshot': 4.0.17 - '@vitest/spy': 4.0.17 - '@vitest/utils': 4.0.17 + '@vitest/expect': 4.0.18 + '@vitest/mocker': 4.0.18(vite@7.3.0(@types/node@25.0.10)(sass@1.97.1)) + '@vitest/pretty-format': 4.0.18 + '@vitest/runner': 4.0.18 + '@vitest/snapshot': 4.0.18 + '@vitest/spy': 4.0.18 + '@vitest/utils': 4.0.18 es-module-lexer: 1.7.0 expect-type: 1.3.0 magic-string: 0.30.21 @@ -8485,10 +8433,10 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.3.1(@types/node@25.0.9)(sass@1.97.1) + vite: 7.3.0(@types/node@25.0.10)(sass@1.97.1) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 25.0.9 + '@types/node': 25.0.10 jsdom: 27.4.0 transitivePeerDependencies: - jiti @@ -8591,10 +8539,7 @@ snapshots: ws@7.5.10: {} - ws@8.18.3: - optional: true - - ws@8.19.0: {} + ws@8.18.3: {} xml-name-validator@5.0.0: {} diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 34f82fc..ded0e66 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,9 +1,10 @@ import {Routes} from '@angular/router'; -import {DashboardComponent} from './dashboard/dashboard.component'; +import {DefaultDashboardComponent} from './dashboard/views/default-dashboard/default-dashboard.component'; import {PageNotFoundComponent} from './page-not-found/page-not-found.component'; import {AboutComponent} from './about/about.component'; import {HelpComponent} from './help/help.component'; +import {UserDashboardComponent} from "@app/dashboard/views/user-dashboard/user-dashboard.component"; export const routes: Routes = [ { @@ -13,17 +14,22 @@ export const routes: Routes = [ }, { path: 'dashboard', - component: DashboardComponent, + component: DefaultDashboardComponent, children: [ { path: 'hotosm', - component: DashboardComponent, + component: DefaultDashboardComponent, }, { path: 'live', - component: DashboardComponent, + component: DefaultDashboardComponent, } ] }, + { + path: 'user-dashboard', + pathMatch: 'full', + component: UserDashboardComponent + }, { path: 'about', pathMatch: 'full', diff --git a/src/app/app.component.html b/src/app/app.component.html index efa08ae..664ea4b 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -9,12 +9,12 @@
+ target="_blank" rel="noopener">
@@ -34,7 +34,7 @@
diff --git a/src/app/app.component.scss b/src/app/app.component.scss index bcde1ff..387d174 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -1,3 +1,8 @@ .sidebar { z-index: 5000; -} \ No newline at end of file +} + +.user-icon-disabled { + filter: grayscale(100%) brightness(0.7); + opacity: 0.6; +} diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 862fbcb..b818188 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -1,10 +1,10 @@ import {TestBed} from '@angular/core/testing'; import {AppComponent} from './app.component'; -import {DataService} from './data.service'; +import {DataService} from '../lib/data.service'; import {provideRouter, Router} from "@angular/router"; import {BehaviorSubject, of} from "rxjs"; import {NO_ERRORS_SCHEMA} from "@angular/core"; -import {StateService} from "./state.service"; +import {StateService} from "../lib/state.service"; import {vi} from "vitest"; describe('AppComponent', () => { diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 6bbbbec..777b21f 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,39 +1,55 @@ -import {AfterViewInit, Component, ElementRef, HostListener, QueryList, ViewChildren} from '@angular/core'; -import {ToastService} from './toast.service'; -import {DataService} from "./data.service"; -import {StateService} from "./state.service"; +import { + AfterViewInit, + Component, + ElementRef, + HostListener, + inject, + QueryList, + signal, + ViewChildren +} from '@angular/core'; +import {ToastService} from '../lib/toast.service'; +import {DataService} from "../lib/data.service"; +import {StateService} from "../lib/state.service"; import packageJson from '../../package.json'; -import {enableTooltips} from "./utils"; +import {enableTooltips} from "../lib/utils"; import {StatusBannerComponent} from "./status-banner/status-banner.component"; import {ToastComponent} from "./toast/toast.component"; import {NgClass} from "@angular/common"; -import {RouterLink, RouterOutlet} from "@angular/router"; +import {Router, RouterLink, RouterOutlet} from "@angular/router"; +import {AuthService} from "../lib/auth.service"; +import {NzIconModule} from "ng-zorro-antd/icon"; +import {NzButtonModule} from "ng-zorro-antd/button"; +import {environment} from "@environments/environment"; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], - imports: [StatusBannerComponent, ToastComponent, NgClass, RouterOutlet, RouterLink], + imports: [StatusBannerComponent, ToastComponent, NgClass, RouterOutlet, RouterLink, NzButtonModule, NzIconModule], standalone: true }) export class AppComponent implements AfterViewInit { @ViewChildren('tooltip') tooltips!: QueryList; + stateService = inject(StateService); + private toastService = inject(ToastService); + private dataService = inject(DataService); + protected authService = inject(AuthService); + private router: Router = inject(Router); + title = 'ohsomeNow Stats' - name = 'HeiGIT'; + name = 'HeiGIT' isOpen = false - live: boolean = false + live = signal(false) page: string = '' protected readonly appVersion: string = packageJson.version protected currentYear: string = new Date().getFullYear().toString() - constructor(private toastService: ToastService, - private dataService: DataService, - stateService: StateService, - ) { + constructor() { this.dataService.liveMode.subscribe(mode => { - this.live = mode + this.live.set(mode) }) - stateService.activePage.subscribe(page => { + this.stateService.activePage.subscribe(page => { this.page = page!.split('?')[0] }) } @@ -70,9 +86,7 @@ export class AppComponent implements AfterViewInit { } toggleSidebar() { - // console.log('>>> AppComponent >>> toggleSidebar ') this.isOpen = !this.isOpen - // this.triggerResizeEvent() const app = document.querySelector('#sidebar-container') if (app) { if (app.classList.contains('is-collapsed')) @@ -82,4 +96,16 @@ export class AppComponent implements AfterViewInit { } } + redirectUserDashboard() { + if(this.authService.isAnon()) { + this.toastService.show({ + title: 'Unauthorized access', + body: `Our User dashboard gives access to statistics of individual OSM users, to view those please + login with your HeiGIT credentials`, + type: 'warning', + }) + } + else + this.router.navigate(['/user-dashboard']) + } } diff --git a/src/app/dashboard/dashboard.component.scss b/src/app/app.module.ts similarity index 100% rename from src/app/dashboard/dashboard.component.scss rename to src/app/app.module.ts diff --git a/src/app/dashboard/country-map/country-map.component.ts b/src/app/dashboard/country-map/country-map.component.ts index 01ad4a1..e3c072a 100644 --- a/src/app/dashboard/country-map/country-map.component.ts +++ b/src/app/dashboard/country-map/country-map.component.ts @@ -1,11 +1,24 @@ -import {Component, computed, effect, ElementRef, NgZone, OnDestroy, OnInit, signal, ViewChild} from '@angular/core'; -import {StateService} from 'src/app/state.service'; +import { + booleanAttribute, + Component, + computed, + effect, + ElementRef, + inject, + input, + NgZone, + OnDestroy, + OnInit, + signal, + ViewChild +} from '@angular/core'; +import {StateService} from '../../../lib/state.service'; import {Overlay} from '../../overlay.component'; import {Color, Deck, DeckProps, MapView, PickingInfo} from '@deck.gl/core'; import {TileLayer} from '@deck.gl/geo-layers'; import {BitmapLayer, ScatterplotLayer} from '@deck.gl/layers'; -import {DataService} from '../../data.service'; -import {ICountryData, ICountryLocationData, IStateParams, StatsType} from '../types'; +import {DataService} from '../../../lib/data.service'; +import {ICountryData, ICountryLocationData, IStateParams, StatsType} from '../../../lib/types'; import countryPlotPositions from '../../../assets/static/json/countryLabelpoint.json'; import topicDefinitions from "../../../assets/static/json/topicDefinitions.json"; import {scalePow, scaleSqrt} from 'd3-scale'; @@ -25,6 +38,9 @@ const typedCountryPlotPositions = countryPlotPositions as unknown as { [countryC export class CountryMapComponent implements OnInit, OnDestroy { @ViewChild('deckContainer', {static: true}) deckContainer!: ElementRef; + private stateService: StateService = inject(StateService); + private dataService: DataService = inject(DataService); + private readonly ngZone: NgZone = inject(NgZone); isLoading = signal(false); enrichedCountryData = signal([]); @@ -64,12 +80,9 @@ export class CountryMapComponent implements OnInit, OnDestroy { }); deck!: Deck; + userMode = input(false, {transform: booleanAttribute}); - constructor( - private stateService: StateService, - private dataService: DataService, - private readonly ngZone: NgZone - ) { + constructor() { effect(() => { this.updateData(this.relevantState()); }); @@ -91,25 +104,34 @@ export class CountryMapComponent implements OnInit, OnDestroy { } updateData(state: IStateParams) { + const isUserMode = this.userMode(); const reqParams = { hashtag: state.hashtag, start: state.start, end: state.end, topics: state.active_topic, - } + ...(!isUserMode ? {} : { osm_user_id: state.osm_user_id }), + }; this.isLoading.set(true); - this.dataService.requestCountryStats(reqParams).subscribe({ - next: (res) => { + (isUserMode + ? this.dataService.requestUserCountryStats(reqParams) + : this.dataService.requestCountryStats(reqParams) + ).subscribe(this.handleResponse()); + } + + private handleResponse() { + return { + next: (res: any) => { const countryData: ICountryData[] = res.result.topics[this.activeTopic()]; this.enrichedCountryData.set(this.enrichCountryDataWithPlotPositions(countryData)); this.isLoading.set(false); }, - error: (err) => { + error: (err: Error) => { console.log(err); this.isLoading.set(false); } - }) + } } /** diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html deleted file mode 100644 index 9a0e618..0000000 --- a/src/app/dashboard/dashboard.component.html +++ /dev/null @@ -1,43 +0,0 @@ -
-
-
- @if (mode === "hotosm") { - - } @else if (mode === "live") { - - } @else { - - } -
-
- -
-
- -
-
-
-
-
- -
-
-
-
- -
-
-
-
-
- -
-
-
-
- -
-
-
-
-
diff --git a/src/app/dashboard/dashboard.component.ts b/src/app/dashboard/dashboard.component.ts deleted file mode 100644 index 201442d..0000000 --- a/src/app/dashboard/dashboard.component.ts +++ /dev/null @@ -1,27 +0,0 @@ -import {Component} from '@angular/core'; -import {StateService} from "../state.service"; -import {HotQueryComponent} from './query/hot-query/hot-query.component'; -import {LiveQueryComponent} from './query/live-query/live-query.component'; -import {DefaultQueryComponent} from './query/default-query/default-query.component'; -import {TrendingHashtagsComponent} from './trending-hashtags/trending-hashtags.component'; -import {ExportDataComponent} from './export-data/export-data.component'; -import {SummaryComponent} from './summary/summary.component'; -import {PlotComponent} from './plot/plot.component'; -import {CountryMapComponent} from './country-map/country-map.component'; -import {HexMapComponent} from './hex-map/hex-map.component'; -import {UTCToLocalConverterPipe} from "./query/pipes/utc-to-local-converter.pipe"; - -@Component({ - selector: 'app-dashboard', - templateUrl: './dashboard.component.html', - styleUrls: ['./dashboard.component.scss'], - imports: [HotQueryComponent, LiveQueryComponent, DefaultQueryComponent, TrendingHashtagsComponent, ExportDataComponent, SummaryComponent, PlotComponent, CountryMapComponent, HexMapComponent], - providers: [UTCToLocalConverterPipe] -}) -export class DashboardComponent { - mode: string = ''; - - constructor(stateService: StateService) { - stateService.activePage.subscribe(page => this.mode = page!) - } -} diff --git a/src/app/dashboard/export-data/export-data.component.spec.ts b/src/app/dashboard/export-data/export-data.component.spec.ts index 3235843..193f399 100644 --- a/src/app/dashboard/export-data/export-data.component.spec.ts +++ b/src/app/dashboard/export-data/export-data.component.spec.ts @@ -1,11 +1,11 @@ import {ComponentFixture, TestBed} from '@angular/core/testing'; import {ExportDataComponent} from './export-data.component'; -import {DataService} from "../../data.service"; -import {StateService} from "../../state.service"; +import {DataService} from "../../../lib/data.service"; +import {StateService} from "../../../lib/state.service"; import {signal} from "@angular/core"; import {of} from "rxjs"; -import {IHashtags, IStateParams} from "../types"; +import {IHashtags, IStateParams} from "../../../lib/types"; import {vi} from "vitest"; describe('ExportDataComponent', () => { diff --git a/src/app/dashboard/export-data/export-data.component.ts b/src/app/dashboard/export-data/export-data.component.ts index f169432..bc86f25 100644 --- a/src/app/dashboard/export-data/export-data.component.ts +++ b/src/app/dashboard/export-data/export-data.component.ts @@ -1,8 +1,8 @@ -import {Component} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {download, generateCsv, mkConfig} from "export-to-csv"; -import {ICountryResult, IPlotResult, IStateParams, IStatsResult} from "../types"; -import {StateService} from "../../state.service"; -import {DataService} from "../../data.service"; +import {ICountryResult, IPlotResult, IStateParams, IStatsResult} from "../../../lib/types"; +import {StateService} from "../../../lib/state.service"; +import {DataService} from "../../../lib/data.service"; @Component({ selector: 'app-export-data', @@ -10,15 +10,11 @@ import {DataService} from "../../data.service"; styleUrl: './export-data.component.scss' }) export class ExportDataComponent { - - constructor( - private stateService: StateService, - private dataService: DataService - ) { - } + private stateService: StateService = inject(StateService); + private dataService: DataService = inject(DataService); exportOverview() { - let state = this.stateService.appState() + const state = this.stateService.appState() this.dataService.requestSummary(state).subscribe({ next: (data) => { this.prepareOverviewDataAndDownload(data.result, state) @@ -82,7 +78,7 @@ export class ExportDataComponent { columnHeaders: arrangedHeaders }); - let csvData = plotData.startDate.map((value, index) => { + const csvData = plotData.startDate.map((value, index) => { return { startDate: value, endDate: plotData.endDate[index], @@ -124,7 +120,7 @@ export class ExportDataComponent { selectedCountryList.length === 0 || selectedCountryList.includes(country as string) ) - let countryData = countries.map(country => { + const countryData = countries.map(country => { return { startDate: state.start, endDate: state.end, diff --git a/src/app/dashboard/hex-map/hex-map.component.spec.ts b/src/app/dashboard/hex-map/hex-map.component.spec.ts index 8fcd5eb..b1f9e99 100644 --- a/src/app/dashboard/hex-map/hex-map.component.spec.ts +++ b/src/app/dashboard/hex-map/hex-map.component.spec.ts @@ -1,8 +1,8 @@ import {type MockedObject, vi} from "vitest"; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {HexMapComponent} from './hex-map.component'; -import {DataService} from '../../data.service'; -import {StateService} from '../../state.service'; +import {DataService} from '../../../lib/data.service'; +import {StateService} from '../../../lib/state.service'; import {of} from 'rxjs'; import {Overlay} from '../../overlay.component'; diff --git a/src/app/dashboard/hex-map/hex-map.component.ts b/src/app/dashboard/hex-map/hex-map.component.ts index 9eea2e0..1b492c6 100644 --- a/src/app/dashboard/hex-map/hex-map.component.ts +++ b/src/app/dashboard/hex-map/hex-map.component.ts @@ -1,15 +1,27 @@ -import {Component, computed, effect, ElementRef, NgZone, OnDestroy, signal, viewChild} from '@angular/core'; +import { + booleanAttribute, + Component, + computed, + effect, + ElementRef, + inject, + input, + NgZone, + OnDestroy, + signal, + viewChild +} from '@angular/core'; import {Color, Deck, DeckProps, MapView, PickingInfo} from '@deck.gl/core'; import {H3HexagonLayer, H3HexagonLayerProps, TileLayer} from '@deck.gl/geo-layers'; import {BitmapLayer} from '@deck.gl/layers'; import {lch, rgb} from 'd3-color'; import {scalePow} from 'd3-scale'; import {interpolateHcl} from "d3-interpolate"; -import {HexDataType, IStateParams, StatsType} from '../types' -import {StateService} from "../../state.service"; -import {DataService} from "../../data.service"; +import {HexDataType, IStateParams, StatsType} from '../../../lib/types' +import {StateService} from "../../../lib/state.service"; +import {DataService} from "../../../lib/data.service"; import topicDefinitions from "../../../assets/static/json/topicDefinitions.json" -import {ToastService} from "../../toast.service"; +import {ToastService} from "../../../lib/toast.service"; import {Overlay} from '../../overlay.component'; import {HexMapLegendComponent} from './legend/hex-map-legend.component'; import {firstValueFrom} from "rxjs"; @@ -21,6 +33,12 @@ import {firstValueFrom} from "rxjs"; imports: [Overlay, HexMapLegendComponent] }) export class HexMapComponent implements OnDestroy { + + private stateService = inject(StateService); + private dataService = inject(DataService); + private toastService = inject(ToastService); + private readonly ngZone = inject(NgZone); + deckContainer = viewChild('deckContainer'); isH3Loading = signal(false); @@ -33,7 +51,6 @@ export class HexMapComponent implements OnDestroy { showResolutionToggle = computed(() => this.canToggleResolution()); isHighResolution = computed(() => this.currentResolution() === 6); - private relevantState = computed((): IStateParams => { return this.stateService.appState() }, { @@ -50,6 +67,7 @@ export class HexMapComponent implements OnDestroy { deck!: Deck; private layer!: H3HexagonLayer; private readonly MAX_HEX_CELL = 314_000; + userMode = input(false, {transform: booleanAttribute}); // Fixed TileLayer configuration private readonly osmLayer = new TileLayer({ @@ -73,11 +91,7 @@ export class HexMapComponent implements OnDestroy { }, }); - constructor( - private stateService: StateService, - private dataService: DataService, - private toastService: ToastService, - private readonly ngZone: NgZone) { + constructor() { effect(() => { const container = this.deckContainer()?.nativeElement; if (!container || this.deck) return; @@ -112,7 +126,8 @@ export class HexMapComponent implements OnDestroy { end: state.end, countries: state.countries, topic: state.active_topic, - resolution: 3 + resolution: 3, + ...(!this.userMode() ? {} : { osm_user_id: state.osm_user_id }), }); }) } @@ -129,6 +144,7 @@ export class HexMapComponent implements OnDestroy { countries: string; topic: string; resolution: number; + osm_user_id?: string; }) { this.layer = await this.createCountryLayer(reqParams); this.deck.setProps({ @@ -139,7 +155,7 @@ export class HexMapComponent implements OnDestroy { } async createCountryLayer( - params: { hashtag: string, start: string, end: string, topic: string, resolution: number, countries: string }, + params: { hashtag: string, start: string, end: string, topic: string, resolution: number, countries: string, osm_user_id?: string }, options?: Partial>, ): Promise> { this.isH3Loading.set(true); @@ -147,7 +163,9 @@ export class HexMapComponent implements OnDestroy { let result; try { result = await firstValueFrom( - this.dataService.getH3Map(params) + this.dataService.getH3Map( + this.userMode() ? params : { ...params, osm_user_id: undefined } + ) ); } catch (e: any) { console.error('Error getting HexMap data from API ', e); diff --git a/src/app/dashboard/plot/plot.component.spec.ts b/src/app/dashboard/plot/plot.component.spec.ts index 9d438f8..b678786 100644 --- a/src/app/dashboard/plot/plot.component.spec.ts +++ b/src/app/dashboard/plot/plot.component.spec.ts @@ -3,10 +3,10 @@ import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing' import {of, throwError} from 'rxjs'; import {PlotComponent} from './plot.component'; -import {DataService} from '../../data.service'; -import {StateService} from '../../state.service'; +import {DataService} from '../../../lib/data.service'; +import {StateService} from '../../../lib/state.service'; import {UTCToLocalConverterPipe} from '../query/pipes/utc-to-local-converter.pipe'; -import {IPlotResult, StatsType} from '../types'; +import {IPlotResult, StatsType} from '../../../lib/types'; import {Overlay} from '../../overlay.component'; import dayjs from "dayjs"; diff --git a/src/app/dashboard/plot/plot.component.ts b/src/app/dashboard/plot/plot.component.ts index 6e60340..88a6589 100644 --- a/src/app/dashboard/plot/plot.component.ts +++ b/src/app/dashboard/plot/plot.component.ts @@ -1,4 +1,4 @@ -import {Component, computed, effect, signal} from '@angular/core'; +import {booleanAttribute, Component, computed, effect, inject, input, signal} from '@angular/core'; import * as PlotlyJS from 'plotly.js-basic-dist-min'; import {Config, Layout} from 'plotly.js-basic-dist-min'; @@ -10,9 +10,9 @@ import { UTCStringToLocalDateConverterFunction, UTCToLocalConverterPipe } from "../query/pipes/utc-to-local-converter.pipe"; -import {StateService} from "../../state.service"; -import {DataService} from "../../data.service"; -import {IPlotResult, IQueryParams, StatsType} from "../types"; +import {StateService} from "../../../lib/state.service"; +import {DataService} from "../../../lib/data.service"; +import {IPlotResult, IQueryParams, StatsType} from "../../../lib/types"; import {Overlay} from '../../overlay.component'; import {PlotlyComponent, PlotlyModule} from 'angular-plotly.js'; @@ -26,6 +26,10 @@ PlotlyModule.forRoot(PlotlyJS) }) export class PlotComponent { + private stateService: StateService = inject(StateService); + private dataService: DataService = inject(DataService); + private utcToLocalConverter: UTCToLocalConverterPipe = inject(UTCToLocalConverterPipe); + data = signal(null); activeTopic = signal(null); isPlotsLoading = signal(false); @@ -79,13 +83,9 @@ export class PlotComponent { click: this.fitToContent() }] } + userMode = input(false, {transform: booleanAttribute}); - constructor( - private stateService: StateService, - private dataService: DataService, - private utcToLocalConverter: UTCToLocalConverterPipe - ) { - + constructor() { // Overall Effect for calling API effect(() => { this.activeTopic.set(this.relevantState().active_topic) @@ -100,8 +100,15 @@ export class PlotComponent { private fetchPlotData(state: IQueryParams) { this.isPlotsLoading.set(true); - this.dataService.requestPlot(state).subscribe({ - next: (res) => { + (this.userMode() + ? this.dataService.requestUserPlot(state) + : this.dataService.requestPlot(state) + ).subscribe(this.handleResponse()); + } + + private handleResponse() { + return { + next: (res: any) => { this.data.set(res.result); this.isPlotsLoading.set(false); @@ -111,10 +118,10 @@ export class PlotComponent { this.resetZoom(); } }, - error: (err) => { + error: (err: Error) => { console.error('Error while requesting Plot data ', err) } - }); + } } plotData = computed(() => { diff --git a/src/app/dashboard/query/default-query/default-query.component.html b/src/app/dashboard/query/default-query/default-query.component.html index cd4ed19..08df65f 100644 --- a/src/app/dashboard/query/default-query/default-query.component.html +++ b/src/app/dashboard/query/default-query/default-query.component.html @@ -74,14 +74,14 @@ + >
diff --git a/src/app/dashboard/query/default-query/default-query.component.spec.ts b/src/app/dashboard/query/default-query/default-query.component.spec.ts index 0b337e3..16c93eb 100644 --- a/src/app/dashboard/query/default-query/default-query.component.spec.ts +++ b/src/app/dashboard/query/default-query/default-query.component.spec.ts @@ -4,12 +4,12 @@ import {of} from "rxjs"; import {ComponentFixture, TestBed} from "@angular/core/testing"; import {QueryComponent} from "../query.component"; import {FormsModule} from "@angular/forms"; -import {DataService} from "../../../data.service"; -import {ToastService} from "../../../toast.service"; -import {StateService} from "../../../state.service"; +import {DataService} from "../../../../lib/data.service"; +import {ToastService} from "../../../../lib/toast.service"; +import {StateService} from "../../../../lib/state.service"; import {UTCToLocalConverterPipe} from "../pipes/utc-to-local-converter.pipe"; import {ActivatedRoute} from "@angular/router"; -import {IHashtags, IStateParams} from "../../types"; +import {IHashtags, IStateParams} from "../../../../lib/types"; import {vi} from "vitest"; describe('DefaultQueryComponent', () => { diff --git a/src/app/dashboard/query/hot-query/hot-query.component.html b/src/app/dashboard/query/hot-query/hot-query.component.html index 2772884..6046a3d 100644 --- a/src/app/dashboard/query/hot-query/hot-query.component.html +++ b/src/app/dashboard/query/hot-query/hot-query.component.html @@ -75,7 +75,7 @@ @@ -118,7 +118,7 @@ diff --git a/src/app/dashboard/query/hot-query/hot-query.component.spec.ts b/src/app/dashboard/query/hot-query/hot-query.component.spec.ts index 08b44de..22e7b84 100644 --- a/src/app/dashboard/query/hot-query/hot-query.component.spec.ts +++ b/src/app/dashboard/query/hot-query/hot-query.component.spec.ts @@ -1,13 +1,13 @@ import {ComponentFixture, TestBed} from '@angular/core/testing'; import {FormsModule} from '@angular/forms'; -import {DataService} from '../../../data.service'; -import {ToastService} from 'src/app/toast.service'; -import {StateService} from '../../../state.service'; +import {DataService} from '../../../../lib/data.service'; +import {ToastService} from '../../../../lib/toast.service'; +import {StateService} from '../../../../lib/state.service'; import {of} from 'rxjs'; import {UTCToLocalConverterPipe} from '../pipes/utc-to-local-converter.pipe'; import {ActivatedRoute} from '@angular/router'; import {NO_ERRORS_SCHEMA, signal} from '@angular/core'; -import {IHashtags, IStateParams} from '../../types'; +import {IHashtags, IStateParams} from '../../../../lib/types'; import {QueryComponent} from "../query.component"; import {HotQueryComponent} from "./hot-query.component"; import {vi} from "vitest"; diff --git a/src/app/dashboard/query/hot-query/hot-query.component.ts b/src/app/dashboard/query/hot-query/hot-query.component.ts index c1aa67e..791667e 100644 --- a/src/app/dashboard/query/hot-query/hot-query.component.ts +++ b/src/app/dashboard/query/hot-query/hot-query.component.ts @@ -1,6 +1,6 @@ import {Component} from '@angular/core'; import {QueryComponent} from "../query.component"; -import {ISelectionItem} from "../../types"; +import {ISelectionItem} from "../../../../lib/types"; import {FormsModule} from '@angular/forms'; import {AutoComplete} from 'primeng/autocomplete'; import {PrimeTemplate} from 'primeng/api'; diff --git a/src/app/dashboard/query/live-query/live-query.component.html b/src/app/dashboard/query/live-query/live-query.component.html index 15fc070..922659a 100644 --- a/src/app/dashboard/query/live-query/live-query.component.html +++ b/src/app/dashboard/query/live-query/live-query.component.html @@ -40,7 +40,7 @@ @@ -49,7 +49,7 @@ diff --git a/src/app/dashboard/query/live-query/live-query.component.spec.ts b/src/app/dashboard/query/live-query/live-query.component.spec.ts index e578364..45a8696 100644 --- a/src/app/dashboard/query/live-query/live-query.component.spec.ts +++ b/src/app/dashboard/query/live-query/live-query.component.spec.ts @@ -1,15 +1,15 @@ import {ComponentFixture, fakeAsync, TestBed} from '@angular/core/testing'; import {FormsModule} from '@angular/forms'; import {LiveQueryComponent} from './live-query.component'; -import {DataService} from '../../../data.service'; -import {ToastService} from 'src/app/toast.service'; -import {StateService} from '../../../state.service'; +import {DataService} from '../../../../lib/data.service'; +import {ToastService} from '../../../../lib/toast.service'; +import {StateService} from '../../../../lib/state.service'; import {of} from 'rxjs'; import {UTCToLocalConverterPipe} from '../pipes/utc-to-local-converter.pipe'; import {ActivatedRoute} from '@angular/router'; import {NO_ERRORS_SCHEMA, signal} from '@angular/core'; import dayjs from 'dayjs'; -import {IHashtags, IStateParams} from '../../types'; +import {IHashtags, IStateParams} from '../../../../lib/types'; import {QueryComponent} from "../query.component"; import {vi} from "vitest"; diff --git a/src/app/dashboard/query/query.component.spec.ts b/src/app/dashboard/query/query.component.spec.ts index 398c924..e0f9def 100644 --- a/src/app/dashboard/query/query.component.spec.ts +++ b/src/app/dashboard/query/query.component.spec.ts @@ -2,14 +2,14 @@ import {type Mock, vi} from "vitest"; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {FormsModule} from '@angular/forms'; import {QueryComponent} from './query.component'; -import {DataService} from '../../data.service'; -import {ToastService} from 'src/app/toast.service'; -import {StateService} from '../../state.service'; +import {DataService} from '../../../lib/data.service'; +import {ToastService} from '../../../lib/toast.service'; +import {StateService} from '../../../lib/state.service'; import {of} from 'rxjs'; import {UTCToLocalConverterPipe} from './pipes/utc-to-local-converter.pipe'; import {ActivatedRoute} from '@angular/router'; import {NO_ERRORS_SCHEMA, signal} from '@angular/core'; -import {IHashtags, IStateParams} from '../types'; +import {IHashtags, IStateParams} from '../../../lib/types'; import {AutoCompleteCompleteEvent} from 'primeng/autocomplete'; describe('QueryComponent', () => { diff --git a/src/app/dashboard/query/query.component.ts b/src/app/dashboard/query/query.component.ts index 246814f..9f679fd 100644 --- a/src/app/dashboard/query/query.component.ts +++ b/src/app/dashboard/query/query.component.ts @@ -19,12 +19,12 @@ import customParseFormat from 'dayjs/plugin/customParseFormat' import dropdownOptions from "../../../assets/static/json/countryCodes.json" import topicDefinitions from "../../../assets/static/json/topicDefinitions.json" -import {DataService} from '../../data.service'; -import {ToastService} from 'src/app/toast.service'; -import {DropdownOption, IHashtags, IHighlightedHashtag, IStateParams, StatsType} from "../types"; -import {StateService} from "../../state.service"; +import {DataService} from '../../../lib/data.service'; +import {ToastService} from '../../../lib/toast.service'; +import {DropdownOption, IHashtags, IHighlightedHashtag, IStateParams, StatsType} from "../../../lib/types"; +import {StateService} from "../../../lib/state.service"; import {AutoCompleteCompleteEvent} from "primeng/autocomplete"; -import {enableTooltips, over5000IntervalBins} from "../../utils"; +import {enableTooltips, over5000IntervalBins} from "../../../lib/utils"; dayjs.extend(duration) dayjs.extend(utc) diff --git a/src/app/dashboard/query/user-query/user-query.component.html b/src/app/dashboard/query/user-query/user-query.component.html new file mode 100644 index 0000000..571be47 --- /dev/null +++ b/src/app/dashboard/query/user-query/user-query.component.html @@ -0,0 +1,109 @@ +
+
+
+
+
+
+
+
+ +
+ + + +
+
+ +
+
+
+ +
+
+ + + +
+ + + + + +
+ +
+
+ +
+
+ + + +
+
+ +
+
+
+
+ + +
+
+
+
+ + +
+
+
+ + +
+
+
+ +
+
+
+
diff --git a/src/app/dashboard/query/user-query/user-query.component.scss b/src/app/dashboard/query/user-query/user-query.component.scss new file mode 100644 index 0000000..4e63945 --- /dev/null +++ b/src/app/dashboard/query/user-query/user-query.component.scss @@ -0,0 +1 @@ +@import url(../query.component.scss); \ No newline at end of file diff --git a/src/app/dashboard/query/user-query/user-query.component.ts b/src/app/dashboard/query/user-query/user-query.component.ts new file mode 100644 index 0000000..11e2e8e --- /dev/null +++ b/src/app/dashboard/query/user-query/user-query.component.ts @@ -0,0 +1,62 @@ +import {Component} from '@angular/core'; +import {QueryComponent} from "../query.component"; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {AutoComplete} from 'primeng/autocomplete'; +import {PrimeTemplate} from 'primeng/api'; +import {SelectDropDownModule} from 'ngx-select-dropdown'; +import {UTCToLocalConverterPipe} from '../pipes/utc-to-local-converter.pipe'; +import {NzDatePickerComponent, NzDatePickerModule} from "ng-zorro-antd/date-picker"; +import dayjs from "dayjs"; +import {StatsType} from "../../../../lib/types"; + + +@Component({ + selector: 'user-query', + templateUrl: './user-query.component.html', + styleUrls: ['./user-query.component.scss'], + imports: [FormsModule, AutoComplete, PrimeTemplate, SelectDropDownModule, UTCToLocalConverterPipe, ReactiveFormsModule, NzDatePickerComponent, NzDatePickerModule], + providers: [] +}) +export class UserQueryComponent extends QueryComponent { + userID: string = "115612"; + + constructor() { + super(); + this.updateSelectionFromState(this.state()); + this.updateStateWithOSMUser() + } + + updateStateWithOSMUser() { + if (!this.validateForm() || !this.selectedDateRange()) + return + + const tempStart = dayjs(this.selectedDateRange()![0]).utc().format() + const tempEnd = dayjs(this.selectedDateRange()![1]).utc().format() + + const tempHashTag = this.cleanHashTag(this.selectedHashtagOption) + + if (this.selectedCountries().length === this.dropdownOptions.length) { + this.countries = [""] + } else { + this.countries = this.selectedCountries().map(e => e.value) + } + + this.topics = this.selectedTopics().map(e => e.value) + const previousState = this.stateService.appState() + const active_topic = this.topics.includes(previousState.active_topic) ? previousState.active_topic : this.topics[0] + + const state = { + countries: this.countries.toString(), + hashtag: tempHashTag, + start: tempStart, + end: tempEnd, + interval: this.interval()!, + topics: this.topics.toString(), + active_topic: active_topic as StatsType, + osm_user_id: this.userID + }; + + // update the state + this.stateService.updatePartialState(state) + } +} \ No newline at end of file diff --git a/src/app/dashboard/summary/big-number/big-number.component.ts b/src/app/dashboard/summary/big-number/big-number.component.ts index 7066a6f..4e0bd95 100644 --- a/src/app/dashboard/summary/big-number/big-number.component.ts +++ b/src/app/dashboard/summary/big-number/big-number.component.ts @@ -1,9 +1,9 @@ import {AfterViewInit, Component, computed, effect, ElementRef, Input, QueryList, ViewChildren} from '@angular/core'; -import {ITopicDefinitionValue} from "../../types"; -import {StateService} from "../../../state.service"; +import {ITopicDefinitionValue} from "../../../../lib/types"; +import {StateService} from "../../../../lib/state.service"; import {Router} from "@angular/router"; -import {enableTooltips} from "../../../utils"; -import { NgClass, NgStyle } from '@angular/common'; +import {enableTooltips} from "../../../../lib/utils"; +import {NgClass, NgStyle} from '@angular/common'; @Component({ selector: 'app-big-number', diff --git a/src/app/dashboard/summary/summary.component.spec.ts b/src/app/dashboard/summary/summary.component.spec.ts index 7865421..f5aa561 100644 --- a/src/app/dashboard/summary/summary.component.spec.ts +++ b/src/app/dashboard/summary/summary.component.spec.ts @@ -2,9 +2,9 @@ import {type MockedObject, vi} from "vitest"; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {of} from 'rxjs'; import {SummaryComponent} from './summary.component'; -import {DataService} from '../../data.service'; -import {StateService} from '../../state.service'; -import {IStateParams, IWrappedStatsResult, StatsType} from '../types'; +import {DataService} from '../../../lib/data.service'; +import {StateService} from '../../../lib/state.service'; +import {IStateParams, IWrappedStatsResult, StatsType} from '../../../lib/types'; import {Overlay} from '../../overlay.component'; describe('SummaryComponent', () => { diff --git a/src/app/dashboard/summary/summary.component.ts b/src/app/dashboard/summary/summary.component.ts index 946a239..03b5162 100644 --- a/src/app/dashboard/summary/summary.component.ts +++ b/src/app/dashboard/summary/summary.component.ts @@ -1,10 +1,10 @@ -import {Component, computed, effect, signal} from '@angular/core'; -import {IQueryParams, ITopicDefinitionValue, StatsType} from "../types"; -import {StateService} from "../../state.service"; -import {DataService} from "../../data.service"; +import {booleanAttribute, Component, computed, effect, inject, input, signal} from '@angular/core'; +import {IQueryParams, ITopicDefinitionValue, IWrappedStatsResult, StatsType} from "../../../lib/types"; +import {StateService} from "../../../lib/state.service"; +import {DataService} from "../../../lib/data.service"; import topicDefinitions from "../../../assets/static/json/topicDefinitions.json" import {BigNumberComponent} from "./big-number/big-number.component"; -import {Overlay} from "../../overlay.component"; +import {Overlay} from "@app/overlay.component"; @Component({ selector: 'app-summary', @@ -13,6 +13,9 @@ import {Overlay} from "../../overlay.component"; imports: [Overlay, BigNumberComponent] }) export class SummaryComponent { + private stateService: StateService = inject(StateService); + private dataService: DataService = inject(DataService); + bignumberData = signal([]); isSummaryLoading = signal(false); @@ -29,11 +32,9 @@ export class SummaryComponent { a.topics === b.topics } ); + userMode = input(false, {transform: booleanAttribute}); - constructor( - private stateService: StateService, - private dataService: DataService - ) { + constructor() { effect(() => { this.requestFromAPI(this.relevantState()); }); @@ -41,9 +42,16 @@ export class SummaryComponent { requestFromAPI(queryParams: IQueryParams) { this.isSummaryLoading.set(true); + const isUserMode = this.userMode(); + (isUserMode + ? this.dataService.requestUserSummary(queryParams) + : this.dataService.requestSummary(queryParams) + ).subscribe(this.processResult()); + } - this.dataService.requestSummary(queryParams).subscribe({ - next: (data) => { + private processResult() { + return { + next: (data: IWrappedStatsResult) => { const topics = data.result.topics; const result: ITopicDefinitionValue[] = []; @@ -55,11 +63,11 @@ export class SummaryComponent { this.bignumberData.set(result); this.isSummaryLoading.set(false); }, - error: err => { + error: (err: Error) => { console.error(err); this.isSummaryLoading.set(false); } - }); + }; } changeSelectedBigNumber(e: MouseEvent, newCurrentStats: string) { diff --git a/src/app/dashboard/trending-hashtags/trending-hashtags.component.spec.ts b/src/app/dashboard/trending-hashtags/trending-hashtags.component.spec.ts index 0383df9..49eefb0 100644 --- a/src/app/dashboard/trending-hashtags/trending-hashtags.component.spec.ts +++ b/src/app/dashboard/trending-hashtags/trending-hashtags.component.spec.ts @@ -5,9 +5,9 @@ import {By} from '@angular/platform-browser'; import {Overlay} from '../../overlay.component'; import {TrendingHashtagsComponent} from './trending-hashtags.component'; -import {DataService} from '../../data.service'; -import {StateService} from '../../state.service'; -import {IHashtag, StatsType} from '../types'; +import {DataService} from '../../../lib/data.service'; +import {StateService} from '../../../lib/state.service'; +import {IHashtag, StatsType} from '../../../lib/types'; describe('TrendingHashtagsComponent', () => { let component: TrendingHashtagsComponent; diff --git a/src/app/dashboard/trending-hashtags/trending-hashtags.component.ts b/src/app/dashboard/trending-hashtags/trending-hashtags.component.ts index 8d078fc..1efdcbb 100644 --- a/src/app/dashboard/trending-hashtags/trending-hashtags.component.ts +++ b/src/app/dashboard/trending-hashtags/trending-hashtags.component.ts @@ -1,11 +1,11 @@ import {Component, computed, effect, ElementRef, QueryList, signal, ViewChildren} from '@angular/core'; -import {DataService} from '../../data.service'; +import {DataService} from '../../../lib/data.service'; import {dashboard} from '../tooltip-data'; -import {IHashtag} from "../types"; -import {StateService} from "../../state.service"; +import {IHashtag} from "../../../lib/types"; +import {StateService} from "../../../lib/state.service"; import {Overlay} from '../../overlay.component'; -import {enableTooltips} from "../../utils"; +import {enableTooltips} from "../../../lib/utils"; @Component({ selector: 'app-trending-hashtags', diff --git a/src/app/dashboard/views/default-dashboard/default-dashboard.component.html b/src/app/dashboard/views/default-dashboard/default-dashboard.component.html new file mode 100644 index 0000000..1c0eab0 --- /dev/null +++ b/src/app/dashboard/views/default-dashboard/default-dashboard.component.html @@ -0,0 +1,44 @@ +
+
+
+ @if (mode === "hotosm") { + + } @else if (mode === "live") { + + } @else { + + } +
+
+ + +
+
+ +
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
diff --git a/src/app/dashboard/views/default-dashboard/default-dashboard.component.scss b/src/app/dashboard/views/default-dashboard/default-dashboard.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/dashboard/dashboard.component.spec.ts b/src/app/dashboard/views/default-dashboard/default-dashboard.component.spec.ts similarity index 83% rename from src/app/dashboard/dashboard.component.spec.ts rename to src/app/dashboard/views/default-dashboard/default-dashboard.component.spec.ts index 2cc283e..fe5aee5 100644 --- a/src/app/dashboard/dashboard.component.spec.ts +++ b/src/app/dashboard/views/default-dashboard/default-dashboard.component.spec.ts @@ -1,8 +1,8 @@ import {ComponentFixture, TestBed} from '@angular/core/testing'; -import {DashboardComponent} from './dashboard.component'; +import {DefaultDashboardComponent} from './default-dashboard.component'; import {Component} from "@angular/core"; -import {StateService} from "../state.service"; +import {StateService} from "../../../../lib/state.service"; import {of} from "rxjs"; // Mock child components @@ -63,8 +63,8 @@ class MockCountryMapComponent { } describe('DashboardComponent', () => { - let component: DashboardComponent; - let fixture: ComponentFixture; + let component: DefaultDashboardComponent; + let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ @@ -77,13 +77,13 @@ describe('DashboardComponent', () => { MockMapComponent, MockHexMapComponent, MockCountryMapComponent, - DashboardComponent + DefaultDashboardComponent ], providers: [{provide: StateService, useValue: {activePage: of(null)}}] }) .compileComponents(); - fixture = TestBed.createComponent(DashboardComponent); + fixture = TestBed.createComponent(DefaultDashboardComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/dashboard/views/default-dashboard/default-dashboard.component.ts b/src/app/dashboard/views/default-dashboard/default-dashboard.component.ts new file mode 100644 index 0000000..aaa6db6 --- /dev/null +++ b/src/app/dashboard/views/default-dashboard/default-dashboard.component.ts @@ -0,0 +1,27 @@ +import {Component} from '@angular/core'; +import {StateService} from "../../../../lib/state.service"; +import {HotQueryComponent} from '../../query/hot-query/hot-query.component'; +import {LiveQueryComponent} from '../../query/live-query/live-query.component'; +import {DefaultQueryComponent} from '../../query/default-query/default-query.component'; +import {TrendingHashtagsComponent} from '../../trending-hashtags/trending-hashtags.component'; +import {ExportDataComponent} from '../../export-data/export-data.component'; +import {SummaryComponent} from '../../summary/summary.component'; +import {PlotComponent} from '../../plot/plot.component'; +import {CountryMapComponent} from '../../country-map/country-map.component'; +import {HexMapComponent} from '../../hex-map/hex-map.component'; +import {UTCToLocalConverterPipe} from "../../query/pipes/utc-to-local-converter.pipe"; + +@Component({ + selector: 'app-default-dashboard', + templateUrl: './default-dashboard.component.html', + styleUrls: ['./default-dashboard.component.scss'], + imports: [HotQueryComponent, LiveQueryComponent, DefaultQueryComponent, TrendingHashtagsComponent, ExportDataComponent, SummaryComponent, PlotComponent, CountryMapComponent, HexMapComponent], + providers: [UTCToLocalConverterPipe] +}) +export class DefaultDashboardComponent { + mode: string = ''; + + constructor(stateService: StateService) { + stateService.activePage.subscribe(page => this.mode = page!) + } +} diff --git a/src/app/dashboard/views/user-dashboard/user-dashboard.component.html b/src/app/dashboard/views/user-dashboard/user-dashboard.component.html new file mode 100644 index 0000000..8293c50 --- /dev/null +++ b/src/app/dashboard/views/user-dashboard/user-dashboard.component.html @@ -0,0 +1,34 @@ +
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
diff --git a/src/app/dashboard/views/user-dashboard/user-dashboard.component.scss b/src/app/dashboard/views/user-dashboard/user-dashboard.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/dashboard/views/user-dashboard/user-dashboard.component.ts b/src/app/dashboard/views/user-dashboard/user-dashboard.component.ts new file mode 100644 index 0000000..97037c6 --- /dev/null +++ b/src/app/dashboard/views/user-dashboard/user-dashboard.component.ts @@ -0,0 +1,34 @@ +import {Component, inject} from '@angular/core'; +import {StateService} from "../../../../lib/state.service"; +import {ExportDataComponent} from '../../export-data/export-data.component'; +import {SummaryComponent} from '../../summary/summary.component'; +import {UTCToLocalConverterPipe} from "../../query/pipes/utc-to-local-converter.pipe"; +import {UserQueryComponent} from "@app/dashboard/query/user-query/user-query.component"; +import {PlotComponent} from "@app/dashboard/plot/plot.component"; +import {CountryMapComponent} from "@app/dashboard/country-map/country-map.component"; +import {HexMapComponent} from "@app/dashboard/hex-map/hex-map.component"; + +@Component({ + selector: 'app-user-dashboard', + templateUrl: './user-dashboard.component.html', + styleUrls: ['./user-dashboard.component.scss'], + imports: [ExportDataComponent, SummaryComponent, UserQueryComponent, PlotComponent, CountryMapComponent, HexMapComponent], + providers: [UTCToLocalConverterPipe] +}) +export class UserDashboardComponent { + private stateService = inject(StateService); + mode: string = ''; + + constructor() { + this.stateService.activePage.subscribe(page => this.mode = page!) + + // in user-dashboard we don't need to show 'contributor' topic + const state = this.stateService.appState() + let topics = state.topics; + topics = topics.replace(/(^|,)contributor(,|$)/, '$1').replace(/^,|,$/g, ''); + this.stateService.updatePartialState({ + active_topic: 'edit', + topics: topics + }); + } +} diff --git a/src/app/toast/toast.component.html b/src/app/toast/toast.component.html index 3711ef5..c60ba2c 100644 --- a/src/app/toast/toast.component.html +++ b/src/app/toast/toast.component.html @@ -7,8 +7,7 @@ -
- {{body}} +
\ No newline at end of file diff --git a/src/app/toast/toast.component.ts b/src/app/toast/toast.component.ts index 542a067..4176eae 100644 --- a/src/app/toast/toast.component.ts +++ b/src/app/toast/toast.component.ts @@ -1,9 +1,10 @@ -import { Component, OnInit } from '@angular/core'; +import {Component, inject, OnInit} from '@angular/core'; import * as bootstrap from 'bootstrap'; -import { IToastUI, ToastService } from '../toast.service'; -import { ToastTypes } from './toasttypes.modal'; -import { NgClass } from '@angular/common'; +import {IToastUI, ToastService} from '../../lib/toast.service'; +import {ToastTypes} from './toasttypes.modal'; +import {NgClass} from '@angular/common'; +import {DomSanitizer, SafeHtml} from "@angular/platform-browser"; @Component({ selector: 'app-toast', @@ -12,51 +13,55 @@ import { NgClass } from '@angular/common'; imports: [NgClass] }) export class ToastComponent implements OnInit { - toastVisible = false - // toastTypes: typeof ToastTypes = ToastTypes - title: string | undefined - body: string | undefined - type: string | undefined - time: number | undefined - - constructor(private toastService: ToastService) {} - - ngOnInit() { - this.toastService.showToast$.subscribe((param: IToastUI | null) => { - if(! param) - return - - // console.log('>>> ToastComponent >>> showToast$.subscribe ', param, ToastTypes, ToastTypes[param.type as keyof typeof ToastTypes]) - this.title = param.title - this.body = param.body - this.type = ToastTypes[param.type as keyof typeof ToastTypes] - this.time = param.time - - this.showToast() - }) - } - - showToast() { - const toastLiveExample = document.getElementById('liveToast') - if(toastLiveExample){ - const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample) - toastBootstrap.show() - this.toastVisible = true + + private toastService: ToastService = inject(ToastService); + private sanitizer: DomSanitizer = inject(DomSanitizer); + + toastVisible = false + // toastTypes: typeof ToastTypes = ToastTypes + title: string | undefined + body: SafeHtml | undefined + type: string | undefined + time: number | undefined + + constructor() {} + + ngOnInit() { + this.toastService.showToast$.subscribe((param: IToastUI | null) => { + if (!param) + return + + // console.log('>>> ToastComponent >>> showToast$.subscribe ', param, ToastTypes, ToastTypes[param.type as keyof typeof ToastTypes]) + this.title = param.title + this.body = this.sanitizer.bypassSecurityTrustHtml(param.body); + this.type = ToastTypes[param.type as keyof typeof ToastTypes] + this.time = param.time + + this.showToast() + }) } - // set auto disappearing only if provided by the caller - if(this.time ){ - setTimeout(() => { - this.hideToast() - }, this.time) + + showToast() { + const toastLiveExample = document.getElementById('liveToast') + if (toastLiveExample) { + const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample) + toastBootstrap.show() + this.toastVisible = true + } + // set auto disappearing only if provided by the caller + if (this.time) { + setTimeout(() => { + this.hideToast() + }, this.time) + } } - } - - hideToast() { - this.toastVisible = false - const toastLiveExample = document.getElementById('liveToast') - if(toastLiveExample){ - const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample) - toastBootstrap.hide() + + hideToast() { + this.toastVisible = false + const toastLiveExample = document.getElementById('liveToast') + if (toastLiveExample) { + const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample) + toastBootstrap.hide() + } } - } } diff --git a/src/assets/images/user.png b/src/assets/images/user.png new file mode 100644 index 0000000..f5f3d1f Binary files /dev/null and b/src/assets/images/user.png differ diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 1899542..ebed46f 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -2,5 +2,7 @@ export const environment = { production: true, ohsomeStatsUrl: 'https://stats.now.ohsome.org', ohsomeStatsServiceUrl: 'https://stats.now.ohsome.org/api', - ohsomeApiUrl: 'https://api.ohsome.org/v1' + appwriteProjectId: '6751abc5002d7cdf3ab7', + appwriteEndpoint: 'https://api.account.heigit.org', + accountFrontendUrl: 'https://account.heigit.org' }; diff --git a/src/environments/environment.staging.ts b/src/environments/environment.staging.ts new file mode 100644 index 0000000..8d53f4a --- /dev/null +++ b/src/environments/environment.staging.ts @@ -0,0 +1,8 @@ +export const environment = { + production: false, + ohsomeStatsUrl: 'https://int-stats.now.ohsome.org', + ohsomeStatsServiceUrl: 'https://int-stats.now.ohsome.org/api', + appwriteProjectId: '66cef0a9000b0675681b', + appwriteEndpoint: 'https://staging.api.account.heigit.org', + accountFrontendUrl: 'https://staging.account.heigit.org' +}; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 43cac8a..33643f8 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -1,19 +1,8 @@ -// This file can be replaced during build by using the `fileReplacements` array. -// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. -// The list of file replacements can be found in `angular.json`. - export const environment = { production: false, - ohsomeStatsUrl: 'https://int-stats.now.ohsome.org', - ohsomeStatsServiceUrl: 'https://int-stats.now.ohsome.org/api', - ohsomeApiUrl: 'https://api.ohsome.org/v1', + ohsomeStatsUrl: 'http://localhost:4200', + ohsomeStatsServiceUrl: 'https://staging.api.heigit.org/ohsome/now/v1', + appwriteProjectId: '6780e947000ac8835ce3', + appwriteEndpoint: 'https://staging.api.account.heigit.org', + accountFrontendUrl: 'http://localhost:5200', }; - -/* - * For easier debugging in development mode, you can import the following file - * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. - * - * This import should be commented out in production mode because it will have a negative impact - * on performance if an error is thrown. - */ -// import 'zone.js/plugins/zone-error'; // Included with Angular CLI. diff --git a/src/lib/appwrite.ts b/src/lib/appwrite.ts new file mode 100644 index 0000000..8aabf8f --- /dev/null +++ b/src/lib/appwrite.ts @@ -0,0 +1,16 @@ +import {Account, Client, Functions, TablesDB} from 'appwrite'; +import {environment} from '@environments/environment'; + +export const client = new Client(); + +client + .setEndpoint(environment.appwriteEndpoint + "/v1") + .setProject(environment.appwriteProjectId); + +export const account = new Account(client); +export const tables = new TablesDB(client); +export const functions = new Functions(client); + +export const functionsList = { + link_on_user_creation_anonymous: "66547d62eb180540b016" +}; \ No newline at end of file diff --git a/src/lib/auth.service.ts b/src/lib/auth.service.ts new file mode 100644 index 0000000..e62a7bf --- /dev/null +++ b/src/lib/auth.service.ts @@ -0,0 +1,75 @@ +import {Injectable, signal} from "@angular/core"; +import {Models} from "appwrite"; +import {account, functions, functionsList, tables} from "./appwrite"; +import {Key} from "./types"; +import {environment} from "@environments/environment"; + +@Injectable({providedIn: 'root'}) +export class AuthService { + private _user = signal({} as Models.User); + public user = this._user.asReadonly() + + private _key = signal({} as Key) + public key = this._key.asReadonly(); + public isAnon = signal(true); + + async initializeUser() { + return account.get() + .then(async user => { + this._user.set(user); + this.isAnon.set(user.email === ""); + this._key.set(await this.getKey(!this.isAnon()) + .catch(e => { + if (e.code === 404) { + this.logout() + } + throw e; + }) + ); + return user; + }) + .catch(async e => { + if (e.code !== 401) { + console.error("Unexpected Error") + throw e; + } else { + // user is not logged in yet + await account.createAnonymousSession(); + this._user.set(await account.get()); + await functions.createExecution( + { + functionId: functionsList["link_on_user_creation_anonymous"], + body: JSON.stringify({ + "policy": "ors_anonymous", // todo: change to some other policy, probably switch to some heigit anon + "tag": "ohsome-now-client" + }) + } + ); + this._key.set(await this.getKey(false)); + return this._user; + } + }) + } + + private async getKey(isFullUser: boolean) { + return await tables.getRow({ + databaseId: "tyk_integration", + tableId: isFullUser ? "basic_keys" : "anonymous_keys", + rowId: this.user()!.$id + }) as unknown as Key; + } + + public login() { + const currentUrl = window.location.href; + window.location.href = `${environment.accountFrontendUrl}/login?redirect=${encodeURIComponent(currentUrl)}`; + } + + public profile() { + window.location.replace(environment.accountFrontendUrl) + } + + public async logout() { + await account.deleteSession({sessionId: 'current'}) + window.location.href = `/dashboard`; + } +} \ No newline at end of file diff --git a/src/app/data.service.spec.ts b/src/lib/data.service.spec.ts similarity index 97% rename from src/app/data.service.spec.ts rename to src/lib/data.service.spec.ts index da84aa0..a5c7cea 100644 --- a/src/app/data.service.spec.ts +++ b/src/lib/data.service.spec.ts @@ -4,8 +4,8 @@ import {HttpClientTestingModule, HttpTestingController} from '@angular/common/ht import {ActivatedRoute} from '@angular/router'; import {DataService} from './data.service'; -import {environment} from '../environments/environment'; -import {IMetaData, IMetadataResponse} from './dashboard/types'; +import {environment} from '@environments/environment'; +import {IMetaData, IMetadataResponse} from './types'; describe('DataService', () => { let service: DataService; diff --git a/src/app/data.service.ts b/src/lib/data.service.ts similarity index 51% rename from src/app/data.service.ts rename to src/lib/data.service.ts index 1a8dbeb..5d385a4 100644 --- a/src/app/data.service.ts +++ b/src/lib/data.service.ts @@ -1,8 +1,8 @@ -import {Injectable, signal} from '@angular/core'; +import {inject, Injectable, signal} from '@angular/core'; import {HttpClient} from '@angular/common/http'; import {BehaviorSubject, catchError, firstValueFrom, map, Observable, retry, tap, throwError} from 'rxjs'; -import {environment} from '../environments/environment'; +import {environment} from '@environments/environment'; import { HexDataType, IHashtag, @@ -13,12 +13,15 @@ import { IWrappedCountryResult, IWrappedPlotResult, IWrappedStatsResult -} from "./dashboard/types"; +} from "./types"; import * as Papa from 'papaparse'; +import {AuthService} from "./auth.service"; @Injectable({providedIn: 'root'}) export class DataService { + private http = inject(HttpClient); + private authService = inject(AuthService); url = environment.ohsomeStatsServiceUrl trendingHashtagLimit = 10 @@ -37,9 +40,10 @@ export class DataService { private _metaData = signal({max_timestamp: "", min_timestamp: ""}) public metaData = this._metaData.asReadonly(); - constructor( - private http: HttpClient, - ) { + private key; + + constructor() { + this.key = this.authService.key; } requestMetadata() { @@ -58,26 +62,40 @@ export class DataService { } requestAllHashtags() { - return this.http.get(`${this.url}/hashtags`) + return this.http.get(`${this.url}/hashtags`, {headers: {"Authorization": this.key().key}}) .pipe( map(res => res.result) ) } requestSummary(params: IQueryParams): Observable { - return this.http.get(`${this.url}/stats?hashtag=${params.hashtag}&startdate=${params.start}&enddate=${params.end}&countries=${params.countries}&topics=${params.topics}`) + return this.http.get(`${this.url}/stats?hashtag=${params.hashtag}&startdate=${params.start}&enddate=${params.end}&countries=${params.countries}&topics=${params.topics}`, {headers: {"Authorization": this.key().key}}) + } + + requestUserSummary(params: IQueryParams) { + return this.http.get( + `${this.url}/user?userId=${params.osm_user_id}&hashtag=${params.hashtag}&startdate=${params.start}&enddate=${params.end}&countries=${params.countries}&topics=${params.topics}`, + {headers: {"Authorization": this.key().key}}) } requestPlot(params: IQueryParams): Observable { - return this.http.get(`${this.url}/stats/interval?hashtag=${params.hashtag}&startdate=${params.start}&enddate=${params.end}&interval=${params.interval}&countries=${params.countries}&topics=${params.topics}`) + return this.http.get(`${this.url}/stats/interval?hashtag=${params.hashtag}&startdate=${params.start}&enddate=${params.end}&interval=${params.interval}&countries=${params.countries}&topics=${params.topics}`, {headers: {"Authorization": this.key().key}}) + } + + requestUserPlot(params: IQueryParams): Observable { + return this.http.get(`${this.url}/user/interval?userId=${params.osm_user_id}&hashtag=${params.hashtag}&startdate=${params.start}&enddate=${params.end}&interval=${params.interval}&countries=${params.countries}&topics=${params.topics}`, {headers: {"Authorization": this.key().key}}) } requestCountryStats(params: any): Observable { - return this.http.get(`${this.url}/stats/country?hashtag=${params['hashtag']}&startdate=${params['start']}&enddate=${params['end']}&topics=${params.topics}`) + return this.http.get(`${this.url}/stats/country?hashtag=${params['hashtag']}&startdate=${params['start']}&enddate=${params['end']}&topics=${params.topics}`, {headers: {"Authorization": this.key().key}}) + } + + requestUserCountryStats(params: any): Observable { + return this.http.get(`${this.url}/user/country?userId=${params.osm_user_id}&hashtag=${params['hashtag']}&startdate=${params['start']}&enddate=${params['end']}&topics=${params.topics}`, {headers: {"Authorization": this.key().key}}) } getTrendingHashtags(params: { start?: string; end?: string; limit?: number; countries?: string; }) { - return this.http.get(`${this.url}/most-used-hashtags?startdate=${params['start']}&enddate=${params['end']}&limit=${params['limit']}&countries=${params['countries']}`) + return this.http.get(`${this.url}/most-used-hashtags?startdate=${params['start']}&enddate=${params['end']}&limit=${params['limit']}&countries=${params['countries']}`, {headers: {"Authorization": this.key().key}}) .pipe( map((response: ITrendingHashtagResponse) => { return response!.result as Array @@ -85,31 +103,41 @@ export class DataService { ) } + private readonly h3Parser = (csv: string): HexDataType[] => { + const parsed = Papa.parse(csv, { header: true, skipEmptyLines: true }); + return (parsed.data as any[]).map(row => ({ + result: Number(row.result), + hex_cell: row.hex_cell + })); + }; + getH3Map(params: { - hashtag: string, - start: string, - end: string, - topic: string, - resolution: number, - countries: string + hashtag: string; + start: string; + end: string; + topic: string; + resolution: number; + countries: string; + osm_user_id?: string; }): Observable { + + const isUserQuery = !!params.osm_user_id; + const endpoint = isUserQuery ? '/user/h3' : '/stats/h3'; + + let reqParamUrl = `hashtag=${params['hashtag']}&startdate=${params['start']}&enddate=${params['end']}&topic=${params['topic']}&resolution=${params['resolution']}&countries=${params['countries']}` + if (isUserQuery) { + reqParamUrl = `userId=${params.osm_user_id}&${reqParamUrl}` + } return this.http.get( - `${this.url}/stats/h3?hashtag=${params['hashtag']}&startdate=${params['start']}&enddate=${params['end']}&topic=${params['topic']}&resolution=${params['resolution']}&countries=${params['countries']}`, - {responseType: 'text'} + `${this.url}${endpoint}?${reqParamUrl}`, + {responseType: 'text', headers: {"Authorization": this.key().key}} ).pipe( - map(csv => { - const parsed = Papa.parse(csv, {header: true, skipEmptyLines: true}); - // parsed is of type ParseResult - // parsed.data is the array of rows - return (parsed.data as any[]).map(row => ({ - result: Number(row.result), - hex_cell: row.hex_cell - })); - }) + map(csv => this.h3Parser(csv)) ); } toggleLiveMode(mode: boolean) { this.bsLive.next(mode) } + } diff --git a/src/app/state.service.spec.ts b/src/lib/state.service.spec.ts similarity index 99% rename from src/app/state.service.spec.ts rename to src/lib/state.service.spec.ts index 9022bad..1d9e383 100644 --- a/src/app/state.service.spec.ts +++ b/src/lib/state.service.spec.ts @@ -4,7 +4,7 @@ import {Router} from '@angular/router'; import {StateService} from './state.service'; import {DataService} from './data.service'; -import {IStateParams, StatsType} from './dashboard/types'; +import {IStateParams, StatsType} from './types'; describe('StateService', () => { let service: StateService; diff --git a/src/app/state.service.ts b/src/lib/state.service.ts similarity index 94% rename from src/app/state.service.ts rename to src/lib/state.service.ts index 5281f4d..8e6f9ed 100644 --- a/src/app/state.service.ts +++ b/src/lib/state.service.ts @@ -1,6 +1,5 @@ -import {effect, Injectable, signal} from '@angular/core'; -import {IStateParams} from "./dashboard/types"; -import {environment} from "../environments/environment"; +import {effect, inject, Injectable, signal} from '@angular/core'; +import {IStateParams} from "./types"; import {DataService} from "./data.service"; import {NavigationEnd, Router} from "@angular/router"; import dayjs from "dayjs"; @@ -11,9 +10,12 @@ import {BehaviorSubject, filter} from "rxjs"; providedIn: 'root' }) export class StateService { + + private dataService = inject(DataService); + private router = inject(Router); + // doing this to be able to mock window easily in tests window = window; - url = environment.ohsomeStatsServiceUrl private initialState = this.initInitialState() @@ -28,16 +30,13 @@ export class StateService { bsActivePage = new BehaviorSubject(undefined); activePage = this.bsActivePage.asObservable(); - constructor( - private dataService: DataService, - private router: Router, - ) { + constructor() { effect(() => { console.info('Query state changed:', this.appState()); // This is THE ONLY PLACE WE WANT URL TO BE UPDATED this.updateURL(this.appState()) }); - if (router.events) { + if (this.router.events) { this.router.events.pipe( filter(event => event instanceof NavigationEnd) ).subscribe((_) => { diff --git a/src/app/toast.service.spec.ts b/src/lib/toast.service.spec.ts similarity index 100% rename from src/app/toast.service.spec.ts rename to src/lib/toast.service.spec.ts diff --git a/src/app/toast.service.ts b/src/lib/toast.service.ts similarity index 100% rename from src/app/toast.service.ts rename to src/lib/toast.service.ts diff --git a/src/app/dashboard/types.d.ts b/src/lib/types.d.ts similarity index 97% rename from src/app/dashboard/types.d.ts rename to src/lib/types.d.ts index 3e81d12..50e6039 100644 --- a/src/app/dashboard/types.d.ts +++ b/src/lib/types.d.ts @@ -108,6 +108,7 @@ export interface IQueryParams { interval: string countries: string topics: string + osm_user_id?: string } export interface IStateParams extends IQueryParams { @@ -196,3 +197,7 @@ export interface ISelectionItem { name: string; value: string; } + +export interface Key extends Models.Row { + key: string; +} diff --git a/src/app/utils.ts b/src/lib/utils.ts similarity index 100% rename from src/app/utils.ts rename to src/lib/utils.ts diff --git a/src/main.ts b/src/main.ts index 8e66bdc..6ff761f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,8 +10,9 @@ import Aura from '@primeuix/themes/aura'; import {AppComponent} from './app/app.component'; import {routes} from './app/app-routing.module'; -import {DataService} from './app/data.service'; -import {ToastService} from './app/toast.service'; +import {DataService} from './lib/data.service'; +import {ToastService} from './lib/toast.service'; +import {AuthService} from './lib/auth.service'; import {registerLocaleData} from '@angular/common'; import en from '@angular/common/locales/en'; @@ -40,7 +41,12 @@ bootstrapApplication(AppComponent, { provideAppInitializer(() => { const dataService = inject(DataService); - return dataService.requestMetadata(); + const authService = inject(AuthService); + console.log("tryToResolve") + return Promise.all( + [dataService.requestMetadata(), + authService.initializeUser()] + ); }) ] }).catch(err => console.error(err)); diff --git a/tsconfig.json b/tsconfig.json index b4c692b..ac8ffd4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,6 +27,14 @@ "ES2023", "dom" ], + "paths": { + "@app/*": [ + "src/app/*" + ], + "@environments/*": [ + "src/environments/*" + ] + }, "skipLibCheck": true }, "angularCompilerOptions": {