@cryptotaxi247 / CoPilot / commits / ec3fe390

Overview alerts (#313)

* `chore: Uncomment bucket creation during initialization` * refactor: Remove requirement for CUSTOMER_CODE field in CustomMonitoringAlertProvisionModel * chore: update dependencies in frontend * refactor: remove CustomerCode check on alert creation dialog * refactor: update template * refactor: update template * refactor: lint * `chore: Update MINIO_ROOT_PASSWORD in .env.example` * feat: add incident overview cards * refactor: update style of incident overview cards * refactor: update labels of incident overview cards * precommit fixes --------- Co-authored-by: Davide Di Modica <webmaster.ddm@gmail.com>

taylor_socfortress committed Oct 1, 2024 at 13:06 UTC ec3fe390df6ad1f9804eaceb162a8833ffe97244
63 files changed +1439 -1185
.env.example
+1
@@ -8,6 +8,7 @@ MYSQL_PASSWORD=REPLACE_WITH_PASSWORD
8
9 MINIO_URL=copilot-minio
10 MINIO_ROOT_USER=admin
11 +# ! Make the password at least 8 characters long ! #
12 MINIO_ROOT_PASSWORD=REPLACE_ME
13 MINIO_SECURE=False
14
backend/app/integrations/monitoring_alert/schema/provision.py
+17 -15
@@ -6,7 +6,6 @@ from typing import Optional
6 from fastapi import HTTPException
7 from pydantic import BaseModel
8 from pydantic import Field
9 -from pydantic import root_validator
9 from pydantic import validator
10
11
@@ -254,17 +253,20 @@ class CustomMonitoringAlertProvisionModel(BaseModel):
253 example=300000,
254 )
255
257 - @root_validator
258 - def check_customer_code(cls, values):
259 - custom_fields = values.get("custom_fields")
260 - if custom_fields is None:
261 - raise HTTPException(
262 - status_code=400,
263 - detail="At least one custom field with name CUSTOMER_CODE is required",
264 - )
265 - if not any(field.name == "CUSTOMER_CODE" for field in custom_fields):
266 - raise HTTPException(
267 - status_code=400,
268 - detail="At least one custom field with name CUSTOMER_CODE is required",
269 - )
270 - return values
256 + # ! I think I can remove the requirement for the CUSTOMER_CODE field.
257 + # ! The new incident management doesnt require the CUSTOMER_CODE to be preset but
258 + # ! rather looks for valid CustomerCodeKeys(Enum) # !
259 + # @root_validator
260 + # def check_customer_code(cls, values):
261 + # custom_fields = values.get("custom_fields")
262 + # if custom_fields is None:
263 + # raise HTTPException(
264 + # status_code=400,
265 + # detail="At least one custom field with name CUSTOMER_CODE is required",
266 + # )
267 + # if not any(field.name == "CUSTOMER_CODE" for field in custom_fields):
268 + # raise HTTPException(
269 + # status_code=400,
270 + # detail="At least one custom field with name CUSTOMER_CODE is required",
271 + # )
272 + # return values
backend/copilot.py
+1 -1
@@ -83,7 +83,7 @@ load_dotenv()
83 server_ip = os.getenv("SERVER_IP", "localhost")
84 environment = os.getenv("ENVIRONMENT", "PRODUCTION")
85
86 -# Not needed for now
86 +# ! Not needed for now maybe revist later ! #
87 # ssl_keyfile = os.path.join(os.path.dirname(__file__), "../nginx/server.key")
88 # ssl_certfile = os.path.join(os.path.dirname(__file__), "../nginx/server.crt")
89
frontend/eslint.config.mjs
+2 -1
@@ -43,6 +43,7 @@ export default antfu({
43 "vue/html-self-closing": "off",
44 "vue/singleline-html-element-content-newline": "off",
45 "vue/comma-dangle": "off",
46 - "vue/quote-props": "off"
46 + "vue/quote-props": "off",
47 + "vue/one-component-per-file": "off"
48 }
49 })
frontend/index.html
+1 -4
@@ -5,10 +5,7 @@
5
6 <meta charset="UTF-8" />
7 <link rel="icon" href="/favicon.ico" />
8 - <meta
9 - name="viewport"
10 - content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height"
11 - />
8 + <meta name="viewport" content="initial-scale=1, minimum-scale=1, width=device-width, height=device-height" />
9 <meta name="mobile-web-app-capable" content="yes" />
10 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
11 <meta name="apple-mobile-web-app-title" content="SOCFortress CoPilot" />
frontend/package-lock.json
+420 -430
@@ -14,10 +14,10 @@
14 "@fontsource/lexend": "^5.1.0",
15 "@fontsource/public-sans": "^5.1.0",
16 "@popperjs/core": "^2.11.8",
17 - "@shikijs/markdown-it": "^1.18.0",
17 + "@shikijs/markdown-it": "^1.21.0",
18 "@vueuse/components": "^11.1.0",
19 "@vueuse/core": "^11.1.0",
20 - "apexcharts": "^3.53.0",
20 + "apexcharts": "^3.54.0",
21 "axios": "^1.7.7",
22 "bytes": "^3.1.2",
23 "colord": "^2.9.3",
@@ -31,14 +31,14 @@
31 "js-md5": "^0.8.3",
32 "lodash": "^4.17.21",
33 "mitt": "^3.0.1",
34 - "naive-ui": "^2.39.0",
34 + "naive-ui": "^2.40.1",
35 "password-validator": "^5.3.0",
36 - "pinia": "^2.2.2",
36 + "pinia": "^2.2.4",
37 "pinia-plugin-persistedstate": "^4.0.2",
38 "secure-ls": "^2.0.0",
39 - "shiki": "^1.18.0",
39 + "shiki": "^1.21.0",
40 "validator": "^13.12.0",
41 - "vue": "^3.5.8",
41 + "vue": "^3.5.10",
42 "vue-advanced-cropper": "^2.8.9",
43 "vue-highlight-words": "^3.0.1",
44 "vue-i18n": "^10.0.3",
@@ -49,7 +49,7 @@
49 "vuedraggable": "^4.1.0"
50 },
51 "devDependencies": {
52 - "@antfu/eslint-config": "^3.7.1",
52 + "@antfu/eslint-config": "^3.7.3",
53 "@clack/prompts": "^0.7.0",
54 "@iconify/vue": "^4.1.2",
55 "@tsconfig/node20": "^20.1.4",
@@ -58,16 +58,16 @@
58 "@types/fs-extra": "^11.0.4",
59 "@types/inquirer": "^9.0.7",
60 "@types/jsdom": "^21.1.7",
61 - "@types/lodash": "^4.17.7",
62 - "@types/node": "^22.5.5",
61 + "@types/lodash": "^4.17.9",
62 + "@types/node": "^22.7.4",
63 "@types/validator": "^13.12.2",
64 "@vitejs/plugin-vue": "^5.1.4",
65 "@vitejs/plugin-vue-jsx": "^4.0.1",
66 "@vue/test-utils": "^2.4.6",
67 "@vue/tsconfig": "^0.5.1",
68 "autoprefixer": "^10.4.20",
69 - "cypress": "^13.14.2",
70 - "eslint": "^9.11.0",
69 + "cypress": "^13.15.0",
70 + "eslint": "^9.11.1",
71 "flourite": "^1.3.0",
72 "fs-extra": "^11.2.0",
73 "globals": "^15.9.0",
@@ -77,18 +77,18 @@
77 "picocolors": "^1.1.0",
78 "postcss": "^8.4.47",
79 "prettier": "^3.3.3",
80 - "sass": "^1.79.3",
80 + "sass": "^1.79.4",
81 "start-server-and-test": "^2.0.8",
82 "tailwind-config-viewer": "^2.0.4",
83 - "tailwindcss": "^3.4.12",
84 - "taze": "^0.16.9",
83 + "tailwindcss": "^3.4.13",
84 + "taze": "^0.17.2",
85 "type-fest": "^4.26.1",
86 "typescript": "~5.5.4",
87 "unplugin-vue-components": "^0.27.4",
88 - "vite": "^5.4.7",
89 - "vite-bundle-analyzer": "^0.11.1",
88 + "vite": "^5.4.8",
89 + "vite-bundle-analyzer": "^0.12.1",
90 "vite-bundle-visualizer": "^1.2.1",
91 - "vite-plugin-vue-devtools": "^7.4.5",
91 + "vite-plugin-vue-devtools": "^7.4.6",
92 "vite-svg-loader": "^5.1.0",
93 "vitest": "^2.1.1",
94 "vue-tsc": "^2.1.6"
@@ -97,7 +97,7 @@
97 "node": ">=18.0.0"
98 },
99 "optionalDependencies": {
100 - "@rollup/rollup-linux-x64-gnu": "^4.22.4"
100 + "@rollup/rollup-linux-x64-gnu": "^4.23.0"
101 }
102 },
103 "node_modules/@ajoelp/json-to-formdata": {
@@ -133,9 +133,9 @@
133 }
134 },
135 "node_modules/@antfu/eslint-config": {
136 - "version": "3.7.1",
137 - "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-3.7.1.tgz",
138 - "integrity": "sha512-cDBAj+Le9XakAK83ZWVNxxyBJKeBfQ6H3VkUGnJPkXn/KJEzXC0fcHDtbu9k633hasLba5gXN5pjm4C70ik+Fg==",
136 + "version": "3.7.3",
137 + "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-3.7.3.tgz",
138 + "integrity": "sha512-vzhKtzQT+f/xBV8T5U8SFy3D7uAqL2CEcjsJVqtA7F8tdKvGuC/96uWeEKMHk5lRfijgj+xRvb+c4qQn60YlIA==",
139 "dev": true,
140 "dependencies": {
141 "@antfu/install-pkg": "^0.4.1",
@@ -143,20 +143,20 @@
143 "@eslint-community/eslint-plugin-eslint-comments": "^4.4.0",
144 "@eslint/markdown": "^6.1.0",
145 "@stylistic/eslint-plugin": "^2.8.0",
146 - "@typescript-eslint/eslint-plugin": "^8.6.0",
147 - "@typescript-eslint/parser": "^8.6.0",
146 + "@typescript-eslint/eslint-plugin": "^8.7.0",
147 + "@typescript-eslint/parser": "^8.7.0",
148 "@vitest/eslint-plugin": "^1.1.4",
149 "eslint-config-flat-gitignore": "^0.3.0",
150 "eslint-flat-config-utils": "^0.4.0",
151 "eslint-merge-processors": "^0.1.0",
152 "eslint-plugin-antfu": "^2.7.0",
153 - "eslint-plugin-command": "^0.2.5",
154 - "eslint-plugin-import-x": "^4.2.1",
155 - "eslint-plugin-jsdoc": "^50.2.4",
153 + "eslint-plugin-command": "^0.2.6",
154 + "eslint-plugin-import-x": "^4.3.0",
155 + "eslint-plugin-jsdoc": "^50.3.0",
156 "eslint-plugin-jsonc": "^2.16.0",
157 "eslint-plugin-n": "^17.10.3",
158 "eslint-plugin-no-only-tests": "^3.3.0",
159 - "eslint-plugin-perfectionist": "^3.6.0",
159 + "eslint-plugin-perfectionist": "^3.7.0",
160 "eslint-plugin-regexp": "^2.6.0",
161 "eslint-plugin-toml": "^0.11.1",
162 "eslint-plugin-unicorn": "^55.0.0",
@@ -687,17 +687,6 @@
687 "@babel/core": "^7.0.0-0"
688 }
689 },
690 - "node_modules/@babel/runtime": {
691 - "version": "7.25.6",
692 - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz",
693 - "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==",
694 - "dependencies": {
695 - "regenerator-runtime": "^0.14.0"
696 - },
697 - "engines": {
698 - "node": ">=6.9.0"
699 - }
700 - },
690 "node_modules/@babel/standalone": {
691 "version": "7.25.6",
692 "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.25.6.tgz",
@@ -784,7 +773,6 @@
773 },
774 "node_modules/@clack/prompts/node_modules/is-unicode-supported": {
775 "version": "1.3.0",
787 - "dev": true,
776 "inBundle": true,
777 "license": "MIT",
778 "engines": {
@@ -1365,6 +1353,14 @@
1353 "node": "*"
1354 }
1355 },
1356 + "node_modules/@eslint/core": {
1357 + "version": "0.6.0",
1358 + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz",
1359 + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==",
1360 + "engines": {
1361 + "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1362 + }
1363 + },
1364 "node_modules/@eslint/eslintrc": {
1365 "version": "3.1.0",
1366 "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz",
@@ -1427,20 +1423,18 @@
1423 }
1424 },
1425 "node_modules/@eslint/markdown": {
1430 - "version": "6.1.0",
1431 - "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.1.0.tgz",
1432 - "integrity": "sha512-cX1tyD+aIbhzKrCKe/9M5s2jZhldWGOR+cy7cIVpxG9RkoaN4XU+gG3dy6oEKtBFXjDx06GtP0OGO7jgbqa2DA==",
1426 + "version": "6.1.1",
1427 + "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-6.1.1.tgz",
1428 + "integrity": "sha512-Z+1js5AeqidwhNBbnIPM6Fn4eY9D5i1NleamS0UBW6BG0J4lpvhIVOKVIi22kmH5gvxDmHUp5MHkkkjda0TehA==",
1429 "dev": true,
1430 "dependencies": {
1431 + "@eslint/plugin-kit": "^0.2.0",
1432 "mdast-util-from-markdown": "^2.0.1",
1433 "mdast-util-gfm": "^3.0.0",
1434 "micromark-extension-gfm": "^3.0.0"
1435 },
1436 "engines": {
1437 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1441 - },
1442 - "peerDependencies": {
1443 - "eslint": ">=9"
1438 }
1439 },
1440 "node_modules/@eslint/object-schema": {
@@ -2181,9 +2175,9 @@
2175 }
2176 },
2177 "node_modules/@rollup/pluginutils": {
2184 - "version": "5.1.1",
2185 - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.1.tgz",
2186 - "integrity": "sha512-bVRmQqBIyGD+VMihdEV2IBurfIrdW9tD9yzJUL3CBRDbyPBVzQnBSMSgyUZHl1E335rpMRj7r4o683fXLYw8iw==",
2178 + "version": "5.1.2",
2179 + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz",
2180 + "integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==",
2181 "dependencies": {
2182 "@types/estree": "^1.0.0",
2183 "estree-walker": "^2.0.2",
@@ -2213,9 +2207,9 @@
2207 }
2208 },
2209 "node_modules/@rollup/rollup-android-arm-eabi": {
2216 - "version": "4.22.4",
2217 - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz",
2218 - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==",
2210 + "version": "4.22.5",
2211 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.5.tgz",
2212 + "integrity": "sha512-SU5cvamg0Eyu/F+kLeMXS7GoahL+OoizlclVFX3l5Ql6yNlywJJ0OuqTzUx0v+aHhPHEB/56CT06GQrRrGNYww==",
2213 "cpu": [
2214 "arm"
2215 ],
@@ -2226,9 +2220,9 @@
2220 ]
2221 },
2222 "node_modules/@rollup/rollup-android-arm64": {
2229 - "version": "4.22.4",
2230 - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz",
2231 - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==",
2223 + "version": "4.22.5",
2224 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.5.tgz",
2225 + "integrity": "sha512-S4pit5BP6E5R5C8S6tgU/drvgjtYW76FBuG6+ibG3tMvlD1h9LHVF9KmlmaUBQ8Obou7hEyS+0w+IR/VtxwNMQ==",
2226 "cpu": [
2227 "arm64"
2228 ],
@@ -2239,9 +2233,9 @@
2233 ]
2234 },
2235 "node_modules/@rollup/rollup-darwin-arm64": {
2242 - "version": "4.22.4",
2243 - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz",
2244 - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==",
2236 + "version": "4.22.5",
2237 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.5.tgz",
2238 + "integrity": "sha512-250ZGg4ipTL0TGvLlfACkIxS9+KLtIbn7BCZjsZj88zSg2Lvu3Xdw6dhAhfe/FjjXPVNCtcSp+WZjVsD3a/Zlw==",
2239 "cpu": [
2240 "arm64"
2241 ],
@@ -2252,9 +2246,9 @@
2246 ]
2247 },
2248 "node_modules/@rollup/rollup-darwin-x64": {
2255 - "version": "4.22.4",
2256 - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz",
2257 - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==",
2249 + "version": "4.22.5",
2250 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.5.tgz",
2251 + "integrity": "sha512-D8brJEFg5D+QxFcW6jYANu+Rr9SlKtTenmsX5hOSzNYVrK5oLAEMTUgKWYJP+wdKyCdeSwnapLsn+OVRFycuQg==",
2252 "cpu": [
2253 "x64"
2254 ],
@@ -2265,9 +2259,9 @@
2259 ]
2260 },
2261 "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
2268 - "version": "4.22.4",
2269 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz",
2270 - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==",
2262 + "version": "4.22.5",
2263 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.5.tgz",
2264 + "integrity": "sha512-PNqXYmdNFyWNg0ma5LdY8wP+eQfdvyaBAojAXgO7/gs0Q/6TQJVXAXe8gwW9URjbS0YAammur0fynYGiWsKlXw==",
2265 "cpu": [
2266 "arm"
2267 ],
@@ -2278,9 +2272,9 @@
2272 ]
2273 },
2274 "node_modules/@rollup/rollup-linux-arm-musleabihf": {
2281 - "version": "4.22.4",
2282 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz",
2283 - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==",
2275 + "version": "4.22.5",
2276 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.5.tgz",
2277 + "integrity": "sha512-kSSCZOKz3HqlrEuwKd9TYv7vxPYD77vHSUvM2y0YaTGnFc8AdI5TTQRrM1yIp3tXCKrSL9A7JLoILjtad5t8pQ==",
2278 "cpu": [
2279 "arm"
2280 ],
@@ -2291,9 +2285,9 @@
2285 ]
2286 },
2287 "node_modules/@rollup/rollup-linux-arm64-gnu": {
2294 - "version": "4.22.4",
2295 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz",
2296 - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==",
2288 + "version": "4.22.5",
2289 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.5.tgz",
2290 + "integrity": "sha512-oTXQeJHRbOnwRnRffb6bmqmUugz0glXaPyspp4gbQOPVApdpRrY/j7KP3lr7M8kTfQTyrBUzFjj5EuHAhqH4/w==",
2291 "cpu": [
2292 "arm64"
2293 ],
@@ -2304,9 +2298,9 @@
2298 ]
2299 },
2300 "node_modules/@rollup/rollup-linux-arm64-musl": {
2307 - "version": "4.22.4",
2308 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz",
2309 - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==",
2301 + "version": "4.22.5",
2302 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.5.tgz",
2303 + "integrity": "sha512-qnOTIIs6tIGFKCHdhYitgC2XQ2X25InIbZFor5wh+mALH84qnFHvc+vmWUpyX97B0hNvwNUL4B+MB8vJvH65Fw==",
2304 "cpu": [
2305 "arm64"
2306 ],
@@ -2317,9 +2311,9 @@
2311 ]
2312 },
2313 "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
2320 - "version": "4.22.4",
2321 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz",
2322 - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==",
2314 + "version": "4.22.5",
2315 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.5.tgz",
2316 + "integrity": "sha512-TMYu+DUdNlgBXING13rHSfUc3Ky5nLPbWs4bFnT+R6Vu3OvXkTkixvvBKk8uO4MT5Ab6lC3U7x8S8El2q5o56w==",
2317 "cpu": [
2318 "ppc64"
2319 ],
@@ -2330,9 +2324,9 @@
2324 ]
2325 },
2326 "node_modules/@rollup/rollup-linux-riscv64-gnu": {
2333 - "version": "4.22.4",
2334 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz",
2335 - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==",
2327 + "version": "4.22.5",
2328 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.5.tgz",
2329 + "integrity": "sha512-PTQq1Kz22ZRvuhr3uURH+U/Q/a0pbxJoICGSprNLAoBEkyD3Sh9qP5I0Asn0y0wejXQBbsVMRZRxlbGFD9OK4A==",
2330 "cpu": [
2331 "riscv64"
2332 ],
@@ -2343,9 +2337,9 @@
2337 ]
2338 },
2339 "node_modules/@rollup/rollup-linux-s390x-gnu": {
2346 - "version": "4.22.4",
2347 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz",
2348 - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==",
2340 + "version": "4.22.5",
2341 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.5.tgz",
2342 + "integrity": "sha512-bR5nCojtpuMss6TDEmf/jnBnzlo+6n1UhgwqUvRoe4VIotC7FG1IKkyJbwsT7JDsF2jxR+NTnuOwiGv0hLyDoQ==",
2343 "cpu": [
2344 "s390x"
2345 ],
@@ -2356,9 +2350,9 @@
2350 ]
2351 },
2352 "node_modules/@rollup/rollup-linux-x64-gnu": {
2359 - "version": "4.22.4",
2360 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz",
2361 - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==",
2353 + "version": "4.23.0",
2354 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.23.0.tgz",
2355 + "integrity": "sha512-I/eXsdVoCKtSgK9OwyQKPAfricWKUMNCwJKtatRYMmDo5N859tbO3UsBw5kT3dU1n6ZcM1JDzPRSGhAUkxfLxw==",
2356 "cpu": [
2357 "x64"
2358 ],
@@ -2368,9 +2362,9 @@
2362 ]
2363 },
2364 "node_modules/@rollup/rollup-linux-x64-musl": {
2371 - "version": "4.22.4",
2372 - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz",
2373 - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==",
2365 + "version": "4.22.5",
2366 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.5.tgz",
2367 + "integrity": "sha512-uBa2e28ohzNNwjr6Uxm4XyaA1M/8aTgfF2T7UIlElLaeXkgpmIJ2EitVNQxjO9xLLLy60YqAgKn/AqSpCUkE9g==",
2368 "cpu": [
2369 "x64"
2370 ],
@@ -2381,9 +2375,9 @@
2375 ]
2376 },
2377 "node_modules/@rollup/rollup-win32-arm64-msvc": {
2384 - "version": "4.22.4",
2385 - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz",
2386 - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==",
2378 + "version": "4.22.5",
2379 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.5.tgz",
2380 + "integrity": "sha512-RXT8S1HP8AFN/Kr3tg4fuYrNxZ/pZf1HemC5Tsddc6HzgGnJm0+Lh5rAHJkDuW3StI0ynNXukidROMXYl6ew8w==",
2381 "cpu": [
2382 "arm64"
2383 ],
@@ -2394,9 +2388,9 @@
2388 ]
2389 },
2390 "node_modules/@rollup/rollup-win32-ia32-msvc": {
2397 - "version": "4.22.4",
2398 - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz",
2399 - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==",
2391 + "version": "4.22.5",
2392 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.5.tgz",
2393 + "integrity": "sha512-ElTYOh50InL8kzyUD6XsnPit7jYCKrphmddKAe1/Ytt74apOxDq5YEcbsiKs0fR3vff3jEneMM+3I7jbqaMyBg==",
2394 "cpu": [
2395 "ia32"
2396 ],
@@ -2407,9 +2401,9 @@
2401 ]
2402 },
2403 "node_modules/@rollup/rollup-win32-x64-msvc": {
2410 - "version": "4.22.4",
2411 - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz",
2412 - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==",
2404 + "version": "4.22.5",
2405 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.5.tgz",
2406 + "integrity": "sha512-+lvL/4mQxSV8MukpkKyyvfwhH266COcWlXE/1qxwN08ajovta3459zrjLghYMgDerlzNwLAcFpvU+WWE5y6nAQ==",
2407 "cpu": [
2408 "x64"
2409 ],
@@ -2420,50 +2414,50 @@
2414 ]
2415 },
2416 "node_modules/@shikijs/core": {
2423 - "version": "1.18.0",
2424 - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.18.0.tgz",
2425 - "integrity": "sha512-VK4BNVCd2leY62Nm2JjyxtRLkyrZT/tv104O81eyaCjHq4Adceq2uJVFJJAIof6lT1mBwZrEo2qT/T+grv3MQQ==",
2417 + "version": "1.21.0",
2418 + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.21.0.tgz",
2419 + "integrity": "sha512-zAPMJdiGuqXpZQ+pWNezQAk5xhzRXBNiECFPcJLtUdsFM3f//G95Z15EHTnHchYycU8kIIysqGgxp8OVSj1SPQ==",
2420 "dependencies": {
2427 - "@shikijs/engine-javascript": "1.18.0",
2428 - "@shikijs/engine-oniguruma": "1.18.0",
2429 - "@shikijs/types": "1.18.0",
2421 + "@shikijs/engine-javascript": "1.21.0",
2422 + "@shikijs/engine-oniguruma": "1.21.0",
2423 + "@shikijs/types": "1.21.0",
2424 "@shikijs/vscode-textmate": "^9.2.2",
2425 "@types/hast": "^3.0.4",
2426 "hast-util-to-html": "^9.0.3"
2427 }
2428 },
2429 "node_modules/@shikijs/engine-javascript": {
2436 - "version": "1.18.0",
2437 - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.18.0.tgz",
2438 - "integrity": "sha512-qoP/aO/ATNwYAUw1YMdaip/YVEstMZEgrwhePm83Ll9OeQPuxDZd48szZR8oSQNQBT8m8UlWxZv8EA3lFuyI5A==",
2430 + "version": "1.21.0",
2431 + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.21.0.tgz",
2432 + "integrity": "sha512-jxQHNtVP17edFW4/0vICqAVLDAxmyV31MQJL4U/Kg+heQALeKYVOWo0sMmEZ18FqBt+9UCdyqGKYE7bLRtk9mg==",
2433 "dependencies": {
2440 - "@shikijs/types": "1.18.0",
2434 + "@shikijs/types": "1.21.0",
2435 "@shikijs/vscode-textmate": "^9.2.2",
2436 "oniguruma-to-js": "0.4.3"
2437 }
2438 },
2439 "node_modules/@shikijs/engine-oniguruma": {
2446 - "version": "1.18.0",
2447 - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.18.0.tgz",
2448 - "integrity": "sha512-B9u0ZKI/cud+TcmF8Chyh+R4V5qQVvyDOqXC2l2a4x73PBSBc6sZ0JRAX3eqyJswqir6ktwApUUGBYePdKnMJg==",
2440 + "version": "1.21.0",
2441 + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.21.0.tgz",
2442 + "integrity": "sha512-AIZ76XocENCrtYzVU7S4GY/HL+tgHGbVU+qhiDyNw1qgCA5OSi4B4+HY4BtAoJSMGuD/L5hfTzoRVbzEm2WTvg==",
2443 "dependencies": {
2450 - "@shikijs/types": "1.18.0",
2444 + "@shikijs/types": "1.21.0",
2445 "@shikijs/vscode-textmate": "^9.2.2"
2446 }
2447 },
2448 "node_modules/@shikijs/markdown-it": {
2455 - "version": "1.18.0",
2456 - "resolved": "https://registry.npmjs.org/@shikijs/markdown-it/-/markdown-it-1.18.0.tgz",
2457 - "integrity": "sha512-acU44AAYYk7cESJbpEmcmLP5KJzuIUBzuCHcVd4glJPRK1UYc7Pqfg/chKv0DFYsC0u5BdFT15Od959tPA3xJQ==",
2449 + "version": "1.21.0",
2450 + "resolved": "https://registry.npmjs.org/@shikijs/markdown-it/-/markdown-it-1.21.0.tgz",
2451 + "integrity": "sha512-wNvze11LNnhNc3NpGG7Y2Jxlecta85bd1QRltB+oqtug4w63BtjzTQubpB3NWwXTWXf91iVlmbo8Sp9mrmZVGQ==",
2452 "dependencies": {
2453 "markdown-it": "^14.1.0",
2460 - "shiki": "1.18.0"
2454 + "shiki": "1.21.0"
2455 }
2456 },
2457 "node_modules/@shikijs/types": {
2464 - "version": "1.18.0",
2465 - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.18.0.tgz",
2466 - "integrity": "sha512-O9N36UEaGGrxv1yUrN2nye7gDLG5Uq0/c1LyfmxsvzNPqlHzWo9DI0A4+fhW2y3bGKuQu/fwS7EPdKJJCowcVA==",
2458 + "version": "1.21.0",
2459 + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.21.0.tgz",
2460 + "integrity": "sha512-tzndANDhi5DUndBtpojEq/42+dpUF2wS7wdCDQaFtIXm3Rd1QkrcVgSSRLOvEwexekihOXfbYJINW37g96tJRw==",
2461 "dependencies": {
2462 "@shikijs/vscode-textmate": "^9.2.2",
2463 "@types/hast": "^3.0.4"
@@ -2625,9 +2619,9 @@
2619 "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ=="
2620 },
2621 "node_modules/@types/lodash": {
2628 - "version": "4.17.7",
2629 - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz",
2630 - "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA=="
2622 + "version": "4.17.9",
2623 + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.9.tgz",
2624 + "integrity": "sha512-w9iWudx1XWOHW5lQRS9iKpK/XuRhnN+0T7HvdCCd802FYkT1AMTnxndJHGrNJwRoRHkslGr4S29tjm1cT7x/7w=="
2625 },
2626 "node_modules/@types/lodash-es": {
2627 "version": "4.17.12",
@@ -2652,9 +2646,9 @@
2646 "dev": true
2647 },
2648 "node_modules/@types/node": {
2655 - "version": "22.5.5",
2656 - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz",
2657 - "integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==",
2649 + "version": "22.7.4",
2650 + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz",
2651 + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==",
2652 "dev": true,
2653 "dependencies": {
2654 "undici-types": "~6.19.2"
@@ -2725,16 +2719,16 @@
2719 }
2720 },
2721 "node_modules/@typescript-eslint/eslint-plugin": {
2728 - "version": "8.6.0",
2729 - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz",
2730 - "integrity": "sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==",
2722 + "version": "8.7.0",
2723 + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz",
2724 + "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==",
2725 "dev": true,
2726 "dependencies": {
2727 "@eslint-community/regexpp": "^4.10.0",
2734 - "@typescript-eslint/scope-manager": "8.6.0",
2735 - "@typescript-eslint/type-utils": "8.6.0",
2736 - "@typescript-eslint/utils": "8.6.0",
2737 - "@typescript-eslint/visitor-keys": "8.6.0",
2728 + "@typescript-eslint/scope-manager": "8.7.0",
2729 + "@typescript-eslint/type-utils": "8.7.0",
2730 + "@typescript-eslint/utils": "8.7.0",
2731 + "@typescript-eslint/visitor-keys": "8.7.0",
2732 "graphemer": "^1.4.0",
2733 "ignore": "^5.3.1",
2734 "natural-compare": "^1.4.0",
@@ -2758,15 +2752,15 @@
2752 }
2753 },
2754 "node_modules/@typescript-eslint/parser": {
2761 - "version": "8.6.0",
2762 - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.6.0.tgz",
2763 - "integrity": "sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==",
2755 + "version": "8.7.0",
2756 + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz",
2757 + "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==",
2758 "dev": true,
2759 "dependencies": {
2766 - "@typescript-eslint/scope-manager": "8.6.0",
2767 - "@typescript-eslint/types": "8.6.0",
2768 - "@typescript-eslint/typescript-estree": "8.6.0",
2769 - "@typescript-eslint/visitor-keys": "8.6.0",
2760 + "@typescript-eslint/scope-manager": "8.7.0",
2761 + "@typescript-eslint/types": "8.7.0",
2762 + "@typescript-eslint/typescript-estree": "8.7.0",
2763 + "@typescript-eslint/visitor-keys": "8.7.0",
2764 "debug": "^4.3.4"
2765 },
2766 "engines": {
@@ -2786,13 +2780,13 @@
2780 }
2781 },
2782 "node_modules/@typescript-eslint/scope-manager": {
2789 - "version": "8.6.0",
2790 - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz",
2791 - "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==",
2783 + "version": "8.7.0",
2784 + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz",
2785 + "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==",
2786 "dev": true,
2787 "dependencies": {
2794 - "@typescript-eslint/types": "8.6.0",
2795 - "@typescript-eslint/visitor-keys": "8.6.0"
2788 + "@typescript-eslint/types": "8.7.0",
2789 + "@typescript-eslint/visitor-keys": "8.7.0"
2790 },
2791 "engines": {
2792 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2803,13 +2797,13 @@
2797 }
2798 },
2799 "node_modules/@typescript-eslint/type-utils": {
2806 - "version": "8.6.0",
2807 - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz",
2808 - "integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==",
2800 + "version": "8.7.0",
2801 + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz",
2802 + "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==",
2803 "dev": true,
2804 "dependencies": {
2811 - "@typescript-eslint/typescript-estree": "8.6.0",
2812 - "@typescript-eslint/utils": "8.6.0",
2805 + "@typescript-eslint/typescript-estree": "8.7.0",
2806 + "@typescript-eslint/utils": "8.7.0",
2807 "debug": "^4.3.4",
2808 "ts-api-utils": "^1.3.0"
2809 },
@@ -2827,9 +2821,9 @@
2821 }
2822 },
2823 "node_modules/@typescript-eslint/types": {
2830 - "version": "8.6.0",
2831 - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz",
2832 - "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==",
2824 + "version": "8.7.0",
2825 + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz",
2826 + "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==",
2827 "dev": true,
2828 "engines": {
2829 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2840,13 +2834,13 @@
2834 }
2835 },
2836 "node_modules/@typescript-eslint/typescript-estree": {
2843 - "version": "8.6.0",
2844 - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz",
2845 - "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==",
2837 + "version": "8.7.0",
2838 + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz",
2839 + "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==",
2840 "dev": true,
2841 "dependencies": {
2848 - "@typescript-eslint/types": "8.6.0",
2849 - "@typescript-eslint/visitor-keys": "8.6.0",
2842 + "@typescript-eslint/types": "8.7.0",
2843 + "@typescript-eslint/visitor-keys": "8.7.0",
2844 "debug": "^4.3.4",
2845 "fast-glob": "^3.3.2",
2846 "is-glob": "^4.0.3",
@@ -2868,15 +2862,15 @@
2862 }
2863 },
2864 "node_modules/@typescript-eslint/utils": {
2871 - "version": "8.6.0",
2872 - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz",
2873 - "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==",
2865 + "version": "8.7.0",
2866 + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz",
2867 + "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==",
2868 "dev": true,
2869 "dependencies": {
2870 "@eslint-community/eslint-utils": "^4.4.0",
2877 - "@typescript-eslint/scope-manager": "8.6.0",
2878 - "@typescript-eslint/types": "8.6.0",
2879 - "@typescript-eslint/typescript-estree": "8.6.0"
2871 + "@typescript-eslint/scope-manager": "8.7.0",
2872 + "@typescript-eslint/types": "8.7.0",
2873 + "@typescript-eslint/typescript-estree": "8.7.0"
2874 },
2875 "engines": {
2876 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2890,12 +2884,12 @@
2884 }
2885 },
2886 "node_modules/@typescript-eslint/visitor-keys": {
2893 - "version": "8.6.0",
2894 - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz",
2895 - "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==",
2887 + "version": "8.7.0",
2888 + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz",
2889 + "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==",
2890 "dev": true,
2891 "dependencies": {
2898 - "@typescript-eslint/types": "8.6.0",
2892 + "@typescript-eslint/types": "8.7.0",
2893 "eslint-visitor-keys": "^3.4.3"
2894 },
2895 "engines": {
@@ -3648,36 +3642,36 @@
3642 }
3643 },
3644 "node_modules/@vue/compiler-core": {
3651 - "version": "3.5.8",
3652 - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.8.tgz",
3653 - "integrity": "sha512-Uzlxp91EPjfbpeO5KtC0KnXPkuTfGsNDeaKQJxQN718uz+RqDYarEf7UhQJGK+ZYloD2taUbHTI2J4WrUaZQNA==",
3645 + "version": "3.5.10",
3646 + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.10.tgz",
3647 + "integrity": "sha512-iXWlk+Cg/ag7gLvY0SfVucU8Kh2CjysYZjhhP70w9qI4MvSox4frrP+vDGvtQuzIcgD8+sxM6lZvCtdxGunTAA==",
3648 "dependencies": {
3649 "@babel/parser": "^7.25.3",
3656 - "@vue/shared": "3.5.8",
3650 + "@vue/shared": "3.5.10",
3651 "entities": "^4.5.0",
3652 "estree-walker": "^2.0.2",
3653 "source-map-js": "^1.2.0"
3654 }
3655 },
3656 "node_modules/@vue/compiler-dom": {
3663 - "version": "3.5.8",
3664 - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.8.tgz",
3665 - "integrity": "sha512-GUNHWvoDSbSa5ZSHT9SnV5WkStWfzJwwTd6NMGzilOE/HM5j+9EB9zGXdtu/fCNEmctBqMs6C9SvVPpVPuk1Eg==",
3657 + "version": "3.5.10",
3658 + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.10.tgz",
3659 + "integrity": "sha512-DyxHC6qPcktwYGKOIy3XqnHRrrXyWR2u91AjP+nLkADko380srsC2DC3s7Y1Rk6YfOlxOlvEQKa9XXmLI+W4ZA==",
3660 "dependencies": {
3667 - "@vue/compiler-core": "3.5.8",
3668 - "@vue/shared": "3.5.8"
3661 + "@vue/compiler-core": "3.5.10",
3662 + "@vue/shared": "3.5.10"
3663 }
3664 },
3665 "node_modules/@vue/compiler-sfc": {
3672 - "version": "3.5.8",
3673 - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.8.tgz",
3674 - "integrity": "sha512-taYpngQtSysrvO9GULaOSwcG5q821zCoIQBtQQSx7Uf7DxpR6CIHR90toPr9QfDD2mqHQPCSgoWBvJu0yV9zjg==",
3666 + "version": "3.5.10",
3667 + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.10.tgz",
3668 + "integrity": "sha512-to8E1BgpakV7224ZCm8gz1ZRSyjNCAWEplwFMWKlzCdP9DkMKhRRwt0WkCjY7jkzi/Vz3xgbpeig5Pnbly4Tow==",
3669 "dependencies": {
3670 "@babel/parser": "^7.25.3",
3677 - "@vue/compiler-core": "3.5.8",
3678 - "@vue/compiler-dom": "3.5.8",
3679 - "@vue/compiler-ssr": "3.5.8",
3680 - "@vue/shared": "3.5.8",
3671 + "@vue/compiler-core": "3.5.10",
3672 + "@vue/compiler-dom": "3.5.10",
3673 + "@vue/compiler-ssr": "3.5.10",
3674 + "@vue/shared": "3.5.10",
3675 "estree-walker": "^2.0.2",
3676 "magic-string": "^0.30.11",
3677 "postcss": "^8.4.47",
@@ -3685,12 +3679,12 @@
3679 }
3680 },
3681 "node_modules/@vue/compiler-ssr": {
3688 - "version": "3.5.8",
3689 - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.8.tgz",
3690 - "integrity": "sha512-W96PtryNsNG9u0ZnN5Q5j27Z/feGrFV6zy9q5tzJVyJaLiwYxvC0ek4IXClZygyhjm+XKM7WD9pdKi/wIRVC/Q==",
3682 + "version": "3.5.10",
3683 + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.10.tgz",
3684 + "integrity": "sha512-hxP4Y3KImqdtyUKXDRSxKSRkSm1H9fCvhojEYrnaoWhE4w/y8vwWhnosJoPPe2AXm5sU7CSbYYAgkt2ZPhDz+A==",
3685 "dependencies": {
3692 - "@vue/compiler-dom": "3.5.8",
3693 - "@vue/shared": "3.5.8"
3686 + "@vue/compiler-dom": "3.5.10",
3687 + "@vue/shared": "3.5.10"
3688 }
3689 },
3690 "node_modules/@vue/compiler-vue2": {
@@ -3709,13 +3703,13 @@
3703 "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
3704 },
3705 "node_modules/@vue/devtools-core": {
3712 - "version": "7.4.5",
3713 - "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-7.4.5.tgz",
3714 - "integrity": "sha512-QwrgKYxwafJUJrKRvJGbzQLuGt0BC1P4qTr4qlEKgOOs+GV0n6zTry2oeHiwmj5H6pOkLoHnwFMOTB9rFtn9QQ==",
3706 + "version": "7.4.6",
3707 + "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-7.4.6.tgz",
3708 + "integrity": "sha512-7ATNPEbVqThOOAp2bg/YUIm9MqqgimbSk24D05hdXUp89JlXX12aTzdrWd9xZRwS78hDR+wCToHl1C/8sopBrg==",
3709 "dev": true,
3710 "dependencies": {
3717 - "@vue/devtools-kit": "^7.4.5",
3718 - "@vue/devtools-shared": "^7.4.5",
3711 + "@vue/devtools-kit": "^7.4.6",
3712 + "@vue/devtools-shared": "^7.4.6",
3713 "mitt": "^3.0.1",
3714 "nanoid": "^3.3.4",
3715 "pathe": "^1.1.2",
@@ -3726,12 +3720,12 @@
3720 }
3721 },
3722 "node_modules/@vue/devtools-kit": {
3729 - "version": "7.4.5",
3730 - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.4.5.tgz",
3731 - "integrity": "sha512-Uuki4Z6Bc/ExvtlPkeDNGSAe4580R+HPcVABfTE9TF7BTz3Nntk7vxIRUyWblZkUEcB/x+wn2uofyt5i2LaUew==",
3723 + "version": "7.4.6",
3724 + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.4.6.tgz",
3725 + "integrity": "sha512-NbYBwPWgEic1AOd9bWExz9weBzFdjiIfov0yRn4DrRfR+EQJCI9dn4I0XS7IxYGdkmUJi8mFW42LLk18WsGqew==",
3726 "dev": true,
3727 "dependencies": {
3734 - "@vue/devtools-shared": "^7.4.5",
3728 + "@vue/devtools-shared": "^7.4.6",
3729 "birpc": "^0.2.17",
3730 "hookable": "^5.5.3",
3731 "mitt": "^3.0.1",
@@ -3741,9 +3735,9 @@
3735 }
3736 },
3737 "node_modules/@vue/devtools-shared": {
3744 - "version": "7.4.5",
3745 - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.4.5.tgz",
3746 - "integrity": "sha512-2XgUOkL/7QDmyYI9J7cm+rz/qBhcGv+W5+i1fhwdQ0HQ1RowhdK66F0QBuJSz/5k12opJY8eN6m03/XZMs7imQ==",
3738 + "version": "7.4.6",
3739 + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.4.6.tgz",
3740 + "integrity": "sha512-rPeSBzElnHYMB05Cc056BQiJpgocQjY8XVulgni+O9a9Gr9tNXgPteSzFFD+fT/iWMxNuUgGKs9CuW5DZewfIg==",
3741 "dev": true,
3742 "dependencies": {
3743 "rfdc": "^1.4.1"
@@ -3774,49 +3768,49 @@
3768 }
3769 },
3770 "node_modules/@vue/reactivity": {
3777 - "version": "3.5.8",
3778 - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.8.tgz",
3779 - "integrity": "sha512-mlgUyFHLCUZcAYkqvzYnlBRCh0t5ZQfLYit7nukn1GR96gc48Bp4B7OIcSfVSvlG1k3BPfD+p22gi1t2n9tsXg==",
3771 + "version": "3.5.10",
3772 + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.10.tgz",
3773 + "integrity": "sha512-kW08v06F6xPSHhid9DJ9YjOGmwNDOsJJQk0ax21wKaUYzzuJGEuoKNU2Ujux8FLMrP7CFJJKsHhXN9l2WOVi2g==",
3774 "dependencies": {
3781 - "@vue/shared": "3.5.8"
3775 + "@vue/shared": "3.5.10"
3776 }
3777 },
3778 "node_modules/@vue/runtime-core": {
3785 - "version": "3.5.8",
3786 - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.8.tgz",
3787 - "integrity": "sha512-fJuPelh64agZ8vKkZgp5iCkPaEqFJsYzxLk9vSC0X3G8ppknclNDr61gDc45yBGTaN5Xqc1qZWU3/NoaBMHcjQ==",
3779 + "version": "3.5.10",
3780 + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.10.tgz",
3781 + "integrity": "sha512-9Q86I5Qq3swSkFfzrZ+iqEy7Vla325M7S7xc1NwKnRm/qoi1Dauz0rT6mTMmscqx4qz0EDJ1wjB+A36k7rl8mA==",
3782 "dependencies": {
3789 - "@vue/reactivity": "3.5.8",
3790 - "@vue/shared": "3.5.8"
3783 + "@vue/reactivity": "3.5.10",
3784 + "@vue/shared": "3.5.10"
3785 }
3786 },
3787 "node_modules/@vue/runtime-dom": {
3794 - "version": "3.5.8",
3795 - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.8.tgz",
3796 - "integrity": "sha512-DpAUz+PKjTZPUOB6zJgkxVI3GuYc2iWZiNeeHQUw53kdrparSTG6HeXUrYDjaam8dVsCdvQxDz6ZWxnyjccUjQ==",
3788 + "version": "3.5.10",
3789 + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.10.tgz",
3790 + "integrity": "sha512-t3x7ht5qF8ZRi1H4fZqFzyY2j+GTMTDxRheT+i8M9Ph0oepUxoadmbwlFwMoW7RYCpNQLpP2Yx3feKs+fyBdpA==",
3791 "dependencies": {
3798 - "@vue/reactivity": "3.5.8",
3799 - "@vue/runtime-core": "3.5.8",
3800 - "@vue/shared": "3.5.8",
3792 + "@vue/reactivity": "3.5.10",
3793 + "@vue/runtime-core": "3.5.10",
3794 + "@vue/shared": "3.5.10",
3795 "csstype": "^3.1.3"
3796 }
3797 },
3798 "node_modules/@vue/server-renderer": {
3805 - "version": "3.5.8",
3806 - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.8.tgz",
3807 - "integrity": "sha512-7AmC9/mEeV9mmXNVyUIm1a1AjUhyeeGNbkLh39J00E7iPeGks8OGRB5blJiMmvqSh8SkaS7jkLWSpXtxUCeagA==",
3799 + "version": "3.5.10",
3800 + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.10.tgz",
3801 + "integrity": "sha512-IVE97tt2kGKwHNq9yVO0xdh1IvYfZCShvDSy46JIh5OQxP1/EXSpoDqetVmyIzL7CYOWnnmMkVqd7YK2QSWkdw==",
3802 "dependencies": {
3809 - "@vue/compiler-ssr": "3.5.8",
3810 - "@vue/shared": "3.5.8"
3803 + "@vue/compiler-ssr": "3.5.10",
3804 + "@vue/shared": "3.5.10"
3805 },
3806 "peerDependencies": {
3813 - "vue": "3.5.8"
3807 + "vue": "3.5.10"
3808 }
3809 },
3810 "node_modules/@vue/shared": {
3817 - "version": "3.5.8",
3818 - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.8.tgz",
3819 - "integrity": "sha512-mJleSWbAGySd2RJdX1RBtcrUBX6snyOc0qHpgk3lGi4l9/P/3ny3ELqFWqYdkXIwwNN/kdm8nD9ky8o6l/Lx2A=="
3811 + "version": "3.5.10",
3812 + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.10.tgz",
3813 + "integrity": "sha512-VkkBhU97Ki+XJ0xvl4C9YJsIZ2uIlQ7HqPpZOS3m9VCvmROPaChZU6DexdMJqvz9tbgG+4EtFVrSuailUq5KGQ=="
3814 },
3815 "node_modules/@vue/test-utils": {
3816 "version": "2.4.6",
@@ -4123,9 +4117,9 @@
4117 }
4118 },
4119 "node_modules/apexcharts": {
4126 - "version": "3.53.0",
4127 - "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.53.0.tgz",
4128 - "integrity": "sha512-QESZHZY3w9LPQ64PGh1gEdfjYjJ5Jp+Dfy0D/CLjsLOPTpXzdxwlNMqRj+vPbTcP0nAHgjWv1maDqcEq6u5olw==",
4120 + "version": "3.54.0",
4121 + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.54.0.tgz",
4122 + "integrity": "sha512-ZgI/seScffjLpwNRX/gAhIkAhpCNWiTNsdICv7qxnF0xisI23XSsaENUKIcMlyP1rbe8ECgvybDnp7plZld89A==",
4123 "dependencies": {
4124 "@yr/monotone-cubic-spline": "^1.0.3",
4125 "svg.draggable.js": "^2.2.2",
@@ -4398,9 +4392,9 @@
4392 }
4393 },
4394 "node_modules/browserslist": {
4401 - "version": "4.23.3",
4402 - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz",
4403 - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==",
4395 + "version": "4.24.0",
4396 + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
4397 + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==",
4398 "funding": [
4399 {
4400 "type": "opencollective",
@@ -4416,8 +4410,8 @@
4410 }
4411 ],
4412 "dependencies": {
4419 - "caniuse-lite": "^1.0.30001646",
4420 - "electron-to-chromium": "^1.5.4",
4413 + "caniuse-lite": "^1.0.30001663",
4414 + "electron-to-chromium": "^1.5.28",
4415 "node-releases": "^2.0.18",
4416 "update-browserslist-db": "^1.1.0"
4417 },
@@ -4606,9 +4600,9 @@
4600 }
4601 },
4602 "node_modules/caniuse-lite": {
4609 - "version": "1.0.30001663",
4610 - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz",
4611 - "integrity": "sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==",
4603 + "version": "1.0.30001664",
4604 + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz",
4605 + "integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==",
4606 "funding": [
4607 {
4608 "type": "opencollective",
@@ -5263,13 +5257,13 @@
5257 "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
5258 },
5259 "node_modules/cypress": {
5266 - "version": "13.14.2",
5267 - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.14.2.tgz",
5268 - "integrity": "sha512-lsiQrN17vHMB2fnvxIrKLAjOr9bPwsNbPZNrWf99s4u+DVmCY6U+w7O3GGG9FvP4EUVYaDu+guWeNLiUzBrqvA==",
5260 + "version": "13.15.0",
5261 + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.15.0.tgz",
5262 + "integrity": "sha512-53aO7PwOfi604qzOkCSzNlWquCynLlKE/rmmpSPcziRH6LNfaDUAklQT6WJIsD8ywxlIy+uVZsnTMCCQVd2kTw==",
5263 "dev": true,
5264 "hasInstallScript": true,
5265 "dependencies": {
5272 - "@cypress/request": "^3.0.1",
5266 + "@cypress/request": "^3.0.4",
5267 "@cypress/xvfb": "^1.2.4",
5268 "@types/sinonjs__fake-timers": "8.1.1",
5269 "@types/sizzle": "^2.3.2",
@@ -5451,26 +5445,20 @@
5445 }
5446 },
5447 "node_modules/date-fns": {
5454 - "version": "2.30.0",
5455 - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
5456 - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
5457 - "dependencies": {
5458 - "@babel/runtime": "^7.21.0"
5459 - },
5460 - "engines": {
5461 - "node": ">=0.11"
5462 - },
5448 + "version": "3.6.0",
5449 + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
5450 + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
5451 "funding": {
5464 - "type": "opencollective",
5465 - "url": "https://opencollective.com/date-fns"
5452 + "type": "github",
5453 + "url": "https://github.com/sponsors/kossnocorp"
5454 }
5455 },
5456 "node_modules/date-fns-tz": {
5469 - "version": "2.0.1",
5470 - "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.1.tgz",
5471 - "integrity": "sha512-fJCG3Pwx8HUoLhkepdsP7Z5RsucUi+ZBOxyM5d0ZZ6c4SdYustq0VMmOu6Wf7bli+yS/Jwp91TOCqn9jMcVrUA==",
5457 + "version": "3.2.0",
5458 + "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.2.0.tgz",
5459 + "integrity": "sha512-sg8HqoTEulcbbbVXeg84u5UnlsQa8GS5QXMqjjYIhS4abEVVKIUwe0/l/UhrZdKaL/W5eWZNlbTeEIiOXTcsBQ==",
5460 "peerDependencies": {
5473 - "date-fns": "2.x"
5461 + "date-fns": "^3.0.0 || ^4.0.0"
5462 }
5463 },
5464 "node_modules/dayjs": {
@@ -5864,9 +5852,9 @@
5852 "dev": true
5853 },
5854 "node_modules/electron-to-chromium": {
5867 - "version": "1.5.27",
5868 - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz",
5869 - "integrity": "sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw=="
5855 + "version": "1.5.29",
5856 + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz",
5857 + "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw=="
5858 },
5859 "node_modules/emoji-regex": {
5860 "version": "8.0.0",
@@ -6038,19 +6026,22 @@
6026 }
6027 },
6028 "node_modules/eslint": {
6041 - "version": "9.11.0",
6042 - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.0.tgz",
6043 - "integrity": "sha512-yVS6XODx+tMFMDFcG4+Hlh+qG7RM6cCJXtQhCKLSsr3XkLvWggHjCqjfh0XsPPnt1c56oaT6PMgW9XWQQjdHXA==",
6029 + "version": "9.11.1",
6030 + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.1.tgz",
6031 + "integrity": "sha512-MobhYKIoAO1s1e4VUrgx1l1Sk2JBR/Gqjjgw8+mfgoLE2xwsHur4gdfTxyTgShrhvdVFTaJSgMiQBl1jv/AWxg==",
6032 "dependencies": {
6033 "@eslint-community/eslint-utils": "^4.2.0",
6034 "@eslint-community/regexpp": "^4.11.0",
6035 "@eslint/config-array": "^0.18.0",
6036 + "@eslint/core": "^0.6.0",
6037 "@eslint/eslintrc": "^3.1.0",
6049 - "@eslint/js": "9.11.0",
6038 + "@eslint/js": "9.11.1",
6039 "@eslint/plugin-kit": "^0.2.0",
6040 "@humanwhocodes/module-importer": "^1.0.1",
6041 "@humanwhocodes/retry": "^0.3.0",
6042 "@nodelib/fs.walk": "^1.2.8",
6043 + "@types/estree": "^1.0.6",
6044 + "@types/json-schema": "^7.0.15",
6045 "ajv": "^6.12.4",
6046 "chalk": "^4.0.0",
6047 "cross-spawn": "^7.0.2",
@@ -6217,9 +6208,9 @@
6208 }
6209 },
6210 "node_modules/eslint-plugin-command": {
6220 - "version": "0.2.5",
6221 - "resolved": "https://registry.npmjs.org/eslint-plugin-command/-/eslint-plugin-command-0.2.5.tgz",
6222 - "integrity": "sha512-mbCaSHD37MT8nVJnJUz2oeDfhz0wdOjfrqQVWkSpXuj3uU8m7/FK/niV2bL922af3M1js5x7Xcu3PwqWsrahfA==",
6211 + "version": "0.2.6",
6212 + "resolved": "https://registry.npmjs.org/eslint-plugin-command/-/eslint-plugin-command-0.2.6.tgz",
6213 + "integrity": "sha512-T0bHZ1oblW1xUHUVoBKZJR2osSNNGkfZuK4iqboNwuNS/M7tdp3pmURaJtTi/XDzitxaQ02lvOdFH0mUd5QLvQ==",
6214 "dev": true,
6215 "dependencies": {
6216 "@es-joy/jsdoccomment": "^0.48.0"
@@ -6253,9 +6244,9 @@
6244 }
6245 },
6246 "node_modules/eslint-plugin-import-x": {
6256 - "version": "4.3.0",
6257 - "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.3.0.tgz",
6258 - "integrity": "sha512-PxGzP7gAjF2DLeRnQtbYkkgZDg1intFyYr/XS1LgTYXUDrSXMHGkXx8++6i2eDv2jMs0jfeO6G6ykyeWxiFX7w==",
6247 + "version": "4.3.1",
6248 + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.3.1.tgz",
6249 + "integrity": "sha512-5TriWkXulDl486XnYYRgsL+VQoS/7mhN/2ci02iLCuL7gdhbiWxnsuL/NTcaKY9fpMgsMFjWZBtIGW7pb+RX0g==",
6250 "dev": true,
6251 "dependencies": {
6252 "@typescript-eslint/utils": "^8.1.0",
@@ -6283,9 +6274,9 @@
6274 "dev": true
6275 },
6276 "node_modules/eslint-plugin-jsdoc": {
6286 - "version": "50.2.4",
6287 - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.2.4.tgz",
6288 - "integrity": "sha512-020jA+dXaXdb+TML3ZJBvpPmzwbNROjnYuTYi/g6A5QEmEjhptz4oPJDKkOGMIByNxsPpdTLzSU1HYVqebOX1w==",
6277 + "version": "50.3.0",
6278 + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.0.tgz",
6279 + "integrity": "sha512-P7qDB/RckdKETpBM4CtjHRQ5qXByPmFhRi86sN3E+J+tySchq+RSOGGhI2hDIefmmKFuTi/1ACjqsnDJDDDfzg==",
6280 "dev": true,
6281 "dependencies": {
6282 "@es-joy/jsdoccomment": "~0.48.0",
@@ -6435,13 +6426,13 @@
6426 }
6427 },
6428 "node_modules/eslint-plugin-perfectionist": {
6438 - "version": "3.6.0",
6439 - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-3.6.0.tgz",
6440 - "integrity": "sha512-sA6ljy6dL/9cM5ruZ/pMqRVt0FQ4Z7mbQWlBYpyX9941LVfm65d2jl2k1ZbWD3ud9Wm+/NKgOvRnAatsKhMJbA==",
6429 + "version": "3.7.0",
6430 + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-3.7.0.tgz",
6431 + "integrity": "sha512-pemhfcR3LDbYVWeveHok9u048yR7GpsnfyPvn6RsDkp/UV7iqBV0y5K0aGb9ZJMsemOyWok7akxGzPLsz+mHKQ==",
6432 "dev": true,
6433 "dependencies": {
6443 - "@typescript-eslint/types": "^8.5.0",
6444 - "@typescript-eslint/utils": "^8.5.0",
6434 + "@typescript-eslint/types": "^8.7.0",
6435 + "@typescript-eslint/utils": "^8.7.0",
6436 "minimatch": "^9.0.5",
6437 "natural-compare-lite": "^1.4.0"
6438 },
@@ -6703,9 +6694,9 @@
6694 }
6695 },
6696 "node_modules/eslint-scope": {
6706 - "version": "8.0.2",
6707 - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz",
6708 - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==",
6697 + "version": "8.1.0",
6698 + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz",
6699 + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==",
6700 "dependencies": {
6701 "esrecurse": "^4.3.0",
6702 "estraverse": "^5.2.0"
@@ -6718,9 +6709,9 @@
6709 }
6710 },
6711 "node_modules/eslint-visitor-keys": {
6721 - "version": "4.0.0",
6722 - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
6723 - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
6712 + "version": "4.1.0",
6713 + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz",
6714 + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==",
6715 "engines": {
6716 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
6717 },
@@ -6729,9 +6720,9 @@
6720 }
6721 },
6722 "node_modules/eslint/node_modules/@eslint/js": {
6732 - "version": "9.11.0",
6733 - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.0.tgz",
6734 - "integrity": "sha512-LPkkenkDqyzTFauZLLAPhIb48fj6drrfMvRGSL9tS3AcZBSVTllemLSNyCvHNNL2t797S/6DJNSIwRwXgMO/eQ==",
6723 + "version": "9.11.1",
6724 + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.1.tgz",
6725 + "integrity": "sha512-/qu+TWz8WwPWc7/HcIJKi+c+MOm46GdVaSlTTQcaqaL53+GsoA6MxWp5PtTx48qbSP7ylM1Kn7nhvkugfJvRSA==",
6726 "engines": {
6727 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
6728 }
@@ -6821,13 +6812,13 @@
6812 }
6813 },
6814 "node_modules/espree": {
6824 - "version": "10.1.0",
6825 - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz",
6826 - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==",
6815 + "version": "10.2.0",
6816 + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz",
6817 + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==",
6818 "dependencies": {
6819 "acorn": "^8.12.0",
6820 "acorn-jsx": "^5.3.2",
6830 - "eslint-visitor-keys": "^4.0.0"
6821 + "eslint-visitor-keys": "^4.1.0"
6822 },
6823 "engines": {
6824 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -7645,9 +7636,9 @@
7636 }
7637 },
7638 "node_modules/highlight-words-core": {
7648 - "version": "1.2.2",
7649 - "resolved": "https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.2.tgz",
7650 - "integrity": "sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg=="
7639 + "version": "1.2.3",
7640 + "resolved": "https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.3.tgz",
7641 + "integrity": "sha512-m1O9HW3/GNHxzSIXWw1wCNXXsgLlxrP0OI6+ycGUhiUHkikqW3OrwVHz+lxeNBe5yqLESdIcj8PowHQ2zLvUvQ=="
7642 },
7643 "node_modules/highlight.js": {
7644 "version": "11.10.0",
@@ -7913,27 +7904,26 @@
7904 }
7905 },
7906 "node_modules/importx": {
7916 - "version": "0.4.4",
7917 - "resolved": "https://registry.npmjs.org/importx/-/importx-0.4.4.tgz",
7918 - "integrity": "sha512-Lo1pukzAREqrBnnHC+tj+lreMTAvyxtkKsMxLY8H15M/bvLl54p3YuoTI70Tz7Il0AsgSlD7Lrk/FaApRcBL7w==",
7907 + "version": "0.5.0",
7908 + "resolved": "https://registry.npmjs.org/importx/-/importx-0.5.0.tgz",
7909 + "integrity": "sha512-qROz3rSOjQYclmEQAajH9RhBuqpAGHM+5CNd9fk+TsF4JKmQsAI1egafW8XZZv8vARCo4nAmmt5d0eI2B8GUsA==",
7910 "dev": true,
7911 "dependencies": {
7912 "bundle-require": "^5.0.0",
7922 - "debug": "^4.3.6",
7913 + "debug": "^4.3.7",
7914 "esbuild": "^0.20.2 || ^0.21.0 || ^0.22.0 || ^0.23.0",
7924 - "jiti": "2.0.0-beta.3",
7925 - "jiti-v1": "npm:jiti@^1.21.6",
7915 + "jiti": "^2.0.0",
7916 "pathe": "^1.1.2",
7927 - "tsx": "^4.19.0"
7917 + "tsx": "^4.19.1"
7918 },
7919 "funding": {
7920 "url": "https://github.com/sponsors/antfu"
7921 }
7922 },
7923 "node_modules/importx/node_modules/jiti": {
7934 - "version": "2.0.0-beta.3",
7935 - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.0.0-beta.3.tgz",
7936 - "integrity": "sha512-pmfRbVRs/7khFrSAYnSiJ8C0D5GvzkE4Ey2pAvUcJsw1ly/p+7ut27jbJrjY79BpAJQJ4gXYFtK6d1Aub+9baQ==",
7924 + "version": "2.0.0",
7925 + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.0.0.tgz",
7926 + "integrity": "sha512-CJ7e7Abb779OTRv3lomfp7Mns/Sy1+U4pcAx5VbjxCZD5ZM/VJaXPpPjNKjtSvWQy/H86E49REXR34dl1JEz9w==",
7927 "dev": true,
7928 "bin": {
7929 "jiti": "lib/jiti-cli.mjs"
@@ -8271,16 +8261,6 @@
8261 "jiti": "bin/jiti.js"
8262 }
8263 },
8274 - "node_modules/jiti-v1": {
8275 - "name": "jiti",
8276 - "version": "1.21.6",
8277 - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
8278 - "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
8279 - "dev": true,
8280 - "bin": {
8281 - "jiti": "bin/jiti.js"
8282 - }
8283 - },
8264 "node_modules/joi": {
8265 "version": "17.13.3",
8266 "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz",
@@ -10198,20 +10178,20 @@
10178 }
10179 },
10180 "node_modules/naive-ui": {
10201 - "version": "2.39.0",
10202 - "resolved": "https://registry.npmjs.org/naive-ui/-/naive-ui-2.39.0.tgz",
10203 - "integrity": "sha512-5oUJzRG+rtLSH8eRU+fJvVYiQids2BxF9jp+fwGoAqHOptEINrBlgBu9uy+95RHE5FLJ7Q/z41o+qkoGnUrKxQ==",
10181 + "version": "2.40.1",
10182 + "resolved": "https://registry.npmjs.org/naive-ui/-/naive-ui-2.40.1.tgz",
10183 + "integrity": "sha512-3NkL+vLRQZKQxCHXa+7xiD6oM74OrQELaehDkGYRYpr6kjT+JJB+Z7h+5LC70gn8VkbgCAETv0+uRWF+6MLlgQ==",
10184 "dependencies": {
10205 - "@css-render/plugin-bem": "^0.15.12",
10206 - "@css-render/vue3-ssr": "^0.15.12",
10185 + "@css-render/plugin-bem": "^0.15.14",
10186 + "@css-render/vue3-ssr": "^0.15.14",
10187 "@types/katex": "^0.16.2",
10188 "@types/lodash": "^4.14.198",
10189 "@types/lodash-es": "^4.17.9",
10190 "async-validator": "^4.2.5",
10211 - "css-render": "^0.15.12",
10191 + "css-render": "^0.15.14",
10192 "csstype": "^3.1.3",
10213 - "date-fns": "^2.30.0",
10214 - "date-fns-tz": "^2.0.0",
10193 + "date-fns": "^3.6.0",
10194 + "date-fns-tz": "^3.1.3",
10195 "evtd": "^0.2.4",
10196 "highlight.js": "^11.8.0",
10197 "lodash": "^4.17.21",
@@ -10220,7 +10200,7 @@
10200 "treemate": "^0.3.11",
10201 "vdirs": "^0.1.8",
10202 "vooks": "^0.2.12",
10223 - "vueuc": "^0.4.58"
10203 + "vueuc": "^0.4.63"
10204 },
10205 "peerDependencies": {
10206 "vue": "^3.0.0"
@@ -10396,15 +10376,15 @@
10376 }
10377 },
10378 "node_modules/nwsapi": {
10399 - "version": "2.2.12",
10400 - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz",
10401 - "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==",
10379 + "version": "2.2.13",
10380 + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz",
10381 + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==",
10382 "dev": true
10383 },
10384 "node_modules/nypm": {
10405 - "version": "0.3.11",
10406 - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.11.tgz",
10407 - "integrity": "sha512-E5GqaAYSnbb6n1qZyik2wjPDZON43FqOJO59+3OkWrnmQtjggrMOVnsyzfjxp/tS6nlYJBA4zRA5jSM2YaadMg==",
10385 + "version": "0.3.12",
10386 + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.12.tgz",
10387 + "integrity": "sha512-D3pzNDWIvgA+7IORhD/IuWzEk4uXv6GsgOxiid4UU3h9oq5IqV1KtPDi63n4sZJ/xcWlr88c0QM2RgN5VbOhFA==",
10388 "dependencies": {
10389 "citty": "^0.1.6",
10390 "consola": "^3.2.3",
@@ -10733,9 +10713,9 @@
10713 }
10714 },
10715 "node_modules/package-json-from-dist": {
10736 - "version": "1.0.0",
10737 - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
10738 - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
10716 + "version": "1.0.1",
10717 + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
10718 + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
10719 "dev": true
10720 },
10721 "node_modules/package-manager-detector": {
@@ -10984,9 +10964,9 @@
10964 }
10965 },
10966 "node_modules/pinia": {
10987 - "version": "2.2.2",
10988 - "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.2.2.tgz",
10989 - "integrity": "sha512-ja2XqFWZC36mupU4z1ZzxeTApV7DOw44cV4dhQ9sGwun+N89v/XP7+j7q6TanS1u1tdbK4r+1BUx7heMaIdagA==",
10967 + "version": "2.2.4",
10968 + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.2.4.tgz",
10969 + "integrity": "sha512-K7ZhpMY9iJ9ShTC0cR2+PnxdQRuwVIsXDO/WIEV/RnMC/vmSoKDTKW/exNQYPI+4ij10UjXqdNiEHwn47McANQ==",
10970 "dependencies": {
10971 "@vue/devtools-api": "^6.6.3",
10972 "vue-demi": "^0.14.10"
@@ -11597,11 +11577,6 @@
11577 "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
11578 }
11579 },
11600 - "node_modules/regenerator-runtime": {
11601 - "version": "0.14.1",
11602 - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
11603 - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
11604 - },
11580 "node_modules/regex": {
11581 "version": "4.3.2",
11582 "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.2.tgz",
@@ -11984,12 +11959,12 @@
11959 }
11960 },
11961 "node_modules/rollup": {
11987 - "version": "4.22.4",
11988 - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz",
11989 - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==",
11962 + "version": "4.22.5",
11963 + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.5.tgz",
11964 + "integrity": "sha512-WoinX7GeQOFMGznEcWA1WrTQCd/tpEbMkc3nuMs9BT0CPjMdSjPMTVClwWd4pgSQwJdP65SK9mTCNvItlr5o7w==",
11965 "devOptional": true,
11966 "dependencies": {
11992 - "@types/estree": "1.0.5"
11967 + "@types/estree": "1.0.6"
11968 },
11969 "bin": {
11970 "rollup": "dist/bin/rollup"
@@ -11999,22 +11974,22 @@
11974 "npm": ">=8.0.0"
11975 },
11976 "optionalDependencies": {
12002 - "@rollup/rollup-android-arm-eabi": "4.22.4",
12003 - "@rollup/rollup-android-arm64": "4.22.4",
12004 - "@rollup/rollup-darwin-arm64": "4.22.4",
12005 - "@rollup/rollup-darwin-x64": "4.22.4",
12006 - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4",
12007 - "@rollup/rollup-linux-arm-musleabihf": "4.22.4",
12008 - "@rollup/rollup-linux-arm64-gnu": "4.22.4",
12009 - "@rollup/rollup-linux-arm64-musl": "4.22.4",
12010 - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4",
12011 - "@rollup/rollup-linux-riscv64-gnu": "4.22.4",
12012 - "@rollup/rollup-linux-s390x-gnu": "4.22.4",
12013 - "@rollup/rollup-linux-x64-gnu": "4.22.4",
12014 - "@rollup/rollup-linux-x64-musl": "4.22.4",
12015 - "@rollup/rollup-win32-arm64-msvc": "4.22.4",
12016 - "@rollup/rollup-win32-ia32-msvc": "4.22.4",
12017 - "@rollup/rollup-win32-x64-msvc": "4.22.4",
11977 + "@rollup/rollup-android-arm-eabi": "4.22.5",
11978 + "@rollup/rollup-android-arm64": "4.22.5",
11979 + "@rollup/rollup-darwin-arm64": "4.22.5",
11980 + "@rollup/rollup-darwin-x64": "4.22.5",
11981 + "@rollup/rollup-linux-arm-gnueabihf": "4.22.5",
11982 + "@rollup/rollup-linux-arm-musleabihf": "4.22.5",
11983 + "@rollup/rollup-linux-arm64-gnu": "4.22.5",
11984 + "@rollup/rollup-linux-arm64-musl": "4.22.5",
11985 + "@rollup/rollup-linux-powerpc64le-gnu": "4.22.5",
11986 + "@rollup/rollup-linux-riscv64-gnu": "4.22.5",
11987 + "@rollup/rollup-linux-s390x-gnu": "4.22.5",
11988 + "@rollup/rollup-linux-x64-gnu": "4.22.5",
11989 + "@rollup/rollup-linux-x64-musl": "4.22.5",
11990 + "@rollup/rollup-win32-arm64-msvc": "4.22.5",
11991 + "@rollup/rollup-win32-ia32-msvc": "4.22.5",
11992 + "@rollup/rollup-win32-x64-msvc": "4.22.5",
11993 "fsevents": "~2.3.2"
11994 }
11995 },
@@ -12073,11 +12048,18 @@
12048 "url": "https://github.com/sponsors/jonschlinkert"
12049 }
12050 },
12076 - "node_modules/rollup/node_modules/@types/estree": {
12077 - "version": "1.0.5",
12078 - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
12079 - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
12080 - "devOptional": true
12051 + "node_modules/rollup/node_modules/@rollup/rollup-linux-x64-gnu": {
12052 + "version": "4.22.5",
12053 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.5.tgz",
12054 + "integrity": "sha512-N0jPPhHjGShcB9/XXZQWuWBKZQnC1F36Ce3sDqWpujsGjDz/CQtOL9LgTrJ+rJC8MJeesMWrMWVLKKNR/tMOCA==",
12055 + "cpu": [
12056 + "x64"
12057 + ],
12058 + "dev": true,
12059 + "optional": true,
12060 + "os": [
12061 + "linux"
12062 + ]
12063 },
12064 "node_modules/rrweb-cssom": {
12065 "version": "0.7.1",
@@ -12155,9 +12137,9 @@
12137 "dev": true
12138 },
12139 "node_modules/sass": {
12158 - "version": "1.79.3",
12159 - "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.3.tgz",
12160 - "integrity": "sha512-m7dZxh0W9EZ3cw50Me5GOuYm/tVAJAn91SUnohLRo9cXBixGUOdvmryN+dXpwR831bhoY3Zv7rEFt85PUwTmzA==",
12140 + "version": "1.79.4",
12141 + "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.4.tgz",
12142 + "integrity": "sha512-K0QDSNPXgyqO4GZq2HO5Q70TLxTH6cIT59RdoCHMivrC8rqzaTw5ab9prjz9KUN1El4FLXrBXJhik61JR4HcGg==",
12143 "dev": true,
12144 "dependencies": {
12145 "chokidar": "^4.0.0",
@@ -12310,14 +12292,14 @@
12292 }
12293 },
12294 "node_modules/shiki": {
12313 - "version": "1.18.0",
12314 - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.18.0.tgz",
12315 - "integrity": "sha512-8jo7tOXr96h9PBQmOHVrltnETn1honZZY76YA79MHheGQg55jBvbm9dtU+MI5pjC5NJCFuA6rvVTLVeSW5cE4A==",
12316 - "dependencies": {
12317 - "@shikijs/core": "1.18.0",
12318 - "@shikijs/engine-javascript": "1.18.0",
12319 - "@shikijs/engine-oniguruma": "1.18.0",
12320 - "@shikijs/types": "1.18.0",
12295 + "version": "1.21.0",
12296 + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.21.0.tgz",
12297 + "integrity": "sha512-apCH5BoWTrmHDPGgg3RF8+HAAbEL/CdbYr8rMw7eIrdhCkZHdVGat5mMNlRtd1erNG01VPMIKHNQ0Pj2HMAiog==",
12298 + "dependencies": {
12299 + "@shikijs/core": "1.21.0",
12300 + "@shikijs/engine-javascript": "1.21.0",
12301 + "@shikijs/engine-oniguruma": "1.21.0",
12302 + "@shikijs/types": "1.21.0",
12303 "@shikijs/vscode-textmate": "^9.2.2",
12304 "@types/hast": "^3.0.4"
12305 }
@@ -13029,9 +13011,9 @@
13011 }
13012 },
13013 "node_modules/tailwindcss": {
13032 - "version": "3.4.12",
13033 - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.12.tgz",
13034 - "integrity": "sha512-Htf/gHj2+soPb9UayUNci/Ja3d8pTmu9ONTfh4QY8r3MATTZOzmv6UYWF7ZwikEIC8okpfqmGqrmDehua8mF8w==",
13014 + "version": "3.4.13",
13015 + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz",
13016 + "integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==",
13017 "dev": true,
13018 "dependencies": {
13019 "@alloc/quick-lru": "^5.2.0",
@@ -13115,17 +13097,17 @@
13097 "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
13098 },
13099 "node_modules/taze": {
13118 - "version": "0.16.9",
13119 - "resolved": "https://registry.npmjs.org/taze/-/taze-0.16.9.tgz",
13120 - "integrity": "sha512-5dROtuXIaP3HOHy7f2jTvnfHbHO8ubCoqfv1At3UOo7QB63y8oLNwpuj7w/4IdVY+lkzQSDV6f5L5Bhl3kq9QQ==",
13100 + "version": "0.17.2",
13101 + "resolved": "https://registry.npmjs.org/taze/-/taze-0.17.2.tgz",
13102 + "integrity": "sha512-VZvB2PfuIXVQdgEnjqg1NLAnxzEv28ypxTLpbtSs8rO0gdZbFRwRj3ES9QXneo112rdIwx1SM2QcIL83EfNBdg==",
13103 "dev": true,
13104 "dependencies": {
13105 "@antfu/ni": "^0.23.0",
13106 "js-yaml": "^4.1.0",
13125 - "ofetch": "^1.3.4",
13107 + "ofetch": "^1.4.0",
13108 "package-manager-detector": "^0.2.0",
13109 "tinyexec": "^0.3.0",
13128 - "unconfig": "^0.5.5",
13110 + "unconfig": "^0.6.0",
13111 "yargs": "^17.7.2"
13112 },
13113 "bin": {
@@ -13136,14 +13118,14 @@
13118 }
13119 },
13120 "node_modules/taze/node_modules/unconfig": {
13139 - "version": "0.5.5",
13140 - "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-0.5.5.tgz",
13141 - "integrity": "sha512-VQZ5PT9HDX+qag0XdgQi8tJepPhXiR/yVOkn707gJDKo31lGjRilPREiQJ9Z6zd/Ugpv6ZvO5VxVIcatldYcNQ==",
13121 + "version": "0.6.0",
13122 + "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-0.6.0.tgz",
13123 + "integrity": "sha512-4C67J0nIF2QwSXty2kW3zZx1pMZ3iXabylvJWWgHybWVUcMf9pxwsngoQt0gC+AVstRywFqrRBp3qOXJayhpOw==",
13124 "dev": true,
13125 "dependencies": {
13126 "@antfu/utils": "^0.7.10",
13127 "defu": "^6.1.4",
13146 - "importx": "^0.4.3"
13128 + "importx": "^0.5.0"
13129 },
13130 "funding": {
13131 "url": "https://github.com/sponsors/antfu"
@@ -13230,21 +13212,21 @@
13212 }
13213 },
13214 "node_modules/tldts": {
13233 - "version": "6.1.47",
13234 - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.47.tgz",
13235 - "integrity": "sha512-R/K2tZ5MiY+mVrnSkNJkwqYT2vUv1lcT6wJvd2emGaMJ7PHUGRY4e3tUsdFCXgqxi2QgbHjL3yJgXCo40v9Hxw==",
13215 + "version": "6.1.48",
13216 + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.48.tgz",
13217 + "integrity": "sha512-SPbnh1zaSzi/OsmHb1vrPNnYuwJbdWjwo5TbBYYMlTtH3/1DSb41t8bcSxkwDmmbG2q6VLPVvQc7Yf23T+1EEw==",
13218 "dev": true,
13219 "dependencies": {
13238 - "tldts-core": "^6.1.47"
13220 + "tldts-core": "^6.1.48"
13221 },
13222 "bin": {
13223 "tldts": "bin/cli.js"
13224 }
13225 },
13226 "node_modules/tldts-core": {
13245 - "version": "6.1.47",
13246 - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.47.tgz",
13247 - "integrity": "sha512-6SWyFMnlst1fEt7GQVAAu16EGgFK0cLouH/2Mk6Ftlwhv3Ol40L0dlpGMcnnNiiOMyD2EV/aF3S+U2nKvvLvrA==",
13227 + "version": "6.1.48",
13228 + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.48.tgz",
13229 + "integrity": "sha512-3gD9iKn/n2UuFH1uilBviK9gvTNT6iYwdqrj1Vr5mh8FuelvpRNaYVH4pNYqUgOGU4aAdL9X35eLuuj0gRsx+A==",
13230 "dev": true
13231 },
13232 "node_modules/tmp": {
@@ -13958,11 +13940,11 @@
13940 }
13941 },
13942 "node_modules/unimport": {
13961 - "version": "3.12.0",
13962 - "resolved": "https://registry.npmjs.org/unimport/-/unimport-3.12.0.tgz",
13963 - "integrity": "sha512-5y8dSvNvyevsnw4TBQkIQR1Rjdbb+XjVSwQwxltpnVZrStBvvPkMPcZrh1kg5kY77kpx6+D4Ztd3W6FOBH/y2Q==",
13943 + "version": "3.13.1",
13944 + "resolved": "https://registry.npmjs.org/unimport/-/unimport-3.13.1.tgz",
13945 + "integrity": "sha512-nNrVzcs93yrZQOW77qnyOVHtb68LegvhYFwxFMfuuWScmwQmyVCG/NBuN8tYsaGzgQUVYv34E/af+Cc9u4og4A==",
13946 "dependencies": {
13965 - "@rollup/pluginutils": "^5.1.0",
13947 + "@rollup/pluginutils": "^5.1.2",
13948 "acorn": "^8.12.1",
13949 "escape-string-regexp": "^5.0.0",
13950 "estree-walker": "^3.0.3",
@@ -14135,26 +14117,34 @@
14117 }
14118 },
14119 "node_modules/untyped": {
14138 - "version": "1.4.2",
14139 - "resolved": "https://registry.npmjs.org/untyped/-/untyped-1.4.2.tgz",
14140 - "integrity": "sha512-nC5q0DnPEPVURPhfPQLahhSTnemVtPzdx7ofiRxXpOB2SYnb3MfdU3DVGyJdS8Lx+tBWeAePO8BfU/3EgksM7Q==",
14120 + "version": "1.5.0",
14121 + "resolved": "https://registry.npmjs.org/untyped/-/untyped-1.5.0.tgz",
14122 + "integrity": "sha512-o2Vjmn2dal08BzCcINxSmWuAteReUUiXseii5VRhmxyLF0b21K0iKZQ9fMYK7RWspVkY+0saqaVQNq4roe3Efg==",
14123 "dependencies": {
14142 - "@babel/core": "^7.23.7",
14143 - "@babel/standalone": "^7.23.8",
14144 - "@babel/types": "^7.23.6",
14124 + "@babel/core": "^7.25.2",
14125 + "@babel/standalone": "^7.25.6",
14126 + "@babel/types": "^7.25.6",
14127 "defu": "^6.1.4",
14146 - "jiti": "^1.21.0",
14128 + "jiti": "^2.0.0",
14129 "mri": "^1.2.0",
14148 - "scule": "^1.2.0"
14130 + "scule": "^1.3.0"
14131 },
14132 "bin": {
14133 "untyped": "dist/cli.mjs"
14134 }
14135 },
14136 + "node_modules/untyped/node_modules/jiti": {
14137 + "version": "2.0.0",
14138 + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.0.0.tgz",
14139 + "integrity": "sha512-CJ7e7Abb779OTRv3lomfp7Mns/Sy1+U4pcAx5VbjxCZD5ZM/VJaXPpPjNKjtSvWQy/H86E49REXR34dl1JEz9w==",
14140 + "bin": {
14141 + "jiti": "lib/jiti-cli.mjs"
14142 + }
14143 + },
14144 "node_modules/update-browserslist-db": {
14155 - "version": "1.1.0",
14156 - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
14157 - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
14145 + "version": "1.1.1",
14146 + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
14147 + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
14148 "funding": [
14149 {
14150 "type": "opencollective",
@@ -14170,8 +14160,8 @@
14160 }
14161 ],
14162 "dependencies": {
14173 - "escalade": "^3.1.2",
14174 - "picocolors": "^1.0.1"
14163 + "escalade": "^3.2.0",
14164 + "picocolors": "^1.1.0"
14165 },
14166 "bin": {
14167 "update-browserslist-db": "cli.js"
@@ -14301,9 +14291,9 @@
14291 }
14292 },
14293 "node_modules/vite": {
14304 - "version": "5.4.7",
14305 - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz",
14306 - "integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==",
14294 + "version": "5.4.8",
14295 + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz",
14296 + "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==",
14297 "dev": true,
14298 "dependencies": {
14299 "esbuild": "^0.21.3",
@@ -14360,9 +14350,9 @@
14350 }
14351 },
14352 "node_modules/vite-bundle-analyzer": {
14363 - "version": "0.11.1",
14364 - "resolved": "https://registry.npmjs.org/vite-bundle-analyzer/-/vite-bundle-analyzer-0.11.1.tgz",
14365 - "integrity": "sha512-0GptL3zHh36t5Gp+W1PAU3CiRU7tA0NS0XJhS2YFX6RtIs7oltdMDqLBKjSXCUJRWa3zki+oASfbE6ssAsf1PA==",
14353 + "version": "0.12.1",
14354 + "resolved": "https://registry.npmjs.org/vite-bundle-analyzer/-/vite-bundle-analyzer-0.12.1.tgz",
14355 + "integrity": "sha512-mIYwsDvTYCqXAUtOZIL3f7NdwWUeL/MlNFhOJzlTdcZE4pye6h06IEnOvWhnc/e+HM4oVVNxuRHZt0Rz6VO7EA==",
14356 "dev": true
14357 },
14358 "node_modules/vite-bundle-visualizer": {
@@ -14493,14 +14483,14 @@
14483 }
14484 },
14485 "node_modules/vite-plugin-vue-devtools": {
14496 - "version": "7.4.5",
14497 - "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.4.5.tgz",
14498 - "integrity": "sha512-8D9Dv7uw620r96uI45M7hCyfsBA9KwttdmxA/DAd0/1KpuGmrFEhNwo4ob/sjaou1noAeK2TrnKdW+sFMR6aKQ==",
14486 + "version": "7.4.6",
14487 + "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.4.6.tgz",
14488 + "integrity": "sha512-lOKur3qovCB3BQStL0qfHEoIusqya1ngfxfWuqn9DTa6h9rlw6+S3PV4geOP5YBGYQ4NW1hRX70OD8I+sYr1dA==",
14489 "dev": true,
14490 "dependencies": {
14501 - "@vue/devtools-core": "^7.4.5",
14502 - "@vue/devtools-kit": "^7.4.5",
14503 - "@vue/devtools-shared": "^7.4.5",
14491 + "@vue/devtools-core": "^7.4.6",
14492 + "@vue/devtools-kit": "^7.4.6",
14493 + "@vue/devtools-shared": "^7.4.6",
14494 "execa": "^8.0.1",
14495 "sirv": "^2.0.4",
14496 "vite-plugin-inspect": "^0.8.7",
@@ -14761,15 +14751,15 @@
14751 "dev": true
14752 },
14753 "node_modules/vue": {
14764 - "version": "3.5.8",
14765 - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.8.tgz",
14766 - "integrity": "sha512-hvuvuCy51nP/1fSRvrrIqTLSvrSyz2Pq+KQ8S8SXCxTWVE0nMaOnSDnSOxV1eYmGfvK7mqiwvd1C59CEEz7dAQ==",
14754 + "version": "3.5.10",
14755 + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.10.tgz",
14756 + "integrity": "sha512-Vy2kmJwHPlouC/tSnIgXVg03SG+9wSqT1xu1Vehc+ChsXsRd7jLkKgMltVEFOzUdBr3uFwBCG+41LJtfAcBRng==",
14757 "dependencies": {
14768 - "@vue/compiler-dom": "3.5.8",
14769 - "@vue/compiler-sfc": "3.5.8",
14770 - "@vue/runtime-dom": "3.5.8",
14771 - "@vue/server-renderer": "3.5.8",
14772 - "@vue/shared": "3.5.8"
14758 + "@vue/compiler-dom": "3.5.10",
14759 + "@vue/compiler-sfc": "3.5.10",
14760 + "@vue/runtime-dom": "3.5.10",
14761 + "@vue/server-renderer": "3.5.10",
14762 + "@vue/shared": "3.5.10"
14763 },
14764 "peerDependencies": {
14765 "typescript": "*"
@@ -14969,9 +14959,9 @@
14959 }
14960 },
14961 "node_modules/vueuc": {
14972 - "version": "0.4.63",
14973 - "resolved": "https://registry.npmjs.org/vueuc/-/vueuc-0.4.63.tgz",
14974 - "integrity": "sha512-QJT0z9yYWXdKpUq6f6IrAgJ83e34iTYMCVHjcAP8lCjldG0JzHnDfJYMpPWkNuLB5SdBZCbYGmYTKnTR+ff7CQ==",
14962 + "version": "0.4.64",
14963 + "resolved": "https://registry.npmjs.org/vueuc/-/vueuc-0.4.64.tgz",
14964 + "integrity": "sha512-wlJQj7fIwKK2pOEoOq4Aro8JdPOGpX8aWQhV8YkTW9OgWD2uj2O8ANzvSsIGjx7LTOc7QbS7sXdxHi6XvRnHPA==",
14965 "dependencies": {
14966 "@css-render/vue3-ssr": "^0.15.10",
14967 "@juggle/resize-observer": "^3.3.1",
frontend/package.json
+22 -22
@@ -41,10 +41,10 @@
41 "@fontsource/lexend": "^5.1.0",
42 "@fontsource/public-sans": "^5.1.0",
43 "@popperjs/core": "^2.11.8",
44 - "@shikijs/markdown-it": "^1.18.0",
44 + "@shikijs/markdown-it": "^1.21.0",
45 "@vueuse/components": "^11.1.0",
46 "@vueuse/core": "^11.1.0",
47 - "apexcharts": "^3.53.0",
47 + "apexcharts": "^3.54.0",
48 "axios": "^1.7.7",
49 "bytes": "^3.1.2",
50 "colord": "^2.9.3",
@@ -58,14 +58,14 @@
58 "js-md5": "^0.8.3",
59 "lodash": "^4.17.21",
60 "mitt": "^3.0.1",
61 - "naive-ui": "^2.39.0",
61 + "naive-ui": "^2.40.1",
62 "password-validator": "^5.3.0",
63 - "pinia": "^2.2.2",
63 + "pinia": "^2.2.4",
64 "pinia-plugin-persistedstate": "^4.0.2",
65 "secure-ls": "^2.0.0",
66 - "shiki": "^1.18.0",
66 + "shiki": "^1.21.0",
67 "validator": "^13.12.0",
68 - "vue": "^3.5.8",
68 + "vue": "^3.5.10",
69 "vue-advanced-cropper": "^2.8.9",
70 "vue-highlight-words": "^3.0.1",
71 "vue-i18n": "^10.0.3",
@@ -76,10 +76,10 @@
76 "vuedraggable": "^4.1.0"
77 },
78 "optionalDependencies": {
79 - "@rollup/rollup-linux-x64-gnu": "^4.22.4"
79 + "@rollup/rollup-linux-x64-gnu": "^4.23.0"
80 },
81 "devDependencies": {
82 - "@antfu/eslint-config": "^3.7.1",
82 + "@antfu/eslint-config": "^3.7.3",
83 "@clack/prompts": "^0.7.0",
84 "@iconify/vue": "^4.1.2",
85 "@tsconfig/node20": "^20.1.4",
@@ -88,16 +88,16 @@
88 "@types/fs-extra": "^11.0.4",
89 "@types/inquirer": "^9.0.7",
90 "@types/jsdom": "^21.1.7",
91 - "@types/lodash": "^4.17.7",
92 - "@types/node": "^22.5.5",
91 + "@types/lodash": "^4.17.9",
92 + "@types/node": "^22.7.4",
93 "@types/validator": "^13.12.2",
94 "@vitejs/plugin-vue": "^5.1.4",
95 "@vitejs/plugin-vue-jsx": "^4.0.1",
96 "@vue/test-utils": "^2.4.6",
97 "@vue/tsconfig": "^0.5.1",
98 "autoprefixer": "^10.4.20",
99 - "cypress": "^13.14.2",
100 - "eslint": "^9.11.0",
99 + "cypress": "^13.15.0",
100 + "eslint": "^9.11.1",
101 "flourite": "^1.3.0",
102 "fs-extra": "^11.2.0",
103 "globals": "^15.9.0",
@@ -107,37 +107,37 @@
107 "picocolors": "^1.1.0",
108 "postcss": "^8.4.47",
109 "prettier": "^3.3.3",
110 - "sass": "^1.79.3",
110 + "sass": "^1.79.4",
111 "start-server-and-test": "^2.0.8",
112 "tailwind-config-viewer": "^2.0.4",
113 - "tailwindcss": "^3.4.12",
114 - "taze": "^0.16.9",
113 + "tailwindcss": "^3.4.13",
114 + "taze": "^0.17.2",
115 "type-fest": "^4.26.1",
116 "typescript": "~5.5.4",
117 "unplugin-vue-components": "^0.27.4",
118 - "vite": "^5.4.7",
119 - "vite-bundle-analyzer": "^0.11.1",
118 + "vite": "^5.4.8",
119 + "vite-bundle-analyzer": "^0.12.1",
120 "vite-bundle-visualizer": "^1.2.1",
121 - "vite-plugin-vue-devtools": "^7.4.5",
121 + "vite-plugin-vue-devtools": "^7.4.6",
122 "vite-svg-loader": "^5.1.0",
123 "vitest": "^2.1.1",
124 "vue-tsc": "^2.1.6"
125 },
126 "pnpm": {
127 "overrides": {
128 - "@typescript-eslint/eslint-plugin": "^8.6.0",
128 + "@typescript-eslint/eslint-plugin": "^8.8.0",
129 "@typescript-eslint/eslint-plugin>eslint": "$eslint",
130 - "@typescript-eslint/parser": "^8.6.0",
130 + "@typescript-eslint/parser": "^8.8.0",
131 "@typescript-eslint/parser>eslint": "$eslint",
132 "eslint": "$eslint"
133 }
134 },
135 "overrides": {
136 "@typescript-eslint/eslint-plugin": {
137 - "eslint": "9.11.0"
137 + "eslint": "9.11.1"
138 },
139 "@typescript-eslint/parser": {
140 - "eslint": "9.11.0"
140 + "eslint": "9.11.1"
141 }
142 }
143 }
frontend/src/App.vue
+4 -4
@@ -22,11 +22,11 @@
22
23 <script lang="ts" setup>
24 import type { Layout, RouterTransition, ThemeName } from "@/types/theme.d"
25 +import Blank from "@/app-layouts/Blank/index.vue"
26 +import Provider from "@/app-layouts/common/Provider.vue"
27 +import SplashScreen from "@/app-layouts/common/SplashScreen.vue"
28 +import HorizontalNav from "@/app-layouts/HorizontalNav/index.vue"
29 import SearchDialog from "@/components/common/SearchDialog.vue"
26 -import Blank from "@/layouts/Blank/index.vue"
27 -import Provider from "@/layouts/common/Provider.vue"
28 -import SplashScreen from "@/layouts/common/SplashScreen.vue"
29 -import HorizontalNav from "@/layouts/HorizontalNav/index.vue"
30 import { useAuthStore } from "@/stores/auth"
31 import { useMainStore } from "@/stores/main"
32 import { useThemeStore } from "@/stores/theme"
frontend/src/app-layouts/Blank/MainContainer.vue renamed
+2 -2
@@ -2,7 +2,7 @@
2 <div class="main">
3 <n-scrollbar ref="scrollbar">
4 <div class="view" :class="[{ boxed }, `route-${routeName}`]">
5 - <slot></slot>
5 + <slot />
6 </div>
7 </n-scrollbar>
8 </div>
@@ -24,7 +24,7 @@ const scrollbar = ref()
24 onMounted(() => {
25 router.afterEach(() => {
26 if (scrollbar?.value?.scrollTo) {
27 - scrollbar?.value.scrollTo({ top: 0 })
27 + scrollbar?.value.scrollTo({ top: 0, behavior: "smooth" })
28 }
29 })
30 })
frontend/src/app-layouts/Blank/index.vue renamed
+1 -1
@@ -1,7 +1,7 @@
1 <template>
2 <div class="layout flex">
3 <MainContainer class="grow">
4 - <slot></slot>
4 + <slot />
5 </MainContainer>
6 </div>
7 </template>
frontend/src/app-layouts/HorizontalNav/HeaderBar.vue renamed
+3 -3
@@ -2,14 +2,14 @@
2 <div class="header-bar flex items-center gap-3">
3 <Logo :mini="false" :dark="isDark" class="anim-wrap" />
4 <n-scrollbar class="grow" x-scrollable>
5 - <Navbar :collapsed="false" mode="horizontal"></Navbar>
5 + <Navbar :collapsed="false" mode="horizontal" />
6 </n-scrollbar>
7 </div>
8 </template>
9
10 <script lang="ts" setup>
11 -import Logo from "@/layouts/common/Logo.vue"
12 -import Navbar from "@/layouts/common/Navbar/index.vue"
11 +import Logo from "@/app-layouts/common/Logo.vue"
12 +import Navbar from "@/app-layouts/common/Navbar/index.vue"
13 import { useThemeStore } from "@/stores/theme"
14 import { NScrollbar } from "naive-ui"
15 import { computed } from "vue"
frontend/src/app-layouts/HorizontalNav/MainContainer.vue renamed
+4 -4
@@ -3,7 +3,7 @@
3 <n-scrollbar ref="scrollbar">
4 <Toolbar :boxed="toolbarBoxed" class="gradient-bg-sidebar" />
5 <div class="view" :class="[{ boxed }, `route-${routeName}`]">
6 - <slot></slot>
6 + <slot />
7 </div>
8 <MainFooter v-if="footerShown" :boxed="boxed" />
9 </n-scrollbar>
@@ -11,8 +11,8 @@
11 </template>
12
13 <script lang="ts" setup>
14 -import MainFooter from "@/layouts/common/MainFooter.vue"
15 -import Toolbar from "@/layouts/common/Toolbar/index.vue"
14 +import MainFooter from "@/app-layouts/common/MainFooter.vue"
15 +import Toolbar from "@/app-layouts/common/Toolbar/index.vue"
16 import { useThemeStore } from "@/stores/theme"
17 import { NScrollbar } from "naive-ui"
18 import { computed, onMounted, ref } from "vue"
@@ -31,7 +31,7 @@ const scrollbar = ref()
31 onMounted(() => {
32 router.afterEach(() => {
33 if (scrollbar?.value?.scrollTo) {
34 - scrollbar?.value.scrollTo({ top: 0 })
34 + scrollbar?.value.scrollTo({ top: 0, behavior: "smooth" })
35 }
36 })
37 })
frontend/src/app-layouts/HorizontalNav/Sidebar.vue renamed
+2 -2
@@ -7,7 +7,7 @@
7 <div ref="sidebar" class="sidebar-wrap grow flex flex-col">
8 <SidebarHeader :logo-mini="sidebarClosed" />
9 <n-scrollbar>
10 - <Navbar :collapsed="sidebarClosed"></Navbar>
10 + <Navbar :collapsed="sidebarClosed" />
11 </n-scrollbar>
12 <SidebarFooter :collapsed="sidebarClosed" />
13 </div>
@@ -15,7 +15,7 @@
15 </template>
16
17 <script lang="ts" setup>
18 -import Navbar from "@/layouts/common/Navbar/index.vue"
18 +import Navbar from "@/app-layouts/common/Navbar/index.vue"
19 import { useThemeStore } from "@/stores/theme"
20 import { isMobile } from "@/utils"
21 import { onClickOutside, useElementHover } from "@vueuse/core"
frontend/src/app-layouts/HorizontalNav/SidebarFooter.vue renamed
frontend/src/app-layouts/HorizontalNav/SidebarHeader.vue renamed
+1 -1
@@ -25,8 +25,8 @@
25 </template>
26
27 <script lang="ts" setup>
28 +import Logo from "@/app-layouts/common/Logo.vue"
29 import Icon from "@/components/common/Icon.vue"
29 -import Logo from "@/layouts/common/Logo.vue"
30 import { useThemeStore } from "@/stores/theme"
31 import { Icon as Iconify } from "@iconify/vue"
32 import { computed, toRefs } from "vue"
frontend/src/app-layouts/HorizontalNav/_variables.scss renamed
frontend/src/app-layouts/HorizontalNav/index.vue renamed
+1 -1
@@ -3,7 +3,7 @@
3 <HeaderBar />
4 <Sidebar />
5 <MainContainer class="grow">
6 - <slot></slot>
6 + <slot />
7 </MainContainer>
8 </div>
9 </template>
frontend/src/app-layouts/HorizontalNav/main.scss renamed
frontend/src/app-layouts/common/GlobalListener.vue renamed
+1 -1
@@ -2,7 +2,7 @@
2 <slot />
3 </template>
4
5 -<script setup>
5 +<script setup lang="ts">
6 import { useGlobalActions } from "@/composables/useGlobalActions"
7 import { useMessage, useNotification } from "naive-ui"
8
frontend/src/app-layouts/common/Logo.vue renamed
+4 -4
@@ -1,15 +1,15 @@
1 <template>
2 <div v-if="isDark && !mini" class="logo">
3 - <img src="@/assets/images/socfortress_logo.svg?url" />
3 + <img alt="logo" src="@/assets/images/socfortress_logo.svg?url" />
4 </div>
5 <div v-else-if="isLight && !mini" class="logo">
6 - <img src="@/assets/images/socfortress_logo.svg?url" />
6 + <img alt="logo" src="@/assets/images/socfortress_logo.svg?url" />
7 </div>
8 <div v-else-if="isDark && mini" class="logo">
9 - <img src="@/assets/images/socfortress_logo.svg?url" />
9 + <img alt="logo" src="@/assets/images/socfortress_logo.svg?url" />
10 </div>
11 <div v-else-if="isLight && mini" class="logo">
12 - <img src="@/assets/images/socfortress_logo.svg?url" />
12 + <img alt="logo" src="@/assets/images/socfortress_logo.svg?url" />
13 </div>
14 </template>
15
frontend/src/app-layouts/common/MainFooter.vue renamed
+1 -1
@@ -10,7 +10,7 @@
10 <a
11 href="https://www.socfortress.co/"
12 target="_blank"
13 - alt="D*VERSE"
13 + alt="SOCFortress"
14 rel="noopener noreferrer"
15 class="mx-1"
16 >
frontend/src/app-layouts/common/Navbar/index.vue renamed
frontend/src/app-layouts/common/Navbar/items.tsx renamed
frontend/src/app-layouts/common/Provider.vue renamed
+17 -23
@@ -24,7 +24,7 @@
24 <script lang="ts" setup>
25 import type { ThemeName } from "@/types/theme.d"
26 import type { RtlItem } from "naive-ui/es/config-provider/src/internal-interface"
27 -import GlobalListener from "@/layouts/common/GlobalListener.vue"
27 +import GlobalListener from "@/app-layouts/common/GlobalListener.vue"
28 import { useThemeStore } from "@/stores/theme"
29 import { useWindowSize } from "@vueuse/core"
30 import {
@@ -36,7 +36,7 @@ import {
36 NMessageProvider,
37 NNotificationProvider
38 } from "naive-ui"
39 -import { computed, watch } from "vue"
39 +import { computed, onBeforeMount, watch } from "vue"
40 import { rtlStyles } from "./rtlProvider"
41
42 const { width } = useWindowSize()
@@ -48,29 +48,17 @@ const style = computed(() => themeStore.style)
48 const isRTL = computed(() => themeStore.isRTL)
49 const rtlOptions = computed<RtlItem[] | undefined>(() => (isRTL.value ? rtlStyles : undefined))
50
51 -watch(
52 - [isRTL, style],
53 - () => {
54 - setGlobalVars()
55 - },
56 - { immediate: true }
57 -)
51 +watch([isRTL, style], () => {
52 + setGlobalVars()
53 +})
54
59 -watch(
60 - themeName,
61 - (val, old) => {
62 - setThemeName(val, old)
63 - },
64 - { immediate: true }
65 -)
55 +watch(themeName, (val, old) => {
56 + setThemeName(val, old)
57 +})
58
67 -watch(
68 - width,
69 - () => {
70 - themeStore.updateVars()
71 - },
72 - { immediate: true }
73 -)
59 +watch(width, () => {
60 + themeStore.updateVars()
61 +})
62
63 // This function allows you to utilize the values in the style object as variables within your CSS/SCSS code like: var(-–bg-color)
64 function setGlobalVars() {
@@ -101,4 +89,10 @@ function setThemeName(val: ThemeName, old?: ThemeName) {
89 html.classList.add(`theme-${val}`)
90 }
91 }
92 +
93 +onBeforeMount(() => {
94 + themeStore.updateVars()
95 + setGlobalVars()
96 + setThemeName(themeName.value)
97 +})
98 </script>
frontend/src/app-layouts/common/SplashScreen.vue renamed
frontend/src/app-layouts/common/Toolbar/Avatar.vue renamed
+1 -1
@@ -1,6 +1,6 @@
1 <template>
2 <n-dropdown :options="options" placement="bottom-end" @select="handleSelect">
3 - <n-avatar round :size="32" :src="userPic" />
3 + <n-avatar round :size="32" :src="userPic" :img-props="{ alt: 'avatar' }" />
4 </n-dropdown>
5 </template>
6
frontend/src/app-layouts/common/Toolbar/Breadcrumb.vue renamed
+1 -1
@@ -1,7 +1,7 @@
1 <template>
2 <n-breadcrumb class="breadcrumb">
3 <n-breadcrumb-item @click="goto({ path: '/' })">
4 - <Icon :size="16" :name="HomeIcon"></Icon>
4 + <Icon :size="16" :name="HomeIcon" />
5 </n-breadcrumb-item>
6 <TransitionGroup name="anim">
7 <n-breadcrumb-item
frontend/src/app-layouts/common/Toolbar/FullscreenSwitch.vue renamed
+2 -2
@@ -1,7 +1,7 @@
1 <template>
2 <button class="fullscreen-switch" alt="fullscreen-switch" aria-label="fullscreen-switch" @click="toggleFullscreen">
3 - <Icon v-if="isFullscreen" :size="20" :name="CloseIcon"></Icon>
4 - <Icon v-else :size="20" :name="OpenIcon"></Icon>
3 + <Icon v-if="isFullscreen" :size="20" :name="CloseIcon" />
4 + <Icon v-else :size="20" :name="OpenIcon" />
5 </button>
6 </template>
7
frontend/src/app-layouts/common/Toolbar/LocaleSwitch.vue renamed
+1 -1
@@ -1,6 +1,6 @@
1 <template>
2 <n-popselect v-model:value="currentLocale" :options="list" :render-label="renderLabel">
3 - <Icon :size="19" :name="MultiLanguageIcon"></Icon>
3 + <Icon :size="19" :name="MultiLanguageIcon" />
4 </n-popselect>
5 </template>
6
frontend/src/app-layouts/common/Toolbar/Notifications.vue renamed
+1 -1
@@ -2,7 +2,7 @@
2 <n-popover :show-arrow="false" placement="bottom" content-class="!p-0 w-72">
3 <template #trigger>
4 <n-badge :show="hasUnread" dot :color="primaryColor">
5 - <Icon :name="BellIcon" :size="21" class="trigger-icon"></Icon>
5 + <Icon :name="BellIcon" :size="21" class="trigger-icon" />
6 </n-badge>
7 </template>
8 <template #header>
frontend/src/app-layouts/common/Toolbar/PinnedPages.vue renamed
+46 -26
@@ -1,28 +1,20 @@
1 <template>
2 - <div class="pinned-pages flex items-center gap-5 relative overflow-hidden py-2 justify-end w-full">
3 - <TransitionGroup name="anim" tag="div" class="flex items-center gap-4 overflow-hidden latest-list">
2 + <div class="flex pinned-pages items-center gap-5">
3 + <TransitionGroup name="anim" tag="div" class="latest-list flex items-center gap-4 overflow-hidden">
4 <n-tag
5 v-for="page of latestSanitized"
6 :key="page.name"
7 round
8 :bordered="false"
9 :closable="false"
10 - class="bg-transparent flex-shrink overflow-hidden p-0 transition-all duration-300"
10 @close="removeLatestPage(page.name)"
11 >
13 - <span
14 - :title="page.title"
15 - class="cursor-pointer ml-0.5 overflow-hidden text-ellipsis hover:underline hover:decoration-2 hover:decoration-[var(--primary-color)]"
16 - @click="gotoPage(page.name)"
17 - >
12 + <span class="page-name" :title="page.title" @click="gotoPage(page.name)">
13 {{ page.title }}
14 </span>
15 <template #icon>
21 - <div
22 - class="cursor-pointer transition-colors duration-300 mr-0.5 hover:text-[var(--primary-color)]"
23 - @click="pinPage(page)"
24 - >
25 - <Icon :size="14" :name="PinnedIcon"></Icon>
16 + <div class="icon-box" @click="pinPage(page)">
17 + <Icon :size="14" :name="PinnedIcon" />
18 </div>
19 </template>
20 </n-tag>
@@ -33,7 +25,7 @@
25 <n-popover :show-arrow="false" placement="bottom-end" trigger="hover" class="!p-1">
26 <template #trigger>
27 <n-button size="small" class="!h-8">
36 - <span class="flex items-center gap-3">
28 + <span class="flex items-center gap-2">
29 Shortcuts
30 <n-badge :value="pinned.length" :color="style['divider-030-color']" />
31 </span>
@@ -48,15 +40,17 @@
40 class="!justify-start"
41 @click="gotoPage(page.name)"
42 >
51 - <template #icon>
43 + <span class="flex items-center gap-1">
44 <Icon
45 :size="20"
46 :name="CloseIcon"
47 class="opacity-50 hover:text-red-500 hover:opacity-100"
48 @click.stop="removePinnedPage(page.name)"
57 - ></Icon>
58 - </template>
59 - {{ page.title }}
49 + />
50 + <span class="px-2">
51 + {{ page.title }}
52 + </span>
53 + </span>
54 </n-button>
55 </div>
56 </n-popover>
@@ -89,6 +83,12 @@ const themeStore = useThemeStore()
83 const style = computed(() => themeStore.style)
84 const latest: RemovableRef<Page[]> = useStorage<Page[]>("latest-pages", [], sessionStorage)
85 const pinned: RemovableRef<Page[]> = useStorage<Page[]>("pinned-pages", [], localStorage)
86 +const latestSanitized: ComputedRef<Page[]> = computed(() => {
87 + return _takeRight(
88 + latest.value.filter(page => pinned.value.findIndex(p => p.name === page.name) === -1).reverse(),
89 + 3
90 + ) as Page[]
91 +})
92
93 function removeLatestPage(pageName: RouteRecordName | string) {
94 latest.value = latest.value.filter(page => page.name !== pageName)
@@ -111,13 +111,6 @@ function pinPage(page: Page) {
111 return true
112 }
113
114 -const latestSanitized: ComputedRef<Page[]> = computed(() => {
115 - return _takeRight(
116 - latest.value.filter(page => pinned.value.findIndex(p => p.name === page.name) === -1).reverse(),
117 - 3
118 - ) as Page[]
119 -})
120 -
114 function checkRoute(route: RouteLocationNormalized) {
115 const title = route.meta?.title || _split(route.name?.toString(), "-").at(-1)
116
@@ -138,16 +131,22 @@ router.afterEach(route => {
131
132 <style lang="scss" scoped>
133 .pinned-pages {
134 + position: relative;
135 + overflow: hidden;
136 + padding: 8px 0;
137 container-type: inline-size;
138 + justify-content: flex-end;
139 + width: 100%;
140
141 :deep() {
142 .n-tag {
143 background-color: transparent;
144 flex-shrink: 1;
145 overflow: hidden;
146 + gap: 4px;
147
148 &.n-tag--round {
150 - padding: 0;
149 + padding: 0 !important;
150 transition: all 0.3s;
151 }
152 .n-tag__icon {
@@ -182,6 +181,27 @@ router.afterEach(route => {
181 }
182 }
183
184 + .page-name {
185 + cursor: pointer;
186 + overflow: hidden;
187 + text-overflow: ellipsis;
188 +
189 + &:hover {
190 + text-decoration: underline;
191 + text-decoration-thickness: 2px;
192 + text-decoration-color: var(--primary-color);
193 + }
194 + }
195 +
196 + .icon-box {
197 + cursor: pointer;
198 + transition: color 0.3s;
199 +
200 + &:hover {
201 + color: var(--primary-color);
202 + }
203 + }
204 +
205 .anim-move,
206 .anim-enter-active,
207 .anim-leave-active {
frontend/src/app-layouts/common/Toolbar/Search.vue renamed
+1 -1
@@ -1,6 +1,6 @@
1 <template>
2 <div class="flex items-center search-btn" @click="openBox">
3 - <Icon :name="SearchIcon" :size="16" class="search-btn-icon"></Icon>
3 + <Icon :name="SearchIcon" :size="16" class="search-btn-icon" />
4 <span>Search</span>
5 <n-text code class="search-command">
6 <span :class="{ win: commandIcon === 'CTRL' }">{{ commandIcon }}</span>
frontend/src/app-layouts/common/Toolbar/ThemeSwitch.vue renamed
+6 -6
@@ -2,12 +2,12 @@
2 <button class="theme-switch" alt="theme-switch" aria-label="theme-switch" @click="toggleTheme">
3 <Transition name="rotate">
4 <Icon v-if="isThemeDark" :size="20">
5 - <Iconify :icon="Sunny" class="hover"></Iconify>
6 - <Iconify :icon="SunnyOutline"></Iconify>
5 + <Iconify :icon="Sunny" class="hover" />
6 + <Iconify :icon="SunnyOutline" />
7 </Icon>
8 <Icon v-else :size="20">
9 - <Iconify :icon="Moon" class="hover"></Iconify>
10 - <Iconify :icon="MoonOutline"></Iconify>
9 + <Iconify :icon="Moon" class="hover" />
10 + <Iconify :icon="MoonOutline" />
11 </Icon>
12 </Transition>
13 </button>
@@ -29,8 +29,8 @@ const isThemeDark = computed<boolean>(() => themeStore.isThemeDark)
29 function toggleTheme(event?: MouseEvent) {
30 const isAppearanceTransition =
31 typeof document !== "undefined" &&
32 - document?.startViewTransition &&
33 - !window?.matchMedia("(prefers-reduced-motion: reduce)").matches
32 + document.startViewTransition &&
33 + !window.matchMedia("(prefers-reduced-motion: reduce)").matches
34
35 if (!isAppearanceTransition || !event) {
36 themeStore.toggleTheme()
frontend/src/app-layouts/common/Toolbar/index.vue renamed
+1 -1
@@ -3,7 +3,7 @@
3 <div class="wrap flex items-center justify-end gap-3">
4 <div class="logo-box flex items-center gap-2 cursor-pointer" @click="openNav()">
5 <Logo mini />
6 - <Icon :size="20" name="carbon:chevron-right"></Icon>
6 + <Icon :size="20" name="carbon:chevron-right" />
7 </div>
8
9 <Breadcrumb class="grow" />
frontend/src/app-layouts/common/rtlProvider.ts renamed
frontend/src/assets/scss/naive-override.scss
+19 -7
@@ -19,32 +19,43 @@
19 }
20 }
21
22 -.n-image-preview-overlay {
23 - backdrop-filter: blur(3px);
24 -}
25 -.n-image-preview-toolbar {
26 - box-sizing: content-box;
27 -
28 - * {
22 +.n-image-preview-container {
23 + .n-image-preview-overlay {
24 + backdrop-filter: blur(3px);
25 + }
26 + .n-image-preview-toolbar {
27 box-sizing: content-box;
28 +
29 + * {
30 + box-sizing: content-box;
31 + }
32 +
33 + & > i {
34 + font-size: clamp(18px, 5.5vw, 28px);
35 + }
36 }
37 }
38 +
39 .n-slider {
40 box-sizing: content-box;
41 }
42 +
43 .n-calendar * {
44 box-sizing: content-box;
45 }
46 +
47 .n-badge {
48 .n-badge-sup {
49 top: inherit;
50 }
51 }
52 +
53 .n-dropdown-menu {
54 &.n-dropdown-menu--scrollable {
55 max-height: 60vh;
56 }
57 }
58 +
59 .n-card {
60 & > .n-card-header {
61 div.n-card-header__main {
@@ -56,6 +67,7 @@
67 max-height: 100%;
68 }
69 }
70 +
71 .n-avatar .n-avatar__text {
72 transform: translateX(-50%) translateY(-50%) scale(1);
73 }
frontend/src/components/auth/AuthForm.vue
+1 -1
@@ -32,7 +32,7 @@
32
33 <script lang="ts" setup>
34 import type { FormType } from "./types.d"
35 -import Logo from "@/layouts/common/Logo.vue"
35 +import Logo from "@/app-layouts/common/Logo.vue"
36 import { useThemeStore } from "@/stores/theme"
37 import { NButton } from "naive-ui"
38 import { computed, onBeforeMount, ref } from "vue"
frontend/src/components/common/CardStatsBars.vue new
+221
@@ -0,0 +1,221 @@
1 +<template>
2 + <n-card content-style="padding:0" :class="{ hovered }">
3 + <div class="flex flex-col overflow-hidden">
4 + <div class="card-header flex gap-4 items-center justify-between">
5 + <div class="title flex items-center gap-2 grow">
6 + <span class="truncate">{{ title }}</span>
7 + <Icon v-if="hovered" :name="ArrowRightIcon" :size="12"></Icon>
8 + </div>
9 + <div class="icon">
10 + <slot name="icon"></slot>
11 + </div>
12 + </div>
13 + <div class="flex flex-col gap-3 card-content">
14 + <div class="bars flex">
15 + <div
16 + v-for="item of barValues"
17 + :key="JSON.stringify(item)"
18 + :class="item.status"
19 + class="bar"
20 + :style="{ width: `${item.percentage}%` }"
21 + >
22 + <div class="fill"></div>
23 + </div>
24 + </div>
25 + <div class="list flex flex-col">
26 + <div
27 + v-for="item of sanitizedValues"
28 + :key="JSON.stringify(item)"
29 + class="flex items-center item gap-3"
30 + :class="item.status"
31 + >
32 + <div class="label flex gap-2 items-center truncate">
33 + <span class="badge"></span>
34 + <span class="font-mono truncate">{{ item.label }}</span>
35 + </div>
36 + <div class="divider grow"></div>
37 + <div class="value flex gap-3 font-mono whitespace-nowrap">
38 + <span v-if="!item.isTotal" class="opacity-50">{{ item.percentage }}%</span>
39 + <strong>{{ item.value }}</strong>
40 + </div>
41 + </div>
42 + </div>
43 + </div>
44 + </div>
45 + </n-card>
46 +</template>
47 +
48 +<script setup lang="ts">
49 +import Icon from "@/components/common/Icon.vue"
50 +import _round from "lodash/round"
51 +import { NCard } from "naive-ui"
52 +import { computed, toRefs } from "vue"
53 +
54 +export interface ItemProps {
55 + value: number
56 + label: string
57 + isTotal?: boolean
58 + status?: "success" | "warning" | "error" | "muted" | "primary"
59 +}
60 +
61 +interface ItemPropsExt extends ItemProps {
62 + percentage: number
63 +}
64 +
65 +const props = defineProps<{
66 + title: string
67 + values: ItemProps[]
68 + showZeroItems?: boolean
69 + hovered?: boolean
70 +}>()
71 +const { title, values, showZeroItems, hovered } = toRefs(props)
72 +
73 +const ArrowRightIcon = "carbon:arrow-right"
74 +const totItem = computed(
75 + () =>
76 + values.value.find(item => item.isTotal) || {
77 + value: values.value.reduce((acc, cur) => {
78 + return acc + cur.value
79 + }, 0),
80 + isTotal: true,
81 + label: "Total"
82 + }
83 +)
84 +
85 +const sanitizedValues = computed<ItemPropsExt[]>(() => {
86 + const list: ItemPropsExt[] = values.value
87 + .filter(o => !o.isTotal)
88 + .map(o => ({ ...o, percentage: _round((o.value / totItem.value.value) * 100, 2) }))
89 + .filter(o => o.value || (!o.value && showZeroItems.value))
90 +
91 + return [{ ...totItem.value, percentage: 100 }, ...list]
92 +})
93 +
94 +const barValues = computed<ItemPropsExt[]>(() => sanitizedValues.value.filter(o => !o.isTotal && o.percentage))
95 +</script>
96 +
97 +<style scoped lang="scss">
98 +.n-card {
99 + overflow: hidden;
100 +
101 + .card-header {
102 + border-bottom: var(--border-small-050);
103 + overflow: hidden;
104 + padding: 10px 16px;
105 +
106 + .title {
107 + font-size: 16px;
108 + text-overflow: ellipsis;
109 + white-space: nowrap;
110 + overflow: hidden;
111 + }
112 + }
113 +
114 + .card-content {
115 + padding: 10px 16px;
116 +
117 + .bars {
118 + height: 10px;
119 +
120 + .bar {
121 + padding: 0 2px;
122 +
123 + &:first-child {
124 + padding-left: 0;
125 + }
126 + &:last-child {
127 + padding-right: 0;
128 + }
129 +
130 + .fill {
131 + border-radius: var(--border-radius-small);
132 + background-color: var(--fg-color);
133 + height: 100%;
134 + width: 100%;
135 + }
136 +
137 + &.success {
138 + .fill {
139 + background-color: var(--success-color);
140 + }
141 + }
142 + &.warning {
143 + .fill {
144 + background-color: var(--warning-color);
145 + }
146 + }
147 + &.error {
148 + .fill {
149 + background-color: var(--error-color);
150 + }
151 + }
152 + &.muted {
153 + .fill {
154 + background-color: var(--fg-secondary-color);
155 + }
156 + }
157 + &.primary {
158 + .fill {
159 + background-color: var(--primary-color);
160 + }
161 + }
162 + }
163 + }
164 +
165 + .list {
166 + font-size: 13px;
167 + gap: 4px;
168 +
169 + .item {
170 + line-height: 1;
171 + padding: 3px 4px;
172 +
173 + .badge {
174 + height: 10px;
175 + width: 10px;
176 + min-width: 10px;
177 + border-radius: var(--border-radius-small);
178 + background-color: var(--fg-color);
179 + }
180 +
181 + .divider {
182 + height: 1px;
183 + background-color: var(--hover-010-color);
184 + }
185 +
186 + &.success {
187 + .badge {
188 + background-color: var(--success-color);
189 + }
190 + }
191 + &.warning {
192 + .badge {
193 + background-color: var(--warning-color);
194 + }
195 + }
196 + &.error {
197 + .badge {
198 + background-color: var(--error-color);
199 + }
200 + }
201 + &.muted {
202 + .badge {
203 + background-color: var(--fg-secondary-color);
204 + }
205 + }
206 + &.primary {
207 + .badge {
208 + background-color: var(--primary-color);
209 + }
210 + }
211 + }
212 + }
213 + }
214 +
215 + &.hovered {
216 + &:hover {
217 + border-color: var(--primary-color);
218 + }
219 + }
220 +}
221 +</style>
frontend/src/components/common/CardStatsMulti.vue renamed
+23 -25
@@ -1,30 +1,27 @@
1 <template>
2 <n-card content-style="padding:0" :class="{ hovered }">
3 - <div class="flex flex-col overflow-hidden">
3 + <div class="flex flex-col overflow-hidden h-full">
4 <div class="card-header flex gap-4 items-center justify-between">
5 - <div class="title flex items-center gap-2">
6 - {{ title }}
5 + <div class="title flex items-center gap-2 grow">
6 + <span class="truncate">{{ title }}</span>
7 <Icon v-if="hovered" :name="ArrowRightIcon" :size="12"></Icon>
8 </div>
9 <div class="icon">
10 <slot name="icon"></slot>
11 </div>
12 </div>
13 - <div class="flex card-content">
14 - <div class="flex flex-col basis-1/2 value-box" :class="firstStatus">
15 - <div class="value">
16 - {{ value }}
13 + <div class="flex card-content grow">
14 + <div
15 + v-for="item of values"
16 + :key="JSON.stringify(item)"
17 + class="flex flex-col value-box"
18 + :class="[item.status, values.length !== 1 ? `basis-1/${values.length}` : 'grow']"
19 + >
20 + <div class="value grow flex justify-center items-center">
21 + {{ item.value }}
22 </div>
18 - <div v-if="firstLabel" class="label">
19 - {{ firstLabel }}
20 - </div>
21 - </div>
22 - <div class="flex flex-col basis-1/2 value-box" :class="secondStatus">
23 - <div class="value">
24 - {{ subValue }}
25 - </div>
26 - <div v-if="secondLabel" class="label">
27 - {{ secondLabel }}
23 + <div v-if="item.label" class="label">
24 + {{ item.label }}
25 </div>
26 </div>
27 </div>
@@ -37,17 +34,18 @@ import Icon from "@/components/common/Icon.vue"
34 import { NCard } from "naive-ui"
35 import { toRefs } from "vue"
36
37 +export interface ItemProps {
38 + value: number | string
39 + label?: string
40 + status?: "success" | "warning" | "error"
41 +}
42 +
43 const props = defineProps<{
44 title: string
42 - value?: number | string
43 - subValue?: number | string
44 - firstLabel?: string
45 - secondLabel?: string
46 - firstStatus?: "success" | "warning" | "error"
47 - secondStatus?: "success" | "warning" | "error"
45 + values: ItemProps[]
46 hovered?: boolean
47 }>()
50 -const { title, value, subValue, firstLabel, secondLabel, firstStatus, secondStatus, hovered } = toRefs(props)
48 +const { title, values, hovered } = toRefs(props)
49
50 const ArrowRightIcon = "carbon:arrow-right"
51 </script>
@@ -74,7 +72,7 @@ const ArrowRightIcon = "carbon:arrow-right"
72 text-align: center;
73 overflow: hidden;
74
77 - &:first-child {
75 + &:not(:last-child) {
76 border-right: var(--border-small-050);
77 }
78
frontend/src/components/common/FileDrop.vue deleted
-54
@@ -1,54 +0,0 @@
1 -<template>
2 - <form class="file-drop">
3 - <label>
4 - <slot />
5 - <input type="file" :multiple="multiple" :accept @change="onChange" />
6 - </label>
7 - </form>
8 -</template>
9 -
10 -<script lang="ts" setup>
11 -import { toRefs } from "vue"
12 -
13 -const props = withDefaults(
14 - defineProps<{
15 - accept: string
16 - multiple: boolean
17 - }>(),
18 - { accept: ".jpg,.jpeg,.png,.webp", multiple: false }
19 -)
20 -const emit = defineEmits<{
21 - (e: "change-file", value: FileList | File | null): void
22 -}>()
23 -
24 -const { accept, multiple } = toRefs(props)
25 -
26 -function onChange(event: Event) {
27 - const input = event.target as HTMLInputElement
28 - if (multiple.value) {
29 - emit("change-file", input?.files)
30 - } else {
31 - if (input?.files?.length) {
32 - emit("change-file", input?.files[0])
33 - }
34 - }
35 - input?.form?.reset()
36 -}
37 -</script>
38 -
39 -<style lang="scss" scoped>
40 -.file-drop {
41 - label {
42 - display: flex;
43 - align-items: center;
44 - justify-content: center;
45 - width: 100%;
46 - height: 100%;
47 - cursor: pointer;
48 -
49 - input {
50 - display: none;
51 - }
52 - }
53 -}
54 -</style>
frontend/src/components/common/ImageLoader.vue deleted
-109
@@ -1,109 +0,0 @@
1 -<template>
2 - <img
3 - v-if="isImageError && fallback"
4 - :src="fallback"
5 - class="image-fallback"
6 - draggable="false"
7 - :class="imageClass"
8 - @load="imageFallback"
9 - />
10 - <img
11 - v-if="!isImageError"
12 - :src="mainSrc"
13 - draggable="false"
14 - class="image-loading"
15 - :class="imageClass"
16 - @load="imageLoading"
17 - />
18 -</template>
19 -
20 -<script setup lang="ts">
21 -import { ref, watch } from "vue"
22 -
23 -export interface ImageEvent {
24 - height: number
25 -}
26 -export interface ImageLoadEvent extends Event {
27 - path?: HTMLElement[]
28 -}
29 -
30 -const props = defineProps({
31 - src: {
32 - type: String,
33 - required: true
34 - },
35 - fallback: {
36 - type: String
37 - },
38 - loading: {
39 - type: String
40 - },
41 - imageClass: {
42 - type: String,
43 - default: ""
44 - }
45 -})
46 -
47 -const emit = defineEmits(["image-error", "image-loading", "image-loaded", "image-fallback"])
48 -
49 -const isImageLoaded = ref(false)
50 -const isImageError = ref(false)
51 -const mainSrc = ref(props.loading)
52 -
53 -function imageLoading(e: ImageLoadEvent) {
54 - const elPath: HTMLElement | undefined = e.path && e.path[0]
55 - const el = (e.target || elPath || null) as HTMLImageElement | null
56 -
57 - emit("image-loading", { height: el?.offsetHeight || 0 } as ImageEvent)
58 - return e
59 -}
60 -function imageFallback(e: ImageLoadEvent) {
61 - const elPath: HTMLElement | undefined = e.path && e.path[0]
62 - const el = (e.target || elPath || null) as HTMLImageElement | null
63 -
64 - emit("image-fallback", { height: el?.offsetHeight || 0 } as ImageEvent)
65 - return e
66 -}
67 -function imageLoaded(e: ImageLoadEvent) {
68 - mainSrc.value = props.src
69 - const elPath: HTMLElement | undefined = e.path && e.path[0]
70 - const el = (e.target || elPath || null) as HTMLImageElement | null
71 - isImageLoaded.value = true
72 -
73 - emit("image-loaded", { height: el?.offsetHeight || 0 } as ImageEvent)
74 -}
75 -function imageError() {
76 - isImageError.value = true
77 - emit("image-error")
78 -}
79 -
80 -function createLoader() {
81 - const img = new Image()
82 - img.onload = imageLoaded
83 - img.onerror = imageError
84 - img.src = props.src
85 -}
86 -
87 -watch(
88 - () => props.src,
89 - () => {
90 - createLoader()
91 - }
92 -)
93 -
94 -createLoader()
95 -</script>
96 -
97 -<style lang="scss" scoped>
98 -img {
99 - opacity: 1;
100 - display: block;
101 - transition: opacity 0.8s;
102 -
103 - &.hide {
104 - opacity: 0;
105 - max-height: 0;
106 - //transform: scale(0);
107 - }
108 -}
109 -</style>
frontend/src/components/common/SearchDialog.vue
+32 -45
@@ -12,9 +12,7 @@
12 <n-scrollbar ref="scrollContent" class="!h-96">
13 <div class="conten-wrap">
14 <div v-for="group of filteredGroups" :key="group.name" class="group">
15 - <div class="group-title">
16 - {{ group.name }}
17 - </div>
15 + <div class="group-title">{{ group.name }}</div>
16 <div class="group-list">
17 <button
18 v-for="item of group.items"
@@ -25,7 +23,13 @@
23 @click="callAction(item.action)"
24 >
25 <div class="icon">
28 - <n-avatar v-if="item.iconImage" round :size="28" :src="item.iconImage" />
26 + <n-avatar
27 + v-if="item.iconImage"
28 + round
29 + :size="28"
30 + :src="item.iconImage"
31 + :img-props="{ alt: 'avatar' }"
32 + />
33 <Icon v-if="item.iconName" :name="item.iconName" :size="16" />
34 </div>
35 <div class="title grow">
@@ -36,9 +40,7 @@
40 :text-to-highlight="item.title"
41 />
42 </div>
39 - <div class="label">
40 - {{ item.label }}
41 - </div>
43 + <div class="label">{{ item.label }}</div>
44 </button>
45 </div>
46 </div>
@@ -86,7 +88,7 @@ interface GroupItem {
88 key: number | string
89 title: string
90 label: string
89 - tags?: string
91 + tags?: string[]
92 action: () => void
93 }
94
@@ -190,53 +192,32 @@ const groups = ref<Groups>([
192 ])
193
194 const keywords = computed<string[]>(() => {
193 - if (search.value.length > 1) {
194 - return search.value.split(" ").filter(k => k)
195 - } else {
196 - return []
197 - }
195 + return search.value.length > 1 ? search.value.split(" ").filter(k => k) : []
196 })
197 +
198 const filteredGroups = computed<Groups>(() => {
200 - if (keywords.value.length === 0) {
201 - return groups.value
202 - }
203 - const newGroups: Groups = []
204 - for (const group of groups.value) {
205 - const items = group.items.filter(item => {
206 - if (keywords.value.filter(k => item.title.toLowerCase().includes(k.toLowerCase())).length !== 0) {
207 - return true
208 - }
209 - if (
210 - item.tags &&
211 - keywords.value.filter(k => item.tags?.toLowerCase().indexOf(k.toLowerCase()) !== -1).length !== 0
212 - ) {
213 - return true
214 - }
215 - return false
216 - })
217 - if (items.length) {
218 - newGroups.push({
219 - name: group.name,
220 - items
221 - })
222 - }
223 - }
224 - return newGroups
199 + if (!keywords.value.length) return groups.value
200 +
201 + return groups.value
202 + .map(group => ({
203 + name: group.name,
204 + items: group.items.filter(
205 + item =>
206 + keywords.value.some(k => item.title.toLowerCase().includes(k.toLowerCase())) ||
207 + item.tags?.some(t => keywords.value.some(k => t.toLowerCase().includes(k.toLowerCase())))
208 + )
209 + }))
210 + .filter(group => group.items.length)
211 })
212
213 const filteredFlattenItems = computed<GroupItem[]>(() => {
228 - const items = []
229 -
230 - for (const group of filteredGroups.value) {
231 - items.push(...group.items)
232 - }
233 -
234 - return items
214 + return filteredGroups.value.reduce((acc, group) => [...acc, ...group.items], [] as GroupItem[])
215 })
216
217 function openBox(e?: MouseEvent) {
218 if (!showSearchBox.value) {
219 showSearchBox.value = true
220 +
221 setTimeout(() => {
222 search.value = ""
223 activeItem.value = null
@@ -244,15 +225,18 @@ function openBox(e?: MouseEvent) {
225 }
226 return e
227 }
228 +
229 function closeBox() {
230 showSearchBox.value = false
231 search.value = ""
232 activeItem.value = null
233 }
234 +
235 function callAction(action: () => void) {
236 action()
237 closeBox()
238 }
239 +
240 function nextItem() {
241 const currentIndex = filteredFlattenItems.value.findIndex(item => item.key === activeItem.value)
242 if (currentIndex === filteredFlattenItems.value.length - 1 || activeItem.value === null) {
@@ -262,6 +246,7 @@ function nextItem() {
246 }
247 centerItem()
248 }
249 +
250 function prevItem() {
251 const currentIndex = filteredFlattenItems.value.findIndex(item => item.key === activeItem.value)
252 if (currentIndex === 0 || activeItem.value === null) {
@@ -271,12 +256,14 @@ function prevItem() {
256 }
257 centerItem()
258 }
259 +
260 function performAction() {
261 const item = filteredFlattenItems.value.find(item => item.key === activeItem.value)
262 if (item) {
263 callAction(item.action)
264 }
265 }
266 +
267 function centerItem() {
268 const element = document.getElementById(activeItem.value?.toString() || "")
269 if (element && scrollContent.value) {
frontend/src/components/common/SegmentedPage.vue
+42 -42
@@ -2,15 +2,16 @@
2 <n-split
3 ref="splitPane"
4 direction="horizontal"
5 - :default-size="splitDefault"
5 + :default-size="sanitizedDefaultSplit"
6 :min="0"
7 :max="1"
8 :resize-trigger-size="0"
9 :disabled="!enableResize || splitDisabled"
10 class="wrapper flex grow"
11 :class="[{ 'sidebar-open': sidebarOpen }, `sidebar-position-${sidebarPosition}`]"
12 + :pane1-style="pane1Style"
13 >
13 - <template #1>
14 + <template #[tplNameSide]>
15 <div v-if="sidebarAvailable" ref="sidebar" class="sidebar flex flex-col">
16 <div v-if="$slots['sidebar-header']" class="sidebar-header flex items-center">
17 <slot name="sidebar-header" />
@@ -36,7 +37,7 @@
37 </div>
38 </template>
39
39 - <template #2>
40 + <template #[tplNameMain]>
41 <div class="main flex-grow flex flex-col">
42 <div v-if="$slots['main-toolbar']" class="main-toolbar flex items-center">
43 <div v-if="sidebarAvailable && !hideMenuBtn" class="menu-btn flex justify-center opacity-50">
@@ -96,8 +97,11 @@ const props = withDefaults(
97 sidebarContentClass?: string
98 enableResize?: boolean
99 disableContainerQuery?: boolean
100 + defaultSplit?: number
101 + maxSidebarWidth?: number
102 + minSidebarWidth?: number
103 }>(),
100 - { sidebarPosition: "left", useMainScroll: true }
104 + { sidebarPosition: "left", useMainScroll: true, defaultSplit: 0.3, maxSidebarWidth: 450, minSidebarWidth: 250 }
105 )
106
107 const emit = defineEmits<{
@@ -112,25 +116,36 @@ const {
116 mainContentStyle,
117 mainContentClass,
118 sidebarContentStyle,
115 - sidebarContentClass
119 + sidebarContentClass,
120 + enableResize,
121 + disableContainerQuery,
122 + defaultSplit,
123 + maxSidebarWidth,
124 + minSidebarWidth
125 } = toRefs(props)
126
127 const MenuIcon = "ph:list-light"
128 const SplitIcon = "carbon:draggable"
129
130 const splitPane = ref()
122 -const splitDefault = ref(0.3)
131 +const sanitizedDefaultSplit = ref(defaultSplit.value)
132 const splitDisabled = ref(false)
133
134 const slots = useSlots()
135 const sidebarOpen = ref(false)
136 const sidebar = ref(null)
137 const mainScrollbar = ref<typeof NScrollbar | null>(null)
138 +const { width } = useWindowSize()
139 const sidebarAvailable = computed(
140 () => !!slots["sidebar-header"] || !!slots["sidebar-content"] || !!slots["sidebar-footer"]
141 )
132 -
133 -onClickOutside(sidebar, () => closeSidebar())
142 +const isSidebarLeft = computed<boolean>(() => sidebarPosition.value === "left")
143 +const tplNameMain = computed<1 | 2>(() => (isSidebarLeft.value ? 2 : 1))
144 +const tplNameSide = computed<1 | 2>(() => (isSidebarLeft.value ? 1 : 2))
145 +const pane1Style = computed(() => ({
146 + maxWidth: isSidebarLeft.value ? `${maxSidebarWidth.value}px` : `calc(100% - ${minSidebarWidth.value}px)`,
147 + minWidth: isSidebarLeft.value ? `${minSidebarWidth.value}px` : `calc(100% - ${maxSidebarWidth.value}px)`
148 +}))
149
150 function closeSidebar() {
151 sidebarOpen.value = false
@@ -140,6 +155,8 @@ function openSidebar() {
155 sidebarOpen.value = true
156 }
157
158 +onClickOutside(sidebar, () => closeSidebar())
159 +
160 watch(
161 sidebarOpen,
162 val => {
@@ -148,12 +165,10 @@ watch(
165 { immediate: true }
166 )
167
151 -const { width } = useWindowSize()
152 -
168 watch(
169 width,
170 val => {
156 - splitDefault.value = val <= 700 ? 0 : 0.3
171 + sanitizedDefaultSplit.value = val <= 700 ? 0 : isSidebarLeft.value ? defaultSplit.value : 1 - defaultSplit.value
172 splitDisabled.value = val <= 700
173 },
174 { immediate: true }
@@ -179,18 +194,6 @@ onMounted(() => {
194 background-color: var(--bg-color);
195 direction: ltr;
196
182 - :deep() {
183 - .n-split-pane-1,
184 - .n-split-pane-2 {
185 - overflow: hidden;
186 - height: 100%;
187 - }
188 - .n-split-pane-1 {
189 - min-width: 250px;
190 - max-width: min(450px, calc(100% - 400px));
191 - }
192 - }
193 -
197 .split-trigger {
198 height: 100%;
199 width: 3px;
@@ -225,9 +228,6 @@ onMounted(() => {
228
229 .sidebar {
230 background-color: var(--bg-secondary-color);
228 - min-width: 250px;
229 - //max-width: calc(100% - 400px);
230 - //width: 35%;
231 height: 100%;
232 overflow: hidden;
233 border-right: 1px solid var(--border-color);
@@ -307,15 +307,6 @@ onMounted(() => {
307 }
308 }
309
310 - &.sidebar-position-right {
311 - flex-direction: row-reverse;
312 -
313 - .sidebar {
314 - border-right: none;
315 - border-left: 1px solid var(--border-color);
316 - }
317 - }
318 -
310 @media (max-width: 700px) {
311 --mb-toolbar-height: 62px;
312 height: 100%;
@@ -323,13 +314,6 @@ onMounted(() => {
314 border-radius: 0;
315 border: none;
316
326 - :deep() {
327 - .n-split-pane-1 {
328 - min-width: 0;
329 - max-width: 0;
330 - }
331 - }
332 -
317 &::before {
318 content: "";
319 width: 100vw;
@@ -399,7 +383,23 @@ onMounted(() => {
383 }
384 }
385
386 + &.sidebar-position-left {
387 + :deep() {
388 + .n-split-pane-1 {
389 + min-width: 0 !important;
390 + max-width: 0 !important;
391 + }
392 + }
393 + }
394 +
395 &.sidebar-position-right {
396 + :deep() {
397 + .n-split-pane-1 {
398 + min-width: 100% !important;
399 + max-width: 100% !important;
400 + }
401 + }
402 +
403 &::before,
404 .sidebar {
405 left: initial;
frontend/src/components/customers/provision/CustomerProvisionWizard.vue
+1 -1
@@ -563,7 +563,7 @@ function toggleDashboards() {
563 form.value.dashboards_to_include.dashboards = dashboardOptions.value
564 .filter(
565 o =>
566 - !["EDR_WAZUH_INVENOTRY", "EDR_WAZUH_INVENTORY", "EDR_AGENT_INVENTORY"]
566 + !["EDR_WAZUH_INVENTORY", "EDR_AGENT_INVENTORY"]
567 .map(d => d.toLowerCase())
568 .includes(o.value.toLowerCase())
569 )
frontend/src/components/graylog/MonitoringAlerts/CustomAlertForm.vue
+12 -1
@@ -214,11 +214,14 @@ const areAllCustomerFieldsUniques = computed(() => {
214 return uniques.length === form.value.custom_fields.length
215 })
216
217 -const isCustomerCodePresent = computed(() => {
217 +/** @deprecated */
218 +/*
219 + const isCustomerCodePresent = computed(() => {
220 const field = form.value.custom_fields.filter(o => o.name === "CUSTOMER_CODE" && !!o.value)
221
222 return !!field.length
223 })
224 +*/
225
226 const alertPriorityOptions: { label: string; value: CustomProvisionPriority }[] = [
227 { label: "Low", value: CustomProvisionPriority.LOW },
@@ -261,6 +264,7 @@ const rules: FormRules = {
264 },
265 custom_fields: {
266 required: true,
267 + // eslint-disable-next-line unused-imports/no-unused-vars
268 validator(rule: FormItemRule, value: string) {
269 if (!areAllCustomerFieldsFilled.value) {
270 return new Error(`Please fill all customer fields`)
@@ -270,9 +274,13 @@ const rules: FormRules = {
274 return new Error(`There are duplicated fields`)
275 }
276
277 + /** @deprecated */
278 + /*
279 if (!value.length || !isCustomerCodePresent.value) {
280 return new Error(`At least one custom field with name CUSTOMER_CODE is required`)
281 }
282 + */
283 +
284 return true
285 },
286 trigger: ["input", "blur"]
@@ -284,9 +292,12 @@ const isValid = computed(() => {
292 return false
293 }
294
295 + /** @deprecated */
296 + /*
297 if (!isCustomerCodePresent.value) {
298 return false
299 }
300 + */
301
302 if (!areAllCustomerFieldsUniques.value) {
303 return false
frontend/src/components/graylog/Pipelines/PipeList.vue
+5 -1
@@ -3,6 +3,7 @@
3 <n-card>
4 <n-spin :show="loading">
5 <n-collapse
6 + v-if="pipelines.length"
7 v-model:expanded-names="selectedPipeline"
8 accordion
9 :style="minHeight ? `min-height: ${minHeight}` : ''"
@@ -23,6 +24,9 @@
24 </div>
25 </n-collapse-item>
26 </n-collapse>
27 + <template v-else>
28 + <n-empty v-if="!loading" description="No pipelines found" class="justify-center h-32" />
29 + </template>
30 </n-spin>
31 </n-card>
32
@@ -47,7 +51,7 @@ import Icon from "@/components/common/Icon.vue"
51 import PipeDetails from "@/components/graylog/Pipelines/PipeDetails.vue"
52 import PipeInfo from "@/components/graylog/Pipelines/PipeInfo.vue"
53 import PipeTitle from "@/components/graylog/Pipelines/PipeTitle.vue"
50 -import { NButton, NCard, NCollapse, NCollapseItem, NModal, NSpin, useMessage } from "naive-ui"
54 +import { NButton, NCard, NCollapse, NCollapseItem, NEmpty, NModal, NSpin, useMessage } from "naive-ui"
55 import { onBeforeMount, ref, toRefs, watch } from "vue"
56
57 const props = defineProps<{
frontend/src/components/indices/ClusterHealth.vue
+4 -1
@@ -29,6 +29,9 @@
29 </div>
30 </n-scrollbar>
31 </div>
32 + <template v-else>
33 + <n-empty v-if="!loading" description="No cluster found" class="justify-center h-48" />
34 + </template>
35 </n-spin>
36 </n-card>
37 </template>
@@ -37,7 +40,7 @@
40 import type { ClusterHealth } from "@/types/indices.d"
41 import Api from "@/api"
42 import IndexIcon from "@/components/indices/IndexIcon.vue"
40 -import { NCard, NScrollbar, NSpin, useMessage } from "naive-ui"
43 +import { NCard, NEmpty, NScrollbar, NSpin, useMessage } from "naive-ui"
44 import { onBeforeMount, ref } from "vue"
45
46 const message = useMessage()
frontend/src/components/indices/Marquee.vue
+24 -12
@@ -1,8 +1,9 @@
1 <template>
2 <div class="indices-marquee">
3 - <n-card content-style="padding:0; " class="overflow-hidden">
4 - <n-spin :show="loading">
3 + <n-card content-class="!p-0" class="overflow-hidden">
4 + <n-spin :show="loading" content-class="h-12">
5 <Vue3Marquee
6 + v-if="list?.length"
7 class="marquee-wrap"
8 :duration="(list?.length || 0) * 1"
9 :pause-on-hover="true"
@@ -12,7 +13,7 @@
13 gradient-length="10%"
14 >
15 <span
15 - v-for="item in list"
16 + v-for="item of list"
17 :key="item.index"
18 class="item flex items-center gap-2"
19 :class="item.health"
@@ -23,6 +24,14 @@
24 {{ item.index }}
25 </span>
26 </Vue3Marquee>
27 + <template v-else>
28 + <n-empty
29 + v-if="!loading"
30 + class="h-full justify-center"
31 + description="No indices found"
32 + :show-icon="false"
33 + />
34 + </template>
35 </n-spin>
36 </n-card>
37 <div v-if="list?.length" class="info">
@@ -37,7 +46,7 @@ import type { IndexStats } from "@/types/indices.d"
46 import Api from "@/api"
47 import IndexIcon from "@/components/indices/IndexIcon.vue"
48 import { useThemeStore } from "@/stores/theme"
40 -import { NCard, NSpin, useMessage } from "naive-ui"
49 +import { NCard, NEmpty, NSpin, useMessage } from "naive-ui"
50 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
51 import { Vue3Marquee } from "vue3-marquee"
52
@@ -50,19 +59,15 @@ const emit = defineEmits<{
59 }>()
60
61 const { indices } = toRefs(props)
53 -
62 const list = ref(indices.value)
55 -
56 -watch(indices, val => {
57 - list.value = val
58 -})
59 -
63 const message = useMessage()
64 const style = computed(() => useThemeStore().style)
65 const gradientColor = computed(() => style.value["bg-color-rgb"].split(", "))
63 -const loading = computed(() => !list?.value || list.value === null)
66 +const loading = ref(false)
67
68 function getIndices() {
69 + loading.value = true
70 +
71 Api.indices
72 .getIndices()
73 .then(res => {
@@ -84,8 +89,15 @@ function getIndices() {
89 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
90 }
91 })
92 + .finally(() => {
93 + loading.value = false
94 + })
95 }
96
97 +watch(indices, val => {
98 + list.value = val
99 +})
100 +
101 onBeforeMount(() => {
102 if (indices.value === undefined) {
103 getIndices()
@@ -101,7 +113,7 @@ onBeforeMount(() => {
113 margin-top: 5px;
114 }
115 .marquee-wrap {
104 - height: 45px;
116 + height: 100%;
117 transform: translate3d(0, 0, 0);
118
119 :deep() {
frontend/src/components/indices/NodeAllocation.vue
+7 -2
@@ -3,7 +3,9 @@
3 <template #header>
4 <div class="flex align-center justify-between">
5 <span>Nodes Allocation</span>
6 - <span class="text-secondary-color font-mono">{{ indicesAllocation.length }}</span>
6 + <span v-if="indicesAllocation.length" class="text-secondary-color font-mono">
7 + {{ indicesAllocation.length }}
8 + </span>
9 </div>
10 </template>
11 <n-spin :show="loading">
@@ -59,6 +61,9 @@
61 </div>
62 </n-scrollbar>
63 </template>
64 + <template v-else>
65 + <n-empty v-if="!loading" description="No allocations found" class="justify-center h-48" />
66 + </template>
67 </div>
68 </n-spin>
69 </n-card>
@@ -67,7 +72,7 @@
72 <script setup lang="ts">
73 import type { IndexAllocation } from "@/types/indices.d"
74 import Api from "@/api"
70 -import { NCard, NProgress, NScrollbar, NSpin, useMessage } from "naive-ui"
75 +import { NCard, NEmpty, NProgress, NScrollbar, NSpin, useMessage } from "naive-ui"
76 import { nanoid } from "nanoid"
77 import { onBeforeMount, ref } from "vue"
78
frontend/src/components/overview/AgentsCard.vue
+7 -15
@@ -1,27 +1,17 @@
1 <template>
2 <n-spin :show="loading">
3 - <CardStatsDouble
4 - title="Agents"
5 - first-label="Total"
6 - hovered
7 - class="cursor-pointer"
8 - :value="total"
9 - second-label="Online"
10 - :sub-value="onlineTotal"
11 - :second-status="onlineTotal ? 'success' : undefined"
12 - @click="gotoAgent()"
13 - >
3 + <CardStatsMulti title="Agents" hovered class="cursor-pointer h-full" :values @click="gotoAgent()">
4 <template #icon>
5 <CardStatsIcon :icon-name="AgentsIcon" boxed :box-size="30"></CardStatsIcon>
6 </template>
17 - </CardStatsDouble>
7 + </CardStatsMulti>
8 </n-spin>
9 </template>
10
11 <script setup lang="ts">
12 import Api from "@/api"
23 -import CardStatsDouble from "@/components/common/CardStatsDouble.vue"
13 import CardStatsIcon from "@/components/common/CardStatsIcon.vue"
14 +import CardStatsMulti, { type ItemProps } from "@/components/common/CardStatsMulti.vue"
15 import { useGoto } from "@/composables/useGoto"
16 import { type Agent, AgentStatus } from "@/types/agents.d"
17 import { NSpin, useMessage } from "naive-ui"
@@ -32,14 +22,16 @@ const { gotoAgent } = useGoto()
22 const message = useMessage()
23 const loading = ref(false)
24 const agents = ref<Agent[]>([])
35 -
25 const total = computed<number>(() => {
26 return agents.value.length || 0
27 })
39 -
28 const onlineTotal = computed(() => {
29 return agents.value.filter(({ wazuh_agent_status }) => wazuh_agent_status === AgentStatus.Active).length || 0
30 })
31 +const values = computed<ItemProps[]>(() => [
32 + { value: total.value, label: "Total" },
33 + { value: onlineTotal.value, label: "Online", status: onlineTotal.value ? "success" : undefined }
34 +])
35
36 function getData() {
37 loading.value = true
frontend/src/components/overview/CustomersCard.vue
+6 -12
@@ -1,33 +1,27 @@
1 <template>
2 <n-spin :show="loading">
3 - <CardStats
3 + <CardStatsMulti
4 title="Customers"
5 - :value="total"
6 - :vertical="vertical"
5 hovered
6 class="cursor-pointer h-full"
7 + :values="[{ value: total, label: 'Total' }]"
8 @click="gotoCustomer()"
9 >
10 <template #icon>
12 - <CardStatsIcon :icon-name="CustomersIcon" boxed :box-size="40"></CardStatsIcon>
11 + <CardStatsIcon :icon-name="CustomersIcon" boxed :box-size="30"></CardStatsIcon>
12 </template>
14 - </CardStats>
13 + </CardStatsMulti>
14 </n-spin>
15 </template>
16
17 <script setup lang="ts">
18 import type { Customer } from "@/types/customers.d"
19 import Api from "@/api"
21 -import CardStats from "@/components/common/CardStats.vue"
20 import CardStatsIcon from "@/components/common/CardStatsIcon.vue"
21 +import CardStatsMulti from "@/components/common/CardStatsMulti.vue"
22 import { useGoto } from "@/composables/useGoto"
23 import { NSpin, useMessage } from "naive-ui"
25 -import { computed, onBeforeMount, ref, toRefs } from "vue"
26 -
27 -const props = defineProps<{
28 - vertical?: boolean
29 -}>()
30 -const { vertical } = toRefs(props)
24 +import { computed, onBeforeMount, ref } from "vue"
25
26 const CustomersIcon = "carbon:user-multiple"
27 const { gotoCustomer } = useGoto()
frontend/src/components/overview/HealthcheckCard.vue
+7 -16
@@ -1,16 +1,6 @@
1 <template>
2 <n-spin :show="loading">
3 - <CardStatsDouble
4 - title="Healthcheck"
5 - first-label="Total"
6 - :value="total"
7 - hovered
8 - class="cursor-pointer"
9 - second-label="Critical"
10 - :sub-value="criticalTotal"
11 - :second-status="criticalTotal ? 'warning' : undefined"
12 - @click="gotoHealthcheck()"
13 - >
3 + <CardStatsMulti title="Healthcheck" hovered class="cursor-pointer h-full" :values @click="gotoHealthcheck()">
4 <template #icon>
5 <CardStatsIcon
6 :icon-name="HealthcheckIcon"
@@ -19,14 +9,14 @@
9 :color="criticalTotal ? style['warning-color'] : undefined"
10 ></CardStatsIcon>
11 </template>
22 - </CardStatsDouble>
12 + </CardStatsMulti>
13 </n-spin>
14 </template>
15
16 <script setup lang="ts">
17 import Api from "@/api"
28 -import CardStatsDouble from "@/components/common/CardStatsDouble.vue"
18 import CardStatsIcon from "@/components/common/CardStatsIcon.vue"
19 +import CardStatsMulti, { type ItemProps } from "@/components/common/CardStatsMulti.vue"
20 import { useGoto } from "@/composables/useGoto"
21 import { useThemeStore } from "@/stores/theme"
22 import { type InfluxDBAlert, InfluxDBAlertLevel } from "@/types/healthchecks.d"
@@ -38,16 +28,17 @@ const { gotoHealthcheck } = useGoto()
28 const message = useMessage()
29 const loading = ref(false)
30 const healthcheck = ref<InfluxDBAlert[]>([])
41 -
31 const style = computed(() => useThemeStore().style)
43 -
32 const total = computed<number>(() => {
33 return healthcheck.value.length || 0
34 })
47 -
35 const criticalTotal = computed<number>(() => {
36 return healthcheck.value.filter(o => o.level === InfluxDBAlertLevel.Crit).length || 0
37 })
38 +const values = computed<ItemProps[]>(() => [
39 + { value: total.value, label: "Total" },
40 + { value: criticalTotal.value, label: "Critical", status: criticalTotal.value ? "warning" : undefined }
41 +])
42
43 function getData() {
44 loading.value = true
frontend/src/components/overview/IncidentAlerts.vue new
+80
@@ -0,0 +1,80 @@
1 +<template>
2 + <n-spin :show="loading">
3 + <CardStatsBars
4 + title="Alerts"
5 + hovered
6 + class="cursor-pointer h-full"
7 + :values
8 + @click="gotoIncidentManagementAlerts()"
9 + >
10 + <template #icon>
11 + <CardStatsIcon :icon-name="AlertsIcon" boxed :box-size="30"></CardStatsIcon>
12 + </template>
13 + </CardStatsBars>
14 + </n-spin>
15 +</template>
16 +
17 +<script setup lang="ts">
18 +import Api from "@/api"
19 +import CardStatsBars, { type ItemProps } from "@/components/common/CardStatsBars.vue"
20 +import CardStatsIcon from "@/components/common/CardStatsIcon.vue"
21 +import { useGoto } from "@/composables/useGoto"
22 +import { NSpin, useMessage } from "naive-ui"
23 +import { computed, onBeforeMount, ref } from "vue"
24 +
25 +const AlertsIcon = "carbon:warning-hex"
26 +const { gotoIncidentManagementAlerts } = useGoto()
27 +const message = useMessage()
28 +const loading = ref(false)
29 +const total = ref(0)
30 +const openedCount = ref(0)
31 +const inProgressCount = ref(0)
32 +const closedCount = ref(0)
33 +const values = computed<ItemProps[]>(() => [
34 + { value: total.value, label: "Total", isTotal: true },
35 + { value: openedCount.value, label: "Open", status: "error" },
36 + { value: inProgressCount.value, label: "In Progress", status: "warning" },
37 + { value: closedCount.value, label: "Closed", status: "success" }
38 +])
39 +
40 +function getData() {
41 + loading.value = true
42 +
43 + Api.incidentManagement
44 + .getAlertsList({
45 + page: 0,
46 + pageSize: 0
47 + })
48 + .then(res => {
49 + if (res.data.success) {
50 + total.value = res.data.total || 0
51 + closedCount.value = res.data.closed || 0
52 + inProgressCount.value = res.data.in_progress || 0
53 + openedCount.value = res.data.open || 0
54 + } else {
55 + message.warning(res.data?.message || "An error occurred. Please try again later.")
56 + }
57 + loading.value = false
58 + })
59 + .catch(err => {
60 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
61 + })
62 + .finally(() => {
63 + loading.value = false
64 + })
65 +}
66 +
67 +onBeforeMount(() => {
68 + getData()
69 +})
70 +</script>
71 +
72 +<style lang="scss" scoped>
73 +.n-spin-container {
74 + :deep() {
75 + .n-spin-content {
76 + height: 100%;
77 + }
78 + }
79 +}
80 +</style>
frontend/src/components/overview/IncidentCases.vue new
+90
@@ -0,0 +1,90 @@
1 +<template>
2 + <n-spin :show="loading">
3 + <CardStatsBars
4 + title="Cases"
5 + hovered
6 + class="cursor-pointer h-full"
7 + :values
8 + @click="gotoIncidentManagementCases()"
9 + >
10 + <template #icon>
11 + <CardStatsIcon :icon-name="CasesIcon" boxed :box-size="30"></CardStatsIcon>
12 + </template>
13 + </CardStatsBars>
14 + </n-spin>
15 +</template>
16 +
17 +<script setup lang="ts">
18 +import type { Case } from "@/types/incidentManagement/cases"
19 +import Api from "@/api"
20 +import CardStatsBars, { type ItemProps } from "@/components/common/CardStatsBars.vue"
21 +import CardStatsIcon from "@/components/common/CardStatsIcon.vue"
22 +import { useGoto } from "@/composables/useGoto"
23 +import { NSpin, useMessage } from "naive-ui"
24 +import { computed, onBeforeMount, ref } from "vue"
25 +
26 +const CasesIcon = "carbon:ibm-secure-infrastructure-on-vpc-for-regulated-industries"
27 +const { gotoIncidentManagementCases } = useGoto()
28 +const message = useMessage()
29 +const loading = ref(false)
30 +const casesList = ref<Case[]>([])
31 +
32 +const total = computed<number>(() => {
33 + return casesList.value.length || 0
34 +})
35 +const openedCount = computed<number>(() => {
36 + return casesList.value.filter(o => o.case_status === "OPEN").length || 0
37 +})
38 +const inProgressCount = computed<number>(() => {
39 + return casesList.value.filter(o => o.case_status === "IN_PROGRESS").length || 0
40 +})
41 +const closedCount = computed<number>(() => {
42 + return casesList.value.filter(o => o.case_status === "CLOSED").length || 0
43 +})
44 +const undefinedCount = computed<number>(() => {
45 + return casesList.value.filter(o => o.case_status === null).length || 0
46 +})
47 +
48 +const values = computed<ItemProps[]>(() => [
49 + { value: total.value, label: "Total", isTotal: true },
50 + { value: openedCount.value, label: "Open", status: "error" },
51 + { value: inProgressCount.value, label: "In Progress", status: "warning" },
52 + { value: closedCount.value, label: "Closed", status: "success" },
53 + { value: undefinedCount.value, label: "N/D", status: "muted" }
54 +])
55 +
56 +function getData() {
57 + loading.value = true
58 +
59 + Api.incidentManagement
60 + .getCasesList()
61 + .then(res => {
62 + if (res.data.success) {
63 + casesList.value = res.data?.cases || []
64 + } else {
65 + message.warning(res.data?.message || "An error occurred. Please try again later.")
66 + }
67 + loading.value = false
68 + })
69 + .catch(err => {
70 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
71 + })
72 + .finally(() => {
73 + loading.value = false
74 + })
75 +}
76 +
77 +onBeforeMount(() => {
78 + getData()
79 +})
80 +</script>
81 +
82 +<style lang="scss" scoped>
83 +.n-spin-container {
84 + :deep() {
85 + .n-spin-content {
86 + height: 100%;
87 + }
88 + }
89 +}
90 +</style>
frontend/src/composables/useGoto.ts
+5
@@ -61,6 +61,10 @@ export function useGoto() {
61 router.push({ name: "Soc-Users", query: userId ? { user_id: userId } : {} })
62 }
63
64 + function gotoIncidentManagementAlerts(alertId?: number) {
65 + router.push({ name: "IncidentManagement-Alerts", query: alertId ? { alert_id: alertId } : {} })
66 + }
67 +
68 function gotoIncidentManagementCases(caseId?: number) {
69 router.push({ name: "IncidentManagement-Cases", query: caseId ? { case_id: caseId } : {} })
70 }
@@ -78,6 +82,7 @@ export function useGoto() {
82 gotoSocUsers,
83 gotoAlerts,
84 gotoConnectors,
85 + gotoIncidentManagementAlerts,
86 gotoIncidentManagementCases
87 }
88 }
frontend/src/main.ts
-1
@@ -2,7 +2,6 @@ import App from "@/App.vue"
2 import { getI18NConf, type Locales, type MessageSchema } from "@/lang/config"
3 import router from "@/router"
4 import { createPinia } from "pinia"
5 -
5 import { createPersistedState } from "pinia-plugin-persistedstate"
6 import { createApp } from "vue"
7 import { createI18n } from "vue-i18n"
frontend/src/stores/theme.ts
+8 -233
@@ -1,62 +1,16 @@
1 +import type { ColorType, Layout, RouterTransition, ThemeName } from "@/types/theme.d"
2 import type { BuiltInGlobalTheme } from "naive-ui/es/themes/interface"
2 -import tokens from "@/design-tokens.json"
3 -import { type ColorType, Layout, RouterTransition, ThemeEnum, type ThemeName } from "@/types/theme.d"
4 -import { exportPrimaryShades, getThemeColors, getTypeValue, hex2rgb, type PrimaryShade } from "@/utils/theme"
3 +import { getCssVars, getDefaultState } from "@/theme"
4 +import { ThemeEnum } from "@/types/theme.d"
5 +import { exportPrimaryShades, getThemeColors, getTypeValue, type PrimaryShade } from "@/utils/theme"
6 import _get from "lodash/get"
7 import _pick from "lodash/pick"
8 import _set from "lodash/set"
8 -import { darkTheme, type GlobalThemeOverrides, lightTheme, type ThemeCommonVars, useOsTheme } from "naive-ui"
9 +import { darkTheme, type GlobalThemeOverrides, lightTheme, type ThemeCommonVars } from "naive-ui"
10 import { acceptHMRUpdate, defineStore } from "pinia"
11
11 -const osTheme = useOsTheme()
12 -
12 export const useThemeStore = defineStore("theme", {
14 - state: () => ({
15 - layout: Layout.HorizontalNav,
16 - themeName: osTheme.value || ThemeEnum.Dark,
17 - routerTransition: RouterTransition.FadeUp,
18 - routerTransitionDuration: 0.3,
19 - rtl: false,
20 - boxed: {
21 - enabled: false,
22 - toolbar: true,
23 - width: 1600
24 - },
25 - sidebar: {
26 - autoClose: true,
27 - collapsed: false,
28 - autoCloseBreakpoint: 1000,
29 - animEase: "ease-in-out",
30 - animDuration: 0.3,
31 - openWidth: 300,
32 - closeWidth: 64
33 - },
34 - footer: {
35 - show: true
36 - },
37 - responsive: {
38 - breakpoint: 700,
39 - override: {
40 - viewPadding: {
41 - desk: 40,
42 - mobile: 20
43 - },
44 - toolbarHeight: {
45 - desk: 80,
46 - mobile: 70
47 - }
48 - }
49 - },
50 - toolbarHeight: 80,
51 - viewPadding: 40,
52 - headerBarHeight: 60,
53 - colors: tokens.colors,
54 - borderRadius: tokens.borderRadius,
55 - lineHeight: tokens.lineHeight,
56 - fontSize: tokens.fontSize,
57 - fontFamily: tokens.fontFamily,
58 - typography: tokens.typography
59 - }),
13 + state: () => getDefaultState(),
14 actions: {
15 setLayout(layout: Layout): void {
16 this.layout = layout
@@ -278,187 +232,7 @@ export const useThemeStore = defineStore("theme", {
232 return { ...this.naiveTheme.common, ...this.themeOverrides.common }
233 },
234 style(state): { [key: string]: string } {
281 - const naive = this.naiveCommon
282 -
283 - const bgColor = naive.baseColor
284 - const bgColorRGB = hex2rgb(bgColor).join(", ")
285 - const bgSecondaryColor = this.backgroundSecondaryColor
286 - const fgColor = naive.textColorBase
287 - const fgSecondaryColor = naive.textColor3
288 -
289 - const tabFgColorActive = naive.textColor2
290 - const borderColor = naive.dividerColor
291 - const primaryColor = naive.primaryColor
292 -
293 - const successColor = naive.successColor
294 - const errorColor = naive.errorColor
295 - const warningColor = naive.warningColor
296 - const infoColor = naive.infoColor
297 - const successColorRGB = hex2rgb(successColor).join(", ")
298 - const errorColorRGB = hex2rgb(errorColor).join(", ")
299 - const warningColorRGB = hex2rgb(warningColor).join(", ")
300 - const infoColorRGB = hex2rgb(infoColor).join(", ")
301 -
302 - const { success005, warning005, error005, info005 } = state.colors[state.themeName]
303 -
304 - const modalColor = naive.modalColor
305 - const modalColorRGB = hex2rgb(modalColor).join(", ")
306 - const codeColor = naive.codeColor
307 - const tabColor = naive.tabColor
308 - const tabColorActive = naive.inputColor
309 - const bezierEase = naive.cubicBezierEaseInOut
310 -
311 - const buttonColorSecondary = naive.buttonColor2
312 - const buttonColorSecondaryHover = naive.buttonColor2Hover
313 - const buttonColorSecondaryPressed = naive.buttonColor2Pressed
314 -
315 - const bgSidebar = this.sidebarBackground
316 - const bgSidebarRGB = hex2rgb(bgSidebar).join(", ")
317 - const bgBody = this.bodyBackground
318 - const bgBodyRGB = hex2rgb(bgBody).join(", ")
319 -
320 - const boxedWidth = state.boxed.width
321 - const routerTransitionDuration = state.routerTransitionDuration
322 - const sidebarAnimEase = state.sidebar.animEase
323 - const sidebarAnimDuration = state.sidebar.animDuration
324 - const sidebarOpenWidth = state.sidebar.openWidth
325 - const sidebarCloseWidth = state.sidebar.closeWidth
326 - const toolbarHeight = state.toolbarHeight
327 - const viewPadding = state.viewPadding
328 - const headerBarHeight = state.headerBarHeight
329 - const fontFamily = state.fontFamily.base
330 - const fontFamilyDisplay = state.fontFamily.display
331 - const fontFamilyMono = state.fontFamily.mono
332 -
333 - const borderRadius = state.borderRadius.base
334 - const borderRadiusSmall = state.borderRadius.small
335 -
336 - const { divider005, divider010, divider020, divider030 } = this.dividerColors
337 - const { hover005, hover010, hover050 } = this.hoverColors
338 - const { primary005, primary010, primary015, primary020, primary030, primary040, primary050, primary060 } =
339 - this.primaryColors
340 - const {
341 - secondary1Opacity005,
342 - secondary1Opacity010,
343 - secondary1Opacity020,
344 - secondary1Opacity030,
345 - secondary2Opacity005,
346 - secondary2Opacity010,
347 - secondary2Opacity020,
348 - secondary2Opacity030,
349 - secondary3Opacity005,
350 - secondary3Opacity010,
351 - secondary3Opacity020,
352 - secondary3Opacity030,
353 - secondary4Opacity005,
354 - secondary4Opacity010,
355 - secondary4Opacity020,
356 - secondary4Opacity030
357 - } = this.secondaryOpacityColors
358 -
359 - const { secondary1, secondary2, secondary3, secondary4 } = this.secondaryColors
360 - const secondary1RGB = hex2rgb(secondary1).join(", ")
361 - const secondary2RGB = hex2rgb(secondary2).join(", ")
362 - const secondary3RGB = hex2rgb(secondary3).join(", ")
363 - const secondary4RGB = hex2rgb(secondary4).join(", ")
364 -
365 - return {
366 - "bg-body": `${bgBody}`,
367 - "bg-body-rgb": `${bgBodyRGB}`,
368 - "bg-sidebar": `${bgSidebar}`,
369 - "bg-sidebar-rgb": `${bgSidebarRGB}`,
370 -
371 - "fg-color": `${fgColor}`,
372 - "fg-secondary-color": `${fgSecondaryColor}`,
373 - "bg-color": `${bgColor}`,
374 - "bg-color-rgb": `${bgColorRGB}`,
375 - "bg-secondary-color": `${bgSecondaryColor}`,
376 -
377 - "border-color": `${borderColor}`,
378 - "bezier-ease": `${bezierEase}`,
379 - "router-transition-duration": `${routerTransitionDuration}s`,
380 - "sidebar-anim-ease": `${sidebarAnimEase}`,
381 - "sidebar-anim-duration": `${sidebarAnimDuration}s`,
382 - "sidebar-open-width": `${sidebarOpenWidth}px`,
383 - "sidebar-close-width": `${sidebarCloseWidth}px`,
384 - "boxed-width": `${boxedWidth}px`,
385 - "toolbar-height": `${toolbarHeight}px`,
386 - "header-bar-height": `${headerBarHeight}px`,
387 - "view-padding": `${viewPadding}px`,
388 - "border-radius": `${borderRadius}`,
389 - "border-radius-small": `${borderRadiusSmall}`,
390 - "font-family": `${fontFamily}`,
391 - "font-family-display": `${fontFamilyDisplay}`,
392 - "font-family-mono": `${fontFamilyMono}`,
393 - "code-color": `${codeColor}`,
394 - "primary-color": `${primaryColor}`,
395 - "tab-color": `${tabColor}`,
396 - "tab-color-active": `${tabColorActive}`,
397 - "tab-fg-color-active": `${tabFgColorActive}`,
398 - "modal-color": `${modalColor}`,
399 - "modal-color-rgb": `${modalColorRGB}`,
400 -
401 - "button-color-secondary": `${buttonColorSecondary}`,
402 - "button-color-secondary-hover": `${buttonColorSecondaryHover}`,
403 - "button-color-secondary-pressed": `${buttonColorSecondaryPressed}`,
404 -
405 - "primary-005-color": `${primary005}`,
406 - "primary-010-color": `${primary010}`,
407 - "primary-015-color": `${primary015}`,
408 - "primary-020-color": `${primary020}`,
409 - "primary-030-color": `${primary030}`,
410 - "primary-040-color": `${primary040}`,
411 - "primary-050-color": `${primary050}`,
412 - "primary-060-color": `${primary060}`,
413 -
414 - "hover-005-color": `${hover005}`,
415 - "hover-010-color": `${hover010}`,
416 - "hover-050-color": `${hover050}`,
417 -
418 - "divider-005-color": `${divider005}`,
419 - "divider-010-color": `${divider010}`,
420 - "divider-020-color": `${divider020}`,
421 - "divider-030-color": `${divider030}`,
422 -
423 - "success-color": `${successColor}`,
424 - "error-color": `${errorColor}`,
425 - "warning-color": `${warningColor}`,
426 - "info-color": `${infoColor}`,
427 - "success-005-color": `${success005}`,
428 - "error-005-color": `${error005}`,
429 - "warning-005-color": `${warning005}`,
430 - "info-005-color": `${info005}`,
431 - "success-color-rgb": `${successColorRGB}`,
432 - "error-color-rgb": `${errorColorRGB}`,
433 - "warning-color-rgb": `${warningColorRGB}`,
434 - "info-color-rgb": `${infoColorRGB}`,
435 -
436 - "secondary1-color": `${secondary1}`,
437 - "secondary1-color-rgb": `${secondary1RGB}`,
438 - "secondary2-color": `${secondary2}`,
439 - "secondary2-color-rgb": `${secondary2RGB}`,
440 - "secondary3-color": `${secondary3}`,
441 - "secondary3-color-rgb": `${secondary3RGB}`,
442 - "secondary4-color": `${secondary4}`,
443 - "secondary4-color-rgb": `${secondary4RGB}`,
444 -
445 - "secondary1-opacity-005-color": `${secondary1Opacity005}`,
446 - "secondary1-opacity-010-color": `${secondary1Opacity010}`,
447 - "secondary1-opacity-020-color": `${secondary1Opacity020}`,
448 - "secondary1-opacity-030-color": `${secondary1Opacity030}`,
449 - "secondary2-opacity-005-color": `${secondary2Opacity005}`,
450 - "secondary2-opacity-010-color": `${secondary2Opacity010}`,
451 - "secondary2-opacity-020-color": `${secondary2Opacity020}`,
452 - "secondary2-opacity-030-color": `${secondary2Opacity030}`,
453 - "secondary3-opacity-005-color": `${secondary3Opacity005}`,
454 - "secondary3-opacity-010-color": `${secondary3Opacity010}`,
455 - "secondary3-opacity-020-color": `${secondary3Opacity020}`,
456 - "secondary3-opacity-030-color": `${secondary3Opacity030}`,
457 - "secondary4-opacity-005-color": `${secondary4Opacity005}`,
458 - "secondary4-opacity-010-color": `${secondary4Opacity010}`,
459 - "secondary4-opacity-020-color": `${secondary4Opacity020}`,
460 - "secondary4-opacity-030-color": `${secondary4Opacity030}`
461 - }
235 + return getCssVars(state, this)
236 },
237 isThemeDark(state): boolean {
238 return state.themeName === ThemeEnum.Dark
@@ -480,6 +254,7 @@ export const useThemeStore = defineStore("theme", {
254 }
255 },
256 persist: {
257 + // use this param to save specific state chunk on localStorage
258 pick: ["layout", "themeName", "routerTransition", "boxed", "sidebar.collapsed"]
259 }
260 })
frontend/src/theme/index.ts new
+255
@@ -0,0 +1,255 @@
1 +import tokens from "@/design-tokens.json"
2 +import { Layout, RouterTransition, ThemeEnum } from "@/types/theme.d"
3 +import { hex2rgb } from "@/utils/theme"
4 +import { type ThemeCommonVars, useOsTheme } from "naive-ui"
5 +
6 +type ThemeState = ReturnType<typeof getDefaultState>
7 +
8 +interface ThemeGetters {
9 + dividerColors: { [key: string]: string }
10 + hoverColors: { [key: string]: string }
11 + primaryColors: { [key: string]: string }
12 + secondaryOpacityColors: { [key: string]: string }
13 + secondaryColors: { [key: string]: string }
14 + sidebarBackground: string
15 + bodyBackground: string
16 + backgroundSecondaryColor: string
17 + naiveCommon: ThemeCommonVars
18 +}
19 +
20 +const osTheme = useOsTheme()
21 +
22 +export function getDefaultState() {
23 + return {
24 + layout: Layout.HorizontalNav, // Type of layout, with vertical or horizontal navigation
25 + themeName: osTheme.value || ThemeEnum.Light, // Theme name (Dark, Light), with fallback to the light theme
26 + routerTransition: RouterTransition.FadeUp, // Type of transition for the router
27 + routerTransitionDuration: 0.3, // Duration of the router transition in seconds
28 + rtl: false, // RTL (right to left) mode toggle
29 + boxed: {
30 + enabled: true, // Choose whether to apply a maximum width to the page
31 + toolbar: true, // Choose whether to apply the maximum width to the toolbar as well
32 + width: 1600 // Maximum width size in pixels
33 + },
34 + sidebar: {
35 + autoClose: true, // Choose whether to automatically close the sidebar when the view goes below the "autoCloseBreakpoint" value
36 + collapsed: false, // Indicates if the sidebar is collapsed
37 + autoCloseBreakpoint: 1000, // Breakpoint for the automatic closing of the sidebar (in pixels)
38 + animEase: "ease-in-out", // Type of easing for animations
39 + animDuration: 0.3, // Duration of sidebar animations (in seconds)
40 + openWidth: 300, // Width of the open sidebar (in pixels)
41 + closeWidth: 64 // Width of the closed sidebar (in pixels)
42 + },
43 + footer: {
44 + show: true // Show or hide the footer
45 + },
46 + responsive: {
47 + breakpoint: 700, // Breakpoint in pixels (Desk -> Mobile)
48 + // Parameters to be adjusted based on the breakpoint
49 + override: {
50 + viewPadding: {
51 + desk: 40, // View padding for desktop
52 + mobile: 20 // View padding for mobile devices
53 + },
54 + toolbarHeight: {
55 + desk: 80, // Height of the toolbar for desktop
56 + mobile: 70 // Height of the toolbar for mobile devices
57 + }
58 + }
59 + },
60 + toolbarHeight: 80, // Default toolbar height (in pixels)
61 + viewPadding: 40, // Default view padding (in pixels)
62 + headerBarHeight: 60, // Height of the header bar (in pixels)
63 + colors: tokens.colors, // Color definitions from the token
64 + borderRadius: tokens.borderRadius, // Border radius from the token
65 + lineHeight: tokens.lineHeight, // Line height from the token
66 + fontSize: tokens.fontSize, // Font size from the token
67 + fontFamily: tokens.fontFamily, // Font family from the token
68 + typography: tokens.typography // Typography configurations from the token
69 + }
70 +}
71 +
72 +export function getCssVars(state: ThemeState, getters: ThemeGetters): { [key: string]: string } {
73 + const naive = getters.naiveCommon
74 +
75 + const bgColor = naive.baseColor
76 + const bgColorRGB = hex2rgb(bgColor).join(", ")
77 + const bgSecondaryColor = getters.backgroundSecondaryColor
78 + const fgColor = naive.textColorBase
79 + const fgSecondaryColor = naive.textColor3
80 +
81 + const tabFgColorActive = naive.textColor2
82 + const borderColor = naive.dividerColor
83 + const primaryColor = naive.primaryColor
84 +
85 + const successColor = naive.successColor
86 + const errorColor = naive.errorColor
87 + const warningColor = naive.warningColor
88 + const infoColor = naive.infoColor
89 + const successColorRGB = hex2rgb(successColor).join(", ")
90 + const errorColorRGB = hex2rgb(errorColor).join(", ")
91 + const warningColorRGB = hex2rgb(warningColor).join(", ")
92 + const infoColorRGB = hex2rgb(infoColor).join(", ")
93 +
94 + const { success005, warning005, error005, info005 } = state.colors[state.themeName]
95 +
96 + const modalColor = naive.modalColor
97 + const modalColorRGB = hex2rgb(modalColor).join(", ")
98 + const codeColor = naive.codeColor
99 + const tabColor = naive.tabColor
100 + const tabColorActive = naive.inputColor
101 + const bezierEase = naive.cubicBezierEaseInOut
102 +
103 + const buttonColorSecondary = naive.buttonColor2
104 + const buttonColorSecondaryHover = naive.buttonColor2Hover
105 + const buttonColorSecondaryPressed = naive.buttonColor2Pressed
106 +
107 + const bgSidebar = getters.sidebarBackground
108 + const bgSidebarRGB = hex2rgb(bgSidebar).join(", ")
109 + const bgBody = getters.bodyBackground
110 + const bgBodyRGB = hex2rgb(bgBody).join(", ")
111 +
112 + const boxedWidth = state.boxed.width
113 + const routerTransitionDuration = state.routerTransitionDuration
114 + const sidebarAnimEase = state.sidebar.animEase
115 + const sidebarAnimDuration = state.sidebar.animDuration
116 + const sidebarOpenWidth = state.sidebar.openWidth
117 + const sidebarCloseWidth = state.sidebar.closeWidth
118 + const toolbarHeight = state.toolbarHeight
119 + const viewPadding = state.viewPadding
120 + const headerBarHeight = state.headerBarHeight
121 + const fontFamily = state.fontFamily.base
122 + const fontFamilyDisplay = state.fontFamily.display
123 + const fontFamilyMono = state.fontFamily.mono
124 +
125 + const borderRadius = state.borderRadius.base
126 + const borderRadiusSmall = state.borderRadius.small
127 +
128 + const { divider005, divider010, divider020, divider030 } = getters.dividerColors
129 + const { hover005, hover010, hover050 } = getters.hoverColors
130 + const { primary005, primary010, primary015, primary020, primary030, primary040, primary050, primary060 } =
131 + getters.primaryColors
132 + const {
133 + secondary1Opacity005,
134 + secondary1Opacity010,
135 + secondary1Opacity020,
136 + secondary1Opacity030,
137 + secondary2Opacity005,
138 + secondary2Opacity010,
139 + secondary2Opacity020,
140 + secondary2Opacity030,
141 + secondary3Opacity005,
142 + secondary3Opacity010,
143 + secondary3Opacity020,
144 + secondary3Opacity030,
145 + secondary4Opacity005,
146 + secondary4Opacity010,
147 + secondary4Opacity020,
148 + secondary4Opacity030
149 + } = getters.secondaryOpacityColors
150 +
151 + const { secondary1, secondary2, secondary3, secondary4 } = getters.secondaryColors
152 + const secondary1RGB = hex2rgb(secondary1).join(", ")
153 + const secondary2RGB = hex2rgb(secondary2).join(", ")
154 + const secondary3RGB = hex2rgb(secondary3).join(", ")
155 + const secondary4RGB = hex2rgb(secondary4).join(", ")
156 +
157 + // This style object, imported via the themeStore, will be available application-wide and is exposed in the HTML tag as a list of CSS variables, which you can use in your CSS/SCSS code like: var(-–bg-color)
158 + return {
159 + "bg-body": `${bgBody}`,
160 + "bg-body-rgb": `${bgBodyRGB}`,
161 + "bg-sidebar": `${bgSidebar}`,
162 + "bg-sidebar-rgb": `${bgSidebarRGB}`,
163 +
164 + "fg-color": `${fgColor}`,
165 + "fg-secondary-color": `${fgSecondaryColor}`,
166 + "bg-color": `${bgColor}`,
167 + "bg-color-rgb": `${bgColorRGB}`,
168 + "bg-secondary-color": `${bgSecondaryColor}`,
169 +
170 + "border-color": `${borderColor}`,
171 + "bezier-ease": `${bezierEase}`,
172 + "router-transition-duration": `${routerTransitionDuration}s`,
173 + "sidebar-anim-ease": `${sidebarAnimEase}`,
174 + "sidebar-anim-duration": `${sidebarAnimDuration}s`,
175 + "sidebar-open-width": `${sidebarOpenWidth}px`,
176 + "sidebar-close-width": `${sidebarCloseWidth}px`,
177 + "boxed-width": `${boxedWidth}px`,
178 + "toolbar-height": `${toolbarHeight}px`,
179 + "header-bar-height": `${headerBarHeight}px`,
180 + "view-padding": `${viewPadding}px`,
181 + "border-radius": `${borderRadius}`,
182 + "border-radius-small": `${borderRadiusSmall}`,
183 + "font-family": `${fontFamily}`,
184 + "font-family-display": `${fontFamilyDisplay}`,
185 + "font-family-mono": `${fontFamilyMono}`,
186 + "code-color": `${codeColor}`,
187 + "primary-color": `${primaryColor}`,
188 + "tab-color": `${tabColor}`,
189 + "tab-color-active": `${tabColorActive}`,
190 + "tab-fg-color-active": `${tabFgColorActive}`,
191 + "modal-color": `${modalColor}`,
192 + "modal-color-rgb": `${modalColorRGB}`,
193 +
194 + "button-color-secondary": `${buttonColorSecondary}`,
195 + "button-color-secondary-hover": `${buttonColorSecondaryHover}`,
196 + "button-color-secondary-pressed": `${buttonColorSecondaryPressed}`,
197 +
198 + "primary-005-color": `${primary005}`,
199 + "primary-010-color": `${primary010}`,
200 + "primary-015-color": `${primary015}`,
201 + "primary-020-color": `${primary020}`,
202 + "primary-030-color": `${primary030}`,
203 + "primary-040-color": `${primary040}`,
204 + "primary-050-color": `${primary050}`,
205 + "primary-060-color": `${primary060}`,
206 +
207 + "hover-005-color": `${hover005}`,
208 + "hover-010-color": `${hover010}`,
209 + "hover-050-color": `${hover050}`,
210 +
211 + "divider-005-color": `${divider005}`,
212 + "divider-010-color": `${divider010}`,
213 + "divider-020-color": `${divider020}`,
214 + "divider-030-color": `${divider030}`,
215 +
216 + "success-color": `${successColor}`,
217 + "error-color": `${errorColor}`,
218 + "warning-color": `${warningColor}`,
219 + "info-color": `${infoColor}`,
220 + "success-005-color": `${success005}`,
221 + "error-005-color": `${error005}`,
222 + "warning-005-color": `${warning005}`,
223 + "info-005-color": `${info005}`,
224 + "success-color-rgb": `${successColorRGB}`,
225 + "error-color-rgb": `${errorColorRGB}`,
226 + "warning-color-rgb": `${warningColorRGB}`,
227 + "info-color-rgb": `${infoColorRGB}`,
228 +
229 + "secondary1-color": `${secondary1}`,
230 + "secondary1-color-rgb": `${secondary1RGB}`,
231 + "secondary2-color": `${secondary2}`,
232 + "secondary2-color-rgb": `${secondary2RGB}`,
233 + "secondary3-color": `${secondary3}`,
234 + "secondary3-color-rgb": `${secondary3RGB}`,
235 + "secondary4-color": `${secondary4}`,
236 + "secondary4-color-rgb": `${secondary4RGB}`,
237 +
238 + "secondary1-opacity-005-color": `${secondary1Opacity005}`,
239 + "secondary1-opacity-010-color": `${secondary1Opacity010}`,
240 + "secondary1-opacity-020-color": `${secondary1Opacity020}`,
241 + "secondary1-opacity-030-color": `${secondary1Opacity030}`,
242 + "secondary2-opacity-005-color": `${secondary2Opacity005}`,
243 + "secondary2-opacity-010-color": `${secondary2Opacity010}`,
244 + "secondary2-opacity-020-color": `${secondary2Opacity020}`,
245 + "secondary2-opacity-030-color": `${secondary2Opacity030}`,
246 + "secondary3-opacity-005-color": `${secondary3Opacity005}`,
247 + "secondary3-opacity-010-color": `${secondary3Opacity010}`,
248 + "secondary3-opacity-020-color": `${secondary3Opacity020}`,
249 + "secondary3-opacity-030-color": `${secondary3Opacity030}`,
250 + "secondary4-opacity-005-color": `${secondary4Opacity005}`,
251 + "secondary4-opacity-010-color": `${secondary4Opacity010}`,
252 + "secondary4-opacity-020-color": `${secondary4Opacity020}`,
253 + "secondary4-opacity-030-color": `${secondary4Opacity030}`
254 + }
255 +}
frontend/src/views/AlertsGraylog.vue
+1 -1
@@ -4,7 +4,7 @@
4 </div>
5 </template>
6
7 -<script setup>
7 +<script setup lang="ts">
8 import AlertsGraylogList from "@/components/alerts/AlertsGraylogList.vue"
9 </script>
10
frontend/src/views/AlertsOld.vue
+1 -1
@@ -4,7 +4,7 @@
4 </div>
5 </template>
6
7 -<script setup>
7 +<script setup lang="ts">
8 import AlertsList from "@/components/alerts/AlertsList.vue"
9 </script>
10
frontend/src/views/Overview.vue
+19 -43
@@ -20,22 +20,21 @@
20 </div>
21 </div>
22 <div class="section">
23 - <div class="columns column-800 overflow-hidden">
24 - <div class="basis-2/5">
25 - <AgentsCard />
23 + <div class="grid grid-flow-row-dense grid-cols-12 gap-6">
24 + <div class="col-span-12 xs:col-span-12 sm:col-span-4 lg:col-span-2">
25 + <AgentsCard class="h-full" />
26 </div>
27 - <div class="basis-2/5">
28 - <HealthcheckCard />
27 + <div class="col-span-12 xs:col-span-6 sm:col-span-4 lg:col-span-2">
28 + <HealthcheckCard class="h-full" />
29 </div>
30 - <div class="basis-1/5 flex gap-6">
31 - <!--
32 - <div class="grow overflow-hidden">
33 - <SocAlertsCard class="h-full" :vertical="cardDirection === 'vertical'" />
34 - </div>
35 - -->
36 - <div class="grow overflow-hidden">
37 - <CustomersCard class="h-full" :vertical="cardDirection === 'vertical'" />
38 - </div>
30 + <div class="col-span-12 xs:col-span-6 sm:col-span-4 lg:col-span-2">
31 + <CustomersCard class="h-full" />
32 + </div>
33 + <div class="col-span-12 lg:col-span-3">
34 + <IncidentAlerts class="h-full" />
35 + </div>
36 + <div class="col-span-12 lg:col-span-3">
37 + <IncidentCases class="h-full" />
38 </div>
39 </div>
40 </div>
@@ -43,7 +42,7 @@
42 <IndicesMarquee @click="gotoIndex($event.index)" />
43 </div>
44 <div class="section">
46 - <div class="columns">
45 + <div class="columns flex-col lg:flex-row">
46 <div class="col basis-1/2">
47 <ClusterHealth class="stretchy" />
48 </div>
@@ -85,15 +84,16 @@ import ClusterHealth from "@/components/indices/ClusterHealth.vue"
84 import IndicesMarquee from "@/components/indices/Marquee.vue"
85 import NodeAllocation from "@/components/indices/NodeAllocation.vue"
86 import AgentsCard from "@/components/overview/AgentsCard.vue"
87 +import CustomersCard from "@/components/overview/CustomersCard.vue"
88 import HealthcheckCard from "@/components/overview/HealthcheckCard.vue"
89 +import IncidentAlerts from "@/components/overview/IncidentAlerts.vue"
90 +import IncidentCases from "@/components/overview/IncidentCases.vue"
91 import StackProvisioningButton from "@/components/stackProvisioning/StackProvisioningButton.vue"
92 import WebVulnerabilityAssessmentButton from "@/components/webVulnerabilityAssessment/WebVulnerabilityAssessmentButton.vue"
91 -import { NButton, NDrawer, NDrawerContent } from "naive-ui"
92 -import { defineAsyncComponent, ref } from "vue"
93 -// import SocAlertsCard from "@/components/overview/SocAlertsCard.vue"
94 -import CustomersCard from "@/components/overview/CustomersCard.vue"
93 import { useGoto } from "@/composables/useGoto"
94 import { useResizeObserver } from "@vueuse/core"
95 +import { NButton, NDrawer, NDrawerContent } from "naive-ui"
96 +import { defineAsyncComponent, ref } from "vue"
97
98 const ThreatIntelButton = defineAsyncComponent(() => import("@/components/threatIntel/ThreatIntelButton.vue"))
99
@@ -125,29 +125,5 @@ useResizeObserver(page, entries => {
125 }
126 }
127 }
128 -
129 - @media (max-width: 1000px) {
130 - .section {
131 - .columns {
132 - &:not(.column-1200, .column-800) {
133 - flex-direction: column;
134 - }
135 - }
136 - }
137 - }
138 - @media (max-width: 800px) {
139 - .section {
140 - .columns.column-800 {
141 - flex-direction: column;
142 - }
143 - }
144 - }
145 - @media (max-width: 1200px) {
146 - .section {
147 - .columns.column-1200 {
148 - flex-direction: column;
149 - }
150 - }
151 - }
128 }
129 </style>
frontend/src/views/ReportCreation.vue
+1 -1
@@ -39,7 +39,7 @@ const panels = ref<Panel[]>([])
39 </script>
40
41 <style lang="scss" scoped>
42 -@import "../layouts/HorizontalNav/_variables.scss";
42 +@import "../app-layouts/HorizontalNav/_variables.scss";
43
44 .page {
45 overflow: hidden;
frontend/tailwind.config.js
+3 -1
@@ -58,7 +58,9 @@ export default {
58 "w-72",
59 "max-h-50vh",
60 "max-w-90vw",
61 - "!h-0.75"
61 + "!h-0.75",
62 + "basis-1/4",
63 + "basis-1/5"
64 ],
65 plugins: [
66 plugin(({ addBase, theme }) => {