Commit 090de8bc by Ooh-Ao

หห

parent d608b7f9
# Gemini Project: myportal-Manage
This file provides context about the myportal-Manage project for the Gemini AI assistant.
## Project Overview
This is an Angular application named "ynex". It appears to be a comprehensive portal with features like authentication, data visualization (charts, grids), and various UI components. The project uses Bitbucket Pipelines for CI/CD and supports internationalization for English and Thai.
## Tech Stack
* **Framework:** Angular 17
* **UI Frameworks:**
* Tailwind CSS
* Angular Material
* Syncfusion (for data grids and pivot tables)
* ng-bootstrap
* **Styling:** SCSS
* **State Management:** Not explicitly defined, likely using RxJS with services.
* **Testing:** Karma and Jasmine
* **CI/CD:** Bitbucket Pipelines
* **Internationalization:** ngx-translate
## Project Structure
* `src/app`: Contains the main application logic.
* `src/app/components`: A large number of reusable UI components.
* `src/app/DPU`: Feature modules for the application.
* `src/app/authentication`: Authentication-related components.
* `src/app/shared`: Shared modules, services, and models.
* `src/assets`: Static assets like images, fonts, and styles.
* `src/assets/i18n`: Translation files.
* `angular.json`: Angular CLI configuration.
* `package.json`: Project dependencies and scripts.
* `bitbucket-pipelines.yml`: CI/CD configuration.
## Development
### Common Commands
* **Run the development server:**
```bash
npm start
```
* **Build the project:**
```bash
npm run build
```
* **Run tests:**
```bash
npm test
```
* **Compile SCSS to CSS:**
```bash
npm run postcss
```
### Internationalization (i18n)
The application uses `ngx-translate` for internationalization. Translation files are located in `src/assets/i18n`.
* `en.json`: English translations
* `th.json`: Thai translations
When adding new text that needs to be translated, you should add it to these files and use the `translate` pipe or service in the application.
...@@ -27,6 +27,9 @@ ...@@ -27,6 +27,9 @@
"@ks89/angular-modal-gallery": "^11.1.1", "@ks89/angular-modal-gallery": "^11.1.1",
"@ng-bootstrap/ng-bootstrap": "^16.0.0", "@ng-bootstrap/ng-bootstrap": "^16.0.0",
"@ng-select/ng-select": "^12.0.6", "@ng-select/ng-select": "^12.0.6",
"@ngrx/effects": "^17.0.0",
"@ngrx/store": "^17.0.0",
"@ngrx/store-devtools": "^17.0.0",
"@ngx-translate/core": "^15.0.0", "@ngx-translate/core": "^15.0.0",
"@ngx-translate/http-loader": "^8.0.0", "@ngx-translate/http-loader": "^8.0.0",
"@syncfusion/ej2-angular-base": "^29.2.4", "@syncfusion/ej2-angular-base": "^29.2.4",
...@@ -121,6 +124,7 @@ ...@@ -121,6 +124,7 @@
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10" "node": ">=10"
...@@ -606,6 +610,7 @@ ...@@ -606,6 +610,7 @@
"version": "17.3.12", "version": "17.3.12",
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-17.3.12.tgz", "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-17.3.12.tgz",
"integrity": "sha512-1F8M7nWfChzurb7obbvuE7mJXlHtY1UG58pcwcomVtpPb+kPavgAO8OEvJHYBMV+bzSxkXt5UIwL9lt9jHUxZA==", "integrity": "sha512-1F8M7nWfChzurb7obbvuE7mJXlHtY1UG58pcwcomVtpPb+kPavgAO8OEvJHYBMV+bzSxkXt5UIwL9lt9jHUxZA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/core": "7.23.9", "@babel/core": "7.23.9",
...@@ -634,6 +639,7 @@ ...@@ -634,6 +639,7 @@
"version": "7.23.9", "version": "7.23.9",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz",
"integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ampproject/remapping": "^2.2.0", "@ampproject/remapping": "^2.2.0",
...@@ -664,12 +670,14 @@ ...@@ -664,12 +670,14 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": {
"version": "6.3.1", "version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"license": "ISC", "license": "ISC",
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
...@@ -1081,6 +1089,7 @@ ...@@ -1081,6 +1089,7 @@
"version": "7.26.10", "version": "7.26.10",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz",
"integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@ampproject/remapping": "^2.2.0", "@ampproject/remapping": "^2.2.0",
...@@ -1111,12 +1120,14 @@ ...@@ -1111,12 +1120,14 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@babel/core/node_modules/semver": { "node_modules/@babel/core/node_modules/semver": {
"version": "6.3.1", "version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"license": "ISC", "license": "ISC",
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
...@@ -3770,29 +3781,6 @@ ...@@ -3770,29 +3781,6 @@
"@fortawesome/fontawesome-svg-core": "~1.2.27 || ~1.3.0-beta2 || ^6.1.0" "@fortawesome/fontawesome-svg-core": "~1.2.27 || ~1.3.0-beta2 || ^6.1.0"
} }
}, },
"node_modules/@fortawesome/fontawesome-common-types": {
"version": "6.7.2",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz",
"integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=6"
}
},
"node_modules/@fortawesome/fontawesome-svg-core": {
"version": "6.7.2",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz",
"integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@fortawesome/fontawesome-common-types": "6.7.2"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@grpc/grpc-js": { "node_modules/@grpc/grpc-js": {
"version": "1.9.15", "version": "1.9.15",
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz",
...@@ -3867,6 +3855,7 @@ ...@@ -3867,6 +3855,7 @@
"version": "8.0.2", "version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"string-width": "^5.1.2", "string-width": "^5.1.2",
...@@ -3884,6 +3873,7 @@ ...@@ -3884,6 +3873,7 @@
"version": "6.2.0", "version": "6.2.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz",
"integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=12" "node": ">=12"
...@@ -3896,6 +3886,7 @@ ...@@ -3896,6 +3886,7 @@
"version": "6.2.1", "version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=12" "node": ">=12"
...@@ -3908,12 +3899,14 @@ ...@@ -3908,12 +3899,14 @@
"version": "9.2.2", "version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@isaacs/cliui/node_modules/string-width": { "node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"eastasianwidth": "^0.2.0", "eastasianwidth": "^0.2.0",
...@@ -3931,6 +3924,7 @@ ...@@ -3931,6 +3924,7 @@
"version": "7.1.0", "version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ansi-regex": "^6.0.1" "ansi-regex": "^6.0.1"
...@@ -3946,6 +3940,7 @@ ...@@ -3946,6 +3940,7 @@
"version": "8.1.0", "version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ansi-styles": "^6.1.0", "ansi-styles": "^6.1.0",
...@@ -4065,13 +4060,6 @@ ...@@ -4065,13 +4060,6 @@
"rxjs": ">=7.5.0" "rxjs": ">=7.5.0"
} }
}, },
"node_modules/@kurkle/color": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
"integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==",
"license": "MIT",
"peer": true
},
"node_modules/@leichtgewicht/ip-codec": { "node_modules/@leichtgewicht/ip-codec": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
...@@ -4935,6 +4923,59 @@ ...@@ -4935,6 +4923,59 @@
"@angular/forms": "^17.0.0-rc.0" "@angular/forms": "^17.0.0-rc.0"
} }
}, },
"node_modules/@ngrx/effects": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-17.0.0.tgz",
"integrity": "sha512-1IK/N4ifyqZFlbstgH+mCBxwNW0FEWTINO2kWEGGb0IZ4lcZaN1GKAqDws69t0011H3bLQePdYLvXH9HJG1qTw==",
"license": "MIT",
"dependencies": {
"@ngrx/operators": "17.0.0-beta.0",
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/core": "^17.0.0",
"@ngrx/store": "17.0.0",
"rxjs": "^6.5.3 || ^7.5.0"
}
},
"node_modules/@ngrx/operators": {
"version": "17.0.0-beta.0",
"resolved": "https://registry.npmjs.org/@ngrx/operators/-/operators-17.0.0-beta.0.tgz",
"integrity": "sha512-EbO8AONuQ6zo2v/mPyBOi4y0CTAp1x4Z+bx7ZF+Pd8BL5ma53BTCL1TmzaeK5zPUe0yApudLk9/ZbHXPnVox5A==",
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"rxjs": "^6.5.3 || ^7.4.0"
}
},
"node_modules/@ngrx/store": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/@ngrx/store/-/store-17.0.0.tgz",
"integrity": "sha512-jIK4r3IUKPjHmhfgnUYrN7eie+NdFfPNArUQiL+NeiEeuomsYWaUF6PwiRSnRCqbZhRMvqPWiIWcd0/ql5YJlg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/core": "^17.0.0",
"rxjs": "^6.5.3 || ^7.5.0"
}
},
"node_modules/@ngrx/store-devtools": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/@ngrx/store-devtools/-/store-devtools-17.0.0.tgz",
"integrity": "sha512-DAi0ABROSUks+T3vhbuzHKmACG5NbbcepfibOsgw6R6btbITW4fT3fXepXOmsymXJRO5dmYv6sSM3PDjV8WF0A==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"@ngrx/store": "17.0.0",
"rxjs": "^6.5.3 || ^7.5.0"
}
},
"node_modules/@ngtools/webpack": { "node_modules/@ngtools/webpack": {
"version": "17.3.17", "version": "17.3.17",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.17.tgz", "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.17.tgz",
...@@ -5020,6 +5061,7 @@ ...@@ -5020,6 +5061,7 @@
"version": "2.2.2", "version": "2.2.2",
"resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz", "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz",
"integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==", "integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"agent-base": "^7.1.0", "agent-base": "^7.1.0",
...@@ -5036,12 +5078,14 @@ ...@@ -5036,12 +5078,14 @@
"version": "10.4.3", "version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/@npmcli/fs": { "node_modules/@npmcli/fs": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz",
"integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"semver": "^7.3.5" "semver": "^7.3.5"
...@@ -5054,6 +5098,7 @@ ...@@ -5054,6 +5098,7 @@
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.8.tgz", "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.8.tgz",
"integrity": "sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==", "integrity": "sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@npmcli/promise-spawn": "^7.0.0", "@npmcli/promise-spawn": "^7.0.0",
...@@ -5074,6 +5119,7 @@ ...@@ -5074,6 +5119,7 @@
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz",
"integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -5083,6 +5129,7 @@ ...@@ -5083,6 +5129,7 @@
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": ">=16" "node": ">=16"
...@@ -5092,12 +5139,14 @@ ...@@ -5092,12 +5139,14 @@
"version": "10.4.3", "version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/@npmcli/git/node_modules/proc-log": { "node_modules/@npmcli/git/node_modules/proc-log": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz",
"integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -5107,6 +5156,7 @@ ...@@ -5107,6 +5156,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"isexe": "^3.1.1" "isexe": "^3.1.1"
...@@ -5122,6 +5172,7 @@ ...@@ -5122,6 +5172,7 @@
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz", "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz",
"integrity": "sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==", "integrity": "sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"npm-bundled": "^3.0.0", "npm-bundled": "^3.0.0",
...@@ -5138,6 +5189,7 @@ ...@@ -5138,6 +5189,7 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz",
"integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -5147,6 +5199,7 @@ ...@@ -5147,6 +5199,7 @@
"version": "5.2.1", "version": "5.2.1",
"resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.2.1.tgz", "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.2.1.tgz",
"integrity": "sha512-f7zYC6kQautXHvNbLEWgD/uGu1+xCn9izgqBfgItWSx22U0ZDekxN08A1vM8cTxj/cRVe0Q94Ode+tdoYmIOOQ==", "integrity": "sha512-f7zYC6kQautXHvNbLEWgD/uGu1+xCn9izgqBfgItWSx22U0ZDekxN08A1vM8cTxj/cRVe0Q94Ode+tdoYmIOOQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@npmcli/git": "^5.0.0", "@npmcli/git": "^5.0.0",
...@@ -5165,6 +5218,7 @@ ...@@ -5165,6 +5218,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
...@@ -5174,6 +5228,7 @@ ...@@ -5174,6 +5228,7 @@
"version": "10.4.5", "version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"foreground-child": "^3.1.0", "foreground-child": "^3.1.0",
...@@ -5194,6 +5249,7 @@ ...@@ -5194,6 +5249,7 @@
"version": "9.0.5", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
...@@ -5209,6 +5265,7 @@ ...@@ -5209,6 +5265,7 @@
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz",
"integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -5218,6 +5275,7 @@ ...@@ -5218,6 +5275,7 @@
"version": "7.0.2", "version": "7.0.2",
"resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz", "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz",
"integrity": "sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==", "integrity": "sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"which": "^4.0.0" "which": "^4.0.0"
...@@ -5230,6 +5288,7 @@ ...@@ -5230,6 +5288,7 @@
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": ">=16" "node": ">=16"
...@@ -5239,6 +5298,7 @@ ...@@ -5239,6 +5298,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"isexe": "^3.1.1" "isexe": "^3.1.1"
...@@ -5254,6 +5314,7 @@ ...@@ -5254,6 +5314,7 @@
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-1.1.0.tgz",
"integrity": "sha512-PfnWuOkQgu7gCbnSsAisaX7hKOdZ4wSAhAzH3/ph5dSGau52kCRrMMGbiSQLwyTZpgldkZ49b0brkOr1AzGBHQ==", "integrity": "sha512-PfnWuOkQgu7gCbnSsAisaX7hKOdZ4wSAhAzH3/ph5dSGau52kCRrMMGbiSQLwyTZpgldkZ49b0brkOr1AzGBHQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^16.14.0 || >=18.0.0" "node": "^16.14.0 || >=18.0.0"
...@@ -5263,6 +5324,7 @@ ...@@ -5263,6 +5324,7 @@
"version": "7.0.4", "version": "7.0.4",
"resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-7.0.4.tgz", "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-7.0.4.tgz",
"integrity": "sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg==", "integrity": "sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@npmcli/node-gyp": "^3.0.0", "@npmcli/node-gyp": "^3.0.0",
...@@ -5279,6 +5341,7 @@ ...@@ -5279,6 +5341,7 @@
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": ">=16" "node": ">=16"
...@@ -5288,6 +5351,7 @@ ...@@ -5288,6 +5351,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"isexe": "^3.1.1" "isexe": "^3.1.1"
...@@ -5606,6 +5670,7 @@ ...@@ -5606,6 +5670,7 @@
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"engines": { "engines": {
...@@ -5993,6 +6058,7 @@ ...@@ -5993,6 +6058,7 @@
"version": "2.3.2", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.3.2.tgz", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.3.2.tgz",
"integrity": "sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==", "integrity": "sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@sigstore/protobuf-specs": "^0.3.2" "@sigstore/protobuf-specs": "^0.3.2"
...@@ -6005,6 +6071,7 @@ ...@@ -6005,6 +6071,7 @@
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@sigstore/core/-/core-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-1.1.0.tgz",
"integrity": "sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==", "integrity": "sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": "^16.14.0 || >=18.0.0" "node": "^16.14.0 || >=18.0.0"
...@@ -6014,6 +6081,7 @@ ...@@ -6014,6 +6081,7 @@
"version": "0.3.3", "version": "0.3.3",
"resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.3.3.tgz", "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.3.3.tgz",
"integrity": "sha512-RpacQhBlwpBWd7KEJsRKcBQalbV28fvkxwTOJIqhIuDysMMaJW47V4OqW30iJB9uRpqOSxxEAQFdr8tTattReQ==", "integrity": "sha512-RpacQhBlwpBWd7KEJsRKcBQalbV28fvkxwTOJIqhIuDysMMaJW47V4OqW30iJB9uRpqOSxxEAQFdr8tTattReQ==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
"node": "^18.17.0 || >=20.5.0" "node": "^18.17.0 || >=20.5.0"
...@@ -6023,6 +6091,7 @@ ...@@ -6023,6 +6091,7 @@
"version": "2.3.2", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.3.2.tgz", "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.3.2.tgz",
"integrity": "sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==", "integrity": "sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@sigstore/bundle": "^2.3.2", "@sigstore/bundle": "^2.3.2",
...@@ -6040,6 +6109,7 @@ ...@@ -6040,6 +6109,7 @@
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz",
"integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -6049,6 +6119,7 @@ ...@@ -6049,6 +6119,7 @@
"version": "2.3.4", "version": "2.3.4",
"resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-2.3.4.tgz", "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-2.3.4.tgz",
"integrity": "sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==", "integrity": "sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@sigstore/protobuf-specs": "^0.3.2", "@sigstore/protobuf-specs": "^0.3.2",
...@@ -6062,6 +6133,7 @@ ...@@ -6062,6 +6133,7 @@
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-1.2.1.tgz", "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-1.2.1.tgz",
"integrity": "sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==", "integrity": "sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@sigstore/bundle": "^2.3.2", "@sigstore/bundle": "^2.3.2",
...@@ -6446,6 +6518,7 @@ ...@@ -6446,6 +6518,7 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz",
"integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^16.14.0 || >=18.0.0" "node": "^16.14.0 || >=18.0.0"
...@@ -6455,6 +6528,7 @@ ...@@ -6455,6 +6528,7 @@
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.1.tgz", "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.1.tgz",
"integrity": "sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==", "integrity": "sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tufjs/canonical-json": "2.0.0", "@tufjs/canonical-json": "2.0.0",
...@@ -6468,6 +6542,7 @@ ...@@ -6468,6 +6542,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
...@@ -6477,6 +6552,7 @@ ...@@ -6477,6 +6552,7 @@
"version": "9.0.5", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
...@@ -6677,16 +6753,6 @@ ...@@ -6677,16 +6753,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/jquery": {
"version": "3.5.33",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.33.tgz",
"integrity": "sha512-SeyVJXlCZpEki5F0ghuYe+L+PprQta6nRZqhONt9F13dWBtR/ftoaIbdRQ7cis7womE+X2LKhsDdDtkkDhJS6g==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/sizzle": "*"
}
},
"node_modules/@types/json-schema": { "node_modules/@types/json-schema": {
"version": "7.0.15", "version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
...@@ -6813,13 +6879,6 @@ ...@@ -6813,13 +6879,6 @@
"@types/send": "*" "@types/send": "*"
} }
}, },
"node_modules/@types/sizzle": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.9.tgz",
"integrity": "sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==",
"license": "MIT",
"peer": true
},
"node_modules/@types/sockjs": { "node_modules/@types/sockjs": {
"version": "0.3.36", "version": "0.3.36",
"resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz",
...@@ -7063,6 +7122,7 @@ ...@@ -7063,6 +7122,7 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
"integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -7148,6 +7208,7 @@ ...@@ -7148,6 +7208,7 @@
"version": "7.1.4", "version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 14" "node": ">= 14"
...@@ -7157,6 +7218,7 @@ ...@@ -7157,6 +7218,7 @@
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
"integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"clean-stack": "^2.0.0", "clean-stack": "^2.0.0",
...@@ -7346,6 +7408,7 @@ ...@@ -7346,6 +7408,7 @@
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/anymatch": { "node_modules/anymatch": {
...@@ -7377,6 +7440,7 @@ ...@@ -7377,6 +7440,7 @@
"version": "5.0.2", "version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/argparse": { "node_modules/argparse": {
...@@ -7530,6 +7594,7 @@ ...@@ -7530,6 +7594,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/base64-js": { "node_modules/base64-js": {
...@@ -7666,6 +7731,7 @@ ...@@ -7666,6 +7731,7 @@
"version": "1.1.12", "version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
...@@ -7761,6 +7827,7 @@ ...@@ -7761,6 +7827,7 @@
"version": "18.0.4", "version": "18.0.4",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz",
"integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@npmcli/fs": "^3.1.0", "@npmcli/fs": "^3.1.0",
...@@ -7784,6 +7851,7 @@ ...@@ -7784,6 +7851,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
...@@ -7793,6 +7861,7 @@ ...@@ -7793,6 +7861,7 @@
"version": "10.4.5", "version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"foreground-child": "^3.1.0", "foreground-child": "^3.1.0",
...@@ -7813,12 +7882,14 @@ ...@@ -7813,12 +7882,14 @@
"version": "10.4.3", "version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/cacache/node_modules/minimatch": { "node_modules/cacache/node_modules/minimatch": {
"version": "9.0.5", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
...@@ -7907,6 +7978,7 @@ ...@@ -7907,6 +7978,7 @@
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 6" "node": ">= 6"
...@@ -7955,19 +8027,6 @@ ...@@ -7955,19 +8027,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/chart.js": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.0.tgz",
"integrity": "sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@kurkle/color": "^0.3.0"
},
"engines": {
"pnpm": ">=8"
}
},
"node_modules/chokidar": { "node_modules/chokidar": {
"version": "3.6.0", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
...@@ -7996,6 +8055,7 @@ ...@@ -7996,6 +8055,7 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": ">=10" "node": ">=10"
...@@ -8015,6 +8075,7 @@ ...@@ -8015,6 +8075,7 @@
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
"integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6" "node": ">=6"
...@@ -8183,6 +8244,7 @@ ...@@ -8183,6 +8244,7 @@
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 6" "node": ">= 6"
...@@ -8248,6 +8310,7 @@ ...@@ -8248,6 +8310,7 @@
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/connect": { "node_modules/connect": {
...@@ -8320,6 +8383,7 @@ ...@@ -8320,6 +8383,7 @@
"version": "1.9.0", "version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/cookie": { "node_modules/cookie": {
...@@ -8498,6 +8562,7 @@ ...@@ -8498,6 +8562,7 @@
"version": "7.0.6", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"path-key": "^3.1.0", "path-key": "^3.1.0",
...@@ -8512,6 +8577,7 @@ ...@@ -8512,6 +8577,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"isexe": "^2.0.0" "isexe": "^2.0.0"
...@@ -8593,6 +8659,7 @@ ...@@ -8593,6 +8659,7 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true,
"license": "MIT", "license": "MIT",
"bin": { "bin": {
"cssesc": "bin/cssesc" "cssesc": "bin/cssesc"
...@@ -8835,6 +8902,7 @@ ...@@ -8835,6 +8902,7 @@
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"dev": true,
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/dir-glob": { "node_modules/dir-glob": {
...@@ -8854,6 +8922,7 @@ ...@@ -8854,6 +8922,7 @@
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/dns-packet": { "node_modules/dns-packet": {
...@@ -8974,6 +9043,7 @@ ...@@ -8974,6 +9043,7 @@
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/echarts": { "node_modules/echarts": {
...@@ -9041,6 +9111,7 @@ ...@@ -9041,6 +9111,7 @@
"version": "0.1.13", "version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
...@@ -9051,6 +9122,7 @@ ...@@ -9051,6 +9122,7 @@
"version": "0.6.3", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
...@@ -9156,6 +9228,7 @@ ...@@ -9156,6 +9228,7 @@
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6" "node": ">=6"
...@@ -9165,6 +9238,7 @@ ...@@ -9165,6 +9238,7 @@
"version": "2.0.3", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
"integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/errno": { "node_modules/errno": {
...@@ -9438,6 +9512,7 @@ ...@@ -9438,6 +9512,7 @@
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz",
"integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==",
"dev": true,
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/express": { "node_modules/express": {
...@@ -9918,6 +9993,7 @@ ...@@ -9918,6 +9993,7 @@
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
"integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"cross-spawn": "^7.0.6", "cross-spawn": "^7.0.6",
...@@ -9934,6 +10010,7 @@ ...@@ -9934,6 +10010,7 @@
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": ">=14" "node": ">=14"
...@@ -9993,6 +10070,7 @@ ...@@ -9993,6 +10070,7 @@
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz",
"integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"minipass": "^7.0.3" "minipass": "^7.0.3"
...@@ -10012,6 +10090,7 @@ ...@@ -10012,6 +10090,7 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/fsevents": { "node_modules/fsevents": {
...@@ -10137,6 +10216,7 @@ ...@@ -10137,6 +10216,7 @@
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported", "deprecated": "Glob versions prior to v9 are no longer supported",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"fs.realpath": "^1.0.0", "fs.realpath": "^1.0.0",
...@@ -10281,6 +10361,7 @@ ...@@ -10281,6 +10361,7 @@
"version": "7.0.2", "version": "7.0.2",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz",
"integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"lru-cache": "^10.0.1" "lru-cache": "^10.0.1"
...@@ -10293,6 +10374,7 @@ ...@@ -10293,6 +10374,7 @@
"version": "10.4.3", "version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/hpack.js": { "node_modules/hpack.js": {
...@@ -10389,6 +10471,7 @@ ...@@ -10389,6 +10471,7 @@
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
"integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
"dev": true,
"license": "BSD-2-Clause" "license": "BSD-2-Clause"
}, },
"node_modules/http-deceiver": { "node_modules/http-deceiver": {
...@@ -10450,6 +10533,7 @@ ...@@ -10450,6 +10533,7 @@
"version": "7.0.2", "version": "7.0.2",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"agent-base": "^7.1.0", "agent-base": "^7.1.0",
...@@ -10488,6 +10572,7 @@ ...@@ -10488,6 +10572,7 @@
"version": "7.0.4", "version": "7.0.4",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz",
"integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"agent-base": "^7.0.2", "agent-base": "^7.0.2",
...@@ -10581,6 +10666,7 @@ ...@@ -10581,6 +10666,7 @@
"version": "6.0.5", "version": "6.0.5",
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.5.tgz", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.5.tgz",
"integrity": "sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==", "integrity": "sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"minimatch": "^9.0.0" "minimatch": "^9.0.0"
...@@ -10593,6 +10679,7 @@ ...@@ -10593,6 +10679,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
...@@ -10602,6 +10689,7 @@ ...@@ -10602,6 +10689,7 @@
"version": "9.0.5", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
...@@ -10664,6 +10752,7 @@ ...@@ -10664,6 +10752,7 @@
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=0.8.19" "node": ">=0.8.19"
...@@ -10673,6 +10762,7 @@ ...@@ -10673,6 +10762,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
"integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
...@@ -10683,6 +10773,7 @@ ...@@ -10683,6 +10773,7 @@
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"once": "^1.3.0", "once": "^1.3.0",
...@@ -10699,6 +10790,7 @@ ...@@ -10699,6 +10790,7 @@
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz",
"integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -10748,6 +10840,7 @@ ...@@ -10748,6 +10840,7 @@
"version": "10.0.1", "version": "10.0.1",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz",
"integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 12" "node": ">= 12"
...@@ -10887,6 +10980,7 @@ ...@@ -10887,6 +10980,7 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
"integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/is-number": { "node_modules/is-number": {
...@@ -11009,6 +11103,7 @@ ...@@ -11009,6 +11103,7 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/isobject": { "node_modules/isobject": {
...@@ -11116,6 +11211,7 @@ ...@@ -11116,6 +11211,7 @@
"version": "3.4.3", "version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"dev": true,
"license": "BlueOak-1.0.0", "license": "BlueOak-1.0.0",
"dependencies": { "dependencies": {
"@isaacs/cliui": "^8.0.2" "@isaacs/cliui": "^8.0.2"
...@@ -11169,6 +11265,7 @@ ...@@ -11169,6 +11265,7 @@
"version": "1.21.7", "version": "1.21.7",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"dev": true,
"license": "MIT", "license": "MIT",
"bin": { "bin": {
"jiti": "bin/jiti.js" "jiti": "bin/jiti.js"
...@@ -11216,6 +11313,7 @@ ...@@ -11216,6 +11313,7 @@
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz",
"integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -11258,6 +11356,7 @@ ...@@ -11258,6 +11356,7 @@
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
"integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
"dev": true,
"engines": [ "engines": [
"node >= 0.2.0" "node >= 0.2.0"
], ],
...@@ -11656,6 +11755,7 @@ ...@@ -11656,6 +11755,7 @@
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/loader-runner": { "node_modules/loader-runner": {
...@@ -11834,6 +11934,7 @@ ...@@ -11834,6 +11934,7 @@
"version": "13.0.1", "version": "13.0.1",
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz",
"integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@npmcli/agent": "^2.0.0", "@npmcli/agent": "^2.0.0",
...@@ -11857,6 +11958,7 @@ ...@@ -11857,6 +11958,7 @@
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz",
"integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -12041,6 +12143,7 @@ ...@@ -12041,6 +12143,7 @@
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
...@@ -12063,6 +12166,7 @@ ...@@ -12063,6 +12166,7 @@
"version": "7.1.2", "version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
...@@ -12072,6 +12176,7 @@ ...@@ -12072,6 +12176,7 @@
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz",
"integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"minipass": "^7.0.3" "minipass": "^7.0.3"
...@@ -12084,6 +12189,7 @@ ...@@ -12084,6 +12189,7 @@
"version": "3.0.5", "version": "3.0.5",
"resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz",
"integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"minipass": "^7.0.3", "minipass": "^7.0.3",
...@@ -12101,6 +12207,7 @@ ...@@ -12101,6 +12207,7 @@
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
"integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"minipass": "^3.0.0" "minipass": "^3.0.0"
...@@ -12113,6 +12220,7 @@ ...@@ -12113,6 +12220,7 @@
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"yallist": "^4.0.0" "yallist": "^4.0.0"
...@@ -12125,12 +12233,14 @@ ...@@ -12125,12 +12233,14 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/minipass-json-stream": { "node_modules/minipass-json-stream": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.2.tgz", "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.2.tgz",
"integrity": "sha512-myxeeTm57lYs8pH2nxPzmEEg8DGIgW+9mv6D4JZD2pa81I/OBjeU7PtICXV6c9eRGTA5JMDsuIPUZRCyBMYNhg==", "integrity": "sha512-myxeeTm57lYs8pH2nxPzmEEg8DGIgW+9mv6D4JZD2pa81I/OBjeU7PtICXV6c9eRGTA5JMDsuIPUZRCyBMYNhg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"jsonparse": "^1.3.1", "jsonparse": "^1.3.1",
...@@ -12141,6 +12251,7 @@ ...@@ -12141,6 +12251,7 @@
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"yallist": "^4.0.0" "yallist": "^4.0.0"
...@@ -12153,12 +12264,14 @@ ...@@ -12153,12 +12264,14 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/minipass-pipeline": { "node_modules/minipass-pipeline": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
"integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"minipass": "^3.0.0" "minipass": "^3.0.0"
...@@ -12171,6 +12284,7 @@ ...@@ -12171,6 +12284,7 @@
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"yallist": "^4.0.0" "yallist": "^4.0.0"
...@@ -12183,12 +12297,14 @@ ...@@ -12183,12 +12297,14 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/minipass-sized": { "node_modules/minipass-sized": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
"integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"minipass": "^3.0.0" "minipass": "^3.0.0"
...@@ -12201,6 +12317,7 @@ ...@@ -12201,6 +12317,7 @@
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"yallist": "^4.0.0" "yallist": "^4.0.0"
...@@ -12213,12 +12330,14 @@ ...@@ -12213,12 +12330,14 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/minizlib": { "node_modules/minizlib": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"minipass": "^3.0.0", "minipass": "^3.0.0",
...@@ -12232,6 +12351,7 @@ ...@@ -12232,6 +12351,7 @@
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"yallist": "^4.0.0" "yallist": "^4.0.0"
...@@ -12244,6 +12364,7 @@ ...@@ -12244,6 +12364,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/mkdirp": { "node_modules/mkdirp": {
...@@ -12312,6 +12433,7 @@ ...@@ -12312,6 +12433,7 @@
"version": "2.7.0", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"any-promise": "^1.0.0", "any-promise": "^1.0.0",
...@@ -12373,6 +12495,7 @@ ...@@ -12373,6 +12495,7 @@
"version": "0.6.4", "version": "0.6.4",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
"integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
...@@ -12744,6 +12867,7 @@ ...@@ -12744,6 +12867,7 @@
"version": "10.3.1", "version": "10.3.1",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.3.1.tgz", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.3.1.tgz",
"integrity": "sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==", "integrity": "sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"env-paths": "^2.2.0", "env-paths": "^2.2.0",
...@@ -12781,6 +12905,7 @@ ...@@ -12781,6 +12905,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
...@@ -12790,6 +12915,7 @@ ...@@ -12790,6 +12915,7 @@
"version": "10.4.5", "version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"foreground-child": "^3.1.0", "foreground-child": "^3.1.0",
...@@ -12810,6 +12936,7 @@ ...@@ -12810,6 +12936,7 @@
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": ">=16" "node": ">=16"
...@@ -12819,6 +12946,7 @@ ...@@ -12819,6 +12946,7 @@
"version": "9.0.5", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
...@@ -12834,6 +12962,7 @@ ...@@ -12834,6 +12962,7 @@
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz",
"integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -12843,6 +12972,7 @@ ...@@ -12843,6 +12972,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"isexe": "^3.1.1" "isexe": "^3.1.1"
...@@ -12864,6 +12994,7 @@ ...@@ -12864,6 +12994,7 @@
"version": "7.2.1", "version": "7.2.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
"integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"abbrev": "^2.0.0" "abbrev": "^2.0.0"
...@@ -12879,6 +13010,7 @@ ...@@ -12879,6 +13010,7 @@
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz",
"integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==",
"dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"hosted-git-info": "^7.0.0", "hosted-git-info": "^7.0.0",
...@@ -12907,13 +13039,6 @@ ...@@ -12907,13 +13039,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/nouislider": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/nouislider/-/nouislider-15.8.1.tgz",
"integrity": "sha512-93TweAi8kqntHJSPiSWQ1o/uZ29VWOmal9YKb6KKGGlCkugaNfAupT7o1qTHqdJvNQ7S0su5rO6qRFCjP8fxtw==",
"license": "MIT",
"peer": true
},
"node_modules/npm": { "node_modules/npm": {
"version": "10.9.3", "version": "10.9.3",
"resolved": "https://registry.npmjs.org/npm/-/npm-10.9.3.tgz", "resolved": "https://registry.npmjs.org/npm/-/npm-10.9.3.tgz",
...@@ -13078,6 +13203,7 @@ ...@@ -13078,6 +13203,7 @@
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.1.tgz", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.1.tgz",
"integrity": "sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==", "integrity": "sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"npm-normalize-package-bin": "^3.0.0" "npm-normalize-package-bin": "^3.0.0"
...@@ -13090,6 +13216,7 @@ ...@@ -13090,6 +13216,7 @@
"version": "6.3.0", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz",
"integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==",
"dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"semver": "^7.1.1" "semver": "^7.1.1"
...@@ -13102,6 +13229,7 @@ ...@@ -13102,6 +13229,7 @@
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz",
"integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -13111,6 +13239,7 @@ ...@@ -13111,6 +13239,7 @@
"version": "11.0.1", "version": "11.0.1",
"resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz",
"integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"hosted-git-info": "^7.0.0", "hosted-git-info": "^7.0.0",
...@@ -13126,6 +13255,7 @@ ...@@ -13126,6 +13255,7 @@
"version": "8.0.2", "version": "8.0.2",
"resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz",
"integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"ignore-walk": "^6.0.4" "ignore-walk": "^6.0.4"
...@@ -13138,6 +13268,7 @@ ...@@ -13138,6 +13268,7 @@
"version": "9.0.0", "version": "9.0.0",
"resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz", "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz",
"integrity": "sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==", "integrity": "sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"npm-install-checks": "^6.0.0", "npm-install-checks": "^6.0.0",
...@@ -13153,6 +13284,7 @@ ...@@ -13153,6 +13284,7 @@
"version": "16.2.1", "version": "16.2.1",
"resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-16.2.1.tgz", "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-16.2.1.tgz",
"integrity": "sha512-8l+7jxhim55S85fjiDGJ1rZXBWGtRLi1OSb4Z3BPLObPuIaeKRlPRiYMSHU4/81ck3t71Z+UwDDl47gcpmfQQA==", "integrity": "sha512-8l+7jxhim55S85fjiDGJ1rZXBWGtRLi1OSb4Z3BPLObPuIaeKRlPRiYMSHU4/81ck3t71Z+UwDDl47gcpmfQQA==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@npmcli/redact": "^1.1.0", "@npmcli/redact": "^1.1.0",
...@@ -13172,6 +13304,7 @@ ...@@ -13172,6 +13304,7 @@
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz",
"integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -15521,6 +15654,7 @@ ...@@ -15521,6 +15654,7 @@
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
...@@ -15530,6 +15664,7 @@ ...@@ -15530,6 +15664,7 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 6" "node": ">= 6"
...@@ -15607,6 +15742,7 @@ ...@@ -15607,6 +15742,7 @@
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"wrappy": "1" "wrappy": "1"
...@@ -15725,6 +15861,7 @@ ...@@ -15725,6 +15861,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
"integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"aggregate-error": "^3.0.0" "aggregate-error": "^3.0.0"
...@@ -15774,12 +15911,14 @@ ...@@ -15774,12 +15911,14 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"dev": true,
"license": "BlueOak-1.0.0" "license": "BlueOak-1.0.0"
}, },
"node_modules/pacote": { "node_modules/pacote": {
"version": "17.0.6", "version": "17.0.6",
"resolved": "https://registry.npmjs.org/pacote/-/pacote-17.0.6.tgz", "resolved": "https://registry.npmjs.org/pacote/-/pacote-17.0.6.tgz",
"integrity": "sha512-cJKrW21VRE8vVTRskJo78c/RCvwJCn1f4qgfxL4w77SOWrTCRcmfkYHlHtS0gqpgjv3zhXflRtgsrUCX5xwNnQ==", "integrity": "sha512-cJKrW21VRE8vVTRskJo78c/RCvwJCn1f4qgfxL4w77SOWrTCRcmfkYHlHtS0gqpgjv3zhXflRtgsrUCX5xwNnQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@npmcli/git": "^5.0.0", "@npmcli/git": "^5.0.0",
...@@ -15941,6 +16080,7 @@ ...@@ -15941,6 +16080,7 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
...@@ -15950,6 +16090,7 @@ ...@@ -15950,6 +16090,7 @@
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
...@@ -15965,6 +16106,7 @@ ...@@ -15965,6 +16106,7 @@
"version": "1.11.1", "version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"dev": true,
"license": "BlueOak-1.0.0", "license": "BlueOak-1.0.0",
"dependencies": { "dependencies": {
"lru-cache": "^10.2.0", "lru-cache": "^10.2.0",
...@@ -15981,6 +16123,7 @@ ...@@ -15981,6 +16123,7 @@
"version": "10.4.3", "version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/path-to-regexp": { "node_modules/path-to-regexp": {
...@@ -16031,6 +16174,7 @@ ...@@ -16031,6 +16174,7 @@
"version": "4.0.7", "version": "4.0.7",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
"integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 6" "node": ">= 6"
...@@ -16267,6 +16411,7 @@ ...@@ -16267,6 +16411,7 @@
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"camelcase-css": "^2.0.1" "camelcase-css": "^2.0.1"
...@@ -16427,6 +16572,7 @@ ...@@ -16427,6 +16572,7 @@
"version": "6.2.0", "version": "6.2.0",
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
"integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
...@@ -16452,6 +16598,7 @@ ...@@ -16452,6 +16598,7 @@
"version": "6.1.2", "version": "6.1.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"cssesc": "^3.0.0", "cssesc": "^3.0.0",
...@@ -16529,6 +16676,7 @@ ...@@ -16529,6 +16676,7 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz",
"integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -16545,6 +16693,7 @@ ...@@ -16545,6 +16693,7 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
"integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/promise-polyfill": { "node_modules/promise-polyfill": {
...@@ -16557,6 +16706,7 @@ ...@@ -16557,6 +16706,7 @@
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
"integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"err-code": "^2.0.2", "err-code": "^2.0.2",
...@@ -16874,6 +17024,7 @@ ...@@ -16874,6 +17024,7 @@
"resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-7.0.1.tgz", "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-7.0.1.tgz",
"integrity": "sha512-8PcDiZ8DXUjLf687Ol4BR8Bpm2umR7vhoZOzNRt+uxD9GpBh/K+CAAALVIiYFknmvlmyg7hM7BSNUXPaCCqd0Q==", "integrity": "sha512-8PcDiZ8DXUjLf687Ol4BR8Bpm2umR7vhoZOzNRt+uxD9GpBh/K+CAAALVIiYFknmvlmyg7hM7BSNUXPaCCqd0Q==",
"deprecated": "This package is no longer supported. Please use @npmcli/package-json instead.", "deprecated": "This package is no longer supported. Please use @npmcli/package-json instead.",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"glob": "^10.2.2", "glob": "^10.2.2",
...@@ -16889,6 +17040,7 @@ ...@@ -16889,6 +17040,7 @@
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz",
"integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"json-parse-even-better-errors": "^3.0.0", "json-parse-even-better-errors": "^3.0.0",
...@@ -16902,6 +17054,7 @@ ...@@ -16902,6 +17054,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
...@@ -16911,6 +17064,7 @@ ...@@ -16911,6 +17064,7 @@
"version": "10.4.5", "version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"foreground-child": "^3.1.0", "foreground-child": "^3.1.0",
...@@ -16931,6 +17085,7 @@ ...@@ -16931,6 +17085,7 @@
"version": "9.0.5", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
...@@ -16984,6 +17139,7 @@ ...@@ -16984,6 +17139,7 @@
"version": "0.2.2", "version": "0.2.2",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
"integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
"dev": true,
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/regenerate": { "node_modules/regenerate": {
...@@ -17202,6 +17358,7 @@ ...@@ -17202,6 +17358,7 @@
"version": "0.12.0", "version": "0.12.0",
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
"integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 4" "node": ">= 4"
...@@ -17808,6 +17965,7 @@ ...@@ -17808,6 +17965,7 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"shebang-regex": "^3.0.0" "shebang-regex": "^3.0.0"
...@@ -17820,6 +17978,7 @@ ...@@ -17820,6 +17978,7 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
...@@ -17924,6 +18083,7 @@ ...@@ -17924,6 +18083,7 @@
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.3.1.tgz", "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.3.1.tgz",
"integrity": "sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==", "integrity": "sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@sigstore/bundle": "^2.3.2", "@sigstore/bundle": "^2.3.2",
...@@ -17993,6 +18153,7 @@ ...@@ -17993,6 +18153,7 @@
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 6.0.0", "node": ">= 6.0.0",
...@@ -18113,6 +18274,7 @@ ...@@ -18113,6 +18274,7 @@
"version": "2.8.7", "version": "2.8.7",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
"integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ip-address": "^10.0.1", "ip-address": "^10.0.1",
...@@ -18127,6 +18289,7 @@ ...@@ -18127,6 +18289,7 @@
"version": "8.0.5", "version": "8.0.5",
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
"integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"agent-base": "^7.1.2", "agent-base": "^7.1.2",
...@@ -18214,6 +18377,7 @@ ...@@ -18214,6 +18377,7 @@
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
"integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"spdx-expression-parse": "^3.0.0", "spdx-expression-parse": "^3.0.0",
...@@ -18224,12 +18388,14 @@ ...@@ -18224,12 +18388,14 @@
"version": "2.5.0", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
"integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
"dev": true,
"license": "CC-BY-3.0" "license": "CC-BY-3.0"
}, },
"node_modules/spdx-expression-parse": { "node_modules/spdx-expression-parse": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"spdx-exceptions": "^2.1.0", "spdx-exceptions": "^2.1.0",
...@@ -18240,6 +18406,7 @@ ...@@ -18240,6 +18406,7 @@
"version": "3.0.22", "version": "3.0.22",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz",
"integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==",
"dev": true,
"license": "CC0-1.0" "license": "CC0-1.0"
}, },
"node_modules/spdy": { "node_modules/spdy": {
...@@ -18291,6 +18458,7 @@ ...@@ -18291,6 +18458,7 @@
"version": "10.0.6", "version": "10.0.6",
"resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz",
"integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"minipass": "^7.0.3" "minipass": "^7.0.3"
...@@ -18361,6 +18529,7 @@ ...@@ -18361,6 +18529,7 @@
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
...@@ -18388,6 +18557,7 @@ ...@@ -18388,6 +18557,7 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
...@@ -18410,6 +18580,7 @@ ...@@ -18410,6 +18580,7 @@
"version": "3.35.0", "version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
"integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/gen-mapping": "^0.3.2",
...@@ -18432,6 +18603,7 @@ ...@@ -18432,6 +18603,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
...@@ -18441,6 +18613,7 @@ ...@@ -18441,6 +18613,7 @@
"version": "10.4.5", "version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"foreground-child": "^3.1.0", "foreground-child": "^3.1.0",
...@@ -18461,6 +18634,7 @@ ...@@ -18461,6 +18634,7 @@
"version": "9.0.5", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
...@@ -18561,6 +18735,7 @@ ...@@ -18561,6 +18735,7 @@
"version": "3.4.17", "version": "3.4.17",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
"integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@alloc/quick-lru": "^5.2.0", "@alloc/quick-lru": "^5.2.0",
...@@ -18598,6 +18773,7 @@ ...@@ -18598,6 +18773,7 @@
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"is-glob": "^4.0.3" "is-glob": "^4.0.3"
...@@ -18610,6 +18786,7 @@ ...@@ -18610,6 +18786,7 @@
"version": "15.1.0", "version": "15.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"postcss-value-parser": "^4.0.0", "postcss-value-parser": "^4.0.0",
...@@ -18627,6 +18804,7 @@ ...@@ -18627,6 +18804,7 @@
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
"integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
...@@ -18662,6 +18840,7 @@ ...@@ -18662,6 +18840,7 @@
"version": "6.1.2", "version": "6.1.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"cssesc": "^3.0.0", "cssesc": "^3.0.0",
...@@ -18689,6 +18868,7 @@ ...@@ -18689,6 +18868,7 @@
"version": "6.2.1", "version": "6.2.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"chownr": "^2.0.0", "chownr": "^2.0.0",
...@@ -18706,6 +18886,7 @@ ...@@ -18706,6 +18886,7 @@
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"minipass": "^3.0.0" "minipass": "^3.0.0"
...@@ -18718,6 +18899,7 @@ ...@@ -18718,6 +18899,7 @@
"version": "3.3.6", "version": "3.3.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"yallist": "^4.0.0" "yallist": "^4.0.0"
...@@ -18730,6 +18912,7 @@ ...@@ -18730,6 +18912,7 @@
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
...@@ -18739,6 +18922,7 @@ ...@@ -18739,6 +18922,7 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"dev": true,
"license": "MIT", "license": "MIT",
"bin": { "bin": {
"mkdirp": "bin/cmd.js" "mkdirp": "bin/cmd.js"
...@@ -18751,6 +18935,7 @@ ...@@ -18751,6 +18935,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/terser": { "node_modules/terser": {
...@@ -18871,6 +19056,7 @@ ...@@ -18871,6 +19056,7 @@
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"any-promise": "^1.0.0" "any-promise": "^1.0.0"
...@@ -18880,6 +19066,7 @@ ...@@ -18880,6 +19066,7 @@
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"thenify": ">= 3.1.0 < 4" "thenify": ">= 3.1.0 < 4"
...@@ -18993,6 +19180,7 @@ ...@@ -18993,6 +19180,7 @@
"version": "0.1.13", "version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
"dev": true,
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/tslib": { "node_modules/tslib": {
...@@ -19005,6 +19193,7 @@ ...@@ -19005,6 +19193,7 @@
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.1.tgz", "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.1.tgz",
"integrity": "sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==", "integrity": "sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tufjs/models": "2.0.1", "@tufjs/models": "2.0.1",
...@@ -19052,6 +19241,7 @@ ...@@ -19052,6 +19241,7 @@
"version": "5.2.2", "version": "5.2.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
...@@ -19151,6 +19341,7 @@ ...@@ -19151,6 +19341,7 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz",
"integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"unique-slug": "^4.0.0" "unique-slug": "^4.0.0"
...@@ -19163,6 +19354,7 @@ ...@@ -19163,6 +19354,7 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz",
"integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"imurmurhash": "^0.1.4" "imurmurhash": "^0.1.4"
...@@ -19268,6 +19460,7 @@ ...@@ -19268,6 +19460,7 @@
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
"dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"spdx-correct": "^3.0.0", "spdx-correct": "^3.0.0",
...@@ -19278,6 +19471,7 @@ ...@@ -19278,6 +19471,7 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz",
"integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"engines": { "engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0" "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
...@@ -20156,6 +20350,7 @@ ...@@ -20156,6 +20350,7 @@
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"isexe": "^2.0.0" "isexe": "^2.0.0"
...@@ -20235,6 +20430,7 @@ ...@@ -20235,6 +20430,7 @@
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ansi-styles": "^4.0.0", "ansi-styles": "^4.0.0",
...@@ -20252,6 +20448,7 @@ ...@@ -20252,6 +20448,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/ws": { "node_modules/ws": {
......
...@@ -32,6 +32,9 @@ ...@@ -32,6 +32,9 @@
"@ks89/angular-modal-gallery": "^11.1.1", "@ks89/angular-modal-gallery": "^11.1.1",
"@ng-bootstrap/ng-bootstrap": "^16.0.0", "@ng-bootstrap/ng-bootstrap": "^16.0.0",
"@ng-select/ng-select": "^12.0.6", "@ng-select/ng-select": "^12.0.6",
"@ngrx/effects": "^17.0.0",
"@ngrx/store": "^17.0.0",
"@ngrx/store-devtools": "^17.0.0",
"@ngx-translate/core": "^15.0.0", "@ngx-translate/core": "^15.0.0",
"@ngx-translate/http-loader": "^8.0.0", "@ngx-translate/http-loader": "^8.0.0",
"@syncfusion/ej2-angular-base": "^29.2.4", "@syncfusion/ej2-angular-base": "^29.2.4",
......
...@@ -104,11 +104,6 @@ export const admin: Routes = [ ...@@ -104,11 +104,6 @@ export const admin: Routes = [
import('./myportal/view-list-course/view-list-course.component').then((m) => m.ViewListCourseComponent), import('./myportal/view-list-course/view-list-course.component').then((m) => m.ViewListCourseComponent),
}, },
{ {
path: 'view-list-widgets',
loadComponent: () =>
import('./myportal/view-list-widgets/view-list-widgets.component').then((m) => m.ViewListWidgetsComponent),
},
{
path: 'excel-report', path: 'excel-report',
loadComponent: () => loadComponent: () =>
import('./myportal/excel-report/excel-report.component').then((m) => m.ExcelReportComponent), import('./myportal/excel-report/excel-report.component').then((m) => m.ExcelReportComponent),
...@@ -134,11 +129,6 @@ export const admin: Routes = [ ...@@ -134,11 +129,6 @@ export const admin: Routes = [
import('./myportal/list-doc/list-doc.component').then((m) => m.ListDocComponent), import('./myportal/list-doc/list-doc.component').then((m) => m.ListDocComponent),
}, },
{ {
path: 'list-widgets',
loadComponent: () =>
import('./myportal/list-widgets/list-widgets.component').then((m) => m.ListWidgetsComponent),
},
{
path: 'excel-list', path: 'excel-list',
loadComponent: () => loadComponent: () =>
import('./myportal/set-excel-reports/excel-list/excel-list.component').then((m) => m.ExcelListComponent), import('./myportal/set-excel-reports/excel-list/excel-list.component').then((m) => m.ExcelListComponent),
......
<app-page-header [title]="'รายการวิทเจ็ด'" [activeTitle]="'ผู้ดูแลระบบ'"
[title1]="'รายการอัพโหลดเอกสาร Widget'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}}
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2"
(click)="openEditExcelDialog()"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาบริษัท"
aria-label=".form-control-sm example" [(ngModel)]="search" (ngModelChange)="onSearchChange()">
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive" *ngIf="checkType !== '1'">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder text-white" style="background-color: #49b6f5;">
<th scope="col" class="text-start">#</th>
<th scope="col" class="text-start">รูปภาพ</th>
<th scope="col" class="text-start">ชื่อ</th>
<th scope="col" class="text-start">รายละเอียด</th>
<th scope="col" class="text-start">ลิงค์</th>
<th scope="col" class="text-start">ไฟล์</th>
<th scope="col" class="text-start">สถานะ</th>
<th scope="col" class="text-start">การจัดการ</th>
</tr>
</thead>
<tbody>
<tr class="border border-defaultborder dark:border-defaultborder/10"
*ngFor="let data of paginatedWidgets; let i = index">
<td>
<div>
<span class="block mb-1">
{{pageIndex * pageSize + i + 1}} </span>
</div>
</td>
<td>
<div class="flex items-center">
<span class="p-3 me-1" style="width: 200px;">
<img src="{{data.getImage()}}" (click)="openEmployeeDialog(data.getImage())" id="profile-img"
class="border-radius-1 cursor-pointer" style="width: 180px; height: 120px; object-fit: cover;">
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
{{ data.widgetTname }}
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
{{ data.thDesc }}
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
<i class="fa fa-link text-blue-600 text-base flex-shrink-0 cursor-pointer active: hover:text-danger hover:scale-125 transition duration-300"
(click)="openLink(data.link1)" style="font-size: 20px;"></i>
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
<i class="fa fa-download text-blue-600 text-base flex-shrink-0 cursor-pointer active hover:text-success hover:scale-125 transition duration-300"
(click)="downloadFile(data.widgetId)" style="font-size: 20px;"></i>
</span>
</div>
</td>
<td>
<div>
<ng-container *ngIf="data.status === 0">
<span class="badge bg-amber-300 text-white">
รออนุมัติ </span>
</ng-container>
<ng-container *ngIf="data.status === 1">
<span class="badge bg-success text-white">
เปิดใช้งาน </span>
</ng-container>
<ng-container *ngIf="data.status === 2">
<span class="badge bg-gray-500 text-white">
ไม่อนุมัติ </span>
</ng-container>
</div>
</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="openEditExcelDialog(data)"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info">
<i class="ri-pencil-line"></i>
</a>
<a aria-label="anchor" href="javascript:void(0);" (click)="deleteFile(data)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger">
<i class="ri-delete-bin-line"></i>
</a>
</div>
</td>
</tr>
<tr *ngIf="paginatedWidgets.length === 0">
<td colspan="9" class="text-center py-4">ไม่พบข้อมูล</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto">
<div class="mb-2 sm:mb-0">
<select class="custom-select m-r-5" style="width: auto" [(ngModel)]="pageSize"
(ngModelChange)="goToPage(0)">
<option [ngValue]="10">รายการต่อหน้า: 10</option>
<option [ngValue]="50">รายการต่อหน้า: 50</option>
<option [ngValue]="100">รายการต่อหน้า: 100</option>
</select>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0 flex">
<li class="page-item" [class.disabled]="pageIndex === 0">
<a class="page-link px-3 py-[0.375rem] cursor-pointer" (click)="goToPage(pageIndex - 1)">
{{ 'Previous' | translate }}
</a>
</li>
<ng-container *ngFor="let p of pages">
<li class="page-item" [class.active]="p === pageIndex">
<a class="page-link px-3 py-[0.375rem] cursor-pointer" [class.active]="p === pageIndex"
(click)="goToPage(p)">
{{ p + 1 }} </a>
</li>
</ng-container>
<li class="page-item" [class.disabled]="pageIndex === totalPages - 1 || totalPages === 0">
<a class="page-link px-3 py-[0.375rem] cursor-pointer" (click)="goToPage(pageIndex + 1)">
{{ 'Next' | translate }}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #editTemplateModal let-modal>
<div class="modal-headtitle ti-modal-header flex justify-between items-center p-4" style="background-color: #fefbfb;">
<h3 class="modal-title text-sm font-semibold text-defaulttextcolor" id="edittemplateLabel">
{{ checkEdit ? ('แก้ไขไฟล์ Widget' | translate) : ('เพิ่มไฟล์ Widget' | translate) }}
</h3>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(click)="closeDialog()" #closeModal> <span class="sr-only">{{ 'Close' | translate }}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="w-full flex justify-end">
<div class="absolute flex">
<div class="px-1">
</div>
</div>
</div>
<mat-dialog-content style="padding: 0px; padding-left: 20px; padding-right: 20px;">
<div class="box p-9 top-4">
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-6 col-span-12">
<label for="nameth" class="block text-primary mb-2 font-bold font-14">{{ 'ชื่อวิทเจ็ด (ไทย)' | translate
}}</label>
<input type="text"
class="form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="nameth" [(ngModel)]="modelWidget.widgetTname" name="widgetTname">
</div>
<div class="xl:col-span-6 col-span-12">
<label for="nameeng" class="block text-primary mb-2 font-bold font-14">{{ 'ชื่อวิทเจ็ด (อังกฤษ)' | translate
}}</label>
<input type="text"
class="form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="nameeng" [(ngModel)]="modelWidget.widgetEname" name="widgetEname">
</div>
<div class="xl:col-span-12 col-span-12">
<label for="thDesc" class="block text-primary mb-2 font-bold font-14">{{ 'รายละเอียด (ไทย)' | translate
}}</label>
<textarea
class="form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="thDesc" [(ngModel)]="modelWidget.thDesc" rows="3" name="thDesc"></textarea>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="engDesc" class="block text-primary mb-2 font-bold font-14">{{ 'รายละเอียด (อังกฤษ)' | translate
}}</label>
<textarea
class="form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="engDesc" [(ngModel)]="modelWidget.engDesc" rows="3" name="engDesc"></textarea>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="group" class="block text-primary mb-2 font-bold font-14">{{ 'ภาษาที่รองรับ' | translate }}</label>
<select
class="custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="status" [(ngModel)]="modelWidget.status" name="status">
<option [value]="0">Private</option>
<option [value]="1">Public</option>
</select>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="dbSupport" class="block text-primary mb-2 font-bold font-14">{{ 'ดาต้าเบสที่รองรับ' | translate
}}</label>
<select
class="custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="dbSupport" [(ngModel)]="modelWidget.dbSupport" name="dbSupport">
<option value="SQLServer">SQLServer</option>
<option value="PostgreSQL">PostgreSQL</option>
<option value="Oracle">Oracle</option>
</select>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="fileUpload" class="block text-primary mb-2 font-bold font-14">{{ 'ไฟล์อัพโหลด' | translate
}}</label>
<div class="flex items-center gap-2">
<input type="file"
class="form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="fileUpload" (change)="onSelectFile($event)">
<button *ngIf="modelWidget.widgetObj && checkEdit" (click)="downloadFile(modelWidget.widgetId)"
class="ti-btn ti-btn-primary flex-shrink-0 px-4 py-2 rounded-md transition-all duration-200">
<i class="fas fa-download mr-1"></i> {{ 'ดาวน์โหลด' | translate }}
</button>
</div>
<div class="msg-detail text-sm text-red mt-1"> ไฟล์ที่อนุญาต:*.xlsx *.xlsm
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="imageUpload" class="block text-primary mb-2 font-bold font-14">{{ 'รูปภาพตัวอย่าง' | translate
}}</label>
<div class="flex items-center gap-2">
<input type="file"
class="form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="imageUpload" (change)="onUploadImage($event)">
</div>
<div class="msg-detail text-sm text-red mt-1"> ไฟล์ที่อนุญาต:*.jpeg, *.jpg, *.png
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="linkExample" class="block text-primary mb-2 font-bold font-14">{{ 'Link ตัวอย่าง' | translate
}}</label>
<input type="text"
class="form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="linkExample" [(ngModel)]="modelWidget.link1" name="link1">
</div>
<div class="xl:col-span-12 col-span-12">
<label for="tags" class="block text-primary mb-2 font-bold font-14">{{ 'แท็ก' | translate }}</label>
<tag-input [theme]="'bootstrap'" [(ngModel)]='modelWidget.tags' placeholder="{{ '+แท็ก' | translate }}"
[onlyFromAutocomplete]="true" secondaryPlaceholder="{{ 'กดปุ่ม Enter เพื่อเพิ่มแท็กใหม่' | translate }}"
[addOnBlur]="true" [clearOnBlur]="true" class="w-full" name="tags">
<tag-input-dropdown [autocompleteItems]="listTag" [showDropdownIfEmpty]="true">
</tag-input-dropdown>
</tag-input>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="group" class="block text-primary mb-2 font-bold font-14">{{ 'กลุ่ม' | translate }}</label>
<select
class="custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="group" [(ngModel)]="modelWidget.group.groupId" (change)="selectGroup()" name="group">
<option *ngFor="let item of listGroup" [ngValue]="item.groupId">{{item.thName}}</option>
</select>
</div>
<div class="xl:col-span-12 col-span-12">
<label class="block text-primary mb-2 font-bold font-14">{{ 'แสดงรูปแบบ Pivot' | translate }}</label>
<div class="flex items-center gap-4 mt-2">
<div class="flex items-center">
<input type="radio" class="form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id="pivot0" name="radio-pivot" [value]="0" [(ngModel)]="modelWidget.isPivot">
<label class="ml-2 text-gray-700" for="pivot0">{{ 'ใช่' | translate }}</label>
</div>
<div class="flex items-center">
<input type="radio" class="form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id="pivot1" name="radio-pivot" [value]="1" [(ngModel)]="modelWidget.isPivot">
<label class="ml-2 text-gray-700" for="pivot1">{{ 'ไม่ใช่' | translate }}</label>
</div>
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label class="block text-primary mb-2 font-bold font-14">{{ 'แสดงรูปแบบ DataGrid' | translate }}</label>
<div class="flex items-center gap-4 mt-2">
<div class="flex items-center">
<input type="radio" class="form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id="datagrid0" name="datagridCheck" [value]="0" [(ngModel)]="modelWidget.isDataGrid">
<label class="ml-2 text-gray-700" for="datagrid0">{{ 'ใช่' | translate }}</label>
</div>
<div class="flex items-center">
<input type="radio" class="form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id="datagrid1" name="datagridCheck" [value]="1" [(ngModel)]="modelWidget.isDataGrid">
<label class="ml-2 text-gray-700" for="datagrid1">{{ 'ไม่ใช่' | translate }}</label>
</div>
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="remark" class="block text-primary mb-2 font-bold font-14">{{ 'หมายเหตุ' | translate }}</label>
<textarea
class="form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="remark" [(ngModel)]="modelWidget.remark" rows="4" name="remark"></textarea>
</div>
</div>
</div>
</mat-dialog-content>
<mat-dialog-actions style="justify-content: end;">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle" (click)="closeDialog()">
{{ 'Cancel' | translate }}
</button>
<button type="submit" class="ti-btn bg-primary text-white !font-medium"
[class.ti-btn-disabled]="!modelWidget.widgetTname||!modelWidget.widgetEname"
[disabled]="!modelWidget.widgetTname||!modelWidget.widgetEname" (click)="onSumit()">
{{ 'Save' | translate }}
</button>
</mat-dialog-actions>
</ng-template>
\ No newline at end of file
::ng-deep ng2-dropdown-menu {
z-index: 9999 !important;
.ng2-dropdown-menu {
z-index: 9999 !important;
ng2-menu-item {
z-index: 9999 !important;
}
}
}
\ No newline at end of file
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { NgbModal, NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';
import { AlertModalComponent } from '../alert-modal/alert-modal.component';
import { UploadService } from '../../../services/upload.service';
import { TagService } from '../../../services/tag.service';
import { TagModel } from '../../../models/tag.mmodel';
import { GroupModel } from '../../../models/group.mmodel';
import { OpenImageComponent } from '../open-image/open-image.component';
import { GroupService } from '../../../services/group.service';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { NgSelectModule } from '@ng-select/ng-select';
import { SharedModule } from '../../../../shared/shared.module';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { TranslateModule } from '@ngx-translate/core';
import saveAs from 'file-saver';
import { TagInputModule } from 'ngx-chips';
import swal from 'sweetalert';
import { WidgetModel } from '../../../models/widgets.model';
import { WidgetService } from '../../../services/widgets.service';
@Component({
selector: 'app-list-widgets',
templateUrl: './list-widgets.component.html',
styleUrls: ['./list-widgets.component.scss'],
standalone: true,
imports: [
CommonModule,
FormsModule,
RouterModule,
NgSelectModule,
SharedModule,
MatDialogModule,
TranslateModule,
NgbPaginationModule,
TagInputModule,
],
})
export class ListWidgetsComponent implements OnInit {
@ViewChild("editTemplateModal") editTemplateModalRef!: TemplateRef<any>;
checkType: string = '';
page = 1;
pageSize = 10;
pageIndex: number = 0;
maxPagesToShow: number = 3;
// Initialize with empty arrays to prevent undefined errors before data loads
listWidgets: WidgetModel[] = []; // This will now store the filtered list
originallistWidgets: WidgetModel[] = []; // This will store the raw data from API
paginatedWidgets: WidgetModel[] = []; // This will store the sliced data for the current page
dialogRef: any;
modelWidget: WidgetModel = new WidgetModel({});
checkEdit: boolean = false;
search: string = '';
listTag: TagModel[] = [];
listGroup: GroupModel[] = [];
constructor(private modalService: NgbModal, private widgetService: WidgetService,
private uploadService: UploadService,
private tagService: TagService,
private groupService: GroupService,
private dialog: MatDialog,) {
}
// Central method for filtering and pagination
applyFilterAndPagination() {
// Ensure `originallistWidgets` is the source for filtering
this.listWidgets = this.originallistWidgets.filter(x =>
x.widgetTname.toLowerCase().includes(this.search.toLowerCase()) ||
x.widgetEname.toLowerCase().includes(this.search.toLowerCase())
);
const totalPagesAfterFilter = Math.ceil(this.listWidgets.length / this.pageSize);
if (this.pageIndex >= totalPagesAfterFilter && totalPagesAfterFilter > 0) {
this.pageIndex = totalPagesAfterFilter - 1;
} else if (totalPagesAfterFilter === 0) {
this.pageIndex = 0;
}
const startIndex = this.pageIndex * this.pageSize;
const endIndex = startIndex + this.pageSize;
this.paginatedWidgets = this.listWidgets.slice(startIndex, endIndex);
}
onSelectFile(event: any) {
if (event.target.files && event.target.files[0]) {
const reader = new FileReader();
const file: File = event.target.files[0];
console.log("🚀 ~ listWidgetsComponent ~ onSelectFile ~ file:", file)
reader.readAsDataURL(event.target.files[0]); // read file as data url
reader.onload = (event) => { // called once readAsDataURL is completed
if (event) {
const allowedTypes = ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel.sheet.macroEnabled.12'];
if (!allowedTypes.includes(file.type)) {
this.openAlertModalWithMatDialog('อัพโหลดได้เฉพาะไฟล์ *.xlsx *.xlsm เท่านั้น');
} else {
let base64 = event.target!.result as string;
this.modelWidget.widgetObj = base64.split(',')[1];
this.modelWidget.fileType = file.name.split('.')[file.name.split('.').length - 1];
}
}
};
}
}
async downloadFile(logId: string) {
try {
// Assuming modelWidget.fileType is available and correct after a file has been selected/uploaded
// If not, you might need to get the file type from the service or infer it.
const data = await this.widgetService.downloadFile(logId).toPromise();
if (data) {
const fileName = `${logId}.${this.modelWidget.fileType || 'xlsx'}`; // Fallback to 'xlsx'
saveAs(new Blob([data]), fileName);
}
} catch (error) {
console.error('Error downloading file:', error);
this.openAlertModalWithMatDialog('ไม่สามารถดาวน์โหลดไฟล์ได้');
}
}
async getListGroup() {
try {
const data = await this.groupService.getList().toPromise();
this.listGroup = data!.map(x => new GroupModel(x));
} catch (error) {
console.error('Error loading groups:', error);
this.openAlertModalWithMatDialog('ไม่สามารถโหลดรายการกลุ่มได้');
}
}
selectGroup() {
let findData = this.listGroup.find(x => x.groupId === this.modelWidget.group.groupId);
this.modelWidget.group = findData ? new GroupModel(findData) : new GroupModel({});
}
async onUploadImage(event: any) {
try {
if (event.target.files.length > 0) {
let fileData = event.target.files[0];
const formData = new FormData();
formData.append('file', fileData);
const allowedTypes = ['image/png', 'image/jpeg', 'image/jpg'];
if (!allowedTypes.includes(fileData.type)) {
this.openAlertModalWithMatDialog('อัพโหลดได้เฉพาะไฟล์ *.jpeg, *.jpg, *.png เท่านั้น');
} else {
const data = await this.uploadService.uploadImage(formData).toPromise();
if (data) {
this.modelWidget.picture = data.body.fileId;
}
}
}
} catch (error) {
console.error('Error uploading image:', error);
this.openAlertModalWithMatDialog('เกิดข้อผิดพลาดในการอัปโหลดรูปภาพ');
}
}
deleteFile(item: WidgetModel) {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณต้องการลบข้อมูลนี้หรือไม่",
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ยืนยัน"],
}).then((willDelete: boolean) => {
if (willDelete) {
this.widgetService.deleteWidget(item).subscribe(result => {
if (result) {
swal("ลบสำเร็จ!!", "บันทึกข้อมูลสำเร็จ", "success");
this.getListWidgets(); // Re-fetch and re-apply filter/pagination
} else {
swal("สำเร็จบางส่วน/ข้อผิดพลาด!!", "มีการลบข้อมูลบางส่วนไม่สำเร็จ หรือมีข้อผิดพลาด", "warning");
}
}, error => {
this.openAlertModalWithMatDialog(error.message);
});
}
});
}
openAlertModalWithMatDialog(message?: string) {
this.dialog.open(AlertModalComponent, {
data: { message: message ? message : "" },
width: '400px',
disableClose: true,
});
}
onUpdate() {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณต้องการอัพเดทข้อมูลหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
}).then((willUpdate: boolean) => {
if (willUpdate) {
console.log(this.modelWidget);
this.widgetService.createWidget(this.modelWidget).subscribe(res => {
if (res) {
swal("บันทึกสำเร็จ!!", "อัพเดทข้อมูลสำเร็จ", "success");
this.closeDialog();
this.getListWidgets(); // Re-fetch and re-apply filter/pagination
} else {
swal('ไม่สามารถอัพเดทข้อมูลได้');
}
}, error => {
console.error("เกิดข้อผิดพลาดในการบันทึก/อัปเดต:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถบันทึก/อัปเดตข้อมูลได้", "error");
});
}
});
}
onCreate() {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
}).then((willSave: boolean) => {
if (willSave) {
this.widgetService.createWidget(this.modelWidget).subscribe(res => {
if (res) {
swal("บันทึกสำเร็จ!!", "บันทึกข้อมูลสมาชิก", "success");
this.closeDialog();
this.getListWidgets(); // Re-fetch and re-apply filter/pagination
} else {
swal('ไม่สามารถสร้างเอกสารได้');
}
}, error => {
console.error("เกิดข้อผิดพลาดในการบันทึก/อัปเดต:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถบันทึก/อัปเดตข้อมูลได้", "error");
});
}
});
}
onSumit() {
if (this.checkEdit) {
this.onUpdate();
} else {
this.onCreate();
}
}
// This method openModal with NgbModal is currently unused as MatDialog is used for edit template.
// If not explicitly needed for other NgbModal usage, it can be removed.
async getWidgetById(targetModal: NgbModal, id: string) {
try {
const data = await this.widgetService.getWidgetById(id).toPromise();
this.modelWidget = new WidgetModel(data!);
if (data) {
this.modalService.open(targetModal, {
centered: true,
backdrop: 'static',
size: 'lg'
});
}
} catch (error) {
console.error('Error loading data:', error);
}
}
getStatus(status: string): string {
if (status === '0') {
return 'Private';
} else if (status === '1') {
return 'Public';
} else {
return 'ไม่ทราบสถานะ';
}
}
async getListWidgets() {
try {
const data = await this.widgetService.getListWidgets().toPromise();
this.originallistWidgets = data!.map(x => new WidgetModel(x)); // Populate original list
this.applyFilterAndPagination(); // Apply filter and pagination after fetching
} catch (error) {
console.error('Error loading data:', error);
this.openAlertModalWithMatDialog('ไม่สามารถโหลดรายการ Widget ได้');
}
}
get totalFilteredItems(): number {
return this.listWidgets.length; // `listWidgets` now holds the filtered count
}
get totalPages(): number {
return Math.ceil(this.totalFilteredItems / this.pageSize);
}
get startItemIndex(): number {
if (this.totalFilteredItems === 0) return 0;
return this.pageIndex * this.pageSize + 1;
}
get endItemIndex(): number {
const end = Math.min((this.pageIndex + 1) * this.pageSize, this.totalFilteredItems);
return end;
}
goToPage(page: number) {
if (page >= 0 && page < this.totalPages) {
this.pageIndex = page;
this.applyFilterAndPagination(); // Re-apply filter and pagination
} else if (this.totalPages === 0 && page === 0) {
this.pageIndex = 0;
this.applyFilterAndPagination();
}
}
onSearchChange() {
this.pageIndex = 0; // Reset to the first page when search changes
this.applyFilterAndPagination(); // Re-apply filter and pagination
}
get pages(): number[] {
const pages: number[] = [];
const startPage = Math.max(0, this.pageIndex - Math.floor(this.maxPagesToShow / 2));
const endPage = Math.min(this.totalPages - 1, startPage + this.maxPagesToShow - 1);
for (let i = startPage; i <= endPage; i++) {
pages.push(i);
}
return pages;
}
ngOnInit() {
this.getListWidgets(); // Initial data fetch and display
this.getListTag();
this.getListGroup();
}
async getListTag() {
try {
// Assuming tagService.getListWidgets() is the correct method for tags
const data = await this.tagService.getList().toPromise(); // Assuming general getList
this.listTag = data!.map(x => new TagModel(x));
} catch (error) {
console.error('Error loading tags:', error);
this.openAlertModalWithMatDialog('ไม่สามารถโหลดรายการแท็กได้');
}
}
openEmployeeDialog(image: string) {
const dialogConfig = {
width: '750px',
disableClose: false,
data: {
linkImage: image
},
panelClass: 'my-dialog-img-preview',
};
this.dialogRef = this.dialog.open(OpenImageComponent, dialogConfig);
this.dialogRef.afterClosed().subscribe((result: any) => {
console.log('The dialog was closed', result);
}, (reason: any) => {
});
}
openEditExcelDialog(item?: WidgetModel) {
if (item) {
this.widgetService.getWidgetById(item.widgetId).toPromise().then(data => {
if (data) {
this.modelWidget = new WidgetModel(data!);
this.checkEdit = true;
}
this.dialogRef = this.dialog.open(this.editTemplateModalRef, {
width: '1100px',
disableClose: true,
});
this.dialogRef.afterClosed().subscribe((result: boolean) => {
console.log('Edit Widget dialog closed with result:', result);
if (result === true) {
this.getListWidgets(); // Refresh list on success
}
});
}).catch(error => {
console.error('Error loading data for edit:', error);
this.openAlertModalWithMatDialog('ไม่สามารถโหลดข้อมูลเพื่อแก้ไขได้');
});
} else {
this.modelWidget = new WidgetModel({});
this.checkEdit = false;
this.dialogRef = this.dialog.open(this.editTemplateModalRef, {
width: '800px',
disableClose: true,
});
this.dialogRef.afterClosed().subscribe((result: boolean) => {
console.log('Edit Widget dialog closed with result:', result);
if (result === true) {
this.getListWidgets(); // Refresh list on success
}
});
}
}
closeDialog() {
if (this.dialogRef) {
this.dialogRef.close();
}
}
closeBtnClick() {
this.modalService.dismissAll();
}
openLink(url: string) {
window.open(url, "_blank");
}
}
\ No newline at end of file
<app-page-header [title]="'รายการวิทเจ็ท'" [activeTitle]="'ผู้ดูแลระบบ'"
[title1]="'รายการวิทเจ็ท'"></app-page-header>
<!-- <div class="row">
<div class="col-12">
<div class="py-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search">
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-4 mb-3" *ngFor="let data of filterListWidget()">
<div class="card border-5 border border-widget h-100 shadow">
<div class=" p-2 border-5">
<img width="100" class="card-img-top cover" src="{{data.getImage()}}"
(click)="openEmployeeModal(data.getImage())">
</div>
<div class="card-body">
<h4 class="card-title">{{ data.widgetTname }}</h4>
<p class="card-text ">{{ data.thDesc }}</p>
<p class="text-info pointer mb-0" (click)="downloadFile(data.widgetId)"><i class="fas fa-download mr-1"></i>
ดาวน์โหลด <small class="text-muted" *ngIf="data.dwTime > 0">{{coverDate(data.downloadDate)}}
{{data.downloadTime}} ( {{data.dwTime}} ครั้ง)</small></p>
<p class="text-info pointer mb-0" (click)="openLink(data.link1)"><i class="fas fa-link mr-1"></i>
ตัวอย่างวิธีใช้งาน</p>
</div>
<div class="card-footer border-bottom-5">
<small class="text-muted">วันที่อัพโหลด {{coverDate(data.uploadDate)}} {{data.uploadTime}}</small>
</div>
</div>
</div>
</div> -->
<div class="box p-4">
<div class="flex flex-wrap -mx-2">
<div class="w-full">
<div class="py-3 px-2">
<input type="text"
class="block w-full md:w-1/4 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 shadow-sm"
placeholder="ค้นหา" [(ngModel)]="search" />
</div>
</div>
<div class="w-full sm:w-1/2 lg:w-1/3 xl:w-1/3 px-2 mb-4" *ngFor="let data of filterListWidget()">
<div
class="group bg-white rounded-lg overflow-hidden shadow-lg border-4 border-blue-600 h-full flex flex-col transform transition-all duration-300 ease-in-out hover:scale-[1.02] hover:shadow-xl">
<div class="p-4 flex justify-center items-center flex-shrink-0">
<img
class="w-full h-full object-cover rounded-md shadow-md transform transition-transform duration-300 group-hover:scale-105 cursor-pointer"
style="width: 400px; height: 200px; max-width: 100%;" src="{{ data.getImage() }}" alt="{{ data.widgetTname }}"
(click)="openDialog(data.getImage())" />
</div>
<div class="p-4 flex-grow">
<span class="text-xl font-semibold text-gray-800 mb-2" style="font-size: 18px;">
{{ data.widgetTname }}
</span>
<p class="text-gray-700 text-sm mb-3">{{ data.thDesc }}</p>
<div class="mb-0 flex items-center justify-center sm:justify-start gap-2 w-1/2 mt-5">
<i class="fa fa-link text-blue-600 text-base flex-shrink-0" aria-hidden="true"></i>
<input type="text" [value]="'ตัวอย่างวิธีใช้งาน'" (click)="openLink(data.link1)"
style="background-color: rgb(76, 117, 207, 1); color: #FFF;"
class="flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly />
</div>
<div class="mb-2 flex items-center justify-center sm:justify-start gap-2 w-1/2">
<i class="fa fa-download text-blue-600 text-base flex-shrink-0" aria-hidden="true"></i>
<input type="text" [value]="'ดาวน์โหลด'" (click)="downloadFile(data.widgetId)"
style="background-color: rgb(34, 197, 94, 1); color: #FFF;"
class="flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly />
</div>
</div>
<div class="px-4 py-3 border-t border-gray-200 text-right flex-shrink-0">
<small class="text-gray-500 text-xs">วันที่อัพโหลด {{ coverDate(data.uploadDate) }}
{{ data.uploadTime }}</small>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { NgbModal, NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';
import { AlertModalComponent } from '../alert-modal/alert-modal.component';
import { OpenImageComponent } from '../open-image/open-image.component';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { SharedModule } from '../../../../shared/shared.module';
import { TranslateModule } from '@ngx-translate/core';
import { NgSelectModule } from '@ng-select/ng-select';
import saveAs from 'file-saver';
import { WidgetModel } from '../../../models/widgets.model';
import { WidgetService } from '../../../services/widgets.service';
@Component({
selector: 'app-view-list-widgets',
templateUrl: './view-list-widgets.component.html',
styleUrls: ['./view-list-widgets.component.scss'],
standalone: true,
imports: [
CommonModule,
FormsModule,
NgSelectModule,
SharedModule,
MatDialogModule,
NgbPaginationModule,
TranslateModule,
],
})
export class ViewListWidgetsComponent implements OnInit {
page = 1;
pageSize = 10;
listWidget:WidgetModel[]=[]
search:string = ''
dialogRef: any;
constructor(private modalService: NgbModal,private widgetService:WidgetService, private dialog: MatDialog,) {
}
openDialog(image: string) {
const dialogConfig = {
width: '750px',
disableClose: false,
data: {
linkImage: image
},
panelClass: 'my-dialog-img-preview',
};
this.dialogRef = this.dialog.open(OpenImageComponent, dialogConfig);
this.dialogRef.afterClosed().subscribe((result: any) => {
console.log('The dialog was closed', result);
}, (reason: any) => {
});
}
async downloadFile(logId: string) {
try {
const data = await this.widgetService.downloadFile(logId).toPromise();
if (data) {
saveAs(new Blob([data]), "file_download.xlsx");
}
} catch (error) {
console.error('Error loading data:', error);
}
}
// getStatus(status: string) {
// if (status == '0') {
// return 'Private'
// } else if (status == '1') {
// return 'Public'
// }
// }
filterListWidget(){
return this.listWidget.filter(x => x.widgetTname.toLowerCase().includes(this.search.toLowerCase())||x.widgetEname.toLowerCase().includes(this.search.toLowerCase()))
}
async getListExcel(){
try {
const data = await this.widgetService.getListWidgets().toPromise();
this.listWidget = data!.map(x => new WidgetModel(x))
} catch (error) {
console.error('Error loading data:', error);
}
}
ngOnInit() {
this.getListExcel();
}
openLink(url:string){
window.open(url, "_blank");
}
openAlertModal(message?: string) {
const modalRef = this.modalService.open(AlertModalComponent, {
centered: true,
backdrop: 'static'
})
modalRef.componentInstance.message = message ? message : ""
modalRef.result.then(result => {
this.modalService.dismissAll()
}, reason => {
this.modalService.dismissAll()
})
}
coverDate(date:string){
return date.split('-').reverse().join('/')
}
}
<div *ngIf="errorMessage$ | async as errorMessage" class="alert alert-danger">{{errorMessage}}</div>
<div class="flex h-screen bg-gray-50"> <div class="flex h-screen bg-gray-50">
<!-- Widget Sidebar --> <!-- Widget Sidebar -->
<div class="w-72 bg-white p-4 overflow-y-auto shadow-lg border-r flex flex-col"> <div class="w-72 bg-white p-4 overflow-y-auto shadow-lg border-r flex flex-col">
...@@ -40,10 +42,11 @@ ...@@ -40,10 +42,11 @@
class="p-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white"> class="p-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white">
<option *ngFor="let dash of userDashboards" [value]="dash.id">{{ dash.name }}</option> <option *ngFor="let dash of userDashboards" [value]="dash.id">{{ dash.name }}</option>
</select> </select>
<div class="relative flex items-center"> <app-dataset-picker (datasetSelected)="onDatasetSelected($event)"></app-dataset-picker>
<div *ngIf="dashboardData" class="relative flex items-center">
<input type="text" [(ngModel)]="dashboardData.name" (blur)="saveDashboardName()" <input type="text" [(ngModel)]="dashboardData.name" (blur)="saveDashboardName()"
class="p-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white text-gray-800 font-semibold"> class="p-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 bg-white text-gray-800 font-semibold">
<button *ngIf="dashboardData?.name !== dashboardData?.originalName" (click)="saveDashboardName()" <button (click)="saveDashboardName()"
class="ml-2 text-emerald-500 hover:text-emerald-700 focus:outline-none"> class="ml-2 text-emerald-500 hover:text-emerald-700 focus:outline-none">
<i class="bi bi-check-circle-fill text-2xl"></i> <i class="bi bi-check-circle-fill text-2xl"></i>
</button> </button>
......
import { Component, OnInit, ViewChild, Type } from '@angular/core'; // Import Type import { Component, OnInit, ViewChild, Type, ChangeDetectionStrategy } from '@angular/core';
import { ActivatedRoute, RouterModule } from '@angular/router'; import { ActivatedRoute, RouterModule } from '@angular/router';
// import { DashboardLayoutComponent, DashboardLayoutModule, PanelModel } from '@syncfusion/ej2-angular-layouts';
import { DashboardService } from '../../shared/services/dashboard.service';
import { DashboardLayout, Widget } from '../../shared/models/dashboard.model';
import { switchMap } from 'rxjs/operators';
import { CommonModule, TitleCasePipe } from '@angular/common'; import { CommonModule, TitleCasePipe } from '@angular/common';
import { NgComponentOutlet } from '@angular/common'; // Import NgComponentOutlet import { NgComponentOutlet } from '@angular/common';
import { FormsModule } from '@angular/forms'; // Import FormsModule for ngModel import { FormsModule } from '@angular/forms';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { DashboardModel, WidgetModel, DatasetModel } from '../models/widgets.model';
import * as DashboardActions from '../state/dashboard.actions';
import * as DashboardSelectors from '../state/dashboard.selectors';
// Import all the widget components // Import all the widget components
import { CompanyInfoWidgetComponent } from '../widgets/company-info-widget.component'; import { CompanyInfoWidgetComponent } from '../widgets/company-info-widget.component';
...@@ -16,86 +18,79 @@ import { HeadcountWidgetComponent } from '../widgets/headcount-widget.component' ...@@ -16,86 +18,79 @@ import { HeadcountWidgetComponent } from '../widgets/headcount-widget.component'
import { AttendanceOverviewWidgetComponent } from '../widgets/attendance-overview-widget.component'; import { AttendanceOverviewWidgetComponent } from '../widgets/attendance-overview-widget.component';
import { PayrollSummaryWidgetComponent } from '../widgets/payroll-summary-widget.component'; import { PayrollSummaryWidgetComponent } from '../widgets/payroll-summary-widget.component';
import { EmployeeDirectoryWidgetComponent } from '../widgets/employee-directory-widget.component'; import { EmployeeDirectoryWidgetComponent } from '../widgets/employee-directory-widget.component';
// New Widget Imports
import { KpiWidgetComponent } from '../widgets/kpi-widget/kpi-widget.component'; import { KpiWidgetComponent } from '../widgets/kpi-widget/kpi-widget.component';
import { WelcomeWidgetComponent } from '../widgets/welcome-widget/welcome-widget.component'; import { WelcomeWidgetComponent } from '../widgets/welcome-widget/welcome-widget.component';
import { ChartWidgetComponent } from '../widgets/chart-widget/chart-widget.component'; import { ChartWidgetComponent } from '../widgets/chart-widget/chart-widget.component';
import { QuickLinksWidgetComponent } from '../widgets/quick-links-widget/quick-links-widget.component'; import { QuickLinksWidgetComponent } from '../widgets/quick-links-widget/quick-links-widget.component';
// New Syncfusion Widget Imports
import { SyncfusionDatagridWidgetComponent } from '../widgets/syncfusion-datagrid-widget/syncfusion-datagrid-widget.component'; import { SyncfusionDatagridWidgetComponent } from '../widgets/syncfusion-datagrid-widget/syncfusion-datagrid-widget.component';
import { SyncfusionPivotWidgetComponent } from '../widgets/syncfusion-pivot-widget/syncfusion-pivot-widget.component'; import { SyncfusionPivotWidgetComponent } from '../widgets/syncfusion-pivot-widget/syncfusion-pivot-widget.component';
import { SyncfusionChartWidgetComponent } from '../widgets/syncfusion-chart-widget/syncfusion-chart-widget.component'; import { SyncfusionChartWidgetComponent } from '../widgets/syncfusion-chart-widget/syncfusion-chart-widget.component';
import { DatasetPickerComponent } from './dataset-picker.component';
import { MockDashboardService } from '../services/mock-dashboard.service';
@Component({ @Component({
selector: 'app-dashboard-management', selector: 'app-dashboard-management',
standalone: true, standalone: true,
imports: [CommonModule, RouterModule, /*DashboardLayoutModule,*/ TitleCasePipe, NgComponentOutlet, FormsModule, CompanyInfoWidgetComponent, HeadcountWidgetComponent, AttendanceOverviewWidgetComponent, PayrollSummaryWidgetComponent, EmployeeDirectoryWidgetComponent, KpiWidgetComponent, WelcomeWidgetComponent, ChartWidgetComponent, QuickLinksWidgetComponent, SyncfusionDatagridWidgetComponent, SyncfusionPivotWidgetComponent, SyncfusionChartWidgetComponent], imports: [CommonModule, RouterModule, TitleCasePipe, NgComponentOutlet, FormsModule, CompanyInfoWidgetComponent, HeadcountWidgetComponent, AttendanceOverviewWidgetComponent, PayrollSummaryWidgetComponent, EmployeeDirectoryWidgetComponent, KpiWidgetComponent, WelcomeWidgetComponent, ChartWidgetComponent, QuickLinksWidgetComponent, SyncfusionDatagridWidgetComponent, SyncfusionPivotWidgetComponent, SyncfusionChartWidgetComponent, DatasetPickerComponent],
templateUrl: './dashboard-management.component.html', templateUrl: './dashboard-management.component.html',
styleUrls: ['./dashboard-management.component.scss'] styleUrls: ['./dashboard-management.component.scss'],
}) })
export class DashboardManagementComponent implements OnInit { export class DashboardManagementComponent implements OnInit {
// @ViewChild('dashboard') dashboardComponent!: DashboardLayoutComponent;
// The panels array will now hold a reference to the component Type public panels: ( { componentType: Type<any>, componentInputs?: { [key: string]: any } })[] = [];
public panels: (/*PanelModel &*/ { componentType: Type<any>, componentInputs?: { [key: string]: any } })[] = [];
public cellSpacing: number[] = [10, 10]; public cellSpacing: number[] = [10, 10];
public availableWidgets: Widget[] = []; public availableWidgets: WidgetModel[] = [];
public filteredAvailableWidgets: Widget[] = []; // For search functionality public filteredAvailableWidgets: WidgetModel[] = [];
public widgetSearchTerm: string = ''; // For search functionality public widgetSearchTerm: string = '';
public dashboardData: DashboardModel;
public appName: string = ''; public userDashboards: DashboardModel[] = [];
public dashboardData!: DashboardLayout; public selectedDashboardId: string = '';
public userDashboards: DashboardLayout[] = []; // To hold all dashboards for the app public userDashboards$: Observable<DashboardModel[]>;
public selectedDashboardId: string = ''; // To hold the ID of the currently selected dashboard public availableWidgets$: Observable<WidgetModel[]>;
public errorMessage$: Observable<string | null>;
// Map string names to actual component classes
private widgetComponentMap: { [key: string]: Type<any> } = { private widgetComponentMap: { [key: string]: Type<any> } = {
'CompanyInfoWidgetComponent': CompanyInfoWidgetComponent, 'CompanyInfoWidgetComponent': CompanyInfoWidgetComponent,
'HeadcountWidgetComponent': HeadcountWidgetComponent, 'HeadcountWidgetComponent': HeadcountWidgetComponent,
'AttendanceOverviewWidgetComponent': AttendanceOverviewWidgetComponent, 'AttendanceOverviewWidgetComponent': AttendanceOverviewWidgetComponent,
'PayrollSummaryWidgetComponent': PayrollSummaryWidgetComponent, 'PayrollSummaryWidgetComponent': PayrollSummaryWidgetComponent,
'EmployeeDirectoryWidgetComponent': EmployeeDirectoryWidgetComponent, 'EmployeeDirectoryWidgetComponent': EmployeeDirectoryWidgetComponent,
// New Widget Mappings
'KpiWidgetComponent': KpiWidgetComponent, 'KpiWidgetComponent': KpiWidgetComponent,
'WelcomeWidgetComponent': WelcomeWidgetComponent, 'WelcomeWidgetComponent': WelcomeWidgetComponent,
'ChartWidgetComponent': ChartWidgetComponent, 'ChartWidgetComponent': ChartWidgetComponent,
'QuickLinksWidgetComponent': QuickLinksWidgetComponent, 'QuickLinksWidgetComponent': QuickLinksWidgetComponent,
// New Syncfusion Widget Mappings
'SyncfusionDatagridWidgetComponent': SyncfusionDatagridWidgetComponent, 'SyncfusionDatagridWidgetComponent': SyncfusionDatagridWidgetComponent,
'SyncfusionPivotWidgetComponent': SyncfusionPivotWidgetComponent, 'SyncfusionPivotWidgetComponent': SyncfusionPivotWidgetComponent,
'SyncfusionChartWidgetComponent': SyncfusionChartWidgetComponent 'SyncfusionChartWidgetComponent': SyncfusionChartWidgetComponent
}; };
constructor( constructor(
private dashboardService: DashboardService, private store: Store,
private route: ActivatedRoute private route: ActivatedRoute,
private mockDashboardService: MockDashboardService
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.appName = this.route.snapshot.paramMap.get('appName') || 'redesign'; // Default to 'redesign' this.store.dispatch(DashboardActions.loadDashboards());
this.store.dispatch(DashboardActions.loadWidgets());
if (this.appName) { this.userDashboards$ = this.store.select(DashboardSelectors.selectAllDashboards);
this.dashboardService.getDashboards(this.appName).subscribe(dashboards => { this.availableWidgets$ = this.store.select(DashboardSelectors.selectAllWidgets);
this.userDashboards = dashboards; this.errorMessage$ = this.store.select(DashboardSelectors.selectError);
if (this.userDashboards.length > 0) { this.mockDashboardService.getDashboards().subscribe(dashboards => {
// Try to load the 'redesign' dashboard if it exists, otherwise load the first one this.userDashboards = dashboards;
const redesignDashboard = this.userDashboards.find(d => d.id === 'dash-redesign-main'); if (this.userDashboards.length > 0) {
this.selectedDashboardId = redesignDashboard ? redesignDashboard.id : this.userDashboards[0].id; this.selectedDashboardId = this.userDashboards[0].id;
this.loadSelectedDashboard(); this.loadSelectedDashboard();
} else { }
this.createNewDashboard(); // Create a new dashboard if none exist });
}
});
this.dashboardService.getWidgets(this.appName).subscribe(widgets => {
this.availableWidgets = widgets;
this.filterWidgets(); // Initialize filtered widgets
});
}
} }
filterWidgets(): void { filterWidgets(): void {
if (!this.widgetSearchTerm) { if (!this.widgetSearchTerm) {
this.filteredAvailableWidgets = [...this.availableWidgets]; this.filteredAvailableWidgets = [...this.availableWidgets];
...@@ -113,19 +108,11 @@ export class DashboardManagementComponent implements OnInit { ...@@ -113,19 +108,11 @@ export class DashboardManagementComponent implements OnInit {
loadSelectedDashboard(): void { loadSelectedDashboard(): void {
if (this.selectedDashboardId) { if (this.selectedDashboardId) {
this.dashboardService.getDashboardLayout(this.selectedDashboardId).subscribe(dashboard => { this.store.select(DashboardSelectors.selectDashboardById(this.selectedDashboardId)).subscribe(dashboard => {
if (dashboard) { if (dashboard) {
this.dashboardData = dashboard; this.dashboardData = dashboard;
// Store the original name for comparison
this.dashboardData.originalName = dashboard.name;
this.panels = this.mapWidgetsToPanels(dashboard.widgets || []); this.panels = this.mapWidgetsToPanels(dashboard.widgets || []);
// Force Syncfusion dashboard to refresh its layout console.log('Panels after mapping:', this.panels);
// Use a setTimeout to ensure the DOM is updated before refresh
// setTimeout(() => {
// if (this.dashboardComponent) {
// this.dashboardComponent.refresh();
// }
// }, 0);
} }
}); });
} }
...@@ -134,36 +121,22 @@ export class DashboardManagementComponent implements OnInit { ...@@ -134,36 +121,22 @@ export class DashboardManagementComponent implements OnInit {
createNewDashboard(): void { createNewDashboard(): void {
const newDashboardName = prompt('Enter a name for the new dashboard:'); const newDashboardName = prompt('Enter a name for the new dashboard:');
if (newDashboardName) { if (newDashboardName) {
const newDashboard: DashboardLayout = { const newDashboard = new DashboardModel({
id: `dash-${this.appName}-${Date.now()}`, id: `dash-${Date.now()}`,
appName: this.appName,
name: newDashboardName, name: newDashboardName,
widgets: [] widgets: []
};
this.dashboardService.saveDashboardLayout(newDashboard).subscribe(savedDashboard => {
this.userDashboards.push(savedDashboard);
this.selectedDashboardId = savedDashboard.id;
this.loadSelectedDashboard();
}); });
this.store.dispatch(DashboardActions.addDashboard({ dashboard: newDashboard }));
} }
} }
saveDashboardName(): void { saveDashboardName(): void {
if (this.dashboardData && this.dashboardData.name !== this.dashboardData.originalName) { if (this.dashboardData) {
this.dashboardService.saveDashboardLayout(this.dashboardData).subscribe(savedDashboard => { this.store.dispatch(DashboardActions.updateDashboard({ dashboard: this.dashboardData }));
// Update the original name after saving
this.dashboardData.originalName = savedDashboard.name;
// Update the name in the userDashboards array for the dropdown
const index = this.userDashboards.findIndex(d => d.id === savedDashboard.id);
if (index !== -1) {
this.userDashboards[index].name = savedDashboard.name;
}
alert('Dashboard name updated successfully!');
});
} }
} }
mapWidgetsToPanels(widgets: Widget[]): (/*PanelModel &*/ { componentType: Type<any>, componentInputs?: { [key: string]: any } })[] { mapWidgetsToPanels(widgets: WidgetModel[]): ({ componentType: Type<any>, componentInputs?: { [key: string]: any } })[] {
return widgets.map(widget => ({ return widgets.map(widget => ({
id: widget.id, id: widget.id,
header: widget.name, header: widget.name,
...@@ -171,74 +144,43 @@ export class DashboardManagementComponent implements OnInit { ...@@ -171,74 +144,43 @@ export class DashboardManagementComponent implements OnInit {
sizeY: widget.rows, sizeY: widget.rows,
row: widget.y, row: widget.y,
col: widget.x, col: widget.x,
// Attach the component Type to the panel object
componentType: this.widgetComponentMap[widget.component], componentType: this.widgetComponentMap[widget.component],
// Pass inputs if available componentInputs: { ...widget.data, datasetId: this.dashboardData.datasetId }
componentInputs: widget.inputs
})); }));
} }
saveLayout(): void { saveLayout(): void {
// if (!this.dashboardData) return; if (!this.dashboardData) return;
// if (!this.dashboardComponent || !this.dashboardComponent.panels) {
// console.warn('Dashboard component or panels not ready for saving.'); this.store.dispatch(DashboardActions.updateDashboard({ dashboard: this.dashboardData }));
// return;
// }
// const updatedWidgets: Widget[] = this.dashboardComponent.panels.map(panel => {
// const baseWidget = this.dashboardData.widgets.find(w => w.id === panel.id) ||
// this.availableWidgets.find(w => w.id === panel.id);
// return {
// ...baseWidget!,
// id: panel.id!,
// cols: panel.sizeX!,
// rows: panel.sizeY!,
// y: panel.row!,
// x: panel.col!,
// component: baseWidget!.component // ensure component name is preserved
// };
// });
// this.dashboardData.widgets = updatedWidgets;
// this.dashboardService.saveDashboardLayout(this.dashboardData).subscribe(() => {
// alert('Dashboard saved successfully!');
// });
} }
addWidgetToDashboard(widget: Widget): void { addWidgetToDashboard(widget: WidgetModel): void {
// const newPanel = this.mapWidgetsToPanels([widget])[0]; if (this.dashboardData.widgets.find(w => w.id === widget.id)) {
// if (this.dashboardComponent.panels.find(p => p.id === newPanel.id)) { alert('Widget already exists in the dashboard.');
// alert('Widget already exists in the dashboard.'); return;
// return; }
// } this.dashboardData.widgets.push(widget);
// this.dashboardComponent.addPanel(newPanel); this.panels = this.mapWidgetsToPanels(this.dashboardData.widgets);
} }
deleteDashboard(): void { deleteDashboard(): void {
// if (this.selectedDashboardId && confirm('Are you sure you want to delete this dashboard?')) { if (this.selectedDashboardId && confirm('Are you sure you want to delete this dashboard?')) {
// this.dashboardService.deleteDashboard(this.selectedDashboardId).subscribe(success => { this.store.dispatch(DashboardActions.deleteDashboard({ id: this.selectedDashboardId }));
// if (success) { }
// alert('Dashboard deleted successfully!');
// // Remove from userDashboards
// this.userDashboards = this.userDashboards.filter(d => d.id !== this.selectedDashboardId);
// // Select a new dashboard or create a new one
// if (this.userDashboards.length > 0) {
// this.selectedDashboardId = this.userDashboards[0].id;
// this.loadSelectedDashboard();
// } else {
// this.createNewDashboard(); // Create a new dashboard if none exist
// }
// } else {
// alert('Failed to delete dashboard.');
// }
// });
// }
} }
removeWidgetFromDashboard(panelId: string): void { removeWidgetFromDashboard(panelId: string): void {
// if (confirm('Are you sure you want to remove this widget?')) { if (confirm('Are you sure you want to remove this widget?')) {
// this.panels = this.panels.filter(panel => panel.id !== panelId); const updatedDashboard = { ...this.dashboardData, widgets: this.dashboardData.widgets.filter(w => w.id !== panelId) };
// this.saveLayout(); // Save the layout after removing the widget this.store.dispatch(DashboardActions.updateDashboard({ dashboard: updatedDashboard }));
// } }
}
onDatasetSelected(datasetId: string): void {
if (this.dashboardData) {
this.dashboardData.datasetId = datasetId;
this.panels = this.mapWidgetsToPanels(this.dashboardData.widgets);
}
} }
} }
<div class="dataset-picker-container">
<label for="dataset-select">Select Dataset:</label>
<select id="dataset-select" (change)="onDatasetChange($event)">
<option value="">-- Please choose a dataset --</option>
<option *ngFor="let dataset of datasets$ | async" [value]="dataset.id">
{{ dataset.name }}
</option>
</select>
</div>
.dataset-picker-container {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 20px;
}
label {
font-weight: bold;
}
select {
padding: 8px;
border-radius: 4px;
border: 1px solid #ccc;
}
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Observable } from 'rxjs';
import { DatasetModel } from '../models/widgets.model';
import { DatasetService } from '../services/dataset.service';
@Component({
selector: 'app-dataset-picker',
standalone: true,
imports: [CommonModule, FormsModule],
templateUrl: './dataset-picker.component.html',
styleUrls: ['./dataset-picker.component.scss']
})
export class DatasetPickerComponent implements OnInit {
datasets$: Observable<DatasetModel[]>;
@Output() datasetSelected = new EventEmitter<string>();
constructor(private datasetService: DatasetService) { }
ngOnInit(): void {
this.datasets$ = this.datasetService.getDatasets();
}
onDatasetChange(event: any): void {
this.datasetSelected.emit(event.target.value);
}
}
<div class="container mx-auto p-4 bg-gray-50 min-h-screen"> <div *ngIf="errorMessage" class="alert alert-danger">{{errorMessage}}</div>
<div class="container mx-auto p-4">
<h2 class="text-2xl font-bold mb-4 text-gray-800">Viewing Dashboard: {{ dashboardName }}</h2> <h2 class="text-2xl font-bold mb-4 text-gray-800">Viewing Dashboard: {{ dashboardName }}</h2>
<div class="control-section"> <div class="control-section">
<ejs-dashboardlayout id='dashboard_viewer' #viewerLayout [cellSpacing]="cellSpacing" [panels]="panels" [columns]="6" [allowResizing]="false" [allowDragging]="false"> <ejs-dashboardlayout id='dashboard_viewer' #viewerLayout [cellSpacing]="cellSpacing" [panels]="panels" [columns]="6" [allowResizing]="false" [allowDragging]="false">
......
import { Component, OnInit, Type } from '@angular/core'; // Import Type import { Component, OnInit, Type, ChangeDetectionStrategy } from '@angular/core'; // Import Type
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { ActivatedRoute, RouterModule } from '@angular/router'; import { ActivatedRoute, RouterModule } from '@angular/router';
import { DashboardLayoutModule, PanelModel } from '@syncfusion/ej2-angular-layouts'; import { DashboardLayoutModule, PanelModel } from '@syncfusion/ej2-angular-layouts';
import { DashboardService } from '../../shared/services/dashboard.service'; import { Store } from '@ngrx/store';
import { DashboardLayout, Widget } from '../../shared/models/dashboard.model';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { NgComponentOutlet } from '@angular/common'; // Import NgComponentOutlet import { NgComponentOutlet } from '@angular/common'; // Import NgComponentOutlet
import * as DashboardActions from '../state/dashboard.actions';
import * as DashboardSelectors from '../state/dashboard.selectors';
import { DashboardModel } from '../models/widgets.model';
// Import all the widget components // Import all the widget components
import { CompanyInfoWidgetComponent } from '../widgets/company-info-widget.component'; import { CompanyInfoWidgetComponent } from '../widgets/company-info-widget.component';
...@@ -29,7 +31,8 @@ import { SyncfusionChartWidgetComponent } from '../widgets/syncfusion-chart-widg ...@@ -29,7 +31,8 @@ import { SyncfusionChartWidgetComponent } from '../widgets/syncfusion-chart-widg
standalone: true, standalone: true,
imports: [CommonModule, RouterModule, DashboardLayoutModule, NgComponentOutlet, CompanyInfoWidgetComponent, HeadcountWidgetComponent, AttendanceOverviewWidgetComponent, PayrollSummaryWidgetComponent, EmployeeDirectoryWidgetComponent, KpiWidgetComponent, WelcomeWidgetComponent, ChartWidgetComponent, QuickLinksWidgetComponent, SyncfusionDatagridWidgetComponent, SyncfusionPivotWidgetComponent, SyncfusionChartWidgetComponent], imports: [CommonModule, RouterModule, DashboardLayoutModule, NgComponentOutlet, CompanyInfoWidgetComponent, HeadcountWidgetComponent, AttendanceOverviewWidgetComponent, PayrollSummaryWidgetComponent, EmployeeDirectoryWidgetComponent, KpiWidgetComponent, WelcomeWidgetComponent, ChartWidgetComponent, QuickLinksWidgetComponent, SyncfusionDatagridWidgetComponent, SyncfusionPivotWidgetComponent, SyncfusionChartWidgetComponent],
templateUrl: './dashboard-viewer.component.html', templateUrl: './dashboard-viewer.component.html',
styleUrls: ['./dashboard-viewer.component.scss'] styleUrls: ['./dashboard-viewer.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class DashboardViewerComponent implements OnInit { export class DashboardViewerComponent implements OnInit {
...@@ -54,9 +57,11 @@ export class DashboardViewerComponent implements OnInit { ...@@ -54,9 +57,11 @@ export class DashboardViewerComponent implements OnInit {
'SyncfusionChartWidgetComponent': SyncfusionChartWidgetComponent 'SyncfusionChartWidgetComponent': SyncfusionChartWidgetComponent
}; };
public errorMessage: string | null = null;
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private dashboardService: DashboardService private store: Store
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
...@@ -67,19 +72,22 @@ export class DashboardViewerComponent implements OnInit { ...@@ -67,19 +72,22 @@ export class DashboardViewerComponent implements OnInit {
console.error('Dashboard ID is missing from the route.'); console.error('Dashboard ID is missing from the route.');
return of(null); return of(null);
} }
return this.dashboardService.getDashboardLayout(id); this.store.dispatch(DashboardActions.loadDashboards());
return this.store.select(DashboardSelectors.selectDashboardById(id));
}) })
).subscribe(dashboard => { ).subscribe({
if (dashboard) { next: dashboard => {
this.loadDashboard(dashboard); if (dashboard) {
} this.loadDashboard(dashboard);
}
},
error: err => this.errorMessage = err.message
}); });
} }
loadDashboard(dashboard: DashboardLayout): void { loadDashboard(dashboard: DashboardModel): void {
this.dashboardName = dashboard.name; this.dashboardName = dashboard.name;
// Map widgets from the layout to Syncfusion PanelModels, attaching componentType this.panels = dashboard.widgets.map(widget => ({
this.panels = dashboard.widgets.map((widget: Widget) => ({
id: widget.id, id: widget.id,
row: widget.y, row: widget.y,
col: widget.x, col: widget.x,
...@@ -87,7 +95,7 @@ export class DashboardViewerComponent implements OnInit { ...@@ -87,7 +95,7 @@ export class DashboardViewerComponent implements OnInit {
sizeY: widget.rows, sizeY: widget.rows,
header: widget.name, header: widget.name,
componentType: this.widgetComponentMap[widget.component], // Attach the component Type componentType: this.widgetComponentMap[widget.component], // Attach the component Type
componentInputs: widget.inputs // Pass inputs if available componentInputs: widget.data // Pass inputs if available
})); }));
} }
} }
...@@ -2,88 +2,77 @@ import { environment } from "../../../environments/environment"; ...@@ -2,88 +2,77 @@ import { environment } from "../../../environments/environment";
import { TagModel } from "./tag.mmodel" import { TagModel } from "./tag.mmodel"
import { GroupModel } from "./group.mmodel" import { GroupModel } from "./group.mmodel"
export interface WidgetModel { export interface IDataset {
widgetId: string id: string;
widgetTname: string name: string;
widgetEname: string url: string;
thDesc: string
engDesc: string
chartType: string
widgetHeight: number
widgetWidth: number
seriesColumn: string
picture: string
remark: string
status: number
link1: string
dbSupport: string
widgetObj: string
fileType: string
isPivot: number
isDataGrid: number
uploadBy: string
uploadDate: string
uploadTime: string
group: GroupModel
tags: TagModel[]
} }
export class WidgetModel implements WidgetModel { export class DatasetModel implements IDataset {
widgetId: string id: string;
widgetTname: string name: string;
widgetEname: string url: string;
thDesc: string
engDesc: string
chartType: string
widgetHeight: number
widgetWidth: number
seriesColumn: string
picture: string
remark: string
status: number
link1: string
dbSupport: string
widgetObj: string
fileType: string
isPivot: number
isDataGrid: number
uploadBy: string
uploadDate: string
uploadTime: string
group: GroupModel
tags: TagModel[]
constructor(data: Partial<WidgetModel>) { constructor(data: Partial<DatasetModel>) {
this.widgetId = data.widgetId ?? '' this.id = data.id ?? '';
this.widgetTname = data.widgetTname ?? '' this.name = data.name ?? '';
this.widgetEname = data.widgetEname ?? '' this.url = data.url ?? '';
this.thDesc = data.thDesc ?? '' }
this.engDesc = data.engDesc ?? '' }
this.chartType = data.chartType ?? ''
this.widgetHeight = data.widgetHeight ?? 0 export interface IWidget {
this.widgetWidth = data.widgetWidth ?? 0 id: string;
this.status = data.status ?? 0 name: string;
this.seriesColumn = data.seriesColumn ?? '' component: string;
this.picture = data.picture ?? '' cols: number;
this.remark = data.remark ?? '' rows: number;
this.link1 = data.link1 ?? '' x: number;
this.widgetObj = data.widgetObj ?? '' y: number;
this.dbSupport = data.dbSupport ?? '' data: any;
this.tags = data.tags ?? [] }
this.fileType = data.fileType ?? ''
this.isPivot = data.isPivot ?? 0 export class WidgetModel implements IWidget {
this.isDataGrid = data.isDataGrid ?? 0 id: string;
this.uploadBy = data.uploadBy ?? '' name: string;
this.uploadDate = data.uploadDate ?? '' component: string;
this.uploadTime = data.uploadTime ?? '' cols: number;
this.group = data.group ? new GroupModel(data.group) : new GroupModel({}) rows: number;
} x: number;
y: number;
data: any;
constructor(data: Partial<IWidget>) {
this.id = data.id ?? '';
this.name = data.name ?? '';
this.component = data.component ?? '';
this.cols = data.cols ?? 1;
this.rows = data.rows ?? 1;
this.x = data.x ?? 0;
this.y = data.y ?? 0;
this.data = data.data ?? {};
}
}
export interface IDashboard {
id: string;
name: string;
description: string;
datasetId?: string;
widgets: IWidget[];
}
getImage(): string { export class DashboardModel implements IDashboard {
if (this.picture) { id: string;
return environment.url + "files/image/" + this.picture name: string;
} else { description: string;
return 'assets/images/big/auth-bg.jpg' datasetId?: string;
} widgets: IWidget[];
}
} constructor(data: Partial<IDashboard>) {
\ No newline at end of file this.id = data.id ?? '';
this.name = data.name ?? '';
this.description = data.description ?? '';
this.datasetId = data.datasetId;
this.widgets = data.widgets ? data.widgets.map(w => new WidgetModel(w)) : [];
}
}
<app-page-header [title]="'รายการวิทเจ็ด'" [activeTitle]="'ผู้ดูแลระบบ'"
[title1]="'รายการอัพโหลดเอกสาร Widget'"></app-page-header>
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-12 col-span-12">
<div class="box">
<div class="box-header justify-between">
<div class="box-title">
{{ 'All List' | translate}}
</div>
<div class="flex flex-wrap gap-2">
<a href="javascript:void(0);" class="hs-dropdown-toggle ti-btn ti-btn-primary-full me-2"
(click)="openEditExcelDialog()"><i class="ri-add-line font-semibold align-middle"></i>{{ 'Create' |
translate}}
</a>
<div>
<input class="form-control form-control" type="text" placeholder="ค้นหาบริษัท"
aria-label=".form-control-sm example" [(ngModel)]="search" (ngModelChange)="onSearchChange()">
</div>
</div>
</div>
<div class="box-body">
<div class="table-responsive" *ngIf="checkType !== '1'">
<table class="table whitespace-nowrap min-w-full ti-custom-table-hover">
<thead>
<tr class="border-b border-defaultborder text-white" style="background-color: #49b6f5;">
<th scope="col" class="text-start">#</th>
<th scope="col" class="text-start">รูปภาพ</th>
<th scope="col" class="text-start">ชื่อ</th>
<th scope="col" class="text-start">รายละเอียด</th>
<th scope="col" class="text-start">ลิงค์</th>
<th scope="col" class="text-start">ไฟล์</th>
<th scope="col" class="text-start">สถานะ</th>
<th scope="col" class="text-start">การจัดการ</th>
</tr>
</thead>
<tbody>
<tr class="border border-defaultborder dark:border-defaultborder/10"
*ngFor="let data of paginatedWidgets; let i = index">
<td>
<div>
<span class="block mb-1">
{{pageIndex * pageSize + i + 1}} </span>
</div>
</td>
<td>
<div class="flex items-center">
<span class="p-3 me-1" style="width: 200px;">
<img src="{{data.getImage()}}" (click)="openEmployeeDialog(data.getImage())" id="profile-img"
class="border-radius-1 cursor-pointer" style="width: 180px; height: 120px; object-fit: cover;">
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
{{ data.widgetTname }}
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
{{ data.thDesc }}
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
<i class="fa fa-link text-blue-600 text-base flex-shrink-0 cursor-pointer active: hover:text-danger hover:scale-125 transition duration-300"
(click)="openLink(data.link1)" style="font-size: 20px;"></i>
</span>
</div>
</td>
<td>
<div>
<span class="block mb-1">
<i class="fa fa-download text-blue-600 text-base flex-shrink-0 cursor-pointer active hover:text-success hover:scale-125 transition duration-300"
(click)="downloadFile(data.widgetId)" style="font-size: 20px;"></i>
</span>
</div>
</td>
<td>
<div>
<ng-container *ngIf="data.status === 0">
<span class="badge bg-amber-300 text-white">
รออนุมัติ </span>
</ng-container>
<ng-container *ngIf="data.status === 1">
<span class="badge bg-success text-white">
เปิดใช้งาน </span>
</ng-container>
<ng-container *ngIf="data.status === 2">
<span class="badge bg-gray-500 text-white">
ไม่อนุมัติ </span>
</ng-container>
</div>
</td>
<td>
<div class="flex flex-row items-center !gap-2 ">
<a aria-label="anchor" (click)="openEditExcelDialog(data)"
class="ti-btn ti-btn-wave !gap-0 !m-0 bg-info/10 text-info hover:bg-info hover:text-white hover:border-info">
<i class="ri-pencil-line"></i>
</a>
<a aria-label="anchor" href="javascript:void(0);" (click)="deleteFile(data)"
class="ti-btn ti-btn-wave product-btn !gap-0 !m-0 bg-danger/10 text-danger hover:bg-danger hover:text-white hover:border-danger">
<i class="ri-delete-bin-line"></i>
</a>
</div>
</td>
</tr>
<tr *ngIf="paginatedWidgets.length === 0">
<td colspan="9" class="text-center py-4">ไม่พบข้อมูล</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<div class="flex items-center flex-wrap overflow-auto">
<div class="mb-2 sm:mb-0">
<select class="custom-select m-r-5" style="width: auto" [(ngModel)]="pageSize"
(ngModelChange)="goToPage(0)">
<option [ngValue]="10">รายการต่อหน้า: 10</option>
<option [ngValue]="50">รายการต่อหน้า: 50</option>
<option [ngValue]="100">รายการต่อหน้า: 100</option>
</select>
</div>
<div class="ms-auto">
<nav aria-label="Page navigation">
<ul class="ti-pagination mb-0 flex">
<li class="page-item" [class.disabled]="pageIndex === 0">
<a class="page-link px-3 py-[0.375rem] cursor-pointer" (click)="goToPage(pageIndex - 1)">
{{ 'Previous' | translate }}
</a>
</li>
<ng-container *ngFor="let p of pages">
<li class="page-item" [class.active]="p === pageIndex">
<a class="page-link px-3 py-[0.375rem] cursor-pointer" [class.active]="p === pageIndex"
(click)="goToPage(p)">
{{ p + 1 }} </a>
</li>
</ng-container>
<li class="page-item" [class.disabled]="pageIndex === totalPages - 1 || totalPages === 0">
<a class="page-link px-3 py-[0.375rem] cursor-pointer" (click)="goToPage(pageIndex + 1)">
{{ 'Next' | translate }}
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<ng-template #editTemplateModal let-modal>
<div class="modal-headtitle ti-modal-header flex justify-between items-center p-4" style="background-color: #fefbfb;">
<h3 class="modal-title text-sm font-semibold text-defaulttextcolor" id="edittemplateLabel">
{{ checkEdit ? ('แก้ไขไฟล์ Widget' | translate) : ('เพิ่มไฟล์ Widget' | translate) }}
</h3>
<button type="button" class="hs-dropdown-toggle !text-[1rem] !font-semibold !text-defaulttextcolor"
(click)="closeDialog()" #closeModal> <span class="sr-only">{{ 'Close' | translate }}</span>
<i class="ri-close-line"></i>
</button>
</div>
<div class="w-full flex justify-end">
<div class="absolute flex">
<div class="px-1">
</div>
</div>
</div>
<mat-dialog-content style="padding: 0px; padding-left: 20px; padding-right: 20px;">
<div class="box p-9 top-4">
<div class="grid grid-cols-12 gap-6">
<div class="xl:col-span-6 col-span-12">
<label for="nameth" class="block text-primary mb-2 font-bold font-14">{{ 'ชื่อวิทเจ็ด (ไทย)' | translate
}}</label>
<input type="text"
class="form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="nameth" [(ngModel)]="modelWidget.widgetTname" name="widgetTname">
</div>
<div class="xl:col-span-6 col-span-12">
<label for="nameeng" class="block text-primary mb-2 font-bold font-14">{{ 'ชื่อวิทเจ็ด (อังกฤษ)' | translate
}}</label>
<input type="text"
class="form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="nameeng" [(ngModel)]="modelWidget.widgetEname" name="widgetEname">
</div>
<div class="xl:col-span-12 col-span-12">
<label for="thDesc" class="block text-primary mb-2 font-bold font-14">{{ 'รายละเอียด (ไทย)' | translate
}}</label>
<textarea
class="form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="thDesc" [(ngModel)]="modelWidget.thDesc" rows="3" name="thDesc"></textarea>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="engDesc" class="block text-primary mb-2 font-bold font-14">{{ 'รายละเอียด (อังกฤษ)' | translate
}}</label>
<textarea
class="form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="engDesc" [(ngModel)]="modelWidget.engDesc" rows="3" name="engDesc"></textarea>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="group" class="block text-primary mb-2 font-bold font-14">{{ 'ภาษาที่รองรับ' | translate }}</label>
<select
class="custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="status" [(ngModel)]="modelWidget.status" name="status">
<option [value]="0">Private</option>
<option [value]="1">Public</option>
</select>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="dbSupport" class="block text-primary mb-2 font-bold font-14">{{ 'ดาต้าเบสที่รองรับ' | translate
}}</label>
<select
class="custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="dbSupport" [(ngModel)]="modelWidget.dbSupport" name="dbSupport">
<option value="SQLServer">SQLServer</option>
<option value="PostgreSQL">PostgreSQL</option>
<option value="Oracle">Oracle</option>
</select>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="fileUpload" class="block text-primary mb-2 font-bold font-14">{{ 'ไฟล์อัพโหลด' | translate
}}</label>
<div class="flex items-center gap-2">
<input type="file"
class="form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="fileUpload" (change)="onSelectFile($event)">
<button *ngIf="modelWidget.widgetObj && checkEdit" (click)="downloadFile(modelWidget.widgetId)"
class="ti-btn ti-btn-primary flex-shrink-0 px-4 py-2 rounded-md transition-all duration-200">
<i class="fas fa-download mr-1"></i> {{ 'ดาวน์โหลด' | translate }}
</button>
</div>
<div class="msg-detail text-sm text-red mt-1"> ไฟล์ที่อนุญาต:*.xlsx *.xlsm
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="imageUpload" class="block text-primary mb-2 font-bold font-14">{{ 'รูปภาพตัวอย่าง' | translate
}}</label>
<div class="flex items-center gap-2">
<input type="file"
class="form-control flex-grow p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="imageUpload" (change)="onUploadImage($event)">
</div>
<div class="msg-detail text-sm text-red mt-1"> ไฟล์ที่อนุญาต:*.jpeg, *.jpg, *.png
</div>
</div>
<div class="xl:col-span-6 col-span-12">
<label for="linkExample" class="block text-primary mb-2 font-bold font-14">{{ 'Link ตัวอย่าง' | translate
}}</label>
<input type="text"
class="form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="linkExample" [(ngModel)]="modelWidget.link1" name="link1">
</div>
<div class="xl:col-span-12 col-span-12">
<label for="tags" class="block text-primary mb-2 font-bold font-14">{{ 'แท็ก' | translate }}</label>
<tag-input [theme]="'bootstrap'" [(ngModel)]='modelWidget.tags' placeholder="{{ '+แท็ก' | translate }}"
[onlyFromAutocomplete]="true" secondaryPlaceholder="{{ 'กดปุ่ม Enter เพื่อเพิ่มแท็กใหม่' | translate }}"
[addOnBlur]="true" [clearOnBlur]="true" class="w-full" name="tags">
<tag-input-dropdown [autocompleteItems]="listTag" [showDropdownIfEmpty]="true">
</tag-input-dropdown>
</tag-input>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="group" class="block text-primary mb-2 font-bold font-14">{{ 'กลุ่ม' | translate }}</label>
<select
class="custom-select w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="group" [(ngModel)]="modelWidget.group.groupId" (change)="selectGroup()" name="group">
<option *ngFor="let item of listGroup" [ngValue]="item.groupId">{{item.thName}}</option>
</select>
</div>
<div class="xl:col-span-12 col-span-12">
<label class="block text-primary mb-2 font-bold font-14">{{ 'แสดงรูปแบบ Pivot' | translate }}</label>
<div class="flex items-center gap-4 mt-2">
<div class="flex items-center">
<input type="radio" class="form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id="pivot0" name="radio-pivot" [value]="0" [(ngModel)]="modelWidget.isPivot">
<label class="ml-2 text-gray-700" for="pivot0">{{ 'ใช่' | translate }}</label>
</div>
<div class="flex items-center">
<input type="radio" class="form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id="pivot1" name="radio-pivot" [value]="1" [(ngModel)]="modelWidget.isPivot">
<label class="ml-2 text-gray-700" for="pivot1">{{ 'ไม่ใช่' | translate }}</label>
</div>
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label class="block text-primary mb-2 font-bold font-14">{{ 'แสดงรูปแบบ DataGrid' | translate }}</label>
<div class="flex items-center gap-4 mt-2">
<div class="flex items-center">
<input type="radio" class="form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id="datagrid0" name="datagridCheck" [value]="0" [(ngModel)]="modelWidget.isDataGrid">
<label class="ml-2 text-gray-700" for="datagrid0">{{ 'ใช่' | translate }}</label>
</div>
<div class="flex items-center">
<input type="radio" class="form-radio h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500"
id="datagrid1" name="datagridCheck" [value]="1" [(ngModel)]="modelWidget.isDataGrid">
<label class="ml-2 text-gray-700" for="datagrid1">{{ 'ไม่ใช่' | translate }}</label>
</div>
</div>
</div>
<div class="xl:col-span-12 col-span-12">
<label for="remark" class="block text-primary mb-2 font-bold font-14">{{ 'หมายเหตุ' | translate }}</label>
<textarea
class="form-control w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200"
id="remark" [(ngModel)]="modelWidget.remark" rows="4" name="remark"></textarea>
</div>
</div>
</div>
</mat-dialog-content>
<mat-dialog-actions style="justify-content: end;">
<button type="button" class="hs-dropdown-toggle ti-btn ti-btn-light align-middle" (click)="closeDialog()">
{{ 'Cancel' | translate }}
</button>
<button type="submit" class="ti-btn bg-primary text-white !font-medium"
[class.ti-btn-disabled]="!modelWidget.widgetTname||!modelWidget.widgetEname"
[disabled]="!modelWidget.widgetTname||!modelWidget.widgetEname" (click)="onSumit()">
{{ 'Save' | translate }}
</button>
</mat-dialog-actions>
</ng-template>
\ No newline at end of file
::ng-deep ng2-dropdown-menu {
z-index: 9999 !important;
.ng2-dropdown-menu {
z-index: 9999 !important;
ng2-menu-item {
z-index: 9999 !important;
}
}
}
\ No newline at end of file
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { NgbModal, NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';
import { AlertModalComponent } from '../alert-modal/alert-modal.component';
import { UploadService } from '../../../services/upload.service';
import { TagService } from '../../../services/tag.service';
import { TagModel } from '../../../models/tag.mmodel';
import { GroupModel } from '../../../models/group.mmodel';
import { OpenImageComponent } from '../open-image/open-image.component';
import { GroupService } from '../../../services/group.service';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { NgSelectModule } from '@ng-select/ng-select';
import { SharedModule } from '../../../../shared/shared.module';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { TranslateModule } from '@ngx-translate/core';
import saveAs from 'file-saver';
import { TagInputModule } from 'ngx-chips';
import swal from 'sweetalert';
import { WidgetModel } from '../../../models/widgets.model';
import { WidgetService } from '../../../services/widgets.service';
@Component({
selector: 'app-list-widgets',
templateUrl: './list-widgets.component.html',
styleUrls: ['./list-widgets.component.scss'],
standalone: true,
imports: [
CommonModule,
FormsModule,
RouterModule,
NgSelectModule,
SharedModule,
MatDialogModule,
TranslateModule,
NgbPaginationModule,
TagInputModule,
],
})
export class ListWidgetsComponent implements OnInit {
@ViewChild("editTemplateModal") editTemplateModalRef!: TemplateRef<any>;
checkType: string = '';
page = 1;
pageSize = 10;
pageIndex: number = 0;
maxPagesToShow: number = 3;
// Initialize with empty arrays to prevent undefined errors before data loads
listWidgets: WidgetModel[] = []; // This will now store the filtered list
originallistWidgets: WidgetModel[] = []; // This will store the raw data from API
paginatedWidgets: WidgetModel[] = []; // This will store the sliced data for the current page
dialogRef: any;
modelWidget: WidgetModel = new WidgetModel({});
checkEdit: boolean = false;
search: string = '';
listTag: TagModel[] = [];
listGroup: GroupModel[] = [];
constructor(private modalService: NgbModal, private widgetService: WidgetService,
private uploadService: UploadService,
private tagService: TagService,
private groupService: GroupService,
private dialog: MatDialog,) {
}
// Central method for filtering and pagination
applyFilterAndPagination() {
// Ensure `originallistWidgets` is the source for filtering
this.listWidgets = this.originallistWidgets.filter(x =>
x.widgetTname.toLowerCase().includes(this.search.toLowerCase()) ||
x.widgetEname.toLowerCase().includes(this.search.toLowerCase())
);
const totalPagesAfterFilter = Math.ceil(this.listWidgets.length / this.pageSize);
if (this.pageIndex >= totalPagesAfterFilter && totalPagesAfterFilter > 0) {
this.pageIndex = totalPagesAfterFilter - 1;
} else if (totalPagesAfterFilter === 0) {
this.pageIndex = 0;
}
const startIndex = this.pageIndex * this.pageSize;
const endIndex = startIndex + this.pageSize;
this.paginatedWidgets = this.listWidgets.slice(startIndex, endIndex);
}
onSelectFile(event: any) {
if (event.target.files && event.target.files[0]) {
const reader = new FileReader();
const file: File = event.target.files[0];
console.log("🚀 ~ listWidgetsComponent ~ onSelectFile ~ file:", file)
reader.readAsDataURL(event.target.files[0]); // read file as data url
reader.onload = (event) => { // called once readAsDataURL is completed
if (event) {
const allowedTypes = ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel.sheet.macroEnabled.12'];
if (!allowedTypes.includes(file.type)) {
this.openAlertModalWithMatDialog('อัพโหลดได้เฉพาะไฟล์ *.xlsx *.xlsm เท่านั้น');
} else {
let base64 = event.target!.result as string;
this.modelWidget.widgetObj = base64.split(',')[1];
this.modelWidget.fileType = file.name.split('.')[file.name.split('.').length - 1];
}
}
};
}
}
async downloadFile(logId: string) {
try {
// Assuming modelWidget.fileType is available and correct after a file has been selected/uploaded
// If not, you might need to get the file type from the service or infer it.
const data = await this.widgetService.downloadFile(logId).toPromise();
if (data) {
const fileName = `${logId}.${this.modelWidget.fileType || 'xlsx'}`; // Fallback to 'xlsx'
saveAs(new Blob([data]), fileName);
}
} catch (error) {
console.error('Error downloading file:', error);
this.openAlertModalWithMatDialog('ไม่สามารถดาวน์โหลดไฟล์ได้');
}
}
async getListGroup() {
try {
const data = await this.groupService.getList().toPromise();
this.listGroup = data!.map(x => new GroupModel(x));
} catch (error) {
console.error('Error loading groups:', error);
this.openAlertModalWithMatDialog('ไม่สามารถโหลดรายการกลุ่มได้');
}
}
selectGroup() {
let findData = this.listGroup.find(x => x.groupId === this.modelWidget.group.groupId);
this.modelWidget.group = findData ? new GroupModel(findData) : new GroupModel({});
}
async onUploadImage(event: any) {
try {
if (event.target.files.length > 0) {
let fileData = event.target.files[0];
const formData = new FormData();
formData.append('file', fileData);
const allowedTypes = ['image/png', 'image/jpeg', 'image/jpg'];
if (!allowedTypes.includes(fileData.type)) {
this.openAlertModalWithMatDialog('อัพโหลดได้เฉพาะไฟล์ *.jpeg, *.jpg, *.png เท่านั้น');
} else {
const data = await this.uploadService.uploadImage(formData).toPromise();
if (data) {
this.modelWidget.picture = data.body.fileId;
}
}
}
} catch (error) {
console.error('Error uploading image:', error);
this.openAlertModalWithMatDialog('เกิดข้อผิดพลาดในการอัปโหลดรูปภาพ');
}
}
deleteFile(item: WidgetModel) {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณต้องการลบข้อมูลนี้หรือไม่",
icon: "warning",
dangerMode: true,
buttons: ["ยกเลิก", "ยืนยัน"],
}).then((willDelete: boolean) => {
if (willDelete) {
this.widgetService.deleteWidget(item).subscribe(result => {
if (result) {
swal("ลบสำเร็จ!!", "บันทึกข้อมูลสำเร็จ", "success");
this.getListWidgets(); // Re-fetch and re-apply filter/pagination
} else {
swal("สำเร็จบางส่วน/ข้อผิดพลาด!!", "มีการลบข้อมูลบางส่วนไม่สำเร็จ หรือมีข้อผิดพลาด", "warning");
}
}, error => {
this.openAlertModalWithMatDialog(error.message);
});
}
});
}
openAlertModalWithMatDialog(message?: string) {
this.dialog.open(AlertModalComponent, {
data: { message: message ? message : "" },
width: '400px',
disableClose: true,
});
}
onUpdate() {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณต้องการอัพเดทข้อมูลหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
}).then((willUpdate: boolean) => {
if (willUpdate) {
console.log(this.modelWidget);
this.widgetService.createWidget(this.modelWidget).subscribe(res => {
if (res) {
swal("บันทึกสำเร็จ!!", "อัพเดทข้อมูลสำเร็จ", "success");
this.closeDialog();
this.getListWidgets(); // Re-fetch and re-apply filter/pagination
} else {
swal('ไม่สามารถอัพเดทข้อมูลได้');
}
}, error => {
console.error("เกิดข้อผิดพลาดในการบันทึก/อัปเดต:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถบันทึก/อัปเดตข้อมูลได้", "error");
});
}
});
}
onCreate() {
swal({
title: "คุณแน่ใจหรือไม่?",
text: "คุณต้องการบันทึกหรือไม่",
icon: "warning",
dangerMode: false,
buttons: ["ยกเลิก", "ยืนยัน"],
}).then((willSave: boolean) => {
if (willSave) {
this.widgetService.createWidget(this.modelWidget).subscribe(res => {
if (res) {
swal("บันทึกสำเร็จ!!", "บันทึกข้อมูลสมาชิก", "success");
this.closeDialog();
this.getListWidgets(); // Re-fetch and re-apply filter/pagination
} else {
swal('ไม่สามารถสร้างเอกสารได้');
}
}, error => {
console.error("เกิดข้อผิดพลาดในการบันทึก/อัปเดต:", error);
swal("ข้อผิดพลาด!!", "ไม่สามารถบันทึก/อัปเดตข้อมูลได้", "error");
});
}
});
}
onSumit() {
if (this.checkEdit) {
this.onUpdate();
} else {
this.onCreate();
}
}
// This method openModal with NgbModal is currently unused as MatDialog is used for edit template.
// If not explicitly needed for other NgbModal usage, it can be removed.
async getWidgetById(targetModal: NgbModal, id: string) {
try {
const data = await this.widgetService.getWidgetById(id).toPromise();
this.modelWidget = new WidgetModel(data!);
if (data) {
this.modalService.open(targetModal, {
centered: true,
backdrop: 'static',
size: 'lg'
});
}
} catch (error) {
console.error('Error loading data:', error);
}
}
getStatus(status: string): string {
if (status === '0') {
return 'Private';
} else if (status === '1') {
return 'Public';
} else {
return 'ไม่ทราบสถานะ';
}
}
async getListWidgets() {
try {
const data = await this.widgetService.getListWidgets().toPromise();
this.originallistWidgets = data!.map(x => new WidgetModel(x)); // Populate original list
this.applyFilterAndPagination(); // Apply filter and pagination after fetching
} catch (error) {
console.error('Error loading data:', error);
this.openAlertModalWithMatDialog('ไม่สามารถโหลดรายการ Widget ได้');
}
}
get totalFilteredItems(): number {
return this.listWidgets.length; // `listWidgets` now holds the filtered count
}
get totalPages(): number {
return Math.ceil(this.totalFilteredItems / this.pageSize);
}
get startItemIndex(): number {
if (this.totalFilteredItems === 0) return 0;
return this.pageIndex * this.pageSize + 1;
}
get endItemIndex(): number {
const end = Math.min((this.pageIndex + 1) * this.pageSize, this.totalFilteredItems);
return end;
}
goToPage(page: number) {
if (page >= 0 && page < this.totalPages) {
this.pageIndex = page;
this.applyFilterAndPagination(); // Re-apply filter and pagination
} else if (this.totalPages === 0 && page === 0) {
this.pageIndex = 0;
this.applyFilterAndPagination();
}
}
onSearchChange() {
this.pageIndex = 0; // Reset to the first page when search changes
this.applyFilterAndPagination(); // Re-apply filter and pagination
}
get pages(): number[] {
const pages: number[] = [];
const startPage = Math.max(0, this.pageIndex - Math.floor(this.maxPagesToShow / 2));
const endPage = Math.min(this.totalPages - 1, startPage + this.maxPagesToShow - 1);
for (let i = startPage; i <= endPage; i++) {
pages.push(i);
}
return pages;
}
ngOnInit() {
this.getListWidgets(); // Initial data fetch and display
this.getListTag();
this.getListGroup();
}
async getListTag() {
try {
// Assuming tagService.getListWidgets() is the correct method for tags
const data = await this.tagService.getList().toPromise(); // Assuming general getList
this.listTag = data!.map(x => new TagModel(x));
} catch (error) {
console.error('Error loading tags:', error);
this.openAlertModalWithMatDialog('ไม่สามารถโหลดรายการแท็กได้');
}
}
openEmployeeDialog(image: string) {
const dialogConfig = {
width: '750px',
disableClose: false,
data: {
linkImage: image
},
panelClass: 'my-dialog-img-preview',
};
this.dialogRef = this.dialog.open(OpenImageComponent, dialogConfig);
this.dialogRef.afterClosed().subscribe((result: any) => {
console.log('The dialog was closed', result);
}, (reason: any) => {
});
}
openEditExcelDialog(item?: WidgetModel) {
if (item) {
this.widgetService.getWidgetById(item.widgetId).toPromise().then(data => {
if (data) {
this.modelWidget = new WidgetModel(data!);
this.checkEdit = true;
}
this.dialogRef = this.dialog.open(this.editTemplateModalRef, {
width: '1100px',
disableClose: true,
});
this.dialogRef.afterClosed().subscribe((result: boolean) => {
console.log('Edit Widget dialog closed with result:', result);
if (result === true) {
this.getListWidgets(); // Refresh list on success
}
});
}).catch(error => {
console.error('Error loading data for edit:', error);
this.openAlertModalWithMatDialog('ไม่สามารถโหลดข้อมูลเพื่อแก้ไขได้');
});
} else {
this.modelWidget = new WidgetModel({});
this.checkEdit = false;
this.dialogRef = this.dialog.open(this.editTemplateModalRef, {
width: '800px',
disableClose: true,
});
this.dialogRef.afterClosed().subscribe((result: boolean) => {
console.log('Edit Widget dialog closed with result:', result);
if (result === true) {
this.getListWidgets(); // Refresh list on success
}
});
}
}
closeDialog() {
if (this.dialogRef) {
this.dialogRef.close();
}
}
closeBtnClick() {
this.modalService.dismissAll();
}
openLink(url: string) {
window.open(url, "_blank");
}
}
\ No newline at end of file
<app-page-header [title]="'รายการวิทเจ็ท'" [activeTitle]="'ผู้ดูแลระบบ'"
[title1]="'รายการวิทเจ็ท'"></app-page-header>
<!-- <div class="row">
<div class="col-12">
<div class="py-3">
<input type="text" class="form-control w-25" placeholder="ค้นหา" [(ngModel)]="search">
</div>
</div>
<div class="col-sm-6 col-md-4 col-lg-4 mb-3" *ngFor="let data of filterListWidget()">
<div class="card border-5 border border-widget h-100 shadow">
<div class=" p-2 border-5">
<img width="100" class="card-img-top cover" src="{{data.getImage()}}"
(click)="openEmployeeModal(data.getImage())">
</div>
<div class="card-body">
<h4 class="card-title">{{ data.widgetTname }}</h4>
<p class="card-text ">{{ data.thDesc }}</p>
<p class="text-info pointer mb-0" (click)="downloadFile(data.widgetId)"><i class="fas fa-download mr-1"></i>
ดาวน์โหลด <small class="text-muted" *ngIf="data.dwTime > 0">{{coverDate(data.downloadDate)}}
{{data.downloadTime}} ( {{data.dwTime}} ครั้ง)</small></p>
<p class="text-info pointer mb-0" (click)="openLink(data.link1)"><i class="fas fa-link mr-1"></i>
ตัวอย่างวิธีใช้งาน</p>
</div>
<div class="card-footer border-bottom-5">
<small class="text-muted">วันที่อัพโหลด {{coverDate(data.uploadDate)}} {{data.uploadTime}}</small>
</div>
</div>
</div>
</div> -->
<div class="box p-4">
<div class="flex flex-wrap -mx-2">
<div class="w-full">
<div class="py-3 px-2">
<input type="text"
class="block w-full md:w-1/4 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all duration-200 shadow-sm"
placeholder="ค้นหา" [(ngModel)]="search" />
</div>
</div>
<div class="w-full sm:w-1/2 lg:w-1/3 xl:w-1/3 px-2 mb-4" *ngFor="let data of filterListWidget()">
<div
class="group bg-white rounded-lg overflow-hidden shadow-lg border-4 border-blue-600 h-full flex flex-col transform transition-all duration-300 ease-in-out hover:scale-[1.02] hover:shadow-xl">
<div class="p-4 flex justify-center items-center flex-shrink-0">
<img
class="w-full h-full object-cover rounded-md shadow-md transform transition-transform duration-300 group-hover:scale-105 cursor-pointer"
style="width: 400px; height: 200px; max-width: 100%;" src="{{ data.getImage() }}" alt="{{ data.widgetTname }}"
(click)="openDialog(data.getImage())" />
</div>
<div class="p-4 flex-grow">
<span class="text-xl font-semibold text-gray-800 mb-2" style="font-size: 18px;">
{{ data.widgetTname }}
</span>
<p class="text-gray-700 text-sm mb-3">{{ data.thDesc }}</p>
<div class="mb-0 flex items-center justify-center sm:justify-start gap-2 w-1/2 mt-5">
<i class="fa fa-link text-blue-600 text-base flex-shrink-0" aria-hidden="true"></i>
<input type="text" [value]="'ตัวอย่างวิธีใช้งาน'" (click)="openLink(data.link1)"
style="background-color: rgb(76, 117, 207, 1); color: #FFF;"
class="flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly />
</div>
<div class="mb-2 flex items-center justify-center sm:justify-start gap-2 w-1/2">
<i class="fa fa-download text-blue-600 text-base flex-shrink-0" aria-hidden="true"></i>
<input type="text" [value]="'ดาวน์โหลด'" (click)="downloadFile(data.widgetId)"
style="background-color: rgb(34, 197, 94, 1); color: #FFF;"
class="flex-grow border border-gray-300 rounded-md px-2 py-1 text-blue-600 cursor-pointer hover:underline focus:outline-none focus:ring-1 focus:ring-blue-500 transition-all duration-200"
readonly />
</div>
</div>
<div class="px-4 py-3 border-t border-gray-200 text-right flex-shrink-0">
<small class="text-gray-500 text-xs">วันที่อัพโหลด {{ coverDate(data.uploadDate) }}
{{ data.uploadTime }}</small>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { NgbModal, NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';
import { AlertModalComponent } from '../alert-modal/alert-modal.component';
import { OpenImageComponent } from '../open-image/open-image.component';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { SharedModule } from '../../../../shared/shared.module';
import { TranslateModule } from '@ngx-translate/core';
import { NgSelectModule } from '@ng-select/ng-select';
import saveAs from 'file-saver';
import { WidgetModel } from '../../../models/widgets.model';
import { WidgetService } from '../../../services/widgets.service';
@Component({
selector: 'app-view-list-widgets',
templateUrl: './view-list-widgets.component.html',
styleUrls: ['./view-list-widgets.component.scss'],
standalone: true,
imports: [
CommonModule,
FormsModule,
NgSelectModule,
SharedModule,
MatDialogModule,
NgbPaginationModule,
TranslateModule,
],
})
export class ViewListWidgetsComponent implements OnInit {
page = 1;
pageSize = 10;
listWidget:WidgetModel[]=[]
search:string = ''
dialogRef: any;
constructor(private modalService: NgbModal,private widgetService:WidgetService, private dialog: MatDialog,) {
}
openDialog(image: string) {
const dialogConfig = {
width: '750px',
disableClose: false,
data: {
linkImage: image
},
panelClass: 'my-dialog-img-preview',
};
this.dialogRef = this.dialog.open(OpenImageComponent, dialogConfig);
this.dialogRef.afterClosed().subscribe((result: any) => {
console.log('The dialog was closed', result);
}, (reason: any) => {
});
}
async downloadFile(logId: string) {
try {
const data = await this.widgetService.downloadFile(logId).toPromise();
if (data) {
saveAs(new Blob([data]), "file_download.xlsx");
}
} catch (error) {
console.error('Error loading data:', error);
}
}
// getStatus(status: string) {
// if (status == '0') {
// return 'Private'
// } else if (status == '1') {
// return 'Public'
// }
// }
filterListWidget(){
return this.listWidget.filter(x => x.widgetTname.toLowerCase().includes(this.search.toLowerCase())||x.widgetEname.toLowerCase().includes(this.search.toLowerCase()))
}
async getListExcel(){
try {
const data = await this.widgetService.getListWidgets().toPromise();
this.listWidget = data!.map(x => new WidgetModel(x))
} catch (error) {
console.error('Error loading data:', error);
}
}
ngOnInit() {
this.getListExcel();
}
openLink(url:string){
window.open(url, "_blank");
}
openAlertModal(message?: string) {
const modalRef = this.modalService.open(AlertModalComponent, {
centered: true,
backdrop: 'static'
})
modalRef.componentInstance.message = message ? message : ""
modalRef.result.then(result => {
this.modalService.dismissAll()
}, reason => {
this.modalService.dismissAll()
})
}
coverDate(date:string){
return date.split('-').reverse().join('/')
}
}
...@@ -30,11 +30,6 @@ export const myportal: Routes = [ ...@@ -30,11 +30,6 @@ export const myportal: Routes = [
import('../myskill-x/myportal/view-list-course/view-list-course.component').then((m) => m.ViewListCourseComponent), import('../myskill-x/myportal/view-list-course/view-list-course.component').then((m) => m.ViewListCourseComponent),
}, },
{ {
path: 'view-list-widgets',
loadComponent: () =>
import('../myskill-x/myportal/view-list-widgets/view-list-widgets.component').then((m) => m.ViewListWidgetsComponent),
},
{
path: 'excel-report', path: 'excel-report',
loadComponent: () => loadComponent: () =>
import('../myskill-x/myportal/excel-report/excel-report.component').then((m) => m.ExcelReportComponent), import('../myskill-x/myportal/excel-report/excel-report.component').then((m) => m.ExcelReportComponent),
...@@ -60,11 +55,6 @@ export const myportal: Routes = [ ...@@ -60,11 +55,6 @@ export const myportal: Routes = [
import('../myskill-x/myportal/list-doc/list-doc.component').then((m) => m.ListDocComponent), import('../myskill-x/myportal/list-doc/list-doc.component').then((m) => m.ListDocComponent),
}, },
{ {
path: 'list-widgets',
loadComponent: () =>
import('../myskill-x/myportal/list-widgets/list-widgets.component').then((m) => m.ListWidgetsComponent),
},
{
path: 'excel-list', path: 'excel-list',
loadComponent: () => loadComponent: () =>
import('../myskill-x/myportal/set-excel-reports/excel-list/excel-list.component').then((m) => m.ExcelListComponent), import('../myskill-x/myportal/set-excel-reports/excel-list/excel-list.component').then((m) => m.ExcelListComponent),
...@@ -154,4 +144,4 @@ export const myportal: Routes = [ ...@@ -154,4 +144,4 @@ export const myportal: Routes = [
}) })
export class MyskillXModule { export class MyskillXModule {
static routes = myportal; static routes = myportal;
} }
\ No newline at end of file
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { DatasetModel } from '../models/widgets.model';
@Injectable({
providedIn: 'root'
})
export class DatasetService {
private datasets: DatasetModel[] = [
new DatasetModel({ id: '1', name: 'Sample Dataset 1', url: 'assets/data/sample1.json' }),
new DatasetModel({ id: '2', name: 'Sample Dataset 2', url: 'assets/data/sample2.json' })
];
constructor() { }
getDatasets(): Observable<DatasetModel[]> {
return of(this.datasets);
}
getDatasetById(id: string): Observable<DatasetModel | undefined> {
return of(this.datasets.find(d => d.id === id));
}
}
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { DashboardModel, WidgetModel } from '../models/widgets.model';
export const MOCK_DASHBOARD_DATA: DashboardModel[] = [
{
id: '1',
name: 'Sales Dashboard',
description: 'Dashboard showing sales performance over time.',
widgets: [
{ id: '101', name: 'Monthly Sales', component: 'ChartWidgetComponent', cols: 2, rows: 1, x: 0, y: 0, data: { type: 'bar', labels: ['Jan', 'Feb', 'Mar'], datasets: [{ data: [65, 59, 80], label: 'Series A' }] } },
{ id: '102', name: 'Top Products', component: 'SyncfusionDatagridWidgetComponent', cols: 2, rows: 1, x: 2, y: 0, data: { columns: ['Product', 'Sales'], data: [{ Product: 'A', Sales: 100 }, { Product: 'B', Sales: 150 }] } }
]
},
{
id: '2',
name: 'Marketing Overview',
description: 'Overview of marketing campaign performance.',
widgets: [
{ id: '201', name: 'Website Traffic', component: 'ChartWidgetComponent', cols: 2, rows: 1, x: 0, y: 0, data: { type: 'line', labels: ['Week 1', 'Week 2', 'Week 3'], datasets: [{ data: [120, 150, 130], label: 'Visitors' }] } },
{ id: '202', name: 'Conversion Rate', component: 'KpiWidgetComponent', cols: 1, rows: 1, x: 2, y: 0, data: { value: '2.5%', label: 'Conversion' } }
]
}
];
@Injectable({
providedIn: 'root'
})
export class MockDashboardService {
constructor() { }
getDashboards(): Observable<DashboardModel[]> {
return of(MOCK_DASHBOARD_DATA);
}
getDashboardById(id: string): Observable<DashboardModel | undefined> {
const dashboard = MOCK_DASHBOARD_DATA.find(d => d.id === id);
return of(dashboard);
}
}
...@@ -36,7 +36,7 @@ export class WidgetService { ...@@ -36,7 +36,7 @@ export class WidgetService {
} }
deleteWidget(model: WidgetModel): Observable<any> { deleteWidget(model: WidgetModel): Observable<any> {
let body = { let body = {
widgetId: model.widgetId widgetId: model.id
} }
let option = { let option = {
headers: new HttpHeaders({ headers: new HttpHeaders({
......
import { createAction, props } from '@ngrx/store';
import { DashboardModel, WidgetModel, DatasetModel } from '../models/widgets.model';
export const loadDashboards = createAction('[Dashboard] Load Dashboards');
export const loadDashboardsSuccess = createAction('[Dashboard] Load Dashboards Success', props<{ dashboards: DashboardModel[] }>());
export const loadDashboardsFailure = createAction('[Dashboard] Load Dashboards Failure', props<{ error: any }>());
export const loadWidgets = createAction('[Dashboard] Load Widgets');
export const loadWidgetsSuccess = createAction('[Dashboard] Load Widgets Success', props<{ widgets: WidgetModel[] }>());
export const loadWidgetsFailure = createAction('[Dashboard] Load Widgets Failure', props<{ error: any }>());
export const loadDatasets = createAction('[Dashboard] Load Datasets');
export const loadDatasetsSuccess = createAction('[Dashboard] Load Datasets Success', props<{ datasets: DatasetModel[] }>());
export const loadDatasetsFailure = createAction('[Dashboard] Load Datasets Failure', props<{ error: any }>());
export const addDashboard = createAction('[Dashboard] Add Dashboard', props<{ dashboard: DashboardModel }>());
export const addDashboardSuccess = createAction('[Dashboard] Add Dashboard Success', props<{ dashboard: DashboardModel }>());
export const addDashboardFailure = createAction('[Dashboard] Add Dashboard Failure', props<{ error: any }>());
export const updateDashboard = createAction('[Dashboard] Update Dashboard', props<{ dashboard: DashboardModel }>());
export const updateDashboardSuccess = createAction('[Dashboard] Update Dashboard Success', props<{ dashboard: DashboardModel }>());
export const updateDashboardFailure = createAction('[Dashboard] Update Dashboard Failure', props<{ error: any }>());
export const deleteDashboard = createAction('[Dashboard] Delete Dashboard', props<{ id: string }>());
export const deleteDashboardSuccess = createAction('[Dashboard] Delete Dashboard Success', props<{ id: string }>());
export const deleteDashboardFailure = createAction('[Dashboard] Delete Dashboard Failure', props<{ error: any }>());
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { of } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { DashboardDataService } from '../../shared/services/dashboard-data.service';
import * as DashboardActions from './dashboard.actions';
@Injectable()
export class DashboardEffects {
loadDashboards$ = createEffect(() => this.actions$.pipe(
ofType(DashboardActions.loadDashboards),
mergeMap(() => this.dashboardDataService.getDashboards()
.pipe(
map(dashboards => DashboardActions.loadDashboardsSuccess({ dashboards })),
catchError(error => of(DashboardActions.loadDashboardsFailure({ error })))
))
));
loadWidgets$ = createEffect(() => this.actions$.pipe(
ofType(DashboardActions.loadWidgets),
mergeMap(() => this.dashboardDataService.getWidgets()
.pipe(
map(widgets => DashboardActions.loadWidgetsSuccess({ widgets })),
catchError(error => of(DashboardActions.loadWidgetsFailure({ error })))
))
));
loadDatasets$ = createEffect(() => this.actions$.pipe(
ofType(DashboardActions.loadDatasets),
mergeMap(() => this.dashboardDataService.getDatasets()
.pipe(
map(datasets => DashboardActions.loadDatasetsSuccess({ datasets })),
catchError(error => of(DashboardActions.loadDatasetsFailure({ error })))
))
));
addDashboard$ = createEffect(() => this.actions$.pipe(
ofType(DashboardActions.addDashboard),
mergeMap(action => this.dashboardDataService.addDashboard(action.dashboard)
.pipe(
map(dashboard => DashboardActions.addDashboardSuccess({ dashboard })),
catchError(error => of(DashboardActions.addDashboardFailure({ error })))
))
));
updateDashboard$ = createEffect(() => this.actions$.pipe(
ofType(DashboardActions.updateDashboard),
mergeMap(action => this.dashboardDataService.updateDashboard(action.dashboard)
.pipe(
map(dashboard => DashboardActions.updateDashboardSuccess({ dashboard })),
catchError(error => of(DashboardActions.updateDashboardFailure({ error })))
))
));
deleteDashboard$ = createEffect(() => this.actions$.pipe(
ofType(DashboardActions.deleteDashboard),
mergeMap(action => this.dashboardDataService.deleteDashboard(action.id)
.pipe(
map(() => DashboardActions.deleteDashboardSuccess({ id: action.id })),
catchError(error => of(DashboardActions.deleteDashboardFailure({ error })))
))
));
constructor(
private actions$: Actions,
private dashboardDataService: DashboardDataService
) {}
}
import { createReducer, on } from '@ngrx/store';
import { DashboardModel, WidgetModel, DatasetModel } from '../models/widgets.model';
import * as DashboardActions from './dashboard.actions';
export interface DashboardState {
dashboards: DashboardModel[];
widgets: WidgetModel[];
datasets: DatasetModel[];
error: any;
}
export const initialState: DashboardState = {
dashboards: [],
widgets: [],
datasets: [],
error: null,
};
export const dashboardReducer = createReducer(
initialState,
on(DashboardActions.loadDashboardsSuccess, (state, { dashboards }) => ({ ...state, dashboards })),
on(DashboardActions.loadDashboardsFailure, (state, { error }) => ({ ...state, error })),
on(DashboardActions.loadWidgetsSuccess, (state, { widgets }) => ({ ...state, widgets })),
on(DashboardActions.loadWidgetsFailure, (state, { error }) => ({ ...state, error })),
on(DashboardActions.loadDatasetsSuccess, (state, { datasets }) => ({ ...state, datasets })),
on(DashboardActions.loadDatasetsFailure, (state, { error }) => ({ ...state, error })),
on(DashboardActions.addDashboardSuccess, (state, { dashboard }) => ({ ...state, dashboards: [...state.dashboards, dashboard] })),
on(DashboardActions.addDashboardFailure, (state, { error }) => ({ ...state, error })),
on(DashboardActions.updateDashboardSuccess, (state, { dashboard }) => ({
...state,
dashboards: state.dashboards.map(d => d.id === dashboard.id ? dashboard : d)
})),
on(DashboardActions.updateDashboardFailure, (state, { error }) => ({ ...state, error })),
on(DashboardActions.deleteDashboardSuccess, (state, { id }) => ({
...state,
dashboards: state.dashboards.filter(d => d.id !== id)
})),
on(DashboardActions.deleteDashboardFailure, (state, { error }) => ({ ...state, error }))
);
import { createFeatureSelector, createSelector } from '@ngrx/store';
import { DashboardState } from './dashboard.reducer';
import { DashboardModel } from '../models/widgets.model';
export const selectDashboardState = createFeatureSelector<DashboardState>('dashboard');
export const selectAllDashboards = createSelector(
selectDashboardState,
(state: DashboardState) => state.dashboards
);
export const selectAllWidgets = createSelector(
selectDashboardState,
(state: DashboardState) => state.widgets
);
export const selectAllDatasets = createSelector(
selectDashboardState,
(state: DashboardState) => state.datasets
);
export const selectDashboardById = (id: string) => createSelector(
selectAllDashboards,
(dashboards: DashboardModel[]) => dashboards.find(d => d.id === id)
);
export const selectError = createSelector(
selectDashboardState,
(state: DashboardState) => state.error
);
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
import { Component, OnInit, Type } from '@angular/core'; import { Component, OnInit, Type } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { ActivatedRoute, Router, RouterModule } from '@angular/router'; import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { DashboardService } from '../../shared/services/dashboard.service';
import { Widget } from '../../shared/models/dashboard.model';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { NgComponentOutlet } from '@angular/common'; import { NgComponentOutlet } from '@angular/common';
import { Store } from '@ngrx/store';
import * as DashboardActions from '../state/dashboard.actions';
import { WidgetModel } from '../models/widgets.model';
// Import all the widget components // Import all the widget components
import { CompanyInfoWidgetComponent } from '../widgets/company-info-widget.component'; import { CompanyInfoWidgetComponent } from '../widgets/company-info-widget.component';
...@@ -53,13 +54,12 @@ export class WidgetFormComponent implements OnInit { ...@@ -53,13 +54,12 @@ export class WidgetFormComponent implements OnInit {
constructor( constructor(
private fb: FormBuilder, private fb: FormBuilder,
private dashboardService: DashboardService, private store: Store,
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router private router: Router
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.appName = this.route.snapshot.paramMap.get('appName') || '';
this.widgetId = this.route.snapshot.paramMap.get('widgetId'); this.widgetId = this.route.snapshot.paramMap.get('widgetId');
this.widgetForm = this.fb.group({ this.widgetForm = this.fb.group({
...@@ -69,17 +69,19 @@ export class WidgetFormComponent implements OnInit { ...@@ -69,17 +69,19 @@ export class WidgetFormComponent implements OnInit {
cols: [1, [Validators.required, Validators.min(1)]], cols: [1, [Validators.required, Validators.min(1)]],
rows: [1, [Validators.required, Validators.min(1)]], rows: [1, [Validators.required, Validators.min(1)]],
x: [0], x: [0],
y: [0] y: [0],
data: [null]
}); });
if (this.widgetId && this.widgetId !== 'new') { if (this.widgetId && this.widgetId !== 'new') {
this.isNew = false; this.isNew = false;
this.dashboardService.getWidget(this.widgetId).subscribe(widget => { this.store.dispatch(DashboardActions.loadWidgets());
if (widget) { // this.store.select(DashboardSelectors.selectWidgetById(this.widgetId)).subscribe(widget => {
this.widgetForm.patchValue(widget); // if (widget) {
this.updatePreview(widget.component); // this.widgetForm.patchValue(widget);
} // this.updatePreview(widget.component);
}); // }
// });
} }
// Subscribe to component name changes for live preview // Subscribe to component name changes for live preview
...@@ -97,10 +99,13 @@ export class WidgetFormComponent implements OnInit { ...@@ -97,10 +99,13 @@ export class WidgetFormComponent implements OnInit {
return; return;
} }
const widgetData: Widget = this.widgetForm.value; const widgetData: WidgetModel = this.widgetForm.value;
this.dashboardService.saveWidget(widgetData).subscribe(() => { if (this.isNew) {
this.router.navigate(['/dpu', this.appName, 'widget-warehouse']); // this.store.dispatch(DashboardActions.addWidget({ widget: widgetData }));
}); } else {
// this.store.dispatch(DashboardActions.updateWidget({ widget: widgetData }));
}
this.router.navigate(['/dpu/widget-management']);
} }
cancel(): void { cancel(): void {
......
...@@ -2,10 +2,12 @@ ...@@ -2,10 +2,12 @@
import { Component, OnInit, Type } from '@angular/core'; import { Component, OnInit, Type } from '@angular/core';
import { ActivatedRoute, Router, RouterModule } from '@angular/router'; import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { Widget } from '../../shared/models/dashboard.model';
import { DashboardService } from '../../shared/services/dashboard.service';
import { CommonModule, TitleCasePipe } from '@angular/common'; import { CommonModule, TitleCasePipe } from '@angular/common';
import { NgComponentOutlet } from '@angular/common'; import { NgComponentOutlet } from '@angular/common';
import { Store } from '@ngrx/store';
import * as DashboardActions from '../state/dashboard.actions';
import * as DashboardSelectors from '../state/dashboard.selectors';
import { WidgetModel } from '../models/widgets.model';
// Import all the widget components // Import all the widget components
import { CompanyInfoWidgetComponent } from '../widgets/company-info-widget.component'; import { CompanyInfoWidgetComponent } from '../widgets/company-info-widget.component';
...@@ -28,7 +30,7 @@ import { SyncfusionChartWidgetComponent } from '../widgets/syncfusion-chart-widg ...@@ -28,7 +30,7 @@ import { SyncfusionChartWidgetComponent } from '../widgets/syncfusion-chart-widg
templateUrl: './widget-list.component.html', templateUrl: './widget-list.component.html',
}) })
export class WidgetListComponent implements OnInit { export class WidgetListComponent implements OnInit {
widgets$!: Observable<Widget[]>; widgets$!: Observable<WidgetModel[]>;
appName: string = ''; appName: string = '';
// Map string names to actual component classes // Map string names to actual component classes
...@@ -48,19 +50,14 @@ export class WidgetListComponent implements OnInit { ...@@ -48,19 +50,14 @@ export class WidgetListComponent implements OnInit {
}; };
constructor( constructor(
private dashboardService: DashboardService, private store: Store,
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router private router: Router
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.appName = this.route.snapshot.paramMap.get('appName') || ''; this.store.dispatch(DashboardActions.loadWidgets());
if (this.appName) { this.widgets$ = this.store.select(DashboardSelectors.selectAllWidgets);
this.widgets$ = this.dashboardService.getWidgets(this.appName);
} else {
// Handle case where appName is not in the URL
console.error('App name is missing from the route.');
}
} }
getComponentType(componentName: string): Type<any> | null { getComponentType(componentName: string): Type<any> | null {
......
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input, OnInit, OnChanges, SimpleChanges, ChangeDetectorRef } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { GridModule, PageService, SortService, FilterService, GroupService } from '@syncfusion/ej2-angular-grids'; import { GridModule, PageService, SortService, FilterService, GroupService } from '@syncfusion/ej2-angular-grids';
import { DatasetService } from '../../services/dataset.service';
import { DatasetModel } from '../../models/widgets.model';
@Component({ @Component({
selector: 'app-syncfusion-datagrid-widget', selector: 'app-syncfusion-datagrid-widget',
...@@ -9,44 +13,37 @@ import { GridModule, PageService, SortService, FilterService, GroupService } fro ...@@ -9,44 +13,37 @@ import { GridModule, PageService, SortService, FilterService, GroupService } fro
providers: [PageService, SortService, FilterService, GroupService], providers: [PageService, SortService, FilterService, GroupService],
templateUrl: './syncfusion-datagrid-widget.component.html', templateUrl: './syncfusion-datagrid-widget.component.html',
}) })
export class SyncfusionDatagridWidgetComponent implements OnInit { export class SyncfusionDatagridWidgetComponent implements OnInit, OnChanges {
@Input() title: string = 'Data Grid'; // New input for title @Input() title: string = 'Data Grid';
@Input() gridData: object[] | undefined; // New input for grid data @Input() datasetId: string;
public data: object[] = []; public data: object[] = [];
public pageSettings: Object = { pageSize: 6 }; public pageSettings: Object = { pageSize: 6 };
constructor(private datasetService: DatasetService, private http: HttpClient, private cdr: ChangeDetectorRef) {}
ngOnInit(): void { ngOnInit(): void {
this.data = this.gridData || [ this.loadData();
{ OrderID: 10248, CustomerID: 'VINET', EmployeeID: 5, ShipCity: 'Reims' }, }
{ OrderID: 10249, CustomerID: 'TOMSP', EmployeeID: 6, ShipCity: 'Münster' },
{ OrderID: 10250, CustomerID: 'HANAR', EmployeeID: 4, ShipCity: 'Rio de Janeiro' }, ngOnChanges(changes: SimpleChanges): void {
{ OrderID: 10251, CustomerID: 'VICTE', EmployeeID: 3, ShipCity: 'Lyon' }, if (changes['datasetId']) {
{ OrderID: 10252, CustomerID: 'SUPRD', EmployeeID: 2, ShipCity: 'Charleroi' }, this.loadData();
{ OrderID: 10253, CustomerID: 'HANAR', EmployeeID: 7, ShipCity: 'Rio de Janeiro' }, }
{ OrderID: 10254, CustomerID: 'CHOPS', EmployeeID: 8, ShipCity: 'Bern' }, }
{ OrderID: 10255, CustomerID: 'RICSU', EmployeeID: 9, ShipCity: 'Genève' },
{ OrderID: 10256, CustomerID: 'WELLI', EmployeeID: 1, ShipCity: 'Resende' }, loadData(): void {
{ OrderID: 10257, CustomerID: 'HILAA', EmployeeID: 2, ShipCity: 'Caracas' }, if (this.datasetId) {
{ OrderID: 10258, CustomerID: 'ERNSH', EmployeeID: 3, ShipCity: 'Graz' }, this.datasetService.getDatasetById(this.datasetId).subscribe((dataset: DatasetModel | undefined) => {
{ OrderID: 10259, CustomerID: 'CENTC', EmployeeID: 4, ShipCity: 'Madrid' }, if (dataset && dataset.url) {
{ OrderID: 10260, CustomerID: 'OTTIK', EmployeeID: 5, ShipCity: 'London' }, this.http.get<object[]>(dataset.url).subscribe(data => {
{ OrderID: 10261, CustomerID: 'QUEDE', EmployeeID: 6, ShipCity: 'Rio de Janeiro' }, this.data = data;
{ OrderID: 10262, CustomerID: 'RATTC', EmployeeID: 7, ShipCity: 'Madrid' }, this.cdr.markForCheck();
{ OrderID: 10263, CustomerID: 'ERNSH', EmployeeID: 8, ShipCity: 'Graz' }, });
{ OrderID: 10264, CustomerID: 'FOLIG', EmployeeID: 9, ShipCity: 'Liège' }, }
{ OrderID: 10265, CustomerID: 'BLONP', EmployeeID: 1, ShipCity: 'Marseille' }, });
{ OrderID: 10266, CustomerID: 'WARTH', EmployeeID: 2, ShipCity: 'Frankfurt a.M.' }, } else {
{ OrderID: 10267, CustomerID: 'FRANS', EmployeeID: 3, ShipCity: 'Torino' }, this.data = [];
{ OrderID: 10268, CustomerID: 'GROSR', EmployeeID: 4, ShipCity: 'London' }, }
{ OrderID: 10269, CustomerID: 'WHITC', EmployeeID: 5, ShipCity: 'Seattle' },
{ OrderID: 10270, CustomerID: 'VAFFE', EmployeeID: 6, ShipCity: 'Oslo' },
{ OrderID: 10271, CustomerID: 'BLAUS', EmployeeID: 7, ShipCity: 'Mannheim' },
{ OrderID: 10272, CustomerID: 'BLONP', EmployeeID: 8, ShipCity: 'Marseille' },
{ OrderID: 10273, CustomerID: 'WARTH', EmployeeID: 9, ShipCity: 'Frankfurt a.M.' },
{ OrderID: 10274, CustomerID: 'FRANS', EmployeeID: 1, ShipCity: 'Torino' },
{ OrderID: 10275, CustomerID: 'GROSR', EmployeeID: 2, ShipCity: 'London' },
{ OrderID: 10276, CustomerID: 'WHITC', EmployeeID: 3, ShipCity: 'Seattle' },
];
} }
} }
...@@ -20,6 +20,13 @@ import { HttpRequestInterceptor } from './shared/services/http-request.intercept ...@@ -20,6 +20,13 @@ import { HttpRequestInterceptor } from './shared/services/http-request.intercept
import { AuthService } from './shared/services/auth.service'; import { AuthService } from './shared/services/auth.service';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader'; import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { MockDataInterceptor } from './shared/interceptors/mock-data.interceptor';
import { DashboardDataService } from './shared/services/dashboard-data.service';
import { provideStore, provideState } from '@ngrx/store';
import { provideEffects } from '@ngrx/effects';
import { provideStoreDevtools } from '@ngrx/store-devtools';
import { dashboardReducer } from './DPU/state/dashboard.reducer';
import { DashboardEffects } from './DPU/state/dashboard.effects';
export function HttpLoaderFactory(http: HttpClient) { export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, "./assets/i18n/", ".json"); return new TranslateHttpLoader(http, "./assets/i18n/", ".json");
...@@ -39,25 +46,51 @@ export const httpInterceptorProviders = [ ...@@ -39,25 +46,51 @@ export const httpInterceptorProviders = [
provide: HTTP_INTERCEPTORS, provide: HTTP_INTERCEPTORS,
useClass: HttpRequestInterceptor, useClass: HttpRequestInterceptor,
multi: true, multi: true,
},
{
provide: HTTP_INTERCEPTORS,
useClass: MockDataInterceptor,
multi: true,
} }
]; ];
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [provideHttpClient(withInterceptors([])), provideRouter(App_Route), RouterOutlet, ColorPickerModule, ColorPickerService, provideAnimations(), AngularFireModule, providers: [
provideHttpClient(withInterceptors([])),
provideRouter(App_Route),
RouterOutlet,
ColorPickerModule,
ColorPickerService,
provideAnimations(),
AngularFireModule,
AngularFireDatabaseModule, AngularFireDatabaseModule,
AngularFirestoreModule, AngularFirestoreModule,
AngularFireAuthModule, AngularFireAuthModule,
importProvidersFrom(RouterModule.forRoot(App_Route, { initialNavigation: 'enabledNonBlocking', useHash: true }), TranslateModule.forRoot(provideTranslation()), CalendarModule.forRoot({ importProvidersFrom(
provide: DateAdapter, RouterModule.forRoot(App_Route, { initialNavigation: 'enabledNonBlocking', useHash: true }),
useFactory: adapterFactory, TranslateModule.forRoot(provideTranslation()),
}), ToastrModule.forRoot({ CalendarModule.forRoot({
timeOut: 15000, // 15 seconds provide: DateAdapter,
closeButton: true, useFactory: adapterFactory,
progressBar: true, }),
}), NgDragDropModule.forRoot(), HttpClientModule), ToastrModule.forRoot({
timeOut: 15000, // 15 seconds
closeButton: true,
progressBar: true,
}),
NgDragDropModule.forRoot(),
HttpClientModule
),
httpInterceptorProviders, httpInterceptorProviders,
DashboardDataService,
provideStore(),
provideState({ name: 'dashboard', reducer: dashboardReducer }),
provideEffects([DashboardEffects]),
provideStoreDevtools({ maxAge: 25, logOnly: environment.production })
] ]
}; };
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http';
import { Observable, of, switchMap } from 'rxjs';
import { DatasetService } from '../../DPU/services/dataset.service';
@Injectable()
export class MockDataInterceptor implements HttpInterceptor {
constructor(private datasetService: DatasetService) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (request.url.startsWith('/api/data/')) {
const datasetId = request.url.split('/').pop();
if (!datasetId) {
return of(new HttpResponse({ status: 404, body: [] }));
}
return this.datasetService.getDatasetById(datasetId).pipe(
switchMap((dataset: any) => {
if (dataset && dataset.url) {
// In a real app, you would fetch the data from the URL.
// For this mock, we'll just return an empty array.
return of(new HttpResponse({ status: 200, body: [] }));
}
return of(new HttpResponse({ status: 404, body: [] }));
})
);
}
return next.handle(request);
}
}
import { Injectable } from '@angular/core';
import { Observable, of, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { DashboardModel, WidgetModel, DatasetModel } from '../../DPU/models/widgets.model';
@Injectable({
providedIn: 'root'
})
export class DashboardDataService {
private mockDatasets: DatasetModel[] = [
new DatasetModel({ id: 'ds-1', name: 'Sales Data', url: '/api/data/sales' }),
new DatasetModel({ id: 'ds-2', name: 'HR Data', url: '/api/data/hr' }),
new DatasetModel({ id: 'ds-3', name: 'Marketing Data', url: '/api/data/marketing' })
];
private mockData: { [key: string]: any[] } = {
'ds-1': [
{ OrderID: 10248, CustomerID: 'VINET', EmployeeID: 5, OrderDate: new Date(8364186e5), ShipName: 'Vins et alcools Chevalier' },
{ OrderID: 10249, CustomerID: 'TOMSP', EmployeeID: 6, OrderDate: new Date(836505e6), ShipName: 'Toms Spezialitäten' },
{ OrderID: 10250, CustomerID: 'HANAR', EmployeeID: 4, OrderDate: new Date(8367642e5), ShipName: 'Hanari Carnes' },
],
'ds-2': [
{ Name: 'John Doe', Title: 'CEO', Country: 'USA' },
{ Name: 'Jane Smith', Title: 'CFO', Country: 'USA' },
{ Name: 'Peter Jones', Title: 'CTO', Country: 'UK' },
]
};
private mockDashboards: DashboardModel[] = [
new DashboardModel({
id: 'dash-1',
name: 'Sales Dashboard',
datasetId: 'ds-1',
widgets: [
new WidgetModel({ id: 'widget-1', name: 'Welcome Message', component: 'WelcomeWidgetComponent', cols: 2, rows: 1, y: 0, x: 0, data: { userName: 'Jane Doe' } }),
new WidgetModel({ id: 'widget-2', name: 'Sales Data Grid', component: 'SyncfusionDatagridWidgetComponent', cols: 4, rows: 3, y: 0, x: 2, data: {} })
]
}),
new DashboardModel({
id: 'dash-2',
name: 'HR Dashboard',
datasetId: 'ds-2',
widgets: [
new WidgetModel({ id: 'widget-1', name: 'Welcome Message', component: 'WelcomeWidgetComponent', cols: 2, rows: 1, y: 0, x: 0, data: { userName: 'John Smith' } })
]
})
];
private mockWidgets: WidgetModel[] = [
new WidgetModel({ id: 'widget-1', name: 'Welcome Message', component: 'WelcomeWidgetComponent', cols: 2, rows: 1, y: 0, x: 0, data: { userName: 'Default User' } }),
new WidgetModel({ id: 'widget-2', name: 'Sales Data Grid', component: 'SyncfusionDatagridWidgetComponent', cols: 4, rows: 3, y: 0, x: 2, data: {} }),
new WidgetModel({ id: 'widget-3', name: 'Chart Widget', component: 'ChartWidgetComponent', cols: 3, rows: 2, y: 0, x: 0, data: {} })
];
constructor() { }
// Dashboard methods
getDashboards(): Observable<DashboardModel[]> {
return of(this.mockDashboards).pipe(catchError(this.handleError));
}
getDashboardById(id: string): Observable<DashboardModel | undefined> {
return of(this.mockDashboards.find(d => d.id === id)).pipe(catchError(this.handleError));
}
addDashboard(dashboard: DashboardModel): Observable<DashboardModel> {
this.mockDashboards.push(dashboard);
return of(dashboard).pipe(catchError(this.handleError));
}
updateDashboard(dashboard: DashboardModel): Observable<DashboardModel> {
const index = this.mockDashboards.findIndex(d => d.id === dashboard.id);
if (index !== -1) {
this.mockDashboards[index] = dashboard;
}
return of(dashboard).pipe(catchError(this.handleError));
}
deleteDashboard(id: string): Observable<void> {
this.mockDashboards = this.mockDashboards.filter(d => d.id !== id);
return of(undefined).pipe(catchError(this.handleError));
}
// Widget methods
getWidgets(): Observable<WidgetModel[]> {
return of(this.mockWidgets).pipe(catchError(this.handleError));
}
// Dataset methods
getDatasets(): Observable<DatasetModel[]> {
return of(this.mockDatasets).pipe(catchError(this.handleError));
}
getDatasetById(id: string): Observable<DatasetModel | undefined> {
return of(this.mockDatasets.find(ds => ds.id === id)).pipe(catchError(this.handleError));
}
private handleError(error: any) {
console.error(error);
return throwError(() => new Error('Something went wrong. Please try again later.'));
}
}
[{"id": 1, "name": "John Doe", "age": 30},{"id": 2, "name": "Jane Smith", "age": 25}]
\ No newline at end of file
[{"product": "Laptop", "price": 1200},{"product": "Mouse", "price": 25}]
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment