Compare commits
12 Commits
ea4c052981
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 72cb2b8d02 | |||
| a0c50bded9 | |||
| 09ada28f09 | |||
| ea28911822 | |||
| 0a88c7f14a | |||
| 1d7e363076 | |||
| 7f94b97a8d | |||
| fe5d4fae37 | |||
| 01610727fd | |||
| 6942469259 | |||
| f73e53bc65 | |||
| 66635a73ff |
Generated
+187
-264
@@ -16,13 +16,13 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"@vitest/coverage-v8": "^4.1.6",
|
||||
"@vitest/coverage-v8": "^5.0.0",
|
||||
"@vue/test-utils": "^2.4.10",
|
||||
"@vue/tsconfig": "^0.9.0",
|
||||
"jsdom": "^30.0.0",
|
||||
"typescript": "~6.0.0",
|
||||
"vite": "^8.0.0",
|
||||
"vitest": "^4.1.6",
|
||||
"vitest": "^5.0.0",
|
||||
"vue-tsc": "^3.0.5"
|
||||
}
|
||||
},
|
||||
@@ -595,13 +595,6 @@
|
||||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@standard-schema/spec": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
|
||||
"integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/chai": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
|
||||
@@ -645,29 +638,27 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/coverage-v8": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.11.tgz",
|
||||
"integrity": "sha512-8MVGEFnJIcdGjcbfKmeq8z0pZHH0JlVtoVZH9Q/qwUp6wyFnEJUBMrw9DCaj+ra3vShGmhavjalMIhPNxZAUcw==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-5.0.0.tgz",
|
||||
"integrity": "sha512-toMg6PZGCIa/lQNCDoASrfb1ly4hsUKXFtFYC9kD4t78o5Y6LyNJU7AENt8eHPr3quYdxaxK7hj2mnbFfUk9NA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@bcoe/v8-coverage": "^1.0.2",
|
||||
"@vitest/utils": "4.1.11",
|
||||
"ast-v8-to-istanbul": "^1.0.0",
|
||||
"istanbul-lib-coverage": "^3.2.2",
|
||||
"istanbul-lib-report": "^3.0.1",
|
||||
"istanbul-reports": "^3.2.0",
|
||||
"magicast": "^0.5.2",
|
||||
"obug": "^2.1.1",
|
||||
"std-env": "^4.0.0-rc.1",
|
||||
"tinyrainbow": "^3.1.0"
|
||||
"@vitest/istanbul-lib-coverage": "^1.0.0",
|
||||
"@vitest/istanbul-lib-report": "^1.0.0",
|
||||
"ast-v8-to-istanbul": "^1.0.5",
|
||||
"magicast": "^0.5.4",
|
||||
"obug": "^2.1.4",
|
||||
"std-env": "^4.2.0",
|
||||
"tinyrainbow": "^3.1.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vitest/browser": "4.1.11",
|
||||
"vitest": "4.1.11"
|
||||
"@vitest/browser": "5.0.0",
|
||||
"vitest": "5.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vitest/browser": {
|
||||
@@ -675,34 +666,40 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/expect": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.11.tgz",
|
||||
"integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==",
|
||||
"node_modules/@vitest/istanbul-lib-coverage": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/istanbul-lib-coverage/-/istanbul-lib-coverage-1.0.1.tgz",
|
||||
"integrity": "sha512-k3DJZ8LhMBK9NS4SclF1ASD3OgXEWDorbIcPTRDK0/Zae6fRvu+fJRxtFdLfHsa9Y24beCdPnoNZ4LviTNstfA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/istanbul-lib-report": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/istanbul-lib-report/-/istanbul-lib-report-1.0.1.tgz",
|
||||
"integrity": "sha512-1EOLRfsTMnyAr3+kEAsP4o9dhaDlGPpD7H5iLBBeq//YpNB1VIahkPhB+eRp9N2Dkfw8oySROjE3yf9XDeaIkQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "^1.1.0",
|
||||
"@types/chai": "^5.2.2",
|
||||
"@vitest/spy": "4.1.11",
|
||||
"@vitest/utils": "4.1.11",
|
||||
"chai": "^6.2.2",
|
||||
"tinyrainbow": "^3.1.0"
|
||||
"@vitest/istanbul-lib-coverage": "1.0.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/mocker": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.11.tgz",
|
||||
"integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.0.tgz",
|
||||
"integrity": "sha512-66PGTMIiVJP3t4a5yxU9qPtf7MdTBs8jmToMvy+HVflB3Yy13WJZTtPePdvU+wjRV02SKK5doLbSA6o9pwOmiA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/spy": "4.1.11",
|
||||
"@jridgewell/trace-mapping": "0.3.31",
|
||||
"@vitest/spy": "5.0.0",
|
||||
"estree-walker": "^3.0.3",
|
||||
"magic-string": "^0.30.21"
|
||||
"magic-string": "^1.2.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
@@ -720,6 +717,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/mocker/node_modules/@vitest/spy": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.0.tgz",
|
||||
"integrity": "sha512-uy+luWBAPw9XfthoHi5AkfHUnuPYEESjl0p/r+meoBnU8bxg5GDQ3Ey8MjcJ6sqahkL4PFyrvfMJJBw7LbU06g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/mocker/node_modules/estree-walker": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
|
||||
@@ -730,72 +737,14 @@
|
||||
"@types/estree": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/pretty-format": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.11.tgz",
|
||||
"integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==",
|
||||
"node_modules/@vitest/mocker/node_modules/magic-string": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.2.3.tgz",
|
||||
"integrity": "sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tinyrainbow": "^3.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/runner": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.11.tgz",
|
||||
"integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/utils": "4.1.11",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/snapshot": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.11.tgz",
|
||||
"integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/pretty-format": "4.1.11",
|
||||
"@vitest/utils": "4.1.11",
|
||||
"magic-string": "^0.30.21",
|
||||
"pathe": "^2.0.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/spy": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.11.tgz",
|
||||
"integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/utils": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.11.tgz",
|
||||
"integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/pretty-format": "4.1.11",
|
||||
"convert-source-map": "^2.0.0",
|
||||
"tinyrainbow": "^3.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@volar/language-core": {
|
||||
@@ -1035,6 +984,63 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vuetify/v0": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@vuetify/v0/-/v0-1.2.1.tgz",
|
||||
"integrity": "sha512-lFBUeMmQiKbFR7JXC1Z74Z2dvvGLCqt/Wd9JQqg4falICTvHtlkulYqaHbtmByGV9eR7cbG1ohN1+7OQLLSPfg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/johnleider"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/vuetify"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@adobe/leonardo-contrast-colors": ">=1.0.0",
|
||||
"@ant-design/colors": ">=7.0.0",
|
||||
"@flagsmith/flagsmith": ">=11.0.0",
|
||||
"@floating-ui/dom": ">=1.8.0",
|
||||
"@js-temporal/polyfill": ">=0.5.0",
|
||||
"@material/material-color-utilities": ">=0.3.0",
|
||||
"launchdarkly-js-client-sdk": "^3.0.0",
|
||||
"posthog-js": "^1.0.0",
|
||||
"vue": ">=3.5.0 || >=3.6.0-0",
|
||||
"vue-i18n": ">=10.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@adobe/leonardo-contrast-colors": {
|
||||
"optional": true
|
||||
},
|
||||
"@ant-design/colors": {
|
||||
"optional": true
|
||||
},
|
||||
"@flagsmith/flagsmith": {
|
||||
"optional": true
|
||||
},
|
||||
"@floating-ui/dom": {
|
||||
"optional": true
|
||||
},
|
||||
"@js-temporal/polyfill": {
|
||||
"optional": true
|
||||
},
|
||||
"@material/material-color-utilities": {
|
||||
"optional": true
|
||||
},
|
||||
"launchdarkly-js-client-sdk": {
|
||||
"optional": true
|
||||
},
|
||||
"posthog-js": {
|
||||
"optional": true
|
||||
},
|
||||
"vue-i18n": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/abbrev": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-5.0.0.tgz",
|
||||
@@ -1223,13 +1229,6 @@
|
||||
"proto-list": "~1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/convert-source-map": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
||||
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/css-tree": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
|
||||
@@ -1313,9 +1312,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/es-module-lexer": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz",
|
||||
"integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==",
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz",
|
||||
"integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -1390,16 +1389,6 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/hookable": {
|
||||
"version": "5.5.3",
|
||||
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
|
||||
@@ -1419,13 +1408,6 @@
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/html-escaper": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
|
||||
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ini": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||
@@ -1440,45 +1422,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/istanbul-lib-coverage": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
|
||||
"integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/istanbul-lib-report": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
|
||||
"integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"istanbul-lib-coverage": "^3.0.0",
|
||||
"make-dir": "^4.0.0",
|
||||
"supports-color": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/istanbul-reports": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
|
||||
"integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"html-escaper": "^2.0.0",
|
||||
"istanbul-lib-report": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/js-beautify": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-2.0.3.tgz",
|
||||
@@ -1873,33 +1816,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/magicast": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.3.tgz",
|
||||
"integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==",
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.4.tgz",
|
||||
"integrity": "sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.29.3",
|
||||
"@babel/types": "^7.29.0",
|
||||
"@babel/parser": "^7.29.7",
|
||||
"@babel/types": "^7.29.7",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/make-dir": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
|
||||
"integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"semver": "^7.5.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/mdn-data": {
|
||||
"version": "2.27.1",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
|
||||
@@ -1969,9 +1896,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.17",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz",
|
||||
"integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==",
|
||||
"version": "3.3.19",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz",
|
||||
"integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -2091,9 +2018,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
|
||||
"integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
|
||||
"integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
@@ -2139,9 +2066,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.26",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
|
||||
"integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==",
|
||||
"version": "8.5.28",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz",
|
||||
"integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -2158,7 +2085,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.17",
|
||||
"nanoid": "^3.3.18",
|
||||
"picocolors": "^1.1.1",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
@@ -2318,19 +2245,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/symbol-tree": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
||||
@@ -2339,16 +2253,19 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tinybench": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
|
||||
"integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.1.4.tgz",
|
||||
"integrity": "sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tinyexec": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz",
|
||||
"integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz",
|
||||
"integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -2372,9 +2289,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tinyrainbow": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz",
|
||||
"integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz",
|
||||
"integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -2528,16 +2445,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "8.2.2",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz",
|
||||
"integrity": "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==",
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-8.3.0.tgz",
|
||||
"integrity": "sha512-lhZBVvEHefgE+HQZC9O7EBJgCU/nVzFNl7vkS4RE0APtWLP02/8QVIkQtzBxPquh7lq5/78NHipTj7ODQ6XuyQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lightningcss": "^1.33.0",
|
||||
"picomatch": "^4.0.5",
|
||||
"postcss": "^8.5.26",
|
||||
"rolldown": "~1.2.4",
|
||||
"picomatch": "^4.0.7",
|
||||
"postcss": "^8.5.28",
|
||||
"rolldown": "~1.2.6",
|
||||
"tinyglobby": "^0.2.17"
|
||||
},
|
||||
"bin": {
|
||||
@@ -2554,7 +2471,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/node": "^20.19.0 || >=22.12.0",
|
||||
"@vitejs/devtools": "^0.4.0 || ^0.5.0",
|
||||
"@vitejs/devtools": "^0.7.1",
|
||||
"esbuild": "^0.27.0 || ^0.28.0",
|
||||
"jiti": ">=1.21.0",
|
||||
"less": "^4.0.0",
|
||||
@@ -2606,38 +2523,31 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vitest": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz",
|
||||
"integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.0.tgz",
|
||||
"integrity": "sha512-gpsMNoRhMjMktVxPtstOH4/PJuPyovVaMDr4oDilXaGH1EcqM2OE96SoHT2VIQ6fTGtTjqmHDrEu2X9RQiXf8Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vitest/expect": "4.1.11",
|
||||
"@vitest/mocker": "4.1.11",
|
||||
"@vitest/pretty-format": "4.1.11",
|
||||
"@vitest/runner": "4.1.11",
|
||||
"@vitest/snapshot": "4.1.11",
|
||||
"@vitest/spy": "4.1.11",
|
||||
"@vitest/utils": "4.1.11",
|
||||
"es-module-lexer": "^2.0.0",
|
||||
"expect-type": "^1.3.0",
|
||||
"magic-string": "^0.30.21",
|
||||
"obug": "^2.1.1",
|
||||
"pathe": "^2.0.3",
|
||||
"picomatch": "^4.0.3",
|
||||
"std-env": "^4.0.0-rc.1",
|
||||
"tinybench": "^2.9.0",
|
||||
"tinyexec": "^1.0.2",
|
||||
"tinyglobby": "^0.2.15",
|
||||
"tinyrainbow": "^3.1.0",
|
||||
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0",
|
||||
"@types/chai": "^5.2.2",
|
||||
"@vitest/mocker": "5.0.0",
|
||||
"chai": "^6.2.2",
|
||||
"es-module-lexer": "^2.3.2",
|
||||
"expect-type": "^1.4.0",
|
||||
"magic-string": "^1.2.3",
|
||||
"obug": "^2.1.4",
|
||||
"picomatch": "^4.0.7",
|
||||
"std-env": "^4.2.0",
|
||||
"tinybench": "6.1.4",
|
||||
"tinyexec": "1.3.0",
|
||||
"tinyglobby": "^0.2.17",
|
||||
"why-is-node-running": "^2.3.0"
|
||||
},
|
||||
"bin": {
|
||||
"vitest": "vitest.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.0.0 || ^22.0.0 || >=24.0.0"
|
||||
"node": "^22.12.0 || ^24.0.0 || >=26.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/vitest"
|
||||
@@ -2645,16 +2555,16 @@
|
||||
"peerDependencies": {
|
||||
"@edge-runtime/vm": "*",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
|
||||
"@vitest/browser-playwright": "4.1.11",
|
||||
"@vitest/browser-preview": "4.1.11",
|
||||
"@vitest/browser-webdriverio": "4.1.11",
|
||||
"@vitest/coverage-istanbul": "4.1.11",
|
||||
"@vitest/coverage-v8": "4.1.11",
|
||||
"@vitest/ui": "4.1.11",
|
||||
"@types/node": "^22.0.0 || >=24.0.0",
|
||||
"@vitest/browser-playwright": "5.0.0",
|
||||
"@vitest/browser-preview": "5.0.0",
|
||||
"@vitest/browser-webdriverio": "^5.0.0-beta.5 || >=5.0.0",
|
||||
"@vitest/coverage-istanbul": "5.0.0",
|
||||
"@vitest/coverage-v8": "5.0.0",
|
||||
"@vitest/ui": "5.0.0",
|
||||
"happy-dom": "*",
|
||||
"jsdom": "*",
|
||||
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
"vite": "^6.4.0 || ^7.0.0 || ^8.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@edge-runtime/vm": {
|
||||
@@ -2695,6 +2605,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/vitest/node_modules/magic-string": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.2.3.tgz",
|
||||
"integrity": "sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-uri": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz",
|
||||
@@ -2796,10 +2716,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vuetify": {
|
||||
"version": "4.1.12",
|
||||
"resolved": "https://registry.npmjs.org/vuetify/-/vuetify-4.1.12.tgz",
|
||||
"integrity": "sha512-WXGbnuzqUGPZM7nF38C3jiucaLRutHZOICVW0wg1dyXppW11i+su/IT20nK+1o86nsgTdedejeEv53cJUrI30A==",
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/vuetify/-/vuetify-4.2.1.tgz",
|
||||
"integrity": "sha512-K3ZIqu7YkorQFB6//dR5KEBpbfOo+y/LkcGtknsnneE3JN1pW3R7o/JB9QDkJuP1ELhENIdBZIkiSmXu0dQ9lQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vuetify/v0": "^1.2.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/johnleider"
|
||||
|
||||
+2
-2
@@ -28,9 +28,9 @@
|
||||
"typescript": "~6.0.0",
|
||||
"vite": "^8.0.0",
|
||||
"vue-tsc": "^3.0.5",
|
||||
"@vitest/coverage-v8": "^4.1.6",
|
||||
"@vitest/coverage-v8": "^5.0.0",
|
||||
"@vue/test-utils": "^2.4.10",
|
||||
"jsdom": "^30.0.0",
|
||||
"vitest": "^4.1.6"
|
||||
"vitest": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, onMounted, onBeforeUnmount, watch } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
hasMore: boolean
|
||||
loading: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
intersect: []
|
||||
}>()
|
||||
|
||||
const sentinelEl = ref<HTMLElement | null>(null)
|
||||
let observer: IntersectionObserver | null = null
|
||||
let observerGeneration = 0
|
||||
|
||||
function destroyObserver() {
|
||||
if (observer) {
|
||||
observer.disconnect()
|
||||
observer = null
|
||||
}
|
||||
}
|
||||
|
||||
async function createObserver() {
|
||||
const generation = ++observerGeneration
|
||||
destroyObserver()
|
||||
|
||||
// The sentinel is conditionally rendered from `hasMore`. Wait until Vue has
|
||||
// committed that DOM update before reading the template ref.
|
||||
await nextTick()
|
||||
|
||||
if (generation !== observerGeneration || !sentinelEl.value || !props.hasMore) {
|
||||
return
|
||||
}
|
||||
|
||||
// root: null (viewport) still resolves correctly through clipping/scrolling
|
||||
// ancestors (including Vuetify's internal v-virtual-scroll container), per the
|
||||
// IntersectionObserver spec — no need to locate that container explicitly.
|
||||
observer = new IntersectionObserver((entries) => {
|
||||
if (entries.some((entry) => entry.isIntersecting) && props.hasMore && !props.loading) {
|
||||
emit('intersect')
|
||||
}
|
||||
}, { root: null, rootMargin: '200px' })
|
||||
|
||||
observer.observe(sentinelEl.value)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void createObserver()
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
observerGeneration++
|
||||
destroyObserver()
|
||||
})
|
||||
watch(
|
||||
[() => props.hasMore, () => props.loading],
|
||||
() => {
|
||||
void createObserver()
|
||||
},
|
||||
{ flush: 'post' },
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="hasMore" ref="sentinelEl" class="files-load-more-sentinel">
|
||||
<v-progress-circular v-if="loading" indeterminate size="20" width="2" color="primary" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.files-load-more-sentinel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 48px;
|
||||
padding: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -6,11 +6,11 @@ import { formatSize, formatDate } from '@/utils/fileHelpers'
|
||||
import FileActionsMenu from '@/components/FileActionsMenu.vue'
|
||||
import FilePreview from '@/components/FilePreview.vue'
|
||||
import FilePreviewPopover from '@/components/viewer/FilePreviewPopover.vue'
|
||||
import FilesLoadMoreSentinel from '@/components/FilesLoadMoreSentinel.vue'
|
||||
|
||||
type ItemWithType = {
|
||||
item: CollectionObject | EntityObject
|
||||
type: 'collection' | 'entity'
|
||||
}
|
||||
type ItemWithType =
|
||||
| { item: CollectionObject | EntityObject; type: 'collection' | 'entity' }
|
||||
| { item: null; type: 'sentinel' }
|
||||
|
||||
type PreviewSource = (item: { id: string; meta?: Record<string, unknown> }) => string | Blob | Promise<string | Blob>
|
||||
|
||||
@@ -18,6 +18,8 @@ const props = defineProps<{
|
||||
collections: CollectionObject[]
|
||||
entities: EntityObject[]
|
||||
selectedIds: Set<string>
|
||||
hasMore?: boolean
|
||||
isLoadingMore?: boolean
|
||||
previewSource?: PreviewSource
|
||||
thumbnailSource?: PreviewSource
|
||||
}>()
|
||||
@@ -30,17 +32,25 @@ const emit = defineEmits<{
|
||||
'delete': [item: CollectionObject | EntityObject]
|
||||
'download': [item: CollectionObject | EntityObject]
|
||||
'show-details': [item: CollectionObject | EntityObject]
|
||||
'load-more': []
|
||||
}>()
|
||||
|
||||
// Combine collections and entities into a single list for virtual scrolling
|
||||
// Combine collections and entities into a single list for virtual scrolling; a
|
||||
// trailing sentinel row (rendered only once virtual-scroll actually mounts it)
|
||||
// drives the infinite-scroll "load more" trigger.
|
||||
const allItems = computed<ItemWithType[]>(() => [
|
||||
...props.collections.map(c => ({ item: c, type: 'collection' as const })),
|
||||
...props.entities.map(e => ({ item: e, type: 'entity' as const }))
|
||||
...props.entities.map(e => ({ item: e, type: 'entity' as const })),
|
||||
...(props.hasMore ? [{ item: null, type: 'sentinel' as const }] : []),
|
||||
])
|
||||
|
||||
function isCollection(wrapped: ItemWithType): wrapped is { item: CollectionObject; type: 'collection' } {
|
||||
return wrapped.type === 'collection'
|
||||
}
|
||||
|
||||
function isSentinel(wrapped: ItemWithType): wrapped is { item: null; type: 'sentinel' } {
|
||||
return wrapped.type === 'sentinel'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -60,9 +70,17 @@ function isCollection(wrapped: ItemWithType): wrapped is { item: CollectionObjec
|
||||
class="files-details-body"
|
||||
>
|
||||
<template #default="{ item: wrapped }">
|
||||
<!-- Load-more sentinel -->
|
||||
<FilesLoadMoreSentinel
|
||||
v-if="isSentinel(wrapped)"
|
||||
:has-more="!!hasMore"
|
||||
:loading="!!isLoadingMore"
|
||||
@intersect="emit('load-more')"
|
||||
/>
|
||||
|
||||
<!-- Folder row -->
|
||||
<div
|
||||
v-if="isCollection(wrapped)"
|
||||
v-else-if="isCollection(wrapped)"
|
||||
class="files-details-row"
|
||||
:class="{ 'files-details-row--selected': selectedIds.has(String(wrapped.item.identifier)) }"
|
||||
@click="emit('item-click', wrapped.item, $event)"
|
||||
|
||||
@@ -5,6 +5,7 @@ import { formatSize } from '@/utils/fileHelpers'
|
||||
import FileActionsMenu from '@/components/FileActionsMenu.vue'
|
||||
import FilePreview from '@/components/FilePreview.vue'
|
||||
import FilePreviewPopover from '@/components/viewer/FilePreviewPopover.vue'
|
||||
import FilesLoadMoreSentinel from '@/components/FilesLoadMoreSentinel.vue'
|
||||
|
||||
type PreviewSource = (item: { id: string; meta?: Record<string, unknown> }) => string | Blob | Promise<string | Blob>
|
||||
|
||||
@@ -12,6 +13,8 @@ const props = defineProps<{
|
||||
collections: CollectionObject[]
|
||||
entities: EntityObject[]
|
||||
selectedIds: Set<string>
|
||||
hasMore?: boolean
|
||||
isLoadingMore?: boolean
|
||||
previewSource?: PreviewSource
|
||||
thumbnailSource?: PreviewSource
|
||||
}>()
|
||||
@@ -24,6 +27,7 @@ const emit = defineEmits<{
|
||||
'delete': [item: CollectionObject | EntityObject]
|
||||
'download': [item: CollectionObject | EntityObject]
|
||||
'show-details': [item: CollectionObject | EntityObject]
|
||||
'load-more': []
|
||||
}>()
|
||||
</script>
|
||||
|
||||
@@ -90,6 +94,12 @@ const emit = defineEmits<{
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<FilesLoadMoreSentinel
|
||||
:has-more="!!hasMore"
|
||||
:loading="!!isLoadingMore"
|
||||
@intersect="emit('load-more')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -6,11 +6,11 @@ import { formatSize } from '@/utils/fileHelpers'
|
||||
import FileActionsMenu from '@/components/FileActionsMenu.vue'
|
||||
import FilePreview from '@/components/FilePreview.vue'
|
||||
import FilePreviewPopover from '@/components/viewer/FilePreviewPopover.vue'
|
||||
import FilesLoadMoreSentinel from '@/components/FilesLoadMoreSentinel.vue'
|
||||
|
||||
type ItemWithType = {
|
||||
item: CollectionObject | EntityObject
|
||||
type: 'collection' | 'entity'
|
||||
}
|
||||
type ItemWithType =
|
||||
| { item: CollectionObject | EntityObject; type: 'collection' | 'entity' }
|
||||
| { item: null; type: 'sentinel' }
|
||||
|
||||
type PreviewSource = (item: { id: string; meta?: Record<string, unknown> }) => string | Blob | Promise<string | Blob>
|
||||
|
||||
@@ -18,6 +18,8 @@ const props = defineProps<{
|
||||
collections: CollectionObject[]
|
||||
entities: EntityObject[]
|
||||
selectedIds: Set<string>
|
||||
hasMore?: boolean
|
||||
isLoadingMore?: boolean
|
||||
previewSource?: PreviewSource
|
||||
thumbnailSource?: PreviewSource
|
||||
}>()
|
||||
@@ -30,17 +32,25 @@ const emit = defineEmits<{
|
||||
'delete': [item: CollectionObject | EntityObject]
|
||||
'download': [item: CollectionObject | EntityObject]
|
||||
'show-details': [item: CollectionObject | EntityObject]
|
||||
'load-more': []
|
||||
}>()
|
||||
|
||||
// Combine collections and entities into a single list for virtual scrolling
|
||||
// Combine collections and entities into a single list for virtual scrolling; a
|
||||
// trailing sentinel row (rendered only once virtual-scroll actually mounts it)
|
||||
// drives the infinite-scroll "load more" trigger.
|
||||
const allItems = computed<ItemWithType[]>(() => [
|
||||
...props.collections.map(c => ({ item: c, type: 'collection' as const })),
|
||||
...props.entities.map(e => ({ item: e, type: 'entity' as const }))
|
||||
...props.entities.map(e => ({ item: e, type: 'entity' as const })),
|
||||
...(props.hasMore ? [{ item: null, type: 'sentinel' as const }] : []),
|
||||
])
|
||||
|
||||
function isCollection(wrapped: ItemWithType): wrapped is { item: CollectionObject; type: 'collection' } {
|
||||
return wrapped.type === 'collection'
|
||||
}
|
||||
|
||||
function isSentinel(wrapped: ItemWithType): wrapped is { item: null; type: 'sentinel' } {
|
||||
return wrapped.type === 'sentinel'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -50,9 +60,17 @@ function isCollection(wrapped: ItemWithType): wrapped is { item: CollectionObjec
|
||||
class="files-list-virtual pa-2"
|
||||
>
|
||||
<template #default="{ item: wrapped }">
|
||||
<!-- Load-more sentinel -->
|
||||
<FilesLoadMoreSentinel
|
||||
v-if="isSentinel(wrapped)"
|
||||
:has-more="!!hasMore"
|
||||
:loading="!!isLoadingMore"
|
||||
@intersect="emit('load-more')"
|
||||
/>
|
||||
|
||||
<!-- Folder -->
|
||||
<v-list-item
|
||||
v-if="isCollection(wrapped)"
|
||||
v-else-if="isCollection(wrapped)"
|
||||
:active="selectedIds.has(String(wrapped.item.identifier))"
|
||||
@click="($event: MouseEvent | KeyboardEvent) => emit('item-click', wrapped.item, $event)"
|
||||
>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* useFileEditor — resolves which registered editor can handle a given MIME type.
|
||||
*
|
||||
* Other modules register editors at the `documents_file_editor` integration
|
||||
* Other modules register editors at the `documents_editor` integration
|
||||
* point by including an entry in their `integrations.ts`:
|
||||
*
|
||||
* ```ts
|
||||
* documents_file_editor: [{
|
||||
* documents_editor: [{
|
||||
* id: 'my_editor',
|
||||
* meta: { mimeTypes: ['text/plain'] },
|
||||
* component: () => import('./components/MyEditor.vue'),
|
||||
@@ -21,7 +21,7 @@
|
||||
import { useIntegrationStore } from '@KTXC'
|
||||
import type { EntityObject } from '@DocumentsManager/models/entity'
|
||||
|
||||
const INTEGRATION_POINT = 'documents_file_editor'
|
||||
const INTEGRATION_POINT = 'documents_editor'
|
||||
|
||||
function mimeMatchesPattern(mime: string, pattern: string): boolean {
|
||||
if (pattern.endsWith('/*')) {
|
||||
|
||||
@@ -293,9 +293,7 @@ export function useFileUpload(options: UseFileUploadOptions) {
|
||||
try {
|
||||
// Create the folder
|
||||
const collection = await nodesStore.createCollection(
|
||||
currentProviderId(),
|
||||
currentServiceId(),
|
||||
parentId,
|
||||
`${currentProviderId()}:${currentServiceId()}:${parentId || ROOT_ID}`,
|
||||
{ label: folderName, owner: '' }
|
||||
)
|
||||
folderIdMap.set(folderPath, String(collection.identifier))
|
||||
@@ -342,9 +340,7 @@ export function useFileUpload(options: UseFileUploadOptions) {
|
||||
|
||||
// Create the entity
|
||||
const entity = await nodesStore.createEntity(
|
||||
currentProviderId(),
|
||||
currentServiceId(),
|
||||
targetCollection || ROOT_ID,
|
||||
`${currentProviderId()}:${currentServiceId()}:${targetCollection || ROOT_ID}`,
|
||||
{
|
||||
'@type': 'documents.properties',
|
||||
urid: null,
|
||||
@@ -360,10 +356,7 @@ export function useFileUpload(options: UseFileUploadOptions) {
|
||||
|
||||
// Write the content
|
||||
await nodesStore.writeEntity(
|
||||
currentProviderId(),
|
||||
currentServiceId(),
|
||||
targetCollection || ROOT_ID,
|
||||
String(entity.identifier),
|
||||
`${entity.provider}:${entity.service}:${entity.collection || ROOT_ID}:${entity.identifier}`,
|
||||
content
|
||||
)
|
||||
|
||||
|
||||
+58
-79
@@ -1,9 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, watch, nextTick, defineAsyncComponent } from 'vue'
|
||||
import { ref, computed, onMounted, onUnmounted, watch, nextTick, defineAsyncComponent } from 'vue'
|
||||
import { useDisplay } from 'vuetify'
|
||||
import { useModuleStore, useIntegrationStore, usePreviewStore } from '@KTXC'
|
||||
import { useDocumentManager, useDocumentSelection, useFileUpload, useFileEditor } from '@/composables'
|
||||
import type { ViewMode, SortField, SortOrder, BreadcrumbItem } from '@/types'
|
||||
import type { ListFilter, ListSort } from '@DocumentsManager/types'
|
||||
import { CollectionObject } from '@DocumentsManager/models/collection'
|
||||
import { EntityObject } from '@DocumentsManager/models/entity'
|
||||
import { ServiceObject } from '@DocumentsManager/models/service'
|
||||
@@ -118,14 +119,14 @@ const mediaViewerDialog = computed(() => {
|
||||
})
|
||||
|
||||
const viewerItems = computed<ViewerItem[]>(() =>
|
||||
sortedItems.value.entities.map(entityToViewerItem),
|
||||
documentManager.currentEntities.value.map(entityToViewerItem),
|
||||
)
|
||||
|
||||
function entityToViewerItem(entity: EntityObject): ViewerItem {
|
||||
return {
|
||||
id: String(entity.identifier ?? ''),
|
||||
title: entity.properties.label ?? String(entity.identifier ?? ''),
|
||||
mime: entity.properties.mime ?? '',
|
||||
mime: 'image/webp',
|
||||
meta: { collection: entity.collection ? String(entity.collection) : null },
|
||||
}
|
||||
}
|
||||
@@ -294,76 +295,45 @@ const breadcrumbs = computed<BreadcrumbItem[]>(() => {
|
||||
return items
|
||||
})
|
||||
|
||||
const sortedItems = computed(() => {
|
||||
const collections = [...documentManager.currentCollections.value]
|
||||
const entities = [...documentManager.currentEntities.value]
|
||||
|
||||
// Sort collections
|
||||
collections.sort((a, b) => {
|
||||
const aVal = sortField.value === 'label'
|
||||
? (a.properties.label || nodeId(a))
|
||||
: sortField.value === 'modifiedOn'
|
||||
? (a.modified?.getTime() ?? 0)
|
||||
: sortField.value === 'createdOn'
|
||||
? (a.created?.getTime() ?? 0)
|
||||
: ''
|
||||
const bVal = sortField.value === 'label'
|
||||
? (b.properties.label || nodeId(b))
|
||||
: sortField.value === 'modifiedOn'
|
||||
? (b.modified?.getTime() ?? 0)
|
||||
: sortField.value === 'createdOn'
|
||||
? (b.created?.getTime() ?? 0)
|
||||
: ''
|
||||
const cmp = String(aVal).localeCompare(String(bVal))
|
||||
return sortOrder.value === 'asc' ? cmp : -cmp
|
||||
})
|
||||
|
||||
// Sort entities
|
||||
entities.sort((a, b) => {
|
||||
const aVal = sortField.value === 'label'
|
||||
? (a.properties.label || nodeId(a))
|
||||
: sortField.value === 'mime'
|
||||
? (a.properties.mime || '')
|
||||
: sortField.value === 'size'
|
||||
? a.properties.size
|
||||
: sortField.value === 'modifiedOn'
|
||||
? (a.modified?.getTime() ?? 0)
|
||||
: sortField.value === 'createdOn'
|
||||
? (a.created?.getTime() ?? 0)
|
||||
: ''
|
||||
const bVal = sortField.value === 'label'
|
||||
? (b.properties.label || nodeId(b))
|
||||
: sortField.value === 'mime'
|
||||
? (b.properties.mime || '')
|
||||
: sortField.value === 'size'
|
||||
? b.properties.size
|
||||
: sortField.value === 'modifiedOn'
|
||||
? (b.modified?.getTime() ?? 0)
|
||||
: sortField.value === 'createdOn'
|
||||
? (b.created?.getTime() ?? 0)
|
||||
: ''
|
||||
const cmp = String(aVal).localeCompare(String(bVal))
|
||||
return sortOrder.value === 'asc' ? cmp : -cmp
|
||||
})
|
||||
|
||||
// Filter by search
|
||||
const filterFn = (item: CollectionObject | EntityObject) => {
|
||||
if (!searchQuery.value) return true
|
||||
const label = item instanceof EntityObject
|
||||
? (item.properties.label || nodeId(item))
|
||||
: (item.properties.label || nodeId(item))
|
||||
return label.toLowerCase().includes(searchQuery.value.toLowerCase())
|
||||
}
|
||||
|
||||
return {
|
||||
collections: collections.filter(filterFn),
|
||||
entities: entities.filter(filterFn),
|
||||
const hasItems = computed(() =>
|
||||
documentManager.currentCollections.value.length > 0 || documentManager.currentEntities.value.length > 0
|
||||
)
|
||||
|
||||
// Search/sort are server-driven: build the current filter/sort and reset-load
|
||||
// the current location whenever either changes.
|
||||
function buildFilter(): ListFilter | undefined {
|
||||
return searchQuery.value ? { label: searchQuery.value } : undefined
|
||||
}
|
||||
|
||||
function buildSort(): ListSort {
|
||||
return { [sortField.value]: sortOrder.value === 'asc' }
|
||||
}
|
||||
|
||||
async function reload() {
|
||||
await documentManager.resetAndLoad(buildFilter(), buildSort())
|
||||
}
|
||||
|
||||
let searchDebounceTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
watch(searchQuery, () => {
|
||||
if (searchDebounceTimer !== null) {
|
||||
clearTimeout(searchDebounceTimer)
|
||||
}
|
||||
searchDebounceTimer = setTimeout(() => {
|
||||
searchDebounceTimer = null
|
||||
reload()
|
||||
}, 300)
|
||||
})
|
||||
|
||||
const hasItems = computed(() =>
|
||||
sortedItems.value.collections.length > 0 || sortedItems.value.entities.length > 0
|
||||
)
|
||||
watch([sortField, sortOrder], () => {
|
||||
reload()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (searchDebounceTimer !== null) {
|
||||
clearTimeout(searchDebounceTimer)
|
||||
}
|
||||
})
|
||||
|
||||
const hasSelection = computed(() => selection.hasSelection.value)
|
||||
|
||||
@@ -695,7 +665,7 @@ async function readEntriesRecursively(
|
||||
async function handleUploadAll() {
|
||||
try {
|
||||
await upload.uploadAll()
|
||||
await documentManager.refresh()
|
||||
await reload()
|
||||
notify('Uploads completed', 'success')
|
||||
} catch (error) {
|
||||
console.error('Failed to upload files:', error)
|
||||
@@ -712,7 +682,7 @@ function handleUploadDialogClose() {
|
||||
// Refresh
|
||||
async function handleRefresh() {
|
||||
try {
|
||||
await documentManager.refresh()
|
||||
await reload()
|
||||
} catch (error) {
|
||||
console.error('Failed to refresh files:', error)
|
||||
notify(getErrorMessage(error, 'Failed to refresh files'), 'error')
|
||||
@@ -725,7 +695,7 @@ onMounted(async () => {
|
||||
await documentManager.initialize()
|
||||
await servicesStore.list()
|
||||
syncActiveService(availableServices.value)
|
||||
await documentManager.refresh()
|
||||
await reload()
|
||||
console.log('[Files] - Initialized with:', {
|
||||
provider: activeProviderId.value,
|
||||
service: activeServiceId.value,
|
||||
@@ -818,9 +788,11 @@ onMounted(async () => {
|
||||
<!-- Grid View -->
|
||||
<FilesGridView
|
||||
v-else-if="viewMode === 'grid'"
|
||||
:collections="sortedItems.collections"
|
||||
:entities="sortedItems.entities"
|
||||
:collections="documentManager.currentCollections.value"
|
||||
:entities="documentManager.currentEntities.value"
|
||||
:selected-ids="selectedIds"
|
||||
:has-more="documentManager.hasMore.value"
|
||||
:is-loading-more="documentManager.isLoadingMore.value"
|
||||
:preview-source="previewsAvailable ? resolvePreviewSource : undefined"
|
||||
:thumbnail-source="previewsAvailable ? resolveThumbnailSource : undefined"
|
||||
@item-click="handleItemClick"
|
||||
@@ -830,14 +802,17 @@ onMounted(async () => {
|
||||
@delete="handleDeleteItem"
|
||||
@download="handleDownloadItem"
|
||||
@show-details="handleShowDetails"
|
||||
@load-more="documentManager.loadMore"
|
||||
/>
|
||||
|
||||
<!-- List View -->
|
||||
<FilesListView
|
||||
v-else-if="viewMode === 'list'"
|
||||
:collections="sortedItems.collections"
|
||||
:entities="sortedItems.entities"
|
||||
:collections="documentManager.currentCollections.value"
|
||||
:entities="documentManager.currentEntities.value"
|
||||
:selected-ids="selectedIds"
|
||||
:has-more="documentManager.hasMore.value"
|
||||
:is-loading-more="documentManager.isLoadingMore.value"
|
||||
:preview-source="previewsAvailable ? resolvePreviewSource : undefined"
|
||||
:thumbnail-source="previewsAvailable ? resolveThumbnailSource : undefined"
|
||||
@item-click="handleItemClick"
|
||||
@@ -847,14 +822,17 @@ onMounted(async () => {
|
||||
@delete="handleDeleteItem"
|
||||
@download="handleDownloadItem"
|
||||
@show-details="handleShowDetails"
|
||||
@load-more="documentManager.loadMore"
|
||||
/>
|
||||
|
||||
<!-- Details View -->
|
||||
<FilesDetailsView
|
||||
v-else-if="viewMode === 'details'"
|
||||
:collections="sortedItems.collections"
|
||||
:entities="sortedItems.entities"
|
||||
:collections="documentManager.currentCollections.value"
|
||||
:entities="documentManager.currentEntities.value"
|
||||
:selected-ids="selectedIds"
|
||||
:has-more="documentManager.hasMore.value"
|
||||
:is-loading-more="documentManager.isLoadingMore.value"
|
||||
:preview-source="previewsAvailable ? resolvePreviewSource : undefined"
|
||||
:thumbnail-source="previewsAvailable ? resolveThumbnailSource : undefined"
|
||||
@item-click="handleItemClick"
|
||||
@@ -864,6 +842,7 @@ onMounted(async () => {
|
||||
@delete="handleDeleteItem"
|
||||
@download="handleDownloadItem"
|
||||
@show-details="handleShowDetails"
|
||||
@load-more="documentManager.loadMore"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
import { computed, ref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import { useProvidersStore, useServicesStore, useNodesStore, ROOT_ID } from '@DocumentsManager/stores'
|
||||
import { CollectionObject } from '@DocumentsManager/models/collection'
|
||||
import { EntityObject } from '@DocumentsManager/models/entity'
|
||||
import type { SortField, SortOrder, ViewMode, BreadcrumbItem } from '@/types'
|
||||
|
||||
type NodeRecord = CollectionObject | EntityObject
|
||||
|
||||
export const useDocumentsStore = defineStore('documentsStore', () => {
|
||||
const providersStore = useProvidersStore()
|
||||
const servicesStore = useServicesStore()
|
||||
const nodesStore = useNodesStore()
|
||||
|
||||
const activeProviderId = ref('default')
|
||||
const activeServiceId = ref<string | number>('personal')
|
||||
const currentLocation = ref<string>(ROOT_ID)
|
||||
|
||||
const viewMode = ref<ViewMode>('grid')
|
||||
const sortField = ref<SortField>('label')
|
||||
const sortOrder = ref<SortOrder>('asc')
|
||||
const searchQuery = ref('')
|
||||
const sidebarVisible = ref(true)
|
||||
|
||||
const transceiving = computed(() =>
|
||||
providersStore.transceiving || servicesStore.transceiving || nodesStore.transceiving,
|
||||
)
|
||||
|
||||
const provider = computed(() => providersStore.provider(activeProviderId.value))
|
||||
const service = computed(() => servicesStore.service(activeProviderId.value, activeServiceId.value))
|
||||
|
||||
const currentCollections = computed(() =>
|
||||
nodesStore.getChildCollections(activeProviderId.value, activeServiceId.value, currentLocation.value),
|
||||
)
|
||||
|
||||
const currentEntities = computed(() =>
|
||||
nodesStore.getChildEntities(activeProviderId.value, activeServiceId.value, currentLocation.value),
|
||||
)
|
||||
|
||||
const breadcrumbs = computed<BreadcrumbItem[]>(() => {
|
||||
const nodes = nodesStore.getPath(activeProviderId.value, activeServiceId.value, currentLocation.value)
|
||||
return [
|
||||
{ id: ROOT_ID, label: 'Home', isRoot: true },
|
||||
...nodes.map((node) => ({
|
||||
id: String(node.identifier),
|
||||
label: node.properties.label,
|
||||
isRoot: false,
|
||||
})),
|
||||
]
|
||||
})
|
||||
|
||||
function sortCollections(items: CollectionObject[]): CollectionObject[] {
|
||||
return [...items].sort((a, b) => {
|
||||
const aVal = sortField.value === 'label'
|
||||
? a.properties.label
|
||||
: sortField.value === 'modifiedOn'
|
||||
? (a.modified?.getTime() ?? 0)
|
||||
: sortField.value === 'createdOn'
|
||||
? (a.created?.getTime() ?? 0)
|
||||
: ''
|
||||
const bVal = sortField.value === 'label'
|
||||
? b.properties.label
|
||||
: sortField.value === 'modifiedOn'
|
||||
? (b.modified?.getTime() ?? 0)
|
||||
: sortField.value === 'createdOn'
|
||||
? (b.created?.getTime() ?? 0)
|
||||
: ''
|
||||
|
||||
const cmp = String(aVal).localeCompare(String(bVal))
|
||||
return sortOrder.value === 'asc' ? cmp : -cmp
|
||||
})
|
||||
}
|
||||
|
||||
function sortEntities(items: EntityObject[]): EntityObject[] {
|
||||
return [...items].sort((a, b) => {
|
||||
const aVal = sortField.value === 'label'
|
||||
? a.properties.label
|
||||
: sortField.value === 'mime'
|
||||
? (a.properties.mime ?? '')
|
||||
: sortField.value === 'size'
|
||||
? a.properties.size
|
||||
: sortField.value === 'modifiedOn'
|
||||
? (a.modified?.getTime() ?? 0)
|
||||
: sortField.value === 'createdOn'
|
||||
? (a.created?.getTime() ?? 0)
|
||||
: ''
|
||||
const bVal = sortField.value === 'label'
|
||||
? b.properties.label
|
||||
: sortField.value === 'mime'
|
||||
? (b.properties.mime ?? '')
|
||||
: sortField.value === 'size'
|
||||
? b.properties.size
|
||||
: sortField.value === 'modifiedOn'
|
||||
? (b.modified?.getTime() ?? 0)
|
||||
: sortField.value === 'createdOn'
|
||||
? (b.created?.getTime() ?? 0)
|
||||
: ''
|
||||
|
||||
const cmp = String(aVal).localeCompare(String(bVal))
|
||||
return sortOrder.value === 'asc' ? cmp : -cmp
|
||||
})
|
||||
}
|
||||
|
||||
function filterNode(node: NodeRecord): boolean {
|
||||
if (!searchQuery.value) return true
|
||||
return node.properties.label.toLowerCase().includes(searchQuery.value.toLowerCase())
|
||||
}
|
||||
|
||||
const sortedItems = computed(() => ({
|
||||
collections: sortCollections(currentCollections.value).filter(filterNode),
|
||||
entities: sortEntities(currentEntities.value).filter(filterNode),
|
||||
}))
|
||||
|
||||
const hasItems = computed(() =>
|
||||
sortedItems.value.collections.length > 0 || sortedItems.value.entities.length > 0,
|
||||
)
|
||||
|
||||
const isAtRoot = computed(() => currentLocation.value === ROOT_ID)
|
||||
|
||||
async function initialize() {
|
||||
await providersStore.list([activeProviderId.value])
|
||||
await servicesStore.list()
|
||||
await refresh()
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
await nodesStore.fetchNodes(activeProviderId.value, activeServiceId.value, currentLocation.value)
|
||||
}
|
||||
|
||||
async function navigateTo(collectionId: string | null) {
|
||||
currentLocation.value = collectionId || ROOT_ID
|
||||
await refresh()
|
||||
}
|
||||
|
||||
async function navigateToRoot() {
|
||||
await navigateTo(ROOT_ID)
|
||||
}
|
||||
|
||||
async function navigateUp() {
|
||||
if (currentLocation.value === ROOT_ID) return
|
||||
const currentNode = nodesStore.getNode(activeProviderId.value, activeServiceId.value, currentLocation.value)
|
||||
if (!currentNode) return
|
||||
const parentId = currentNode.collection ? String(currentNode.collection) : ROOT_ID
|
||||
await navigateTo(parentId)
|
||||
}
|
||||
|
||||
async function createFolder(label: string) {
|
||||
await nodesStore.createCollection(
|
||||
activeProviderId.value,
|
||||
activeServiceId.value,
|
||||
currentLocation.value,
|
||||
{ label, owner: '' },
|
||||
)
|
||||
await refresh()
|
||||
}
|
||||
|
||||
async function renameNode(node: NodeRecord, label: string) {
|
||||
if (node instanceof CollectionObject) {
|
||||
await nodesStore.updateCollection(
|
||||
activeProviderId.value,
|
||||
activeServiceId.value,
|
||||
node.identifier,
|
||||
{ label, owner: node.properties.owner },
|
||||
)
|
||||
} else {
|
||||
await nodesStore.updateEntity(
|
||||
activeProviderId.value,
|
||||
activeServiceId.value,
|
||||
node.collection,
|
||||
node.identifier,
|
||||
{
|
||||
'@type': 'documents.properties',
|
||||
urid: node.properties.urid,
|
||||
size: node.properties.size,
|
||||
label,
|
||||
mime: node.properties.mime,
|
||||
format: node.properties.format,
|
||||
encoding: node.properties.encoding,
|
||||
},
|
||||
)
|
||||
}
|
||||
await refresh()
|
||||
}
|
||||
|
||||
async function deleteNode(node: NodeRecord) {
|
||||
if (node instanceof CollectionObject) {
|
||||
await nodesStore.deleteCollection(activeProviderId.value, activeServiceId.value, node.identifier)
|
||||
} else {
|
||||
await nodesStore.deleteEntity(activeProviderId.value, activeServiceId.value, node.collection, node.identifier)
|
||||
}
|
||||
await refresh()
|
||||
}
|
||||
|
||||
return {
|
||||
activeProviderId,
|
||||
activeServiceId,
|
||||
currentLocation,
|
||||
viewMode,
|
||||
sortField,
|
||||
sortOrder,
|
||||
searchQuery,
|
||||
sidebarVisible,
|
||||
transceiving,
|
||||
provider,
|
||||
service,
|
||||
currentCollections,
|
||||
currentEntities,
|
||||
sortedItems,
|
||||
hasItems,
|
||||
breadcrumbs,
|
||||
isAtRoot,
|
||||
initialize,
|
||||
refresh,
|
||||
navigateTo,
|
||||
navigateToRoot,
|
||||
navigateUp,
|
||||
createFolder,
|
||||
renameNode,
|
||||
deleteNode,
|
||||
ROOT_ID,
|
||||
}
|
||||
})
|
||||
@@ -1 +0,0 @@
|
||||
export { useDocumentsStore } from './documentsStore'
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
export type ViewMode = 'grid' | 'list' | 'details'
|
||||
|
||||
export type SortField = 'label' | 'size' | 'modifiedOn' | 'createdOn' | 'mime'
|
||||
export type SortField = 'label' | 'size' | 'modifiedOn' | 'createdOn'
|
||||
|
||||
export type SortOrder = 'asc' | 'desc'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user