Compare commits

..
Author SHA1 Message Date
Dominik Pschenitschni fb6c96f6c6 wip2 2025-01-17 15:00:30 +01:00
Dominik Pschenitschni b4875a839a wip: try out to fix beforeAuth issue 2025-01-17 15:00:30 +01:00
Dominik Pschenitschni 4fa3389232 wip 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni 96586ad193 feat: unify project.view & project.index 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni 6741b1b6eb fix: 404 route 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni a057523314 fix: settings 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni 37e8cba630 feat: re-add route names, meta and props via definePage 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni 6828b6a10e fix: merge project.create with project.createFromParent 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni 2501c07bfb feat: move migrators to helpers 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni ecbb16c63e feat: move useGanttFilters and useGanttTaskList to composables 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni cb0c1d90eb feat: ShowTasks 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni f29eb76318 feat: register and share routes 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni 05aeba483e feat: move to file-based routes 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni c0651b9927 feat: eslint 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni 0efa70c5ee feat: router hot update 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni beb2e1f9f9 feat: install unplugin-vue-router 2025-01-17 15:00:29 +01:00
Dominik Pschenitschni 356e83a6c9 feat: inline dynamic component definitions in routes 2025-01-17 14:59:59 +01:00
87 changed files with 727 additions and 651 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
name: Bug Report
description: Found something you weren't expecting? Report it here!
type: Bug
labels: kind/bug
body:
- type: markdown
attributes:
@@ -49,4 +49,4 @@ body:
id: screenshots
attributes:
label: Screenshots
description: If this issue involves the Web Interface, please provide one or more screenshots
description: If this issue involves the Web Interface, please provide one or more screenshots
+6 -1
View File
@@ -30,5 +30,10 @@
],
"i18n-ally.sortKeys": true,
"i18n-ally.keepFulfilled": true,
"i18n-ally.keystyle": "nested"
"i18n-ally.keystyle": "nested",
// unplugin-vue-router
// https://uvr.esm.is/introduction.html#setup
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.preferences.autoImportFileExcludePatterns": ["vue-router/auto$"]
}
+4 -1
View File
@@ -1 +1,4 @@
declare module 'postcss-easing-gradients';
declare module 'postcss-easing-gradients' {
import postcssEasingGradients from 'postcss-easing-gradients'
export default postcssEasingGradients
}
+1
View File
@@ -2,6 +2,7 @@
/// <reference types="vite-svg-loader" />
/// <reference types="cypress" />
/// <reference types="@histoire/plugin-vue/components" />
/// <reference types="unplugin-vue-router/client" />
interface ImportMetaEnv {
readonly VIKUNJA_API_URL?: string
+10 -1
View File
@@ -84,5 +84,14 @@ export default [
// 'cypress/*',
// ],
},
{
// unplugin-vue-router
// https://uvr.esm.is/guide/eslint.html#eslint
settings: {
'import/core-modules': ['vue-router/auto-routes'],
},
globals: {
'definePage': 'readonly',
},
},
]
+3 -2
View File
@@ -100,6 +100,7 @@
"tailwindcss": "3.4.17",
"tippy.js": "6.3.7",
"ufo": "1.5.4",
"unplugin-vue-router": "0.10.9",
"vue": "3.5.13",
"vue-advanced-cropper": "2.8.9",
"vue-flatpickr-component": "11.0.5",
@@ -130,7 +131,7 @@
"@vue/tsconfig": "0.7.0",
"autoprefixer": "10.4.20",
"browserslist": "4.24.4",
"caniuse-lite": "1.0.30001695",
"caniuse-lite": "1.0.30001692",
"csstype": "3.1.3",
"cypress": "14.0.0",
"esbuild": "0.24.2",
@@ -152,7 +153,7 @@
"vite-plugin-sentry": "1.4.0",
"vite-plugin-vue-devtools": "7.7.0",
"vite-svg-loader": "5.1.0",
"vitest": "3.0.2",
"vitest": "3.0.1",
"vue-tsc": "2.2.0",
"wait-on": "8.0.2",
"workbox-cli": "7.3.0"
+263 -110
View File
@@ -169,6 +169,9 @@ importers:
ufo:
specifier: 1.5.4
version: 1.5.4
unplugin-vue-router:
specifier: 0.10.9
version: 0.10.9(rollup@4.30.1)(vue-router@4.5.0(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3))
vue:
specifier: 3.5.13
version: 3.5.13(typescript@5.7.3)
@@ -208,10 +211,10 @@ importers:
version: 9.4.0
'@histoire/plugin-screenshot':
specifier: 0.17.17
version: 0.17.17(histoire@0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)))
version: 0.17.17(histoire@0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)))
'@histoire/plugin-vue':
specifier: 0.17.17
version: 0.17.17(histoire@0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)))(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))(vue@3.5.13(typescript@5.7.3))
version: 0.17.17(histoire@0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)))(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))
'@tsconfig/node22':
specifier: 22.0.0
version: 22.0.0
@@ -238,7 +241,7 @@ importers:
version: 8.20.0(eslint@9.18.0(jiti@1.21.6))(typescript@5.7.3)
'@vitejs/plugin-vue':
specifier: 5.2.1
version: 5.2.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))(vue@3.5.13(typescript@5.7.3))
version: 5.2.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))
'@vue/eslint-config-typescript':
specifier: 14.3.0
version: 14.3.0(eslint-plugin-vue@9.32.0(eslint@9.18.0(jiti@1.21.6)))(eslint@9.18.0(jiti@1.21.6))(typescript@5.7.3)
@@ -255,8 +258,8 @@ importers:
specifier: 4.24.4
version: 4.24.4
caniuse-lite:
specifier: 1.0.30001695
version: 1.0.30001695
specifier: 1.0.30001692
version: 1.0.30001692
csstype:
specifier: 3.1.3
version: 3.1.3
@@ -277,7 +280,7 @@ importers:
version: 16.6.0
histoire:
specifier: 0.17.17
version: 0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
version: 0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
postcss:
specifier: 8.5.1
version: 8.5.1
@@ -307,22 +310,22 @@ importers:
version: 3.0.0
vite:
specifier: 6.0.7
version: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
version: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
vite-plugin-pwa:
specifier: 0.21.1
version: 0.21.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))(workbox-build@7.3.0)(workbox-window@7.3.0)
version: 0.21.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))(workbox-build@7.3.0)(workbox-window@7.3.0)
vite-plugin-sentry:
specifier: 1.4.0
version: 1.4.0(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
version: 1.4.0(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
vite-plugin-vue-devtools:
specifier: 7.7.0
version: 7.7.0(rollup@4.30.1)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))(vue@3.5.13(typescript@5.7.3))
version: 7.7.0(rollup@4.30.1)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))
vite-svg-loader:
specifier: 5.1.0
version: 5.1.0(vue@3.5.13(typescript@5.7.3))
vitest:
specifier: 3.0.2
version: 3.0.2(@types/node@22.10.7)(happy-dom@16.6.0)(jiti@1.21.6)(jsdom@20.0.3)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
specifier: 3.0.1
version: 3.0.1(@types/node@22.10.7)(happy-dom@16.6.0)(jiti@1.21.6)(jsdom@20.0.3)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
vue-tsc:
specifier: 2.2.0
version: 2.2.0(typescript@5.7.3)
@@ -473,6 +476,11 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
'@babel/parser@7.26.5':
resolution: {integrity: sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==}
engines: {node: '>=6.0.0'}
hasBin: true
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9':
resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==}
engines: {node: '>=6.9.0'}
@@ -889,6 +897,10 @@ packages:
resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==}
engines: {node: '>=6.9.0'}
'@babel/types@7.26.5':
resolution: {integrity: sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==}
engines: {node: '>=6.9.0'}
'@bufbuild/protobuf@2.2.2':
resolution: {integrity: sha512-UNtPCbrwrenpmrXuRwn9jYpPoweNXj8X5sMvYgsqYyaH8jQ6LfUJSk3dJLnBK+6sfYPrF4iAIo5sd5HQ+tg75A==}
@@ -2514,11 +2526,11 @@ packages:
vite: ^5.0.0 || ^6.0.0
vue: ^3.2.25
'@vitest/expect@3.0.2':
resolution: {integrity: sha512-dKSHLBcoZI+3pmP5hiZ7I5grNru2HRtEW8Z5Zp4IXog8QYcxhlox7JUPyIIFWfN53+3HW3KPLIl6nSzUGgKSuQ==}
'@vitest/expect@3.0.1':
resolution: {integrity: sha512-oPrXe8dwvQdzUxQFWwibY97/smQ6k8iPVeSf09KEvU1yWzu40G6naHExY0lUgjnTPWMRGQOJnhMBb8lBu48feg==}
'@vitest/mocker@3.0.2':
resolution: {integrity: sha512-Hr09FoBf0jlwwSyzIF4Xw31OntpO3XtZjkccpcBf8FeVW3tpiyKlkeUzxS/txzHqpUCNIX157NaTySxedyZLvA==}
'@vitest/mocker@3.0.1':
resolution: {integrity: sha512-5letLsVdFhReCPws/SNwyekBCyi4w2IusycV4T7eVdt2mfellS2yKDrEmnE5KPCHr0Ez5xCZVJbJws3ckuNNgQ==}
peerDependencies:
msw: ^2.4.9
vite: ^5.0.0 || ^6.0.0
@@ -2528,20 +2540,20 @@ packages:
vite:
optional: true
'@vitest/pretty-format@3.0.2':
resolution: {integrity: sha512-yBohcBw/T/p0/JRgYD+IYcjCmuHzjC3WLAKsVE4/LwiubzZkE8N49/xIQ/KGQwDRA8PaviF8IRO8JMWMngdVVQ==}
'@vitest/pretty-format@3.0.1':
resolution: {integrity: sha512-FnyGQ9eFJ/Dnqg3jCvq9O6noXtxbZhOlSvNLZsCGJxhsGiZ5LDepmsTCizRfyGJt4Q6pJmZtx7rO/qqr9R9gDA==}
'@vitest/runner@3.0.2':
resolution: {integrity: sha512-GHEsWoncrGxWuW8s405fVoDfSLk6RF2LCXp6XhevbtDjdDme1WV/eNmUueDfpY1IX3MJaCRelVCEXsT9cArfEg==}
'@vitest/runner@3.0.1':
resolution: {integrity: sha512-LfVbbYOduTVx8PnYFGH98jpgubHBefIppbPQJBSlgjnRRlaX/KR6J46htECUHpf+ElJZ4xxssAfEz/Cb2iIMYA==}
'@vitest/snapshot@3.0.2':
resolution: {integrity: sha512-h9s67yD4+g+JoYG0zPCo/cLTabpDqzqNdzMawmNPzDStTiwxwkyYM1v5lWE8gmGv3SVJ2DcxA2NpQJZJv9ym3g==}
'@vitest/snapshot@3.0.1':
resolution: {integrity: sha512-ZYV+iw2lGyc4QY2xt61b7Y3NJhSAO7UWcYWMcV0UnMrkXa8hXtfZES6WAk4g7Jr3p4qJm1P0cgDcOFyY5me+Ug==}
'@vitest/spy@3.0.2':
resolution: {integrity: sha512-8mI2iUn+PJFMT44e3ISA1R+K6ALVs47W6eriDTfXe6lFqlflID05MB4+rIFhmDSLBj8iBsZkzBYlgSkinxLzSQ==}
'@vitest/spy@3.0.1':
resolution: {integrity: sha512-HnGJB3JFflnlka4u7aD0CfqrEtX3FgNaZAar18/KIhfo0r/WADn9PhBfiqAmNw4R/xaRcLzLPFXDwEQV1vHlJA==}
'@vitest/utils@3.0.2':
resolution: {integrity: sha512-Qu01ZYZlgHvDP02JnMBRpX43nRaZtNpIzw3C1clDXmn8eakgX6iQVGzTQ/NjkIr64WD8ioqOjkaYRVvHQI5qiw==}
'@vitest/utils@3.0.1':
resolution: {integrity: sha512-i+Gm61rfIeSitPUsu4ZcWqucfb18ShAanRpOG6KlXfd1j6JVK5XxO2Z6lEmfjMnAQRIvvLtJ3JByzDTv347e8w==}
'@volar/language-core@2.4.11':
resolution: {integrity: sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==}
@@ -2552,6 +2564,15 @@ packages:
'@volar/typescript@2.4.11':
resolution: {integrity: sha512-2DT+Tdh88Spp5PyPbqhyoYavYCPDsqbHLFwcUI9K1NlY1YgUJvujGdrqUp0zWxnW7KWNTr3xSpMuv2WnaTKDAw==}
'@vue-macros/common@1.15.1':
resolution: {integrity: sha512-O0ZXaladWXwHplQnSjxLbB/G1KpdWCUNJPNYVHIxHonGex1BGpoB4fBZZLgddHgAiy18VZG/Iu5L0kwG+SV7JQ==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.2.25
peerDependenciesMeta:
vue:
optional: true
'@vue/babel-helper-vue-transform-on@1.2.5':
resolution: {integrity: sha512-lOz4t39ZdmU4DJAa2hwPYmKc8EsuGa2U0L9KaZaOJUt0UwQNjNA3AZTq6uEivhOKhhG1Wvy96SvYBoFmCg3uuw==}
@@ -2786,6 +2807,14 @@ packages:
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
engines: {node: '>=12'}
ast-kit@1.3.2:
resolution: {integrity: sha512-gdvX700WVC6sHCJQ7bJGfDvtuKAh6Sa6weIZROxfzUZKP7BjvB8y0SMlM/o4omSQ3L60PQSJROBJsb0vEViVnA==}
engines: {node: '>=16.14.0'}
ast-walker-scope@0.6.2:
resolution: {integrity: sha512-1UWOyC50xI3QZkRuDj6PqDtpm1oHWtYs+NQGwqL/2R11eN3Q81PHAHPM0SWW3BNQm53UDwS//Jv8L4CCVLM1bQ==}
engines: {node: '>=16.14.0'}
astral-regex@2.0.0:
resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
engines: {node: '>=8'}
@@ -2947,8 +2976,8 @@ packages:
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
engines: {node: '>=6'}
caniuse-lite@1.0.30001695:
resolution: {integrity: sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==}
caniuse-lite@1.0.30001692:
resolution: {integrity: sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==}
capital-case@1.0.4:
resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==}
@@ -3098,6 +3127,9 @@ packages:
confbox@0.1.7:
resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==}
confbox@0.1.8:
resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
config-chain@1.1.13:
resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
@@ -4452,6 +4484,10 @@ packages:
enquirer:
optional: true
local-pkg@0.5.1:
resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==}
engines: {node: '>=14'}
locate-path@5.0.0:
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
engines: {node: '>=8'}
@@ -4510,6 +4546,10 @@ packages:
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
magic-string-ast@0.6.3:
resolution: {integrity: sha512-C9sgUzVZtUtzCBoMdYtwrIRQ4IucGRFGgdhkjL7PXsVfPYmTuWtewqzk7dlipaCMWH/gOYehW9rgMoa4Oebtpw==}
engines: {node: '>=16.14.0'}
magic-string@0.25.9:
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
@@ -4639,6 +4679,9 @@ packages:
mlly@1.7.1:
resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==}
mlly@1.7.4:
resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==}
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
@@ -4919,8 +4962,8 @@ packages:
pathe@1.1.2:
resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
pathe@2.0.1:
resolution: {integrity: sha512-6jpjMpOth5S9ITVu5clZ7NOgHNsv5vRQdheL9ztp2vZmM6fRbLvyua1tiBIL4lk8SAe3ARzeXEly6siXCjDHDw==}
pathe@2.0.2:
resolution: {integrity: sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==}
pathval@2.0.0:
resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==}
@@ -4979,6 +5022,9 @@ packages:
pkg-types@1.2.0:
resolution: {integrity: sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==}
pkg-types@1.3.1:
resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
possible-typed-array-names@1.0.0:
resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==}
engines: {node: '>= 0.4'}
@@ -5639,6 +5685,9 @@ packages:
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
engines: {node: '>=v12.22.7'}
scule@1.3.0:
resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==}
section-matter@1.0.0:
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
engines: {node: '>=4'}
@@ -6184,10 +6233,22 @@ packages:
html-webpack-plugin:
optional: true
unplugin-vue-router@0.10.9:
resolution: {integrity: sha512-DXmC0GMcROOnCmN56GRvi1bkkG1BnVs4xJqNvucBUeZkmB245URvtxOfbo3H6q4SOUQQbLPYWd6InzvjRh363A==}
peerDependencies:
vue-router: ^4.4.0
peerDependenciesMeta:
vue-router:
optional: true
unplugin@1.12.2:
resolution: {integrity: sha512-bEqQxeC7rxtxPZ3M5V4Djcc4lQqKPgGe3mAWZvxcSmX5jhGxll19NliaRzQSQPrk4xJZSGniK3puLWpRuZN7VQ==}
engines: {node: '>=14.0.0'}
unplugin@2.0.0-beta.1:
resolution: {integrity: sha512-2qzQo5LN2DmUZXkWDHvGKLF5BP0WN+KthD6aPnPJ8plRBIjv4lh5O07eYcSxgO2znNw9s4MNhEO1sB+JDllDbQ==}
engines: {node: '>=18.12.0'}
untildify@4.0.0:
resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==}
engines: {node: '>=8'}
@@ -6253,8 +6314,8 @@ packages:
engines: {node: '>=v14.18.0'}
hasBin: true
vite-node@3.0.2:
resolution: {integrity: sha512-hsEQerBAHvVAbv40m3TFQe/lTEbOp7yDpyqMJqr2Tnd+W58+DEYOt+fluQgekOePcsNBmR77lpVAnIU2Xu4SvQ==}
vite-node@3.0.1:
resolution: {integrity: sha512-PoH9mCNsSZQXl3gdymM5IE4WR0k0WbnFd89nAyyDvltF2jVGdFcI8vpB1PBdKTcjAR7kkYiHSlIO68X/UT8Q1A==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
@@ -6373,15 +6434,15 @@ packages:
yaml:
optional: true
vitest@3.0.2:
resolution: {integrity: sha512-5bzaHakQ0hmVVKLhfh/jXf6oETDBtgPo8tQCHYB+wftNgFJ+Hah67IsWc8ivx4vFL025Ow8UiuTf4W57z4izvQ==}
vitest@3.0.1:
resolution: {integrity: sha512-SWKoSAkxtFHqt8biR3eN53dzmeWkigEpyipqfblcsoAghVvoFMpxQEj0gc7AajMi6Ra49fjcTN6v4AxklmS4aQ==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
'@vitest/browser': 3.0.2
'@vitest/ui': 3.0.2
'@vitest/browser': 3.0.1
'@vitest/ui': 3.0.1
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
@@ -6674,6 +6735,11 @@ packages:
engines: {node: '>= 14'}
hasBin: true
yaml@2.7.0:
resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==}
engines: {node: '>= 14'}
hasBin: true
yargs-parser@18.1.3:
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
engines: {node: '>=6'}
@@ -6900,6 +6966,10 @@ snapshots:
dependencies:
'@babel/types': 7.26.0
'@babel/parser@7.26.5':
dependencies:
'@babel/types': 7.26.5
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.0)':
dependencies:
'@babel/core': 7.26.0
@@ -7427,6 +7497,11 @@ snapshots:
'@babel/helper-string-parser': 7.25.9
'@babel/helper-validator-identifier': 7.25.9
'@babel/types@7.26.5':
dependencies:
'@babel/helper-string-parser': 7.25.9
'@babel/helper-validator-identifier': 7.25.9
'@bufbuild/protobuf@2.2.2': {}
'@cliqz/adblocker-content@1.33.0':
@@ -8018,10 +8093,10 @@ snapshots:
dependencies:
'@hapi/hoek': 9.3.0
'@histoire/app@0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))':
'@histoire/app@0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))':
dependencies:
'@histoire/controls': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
'@histoire/shared': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
'@histoire/controls': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
'@histoire/shared': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
'@histoire/vendors': 0.17.17
'@types/flexsearch': 0.7.6
flexsearch: 0.7.21
@@ -8029,7 +8104,7 @@ snapshots:
transitivePeerDependencies:
- vite
'@histoire/controls@0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))':
'@histoire/controls@0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))':
dependencies:
'@codemirror/commands': 6.6.0
'@codemirror/lang-json': 6.0.1
@@ -8038,17 +8113,17 @@ snapshots:
'@codemirror/state': 6.4.1
'@codemirror/theme-one-dark': 6.1.2
'@codemirror/view': 6.33.0
'@histoire/shared': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
'@histoire/shared': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
'@histoire/vendors': 0.17.17
transitivePeerDependencies:
- vite
'@histoire/plugin-screenshot@0.17.17(histoire@0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)))':
'@histoire/plugin-screenshot@0.17.17(histoire@0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)))':
dependencies:
capture-website: 2.4.1
defu: 6.1.4
fs-extra: 10.1.0
histoire: 0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
histoire: 0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
pathe: 1.1.2
transitivePeerDependencies:
- bufferutil
@@ -8056,21 +8131,21 @@ snapshots:
- supports-color
- utf-8-validate
'@histoire/plugin-vue@0.17.17(histoire@0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)))(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))(vue@3.5.13(typescript@5.7.3))':
'@histoire/plugin-vue@0.17.17(histoire@0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)))(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))':
dependencies:
'@histoire/controls': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
'@histoire/shared': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
'@histoire/controls': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
'@histoire/shared': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
'@histoire/vendors': 0.17.17
change-case: 4.1.2
globby: 13.2.2
histoire: 0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
histoire: 0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
launch-editor: 2.8.1
pathe: 1.1.2
vue: 3.5.13(typescript@5.7.3)
transitivePeerDependencies:
- vite
'@histoire/shared@0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))':
'@histoire/shared@0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))':
dependencies:
'@histoire/vendors': 0.17.17
'@types/fs-extra': 9.0.13
@@ -8078,7 +8153,7 @@ snapshots:
chokidar: 3.6.0
pathe: 1.1.2
picocolors: 1.1.1
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
'@histoire/vendors@0.17.17': {}
@@ -8973,48 +9048,48 @@ snapshots:
'@typescript-eslint/types': 8.20.0
eslint-visitor-keys: 4.2.0
'@vitejs/plugin-vue@5.2.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))(vue@3.5.13(typescript@5.7.3))':
'@vitejs/plugin-vue@5.2.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))':
dependencies:
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
vue: 3.5.13(typescript@5.7.3)
'@vitest/expect@3.0.2':
'@vitest/expect@3.0.1':
dependencies:
'@vitest/spy': 3.0.2
'@vitest/utils': 3.0.2
'@vitest/spy': 3.0.1
'@vitest/utils': 3.0.1
chai: 5.1.2
tinyrainbow: 2.0.0
'@vitest/mocker@3.0.2(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))':
'@vitest/mocker@3.0.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))':
dependencies:
'@vitest/spy': 3.0.2
'@vitest/spy': 3.0.1
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
'@vitest/pretty-format@3.0.2':
'@vitest/pretty-format@3.0.1':
dependencies:
tinyrainbow: 2.0.0
'@vitest/runner@3.0.2':
'@vitest/runner@3.0.1':
dependencies:
'@vitest/utils': 3.0.2
pathe: 2.0.1
'@vitest/utils': 3.0.1
pathe: 2.0.2
'@vitest/snapshot@3.0.2':
'@vitest/snapshot@3.0.1':
dependencies:
'@vitest/pretty-format': 3.0.2
'@vitest/pretty-format': 3.0.1
magic-string: 0.30.17
pathe: 2.0.1
pathe: 2.0.2
'@vitest/spy@3.0.2':
'@vitest/spy@3.0.1':
dependencies:
tinyspy: 3.0.2
'@vitest/utils@3.0.2':
'@vitest/utils@3.0.1':
dependencies:
'@vitest/pretty-format': 3.0.2
'@vitest/pretty-format': 3.0.1
loupe: 3.1.2
tinyrainbow: 2.0.0
@@ -9030,6 +9105,19 @@ snapshots:
path-browserify: 1.0.1
vscode-uri: 3.0.8
'@vue-macros/common@1.15.1(rollup@4.30.1)(vue@3.5.13(typescript@5.7.3))':
dependencies:
'@babel/types': 7.26.5
'@rollup/pluginutils': 5.1.3(rollup@4.30.1)
'@vue/compiler-sfc': 3.5.13
ast-kit: 1.3.2
local-pkg: 0.5.1
magic-string-ast: 0.6.3
optionalDependencies:
vue: 3.5.13(typescript@5.7.3)
transitivePeerDependencies:
- rollup
'@vue/babel-helper-vue-transform-on@1.2.5': {}
'@vue/babel-plugin-jsx@1.2.5(@babel/core@7.26.0)':
@@ -9081,7 +9169,7 @@ snapshots:
'@vue/compiler-ssr': 3.5.13
'@vue/shared': 3.5.13
estree-walker: 2.0.2
magic-string: 0.30.17
magic-string: 0.30.14
postcss: 8.5.1
source-map-js: 1.2.1
@@ -9097,14 +9185,14 @@ snapshots:
'@vue/devtools-api@6.6.4': {}
'@vue/devtools-core@7.7.0(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))(vue@3.5.13(typescript@5.7.3))':
'@vue/devtools-core@7.7.0(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))':
dependencies:
'@vue/devtools-kit': 7.7.0
'@vue/devtools-shared': 7.7.0
mitt: 3.0.1
nanoid: 5.0.9
pathe: 1.1.2
vite-hot-client: 0.2.4(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
vite-hot-client: 0.2.4(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
vue: 3.5.13(typescript@5.7.3)
transitivePeerDependencies:
- vite
@@ -9338,6 +9426,16 @@ snapshots:
assertion-error@2.0.1: {}
ast-kit@1.3.2:
dependencies:
'@babel/parser': 7.26.5
pathe: 1.1.2
ast-walker-scope@0.6.2:
dependencies:
'@babel/parser': 7.26.1
ast-kit: 1.3.2
astral-regex@2.0.0: {}
async@3.2.6: {}
@@ -9349,7 +9447,7 @@ snapshots:
autoprefixer@10.4.20(postcss@8.5.1):
dependencies:
browserslist: 4.24.4
caniuse-lite: 1.0.30001695
caniuse-lite: 1.0.30001692
fraction.js: 4.3.7
normalize-range: 0.1.2
picocolors: 1.0.1
@@ -9450,7 +9548,7 @@ snapshots:
browserslist@4.24.4:
dependencies:
caniuse-lite: 1.0.30001695
caniuse-lite: 1.0.30001692
electron-to-chromium: 1.5.73
node-releases: 2.0.19
update-browserslist-db: 1.1.1(browserslist@4.24.4)
@@ -9513,7 +9611,7 @@ snapshots:
camelcase@5.3.1: {}
caniuse-lite@1.0.30001695: {}
caniuse-lite@1.0.30001692: {}
capital-case@1.0.4:
dependencies:
@@ -9669,6 +9767,8 @@ snapshots:
confbox@0.1.7: {}
confbox@0.1.8: {}
config-chain@1.1.13:
dependencies:
ini: 1.3.8
@@ -10752,12 +10852,12 @@ snapshots:
highlight.js@11.11.1: {}
histoire@0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)):
histoire@0.17.17(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)):
dependencies:
'@akryum/tinypool': 0.3.1
'@histoire/app': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
'@histoire/controls': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
'@histoire/shared': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
'@histoire/app': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
'@histoire/controls': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
'@histoire/shared': 0.17.17(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
'@histoire/vendors': 0.17.17
'@types/flexsearch': 0.7.6
'@types/markdown-it': 12.2.3
@@ -10784,7 +10884,7 @@ snapshots:
sade: 1.8.1
shiki-es: 0.2.0
sirv: 2.0.4
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
vite-node: 0.34.7(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)
transitivePeerDependencies:
- '@types/node'
@@ -11237,6 +11337,11 @@ snapshots:
optionalDependencies:
enquirer: 2.4.1
local-pkg@0.5.1:
dependencies:
mlly: 1.7.4
pkg-types: 1.3.1
locate-path@5.0.0:
dependencies:
p-locate: 4.1.0
@@ -11293,6 +11398,10 @@ snapshots:
dependencies:
yallist: 3.1.1
magic-string-ast@0.6.3:
dependencies:
magic-string: 0.30.14
magic-string@0.25.9:
dependencies:
sourcemap-codec: 1.4.8
@@ -11423,6 +11532,13 @@ snapshots:
pkg-types: 1.2.0
ufo: 1.5.4
mlly@1.7.4:
dependencies:
acorn: 8.14.0
pathe: 2.0.2
pkg-types: 1.3.1
ufo: 1.5.4
mri@1.2.0: {}
mrmime@1.0.1: {}
@@ -11679,7 +11795,7 @@ snapshots:
pathe@1.1.2: {}
pathe@2.0.1: {}
pathe@2.0.2: {}
pathval@2.0.0: {}
@@ -11727,6 +11843,12 @@ snapshots:
mlly: 1.7.1
pathe: 1.1.2
pkg-types@1.3.1:
dependencies:
confbox: 0.1.8
mlly: 1.7.4
pathe: 2.0.2
possible-typed-array-names@1.0.0: {}
postcss-attribute-case-insensitive@7.0.1(postcss@8.5.1):
@@ -12478,6 +12600,8 @@ snapshots:
dependencies:
xmlchars: 2.2.0
scule@1.3.0: {}
section-matter@1.0.0:
dependencies:
extend-shallow: 2.0.1
@@ -13052,6 +13176,28 @@ snapshots:
unplugin: 1.12.2
webpack-sources: 3.2.3
unplugin-vue-router@0.10.9(rollup@4.30.1)(vue-router@4.5.0(vue@3.5.13(typescript@5.7.3)))(vue@3.5.13(typescript@5.7.3)):
dependencies:
'@babel/types': 7.26.0
'@rollup/pluginutils': 5.1.3(rollup@4.30.1)
'@vue-macros/common': 1.15.1(rollup@4.30.1)(vue@3.5.13(typescript@5.7.3))
ast-walker-scope: 0.6.2
chokidar: 3.6.0
fast-glob: 3.3.3
json5: 2.2.3
local-pkg: 0.5.1
magic-string: 0.30.14
mlly: 1.7.4
pathe: 1.1.2
scule: 1.3.0
unplugin: 2.0.0-beta.1
yaml: 2.7.0
optionalDependencies:
vue-router: 4.5.0(vue@3.5.13(typescript@5.7.3))
transitivePeerDependencies:
- rollup
- vue
unplugin@1.12.2:
dependencies:
acorn: 8.12.1
@@ -13059,6 +13205,11 @@ snapshots:
webpack-sources: 3.2.3
webpack-virtual-modules: 0.6.2
unplugin@2.0.0-beta.1:
dependencies:
acorn: 8.14.0
webpack-virtual-modules: 0.6.2
untildify@4.0.0: {}
upath@1.2.0: {}
@@ -13125,9 +13276,9 @@ snapshots:
core-util-is: 1.0.2
extsprintf: 1.3.0
vite-hot-client@0.2.4(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)):
vite-hot-client@0.2.4(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)):
dependencies:
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
vite-node@0.34.7(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6):
dependencies:
@@ -13148,13 +13299,13 @@ snapshots:
- supports-color
- terser
vite-node@3.0.2(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0):
vite-node@3.0.1(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0):
dependencies:
cac: 6.7.14
debug: 4.4.0(supports-color@8.1.1)
es-module-lexer: 1.6.0
pathe: 2.0.1
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
pathe: 2.0.2
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -13169,7 +13320,7 @@ snapshots:
- tsx
- yaml
vite-plugin-inspect@0.8.9(rollup@4.30.1)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)):
vite-plugin-inspect@0.8.9(rollup@4.30.1)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)):
dependencies:
'@antfu/utils': 0.7.10
'@rollup/pluginutils': 5.1.3(rollup@4.30.1)
@@ -13180,47 +13331,47 @@ snapshots:
perfect-debounce: 1.0.0
picocolors: 1.1.1
sirv: 3.0.0
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
transitivePeerDependencies:
- rollup
- supports-color
vite-plugin-pwa@0.21.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))(workbox-build@7.3.0)(workbox-window@7.3.0):
vite-plugin-pwa@0.21.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))(workbox-build@7.3.0)(workbox-window@7.3.0):
dependencies:
debug: 4.3.7
pretty-bytes: 6.1.1
tinyglobby: 0.2.10
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
workbox-build: 7.3.0
workbox-window: 7.3.0
transitivePeerDependencies:
- supports-color
vite-plugin-sentry@1.4.0(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)):
vite-plugin-sentry@1.4.0(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)):
dependencies:
'@sentry/cli': 2.33.1
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
transitivePeerDependencies:
- encoding
- supports-color
vite-plugin-vue-devtools@7.7.0(rollup@4.30.1)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))(vue@3.5.13(typescript@5.7.3)):
vite-plugin-vue-devtools@7.7.0(rollup@4.30.1)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3)):
dependencies:
'@vue/devtools-core': 7.7.0(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))(vue@3.5.13(typescript@5.7.3))
'@vue/devtools-core': 7.7.0(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))
'@vue/devtools-kit': 7.7.0
'@vue/devtools-shared': 7.7.0
execa: 9.5.1
sirv: 3.0.0
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
vite-plugin-inspect: 0.8.9(rollup@4.30.1)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
vite-plugin-vue-inspector: 5.3.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
vite-plugin-inspect: 0.8.9(rollup@4.30.1)(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
vite-plugin-vue-inspector: 5.3.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
transitivePeerDependencies:
- '@nuxt/kit'
- rollup
- supports-color
- vue
vite-plugin-vue-inspector@5.3.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)):
vite-plugin-vue-inspector@5.3.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)):
dependencies:
'@babel/core': 7.26.0
'@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.0)
@@ -13231,7 +13382,7 @@ snapshots:
'@vue/compiler-dom': 3.5.13
kolorist: 1.8.0
magic-string: 0.30.14
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
transitivePeerDependencies:
- supports-color
@@ -13252,7 +13403,7 @@ snapshots:
sass-embedded: 1.83.4
terser: 5.31.6
vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0):
vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0):
dependencies:
esbuild: 0.24.2
postcss: 8.5.1
@@ -13264,29 +13415,29 @@ snapshots:
sass: 1.80.6
sass-embedded: 1.83.4
terser: 5.31.6
yaml: 2.5.0
yaml: 2.7.0
vitest@3.0.2(@types/node@22.10.7)(happy-dom@16.6.0)(jiti@1.21.6)(jsdom@20.0.3)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0):
vitest@3.0.1(@types/node@22.10.7)(happy-dom@16.6.0)(jiti@1.21.6)(jsdom@20.0.3)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0):
dependencies:
'@vitest/expect': 3.0.2
'@vitest/mocker': 3.0.2(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0))
'@vitest/pretty-format': 3.0.2
'@vitest/runner': 3.0.2
'@vitest/snapshot': 3.0.2
'@vitest/spy': 3.0.2
'@vitest/utils': 3.0.2
'@vitest/expect': 3.0.1
'@vitest/mocker': 3.0.1(vite@6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0))
'@vitest/pretty-format': 3.0.1
'@vitest/runner': 3.0.1
'@vitest/snapshot': 3.0.1
'@vitest/spy': 3.0.1
'@vitest/utils': 3.0.1
chai: 5.1.2
debug: 4.4.0(supports-color@8.1.1)
expect-type: 1.1.0
magic-string: 0.30.17
pathe: 2.0.1
pathe: 2.0.2
std-env: 3.8.0
tinybench: 2.9.0
tinyexec: 0.3.2
tinypool: 1.0.2
tinyrainbow: 2.0.0
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
vite-node: 3.0.2(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.5.0)
vite: 6.0.7(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
vite-node: 3.0.1(@types/node@22.10.7)(jiti@1.21.6)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)(yaml@2.7.0)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 22.10.7
@@ -13643,6 +13794,8 @@ snapshots:
yaml@2.5.0: {}
yaml@2.7.0: {}
yargs-parser@18.1.3:
dependencies:
camelcase: 5.3.1

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Before

Width:  |  Height:  |  Size: 471 B

After

Width:  |  Height:  |  Size: 471 B

Before

Width:  |  Height:  |  Size: 745 B

After

Width:  |  Height:  |  Size: 745 B

Before

Width:  |  Height:  |  Size: 512 B

After

Width:  |  Height:  |  Size: 512 B

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

+1 -1
View File
@@ -37,7 +37,7 @@
v-slot="{ Component }"
:route="routeWithModal"
>
<keep-alive :include="['project.view']">
<keep-alive :include="['project']">
<component :is="Component" />
</keep-alive>
</RouterView>
@@ -15,7 +15,7 @@
/>
</BaseButton>
<BaseButton
:to="{ name: 'project.index', params: { projectId: project.id} }"
:to="{ name: 'project', params: { projectId: project.id} }"
class="list-menu-link"
:class="{'router-link-exact-active': currentProject?.id === project.id}"
>
@@ -63,7 +63,7 @@ const motd = computed(() => configStore.motd)
const route = useRoute()
const {t} = useI18n({useScope: 'global'})
const title = computed(() => route.meta?.title ? t(route.meta.title as string) : '')
const title = computed(() => t(route.meta?.title as string || ''))
useTitle(() => title.value)
</script>
@@ -62,7 +62,7 @@ export const KEYBOARD_SHORTCUTS : ShortcutGroup[] = [
},
{
title: 'project.kanban.title',
available: (route) => route.name === 'project.view',
available: (route) => route.name === 'project',
shortcuts: [
{
title: 'keyboardShortcuts.task.done',
@@ -103,7 +103,7 @@
{{ $t('project.webhooks.title') }}
</DropdownItem>
<DropdownItem
:to="{ name: 'project.createFromParent', params: { parentProjectId: project.id } }"
:to="{ name: 'project.create', params: { parentProjectId: project.id } }"
icon="layer-group"
>
{{ $t('menu.createProject') }}
@@ -1,10 +1,7 @@
<template>
<div
:class="{ 'is-loading': projectService.loading, 'is-archived': currentProject?.isArchived}"
class="loader-container"
:class="{
'is-loading': isLoadingProject,
'is-archived': currentProject?.isArchived,
}"
>
<h1 class="project-title-print">
{{ getProjectTitle(currentProject) }}
@@ -23,7 +20,7 @@
:key="view.id"
class="switch-view-button"
:class="{'is-active': view.id === viewId}"
:to="{ name: 'project.view', params: { projectId, viewId: view.id } }"
:to="{ name: 'project', params: { projectId, viewId: view.id } }"
>
{{ getViewTitle(view) }}
</BaseButton>
@@ -40,37 +37,43 @@
</Message>
</CustomTransition>
<slot v-if="!isLoadingProject" />
<slot v-if="loadedProjectId" />
</div>
</template>
<script setup lang="ts">
import {computed} from 'vue'
import {useI18n} from 'vue-i18n'
import {computed, ref, shallowReactive, watch, watchEffect} from 'vue'
import {useRoute} from 'vue-router'
import BaseButton from '@/components/base/BaseButton.vue'
import Message from '@/components/misc/Message.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import ProjectModel from '@/models/project'
import ProjectService from '@/services/project'
import {getProjectTitle} from '@/helpers/getProjectTitle'
import {saveProjectToHistory} from '@/modules/projectHistory'
import {useTitle} from '@/composables/useTitle'
import {useBaseStore} from '@/stores/base'
import {useProjectStore} from '@/stores/projects'
import type {IProject} from '@/modelTypes/IProject'
import type {IProjectView} from '@/modelTypes/IProjectView'
import {useI18n} from 'vue-i18n'
const props = defineProps<{
isLoadingProject: boolean,
projectId: IProject['id'],
viewId: IProjectView['id'],
}>()
const route = useRoute()
const {t} = useI18n()
const baseStore = useBaseStore()
const projectStore = useProjectStore()
const projectService = shallowReactive(new ProjectService())
const loadedProjectId = ref(0)
const currentProject = computed<IProject>(() => {
return typeof baseStore.currentProject === 'undefined' ? {
@@ -84,6 +87,54 @@ useTitle(() => currentProject.value?.id ? getProjectTitle(currentProject.value)
const views = computed(() => projectStore.projects[props.projectId]?.views)
// watchEffect would be called every time the prop would get a value assigned, even if that value was the same as before.
// This resulted in loading and setting the project multiple times, even when navigating away from it.
// This caused wired bugs where the project background would be set on the home page but only right after setting a new
// project background and then navigating to home. It also highlighted the project in the menu and didn't allow changing any
// of it, most likely due to the rights not being properly populated.
watch(
() => props.projectId,
// loadProject
async (projectIdToLoad: number) => {
saveProjectToHistory({id: projectIdToLoad})
// Don't load the project if we either already loaded it or aren't dealing with a project at all currently and
// the currently loaded project has the right set.
if (
(
projectIdToLoad === loadedProjectId.value ||
typeof projectIdToLoad === 'undefined' ||
projectIdToLoad === currentProject.value?.id
)
&& typeof currentProject.value !== 'undefined' && currentProject.value.maxRight !== null
) {
loadedProjectId.value = projectIdToLoad
return
}
console.debug('Loading project, $route.params =', route.params, `, loadedProjectId = ${loadedProjectId.value}, currentProject = `, currentProject.value)
// Set the current project to the one we're about to load so that the title is already shown at the top
loadedProjectId.value = 0
const projectFromStore = projectStore.projects[projectIdToLoad]
if (projectFromStore) {
baseStore.handleSetCurrentProject({project: projectFromStore, currentProjectViewId: props.viewId})
}
// We create an extra project object instead of creating it in project.value because that would trigger a ui update which would result in bad ux.
const project = new ProjectModel({id: projectIdToLoad})
try {
const loadedProject = await projectService.get(project)
baseStore.handleSetCurrentProject({project: loadedProject, currentProjectViewId: props.viewId})
} finally {
loadedProjectId.value = projectIdToLoad
}
},
{immediate: true},
)
watchEffect(() => baseStore.setCurrentProjectViewId(props.viewId))
function getViewTitle(view: IProjectView) {
switch (view.title) {
case 'List':
@@ -37,7 +37,7 @@
:aria-label="project.title"
:title="textOnlyDescription"
:to="{
name: 'project.index',
name: 'project',
params: { projectId: project.id}
}"
/>
@@ -1,7 +1,6 @@
<template>
<ProjectWrapper
class="project-gantt"
:is-loading-project="isLoadingProject"
:project-id="filters.projectId"
:view-id
>
@@ -86,7 +85,7 @@ import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
import TaskForm from '@/components/tasks/TaskForm.vue'
import {createAsyncComponent} from '@/helpers/createAsyncComponent'
import {useGanttFilters} from '../../../views/project/helpers/useGanttFilters'
import {useGanttFilters} from '@/composables/useGanttFilters'
import {RIGHTS} from '@/constants/rights'
import type {DateISO} from '@/types/DateISO'
@@ -96,7 +95,6 @@ import type {IProjectView} from '@/modelTypes/IProjectView'
type Options = Flatpickr.Options.Options
const props = defineProps<{
isLoadingProject: boolean,
route: RouteLocationNormalized
viewId: IProjectView['id']
}>()
@@ -1,7 +1,6 @@
<template>
<ProjectWrapper
class="project-kanban"
:is-loading-project="isLoadingProject"
:project-id="projectId"
:view-id
>
@@ -316,7 +315,6 @@ import TaskBucketService from '@/services/taskBucket'
import TaskBucketModel from '@/models/taskBucket'
const props = defineProps<{
isLoadingProject: boolean,
projectId: number,
viewId: IProjectView['id'],
}>()
@@ -1,7 +1,6 @@
<template>
<ProjectWrapper
class="project-list"
:is-loading-project="isLoadingProject"
:project-id="projectId"
:view-id
>
@@ -124,7 +123,6 @@ import TaskPositionService from '@/services/taskPosition'
import TaskPositionModel from '@/models/taskPosition'
const props = defineProps<{
isLoadingProject: boolean,
projectId: IProject['id'],
viewId: IProjectView['id'],
}>()
@@ -1,7 +1,6 @@
<template>
<ProjectWrapper
class="project-table"
:is-loading-project="isLoadingProject"
:project-id="projectId"
:view-id
>
@@ -299,7 +298,6 @@ import { camelCase } from 'change-case'
import {isSavedFilter} from '@/services/savedFilter'
const props = defineProps<{
isLoadingProject: boolean,
projectId: IProject['id'],
viewId: IProjectView['id'],
}>()
@@ -449,7 +449,7 @@ async function doAction(type: ACTION_TYPE, item: DoAction) {
case ACTION_TYPE.PROJECT:
closeQuickActions()
await router.push({
name: 'project.index',
name: 'project',
params: {projectId: (item as DoAction<IProject>).id},
})
break
+1 -1
View File
@@ -54,7 +54,7 @@ import {parseKebabDate} from '@/helpers/time/parseKebabDate'
import type {ITask, ITaskPartialWithId} from '@/modelTypes/ITask'
import type {DateISO} from '@/types/DateISO'
import type {GanttFilters} from '@/views/project/helpers/useGanttFilters'
import type {GanttFilters} from '@/composables/useGanttFilters'
import {
extendDayjs,
@@ -28,7 +28,7 @@
<RouterLink
v-if="showProject && typeof project !== 'undefined'"
v-tooltip="$t('task.detail.belongsToProject', {project: project.title})"
:to="{ name: 'project.index', params: { projectId: task.projectId } }"
:to="{ name: 'project', params: { projectId: task.projectId } }"
class="task-project mr-1"
:class="{'mr-2': task.hexColor !== ''}"
@click.stop
@@ -139,7 +139,7 @@
<RouterLink
v-if="showProjectSeparately"
v-tooltip="$t('task.detail.belongsToProject', {project: project.title})"
:to="{ name: 'project.index', params: { projectId: task.projectId } }"
:to="{ name: 'project', params: { projectId: task.projectId } }"
class="task-project"
@click.stop
>
@@ -5,7 +5,7 @@ import {isoToKebabDate} from '@/helpers/time/isoToKebabDate'
import {parseDateProp} from '@/helpers/time/parseDateProp'
import {parseBooleanProp} from '@/helpers/time/parseBooleanProp'
import {useRouteFilters} from '@/composables/useRouteFilters'
import {useGanttTaskList} from './useGanttTaskList'
import {useGanttTaskList} from '@/composables/useGanttTaskList'
import type {IProject} from '@/modelTypes/IProject'
import type {TaskFilterParams} from '@/services/taskCollection'
@@ -72,7 +72,7 @@ function ganttFiltersToRoute(filters: GanttFilters): RouteLocationRaw {
}
return {
name: 'project.view',
name: 'project',
params: {
projectId: filters.projectId,
viewId: filters.viewId,
@@ -104,7 +104,7 @@ export function useGanttFilters(route: Ref<RouteLocationNormalized>, viewId: Ref
ganttGetDefaultFilters,
ganttRouteToFilters,
ganttFiltersToRoute,
['project.view'],
['project'],
)
const {
@@ -72,7 +72,7 @@ export function useRouteWithModal() {
}
const newRoute = {
name: 'project.view',
name: 'project',
params: {
projectId: baseStore.currentProject?.id,
viewId,
+2 -2
View File
@@ -1,6 +1,6 @@
import {computed, toValue} from 'vue'
import {computed} from 'vue'
import {useTitle as useTitleVueUse, type UseTitleOptions, type ReadonlyRefOrGetter, type MaybeRef, type MaybeRefOrGetter} from '@vueuse/core'
import {useTitle as useTitleVueUse, toValue, type UseTitleOptions, type ReadonlyRefOrGetter, type MaybeRef, type MaybeRefOrGetter} from '@vueuse/core'
export function useTitle(
newTitle:
@@ -1,9 +1,9 @@
import wunderlistIcon from './icons/wunderlist.jpg'
import todoistIcon from './icons/todoist.svg?url'
import trelloIcon from './icons/trello.svg?url'
import microsoftTodoIcon from './icons/microsoft-todo.svg?url'
import vikunjaFileIcon from './icons/vikunja-file.png?url'
import tickTickIcon from './icons/ticktick.svg?url'
import wunderlistIcon from '@/assets/migrators/wunderlist.jpg'
import todoistIcon from '@/assets/migrators/todoist.svg?url'
import trelloIcon from '@/assets/migrators/trello.svg?url'
import microsoftTodoIcon from '@/assets/migrators/microsoft-todo.svg?url'
import vikunjaFileIcon from '@/assets/migrators/vikunja-file.png?url'
import tickTickIcon from '@/assets/migrators/ticktick.svg?url'
export interface Migrator {
id: string
+1 -1
View File
@@ -1124,7 +1124,7 @@
}
},
"date": {
"locale": "nn",
"locale": "nb_NO",
"altFormatLong": "d.m.y H:i",
"altFormatShort": "d.m.y"
},
+17 -17
View File
@@ -73,26 +73,26 @@ setLanguage(browserLanguage).then(() => {
error(err)
}
if (import.meta.env.DEV) {
app.config.warnHandler = (msg) => {
error(msg)
throw msg
}
// if (import.meta.env.DEV) {
// app.config.warnHandler = (msg) => {
// error(msg)
// throw msg
// }
// https://stackoverflow.com/a/52076738/15522256
window.addEventListener('error', (err) => {
error(err)
throw err
})
// // https://stackoverflow.com/a/52076738/15522256
// window.addEventListener('error', (err) => {
// error(err)
// throw err
// })
window.addEventListener('unhandledrejection', (err) => {
// event.promise contains the promise object
// event.reason contains the reason for the rejection
error(err)
throw err
})
}
// window.addEventListener('unhandledrejection', (err) => {
// // event.promise contains the promise object
// // event.reason contains the reason for the rejection
// error(err)
// throw err
// })
// }
app.config.globalProperties.$message = {
error,
@@ -8,5 +8,13 @@
<script setup lang="ts">
import {useTitle} from '@/composables/useTitle'
// regarding the name of this component, see
// https://github.com/posva/unplugin-vue-router/issues/412#issuecomment-2150643118
definePage({
name: 'not-found',
})
defineOptions({ name: 'NotFound' })
useTitle(() => '404')
</script>
@@ -71,6 +71,11 @@ import PasswordResetModel from '@/models/passwordReset'
import PasswordResetService from '@/services/passwordReset'
import Message from '@/components/misc/Message.vue'
definePage({
name: 'user.password-reset.request',
meta: { title: 'user.auth.resetPassword' },
})
const passwordResetService = shallowReactive(new PasswordResetService())
const passwordReset = ref(new PasswordResetModel())
const errorMsg = ref('')
@@ -161,6 +161,11 @@ import {useConfigStore} from '@/stores/config'
import {useTitle} from '@/composables/useTitle'
definePage({
name: 'user.login',
meta: { title: 'user.auth.login' },
})
const {t} = useI18n({useScope: 'global'})
useTitle(() => t('user.auth.login'))
@@ -58,6 +58,11 @@ import PasswordResetService from '@/services/passwordReset'
import Message from '@/components/misc/Message.vue'
import Password from '@/components/input/Password.vue'
definePage({
name: 'user.password-reset.reset',
meta: { title: 'user.auth.resetPassword' },
})
const credentials = reactive({
password: '',
})
@@ -32,6 +32,8 @@ import {computed} from 'vue'
import {useConfigStore} from '@/stores/config'
definePage({ name: 'about' })
const configStore = useConfigStore()
const apiVersion = computed(() => configStore.version)
</script>
@@ -34,6 +34,8 @@ import {useRedirectToLastVisited} from '@/composables/useRedirectToLastVisited'
import {useAuthStore} from '@/stores/auth'
definePage({ name: 'openid.auth' })
const {t} = useI18n({useScope: 'global'})
const route = useRoute()
@@ -88,6 +88,11 @@ import Filters from '@/components/project/partials/Filters.vue'
import {useSavedFilter} from '@/services/savedFilter'
definePage({
name: 'filters.create',
meta: { showAsModal: true }
})
const {
filter,
filters,
@@ -58,7 +58,7 @@
import {ref, computed} from 'vue'
import Message from '@/components/misc/Message.vue'
import ShowTasks from '@/views/tasks/ShowTasks.vue'
import ShowTasks from '@/components/tasks/ShowTasks.vue'
import ProjectCardGrid from '@/components/project/partials/ProjectCardGrid.vue'
import AddTask from '@/components/tasks/AddTask.vue'
@@ -73,6 +73,8 @@ import {useConfigStore} from '@/stores/config'
import {useAuthStore} from '@/stores/auth'
import {useTaskStore} from '@/stores/tasks'
definePage({ name: 'home' })
const salutation = useDaytimeSalutation()
const baseStore = useBaseStore()
@@ -149,6 +149,8 @@ import {useLabelStore} from '@/stores/labels'
import { useTitle } from '@/composables/useTitle'
definePage({ name: 'labels.index' })
const {t} = useI18n({useScope: 'global'})
const labelEditLabel = ref<ILabel>(new LabelModel())
@@ -54,6 +54,8 @@ import {useTitle} from '@/composables/useTitle'
import {success} from '@/message'
import {getRandomColorHex} from '@/helpers/color/randomColor'
definePage({ name: 'labels.create' })
const router = useRouter()
const {t} = useI18n({useScope: 'global'})
@@ -110,16 +110,6 @@
</div>
</template>
<script lang="ts">
export default {
beforeRouteEnter(to) {
if (MIGRATORS[to.params.service as string] === undefined) {
return {name: 'not-found'}
}
},
}
</script>
<script setup lang="ts">
import {computed, ref, shallowReactive} from 'vue'
import {useI18n} from 'vue-i18n'
@@ -133,11 +123,24 @@ import AbstractMigrationFileService from '@/services/migrator/abstractMigrationF
import {formatDateLong} from '@/helpers/time/formatDate'
import {parseDateOrNull} from '@/helpers/parseDateOrNull'
import {MIGRATORS, type Migrator} from './migrators'
import {MIGRATORS, type Migrator} from '@/helpers/migrators'
import {useTitle} from '@/composables/useTitle'
import {useProjectStore} from '@/stores/projects'
import {getErrorText} from '@/message'
definePage({
name: 'migrate.service',
props: route => ({
service: route.params.service as string,
code: route.query.code as string,
}),
beforeEnter(to) {
if (MIGRATORS[to.params.service as string] === undefined) {
return {name: 'not-found'}
}
}
})
const props = defineProps<{
service: string,
code?: string,
@@ -65,6 +65,14 @@ import {useProjectStore} from '@/stores/projects'
import ProjectSearch from '@/components/tasks/partials/ProjectSearch.vue'
import type {IProject} from '@/modelTypes/IProject'
definePage({
name: 'project.create',
props: route => ({ parentProjectId: Number(route.params.parentProjectId as string) }),
meta: {
showAsModal: true,
},
})
const props = defineProps<{
parentProjectId?: number,
}>()
@@ -1,21 +1,44 @@
<script setup lang="ts">
import {computed, ref, shallowReactive, watch, watchEffect} from 'vue'
import {useRoute, useRouter} from 'vue-router'
import {useBaseStore} from '@/stores/base'
import {computed, watch, watchEffect} from 'vue'
import {useProjectStore} from '@/stores/projects'
import {useAuthStore} from '@/stores/auth'
import {saveProjectView} from '@/helpers/projectView'
import ProjectService from '@/services/project'
import {useRoute, useRouter} from 'vue-router'
import {getProjectViewId, saveProjectView} from '@/helpers/projectView'
import ProjectList from '@/components/project/views/ProjectList.vue'
import ProjectGantt from '@/components/project/views/ProjectGantt.vue'
import ProjectTable from '@/components/project/views/ProjectTable.vue'
import ProjectKanban from '@/components/project/views/ProjectKanban.vue'
import {useAuthStore} from '@/stores/auth'
import {DEFAULT_PROJECT_VIEW_SETTINGS} from '@/modelTypes/IProjectView'
import {saveProjectToHistory} from '@/modules/projectHistory'
definePage({
name: 'project',
// beforeEnter(to) {
// if (to.name !== 'project') {
// throw new Error()
// }
// const projectId = Number(to.params?.projectId)
// const viewIdFromRoute = Number(to.params?.viewId)
// const newViewid = getProjectViewId(projectId) ?? 0
// if (!viewIdFromRoute || viewIdFromRoute !== newViewid) {
// return {
// name: 'project',
// replace: true,
// params: {
// projectId,
// viewId: newViewid,
// },
// }
// }
// },
props: route => ({
projectId: parseInt(route.params.projectId as string),
viewId: route.params.viewId ? parseInt(route.params.viewId as string): undefined,
}),
})
const props = defineProps<{
projectId: number,
@@ -23,10 +46,8 @@ const props = defineProps<{
}>()
const router = useRouter()
const baseStore = useBaseStore()
const projectStore = useProjectStore()
const authStore = useAuthStore()
const route = useRoute()
const currentProject = computed(() => projectStore.projects[props.projectId])
@@ -34,61 +55,13 @@ const currentView = computed(() => {
return currentProject.value?.views.find(v => v.id === props.viewId)
})
const projectService = shallowReactive(new ProjectService())
const isLoadingProject = computed(() => projectService.loading)
const loadedProjectId = ref(0)
watch(
() => props.projectId,
// loadProject
async (projectIdToLoad, oldProjectIdToLoad) => {
console.debug('Loading project, $route.params =', route.params, `, loadedProjectId = ${loadedProjectId.value}, currentProject = `, currentProject.value)
if (projectIdToLoad !== oldProjectIdToLoad) {
loadedProjectId.value = 0
}
try {
const loadedProject = await projectService.get({id: projectIdToLoad})
// Here, we only set the new project in the projectStore.
// Setting that projet as the current one in the baseStore is handled by the watcher below.
projectStore.setProject(loadedProject)
} finally {
loadedProjectId.value = projectIdToLoad
}
},
{immediate: true},
)
watch(
() => [currentProject.value, props.viewId],
([newCurrentProject, newViewId]) => {
if (!newCurrentProject) {
baseStore.handleSetCurrentProject({project: null})
return
}
baseStore.handleSetCurrentProject({
project: newCurrentProject,
currentProjectViewId: newViewId,
})
}, {
deep: true,
immediate: true,
},
)
function redirectToDefaultViewIfNecessary() {
if (props.viewId === 0 || !currentView.value) {
// Ideally, we would do that in the router redirect, but the projects (and therefore, the views)
// are not always loaded then.
const defaultView = authStore.settings.frontendSettings.defaultView
let view
const defaultView = authStore.settings.frontendSettings.defaultView
if (defaultView !== DEFAULT_PROJECT_VIEW_SETTINGS.FIRST) {
view = currentProject.value?.views.find(v => v.viewKind === defaultView)
}
@@ -100,7 +73,7 @@ function redirectToDefaultViewIfNecessary() {
if (view) {
router.replace({
name: 'project.view',
name: 'project',
params: {
projectId: props.projectId,
viewId: view.id,
@@ -117,39 +90,35 @@ watch(
)
watch(
currentProject,
() => projectStore.projects[props.projectId],
redirectToDefaultViewIfNecessary,
)
watchEffect(() => saveProjectToHistory({id: props.projectId}))
// using a watcher instead of beforeEnter because beforeEnter is not called when only the viewId changes
watchEffect(() => saveProjectView(props.projectId, props.viewId))
watchEffect(() => baseStore.setCurrentProjectViewId(props.viewId))
const route = useRoute()
</script>
<template>
<ProjectList
v-if="currentView?.viewKind === 'list'"
:project-id="projectId"
:is-loading-project="isLoadingProject"
:view-id
/>
<ProjectGantt
v-if="currentView?.viewKind === 'gantt'"
:route
:is-loading-project="isLoadingProject"
:view-id
/>
<ProjectTable
v-if="currentView?.viewKind === 'table'"
:project-id="projectId"
:is-loading-project="isLoadingProject"
:view-id
/>
<ProjectKanban
v-if="currentView?.viewKind === 'kanban'"
:project-id="projectId"
:is-loading-project="isLoadingProject"
:view-id
/>
</template>
@@ -25,6 +25,12 @@ import {computed} from 'vue'
import DOMPurify from 'dompurify'
import {useProjectStore} from '@/stores/projects'
definePage({
name: 'project.info',
meta: { showAsModal: true },
props: route => ({ projectId: Number(route.params.projectId as string) }),
})
const props = defineProps<{
projectId: number
}>()
@@ -28,6 +28,11 @@ import {useTitle} from '@/composables/useTitle'
import {useBaseStore} from '@/stores/base'
import {useProjectStore} from '@/stores/projects'
definePage({
name: 'project.settings.archive',
meta: { showAsModal: true }
})
const {t} = useI18n({useScope: 'global'})
const projectStore = useProjectStore()
const router = useRouter()
@@ -133,6 +133,11 @@ import {useTitle} from '@/composables/useTitle'
import CreateEdit from '@/components/misc/CreateEdit.vue'
import {success} from '@/message'
definePage({
name: 'project.settings.background',
meta: { showAsModal: true }
})
const SEARCH_DEBOUNCE = 300
const {t} = useI18n({useScope: 'global'})
@@ -41,6 +41,11 @@ import Loading from '@/components/misc/Loading.vue'
import {useProjectStore} from '@/stores/projects'
import TaskService from '@/services/task'
definePage({
name: 'project.settings.delete',
meta: { showAsModal: true }
})
const {t} = useI18n({useScope: 'global'})
const projectStore = useProjectStore()
const route = useRoute()
@@ -24,6 +24,11 @@ import {useTitle} from '@/composables/useTitle'
import {useProject, useProjectStore} from '@/stores/projects'
import type {IProject} from '@/modelTypes/IProject'
definePage({
name: 'project.settings.duplicate',
meta: { showAsModal: true }
})
const {t} = useI18n({useScope: 'global'})
useTitle(() => t('project.duplicate.title'))
@@ -101,6 +101,14 @@ import {useProject} from '@/stores/projects'
import {useTitle} from '@/composables/useTitle'
import {RIGHTS} from '@/constants/rights'
definePage({
name: 'project.settings.edit',
props: route => ({ projectId: Number(route.params.projectId as string) }),
meta: {
showAsModal: true,
},
})
const props = defineProps<{
projectId: IProject['id'],
}>()
@@ -48,6 +48,11 @@ import userTeam from '@/components/sharing/UserTeam.vue'
import {useBaseStore} from '@/stores/base'
import {useConfigStore} from '@/stores/config'
definePage({
name: 'project.settings.share',
meta: { showAsModal: true }
})
const {t} = useI18n({useScope: 'global'})
const project = ref<IProject>()
@@ -16,6 +16,12 @@ import Message from '@/components/misc/Message.vue'
import draggable from 'zhyswan-vuedraggable'
import {calculateItemPosition} from '@/helpers/calculateItemPosition'
definePage({
name: 'project.settings.views',
meta: { showAsModal: true },
props: route => ({ projectId: Number(route.params.projectId as string) }),
})
const props = defineProps<{
projectId: number
}>()
@@ -25,6 +25,11 @@ import FancyCheckbox from '@/components/input/FancyCheckbox.vue'
import {success} from '@/message'
import {isValidHttpUrl} from '@/helpers/isValidHttpUrl'
definePage({
name: 'project.settings.webhooks',
meta: { showAsModal: true }
})
const {t} = useI18n({useScope: 'global'})
const project = ref<IProject>()
@@ -48,6 +48,8 @@ import {useStorage} from '@vueuse/core'
import {useProjectStore} from '@/stores/projects'
definePage({ name: 'projects.index' })
const {t} = useI18n()
const projectStore = useProjectStore()
@@ -35,7 +35,7 @@
</a>
<RouterLink
v-else
:to="{ name: 'project.index', params: { projectId: p.id } }"
:to="{ name: 'project', params: { projectId: p.id } }"
>
{{ getProjectTitle(p) }}
</RouterLink>
@@ -644,6 +644,11 @@ import {useTitle} from '@/composables/useTitle'
import {success} from '@/message'
import type {Action as MessageAction} from '@/message'
definePage({
name: 'task.detail',
props: route => ({ taskId: Number(route.params.id as string) })
})
const props = defineProps<{
taskId: ITask['id'],
backdropView?: RouteLocation['fullPath'],
@@ -876,7 +881,7 @@ const showDeleteModal = ref(false)
async function deleteTask() {
await taskStore.delete(task.value)
success({message: t('task.detail.deleteSuccess')})
router.push({name: 'project.index', params: {projectId: task.value.projectId}})
router.push({name: 'project', params: {projectId: task.value.projectId}})
}
async function toggleTaskDone() {
+27
View File
@@ -0,0 +1,27 @@
<template>
<ShowTasks v-bind="props" />
</template>
<script setup lang="ts">
import {parseDateOrString} from '@/helpers/time/parseDateOrString'
import {getNextWeekDate} from '@/helpers/time/getNextWeekDate'
import ShowTasks from '@/components/tasks/ShowTasks.vue';
definePage({
name: 'tasks.range',
props: route => ({
dateFrom: parseDateOrString(route.query.from as string, new Date()),
dateTo: parseDateOrString(route.query.to as string, getNextWeekDate()),
showNulls: route.query.showNulls === 'true',
showOverdue: route.query.showOverdue === 'true',
})
})
const props = defineProps<{
dateFrom?: Date | string,
dateTo?: Date | string,
showNulls?: boolean,
showOverdue?: boolean,
}>()
</script>
@@ -282,6 +282,8 @@ import type {ITeam} from '@/modelTypes/ITeam'
import type {IUser} from '@/modelTypes/IUser'
import type {ITeamMember} from '@/modelTypes/ITeamMember'
definePage({ name: 'teams.edit' })
const authStore = useAuthStore()
const configStore = useConfigStore()
const route = useRoute()
@@ -46,6 +46,8 @@ import { useI18n } from 'vue-i18n'
import TeamService from '@/services/team'
import { useTitle } from '@/composables/useTitle'
definePage({ name: 'teams.index' })
const { t } = useI18n({useScope: 'global'})
useTitle(() => t('team.title'))
@@ -74,6 +74,11 @@ import {success} from '@/message'
import {useConfigStore} from '@/stores/config'
definePage({
name: 'teams.create',
meta: { showAsModal: true }
})
const {t} = useI18n()
const title = computed(() => t('team.create.title'))
useTitle(title)
@@ -47,6 +47,8 @@ import {ref, computed, reactive} from 'vue'
import DataExportService from '@/services/dataExport'
import {useAuthStore} from '@/stores/auth'
definePage({ name: 'user.export.download' })
const dataExportService = reactive(new DataExportService())
const password = ref('')
const errPasswordRequired = ref(false)
@@ -32,6 +32,11 @@ import { useConfigStore } from '@/stores/config'
import { useAuthStore } from '@/stores/auth'
import {useRoute} from 'vue-router'
definePage({
name: 'user.settings',
redirect: {name: 'user.settings.general'}
})
const { t } = useI18n({useScope: 'global'})
useTitle(() => t('user.settings.title'))
@@ -14,6 +14,8 @@ import {useI18n} from 'vue-i18n'
import Message from '@/components/misc/Message.vue'
import type {IApiToken} from '@/modelTypes/IApiToken'
definePage({ name: 'user.settings.apiTokens' })
const service = new ApiTokenService()
const tokens = ref<IApiToken[]>([])
const apiDocsUrl = window.API_URL + '/docs'
@@ -81,6 +81,8 @@ import {useTitle} from '@/composables/useTitle'
import {success} from '@/message'
import {useAuthStore} from '@/stores/auth'
definePage({ name: 'user.settings.avatar' })
const {t} = useI18n({useScope: 'global'})
const authStore = useAuthStore()
@@ -114,6 +114,8 @@ import type {ICaldavToken} from '@/modelTypes/ICaldavToken'
import {useConfigStore} from '@/stores/config'
import {useAuthStore} from '@/stores/auth'
definePage({ name: 'user.settings.caldav' })
const copy = useCopyToClipboard()
const {t} = useI18n({useScope: 'global'})
@@ -58,6 +58,8 @@ import {useTitle} from '@/composables/useTitle'
import {success} from '@/message'
import {useAuthStore} from '@/stores/auth'
definePage({ name: 'user.settings.data-export' })
const {t} = useI18n({useScope: 'global'})
const authStore = useAuthStore()
@@ -126,6 +126,8 @@ import {success} from '@/message'
import {useAuthStore} from '@/stores/auth'
import {useConfigStore} from '@/stores/config'
definePage({ name: 'user.settings.deletion' })
const {t} = useI18n({useScope: 'global'})
useTitle(() => `${t('user.deletion.title')} - ${t('user.settings.title')}`)
@@ -62,6 +62,8 @@ import {success} from '@/message'
import {useTitle} from '@/composables/useTitle'
import {useAuthStore} from '@/stores/auth'
definePage({ name: 'user.settings.email-update' })
const {t} = useI18n({useScope: 'global'})
useTitle(() => `${t('user.settings.updateEmailTitle')} - ${t('user.settings.title')}`)
@@ -239,6 +239,8 @@ import type {IUserSettings} from '@/modelTypes/IUserSettings'
import {isSavedFilter} from '@/services/savedFilter'
import {DEFAULT_PROJECT_VIEW_SETTINGS} from '@/modelTypes/IProjectView'
definePage({ name: 'user.settings.general' })
const {t} = useI18n({useScope: 'global'})
useTitle(() => `${t('user.settings.general.title')} - ${t('user.settings.title')}`)
@@ -24,10 +24,12 @@
import {computed} from 'vue'
import {useI18n} from 'vue-i18n'
import {MIGRATORS} from './migrators'
import {MIGRATORS} from '@/helpers/migrators'
import {useTitle} from '@/composables/useTitle'
import {useConfigStore} from '@/stores/config'
definePage({ name: 'migrate.start' })
const {t} = useI18n({useScope: 'global'})
useTitle(() => t('migrate.title'))
@@ -83,6 +83,8 @@ import {useTitle} from '@/composables/useTitle'
import {success, error} from '@/message'
import {useAuthStore} from '@/stores/auth'
definePage({ name: 'user.settings.password-update' })
const passwordUpdateService = shallowReactive(new PasswordUpdateService())
const passwordUpdate = reactive(new PasswordUpdateModel())
const passwordConfirm = ref('')
@@ -110,6 +110,8 @@ import {useTitle} from '@/composables/useTitle'
import {useConfigStore} from '@/stores/config'
import type {ITotp} from '@/modelTypes/ITotp'
definePage({ name: 'user.settings.totp' })
const {t} = useI18n({useScope: 'global'})
useTitle(() => `${t('user.settings.totp.title')} - ${t('user.settings.title')}`)
+26 -368
View File
@@ -1,74 +1,25 @@
import { createRouter, createWebHistory } from 'vue-router'
import type { RouteLocation } from 'vue-router'
import { createRouter, createWebHistory, type RouteLocation, type RouteRecordInfo, type ParamValue } from 'vue-router'
import { routes, handleHotUpdate } from 'vue-router/auto-routes'
import {saveLastVisited} from '@/helpers/saveLastVisited'
import {getProjectViewId} from '@/helpers/projectView'
import {parseDateOrString} from '@/helpers/time/parseDateOrString'
import {getNextWeekDate} from '@/helpers/time/getNextWeekDate'
import {LINK_SHARE_HASH_PREFIX} from '@/constants/linkShareHash'
import {useAuthStore} from '@/stores/auth'
import {useBaseStore} from '@/stores/base'
import HomeComponent from '@/views/Home.vue'
import NotFoundComponent from '@/views/404.vue'
const About = () => import('@/views/About.vue')
// User Handling
import LoginComponent from '@/views/user/Login.vue'
import RegisterComponent from '@/views/user/Register.vue'
import OpenIdAuth from '@/views/user/OpenIdAuth.vue'
const DataExportDownload = () => import('@/views/user/DataExportDownload.vue')
// Tasks
import UpcomingTasksComponent from '@/views/tasks/ShowTasks.vue'
import LinkShareAuthComponent from '@/views/sharing/LinkSharingAuth.vue'
const TaskDetailView = () => import('@/views/tasks/TaskDetailView.vue')
import Register from '@/views/user/Register.vue'
import LinkSharingAuth from '@/views/sharing/LinkSharingAuth.vue'
// Team Handling
const ListTeamsComponent = () => import('@/views/teams/ListTeams.vue')
// Label Handling
const ListLabelsComponent = () => import('@/views/labels/ListLabels.vue')
const NewLabelComponent = () => import('@/views/labels/NewLabel.vue')
// Migration
const MigrationComponent = () => import('@/views/migrate/Migration.vue')
const MigrationHandlerComponent = () => import('@/views/migrate/MigrationHandler.vue')
// Project View
import ProjectView from '@/views/project/ProjectView.vue'
const ProjectInfo = () => import('@/views/project/ProjectInfo.vue')
declare module 'vue-router/auto-routes' {
export interface RouteNamedMap {
'/register': RouteRecordInfo<'/register', '/register', {}, {}>,
'/share/[share]/auth': RouteRecordInfo<'/share/[share]/auth', '/share/:share/auth', { share: ParamValue<true> }, { share: ParamValue<false> }>,
// Project Settings
const ListProjects = () => import('@/views/project/ListProjects.vue')
const ProjectSettingEdit = () => import('@/views/project/settings/ProjectSettingsEdit.vue')
const ProjectSettingBackground = () => import('@/views/project/settings/ProjectSettingsBackground.vue')
const ProjectSettingDuplicate = () => import('@/views/project/settings/ProjectSettingsDuplicate.vue')
const ProjectSettingShare = () => import('@/views/project/settings/ProjectSettingsShare.vue')
const ProjectSettingWebhooks = () => import('@/views/project/settings/ProjectSettingsWebhooks.vue')
const ProjectSettingDelete = () => import('@/views/project/settings/ProjectSettingsDelete.vue')
const ProjectSettingArchive = () => import('@/views/project/settings/ProjectSettingsArchive.vue')
const ProjectSettingViews = () => import('@/views/project/settings/ProjectSettingsViews.vue')
}
}
// Saved Filters
const FilterNew = () => import('@/views/filters/FilterNew.vue')
const FilterEdit = () => import('@/views/filters/FilterEdit.vue')
const FilterDelete = () => import('@/views/filters/FilterDelete.vue')
const PasswordResetComponent = () => import('@/views/user/PasswordReset.vue')
const GetPasswordResetComponent = () => import('@/views/user/RequestPasswordReset.vue')
const UserSettingsComponent = () => import('@/views/user/Settings.vue')
const UserSettingsAvatarComponent = () => import('@/views/user/settings/Avatar.vue')
const UserSettingsCaldavComponent = () => import('@/views/user/settings/Caldav.vue')
const UserSettingsDataExportComponent = () => import('@/views/user/settings/DataExport.vue')
const UserSettingsDeletionComponent = () => import('@/views/user/settings/Deletion.vue')
const UserSettingsEmailUpdateComponent = () => import('@/views/user/settings/EmailUpdate.vue')
const UserSettingsGeneralComponent = () => import('@/views/user/settings/General.vue')
const UserSettingsPasswordUpdateComponent = () => import('@/views/user/settings/PasswordUpdate.vue')
const UserSettingsTOTPComponent = () => import('@/views/user/settings/TOTP.vue')
const UserSettingsApiTokensComponent = () => import('@/views/user/settings/ApiTokens.vue')
// Project Handling
const NewProjectComponent = () => import('@/views/project/NewProject.vue')
const EditTeamComponent = () => import('@/views/teams/EditTeam.vue')
const NewTeamComponent = () => import('@/views/teams/NewTeam.vue')
console.log(routes)
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
@@ -87,147 +38,23 @@ const router = createRouter({
return {left: 0, top: 0}
},
routes: [
{
path: '/',
name: 'home',
component: HomeComponent,
},
{
path: '/:pathMatch(.*)*',
name: 'not-found',
component: NotFoundComponent,
},
// if you omit the last `*`, the `/` character in params will be encoded when resolving or pushing
{
path: '/:pathMatch(.*)',
name: 'bad-not-found',
component: NotFoundComponent,
},
{
path: '/login',
name: 'user.login',
component: LoginComponent,
meta: {
title: 'user.auth.login',
},
},
{
path: '/get-password-reset',
name: 'user.password-reset.request',
component: GetPasswordResetComponent,
meta: {
title: 'user.auth.resetPassword',
},
},
{
path: '/password-reset',
name: 'user.password-reset.reset',
component: PasswordResetComponent,
meta: {
title: 'user.auth.resetPassword',
},
},
...routes,
{
path: '/register',
name: 'user.register',
component: RegisterComponent,
// FIXME: use dynamic imports
// component: () => import('@/views/user/Register.vue'),
component: Register,
meta: {
title: 'user.auth.createAccount',
},
},
{
path: '/user/settings',
name: 'user.settings',
component: UserSettingsComponent,
redirect: {name: 'user.settings.general'},
children: [
{
path: '/user/settings/avatar',
name: 'user.settings.avatar',
component: UserSettingsAvatarComponent,
},
{
path: '/user/settings/caldav',
name: 'user.settings.caldav',
component: UserSettingsCaldavComponent,
},
{
path: '/user/settings/data-export',
name: 'user.settings.data-export',
component: UserSettingsDataExportComponent,
},
{
path: '/user/settings/deletion',
name: 'user.settings.deletion',
component: UserSettingsDeletionComponent,
},
{
path: '/user/settings/email-update',
name: 'user.settings.email-update',
component: UserSettingsEmailUpdateComponent,
},
{
path: '/user/settings/general',
name: 'user.settings.general',
component: UserSettingsGeneralComponent,
},
{
path: '/user/settings/password-update',
name: 'user.settings.password-update',
component: UserSettingsPasswordUpdateComponent,
},
{
path: '/user/settings/totp',
name: 'user.settings.totp',
component: UserSettingsTOTPComponent,
},
{
path: '/user/settings/api-tokens',
name: 'user.settings.apiTokens',
component: UserSettingsApiTokensComponent,
},
{
path: '/user/settings/migrate',
name: 'migrate.start',
component: MigrationComponent,
},
{
path: '/migrate/:service',
name: 'migrate.service',
component: MigrationHandlerComponent,
props: route => ({
service: route.params.service as string,
code: route.query.code as string,
}),
},
],
},
{
path: '/user/export/download',
name: 'user.export.download',
component: DataExportDownload,
},
{
path: '/share/:share/auth',
name: 'link-share.auth',
component: LinkShareAuthComponent,
},
{
path: '/tasks/:id',
name: 'task.detail',
component: TaskDetailView,
props: route => ({ taskId: Number(route.params.id as string) }),
},
{
path: '/tasks/by/upcoming',
name: 'tasks.range',
component: UpcomingTasksComponent,
props: route => ({
dateFrom: parseDateOrString(route.query.from as string, new Date()),
dateTo: parseDateOrString(route.query.to as string, getNextWeekDate()),
showNulls: route.query.showNulls === 'true',
showOverdue: route.query.showOverdue === 'true',
}),
// FIXME: use dynamic imports
// component: () => import('@/views/sharing/LinkSharingAuth.vue'),
component: LinkSharingAuth,
},
{
// Redirect old list routes to the respective project routes
@@ -242,98 +69,10 @@ const router = createRouter({
}
},
},
{
path: '/projects',
name: 'projects.index',
component: ListProjects,
},
{
path: '/projects/new',
name: 'project.create',
component: NewProjectComponent,
meta: {
showAsModal: true,
},
},
{
path: '/projects/:parentProjectId/new',
name: 'project.createFromParent',
component: NewProjectComponent,
props: route => ({ parentProjectId: Number(route.params.parentProjectId as string) }),
meta: {
showAsModal: true,
},
},
{
path: '/projects/:projectId/settings/edit',
name: 'project.settings.edit',
component: ProjectSettingEdit,
props: route => ({ projectId: Number(route.params.projectId as string) }),
meta: {
showAsModal: true,
},
},
{
path: '/projects/:projectId/settings/background',
name: 'project.settings.background',
component: ProjectSettingBackground,
meta: {
showAsModal: true,
},
},
{
path: '/projects/:projectId/settings/duplicate',
name: 'project.settings.duplicate',
component: ProjectSettingDuplicate,
meta: {
showAsModal: true,
},
},
{
path: '/projects/:projectId/settings/share',
name: 'project.settings.share',
component: ProjectSettingShare,
meta: {
showAsModal: true,
},
},
{
path: '/projects/:projectId/settings/webhooks',
name: 'project.settings.webhooks',
component: ProjectSettingWebhooks,
meta: {
showAsModal: true,
},
},
{
path: '/projects/:projectId/settings/delete',
name: 'project.settings.delete',
component: ProjectSettingDelete,
meta: {
showAsModal: true,
},
},
{
path: '/projects/:projectId/settings/archive',
name: 'project.settings.archive',
component: ProjectSettingArchive,
meta: {
showAsModal: true,
},
},
{
path: '/projects/:projectId/settings/views',
name: 'project.settings.views',
component: ProjectSettingViews,
meta: {
showAsModal: true,
},
props: route => ({ projectId: Number(route.params.projectId as string) }),
},
{
path: '/projects/:projectId/settings/edit',
name: 'filter.settings.edit',
component: FilterEdit,
component: () => import('@/views/filters/FilterEdit.vue'),
meta: {
showAsModal: true,
},
@@ -342,101 +81,20 @@ const router = createRouter({
{
path: '/projects/:projectId/settings/delete',
name: 'filter.settings.delete',
component: FilterDelete,
component: () => import('@/views/filters/FilterDelete.vue'),
meta: {
showAsModal: true,
},
props: route => ({ projectId: Number(route.params.projectId as string) }),
},
{
path: '/projects/:projectId/info',
name: 'project.info',
component: ProjectInfo,
meta: {
showAsModal: true,
},
props: route => ({ projectId: Number(route.params.projectId as string) }),
},
{
path: '/projects/:projectId',
name: 'project.index',
redirect(to) {
const viewId = getProjectViewId(Number(to.params.projectId as string))
if (viewId) {
console.debug('Replaced list view with', viewId)
}
return {
name: 'project.view',
params: {
projectId: parseInt(to.params.projectId as string),
viewId: viewId ?? 0,
},
}
},
},
{
path: '/projects/:projectId/:viewId',
name: 'project.view',
component: ProjectView,
props: route => ({
projectId: parseInt(route.params.projectId as string),
viewId: route.params.viewId ? parseInt(route.params.viewId as string): undefined,
}),
},
{
path: '/teams',
name: 'teams.index',
component: ListTeamsComponent,
},
{
path: '/teams/new',
name: 'teams.create',
component: NewTeamComponent,
meta: {
showAsModal: true,
},
},
{
path: '/teams/:id/edit',
name: 'teams.edit',
component: EditTeamComponent,
},
{
path: '/labels',
name: 'labels.index',
component: ListLabelsComponent,
},
{
path: '/labels/new',
name: 'labels.create',
component: NewLabelComponent,
meta: {
showAsModal: true,
},
},
{
path: '/filters/new',
name: 'filters.create',
component: FilterNew,
meta: {
showAsModal: true,
},
},
{
path: '/auth/openid/:provider',
name: 'openid.auth',
component: OpenIdAuth,
},
{
path: '/about',
name: 'about',
component: About,
},
],
})
// Update routes at runtime without reloading the page
if (import.meta.hot) {
handleHotUpdate(router)
}
export async function getAuthForRoute(to: RouteLocation, authStore) {
if (authStore.authUser || authStore.authLinkShare) {
return
+1 -1
View File
@@ -87,7 +87,7 @@ export function useSavedFilter(projectId?: MaybeRefOrGetter<IProject['id']>) {
async function createFilter() {
filter.value = await filterService.create(filter.value)
await projectStore.loadAllProjects()
router.push({name: 'project.index', params: {projectId: getProjectId(filter.value)}})
router.push({name: 'project', params: {projectId: getProjectId(filter.value)}})
}
async function saveFilter() {
+1 -1
View File
@@ -6,7 +6,7 @@ import {HTTPFactory} from '@/helpers/fetcher'
import {objectToCamelCase} from '@/helpers/case'
import type {IProvider} from '@/types/IProvider'
import type {MIGRATORS} from '@/views/migrate/migrators'
import type {MIGRATORS} from '@/helpers/migrators'
import {InvalidApiUrlProvidedError} from '@/helpers/checkAndSetApiUrl'
export interface ConfigState {
+2 -2
View File
@@ -150,7 +150,7 @@ export const useProjectStore = defineStore('project', () => {
const createdProject = await projectService.create(project)
setProject(createdProject)
router.push({
name: 'project.index',
name: 'project',
params: { projectId: createdProject.id },
})
return createdProject
@@ -315,7 +315,7 @@ export function useProject(projectId: MaybeRefOrGetter<IProject['id']>) {
projectStore.setProject(duplicate.duplicatedProject)
success({message: t('project.duplicate.success')})
router.push({name: 'project.index', params: {projectId: duplicate.duplicatedProject.id}})
router.push({name: 'project', params: {projectId: duplicate.duplicatedProject.id}})
}
return {
@@ -55,6 +55,8 @@ import {useBaseStore} from '@/stores/base'
import {useAuthStore} from '@/stores/auth'
import {useRedirectToLastVisited} from '@/composables/useRedirectToLastVisited'
definePage({ name: 'link-share.auth' })
const {t} = useI18n({useScope: 'global'})
useTitle(t('sharing.authenticating'))
const {getLastVisitedRoute} = useRedirectToLastVisited()
@@ -106,7 +108,7 @@ function useAuth() {
}
return router.push({
name: 'project.index',
name: 'project',
params: {
projectId,
},
+12 -8
View File
@@ -129,18 +129,22 @@ import {useAuthStore} from '@/stores/auth'
import {useConfigStore} from '@/stores/config'
import {validatePassword} from '@/helpers/validatePasswort'
definePage({
name: 'user.register',
meta: { title: 'user.auth.createAccount' },
beforeEnter() {
const authStore = useAuthStore()
if (authStore.authenticated) {
router.push({ name: 'home' })
}
}
})
const {t} = useI18n()
const authStore = useAuthStore()
const configStore = useConfigStore()
// FIXME: use the `beforeEnter` hook of vue-router
// Check if the user is already logged in, if so, redirect them to the homepage
onBeforeMount(() => {
if (authStore.authenticated) {
router.push({name: 'home'})
}
})
const credentials = reactive({
username: '',
email: '',
+3 -1
View File
@@ -6,7 +6,9 @@
"src/**/*",
"src/**/*.vue",
"src/**/*.json",
"tailwind.config.js"
"tailwind.config.js",
// https://uvr.esm.is/introduction.html#setup
"./typed-router.d.ts"
],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
+1 -6
View File
@@ -3,12 +3,7 @@
"@tsconfig/node22/tsconfig.json",
"@vue/tsconfig/tsconfig.json"
],
"include": [
"env.config.d.ts",
"vite.config.*",
"vitest.config.*",
"cypress.config.*"
],
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*"],
"compilerOptions": {
"composite": true,
"noEmit": true,
+62
View File
@@ -0,0 +1,62 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️
// It's recommended to commit this file.
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.
declare module 'vue-router/auto-routes' {
import type {
RouteRecordInfo,
ParamValue,
ParamValueOneOrMore,
ParamValueZeroOrMore,
ParamValueZeroOrOne,
} from 'vue-router'
/**
* Route name map generated by unplugin-vue-router
*/
export interface RouteNamedMap {
'home': RouteRecordInfo<'home', '/', Record<never, never>, Record<never, never>>,
'user.password-reset.request': RouteRecordInfo<'user.password-reset.request', '/:auth?/get-password-reset', { auth?: ParamValueZeroOrOne<true> }, { auth?: ParamValueZeroOrOne<false> }>,
'user.login': RouteRecordInfo<'user.login', '/:auth?/login', { auth?: ParamValueZeroOrOne<true> }, { auth?: ParamValueZeroOrOne<false> }>,
'user.password-reset.reset': RouteRecordInfo<'user.password-reset.reset', '/:auth?/password-reset', { auth?: ParamValueZeroOrOne<true> }, { auth?: ParamValueZeroOrOne<false> }>,
'not-found': RouteRecordInfo<'not-found', '/:path(.*)*', { path?: ParamValueZeroOrMore<true> }, { path?: ParamValueZeroOrMore<false> }>,
'about': RouteRecordInfo<'about', '/about', Record<never, never>, Record<never, never>>,
'openid.auth': RouteRecordInfo<'openid.auth', '/auth/openid/:provider', { provider: ParamValue<true> }, { provider: ParamValue<false> }>,
'filters.create': RouteRecordInfo<'filters.create', '/filters/new', Record<never, never>, Record<never, never>>,
'labels.index': RouteRecordInfo<'labels.index', '/labels', Record<never, never>, Record<never, never>>,
'labels.create': RouteRecordInfo<'labels.create', '/labels/new', Record<never, never>, Record<never, never>>,
'migrate.service': RouteRecordInfo<'migrate.service', '/migrate/:service', { service: ParamValue<true> }, { service: ParamValue<false> }>,
'projects.index': RouteRecordInfo<'projects.index', '/projects', Record<never, never>, Record<never, never>>,
'project.create': RouteRecordInfo<'project.create', '/projects/:parentProjectId?/new', { parentProjectId?: ParamValueZeroOrOne<true> }, { parentProjectId?: ParamValueZeroOrOne<false> }>,
'project': RouteRecordInfo<'project', '/projects/:projectId/:viewId?', { projectId: ParamValue<true>, viewId?: ParamValueZeroOrOne<true> }, { projectId: ParamValue<false>, viewId?: ParamValueZeroOrOne<false> }>,
'project.info': RouteRecordInfo<'project.info', '/projects/:projectId/info', { projectId: ParamValue<true> }, { projectId: ParamValue<false> }>,
'project.settings.archive': RouteRecordInfo<'project.settings.archive', '/projects/:projectId/settings/archive', { projectId: ParamValue<true> }, { projectId: ParamValue<false> }>,
'project.settings.background': RouteRecordInfo<'project.settings.background', '/projects/:projectId/settings/background', { projectId: ParamValue<true> }, { projectId: ParamValue<false> }>,
'project.settings.delete': RouteRecordInfo<'project.settings.delete', '/projects/:projectId/settings/delete', { projectId: ParamValue<true> }, { projectId: ParamValue<false> }>,
'project.settings.duplicate': RouteRecordInfo<'project.settings.duplicate', '/projects/:projectId/settings/duplicate', { projectId: ParamValue<true> }, { projectId: ParamValue<false> }>,
'project.settings.edit': RouteRecordInfo<'project.settings.edit', '/projects/:projectId/settings/edit', { projectId: ParamValue<true> }, { projectId: ParamValue<false> }>,
'project.settings.share': RouteRecordInfo<'project.settings.share', '/projects/:projectId/settings/share', { projectId: ParamValue<true> }, { projectId: ParamValue<false> }>,
'project.settings.views': RouteRecordInfo<'project.settings.views', '/projects/:projectId/settings/views', { projectId: ParamValue<true> }, { projectId: ParamValue<false> }>,
'project.settings.webhooks': RouteRecordInfo<'project.settings.webhooks', '/projects/:projectId/settings/webhooks', { projectId: ParamValue<true> }, { projectId: ParamValue<false> }>,
'task.detail': RouteRecordInfo<'task.detail', '/task/:id', { id: ParamValue<true> }, { id: ParamValue<false> }>,
'tasks.range': RouteRecordInfo<'tasks.range', '/tasks/by/upcoming', Record<never, never>, Record<never, never>>,
'teams.index': RouteRecordInfo<'teams.index', '/teams', Record<never, never>, Record<never, never>>,
'teams.edit': RouteRecordInfo<'teams.edit', '/teams/:id/edit', { id: ParamValue<true> }, { id: ParamValue<false> }>,
'teams.create': RouteRecordInfo<'teams.create', '/teams/new', Record<never, never>, Record<never, never>>,
'user.export.download': RouteRecordInfo<'user.export.download', '/user/export/download', Record<never, never>, Record<never, never>>,
'user.settings': RouteRecordInfo<'user.settings', '/user/settings', Record<never, never>, Record<never, never>>,
'user.settings.apiTokens': RouteRecordInfo<'user.settings.apiTokens', '/user/settings/api-tokens', Record<never, never>, Record<never, never>>,
'user.settings.avatar': RouteRecordInfo<'user.settings.avatar', '/user/settings/avatar', Record<never, never>, Record<never, never>>,
'user.settings.caldav': RouteRecordInfo<'user.settings.caldav', '/user/settings/caldav', Record<never, never>, Record<never, never>>,
'user.settings.data-export': RouteRecordInfo<'user.settings.data-export', '/user/settings/data-export', Record<never, never>, Record<never, never>>,
'user.settings.deletion': RouteRecordInfo<'user.settings.deletion', '/user/settings/deletion', Record<never, never>, Record<never, never>>,
'user.settings.email-update': RouteRecordInfo<'user.settings.email-update', '/user/settings/email-update', Record<never, never>, Record<never, never>>,
'user.settings.general': RouteRecordInfo<'user.settings.general', '/user/settings/general', Record<never, never>, Record<never, never>>,
'migrate.start': RouteRecordInfo<'migrate.start', '/user/settings/migrate', Record<never, never>, Record<never, never>>,
'user.settings.password-update': RouteRecordInfo<'user.settings.password-update', '/user/settings/password-update', Record<never, never>, Record<never, never>>,
'user.settings.totp': RouteRecordInfo<'user.settings.totp', '/user/settings/totp', Record<never, never>, Record<never, never>>,
}
}
+2
View File
@@ -16,6 +16,7 @@ import postcssPresetEnv from 'postcss-preset-env'
import postcssEasingGradients from 'postcss-easing-gradients'
import tailwindcss from 'tailwindcss'
import vueDevTools from 'vite-plugin-vue-devtools'
import VueRouter from 'unplugin-vue-router/vite'
const pathSrc = fileURLToPath(new URL('./src', import.meta.url)).replaceAll('\\', '/')
@@ -105,6 +106,7 @@ export default defineConfig(({mode}) => {
propsDestructure: true,
},
}),
VueRouter(),
svgLoader({
// Since the svgs are already manually optimized via https://jakearchibald.github.io/svgomg/
// we don't need to optimize them again.
+1 -1
View File
@@ -67,7 +67,7 @@ require (
github.com/tkuchiki/go-timezone v0.2.3
github.com/typesense/typesense-go/v2 v2.0.0
github.com/ulule/limiter/v3 v3.11.2
github.com/wneessen/go-mail v0.6.1
github.com/wneessen/go-mail v0.6.0
github.com/yuin/goldmark v1.7.8
golang.org/x/crypto v0.32.0
golang.org/x/image v0.23.0
-2
View File
@@ -1377,8 +1377,6 @@ github.com/wneessen/go-mail v0.5.2 h1:MZKwgHJoRboLJ+EHMLuHpZc95wo+u1xViL/4XSswDT
github.com/wneessen/go-mail v0.5.2/go.mod h1:kRroJvEq2hOSEPFRiKjN7Csrz0G1w+RpiGR3b6yo+Ck=
github.com/wneessen/go-mail v0.6.0 h1:wO7EeJ8RL6DD+aycFGntil6b11g3FNQpQQQC1gkm97Y=
github.com/wneessen/go-mail v0.6.0/go.mod h1:G702XlFhzHV0Z4w9j2VsH5K9dJDvj0hx+yOOp1oX9vc=
github.com/wneessen/go-mail v0.6.1 h1:cDGqlGuEEhdILRe53VFzmM9WBk8Xh/QMvbO0oxrNJB4=
github.com/wneessen/go-mail v0.6.1/go.mod h1:G702XlFhzHV0Z4w9j2VsH5K9dJDvj0hx+yOOp1oX9vc=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=