Compare commits

...
Author SHA1 Message Date
Dominik Pschenitschni 356e83a6c9 feat: inline dynamic component definitions in routes 2025-01-17 14:59:59 +01:00
Dominik Pschenitschni 47538ca810 fix: method name 2025-01-17 13:59:12 +01:00
kolaente abae6f05e0 fix(auth): move read all notifications to notification group
Resolves
https://kolaente.dev/vikunja/vikunja/issues/2977
2025-01-17 12:52:42 +01:00
kolaente 45ec1a4c47 fix(auth): make sure routes from the "other" group work as intended
Resolves
https://kolaente.dev/vikunja/vikunja/issues/2977
2025-01-17 11:06:00 +01:00
kolaente 77d1616fea docs: adjust frontend readme
Resolves https://kolaente.dev/vikunja/vikunja/issues/3012
2025-01-17 10:41:45 +01:00
Dominik Pschenitschniandkonrad b5cb98498a fix: global component types
See canonical source https://github.com/vuejs/language-tools/wiki/Global-Component-Types
This was kind of hard to find, imho should be in vue docs itself…
2025-01-17 08:09:44 +00:00
Dominik Pschenitschniandkonrad 70e027a84e feat: withDefaults for RelatedTasks 2025-01-17 07:56:57 +00:00
Dominik Pschenitschniandkonrad 289bb73e9e feat: withDefaults for Flatpickr 2025-01-17 07:55:44 +00:00
Dominik Pschenitschniandkonrad 8bada3e967 fix: git ignore all dist folders 2025-01-17 07:53:54 +00:00
renovate 1863b06d0c chore(deps): update dev-dependencies 2025-01-17 00:07:27 +00:00
renovate d630586f63 chore(deps): update dependency go to v1.23.5 2025-01-16 21:07:59 +00:00
renovateandkonrad 13002d77f5 fix(deps): update module github.com/threedotslabs/watermill to v1.4.4 2025-01-16 15:38:43 +00:00
Dominik Pschenitschni a61e2d064d fix: lowlight imports for v3 2025-01-16 13:14:09 +01:00
renovateandDominik Pschenitschni e1f78462e5 fix(deps): update dependency lowlight to v3 2025-01-16 13:05:24 +01:00
12 changed files with 254 additions and 308 deletions
+2
View File
@@ -11,6 +11,8 @@ stats.html
node_modules
.DS_Store
dist
dist-dev
dist-test
coverage
*.zip
.vite/
+2 -18
View File
@@ -2,30 +2,14 @@
> The todo app to organize your life.
[![Build Status](https://drone.kolaente.de/api/badges/vikunja/vikunja/status.svg)](https://drone.kolaente.de/vikunja/vikunja)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](LICENSE)
[![Download](https://img.shields.io/badge/download-v0.22.1-brightgreen.svg)](https://dl.vikunja.io)
[![Translation](https://badges.crowdin.net/vikunja/localized.svg)](https://crowdin.com/project/vikunja)
This is the web frontend for Vikunja, written in Vue.js.
Take a look at [our roadmap](https://my.vikunja.cloud/share/UrdhKPqumxDXUbYpEGJLSIyNTwAnbBzVlwdDpRbv/auth) (hosted on Vikunja!) for a list of things we're currently working on!
## Security Reports
If you find any security-related issues you don't want to disclose publicly, please use [the contact information on our website](https://vikunja.io/contact/#security).
## Docker
There is a [docker image available](https://hub.docker.com/r/vikunja/vikunja) with support for http/2 and aggressive caching enabled.
In order to build it from sources run the command below. (Docker >= v19.03)
```shell
export DOCKER_BUILDKIT=1
docker build -t vikunja/frontend .
```
Refer to [multi-platform documentation](https://docs.docker.com/build/building/multi-platform/) in order to build for different platforms.
For general information about the project, refer to the top-level readme of this repo.
## Project setup
@@ -36,7 +20,7 @@ pnpm install
### Compiles and hot-reloads for development
```shell
pnpm run serve
pnpm run dev
```
### Compiles and minifies for production
+3 -3
View File
@@ -93,7 +93,7 @@
"floating-vue": "5.2.2",
"is-touch-device": "1.0.1",
"klona": "2.0.6",
"lowlight": "2.9.0",
"lowlight": "3.3.0",
"pinia": "2.3.0",
"register-service-worker": "1.7.2",
"sortablejs": "1.15.6",
@@ -132,7 +132,7 @@
"browserslist": "4.24.4",
"caniuse-lite": "1.0.30001692",
"csstype": "3.1.3",
"cypress": "13.17.0",
"cypress": "14.0.0",
"esbuild": "0.24.2",
"eslint": "9.18.0",
"eslint-plugin-vue": "9.32.0",
@@ -152,7 +152,7 @@
"vite-plugin-sentry": "1.4.0",
"vite-plugin-vue-devtools": "7.7.0",
"vite-svg-loader": "5.1.0",
"vitest": "2.1.8",
"vitest": "3.0.1",
"vue-tsc": "2.2.0",
"wait-on": "8.0.2",
"workbox-cli": "7.3.0"
+143 -125
View File
@@ -54,7 +54,7 @@ importers:
version: 2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))(@tiptap/pm@2.11.2)
'@tiptap/extension-code-block-lowlight':
specifier: 2.11.2
version: 2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))(@tiptap/extension-code-block@2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))(@tiptap/pm@2.11.2))(@tiptap/pm@2.11.2)(highlight.js@11.8.0)(lowlight@2.9.0)
version: 2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))(@tiptap/extension-code-block@2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))(@tiptap/pm@2.11.2))(@tiptap/pm@2.11.2)(highlight.js@11.11.1)(lowlight@3.3.0)
'@tiptap/extension-hard-break':
specifier: 2.11.2
version: 2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))
@@ -149,8 +149,8 @@ importers:
specifier: 2.0.6
version: 2.0.6
lowlight:
specifier: 2.9.0
version: 2.9.0
specifier: 3.3.0
version: 3.3.0
pinia:
specifier: 2.3.0
version: 2.3.0(typescript@5.7.3)(vue@3.5.13(typescript@5.7.3))
@@ -196,13 +196,13 @@ importers:
devDependencies:
'@4tw/cypress-drag-drop':
specifier: 2.2.5
version: 2.2.5(cypress@13.17.0)
version: 2.2.5(cypress@14.0.0)
'@cypress/vite-dev-server':
specifier: 6.0.1
version: 6.0.1(cypress@13.17.0)
version: 6.0.1(cypress@14.0.0)
'@cypress/vue':
specifier: 6.0.2
version: 6.0.2(cypress@13.17.0)(vue@3.5.13(typescript@5.7.3))
version: 6.0.2(cypress@14.0.0)(vue@3.5.13(typescript@5.7.3))
'@faker-js/faker':
specifier: 9.4.0
version: 9.4.0
@@ -261,8 +261,8 @@ importers:
specifier: 3.1.3
version: 3.1.3
cypress:
specifier: 13.17.0
version: 13.17.0
specifier: 14.0.0
version: 14.0.0
esbuild:
specifier: 0.24.2
version: 0.24.2
@@ -321,8 +321,8 @@ importers:
specifier: 5.1.0
version: 5.1.0(vue@3.5.13(typescript@5.7.3))
vitest:
specifier: 2.1.8
version: 2.1.8(@types/node@22.10.7)(happy-dom@16.6.0)(jsdom@20.0.3)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)
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.5.0)
vue-tsc:
specifier: 2.2.0
version: 2.2.0(typescript@5.7.3)
@@ -2376,8 +2376,8 @@ packages:
'@types/har-format@1.2.15':
resolution: {integrity: sha512-RpQH4rXLuvTXKR0zqHq3go0RVXYv/YVqv4TnPH95VbwUxZdQlK1EtcMvQvMpDngHbt13Csh9Z4qT9AbkiQH5BA==}
'@types/hast@2.3.10':
resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==}
'@types/hast@3.0.4':
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
'@types/is-touch-device@1.0.3':
resolution: {integrity: sha512-mEDTb0fQdHRzXLKbwTcpLxFFcQAzfUz6JdSj4qOS8ZevHH78umROLg1ftssalYHKjHz3qPgXBY9DrPsOFcDwMQ==}
@@ -2514,34 +2514,34 @@ packages:
vite: ^5.0.0 || ^6.0.0
vue: ^3.2.25
'@vitest/expect@2.1.8':
resolution: {integrity: sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==}
'@vitest/expect@3.0.1':
resolution: {integrity: sha512-oPrXe8dwvQdzUxQFWwibY97/smQ6k8iPVeSf09KEvU1yWzu40G6naHExY0lUgjnTPWMRGQOJnhMBb8lBu48feg==}
'@vitest/mocker@2.1.8':
resolution: {integrity: sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==}
'@vitest/mocker@3.0.1':
resolution: {integrity: sha512-5letLsVdFhReCPws/SNwyekBCyi4w2IusycV4T7eVdt2mfellS2yKDrEmnE5KPCHr0Ez5xCZVJbJws3ckuNNgQ==}
peerDependencies:
msw: ^2.4.9
vite: ^5.0.0
vite: ^5.0.0 || ^6.0.0
peerDependenciesMeta:
msw:
optional: true
vite:
optional: true
'@vitest/pretty-format@2.1.8':
resolution: {integrity: sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==}
'@vitest/pretty-format@3.0.1':
resolution: {integrity: sha512-FnyGQ9eFJ/Dnqg3jCvq9O6noXtxbZhOlSvNLZsCGJxhsGiZ5LDepmsTCizRfyGJt4Q6pJmZtx7rO/qqr9R9gDA==}
'@vitest/runner@2.1.8':
resolution: {integrity: sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==}
'@vitest/runner@3.0.1':
resolution: {integrity: sha512-LfVbbYOduTVx8PnYFGH98jpgubHBefIppbPQJBSlgjnRRlaX/KR6J46htECUHpf+ElJZ4xxssAfEz/Cb2iIMYA==}
'@vitest/snapshot@2.1.8':
resolution: {integrity: sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==}
'@vitest/snapshot@3.0.1':
resolution: {integrity: sha512-ZYV+iw2lGyc4QY2xt61b7Y3NJhSAO7UWcYWMcV0UnMrkXa8hXtfZES6WAk4g7Jr3p4qJm1P0cgDcOFyY5me+Ug==}
'@vitest/spy@2.1.8':
resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==}
'@vitest/spy@3.0.1':
resolution: {integrity: sha512-HnGJB3JFflnlka4u7aD0CfqrEtX3FgNaZAar18/KIhfo0r/WADn9PhBfiqAmNw4R/xaRcLzLPFXDwEQV1vHlJA==}
'@vitest/utils@2.1.8':
resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==}
'@vitest/utils@3.0.1':
resolution: {integrity: sha512-i+Gm61rfIeSitPUsu4ZcWqucfb18ShAanRpOG6KlXfd1j6JVK5XxO2Z6lEmfjMnAQRIvvLtJ3JByzDTv347e8w==}
'@volar/language-core@2.4.11':
resolution: {integrity: sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==}
@@ -3200,9 +3200,9 @@ packages:
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
cypress@13.17.0:
resolution: {integrity: sha512-5xWkaPurwkIljojFidhw8lFScyxhtiFHl/i/3zov+1Z5CmY4t9tjIdvSXfu82Y3w7wt0uR9KkucbhkVvJZLQSA==}
engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0}
cypress@14.0.0:
resolution: {integrity: sha512-kEGqQr23so5IpKeg/dp6GVi7RlHx1NmW66o2a2Q4wk9gRaAblLZQSiZJuDI8UMC4LlG5OJ7Q6joAiqTrfRNbTw==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
dashdash@1.14.1:
@@ -3351,11 +3351,18 @@ packages:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
detect-libc@1.0.3:
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
engines: {node: '>=0.10'}
hasBin: true
devlop@1.1.0:
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
devtools-protocol@0.0.981744:
resolution: {integrity: sha512-0cuGS8+jhR67Fy7qG3i3Pc7Aw494sb9yG9QgpG97SFVWwolgYjlhJg7n+UaHxOQT30d1TYu/EYe9k01ivLErIg==}
@@ -3492,8 +3499,8 @@ packages:
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
engines: {node: '>= 0.4'}
es-module-lexer@1.5.4:
resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
es-module-lexer@1.6.0:
resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==}
es-object-atoms@1.0.0:
resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==}
@@ -3680,9 +3687,6 @@ packages:
fastq@1.17.1:
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
fault@2.0.1:
resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==}
fd-slicer@1.1.0:
resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
@@ -3785,10 +3789,6 @@ packages:
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
engines: {node: '>= 6'}
format@0.2.2:
resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
engines: {node: '>=0.4.x'}
formdata-polyfill@4.0.10:
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
engines: {node: '>=12.20.0'}
@@ -3979,8 +3979,8 @@ packages:
header-case@2.0.4:
resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==}
highlight.js@11.8.0:
resolution: {integrity: sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg==}
highlight.js@11.11.1:
resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==}
engines: {node: '>=12.0.0'}
histoire@0.17.17:
@@ -4501,8 +4501,8 @@ packages:
resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==}
engines: {node: '>=8'}
lowlight@2.9.0:
resolution: {integrity: sha512-OpcaUTCLmHuVuBcyNckKfH5B0oA4JUavb/M/8n9iAvanJYNQkrVm4pvyX0SUaqkBG4dnWHKt7p50B3ngAG2Rfw==}
lowlight@3.3.0:
resolution: {integrity: sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==}
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
@@ -4516,6 +4516,9 @@ packages:
magic-string@0.30.14:
resolution: {integrity: sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==}
magic-string@0.30.17:
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
make-dir@3.1.0:
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
engines: {node: '>=8'}
@@ -4916,6 +4919,9 @@ packages:
pathe@1.1.2:
resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
pathe@2.0.1:
resolution: {integrity: sha512-6jpjMpOth5S9ITVu5clZ7NOgHNsv5vRQdheL9ztp2vZmM6fRbLvyua1tiBIL4lk8SAe3ARzeXEly6siXCjDHDw==}
pathval@2.0.0:
resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==}
engines: {node: '>= 14.16'}
@@ -5951,19 +5957,19 @@ packages:
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
tinyexec@0.3.1:
resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==}
tinyexec@0.3.2:
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
tinyglobby@0.2.10:
resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==}
engines: {node: '>=12.0.0'}
tinypool@1.0.1:
resolution: {integrity: sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==}
tinypool@1.0.2:
resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==}
engines: {node: ^18.0.0 || >=20.0.0}
tinyrainbow@1.2.0:
resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
tinyrainbow@2.0.0:
resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
engines: {node: '>=14.0.0'}
tinyspy@3.0.2:
@@ -6247,9 +6253,9 @@ packages:
engines: {node: '>=v14.18.0'}
hasBin: true
vite-node@2.1.8:
resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==}
engines: {node: ^18.0.0 || >=20.0.0}
vite-node@3.0.1:
resolution: {integrity: sha512-PoH9mCNsSZQXl3gdymM5IE4WR0k0WbnFd89nAyyDvltF2jVGdFcI8vpB1PBdKTcjAR7kkYiHSlIO68X/UT8Q1A==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
vite-plugin-inspect@0.8.9:
@@ -6367,15 +6373,15 @@ packages:
yaml:
optional: true
vitest@2.1.8:
resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==}
engines: {node: ^18.0.0 || >=20.0.0}
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
'@vitest/browser': 2.1.8
'@vitest/ui': 2.1.8
'@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
'@vitest/browser': 3.0.1
'@vitest/ui': 3.0.1
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
@@ -6702,9 +6708,9 @@ packages:
snapshots:
'@4tw/cypress-drag-drop@2.2.5(cypress@13.17.0)':
'@4tw/cypress-drag-drop@2.2.5(cypress@14.0.0)':
dependencies:
cypress: 13.17.0
cypress: 14.0.0
'@akryum/tinypool@0.3.1': {}
@@ -7765,9 +7771,9 @@ snapshots:
tunnel-agent: 0.6.0
uuid: 8.3.2
'@cypress/vite-dev-server@6.0.1(cypress@13.17.0)':
'@cypress/vite-dev-server@6.0.1(cypress@14.0.0)':
dependencies:
cypress: 13.17.0
cypress: 14.0.0
debug: 4.4.0(supports-color@8.1.1)
find-up: 6.3.0
node-html-parser: 5.3.3
@@ -7775,9 +7781,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@cypress/vue@6.0.2(cypress@13.17.0)(vue@3.5.13(typescript@5.7.3))':
'@cypress/vue@6.0.2(cypress@14.0.0)(vue@3.5.13(typescript@5.7.3))':
dependencies:
cypress: 13.17.0
cypress: 14.0.0
vue: 3.5.13(typescript@5.7.3)
'@cypress/xvfb@1.2.4(supports-color@8.1.1)':
@@ -8576,13 +8582,13 @@ snapshots:
dependencies:
'@tiptap/core': 2.11.2(@tiptap/pm@2.11.2)
'@tiptap/extension-code-block-lowlight@2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))(@tiptap/extension-code-block@2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))(@tiptap/pm@2.11.2))(@tiptap/pm@2.11.2)(highlight.js@11.8.0)(lowlight@2.9.0)':
'@tiptap/extension-code-block-lowlight@2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))(@tiptap/extension-code-block@2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))(@tiptap/pm@2.11.2))(@tiptap/pm@2.11.2)(highlight.js@11.11.1)(lowlight@3.3.0)':
dependencies:
'@tiptap/core': 2.11.2(@tiptap/pm@2.11.2)
'@tiptap/extension-code-block': 2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))(@tiptap/pm@2.11.2)
'@tiptap/pm': 2.11.2
highlight.js: 11.8.0
lowlight: 2.9.0
highlight.js: 11.11.1
lowlight: 3.3.0
'@tiptap/extension-code-block@2.11.2(@tiptap/core@2.11.2(@tiptap/pm@2.11.2))(@tiptap/pm@2.11.2)':
dependencies:
@@ -8801,7 +8807,7 @@ snapshots:
'@types/har-format@1.2.15': {}
'@types/hast@2.3.10':
'@types/hast@3.0.4':
dependencies:
'@types/unist': 2.0.11
@@ -8972,45 +8978,45 @@ snapshots:
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)
'@vitest/expect@2.1.8':
'@vitest/expect@3.0.1':
dependencies:
'@vitest/spy': 2.1.8
'@vitest/utils': 2.1.8
'@vitest/spy': 3.0.1
'@vitest/utils': 3.0.1
chai: 5.1.2
tinyrainbow: 1.2.0
tinyrainbow: 2.0.0
'@vitest/mocker@2.1.8(vite@5.4.11(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6))':
'@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.5.0))':
dependencies:
'@vitest/spy': 2.1.8
'@vitest/spy': 3.0.1
estree-walker: 3.0.3
magic-string: 0.30.14
magic-string: 0.30.17
optionalDependencies:
vite: 5.4.11(@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)
'@vitest/pretty-format@2.1.8':
'@vitest/pretty-format@3.0.1':
dependencies:
tinyrainbow: 1.2.0
tinyrainbow: 2.0.0
'@vitest/runner@2.1.8':
'@vitest/runner@3.0.1':
dependencies:
'@vitest/utils': 2.1.8
pathe: 1.1.2
'@vitest/utils': 3.0.1
pathe: 2.0.1
'@vitest/snapshot@2.1.8':
'@vitest/snapshot@3.0.1':
dependencies:
'@vitest/pretty-format': 2.1.8
magic-string: 0.30.14
pathe: 1.1.2
'@vitest/pretty-format': 3.0.1
magic-string: 0.30.17
pathe: 2.0.1
'@vitest/spy@2.1.8':
'@vitest/spy@3.0.1':
dependencies:
tinyspy: 3.0.2
'@vitest/utils@2.1.8':
'@vitest/utils@3.0.1':
dependencies:
'@vitest/pretty-format': 2.1.8
'@vitest/pretty-format': 3.0.1
loupe: 3.1.2
tinyrainbow: 1.2.0
tinyrainbow: 2.0.0
'@volar/language-core@2.4.11':
dependencies:
@@ -9782,7 +9788,7 @@ snapshots:
csstype@3.1.3: {}
cypress@13.17.0:
cypress@14.0.0:
dependencies:
'@cypress/request': 3.0.6
'@cypress/xvfb': 1.2.4(supports-color@8.1.1)
@@ -9944,9 +9950,15 @@ snapshots:
delayed-stream@1.0.0: {}
dequal@2.0.3: {}
detect-libc@1.0.3:
optional: true
devlop@1.1.0:
dependencies:
dequal: 2.0.3
devtools-protocol@0.0.981744: {}
diacritics@1.3.0: {}
@@ -10124,7 +10136,7 @@ snapshots:
es-errors@1.3.0: {}
es-module-lexer@1.5.4: {}
es-module-lexer@1.6.0: {}
es-object-atoms@1.0.0:
dependencies:
@@ -10426,10 +10438,6 @@ snapshots:
dependencies:
reusify: 1.0.4
fault@2.0.1:
dependencies:
format: 0.2.2
fd-slicer@1.1.0:
dependencies:
pend: 1.2.0
@@ -10532,8 +10540,6 @@ snapshots:
combined-stream: 1.0.8
mime-types: 2.1.35
format@0.2.2: {}
formdata-polyfill@4.0.10:
dependencies:
fetch-blob: 3.2.0
@@ -10744,7 +10750,7 @@ snapshots:
capital-case: 1.0.4
tslib: 2.7.0
highlight.js@11.8.0: {}
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)):
dependencies:
@@ -11275,11 +11281,11 @@ snapshots:
lowercase-keys@2.0.0: {}
lowlight@2.9.0:
lowlight@3.3.0:
dependencies:
'@types/hast': 2.3.10
fault: 2.0.1
highlight.js: 11.8.0
'@types/hast': 3.0.4
devlop: 1.1.0
highlight.js: 11.11.1
lru-cache@10.4.3: {}
@@ -11295,6 +11301,10 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
magic-string@0.30.17:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
make-dir@3.1.0:
dependencies:
semver: 6.3.1
@@ -11669,6 +11679,8 @@ snapshots:
pathe@1.1.2: {}
pathe@2.0.1: {}
pathval@2.0.0: {}
pause-stream@0.0.11:
@@ -12841,16 +12853,16 @@ snapshots:
tinybench@2.9.0: {}
tinyexec@0.3.1: {}
tinyexec@0.3.2: {}
tinyglobby@0.2.10:
dependencies:
fdir: 6.4.2(picomatch@4.0.2)
picomatch: 4.0.2
tinypool@1.0.1: {}
tinypool@1.0.2: {}
tinyrainbow@1.2.0: {}
tinyrainbow@2.0.0: {}
tinyspy@3.0.2: {}
@@ -13136,15 +13148,16 @@ snapshots:
- supports-color
- terser
vite-node@2.1.8(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6):
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.5.0):
dependencies:
cac: 6.7.14
debug: 4.4.0(supports-color@8.1.1)
es-module-lexer: 1.5.4
pathe: 1.1.2
vite: 5.4.11(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)
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)
transitivePeerDependencies:
- '@types/node'
- jiti
- less
- lightningcss
- sass
@@ -13153,6 +13166,8 @@ snapshots:
- sugarss
- supports-color
- terser
- 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)):
dependencies:
@@ -13251,33 +13266,34 @@ snapshots:
terser: 5.31.6
yaml: 2.5.0
vitest@2.1.8(@types/node@22.10.7)(happy-dom@16.6.0)(jsdom@20.0.3)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6):
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.5.0):
dependencies:
'@vitest/expect': 2.1.8
'@vitest/mocker': 2.1.8(vite@5.4.11(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6))
'@vitest/pretty-format': 2.1.8
'@vitest/runner': 2.1.8
'@vitest/snapshot': 2.1.8
'@vitest/spy': 2.1.8
'@vitest/utils': 2.1.8
'@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.5.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.3.7
debug: 4.4.0(supports-color@8.1.1)
expect-type: 1.1.0
magic-string: 0.30.14
pathe: 1.1.2
magic-string: 0.30.17
pathe: 2.0.1
std-env: 3.8.0
tinybench: 2.9.0
tinyexec: 0.3.1
tinypool: 1.0.1
tinyrainbow: 1.2.0
vite: 5.4.11(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)
vite-node: 2.1.8(@types/node@22.10.7)(sass-embedded@1.83.4)(sass@1.80.6)(terser@5.31.6)
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.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.5.0)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 22.10.7
happy-dom: 16.6.0
jsdom: 20.0.3
transitivePeerDependencies:
- jiti
- less
- lightningcss
- msw
@@ -13287,6 +13303,8 @@ snapshots:
- sugarss
- supports-color
- terser
- tsx
- yaml
vscode-uri@3.0.8: {}
@@ -167,7 +167,7 @@ import {Node} from '@tiptap/pm/model'
import Commands from './commands'
import suggestionSetup from './suggestion'
import {lowlight} from 'lowlight'
import {common, createLowlight} from 'lowlight'
import type {BottomAction, UploadCallback} from './types'
import type {ITask} from '@/modelTypes/ITask'
@@ -343,7 +343,7 @@ const extensions : Extensions = [
}),
CodeBlockLowlight.configure({
lowlight,
lowlight: createLowlight(common),
}),
HardBreak.extend({
addKeyboardShortcuts() {
@@ -62,29 +62,22 @@ export default {inheritAttrs: false}
</script>
<script setup lang="ts">
import {computed, onBeforeUnmount, onMounted, ref, toRefs, useAttrs, watch, watchEffect, type PropType} from 'vue'
import {computed, onBeforeUnmount, onMounted, ref, toRefs, useAttrs, watch, watchEffect} from 'vue'
const props = defineProps({
modelValue: {
type: [String, Number, Date, Array] as PropType<DateOption | DateOption[] | null>,
default: null,
},
// https://flatpickr.js.org/options/
config: {
type: Object as PropType<Options>,
default: () => ({
defaultDate: null,
wrap: false,
}),
},
events: {
type: Array as PropType<HookKey[]>,
default: () => includedEvents,
},
disabled: {
type: Boolean,
default: false,
},
const props = withDefaults(defineProps<{
modelValue: DateOption | DateOption[] | null,
/** https://flatpickr.js.org/options/ */
config: Options,
events: HookKey[],
disabled: boolean,
}>(), {
modelValue: null,
config: () => ({
defaultDate: undefined,
wrap: false,
}),
events: () => includedEvents,
disabled: false,
})
const emit = defineEmits([
@@ -183,7 +183,7 @@
</template>
<script setup lang="ts">
import {ref, reactive, shallowReactive, watch, computed, type PropType} from 'vue'
import {ref, reactive, shallowReactive, watch, computed} from 'vue'
import {useI18n} from 'vue-i18n'
import {useRoute} from 'vue-router'
@@ -206,27 +206,17 @@ import {useTaskStore} from '@/stores/tasks'
import {useProjectStore} from '@/stores/projects'
import {playPopSound} from '@/helpers/playPop'
const props = defineProps({
taskId: {
type: Number,
required: true,
},
initialRelatedTasks: {
type: Object as PropType<ITask['relatedTasks']>,
default: () => ({}),
},
showNoRelationsNotice: {
type: Boolean,
default: false,
},
projectId: {
type: Number,
default: 0,
},
editEnabled: {
type: Boolean,
default: true,
},
const props = withDefaults(defineProps<{
taskId: number,
initialRelatedTasks?: ITask['relatedTasks'],
showNoRelationsNotice?: boolean,
projectId: number,
editEnabled: boolean,
}>(), {
initialRelatedTasks: () => ({}),
showNoRelationsNotice: false,
projectId: 0,
editEnabled: true, // this seems like a mistake
})
const taskStore = useTaskStore()
+51 -102
View File
@@ -10,65 +10,10 @@ 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 Register from '@/views/user/Register.vue'
import LinkSharingAuth from '@/views/sharing/LinkSharingAuth.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')
// 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')
// 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')
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
@@ -90,7 +35,7 @@ const router = createRouter({
{
path: '/',
name: 'home',
component: HomeComponent,
component: () => import('@/views/Home.vue'),
},
{
path: '/:pathMatch(.*)*',
@@ -106,7 +51,7 @@ const router = createRouter({
{
path: '/login',
name: 'user.login',
component: LoginComponent,
component: () => import('@/views/user/Login.vue'),
meta: {
title: 'user.auth.login',
},
@@ -114,7 +59,7 @@ const router = createRouter({
{
path: '/get-password-reset',
name: 'user.password-reset.request',
component: GetPasswordResetComponent,
component: () => import('@/views/user/RequestPasswordReset.vue'),
meta: {
title: 'user.auth.resetPassword',
},
@@ -122,7 +67,7 @@ const router = createRouter({
{
path: '/password-reset',
name: 'user.password-reset.reset',
component: PasswordResetComponent,
component: () => import('@/views/user/PasswordReset.vue'),
meta: {
title: 'user.auth.resetPassword',
},
@@ -130,7 +75,9 @@ const router = createRouter({
{
path: '/register',
name: 'user.register',
component: RegisterComponent,
// FIXME: use dynamic imports
// component: () => import('@/views/user/Register.vue'),
component: Register,
meta: {
title: 'user.auth.createAccount',
},
@@ -138,63 +85,63 @@ const router = createRouter({
{
path: '/user/settings',
name: 'user.settings',
component: UserSettingsComponent,
component: () => import('@/views/user/Settings.vue'),
redirect: {name: 'user.settings.general'},
children: [
{
path: '/user/settings/avatar',
name: 'user.settings.avatar',
component: UserSettingsAvatarComponent,
component: () => import('@/views/user/settings/Avatar.vue'),
},
{
path: '/user/settings/caldav',
name: 'user.settings.caldav',
component: UserSettingsCaldavComponent,
component: () => import('@/views/user/settings/Caldav.vue'),
},
{
path: '/user/settings/data-export',
name: 'user.settings.data-export',
component: UserSettingsDataExportComponent,
component: () => import('@/views/user/settings/DataExport.vue'),
},
{
path: '/user/settings/deletion',
name: 'user.settings.deletion',
component: UserSettingsDeletionComponent,
component: () => import('@/views/user/settings/Deletion.vue'),
},
{
path: '/user/settings/email-update',
name: 'user.settings.email-update',
component: UserSettingsEmailUpdateComponent,
component: () => import('@/views/user/settings/EmailUpdate.vue'),
},
{
path: '/user/settings/general',
name: 'user.settings.general',
component: UserSettingsGeneralComponent,
component: () => import('@/views/user/settings/General.vue'),
},
{
path: '/user/settings/password-update',
name: 'user.settings.password-update',
component: UserSettingsPasswordUpdateComponent,
component: () => import('@/views/user/settings/PasswordUpdate.vue'),
},
{
path: '/user/settings/totp',
name: 'user.settings.totp',
component: UserSettingsTOTPComponent,
component: () => import('@/views/user/settings/TOTP.vue'),
},
{
path: '/user/settings/api-tokens',
name: 'user.settings.apiTokens',
component: UserSettingsApiTokensComponent,
component: () => import('@/views/user/settings/ApiTokens.vue'),
},
{
path: '/user/settings/migrate',
name: 'migrate.start',
component: MigrationComponent,
component: () => import('@/views/migrate/Migration.vue'),
},
{
path: '/migrate/:service',
name: 'migrate.service',
component: MigrationHandlerComponent,
component: () => import('@/views/migrate/MigrationHandler.vue'),
props: route => ({
service: route.params.service as string,
code: route.query.code as string,
@@ -205,23 +152,25 @@ const router = createRouter({
{
path: '/user/export/download',
name: 'user.export.download',
component: DataExportDownload,
component: () => import('@/views/user/DataExportDownload.vue'),
},
{
path: '/share/:share/auth',
name: 'link-share.auth',
component: LinkShareAuthComponent,
// FIXME: use dynamic imports
// component: () => import('@/views/sharing/LinkSharingAuth.vue'),
component: LinkSharingAuth,
},
{
path: '/tasks/:id',
name: 'task.detail',
component: TaskDetailView,
component: () => import('@/views/tasks/TaskDetailView.vue'),
props: route => ({ taskId: Number(route.params.id as string) }),
},
{
path: '/tasks/by/upcoming',
name: 'tasks.range',
component: UpcomingTasksComponent,
component: () => import('@/views/tasks/ShowTasks.vue'),
props: route => ({
dateFrom: parseDateOrString(route.query.from as string, new Date()),
dateTo: parseDateOrString(route.query.to as string, getNextWeekDate()),
@@ -245,12 +194,12 @@ const router = createRouter({
{
path: '/projects',
name: 'projects.index',
component: ListProjects,
component: () => import('@/views/project/ListProjects.vue'),
},
{
path: '/projects/new',
name: 'project.create',
component: NewProjectComponent,
component: () => import('@/views/project/NewProject.vue'),
meta: {
showAsModal: true,
},
@@ -258,7 +207,7 @@ const router = createRouter({
{
path: '/projects/:parentProjectId/new',
name: 'project.createFromParent',
component: NewProjectComponent,
component: () => import('@/views/project/NewProject.vue'),
props: route => ({ parentProjectId: Number(route.params.parentProjectId as string) }),
meta: {
showAsModal: true,
@@ -267,7 +216,7 @@ const router = createRouter({
{
path: '/projects/:projectId/settings/edit',
name: 'project.settings.edit',
component: ProjectSettingEdit,
component: () => import('@/views/project/settings/ProjectSettingsEdit.vue'),
props: route => ({ projectId: Number(route.params.projectId as string) }),
meta: {
showAsModal: true,
@@ -276,7 +225,7 @@ const router = createRouter({
{
path: '/projects/:projectId/settings/background',
name: 'project.settings.background',
component: ProjectSettingBackground,
component: () => import('@/views/project/settings/ProjectSettingsBackground.vue'),
meta: {
showAsModal: true,
},
@@ -284,7 +233,7 @@ const router = createRouter({
{
path: '/projects/:projectId/settings/duplicate',
name: 'project.settings.duplicate',
component: ProjectSettingDuplicate,
component: () => import('@/views/project/settings/ProjectSettingsDuplicate.vue'),
meta: {
showAsModal: true,
},
@@ -292,7 +241,7 @@ const router = createRouter({
{
path: '/projects/:projectId/settings/share',
name: 'project.settings.share',
component: ProjectSettingShare,
component: () => import('@/views/project/settings/ProjectSettingsShare.vue'),
meta: {
showAsModal: true,
},
@@ -300,7 +249,7 @@ const router = createRouter({
{
path: '/projects/:projectId/settings/webhooks',
name: 'project.settings.webhooks',
component: ProjectSettingWebhooks,
component: () => import('@/views/project/settings/ProjectSettingsWebhooks.vue'),
meta: {
showAsModal: true,
},
@@ -308,7 +257,7 @@ const router = createRouter({
{
path: '/projects/:projectId/settings/delete',
name: 'project.settings.delete',
component: ProjectSettingDelete,
component: () => import('@/views/project/settings/ProjectSettingsDelete.vue'),
meta: {
showAsModal: true,
},
@@ -316,7 +265,7 @@ const router = createRouter({
{
path: '/projects/:projectId/settings/archive',
name: 'project.settings.archive',
component: ProjectSettingArchive,
component: () => import('@/views/project/settings/ProjectSettingsArchive.vue'),
meta: {
showAsModal: true,
},
@@ -324,7 +273,7 @@ const router = createRouter({
{
path: '/projects/:projectId/settings/views',
name: 'project.settings.views',
component: ProjectSettingViews,
component: () => import('@/views/project/settings/ProjectSettingsViews.vue'),
meta: {
showAsModal: true,
},
@@ -333,7 +282,7 @@ const router = createRouter({
{
path: '/projects/:projectId/settings/edit',
name: 'filter.settings.edit',
component: FilterEdit,
component: () => import('@/views/filters/FilterEdit.vue'),
meta: {
showAsModal: true,
},
@@ -342,7 +291,7 @@ const router = createRouter({
{
path: '/projects/:projectId/settings/delete',
name: 'filter.settings.delete',
component: FilterDelete,
component: () => import('@/views/filters/FilterDelete.vue'),
meta: {
showAsModal: true,
},
@@ -351,7 +300,7 @@ const router = createRouter({
{
path: '/projects/:projectId/info',
name: 'project.info',
component: ProjectInfo,
component: () => import('@/views/project/ProjectInfo.vue') ,
meta: {
showAsModal: true,
},
@@ -379,7 +328,7 @@ const router = createRouter({
{
path: '/projects/:projectId/:viewId',
name: 'project.view',
component: ProjectView,
component: () => import('@/views/project/ProjectView.vue'),
props: route => ({
projectId: parseInt(route.params.projectId as string),
viewId: route.params.viewId ? parseInt(route.params.viewId as string): undefined,
@@ -388,12 +337,12 @@ const router = createRouter({
{
path: '/teams',
name: 'teams.index',
component: ListTeamsComponent,
component: () => import('@/views/teams/ListTeams.vue'),
},
{
path: '/teams/new',
name: 'teams.create',
component: NewTeamComponent,
component: () => import('@/views/teams/NewTeam.vue'),
meta: {
showAsModal: true,
},
@@ -401,17 +350,17 @@ const router = createRouter({
{
path: '/teams/:id/edit',
name: 'teams.edit',
component: EditTeamComponent,
component: () => import('@/views/teams/EditTeam.vue'),
},
{
path: '/labels',
name: 'labels.index',
component: ListLabelsComponent,
component: () => import('@/views/labels/ListLabels.vue'),
},
{
path: '/labels/new',
name: 'labels.create',
component: NewLabelComponent,
component: () => import('@/views/labels/NewLabel.vue'),
meta: {
showAsModal: true,
},
@@ -419,7 +368,7 @@ const router = createRouter({
{
path: '/filters/new',
name: 'filters.create',
component: FilterNew,
component: () => import('@/views/filters/FilterNew.vue'),
meta: {
showAsModal: true,
},
@@ -427,12 +376,12 @@ const router = createRouter({
{
path: '/auth/openid/:provider',
name: 'openid.auth',
component: OpenIdAuth,
component: () => import('@/views/user/OpenIdAuth.vue'),
},
{
path: '/about',
name: 'about',
component: About,
component: () => import('@/views/About.vue'),
},
],
})
+2 -5
View File
@@ -7,11 +7,8 @@ import type Modal from '@/components/misc/Modal.vue'
import type Card from '@/components/misc/Card.vue'
// Here we define globally imported components
// See:
// https://github.com/johnsoncodehk/volar/blob/2ca8fd3434423c7bea1c8e08132df3b9ce84eea7/extensions/vscode-vue-language-features/README.md#usage
// Under the hidden collapsible "Define Global Components"
declare module '@vue/runtime-core' {
// See: https://github.com/vuejs/language-tools/wiki/Global-Component-Types
declare module 'vue' {
export interface GlobalComponents {
Icon: FontAwesomeIconFixedTypes
Notifications: FunctionalComponent<Notifications>
+2 -2
View File
@@ -18,7 +18,7 @@ module code.vikunja.io/api
require (
dario.cat/mergo v1.0.1
github.com/ThreeDotsLabs/watermill v1.4.3
github.com/ThreeDotsLabs/watermill v1.4.4
github.com/adlio/trello v1.12.0
github.com/arran4/golang-ical v0.3.1
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
@@ -216,4 +216,4 @@ replace github.com/samedi/caldav-go => github.com/kolaente/caldav-go v3.0.1-0.20
go 1.22.0
toolchain go1.23.4
toolchain go1.23.5
+2
View File
@@ -664,6 +664,8 @@ github.com/ThreeDotsLabs/watermill v1.4.2 h1:lX/J79HyUipxZ2VetC7vMPqlw29xreHMxzh
github.com/ThreeDotsLabs/watermill v1.4.2/go.mod h1:lBnrLbxOjeMRgcJbv+UiZr8Ylz8RkJ4m6i/VN/Nk+to=
github.com/ThreeDotsLabs/watermill v1.4.3 h1:cRT1v7jlAgoPyEknvz0IFp3EKdSBRD/0Qbtz6KhexG8=
github.com/ThreeDotsLabs/watermill v1.4.3/go.mod h1:lBnrLbxOjeMRgcJbv+UiZr8Ylz8RkJ4m6i/VN/Nk+to=
github.com/ThreeDotsLabs/watermill v1.4.4 h1:aLClMl6EYIOQy4BML9yb2VpTekbynDatvQbXGp7idCU=
github.com/ThreeDotsLabs/watermill v1.4.4/go.mod h1:lBnrLbxOjeMRgcJbv+UiZr8Ylz8RkJ4m6i/VN/Nk+to=
github.com/adlio/trello v1.12.0 h1:JqOE2GFHQ9YtEviRRRSnicSxPbt4WFOxhqXzjMOw8lw=
github.com/adlio/trello v1.12.0/go.mod h1:I4Lti4jf2KxjTNgTqs5W3lLuE78QZZdYbbPnQQGwjOo=
github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
+18 -7
View File
@@ -100,6 +100,12 @@ func getRouteDetail(route echo.Route) (method string, detail *RouteDetail) {
}
}
func ensureAPITokenRoutesGroup(group string) {
if _, has := apiTokenRoutes[group]; !has {
apiTokenRoutes[group] = make(APITokenRoute)
}
}
// CollectRoutesForAPITokenUsage gets called for every added APITokenRoute and builds a list of all routes we can use for the api tokens.
func CollectRoutesForAPITokenUsage(route echo.Route, middlewares []echo.MiddlewareFunc) {
@@ -139,10 +145,15 @@ func CollectRoutesForAPITokenUsage(route echo.Route, middlewares []echo.Middlewa
// and if that's the case, add it to its parent instead.
// Otherwise, we add it to the "other" key.
if len(routeParts) == 1 {
if _, has := apiTokenRoutes["other"]; !has {
apiTokenRoutes["other"] = make(APITokenRoute)
if routeGroupName == "notifications" && route.Method == http.MethodPost {
ensureAPITokenRoutesGroup("notifications")
apiTokenRoutes["notifications"]["mark_all_as_read"] = routeDetail
return
}
ensureAPITokenRoutesGroup("other")
_, exists := apiTokenRoutes["other"][routeGroupName]
if exists {
routeGroupName += "_" + strings.ToLower(route.Method)
@@ -168,10 +179,7 @@ func CollectRoutesForAPITokenUsage(route echo.Route, middlewares []echo.Middlewa
if strings.HasSuffix(routeGroupName, "_bulk") {
parent := strings.TrimSuffix(routeGroupName, "_bulk")
_, has := apiTokenRoutes[parent]
if !has {
apiTokenRoutes[parent] = make(APITokenRoute)
}
ensureAPITokenRoutesGroup(parent)
method, routeDetail := getRouteDetail(route)
apiTokenRoutes[parent][method+"_bulk"] = routeDetail
@@ -202,6 +210,7 @@ func CollectRoutesForAPITokenUsage(route echo.Route, middlewares []echo.Middlewa
}
}
}
}
// GetAvailableAPIRoutesForToken returns a list of all API routes which are available for token usage.
@@ -229,7 +238,9 @@ func CanDoAPIRoute(c echo.Context, token *APIToken) (can bool) {
routeGroupName = strings.TrimSuffix(routeGroupName, "_bulk")
if routeGroupName == "user" {
if routeGroupName == "user" ||
routeGroupName == "users" ||
routeGroupName == "routes" {
routeGroupName = "other"
}