Compare commits

..

289 Commits

Author SHA1 Message Date
renovate a4849ac3dd fix(deps): update dependency flexsearch to v0.7.31
continuous-integration/drone/pr Build is failing Details
2023-01-06 10:04:20 +00:00
Dominik Pschenitschni 72e80f637d feat(postcss): mock plugin types (#2930)
continuous-integration/drone/push Build is failing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2930
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2023-01-06 09:27:55 +00:00
konrad a4424e089c feat: add histoire (#2724)
continuous-integration/drone/push Build is failing Details
Reviewed-on: #2724
2023-01-06 09:27:09 +00:00
Frederick [Bot] 945128c3cd [skip ci] Updated translations via Crowdin 2023-01-06 00:34:21 +00:00
Dominik Pschenitschni 35cfb2f3ca
feat: add card story
continuous-integration/drone/pr Build is passing Details
2023-01-05 23:12:58 +01:00
Dominik Pschenitschni ccc85b9a82
feat: add XButton story 2023-01-05 23:12:58 +01:00
Dominik Pschenitschni 9523f60763
fix(BaseButton): prop type 2023-01-05 23:12:58 +01:00
Dominik Pschenitschni 7be8e892e2
feat: add histoire 2023-01-05 23:12:58 +01:00
renovate 2a6aff6ffa fix(deps): update dependency dompurify to v2.4.2
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2023-01-05 17:04:34 +00:00
Dominik Pschenitschni 6a03972f16 feat(netlify): abstract createSlug helper function (#2923)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2923
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2023-01-05 16:46:38 +00:00
Dominik Pschenitschni 4023ebcdd1 fix(drone): use correct property value (#2920)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: #2920
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2023-01-05 13:50:32 +00:00
Dominik Pschenitschni 6049427322 chore(config): remove unused URL_PREFIX const (#2926)
continuous-integration/drone/push Build is failing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2926
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2023-01-05 13:35:28 +00:00
Dominik Pschenitschni f658d3bbba fix(cypress): use env for API_URL (#2925)
continuous-integration/drone/push Build is failing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2925
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2023-01-05 13:34:40 +00:00
Dominik Pschenitschni a029887102 fix(useOnline): only log if actually faking state (#2924)
continuous-integration/drone/push Build is failing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2924
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2023-01-05 13:33:37 +00:00
Dominik Pschenitschni 0f7b7f72d0 fix(faker): remove mock types (#2921)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2921
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2023-01-05 13:27:36 +00:00
Dominik Pschenitschni a29131e7d4 feat: remove formatISO from list-view-gantt.spec (#2922)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2922
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2023-01-05 13:27:04 +00:00
Dominik Pschenitschni b71d41c5ec chore(package): use pnpm commands (#2919)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2919
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2023-01-05 10:29:16 +00:00
renovate 81594e234a chore(deps): update dependency vue-tsc to v1.0.22
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2023-01-05 02:05:01 +00:00
renovate 0846d1dc5e chore(deps): update dependency vue-tsc to v1.0.21
continuous-integration/drone/push Build is passing Details
2023-01-04 23:26:07 +00:00
renovate 5dfaa48ea5 fix(deps): update dependency axios to v1
continuous-integration/drone/push Build is passing Details
2023-01-04 23:13:25 +00:00
renovate 63671efbe2 chore(deps): update dependency esbuild to v0.16.14
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2023-01-04 21:04:20 +00:00
Dominik Pschenitschni 4be53b098c feat: add-task usability improvements (#2767)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2767
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2023-01-04 15:54:09 +00:00
renovate 5a89bc0183 fix(deps): update sentry-javascript monorepo to v7.29.0 (#2915)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2915
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2023-01-04 14:14:26 +00:00
renovate 97b1149a90 chore(deps): update dependency vite to v4.0.4 (#2908)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2908
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2023-01-04 13:14:24 +00:00
renovate 2ca33671aa chore(deps): update dependency @vue/test-utils to v2.2.7 (#2914)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2914
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2023-01-04 13:13:44 +00:00
renovate d82f377f94 chore(deps): update pnpm to v7.22.0 (#2910)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2910
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2023-01-04 12:20:17 +00:00
kolaente a2cd08a7af
fix(ci): sign drone config
continuous-integration/drone/push Build is passing Details
2023-01-04 11:38:06 +01:00
renovate 830d6d0a38 fix(deps): update dependency @vueuse/core to v9.10.0 (#2911)
continuous-integration/drone/push Build is pending Details
Reviewed-on: #2911
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2023-01-04 09:48:37 +00:00
renovate 6cc23ff7aa chore(deps): update dependency cypress to v12.3.0
continuous-integration/drone/push Build was killed Details
2023-01-04 03:32:05 +00:00
konrad bb4ed3d223 chore(tests): fix macos cypress and align with create vite (#2898)
continuous-integration/drone/push Build was killed Details
Reviewed-on: #2898
Reviewed-by: konrad <k@knt.li>
2023-01-04 03:19:36 +00:00
renovate f56302a99f chore(deps): update dependency vue-tsc to v1.0.20
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2023-01-04 00:05:43 +00:00
Dominik Pschenitschni d850d5b98f
fix(cypress): use ts for updateUserSettings
continuous-integration/drone/pr Build is passing Details
2023-01-03 16:30:46 +01:00
Dominik Pschenitschni 4908469d49
feat(cypress): use cy.session
Also align repo closer to `create-vue` template and improve cypress integration
2023-01-03 16:30:46 +01:00
Dominik Pschenitschni 1f25386f54 feat: remove date-fns formatISO (#2899)
continuous-integration/drone/push Build is failing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2899
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2023-01-03 14:20:06 +00:00
renovate c97ed67f50 chore(deps): update typescript-eslint monorepo to v5.48.0 (#2906)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2906
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2023-01-03 14:05:36 +00:00
renovate be53474eeb chore(deps): update dependency esbuild to v0.16.13 (#2907)
continuous-integration/drone/push Build is failing Details
Reviewed-on: #2907
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2023-01-03 14:04:57 +00:00
renovate c6cb2343ae chore(deps): update dependency vite-plugin-pwa to v0.14.1 (#2909)
continuous-integration/drone/push Build is failing Details
Reviewed-on: #2909
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2023-01-03 14:03:50 +00:00
renovate 76bb081db5 chore(deps): update dependency vitest to v0.26.3
continuous-integration/drone/push Build is failing Details
2023-01-02 16:51:44 +00:00
renovate 8e9468228e chore(deps): update dependency rollup to v3.9.1
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2023-01-02 14:04:05 +00:00
renovate 61ba2facbc chore(deps): update dependency @types/codemirror to v5.60.6
continuous-integration/drone/push Build is passing Details
2022-12-31 11:02:14 +00:00
renovate 1bec289021 chore(deps): update dependency vue-tsc to v1.0.19
continuous-integration/drone/push Build is passing Details
2022-12-31 11:01:28 +00:00
renovate 82b108a79d chore(deps): update dependency eslint to v8.31.0
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-12-31 06:04:13 +00:00
renovate 54c49391d1 chore(deps): update pnpm to v7.21.0 (#2895)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2895
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-30 16:50:17 +00:00
Dominik Pschenitschni 6ddfba4f1f
feat(cypress): remove getSettled 2022-12-30 16:39:51 +01:00
renovate b2bf39fffa fix(deps): update dependency marked to v4.2.5 (#2880)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2880
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-30 14:13:11 +00:00
Dominik Pschenitschni 09d13520b0 feat: enable ts for rollup-plugin-visualizer (#2897)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2897
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-12-30 13:37:31 +00:00
renovate 0d91d2845f chore(deps): update dependency rollup-plugin-visualizer to v5.9.0 (#2896)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2896
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-30 13:13:05 +00:00
renovate 1b69b1b527 chore(deps): update dependency rollup to v3.9.0 (#2894)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2894
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-28 08:30:18 +00:00
renovate e14b34fca2 chore(deps): update dependency esbuild to v0.16.12 (#2893)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2893
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-28 08:29:39 +00:00
renovate ce5e4aad6f chore(deps): update dependency esbuild to v0.16.11
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-12-27 02:03:43 +00:00
renovate 12e85909b2 chore(deps): update typescript-eslint monorepo to v5.47.1 (#2890)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2890
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-26 20:08:47 +00:00
renovate 5c245d8921 chore(deps): update dependency @types/node to v18.11.18 (#2889)
continuous-integration/drone/push Build is failing Details
Reviewed-on: #2889
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-26 20:08:10 +00:00
renovate ee89aa3b46 chore(deps): update dependency happy-dom to v8.1.1 (#2885)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2885
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-26 11:15:55 +00:00
renovate efe22c339a chore(deps): update dependency vue-tsc to v1.0.18 (#2888)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2888
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-26 10:59:09 +00:00
renovate 0aa4d1cb65 chore(deps): update pnpm to v7.20.0 (#2887)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2887
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-26 08:45:09 +00:00
renovate 5b6ad786ee chore(deps): update dependency netlify-cli to v12.5.0 (#2886)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2886
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-26 08:44:18 +00:00
renovate 53b4352e04 chore(deps): update dependency caniuse-lite to v1.0.30001441 (#2884)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2884
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-26 08:43:38 +00:00
renovate ac5b849d06 chore(deps): update dependency vue-tsc to v1.0.17 (#2883)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2883
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-25 20:32:50 +00:00
renovate 3a8a45375c chore(deps): update dependency vite-svg-loader to v4 (#2882)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2882
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-24 10:36:36 +00:00
drone 93f2ccf2e6 [skip ci] Updated translations via Crowdin 2022-12-24 00:34:12 +00:00
renovate a910b263cb chore(deps): update dependency rollup to v3.8.1 (#2879)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2879
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-23 21:17:25 +00:00
renovate a6e4bbebec fix(deps): update dependency @vueuse/core to v9.9.0 (#2881)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2881
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-23 20:17:16 +00:00
kolaente 96dd0aab34
fix(i18n): incorrect translation string
continuous-integration/drone/push Build is failing Details
2022-12-23 17:19:05 +01:00
kolaente a6a0c3b121
fix(ci): sign drone config
continuous-integration/drone/push Build is failing Details
2022-12-23 11:22:20 +01:00
drone 367f55c04a [skip ci] Updated translations via Crowdin 2022-12-23 00:34:13 +00:00
kolaente c2fd41b80a
fix(ci): make sure the i18n sync cron job actually runs
continuous-integration/drone/push Build is pending Details
2022-12-22 13:06:16 +01:00
kolaente 373b04bd58
feat(i18n): add Norwegian translation 2022-12-22 13:05:42 +01:00
renovate 60890e4bb7 fix(deps): update sentry-javascript monorepo to v7.28.1 (#2878)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2878
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-22 10:24:04 +00:00
renovate aaa8a3859a chore(deps): update dependency rollup to v3.8.0 (#2877)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2877
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-22 08:52:22 +00:00
renovate 7f886bc6ac chore(deps): update pnpm to v7.19.0 (#2875)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2875
Reviewed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-21 15:20:56 +00:00
renovate cacb59d6e3 chore(deps): update dependency vite to v4.0.3 (#2876)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2876
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-21 15:19:56 +00:00
renovate 017dad9b4b chore(deps): update dependency vitest to v0.26.2 (#2874)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2874
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-21 11:23:36 +00:00
renovate 7123bbc440 chore(deps): update dependency cypress to v12.2.0 (#2873)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2873
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-21 09:39:42 +00:00
renovate 4eb63452cb fix(deps): update sentry-javascript monorepo to v7.28.0
continuous-integration/drone/push Build is passing Details
2022-12-20 17:13:54 +00:00
renovate 4ee201e7bd fix(deps): update dependency @vueuse/core to v9.8.2
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-12-20 15:03:43 +00:00
renovate 7eb971890c fix(deps): update dependency @vueuse/core to v9.8.1 (#2870)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2870
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-20 14:14:58 +00:00
renovate 872197414d chore(deps): update dependency vitest to v0.26.1
continuous-integration/drone/push Build is passing Details
2022-12-20 12:53:40 +00:00
renovate 59b99407cc fix(deps): update dependency @vueuse/core to v9.8.0
continuous-integration/drone/push Build is passing Details
2022-12-20 12:51:57 +00:00
renovate f5d30ccd44 fix(deps): update dependency codemirror to v5.65.11
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-12-20 11:03:43 +00:00
renovate 46f89bd5ed chore(deps): update dependency vue-tsc to v1.0.16 (#2867)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2867
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-20 09:14:33 +00:00
renovate 65167c5989 chore(deps): update dependency sass to v1.57.1 (#2866)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2866
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-20 07:23:10 +00:00
renovate e8b46829dd chore(deps): update dependency esbuild to v0.16.10 (#2865)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2865
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-20 07:22:38 +00:00
renovate 865172951a chore(deps): update typescript-eslint monorepo to v5.47.0 (#2864)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2864
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-19 18:14:54 +00:00
renovate f152a84847 chore(deps): update dependency netlify-cli to v12.4.0 (#2862)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2862
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-19 07:57:24 +00:00
kolaente c09fbe9abe
fix(migration): actually pass migration oauth code from query param
continuous-integration/drone/push Build is failing Details
2022-12-18 20:38:38 +01:00
renovate a6bafe1a9a chore(deps): update dependency vite to v4.0.2 (#2861)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2861
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-18 12:17:39 +00:00
kolaente 3dfb8b858e
chore: 0.20.2 release preperations
continuous-integration/drone/push Build is failing Details
2022-12-18 12:23:51 +01:00
renovate ebccd6f411 chore(deps): update dependency @types/node to v18.11.17 (#2858)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2858
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-18 11:16:10 +00:00
renovate f465576baa chore(deps): update dependency esbuild to v0.16.9 (#2859)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2859
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-18 10:43:41 +00:00
renovate 25b082c45d chore(deps): update dependency vue-tsc to v1.0.14 (#2860)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2860
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-18 10:04:35 +00:00
renovate 3e42eeba2c chore(deps): update dependency sass to v1.57.0 (#2856)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2856
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-17 10:19:44 +00:00
renovate 263265157a chore(deps): update dependency esbuild to v0.16.8 (#2854)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2854
Reviewed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-17 09:05:23 +00:00
renovate fc95c8e2be chore(deps): update dependency rollup to v3.7.5 (#2857)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2857
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-17 09:04:25 +00:00
renovate f58013fc32 chore(deps): update dependency eslint to v8.30.0
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-12-17 00:06:14 +00:00
renovate 563ff7b20e chore(deps): update dependency @types/node to v18.11.16 (#2853)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2853
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-16 21:18:15 +00:00
renovate 44821b4f24 chore(deps): update dependency wait-on to v7 (#2852)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2852
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-16 20:53:31 +00:00
renovate 344b38bf93 fix(deps): update dependency @vueuse/core to v9.7.0 (#2851)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2851
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-16 16:20:03 +00:00
kolaente f6171935ca
fix(tasks): translation for multiple related tasks now works
continuous-integration/drone/push Build is passing Details
Resolves https://github.com/go-vikunja/frontend/issues/98
2022-12-16 14:42:58 +01:00
renovate 5f96407dc0 fix(deps): update sentry-javascript monorepo to v7.27.0 (#2850)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2850
Reviewed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-16 13:24:53 +00:00
Dominik Pschenitschni b6a89a0cde feat: use variable fonts with subsetting (#2817)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2817
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-12-15 21:37:02 +00:00
renovate a3978bb359 chore(deps): update dependency esbuild to v0.16.7
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-12-14 23:05:51 +00:00
renovate 43eb7c4abf chore(deps): update dependency esbuild to v0.16.6 (#2848)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2848
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-14 07:19:37 +00:00
renovate 6dd566ba46 chore(deps): update dependency @types/node to v18.11.15
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-12-13 22:05:16 +00:00
Dominik Pschenitschni 318e8c83a6 fix: vite.config imports (#2843)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2843
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-12-13 19:02:23 +00:00
Dominik Pschenitschni f6c6f52abe feat: use vite preview for serve:dist:dev (#2842)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2842
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-12-13 19:01:56 +00:00
Dominik Pschenitschni c449925826 fix(bug-report.yml): list (#2845)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2845
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-12-13 19:00:50 +00:00
renovate c6eb72bdeb chore(deps): update dependency esbuild to v0.16.5 (#2846)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2846
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-13 18:15:34 +00:00
renovate aecfe7e15f fix(deps): update sentry-javascript monorepo to v7.26.0
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-12-13 17:03:45 +00:00
renovate f3a7093ed8 chore(deps): update dependency vitest to v0.25.8
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-12-13 11:03:48 +00:00
renovate b37ae37116 chore(deps): update dependency rollup to v3.7.4 (#2840)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2840
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-13 10:30:01 +00:00
renovate a3a482769d chore(deps): update dependency cypress to v12.1.0 (#2838)
continuous-integration/drone/push Build is failing Details
Reviewed-on: #2838
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-13 08:36:05 +00:00
renovate 7cc6cf233f chore(deps): update dependency @types/node to v18.11.14 (#2839)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2839
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-13 08:35:15 +00:00
renovate ce529579c3 chore(deps): update dependency @4tw/cypress-drag-drop to v2.2.3 (#2836)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2836
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-12 22:08:18 +00:00
renovate 7680c82ce1 chore(deps): update typescript-eslint monorepo to v5.46.1 (#2837)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2837
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-12 22:07:10 +00:00
renovate 1bb6bedd6e chore(deps): update pnpm to v7.18.2 (#2834)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2834
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-12 22:06:35 +00:00
renovate 4b29e3d9dd chore(deps): update dependency vite to v4 (#2816)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2816
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-12 20:15:40 +00:00
renovate 00b869c727 fix(deps): update sentry-javascript monorepo to v7.25.0
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-12-12 13:03:44 +00:00
renovate fe2db90c4a chore(deps): update dependency vue-tsc to v1.0.13 (#2832)
continuous-integration/drone/push Build is failing Details
Reviewed-on: #2832
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-12 10:32:57 +00:00
renovate 5b566178b3 chore(deps): update dependency rollup to v3.7.3 (#2825)
continuous-integration/drone/push Build is failing Details
Reviewed-on: #2825
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-12 10:32:10 +00:00
renovate c887e15421 chore(deps): update dependency vite-plugin-pwa to v0.14.0 (#2833)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2833
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-12 10:31:07 +00:00
renovate 99813772ef chore(deps): update dependency netlify-cli to v12.2.10 (#2829)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2829
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-12 10:30:32 +00:00
renovate 4d280a26d3 fix(deps): update dependency @intlify/unplugin-vue-i18n to v0.8.1 (#2826)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2826
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-12 09:35:23 +00:00
renovate 6d6922c90b chore(deps): update dependency caniuse-lite to v1.0.30001439 (#2828)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2828
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-12 09:34:53 +00:00
renovate ab65276e6b chore(deps): update dependency postcss to v8.4.20 (#2827)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2827
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-12 09:34:12 +00:00
renovate 3b6dfcec78 chore(deps): update dependency happy-dom to v8 (#2831)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2831
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-12 09:33:05 +00:00
drone a72cd31202 [skip ci] Updated translations via Crowdin 2022-12-11 00:30:17 +00:00
kolaente 2141171529
fix(task): move task color bubble next to task index and done badge on mobile
continuous-integration/drone/push Build is passing Details
2022-12-10 22:28:19 +01:00
kolaente 9b050846a4
Revert "feat: use img for logo so that it's not part of the main bundle (#2684)"
continuous-integration/drone/push Build is passing Details
This reverts commit 02de481297.
2022-12-10 22:21:50 +01:00
renovate f6b8d2c4ca chore(deps): update dependency @types/node to v18.11.13 (#2823)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2823
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-10 21:18:26 +00:00
renovate 86119ff414 chore(deps): update dependency vitest to v0.25.7 (#2824)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2824
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-10 20:25:24 +00:00
renovate 7c5622af11 chore(deps): update dependency esbuild to v0.16.4 (#2821)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2821
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-10 09:04:33 +00:00
renovate 6ac3ce65b4 chore(deps): update dependency rollup to v3.7.2 (#2822)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2822
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-10 09:03:41 +00:00
renovate 07f9784e0d chore(deps): update dependency rollup to v3.7.1 (#2820)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2820
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 20:12:45 +00:00
renovate fb751236d1 chore(deps): update dependency @cypress/vite-dev-server to v5.0.2 (#2819)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2819
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 18:51:31 +00:00
renovate 396943b3a6 chore(deps): update dependency @vitejs/plugin-legacy to v3.0.1 (#2818)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2818
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 14:23:13 +00:00
renovate b8a19ac88a fix(deps): update dependency pinia to v2.0.28 (#2815)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2815
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 11:33:27 +00:00
renovate 02fac73e07 chore(deps): update dependency @vitejs/plugin-legacy to v3 (#2813)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2813
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 11:32:49 +00:00
renovate 21e52c3b1f chore(deps): update dependency @vitejs/plugin-vue to v4 (#2814)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2814
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 10:17:24 +00:00
renovate 213ef84586 chore(deps): update dependency cypress to v12.0.2 (#2807)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2807
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 10:14:38 +00:00
renovate 25852ffac3 chore(deps): update dependency @types/node to v18.11.12 (#2808)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2808
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 10:14:10 +00:00
renovate 1255b50ed7 chore(deps): update dependency vue-tsc to v1.0.12 (#2811)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2811
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 10:13:23 +00:00
renovate afe8198158 chore(deps): update dependency @types/marked to v4.0.8 (#2812)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2812
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 09:34:43 +00:00
renovate abe43c4ef8 chore(deps): update dependency sass to v1.56.2 (#2810)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2810
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 09:33:58 +00:00
renovate 8d5ddd695a chore(deps): update dependency esbuild to v0.16.3 (#2809)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2809
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 09:33:28 +00:00
renovate a0087bc34a chore(deps): update dependency @cypress/vite-dev-server to v5.0.1 (#2806)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2806
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-09 09:32:51 +00:00
renovate 18a73c39e5 chore(deps): update dependency vitest to v0.25.6 (#2804)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2804
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-08 11:14:02 +00:00
renovate e0351495ff chore(deps): update typescript-eslint monorepo to v5.46.0 (#2803)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2803
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-08 10:26:51 +00:00
renovate b97e045118 chore(deps): update dependency esbuild to v0.16.2 (#2802)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2802
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-08 09:32:28 +00:00
renovate a052305adf chore(deps): update dependency rollup to v3.7.0 (#2801)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2801
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-08 09:30:16 +00:00
renovate 237de35b25 chore(deps): update dependency typescript to v4.9.4 (#2800)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2800
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-08 09:29:39 +00:00
renovate 85beebf0d8 fix(deps): update sentry-javascript monorepo to v7.24.2 (#2799)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2799
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-07 20:14:23 +00:00
renovate e81b216f85 fix(deps): update sentry-javascript monorepo to v7.24.1 (#2798)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2798
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-07 13:32:51 +00:00
renovate fc9e75e9b3 fix(deps): update sentry-javascript monorepo to v7.24.0 (#2797)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2797
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-07 11:15:30 +00:00
renovate b576621569 chore(deps): update dependency cypress to v12.0.1 (#2794)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2794
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-07 10:12:16 +00:00
renovate 08a031ca07 chore(deps): update dependency esbuild to v0.16.1 (#2795)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2795
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-07 09:13:46 +00:00
renovate d306bb967c fix(deps): update dependency marked to v4.2.4 (#2796)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2796
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-07 09:12:25 +00:00
renovate 3f6a64d7f9 chore(deps): update dependency vitest to v0.25.5 (#2793)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2793
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-06 21:48:16 +00:00
renovate 2d392c9973 chore(deps): update dependency cypress to v12 (#2792)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2792
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-06 18:47:02 +00:00
renovate 9897bc9b43 fix(deps): update dependency dayjs to v1.11.7 (#2791)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2791
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-06 16:25:41 +00:00
renovate 92546f4b34 chore(deps): update pnpm to v7.18.1 (#2790)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2790
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-06 14:35:50 +00:00
renovate 8d326aca03 chore(deps): update dependency @types/node to v18.11.11 (#2789)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2789
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-05 21:13:45 +00:00
renovate 4bf9284b38 chore(deps): update dependency vitest to v0.25.4 (#2788)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2788
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-05 19:14:26 +00:00
renovate 0de9376b2b chore(deps): update typescript-eslint monorepo to v5.45.1 (#2787)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2787
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-05 18:38:15 +00:00
renovate 0602f6693b chore(deps): update dependency rollup to v3.6.0 (#2786)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2786
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-05 12:14:06 +00:00
renovate 7d5cde53e3 chore(deps): update dependency vite to v3.2.5 (#2785)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2785
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-05 09:27:20 +00:00
renovate 8361640559 chore(deps): update dependency happy-dom to v7.7.2 (#2781)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2781
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-05 08:13:36 +00:00
renovate 517a6cea1e chore(deps): update dependency netlify-cli to v12.2.8 (#2782)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2782
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-05 07:40:17 +00:00
renovate ed4dd93bba chore(deps): update dependency esbuild to v0.15.18 (#2783)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2783
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-05 07:39:38 +00:00
renovate d50de97490 chore(deps): update dependency @vue/test-utils to v2.2.6 (#2784)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2784
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-05 07:38:49 +00:00
renovate aa719d3a68 chore(deps): update dependency caniuse-lite to v1.0.30001436 (#2780)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2780
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-05 07:38:08 +00:00
kolaente 463d22b07c
fix(quick add magic): don't create a new label multiple times if it is used in multiple tasks
continuous-integration/drone/push Build is passing Details
Resolves https://github.com/go-vikunja/frontend/issues/94
2022-12-04 20:19:43 +01:00
renovate 33494cab6b chore(deps): update dependency esbuild to v0.15.17 (#2779)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2779
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-04 12:51:12 +00:00
renovate 8fa922a0ca chore(deps): update pnpm to v7.18.0 (#2778)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2778
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-03 23:19:41 +00:00
renovate e5815e21cb chore(deps): update dependency @cypress/vite-dev-server to v5 (#2776)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2776
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-03 10:12:17 +00:00
renovate 529b47e488 chore(deps): update dependency vue-tsc to v1.0.11 (#2777)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2777
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-03 09:33:19 +00:00
renovate 63c3e4ea58 chore(deps): update dependency @cypress/vue to v5.0.3 (#2775)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2775
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-03 09:32:32 +00:00
renovate d52e917357 chore(deps): update dependency eslint to v8.29.0 (#2774)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2774
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-03 09:31:53 +00:00
kolaente b2da4fd126
fix(task): pass a list specified via quick add magic down to all subtasks created via indention
continuous-integration/drone/push Build is passing Details
Resolves #2771
2022-12-02 18:39:52 +01:00
kolaente 83fb8c3ded
fix(tasks): missing space when showing parent tasks and list title
continuous-integration/drone/push Build is passing Details
See #2771
2022-12-02 18:05:48 +01:00
Dominik Pschenitschni b44d11cfc0 feat: add @intlify/unplugin-vue-i18n (#2772)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2772
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-12-02 15:16:15 +00:00
renovate d4133b9e78 chore(deps): update dependency @vue/test-utils to v2.2.5 (#2773)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2773
Reviewed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-02 14:27:23 +00:00
renovate c478926038 fix(deps): update sentry-javascript monorepo to v7.23.0
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is failing Details
2022-12-01 17:03:38 +00:00
renovate 00e40a0f53 chore(deps): update dependency rollup to v3.5.1 (#2769)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2769
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-12-01 07:23:21 +00:00
renovate 0567ba2a47 chore(deps): update dependency @types/node to v18.11.10 (#2768)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2768
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-30 21:39:34 +00:00
Dominik Pschenitschni 3b95824f58 feat: use Intl.DateTimeFormat for gantt weekdays (#2766)
continuous-integration/drone/push Build is passing Details
Fixes #2728

Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2766
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-30 15:58:04 +00:00
renovate 963f3bfb07 fix(deps): update sentry-javascript monorepo to v7.22.0 (#2765)
continuous-integration/drone/push Build is failing Details
Reviewed-on: #2765
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-29 14:16:53 +00:00
renovate d1c05eb3fb chore(deps): update dependency vue-tsc to v1.0.10 (#2764)
continuous-integration/drone/push Build is failing Details
Reviewed-on: #2764
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-29 14:15:48 +00:00
renovate 2326e50d5d fix(deps): update dependency ufo to v1.0.1 (#2763)
continuous-integration/drone/push Build is failing Details
Reviewed-on: #2763
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-29 13:13:46 +00:00
drone b7fa1a3ca1 [skip ci] Updated translations via Crowdin 2022-11-29 00:29:59 +00:00
renovate a3e1e43ec7 chore(deps): update typescript-eslint monorepo to v5.45.0 (#2762)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2762
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-28 18:15:03 +00:00
renovate 39f163df4a fix(deps): update dependency @kyvg/vue3-notification to v2.7.0 (#2761)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2761
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-28 11:13:49 +00:00
renovate f0e8ff93ff chore(deps): update dependency netlify-cli to v12.2.7 (#2760)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2760
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-28 10:13:47 +00:00
Dominik Pschenitschni 3ee0bc345d feat: remove useRouteQuery (#2751)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2751
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-28 09:06:07 +00:00
renovate b4ffee8929 chore(deps): update dependency caniuse-lite to v1.0.30001434 (#2759)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2759
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-28 09:04:04 +00:00
renovate e3c3d3ee53 fix(deps): update dependency pinia to v2.0.27 (#2757)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2757
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-28 09:03:03 +00:00
renovate 67e7b94f5d chore(deps): update dependency esbuild to v0.15.16
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-27 17:03:30 +00:00
renovate 6bbddeae8c chore(deps): update pnpm to v7.17.1 (#2755)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2755
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-27 09:49:01 +00:00
renovate 94a0e1e25f chore(deps): update dependency rollup to v3.5.0 (#2756)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2756
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-27 09:48:26 +00:00
renovate 4df9bc33df fix(deps): update dependency @infectoone/vue-ganttastic to v2.1.3
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-26 18:03:30 +00:00
drone 5c64e8a2d7 [skip ci] Updated translations via Crowdin 2022-11-25 00:12:02 +00:00
renovate e10791f28c chore(deps): update dependency eslint-plugin-vue to v9.8.0 (#2753)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2753
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-24 07:44:19 +00:00
drone 44b58ff34b [skip ci] Updated translations via Crowdin 2022-11-24 00:11:48 +00:00
renovate da17f78d30 fix(deps): update dependency highlight.js to v11.7.0 (#2752)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2752
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-23 23:15:37 +00:00
renovate 61cdb7a91f chore(deps): update dependency @cypress/vue to v5.0.2
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-23 19:03:58 +00:00
renovate 1b8ed9417a fix(deps): update dependency pinia to v2.0.26
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-23 14:04:04 +00:00
renovate 4657da8c90 fix(deps): update sentry-javascript monorepo to v7.21.1 (#2747)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2747
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-23 12:41:33 +00:00
renovate 6cd2908040 chore(deps): update dependency @4tw/cypress-drag-drop to v2.2.2
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-23 09:03:55 +00:00
renovate 4dd99ae6fc fix(deps): update sentry-javascript monorepo to v7.21.0
continuous-integration/drone/push Build is passing Details
2022-11-22 20:22:49 +00:00
renovate 0d5fa1326d chore(deps): update dependency cypress to v11.2.0
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-22 20:03:57 +00:00
renovate dd692de7c4 chore(deps): update dependency vitest to v0.25.3 (#2743)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2743
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-22 13:26:18 +00:00
Dominik Pschenitschni 93d95b0821 feat: use fetch instead of axios for deploy preview (#2719)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2719
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-22 13:11:26 +00:00
Dominik Pschenitschni 422e731fe0 fix: add all json files in src (#2737)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2737
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-22 13:08:32 +00:00
Dominik Pschenitschni 7db79ff04e fix: only load buckets if listId set (#2741)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2741
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-22 13:00:36 +00:00
renovate 59cc241226 fix(deps): update vueuse to v9.6.0 (#2742)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2742
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-22 12:58:21 +00:00
renovate 2ac2e95cf2 chore(deps): update typescript-eslint monorepo to v5.44.0
continuous-integration/drone/push Build is passing Details
2022-11-22 09:32:54 +00:00
renovate f8ce3d6ed6 chore(deps): update dependency rollup to v3.4.0
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-22 06:04:25 +00:00
drone 93f33d9647 [skip ci] Updated translations via Crowdin 2022-11-22 00:12:21 +00:00
renovate 6d32b22da3 fix(deps): update dependency pinia to v2.0.25
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-21 22:04:33 +00:00
renovate b333898595 fix(deps): update sentry-javascript monorepo to v7.20.1
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-21 13:04:18 +00:00
renovate ccc633f3d9 fix(deps): update dependency codemirror to v5.65.10
continuous-integration/drone/push Build is passing Details
2022-11-21 10:39:30 +00:00
renovate d39b0675d3 fix(deps): update dependency marked to v4.2.3
continuous-integration/drone/push Build is passing Details
2022-11-21 10:38:45 +00:00
renovate 274092bfc4 chore(deps): update pnpm to v7.17.0
continuous-integration/drone/push Build is passing Details
2022-11-21 10:38:05 +00:00
renovate cb2c032e60 chore(deps): update dependency @vue/test-utils to v2.2.4
continuous-integration/drone/push Build is passing Details
2022-11-21 10:37:06 +00:00
renovate fdf294bcb3 chore(deps): update dependency netlify-cli to v12.2.4
continuous-integration/drone/push Build is passing Details
2022-11-21 10:36:15 +00:00
renovate 58baa5960c chore(deps): update dependency esbuild to v0.15.15
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-21 05:04:34 +00:00
renovate e948678e42 chore(deps): update dependency eslint to v8.28.0
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-19 01:04:33 +00:00
Dominik Pschenitschni 5ccedc6f67 [skip ci] Updated translations via Crowdin 2022-11-19 00:12:18 +00:00
Dominik Pschenitschni 74ad98de68 fix: icon offset and color
continuous-integration/drone/push Build is passing Details
2022-11-18 15:49:38 +00:00
Dominik Pschenitschni 3282f55c34 chore: add TODO comment 2022-11-18 15:49:38 +00:00
Dominik Pschenitschni d9984b28f7 feat: move link color location together 2022-11-18 15:49:38 +00:00
Dominik Pschenitschni 4fc7b9c67e feat: group navigation styles further 2022-11-18 15:49:38 +00:00
Dominik Pschenitschni ff9efe7889 feat: outdent navigation logo styles 2022-11-18 15:49:38 +00:00
Dominik Pschenitschni 66be0e6ac4 feat: undent and order navigation css 2022-11-18 15:49:38 +00:00
Dominik Pschenitschni da8df8b667 feat: move avatar class to where it is used (#2725)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2725
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-18 13:30:41 +00:00
Dominik Pschenitschni 42e9f306e8
feat: grid for list cards
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-18 14:04:20 +01:00
Angelo Delicato 4b47478440
feat: change list-content style (#91)
continuous-integration/drone/push Build is passing Details
Co-authored-by: thelicato <thelicato@users.noreply.github.com>
Reviewed-on: https://github.com/go-vikunja/frontend/pull/91
2022-11-17 17:35:06 +01:00
Dominik Pschenitschni b42e4cca59 feat: more horizontal space on mobile (#2722)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2722
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-17 16:17:18 +00:00
Dominik Pschenitschni 33d4efecc4 feat: move useAutoHeightTextarea to composable (#2723)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2723
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-17 15:39:34 +00:00
Dominik Pschenitschni 45ec1623d5 feat: remove edit-task from list view (#2721)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2721
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-17 15:35:18 +00:00
Dominik Pschenitschni 8ef309243d feat: improve loadTask logic (#2715)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2715
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-17 15:31:21 +00:00
Dominik Pschenitschni 3aaacf4533 fix: remove vuex leftover from setModuleLoading (#2716)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2716
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-17 15:02:26 +00:00
renovate 0350e37fbb fix(deps): update sentry-javascript monorepo to v7.20.0 (#2720)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2720
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-17 12:13:40 +00:00
renovate 244c436202 fix(deps): update dependency pinia to v2.0.24
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-17 08:04:15 +00:00
drone 18d0c8ba2c [skip ci] Updated translations via Crowdin 2022-11-17 00:12:14 +00:00
kolaente 3891d5b876
feat: only automatically redirect to provider if the url contains ?redirectToProvider=true and it's the only one
continuous-integration/drone/push Build is passing Details
Resolves https://github.com/go-vikunja/frontend/issues/90
2022-11-16 16:37:00 +01:00
Dominik Pschenitschni 98b38af43c feat: disable fullscreen for EasyMDE side-by-side mode (#2710)
continuous-integration/drone/push Build is passing Details
Fixes https://github.com/go-vikunja/frontend/issues/92
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2710
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-16 14:37:03 +00:00
konrad 77ff0aa256 feat: move transition in component (#2694)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2694
Reviewed-by: konrad <k@knt.li>
2022-11-16 14:36:17 +00:00
renovate 2ab26ee7c5 chore(deps): update pnpm to v7.16.1 (#2717)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2717
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-16 14:16:20 +00:00
renovate 58f38bcfc3 fix(deps): update font awesome to v6.2.1 (#2712)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2712
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-16 09:04:05 +00:00
renovate bcb5190365 chore(deps): update dependency cypress to v11.1.0
continuous-integration/drone/push Build is passing Details
2022-11-15 21:06:37 +00:00
renovate c99d09c83e chore(deps): update dependency typescript to v4.9.3
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-15 19:04:55 +00:00
renovate f49ea9752d chore(deps): update dependency vite to v3.2.4
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-15 14:04:41 +00:00
renovate a56683cdc2 chore(deps): update dependency @vue/test-utils to v2.2.3 (#2707)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2707
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-15 09:17:14 +00:00
renovate 7f4af63003 chore(deps): update dependency esbuild to v0.15.14 (#2706)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2706
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-15 08:36:58 +00:00
Dominik Pschenitschni 8c44ed83e6
feat: use transition component everywhere
continuous-integration/drone/pr Build is passing Details
2022-11-14 22:08:54 +01:00
renovate b388677eaf fix(deps): update dependency ufo to v1
continuous-integration/drone/push Build is passing Details
2022-11-14 18:42:12 +00:00
renovate bd7430b405 chore(deps): update typescript-eslint monorepo to v5.43.0
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-14 18:05:00 +00:00
renovate 4baed8fe79 chore(deps): update pnpm to v7.16.0 (#2703)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2703
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-14 16:01:36 +00:00
renovate fdbe4e8314 chore(deps): update dependency vitest to v0.25.2 (#2702)
continuous-integration/drone/push Build is failing Details
Reviewed-on: #2702
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-14 16:00:57 +00:00
renovate 4a7f839449 chore(deps): update dependency postcss-preset-env to v7.8.3 (#2701)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2701
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-14 10:15:12 +00:00
renovate c359f4d4dd chore(deps): update dependency netlify-cli to v12.1.1 (#2699)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2699
Reviewed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-14 09:16:36 +00:00
renovate 79d6212e48 chore(deps): update dependency happy-dom to v7.7.0
continuous-integration/drone/push Build is passing Details
2022-11-14 08:54:27 +00:00
renovate e541213872 chore(deps): update dependency caniuse-lite to v1.0.30001431
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2022-11-14 00:05:39 +00:00
Dominik Pschenitschni fd1d01164f feature/load-views-async (#2672)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2672
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-13 21:52:28 +00:00
renovate 34edf0dc5f chore(deps): update dependency @vue/test-utils to v2.2.2 (#2696)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2696
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-13 10:17:32 +00:00
Dominik Pschenitschni 631a19fa92
feat: move transition in own component 2022-11-12 19:32:39 +01:00
Dominik Pschenitschni fba402fcd0
feat: reduce TaskDetailView selector specificity 2022-11-12 19:29:20 +01:00
Dominik Pschenitschni 4c4adfdf4e fix: reactive const assignment (#2692)
continuous-integration/drone/push Build is passing Details
Resolves #2691

Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2692
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-12 16:14:32 +00:00
Dominik Pschenitschni 06775cf4c7 fix: use scss for datemathHelp (#2690)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2690
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-12 14:38:31 +00:00
kolaente c07954f2b8
feat(ci): use docker buildx for multiarch builds
continuous-integration/drone/push Build is passing Details
2022-11-12 14:43:29 +01:00
kolaente 995cc12880
fix(tasks): remove a task from its bucket when it is in the first kanban bucket
continuous-integration/drone/push Build is passing Details
Resolves https://github.com/go-vikunja/frontend/issues/89
2022-11-12 12:13:00 +01:00
Dominik Pschenitschni 293402b6fd fix: move heading styles to component (#2686)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2686
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-12 10:52:16 +00:00
Dominik Pschenitschni 708ef2d72e feat: improve user component (#2687)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2687
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-12 10:51:35 +00:00
Dominik Pschenitschni 4c458a1ad0 fix: move createdUpdated styles to component (#2685)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2685
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-12 10:50:48 +00:00
Dominik Pschenitschni 02de481297 feat: use img for logo so that it's not part of the main bundle (#2684)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2684
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-12 10:48:52 +00:00
Dominik Pschenitschni 9d604f7a3b feat: reduce ready selector specificity (#2683)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2683
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-12 10:48:15 +00:00
Dominik Pschenitschni 0f1f131f7a feat: reduce attachments selector specificity (#2682)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2682
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-12 10:47:46 +00:00
Dominik Pschenitschni eb4c2a4b9d feat: reduce dropdown-item selector specificity (#2680)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2680
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-12 10:46:39 +00:00
Dominik Pschenitschni 599c1ba4b5 feat: reduce ListWrapper selector specificity (#2679)
continuous-integration/drone/push Build is failing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2679
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-12 10:46:00 +00:00
Dominik Pschenitschni 12a8f7ebe9 feat: reduce contentAuth selector specifity (#2677)
continuous-integration/drone/push Build is failing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2677
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-12 10:45:24 +00:00
Dominik Pschenitschni 9f0f0b39f8 feat: reduce multiselect selector specificity (#2678)
continuous-integration/drone/push Build is passing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2678
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-12 10:44:49 +00:00
konrad 4a550da6a6 feat: filters script setup (#2671)
continuous-integration/drone/push Build is failing Details
Reviewed-on: #2671
2022-11-12 10:43:24 +00:00
renovate 52ba168d41 chore(deps): update dependency @types/dompurify to v2.4.0 (#2688)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2688
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-12 10:42:19 +00:00
renovate 9c7680aa55 chore(deps): update dependency rollup to v3.3.0 (#2689)
continuous-integration/drone/push Build is passing Details
Reviewed-on: #2689
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-11-12 10:41:30 +00:00
Dominik Pschenitschni 83bb030c6e [skip ci] Updated translations via Crowdin 2022-11-12 00:12:21 +00:00
Dominik Pschenitschni 163d9366d3 feat: add vite build target esnext (#2674)
continuous-integration/drone/push Build is failing Details
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: #2674
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-11-11 14:43:23 +00:00
kolaente 5cff9988a3
chore: 0.20.1 release preperations
continuous-integration/drone/push Build is failing Details
2022-11-11 12:02:16 +01:00
Dominik Pschenitschni bb58dba8e0
feat: move select filters to dedicated components
continuous-integration/drone/pr Build is passing Details
2022-11-10 17:11:56 +01:00
Dominik Pschenitschni 4bad685f39
feat: filters script setup 2022-11-10 17:11:56 +01:00
187 changed files with 7993 additions and 4870 deletions

View File

@ -96,7 +96,7 @@ steps:
- dependencies
- name: test-frontend
image: cypress/browsers:node18.12.0-chrome106-ff106
image: cypress/browsers:node18.12.0-chrome107
pull: always
environment:
CYPRESS_API_URL: http://api:3456/api/v1
@ -110,8 +110,7 @@ steps:
- sed -i 's/localhost/api/g' dist/index.html
- corepack enable && pnpm config set store-dir .cache/pnpm
- pnpm cypress install
- pnpm run serve:dist & npx wait-on http://localhost:4173
- pnpm run test:frontend --browser chrome --record
- pnpm run test:e2e-record
depends_on:
- build-prod
@ -342,111 +341,7 @@ steps:
---
kind: pipeline
type: docker
name: docker-arm-release
depends_on:
- release-latest
- release-version
platform:
os: linux
arch: arm64
trigger:
ref:
- refs/heads/main
- "refs/tags/**"
event:
exclude:
- cron
steps:
- name: docker-unstable
image: plugins/docker:linux-arm
pull: always
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/frontend
tags: unstable-linux-arm
build_args:
- USE_RELEASE=true
- RELEASE_VERSION=unstable
when:
ref:
- refs/heads/main
depends_on:
- clone
- name: docker-version
image: plugins/docker:linux-arm
pull: always
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/frontend
auto_tag: true
auto_tag_suffix: linux-arm
build_args:
- USE_RELEASE=true
- RELEASE_VERSION=${DRONE_TAG##v}
when:
ref:
- "refs/tags/**"
depends_on:
- clone
- name: docker-unstable-arm64
image: plugins/docker:linux-arm64
pull: always
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/frontend
tags: unstable-linux-arm64
build_args:
- USE_RELEASE=true
- RELEASE_VERSION=unstable
when:
ref:
- refs/heads/main
depends_on:
- clone
- name: docker-version-arm64
image: plugins/docker:linux-arm64
pull: always
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/frontend
auto_tag: true
auto_tag_suffix: linux-arm64
build_args:
- USE_RELEASE=true
- RELEASE_VERSION=${DRONE_TAG##v}
when:
ref:
- "refs/tags/**"
depends_on:
- clone
---
kind: pipeline
type: docker
name: docker-amd64-release
platform:
os: linux
arch: amd64
name: docker-release
depends_on:
- release-latest
@ -461,8 +356,14 @@ trigger:
- cron
steps:
- name: fetch-tags
image: docker:git
commands:
- git fetch --tags
- name: docker-unstable
image: plugins/docker:linux-amd64
image: thegeeklab/drone-docker-buildx
privileged: true
pull: always
settings:
username:
@ -470,92 +371,42 @@ steps:
password:
from_secret: docker_password
repo: vikunja/frontend
tags: unstable-linux-amd64
build_args:
- USE_RELEASE=true
- RELEASE_VERSION=unstable
when:
ref:
- refs/heads/main
- name: docker-version
image: plugins/docker:linux-amd64
pull: always
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/frontend
auto_tag: true
auto_tag_suffix: linux-amd64
build_args:
- USE_RELEASE=true
- RELEASE_VERSION=${DRONE_TAG##v}
when:
ref:
- "refs/tags/**"
---
kind: pipeline
type: docker
name: docker-manifest
trigger:
ref:
- refs/heads/main
- "refs/tags/**"
event:
exclude:
- cron
depends_on:
- docker-amd64-release
- docker-arm-release
steps:
- name: manifest-unstable
pull: always
image: plugins/manifest
settings:
tags: unstable
spec: docker-manifest-unstable.tmpl
password:
from_secret: docker_password
username:
from_secret: docker_username
build_args:
- USE_RELEASE=true
- RELEASE_VERSION=unstable
platforms:
- linux/386
- linux/amd64
- linux/arm/v6
- linux/arm/v7
- linux/arm64/v8
depends_on: [ fetch-tags ]
when:
ref:
- refs/heads/main
- name: manifest-release
- name: docker-release
image: thegeeklab/drone-docker-buildx
privileged: true
pull: always
image: plugins/manifest
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/frontend
auto_tag: true
ignore_missing: true
spec: docker-manifest.tmpl
password:
from_secret: docker_password
username:
from_secret: docker_username
when:
ref:
- "refs/tags/**"
- name: manifest-release-latest
pull: always
image: plugins/manifest
depends_on:
- clone
settings:
tags: latest
ignore_missing: true
spec: docker-manifest.tmpl
password:
from_secret: docker_password
username:
from_secret: docker_username
build_args:
- USE_RELEASE=true
- RELEASE_VERSION=${DRONE_TAG##v}
platforms:
- linux/386
- linux/amd64
- linux/arm/v6
- linux/arm/v7
- linux/arm64/v8
depends_on: [ fetch-tags ]
when:
ref:
- "refs/tags/**"
@ -578,9 +429,7 @@ depends_on:
- release-version
- release-latest
- trigger-desktop-update
- docker-arm-release
- docker-amd64-release
- docker-manifest
- docker-release
steps:
- name: notify
@ -601,9 +450,6 @@ kind: pipeline
type: docker
name: update-translations
depends_on:
- build
trigger:
branch:
- main
@ -663,6 +509,6 @@ steps:
from_secret: crowdin_key
---
kind: signature
hmac: 6784e836f6568c67abfb909449c6e845cc73cbe9a31e9e7ad9166a0eb59e30a2
hmac: dd67ef81f5bd85633fa72c9335fbceebbba5baebce5ebc310452459fd3dae2a8
...

View File

@ -1,6 +1,7 @@
name: Bug Report
description: Found something you weren't expecting? Report it here!
labels: kind/bug
labels:
- kind/bug
body:
- type: markdown
attributes:

37
.gitignore vendored
View File

@ -1,26 +1,31 @@
.DS_Store
node_modules
/dist*
*.zip
.direnv/
# local env files
.env.local
.env.*.local
# Log files
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
stats.html
pnpm-debug.log*
lerna-debug.log*
stats.html
node_modules
.DS_Store
/dist*
coverage
*.zip
.direnv/
# Test files
cypress/screenshots
cypress/videos
# local env files
.env.local
.env.*.local
# Editor directories and files
.idea
.vscode
.idea
*.suo
*.ntvs*
*.njsproj
@ -28,9 +33,9 @@ lerna-debug.log*
*.sw*
!rollup.sw.js
# Test files
cypress/screenshots
cypress/videos
# Local Netlify folder
.netlify
# histoire
.histoire

View File

@ -9,6 +9,340 @@ All releases can be found on https://code.vikunja.io/frontend/releases.
The releases aim at the api versions which is why there are missing versions.
## [0.20.2] - 2022-12-18
### Bug Fixes
* *(bug-report.yml)* List (#2845)
* *(quick add magic)* Don't create a new label multiple times if it is used in multiple tasks
* *(task)* Pass a list specified via quick add magic down to all subtasks created via indention
* *(task)* Move task color bubble next to task index and done badge on mobile
* *(tasks)* Remove a task from its bucket when it is in the first kanban bucket
* *(tasks)* Missing space when showing parent tasks and list title
* *(tasks)* Translation for multiple related tasks now works
* Move createdUpdated styles to component (#2685) ([4c458a1](4c458a1ad0761920868e3863982d5175664b3e6e))
* Move heading styles to component (#2686) ([293402b](293402b6fdfc699661c7f287ff1759a9ce5bea17))
* Use scss for datemathHelp (#2690) ([06775cf](06775cf4c72cf81a125b91d49c8d81e8649af661))
* Reactive const assignment (#2692) ([4c4adfd](4c4adfdf4e79eff3e101d9f0bd68bc3e5bb76495))
* Remove vuex leftover from setModuleLoading (#2716) ([3aaacf4](3aaacf4533c761864d3081edb92c9380df43f8b1))
* Icon offset and color ([74ad98d](74ad98de680f8b56e42886cd1e33874bd05772fa))
* Only load buckets if listId set (#2741) ([7db79ff](7db79ff04e4ce87d62cae7f93b67570bbc5c13be))
* Add all json files in src (#2737) ([422e731](422e731fe0d44c2e3be603b549538a05a695b95c))
* Vite.config imports (#2843) ([318e8c8](318e8c83a68bcb2f7953553c036f677a97b01c21))
### Dependencies
* *(deps)* Update dependency rollup to v3.3.0 (#2689)
* *(deps)* Update dependency @types/dompurify to v2.4.0 (#2688)
* *(deps)* Update dependency @vue/test-utils to v2.2.2 (#2696)
* *(deps)* Update dependency caniuse-lite to v1.0.30001431
* *(deps)* Update dependency happy-dom to v7.7.0
* *(deps)* Update dependency netlify-cli to v12.1.1 (#2699)
* *(deps)* Update dependency postcss-preset-env to v7.8.3 (#2701)
* *(deps)* Update dependency vitest to v0.25.2 (#2702)
* *(deps)* Update pnpm to v7.16.0 (#2703)
* *(deps)* Update typescript-eslint monorepo to v5.43.0
* *(deps)* Update dependency ufo to v1
* *(deps)* Update dependency esbuild to v0.15.14 (#2706)
* *(deps)* Update dependency @vue/test-utils to v2.2.3 (#2707)
* *(deps)* Update dependency vite to v3.2.4
* *(deps)* Update dependency typescript to v4.9.3
* *(deps)* Update dependency cypress to v11.1.0
* *(deps)* Update font awesome to v6.2.1 (#2712)
* *(deps)* Update pnpm to v7.16.1 (#2717)
* *(deps)* Update dependency pinia to v2.0.24
* *(deps)* Update sentry-javascript monorepo to v7.20.0 (#2720)
* *(deps)* Update dependency eslint to v8.28.0
* *(deps)* Update dependency esbuild to v0.15.15
* *(deps)* Update dependency netlify-cli to v12.2.4
* *(deps)* Update dependency @vue/test-utils to v2.2.4
* *(deps)* Update pnpm to v7.17.0
* *(deps)* Update dependency marked to v4.2.3
* *(deps)* Update dependency codemirror to v5.65.10
* *(deps)* Update sentry-javascript monorepo to v7.20.1
* *(deps)* Update dependency pinia to v2.0.25
* *(deps)* Update dependency rollup to v3.4.0
* *(deps)* Update typescript-eslint monorepo to v5.44.0
* *(deps)* Update vueuse to v9.6.0 (#2742)
* *(deps)* Update dependency vitest to v0.25.3 (#2743)
* *(deps)* Update dependency cypress to v11.2.0
* *(deps)* Update sentry-javascript monorepo to v7.21.0
* *(deps)* Update dependency @4tw/cypress-drag-drop to v2.2.2
* *(deps)* Update sentry-javascript monorepo to v7.21.1 (#2747)
* *(deps)* Update dependency pinia to v2.0.26
* *(deps)* Update dependency @cypress/vue to v5.0.2
* *(deps)* Update dependency highlight.js to v11.7.0 (#2752)
* *(deps)* Update dependency eslint-plugin-vue to v9.8.0 (#2753)
* *(deps)* Update dependency @infectoone/vue-ganttastic to v2.1.3
* *(deps)* Update dependency rollup to v3.5.0 (#2756)
* *(deps)* Update pnpm to v7.17.1 (#2755)
* *(deps)* Update dependency esbuild to v0.15.16
* *(deps)* Update dependency pinia to v2.0.27 (#2757)
* *(deps)* Update dependency caniuse-lite to v1.0.30001434 (#2759)
* *(deps)* Update dependency netlify-cli to v12.2.7 (#2760)
* *(deps)* Update dependency @kyvg/vue3-notification to v2.7.0 (#2761)
* *(deps)* Update typescript-eslint monorepo to v5.45.0 (#2762)
* *(deps)* Update dependency ufo to v1.0.1 (#2763)
* *(deps)* Update dependency vue-tsc to v1.0.10 (#2764)
* *(deps)* Update sentry-javascript monorepo to v7.22.0 (#2765)
* *(deps)* Update dependency @types/node to v18.11.10 (#2768)
* *(deps)* Update dependency rollup to v3.5.1 (#2769)
* *(deps)* Update sentry-javascript monorepo to v7.23.0
* *(deps)* Update dependency @vue/test-utils to v2.2.5 (#2773)
* *(deps)* Update dependency eslint to v8.29.0 (#2774)
* *(deps)* Update dependency @cypress/vue to v5.0.3 (#2775)
* *(deps)* Update dependency vue-tsc to v1.0.11 (#2777)
* *(deps)* Update dependency @cypress/vite-dev-server to v5 (#2776)
* *(deps)* Update pnpm to v7.18.0 (#2778)
* *(deps)* Update dependency esbuild to v0.15.17 (#2779)
* *(deps)* Update dependency caniuse-lite to v1.0.30001436 (#2780)
* *(deps)* Update dependency @vue/test-utils to v2.2.6 (#2784)
* *(deps)* Update dependency esbuild to v0.15.18 (#2783)
* *(deps)* Update dependency netlify-cli to v12.2.8 (#2782)
* *(deps)* Update dependency happy-dom to v7.7.2 (#2781)
* *(deps)* Update dependency vite to v3.2.5 (#2785)
* *(deps)* Update dependency rollup to v3.6.0 (#2786)
* *(deps)* Update typescript-eslint monorepo to v5.45.1 (#2787)
* *(deps)* Update dependency vitest to v0.25.4 (#2788)
* *(deps)* Update dependency @types/node to v18.11.11 (#2789)
* *(deps)* Update pnpm to v7.18.1 (#2790)
* *(deps)* Update dependency dayjs to v1.11.7 (#2791)
* *(deps)* Update dependency cypress to v12 (#2792)
* *(deps)* Update dependency vitest to v0.25.5 (#2793)
* *(deps)* Update dependency marked to v4.2.4 (#2796)
* *(deps)* Update dependency esbuild to v0.16.1 (#2795)
* *(deps)* Update dependency cypress to v12.0.1 (#2794)
* *(deps)* Update sentry-javascript monorepo to v7.24.0 (#2797)
* *(deps)* Update sentry-javascript monorepo to v7.24.1 (#2798)
* *(deps)* Update sentry-javascript monorepo to v7.24.2 (#2799)
* *(deps)* Update dependency typescript to v4.9.4 (#2800)
* *(deps)* Update dependency rollup to v3.7.0 (#2801)
* *(deps)* Update dependency esbuild to v0.16.2 (#2802)
* *(deps)* Update typescript-eslint monorepo to v5.46.0 (#2803)
* *(deps)* Update dependency vitest to v0.25.6 (#2804)
* *(deps)* Update dependency @cypress/vite-dev-server to v5.0.1 (#2806)
* *(deps)* Update dependency esbuild to v0.16.3 (#2809)
* *(deps)* Update dependency sass to v1.56.2 (#2810)
* *(deps)* Update dependency @types/marked to v4.0.8 (#2812)
* *(deps)* Update dependency vue-tsc to v1.0.12 (#2811)
* *(deps)* Update dependency @types/node to v18.11.12 (#2808)
* *(deps)* Update dependency cypress to v12.0.2 (#2807)
* *(deps)* Update dependency @vitejs/plugin-vue to v4 (#2814)
* *(deps)* Update dependency @vitejs/plugin-legacy to v3 (#2813)
* *(deps)* Update dependency pinia to v2.0.28 (#2815)
* *(deps)* Update dependency @vitejs/plugin-legacy to v3.0.1 (#2818)
* *(deps)* Update dependency @cypress/vite-dev-server to v5.0.2 (#2819)
* *(deps)* Update dependency rollup to v3.7.1 (#2820)
* *(deps)* Update dependency rollup to v3.7.2 (#2822)
* *(deps)* Update dependency esbuild to v0.16.4 (#2821)
* *(deps)* Update dependency vitest to v0.25.7 (#2824)
* *(deps)* Update dependency @types/node to v18.11.13 (#2823)
* *(deps)* Update dependency happy-dom to v8 (#2831)
* *(deps)* Update dependency postcss to v8.4.20 (#2827)
* *(deps)* Update dependency caniuse-lite to v1.0.30001439 (#2828)
* *(deps)* Update dependency @intlify/unplugin-vue-i18n to v0.8.1 (#2826)
* *(deps)* Update dependency netlify-cli to v12.2.10 (#2829)
* *(deps)* Update dependency vite-plugin-pwa to v0.14.0 (#2833)
* *(deps)* Update dependency rollup to v3.7.3 (#2825)
* *(deps)* Update dependency vue-tsc to v1.0.13 (#2832)
* *(deps)* Update sentry-javascript monorepo to v7.25.0
* *(deps)* Update dependency vite to v4 (#2816)
* *(deps)* Update pnpm to v7.18.2 (#2834)
* *(deps)* Update typescript-eslint monorepo to v5.46.1 (#2837)
* *(deps)* Update dependency @4tw/cypress-drag-drop to v2.2.3 (#2836)
* *(deps)* Update dependency @types/node to v18.11.14 (#2839)
* *(deps)* Update dependency cypress to v12.1.0 (#2838)
* *(deps)* Update dependency rollup to v3.7.4 (#2840)
* *(deps)* Update dependency vitest to v0.25.8
* *(deps)* Update sentry-javascript monorepo to v7.26.0
* *(deps)* Update dependency esbuild to v0.16.5 (#2846)
* *(deps)* Update dependency @types/node to v18.11.15
* *(deps)* Update dependency esbuild to v0.16.6 (#2848)
* *(deps)* Update dependency esbuild to v0.16.7
* *(deps)* Update sentry-javascript monorepo to v7.27.0 (#2850)
* *(deps)* Update dependency @vueuse/core to v9.7.0 (#2851)
* *(deps)* Update dependency wait-on to v7 (#2852)
* *(deps)* Update dependency @types/node to v18.11.16 (#2853)
* *(deps)* Update dependency eslint to v8.30.0
* *(deps)* Update dependency rollup to v3.7.5 (#2857)
* *(deps)* Update dependency esbuild to v0.16.8 (#2854)
* *(deps)* Update dependency sass to v1.57.0 (#2856)
* *(deps)* Update dependency vue-tsc to v1.0.14 (#2860)
* *(deps)* Update dependency esbuild to v0.16.9 (#2859)
* *(deps)* Update dependency @types/node to v18.11.17 (#2858)
### Features
* *(ci)* Use docker buildx for multiarch builds* Filters script setup ([4bad685](4bad685f39388d59fdd8ff79a1766c55f75262c2))
* Move select filters to dedicated components ([bb58dba](bb58dba8e07d683c75637ec88a378e873711eb29))
* Add vite build target esnext (#2674) ([163d936](163d9366d3061c40b5db7f3aad5c2cea01948403))
* Filters script setup (#2671) ([4a550da](4a550da6a69a50126b9d4a555b6713687347c2d3))
* Reduce multiselect selector specificity (#2678) ([9f0f0b3](9f0f0b39f8eea399b7b03003afa5893d0b8016f8))
* Reduce contentAuth selector specifity (#2677) ([12a8f7e](12a8f7ebe9fc556a7b0bc6e2d74e81d424ccfcf8))
* Reduce ListWrapper selector specificity (#2679) ([599c1ba](599c1ba4b5b0861d89755addf016e8f797b49dfe))
* Reduce dropdown-item selector specificity (#2680) ([eb4c2a4](eb4c2a4b9df93ee35404cd7143cc88b3d44f9d59))
* Reduce attachments selector specificity (#2682) ([0f1f131](0f1f131f7a2a38ee57175edfd5ed1c932225af16))
* Reduce ready selector specificity (#2683) ([9d604f7](9d604f7a3bc057bbe27ac19e73ac59736154d9b7))
* Use img for logo so that it's not part of the main bundle (#2684) ([02de481](02de481297502ad4b0b2eb2fa3e06366cce6d630))
* Improve user component (#2687) ([708ef2d](708ef2d72efbdfe6261322937b0a8f76ee19b9e4))
* Reduce TaskDetailView selector specificity ([fba402f](fba402fcd056ee397ce54f97ed4fec98845c7933))
* Move transition in own component ([631a19f](631a19fa923dba2759603e6a8b224cb4d3e1a038))
* Feature/load-views-async (#2672)
* Use transition component everywhere ([8c44ed8](8c44ed83e6530f67cc923a5e6d1a26c14575884a))
* Move transition in component (#2694) ([77ff0aa](77ff0aa256fbf388210af09d88673475386b3553))
* Disable fullscreen for EasyMDE side-by-side mode (#2710) ([98b38af](98b38af43c3acc9822f167ebca295f5aecb4908d))
* Only automatically redirect to provider if the url contains ?redirectToProvider=true and it's the only one ([3891d5b](3891d5b87634c890265477680fafaa04ff06cc3e))
* Improve loadTask logic (#2715) ([8ef3092](8ef309243db4e37d306167455987572006858cad))
* Remove edit-task from list view (#2721) ([45ec162](45ec1623d525ed31a49b6be6d609802c341fad27))
* Move useAutoHeightTextarea to composable (#2723) ([33d4efe](33d4efecc45ef8da5360fb878b7d365d1901b56c))
* More horizontal space on mobile (#2722) ([b42e4cc](b42e4cca59e338278261bc3ec613eefedde6fcce))
* Change list-content style (#91) ([4b47478](4b47478440d0af1bf24c44ea614c0f62f20723f7))
* Grid for list cards ([42e9f30](42e9f306e84120ba51d9b527c7868148730bf892))
* Move avatar class to where it is used (#2725) ([da8df8b](da8df8b667fc57798c1de7d78c1a7f88b0419d38))
* Undent and order navigation css ([66be0e6](66be0e6ac4bcf48124b33267224187b56ac9320a))
* Outdent navigation logo styles ([ff9efe7](ff9efe7889256706ac86bb1face842cd2de6f935))
* Group navigation styles further ([4fc7b9c](4fc7b9c67e2088e82760005cd530ea97cf796a4c))
* Move link color location together ([d9984b2](d9984b28f7d01da0f9d8f0afd5b6f0edf35823c2))
* Use fetch instead of axios for deploy preview (#2719) ([93d95b0](93d95b0821f39719c4a28c144ebb583c2eac754e))
* Remove useRouteQuery (#2751) ([3ee0bc3](3ee0bc345d6cd65769789ec029c50e652d80e1ca))
* Use Intl.DateTimeFormat for gantt weekdays (#2766) ([3b95824](3b95824f5834d7de50210414c56b07889db895c7))
* Add @intlify/unplugin-vue-i18n (#2772) ([b44d11c](b44d11cfc04712b9f9ec9479ba3a77a26c453532))
* Use vite preview for serve:dist:dev (#2842) ([f6c6f52](f6c6f52abe71674fa5f3951cc0ba61798758bd03))
* Use variable fonts with subsetting (#2817) ([b6a89a0](b6a89a0cde3c769e38146b05c33ff4ca4e97bca2))
### Other
* *(other)* [skip ci] Updated translations via Crowdin
## [0.20.1] - 2022-11-11
### Bug Fixes
* *(auth)* Always redirect to external openid provider if only one is enabled
* *(ci)* Cache folder name
* *(gantt)* Don't try to load list NaN when opening a task from the gantt chart
* *(kanban)* Don't allow dragging a bucket if a task input is focused
* *(quick add magic)* Don't parse labels, assignees or lists as date expressions if they are called that
* *(table)* Sort tasks by index instead of id
* *(tasks)* Show any errors happening during task load* SetModuleLoading LoadingState type ([35f4bb1](35f4bb138554d300757420261d70d1a6bf6b9cc0))
* Better kanban updateBucket types ([964aba4](964aba4824418e431955881be284e35f412e873b))
* Disable props destructure error ([d6cb965](d6cb965ea7330f80f1e3c213442a049f63cba57e))
* Missing href ([5d601ca](5d601ca4b34cd7368ff6061659617fff2836cdbc))
* Multiselect modelValue prop type ([480aa88](480aa8813ec28e1228e02ba78dd3ee3037f4928a))
* Potential issue with refs in Avatar ([3c5bfcc](3c5bfcc6f3cece0f3bd6e4f862a187c17a2c4d6c))
* CoverImageAttachmentId ([e01df4d](e01df4d36996aa281ef73ee74f3ac5316a0b8a98))
* Don't show user deletion menu entry in user settings if the server disabled it ([09b76b7](09b76b7bd476b9de653e53de579f1c533d101d4d))
* Resolve issues with vue-easymde (#2629) ([eb59ca5](eb59ca5836ae8454885827bcf28a8476600bd122))
* Remove wrong loadTask params (#2635) ([f7728e5](f7728e538408d15fcbfcd9ce02cd235447dfa6f0))
* Remove duplicate store assignment (#2644) ([38cef79](38cef79f680ddf3612376a90c69198e01283a5a0))
* Flatpickr types (#2647) ([7fbb6e8](7fbb6e8f700157238f8924ce95424d79a34b7543))
* Sort task alphabetically ([612e592](612e592da799ee6a76d32c8ebc567aeadde3ee11))
* Too much recursion error when opening a task from the gantt chart ([d47791b](d47791b95793aabf1524544494621b237479c15d))
* Lint & formatting ([c2dd18e](c2dd18edaa8ac29446845a5028d1a04c1f39fc76))
* Gantt route sync ([7ec2b6c](7ec2b6c0d28a1ae1799b1ed7a781efbf4c4542d7))
* Gantt route sync (#2664) ([9450817](94508173dcfc75d606d490a536f80e10397fb69c))
### Dependencies
* *(deps)* Update dependency vite to v3.2.1
* *(deps)* Update dependency @vue/test-utils to v2.2.1 (#2591)
* *(deps)* Update pnpm to v7.14.1 (#2593)
* *(deps)* Update dependency vue-flatpickr-component to v11
* *(deps)* Update sentry-javascript monorepo to v7.17.3
* *(deps)* Update dependency eslint-plugin-vue to v9.7.0
* *(deps)* Update dependency caniuse-lite to v1.0.30001427
* *(deps)* Update dependency blurhash to v2.0.4
* *(deps)* Update dependency vitest to v0.24.4
* *(deps)* Update dependency @types/node to v18.11.8
* *(deps)* Update dependency vite to v3.2.2
* *(deps)* Update dependency @kyvg/vue3-notification to v2.5.0
* *(deps)* Update dependency @kyvg/vue3-notification to v2.5.1
* *(deps)* Update dependency @kyvg/vue3-notification to v2.6.0 (#2612)
* *(deps)* Update typescript-eslint monorepo to v5.42.0
* *(deps)* Update dependency rollup to v3.2.4 (#2614)
* *(deps)* Update dependency @kyvg/vue3-notification to v2.6.1 (#2615)
* *(deps)* Update dependency rollup to v3.2.5 (#2618)
* *(deps)* Update dependency @cypress/vite-dev-server to v3.4.0 (#2617)
* *(deps)* Update dependency marked to v4.2.0 (#2616)
* *(deps)* Update dependency @types/node to v18.11.9 (#2619)
* *(deps)* Update dependency vitest to v0.24.5 (#2621)
* *(deps)* Update dependency @cypress/vue to v4.2.2
* *(deps)* Update dependency marked to v4.2.1 (#2625)
* *(deps)* Update pnpm to v7.14.2
* *(deps)* Update dependency esbuild to v0.15.13 (#2627)
* *(deps)* Update sentry-javascript monorepo to v7.17.4 (#2628)
* *(deps)* Pin dependency @types/codemirror to 5.60.5
* *(deps)* Update dependency vite-plugin-pwa to v0.13.2 (#2632)
* *(deps)* Update dependency sass to v1.56.0 (#2633)
* *(deps)* Update dependency marked to v4.2.2 (#2636)
* *(deps)* Update dependency eslint to v8.27.0
* *(deps)* Update dependency caniuse-lite to v1.0.30001430 (#2639)
* *(deps)* Update dependency netlify-cli to v12.1.0 (#2640)
* *(deps)* Update dependency vite to v3.2.3
* *(deps)* Update dependency @vitejs/plugin-legacy to v2.3.1 (#2641)
* *(deps)* Update dependency vite-plugin-pwa to v0.13.3 (#2648)
* *(deps)* Update dependency @cypress/vite-dev-server to v4 (#2651)
* *(deps)* Update dependency vitest to v0.25.0 (#2650)
* *(deps)* Update dependency @cypress/vue to v5 (#2652)
* *(deps)* Update typescript-eslint monorepo to v5.42.1 (#2653)
* *(deps)* Update dependency @cypress/vue to v5.0.1 (#2655)
* *(deps)* Update sentry-javascript monorepo to v7.18.0
* *(deps)* Update dependency vitest to v0.25.1 (#2657)
* *(deps)* Update dependency @cypress/vite-dev-server to v4.0.1 (#2658)
* *(deps)* Update vueuse to v9.5.0 (#2660)
* *(deps)* Update dependency sass to v1.56.1 (#2661)
* *(deps)* Update dependency vue to v3.2.42
* *(deps)* Update dependency @fortawesome/vue-fontawesome to v3.0.2
* *(deps)* Update dependency vue to v3.2.43 (#2663)
* *(deps)* Update dependency vue to v3.2.44 (#2666)
* *(deps)* Update pnpm to v7.15.0 (#2667)
* *(deps)* Update dependency cypress to v11 (#2659)
* *(deps)* Update dependency dompurify to v2.4.1 (#2669)
### Features
* *(ci)* Use 'always' for pull
* *(ci)* Add kind everywhere
* *(ci)* Update cypress image
* *(ci)* Improve drone config (#2637)
* *(tests)* Add tests for gantt chart time range
* *(tests)* Add tests for gantt chart task detail open* Task store with composition api (#2610) ([839d331](839d331bf51f9a0e9742b9972dbd6a88fa38f1c3))
* Auth store with composition api (#2602) ([825ba10](825ba100f0c05e1ab98d401157c30aad8658afa6))
* Config store with composition api (#2604) ([15ef86d](15ef86d597ceb8731febf789f1b812a339273e40))
* Base store with composition api (#2601) ([b4f4fd4](b4f4fd45a4c98629de182033e808cf7b22a1fe4a))
* Attachments store with composition api (#2603) ([a50eca8](a50eca852fcb841166baa07a6cc405eeb70c6e9d))
* Namespaces store with composition api (#2607) ([0832184](08321842220798b478ffaef7e9e11c527cb5b3bd))
* Lists store with composition api (#2606) ([5ae8bac](5ae8bace820b05d3ad05f40ab51164ec2c35c068))
* Label store with composition api (#2605) ([1002579](1002579173bd4b89e157c78ac607abd7969d85bc))
* Type improvements ([599e28e](599e28e5e5d56e4ced338ec1c79fea7d4576b85a))
* Type global components and especially icon prop ([a2c1702](a2c1702eef64dd779c86940898bd49fc2c96233f))
* Rework BaseButton ([e8c6afc](e8c6afce7298267f2f77ece0a746218c2eb3f7b7))
* Rework XButton ([4cd0e90](4cd0e90feaab05a2275e92affda23dde7453013f))
* Rework dropdown-item ([02deb0b](02deb0beddbc9221bdcafd0d09cee383571dae55))
* Rework popup ([0b58973](0b58973d872d8d54c9a829a06c8535a7a7115613))
* SingleTaskInList script setup (#2463) ([44e6981](44e6981759261cdada6388384cbad96e5401b8a9))
* Add type info ([0182695](0182695cda1252a65df3f48fdc316e82cd7fadbd))
* Rename http-common to fetcher (#2620) ([096daad](096daad80a9c089e732116ce3b8aa4310a611368))
* Improved types (#2547) ([0ff0d8c](0ff0d8c5b89bd6a8b628ddbe6074f61797b6b9c1))
* MigrateService script setup (#2432) ([8b7b4d6](8b7b4d61a3b9dd01ab58b7e7dd30bf649b62fcf6))
* Sticky action buttons (#2622) ([f4bc2b9](f4bc2b94f0466a357361a69cfb3562e84d1ea439))
* Simpliy editAssignees (#2646) ([d9a8382](d9a83820495f34ddbd776f70cabdc24bbb1c3f32))
* Remove comments from prioritySelect (#2645) ([6a93701](6a93701649d35622d13dda969aae4aedf145d4d0))
* ListKanban script setup (#2643) ([d85abbd](d85abbd77a8197e977fdbfec0ee309736cce05fa))
* Kanban store with composition api ([f0492d4](f0492d49ef5cd99d95085deec066cec85f4688b3))
### Miscellaneous Tasks
* *(ci)* Sign drone config* Remove comment ([1101fcb](1101fcb3fff1fce102a7418b1e2734a71cdf84e2))
* Improve multiselect hover types ([caa29c1](caa29c152d35b28658773b838de0a8909d0e509f))
* Remove unused processModel in services (#2624) ([7f00c7d](7f00c7dabd1e55ec0e9a86ca495f702a38ddb18d))
* Inline simple helper (#2631) ([e49f960](e49f960aea2ead5baca6965649821db6584cbac2))
* Move run.sh in scripts folder (#2649) ([5057b69](5057b69382ca65659b624206b381d8f1500bae82))
### Other
* *(other)* [skip ci] Updated translations via Crowdin
## [0.20.0] - 2022-10-28
### Bug Fixes

View File

@ -1,5 +1,5 @@
# Stage 1: Build application
FROM node:18-alpine AS compile-image
FROM --platform=$BUILDPLATFORM node:18-alpine AS compile-image
WORKDIR /build

View File

@ -4,7 +4,7 @@
[![Build Status](https://drone.kolaente.de/api/badges/vikunja/frontend/status.svg)](https://drone.kolaente.de/vikunja/frontend)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](LICENSE)
[![Download](https://img.shields.io/badge/download-v0.20.0-brightgreen.svg)](https://dl.vikunja.io)
[![Download](https://img.shields.io/badge/download-v0.20.2-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.

View File

@ -11,8 +11,10 @@ export default defineConfig({
},
projectId: '181c7x',
e2e: {
baseUrl: 'http://localhost:4173',
specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}',
specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}',
baseUrl: 'http://127.0.0.1:4173',
experimentalRunAllSpecs: true,
// testIsolation: false,
},
component: {
devServer: {

View File

@ -36,7 +36,7 @@ to get a shell inside the cypress container.
In that shell you can then execute the tests with
```shell
pnpm run test:frontend
pnpm run test:e2e
```
### Using The Cypress Dashboard
@ -44,5 +44,5 @@ pnpm run test:frontend
To open the Cypress Dashboard and run tests from there, run
```shell
pnpm run cypress:open
pnpm run test:e2e:dev
```

View File

@ -9,7 +9,7 @@ services:
ports:
- 3456:3456
cypress:
image: cypress/browsers:node16.14.0-chrome99-ff97
image: cypress/browsers:node18.12.0-chrome107
volumes:
- ..:/project
- $HOME/.cache:/home/node/.cache/

View File

@ -1,9 +1,10 @@
import {ListFactory} from '../../factories/list'
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import '../../support/authenticateUser'
import {ListFactory} from '../../factories/list'
import {prepareLists} from './prepareLists'
describe('List History', () => {
createFakeUserAndLogin()
prepareLists()
it('should show a list history on the home page', () => {
@ -45,7 +46,7 @@ describe('List History', () => {
cy.get('body')
.should('contain', 'Last viewed')
cy.get('.list-cards-wrapper-2-rows')
cy.get('[data-cy="listCardGrid"]')
.should('not.contain', lists[0].title)
.should('contain', lists[1].title)
.should('contain', lists[2].title)

View File

@ -1,10 +1,12 @@
import {formatISO, format} from 'date-fns'
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task'
import {prepareLists} from './prepareLists'
import '../../support/authenticateUser'
describe('List View Gantt', () => {
createFakeUserAndLogin()
prepareLists()
it('Hides tasks with no dates', () => {
@ -33,8 +35,8 @@ describe('List View Gantt', () => {
it('Shows tasks with dates', () => {
const now = new Date()
const tasks = TaskFactory.create(1, {
start_date: formatISO(now),
end_date: formatISO(now.setDate(now.getDate() + 4)),
start_date: now.toISOString(),
end_date: new Date(new Date(now).setDate(now.getDate() + 4)).toISOString(),
})
cy.visit('/lists/1/gantt')
@ -60,13 +62,12 @@ describe('List View Gantt', () => {
})
it('Drags a task around', () => {
cy.intercept('**/api/v1/tasks/*')
.as('taskUpdate')
cy.intercept(Cypress.env('API_URL') + '/tasks/*').as('taskUpdate')
const now = new Date()
TaskFactory.create(1, {
start_date: formatISO(now),
end_date: formatISO(now.setDate(now.getDate() + 4)),
start_date: now.toISOString(),
end_date: new Date(new Date(now).setDate(now.getDate() + 4)).toISOString(),
})
cy.visit('/lists/1/gantt')

View File

@ -1,14 +1,15 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {BucketFactory} from '../../factories/bucket'
import {ListFactory} from '../../factories/list'
import {TaskFactory} from '../../factories/task'
import {prepareLists} from './prepareLists'
import '../../support/authenticateUser'
describe('List View Kanban', () => {
let buckets
createFakeUserAndLogin()
prepareLists()
let buckets
beforeEach(() => {
buckets = BucketFactory.create(2)
})
@ -38,7 +39,7 @@ describe('List View Kanban', () => {
})
cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket')
cy.get('.kanban .bucket')
.contains(buckets[0].title)
.get('.bucket-footer .button')
.contains('Add another task')
@ -70,7 +71,7 @@ describe('List View Kanban', () => {
it('Can set a bucket limit', () => {
cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger')
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger')
.first()
.click()
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item')
@ -91,7 +92,7 @@ describe('List View Kanban', () => {
it('Can rename a bucket', () => {
cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .bucket-header .title')
cy.get('.kanban .bucket .bucket-header .title')
.first()
.type('{selectall}New Bucket Title{enter}')
cy.get('.kanban .bucket .bucket-header .title')
@ -102,7 +103,7 @@ describe('List View Kanban', () => {
it('Can delete a bucket', () => {
cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger')
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger')
.first()
.click()
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item')
@ -129,7 +130,7 @@ describe('List View Kanban', () => {
})
cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .tasks .task')
cy.get('.kanban .bucket .tasks .task')
.contains(tasks[0].title)
.first()
.drag('.kanban .bucket:nth-child(2) .tasks')
@ -148,7 +149,7 @@ describe('List View Kanban', () => {
})
cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .tasks .task')
cy.get('.kanban .bucket .tasks .task')
.contains(tasks[0].title)
.should('be.visible')
.click()
@ -170,7 +171,7 @@ describe('List View Kanban', () => {
const task = tasks[0]
cy.visit('/lists/1/kanban')
cy.getSettled('.kanban .bucket .tasks .task')
cy.get('.kanban .bucket .tasks .task')
.contains(task.title)
.should('be.visible')
.click()
@ -204,4 +205,37 @@ describe('List View Kanban', () => {
cy.get('.list-kanban .filter-container .base-button')
.should('exist')
})
it('Should remove a task from the board when deleting it', () => {
const lists = ListFactory.create(1)
const buckets = BucketFactory.create(2, {
list_id: lists[0].id,
})
const tasks = TaskFactory.create(5, {
list_id: 1,
bucket_id: buckets[0].id,
})
const task = tasks[0]
cy.visit('/lists/1/kanban')
cy.get('.kanban .bucket .tasks .task')
.contains(task.title)
.should('be.visible')
.click()
cy.get('.task-view .action-buttons .button')
.should('be.visible')
.contains('Delete')
.click()
cy.get('.modal-mask .modal-container .modal-content .header')
.should('contain', 'Delete this task')
cy.get('.modal-mask .modal-container .modal-content .actions .button')
.contains('Do it!')
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.kanban .bucket .tasks')
.should('not.contain', task.title)
})
})

View File

@ -1,12 +1,13 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {UserListFactory} from '../../factories/users_list'
import {TaskFactory} from '../../factories/task'
import {UserFactory} from '../../factories/user'
import {ListFactory} from '../../factories/list'
import {prepareLists} from './prepareLists'
import '../../support/authenticateUser'
describe('List View List', () => {
createFakeUserAndLogin()
prepareLists()
it('Should be an empty list', () => {
@ -78,7 +79,7 @@ describe('List View List', () => {
cy.get('.menu-list li .list-menu-link .color-bubble')
.should('have.css', 'background-color', 'rgb(0, 219, 96)')
cy.get('.tasks-container .tasks .color-bubble')
cy.get('.tasks .color-bubble')
.should('not.exist')
})
@ -90,9 +91,9 @@ describe('List View List', () => {
})
cy.visit('/lists/1/list')
cy.get('.tasks-container .tasks')
cy.get('.tasks')
.should('contain', tasks[1].title)
cy.get('.tasks-container .tasks')
cy.get('.tasks')
.should('not.contain', tasks[99].title)
cy.get('.card-content .pagination .pagination-link')
@ -101,9 +102,9 @@ describe('List View List', () => {
cy.url()
.should('contain', '?page=2')
cy.get('.tasks-container .tasks')
cy.get('.tasks')
.should('contain', tasks[99].title)
cy.get('.tasks-container .tasks')
cy.get('.tasks')
.should('not.contain', tasks[1].title)
})
})

View File

@ -1,8 +1,10 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task'
import '../../support/authenticateUser'
describe('List View Table', () => {
createFakeUserAndLogin()
it('Should show a table with tasks', () => {
const tasks = TaskFactory.create(1)
cy.visit('/lists/1/table')

View File

@ -1,9 +1,11 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task'
import {prepareLists} from './prepareLists'
import '../../support/authenticateUser'
describe('Lists', () => {
createFakeUserAndLogin()
let lists
prepareLists((newLists) => (lists = newLists))
@ -52,7 +54,7 @@ describe('Lists', () => {
cy.get('.list-title h1')
.should('contain', 'First List')
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .dropdown-trigger')
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .menu-list-dropdown-trigger')
.click()
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .dropdown-content')
.contains('Edit')
@ -80,7 +82,7 @@ describe('Lists', () => {
it('Should remove a list', () => {
cy.visit(`/lists/${lists[0].id}`)
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .dropdown-trigger')
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .menu-list-dropdown-trigger')
.click()
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .dropdown-content')
.contains('Delete')

View File

@ -1,14 +1,14 @@
import {UserFactory} from '../../factories/user'
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import '../../support/authenticateUser'
import {ListFactory} from '../../factories/list'
import {NamespaceFactory} from '../../factories/namespace'
describe('Namepaces', () => {
createFakeUserAndLogin()
let namespaces
beforeEach(() => {
UserFactory.create(1)
namespaces = NamespaceFactory.create(1)
ListFactory.create(1)
})

View File

@ -1,10 +1,8 @@
import {ListFactory} from '../../factories/list'
import {UserFactory} from '../../factories/user'
import {NamespaceFactory} from '../../factories/namespace'
import {TaskFactory} from '../../factories/task'
export function createLists() {
UserFactory.create(1)
NamespaceFactory.create(1)
const lists = ListFactory.create(1, {
title: 'First List'

View File

@ -1,14 +1,16 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task'
import {ListFactory} from '../../factories/list'
import {NamespaceFactory} from '../../factories/namespace'
import {UserListFactory} from '../../factories/users_list'
import '../../support/authenticateUser'
describe('Editor', () => {
createFakeUserAndLogin()
beforeEach(() => {
NamespaceFactory.create(1)
const lists = ListFactory.create(1)
ListFactory.create(1)
TaskFactory.truncate()
UserListFactory.truncate()
})

View File

@ -1,6 +1,12 @@
import '../../support/authenticateUser'
import {createFakeUserAndLogin} from '../../support/authenticateUser'
describe('The Menu', () => {
createFakeUserAndLogin()
beforeEach(() => {
cy.visit('/')
})
it('Is visible by default on desktop', () => {
cy.get('.namespace-container')
.should('have.class', 'is-active')

View File

@ -1,9 +1,12 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TeamFactory} from '../../factories/team'
import {TeamMemberFactory} from '../../factories/team_member'
import {UserFactory} from '../../factories/user'
import '../../support/authenticateUser'
describe('Team', () => {
createFakeUserAndLogin()
it('Creates a new team', () => {
TeamFactory.truncate()
cy.visit('/teams')

View File

@ -1,16 +1,13 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {ListFactory} from '../../factories/list'
import {seed} from '../../support/seed'
import {TaskFactory} from '../../factories/task'
import {formatISO} from 'date-fns'
import {UserFactory} from '../../factories/user'
import {NamespaceFactory} from '../../factories/namespace'
import {BucketFactory} from '../../factories/bucket'
import {updateUserSettings} from '../../support/updateUserSettings'
import '../../support/authenticateUser'
function seedTasks(numberOfTasks = 100, startDueDate = new Date()) {
UserFactory.create(1)
function seedTasks(numberOfTasks = 50, startDueDate = new Date()) {
NamespaceFactory.create(1)
const list = ListFactory.create()[0]
BucketFactory.create(1, {
@ -20,7 +17,7 @@ function seedTasks(numberOfTasks = 100, startDueDate = new Date()) {
let dueDate = startDueDate
for (let i = 0; i < numberOfTasks; i++) {
const now = new Date()
dueDate = (new Date(dueDate.valueOf())).setDate((new Date(dueDate.valueOf())).getDate() + 2)
dueDate = new Date(new Date(dueDate).setDate(dueDate.getDate() + 2))
tasks.push({
id: i + 1,
list_id: list.id,
@ -28,9 +25,9 @@ function seedTasks(numberOfTasks = 100, startDueDate = new Date()) {
created_by_id: 1,
title: 'Test Task ' + i,
index: i + 1,
due_date: formatISO(dueDate),
created: formatISO(now),
updated: formatISO(now),
due_date: dueDate.toISOString(),
created: now.toISOString(),
updated: now.toISOString(),
})
}
seed(TaskFactory.table, tasks)
@ -38,8 +35,11 @@ function seedTasks(numberOfTasks = 100, startDueDate = new Date()) {
}
describe('Home Page Task Overview', () => {
createFakeUserAndLogin()
it('Should show tasks with a near due date first on the home page overview', () => {
const {tasks} = seedTasks()
const taskCount = 50
const {tasks} = seedTasks(taskCount)
cy.visit('/')
cy.get('[data-cy="showTasks"] .card .task')
@ -49,8 +49,10 @@ describe('Home Page Task Overview', () => {
})
it('Should show overdue tasks first, then show other tasks', () => {
const oldDate = (new Date()).setDate((new Date()).getDate() - 14)
const {tasks} = seedTasks(100, oldDate)
const now = new Date()
const oldDate = new Date(new Date(now).setDate(now.getDate() - 14))
const taskCount = 50
const {tasks} = seedTasks(taskCount, oldDate)
cy.visit('/')
cy.get('[data-cy="showTasks"] .card .task')
@ -68,7 +70,7 @@ describe('Home Page Task Overview', () => {
TaskFactory.create(1, {
id: 999,
title: newTaskTitle,
due_date: formatISO(new Date()),
due_date: new Date().toISOString(),
}, false)
cy.visit(`/lists/${tasks[0].list_id}/list`)
@ -83,7 +85,7 @@ describe('Home Page Task Overview', () => {
it('Should not show a new task without a date at the bottom when there are > 50 tasks', () => {
// We're not using the api here to create the task in order to verify the flow
const {tasks} = seedTasks()
const {tasks} = seedTasks(100)
const newTaskTitle = 'New Task'
cy.visit('/')

View File

@ -1,4 +1,4 @@
import {formatISO} from 'date-fns'
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task'
import {ListFactory} from '../../factories/list'
@ -11,7 +11,6 @@ import {LabelFactory} from '../../factories/labels'
import {LabelTaskFactory} from '../../factories/label_task'
import {BucketFactory} from '../../factories/bucket'
import '../../support/authenticateUser'
import {TaskAttachmentFactory} from '../../factories/task_attachments'
function addLabelToTaskAndVerify(labelTitle: string) {
@ -46,12 +45,14 @@ function uploadAttachmentAndVerify(taskId: number) {
}
describe('Task', () => {
createFakeUserAndLogin()
let namespaces
let lists
let buckets
beforeEach(() => {
UserFactory.create(1)
// UserFactory.create(1)
namespaces = NamespaceFactory.create(1)
lists = ListFactory.create(1)
buckets = BucketFactory.create(1, {
@ -145,7 +146,7 @@ describe('Task', () => {
id: 1,
index: 1,
done: true,
done_at: formatISO(new Date())
done_at: new Date().toISOString()
})
cy.visit(`/tasks/${tasks[0].id}`)
@ -421,10 +422,10 @@ describe('Task', () => {
cy.visit(`/tasks/${tasks[0].id}`)
cy.getSettled('.task-view .details.labels-list .multiselect .input-wrapper')
cy.get('.task-view .details.labels-list .multiselect .input-wrapper')
.should('be.visible')
.should('contain', labels[0].title)
cy.getSettled('.task-view .details.labels-list .multiselect .input-wrapper')
cy.get('.task-view .details.labels-list .multiselect .input-wrapper')
.children()
.first()
.get('[data-cy="taskDetail.removeLabel"]')

11
cypress/e2e/tsconfig.json Normal file
View File

@ -0,0 +1,11 @@
{
"extends": "@vue/tsconfig/tsconfig.web.json",
"include": ["./**/*", "../support/**/*", "../factories/**/*"],
"compilerOptions": {
"baseUrl": ".",
"isolatedModules": false,
"target": "ES2015",
"lib": ["ESNext", "dom"],
"types": ["cypress"]
}
}

View File

@ -11,16 +11,11 @@ const testAndAssertFailed = fixture => {
cy.get('div.message.danger').contains('Wrong username or password.')
}
const username = 'test'
context('Login', () => {
beforeEach(() => {
UserFactory.create(1, {
username: 'test',
})
cy.visit('/', {
onBeforeLoad(win) {
win.localStorage.removeItem('token')
},
})
UserFactory.create(1, {username})
})
it('Should log in with the right credentials', () => {

View File

@ -1,4 +1,4 @@
import '../../support/authenticateUser'
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {createLists} from '../list/prepareLists'
function logout() {
@ -10,6 +10,8 @@ function logout() {
}
describe('Log out', () => {
createFakeUserAndLogin()
it('Logs the user out', () => {
cy.visit('/')

View File

@ -1,11 +1,7 @@
import {UserFactory} from '../../factories/user'
import '../../support/authenticateUser'
import {createFakeUserAndLogin} from '../../support/authenticateUser'
describe('User Settings', () => {
beforeEach(() => {
UserFactory.create(1)
})
createFakeUserAndLogin()
it('Changes the user avatar', () => {
cy.intercept(`${Cypress.env('API_URL')}/user/settings/avatar/upload`).as('uploadAvatar')

View File

@ -1,6 +1,5 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class BucketFactory extends Factory {
static table = 'buckets'
@ -13,8 +12,8 @@ export class BucketFactory extends Factory {
title: faker.lorem.words(3),
list_id: 1,
created_by_id: 1,
created: formatISO(now),
updated: formatISO(now)
created: now.toISOString(),
updated: now.toISOString(),
}
}
}

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class LabelTaskFactory extends Factory {
static table = 'label_tasks'
@ -11,7 +10,7 @@ export class LabelTaskFactory extends Factory {
id: '{increment}',
task_id: 1,
label_id: 1,
created: formatISO(now),
created: now.toISOString(),
}
}
}

View File

@ -1,7 +1,6 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class LabelFactory extends Factory {
static table = 'labels'
@ -15,8 +14,8 @@ export class LabelFactory extends Factory {
description: faker.lorem.text(10),
hex_color: (Math.random()*0xFFFFFF<<0).toString(16), // random 6-digit hex number
created_by_id: 1,
created: formatISO(now),
updated: formatISO(now),
created: now.toISOString(),
updated: now.toISOString(),
}
}
}

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory'
import {formatISO} from "date-fns"
import {faker} from '@faker-js/faker'
export class LinkShareFactory extends Factory {
@ -15,8 +14,8 @@ export class LinkShareFactory extends Factory {
right: 0,
sharing_type: 0,
shared_by_id: 1,
created: formatISO(now),
updated: formatISO(now)
created: now.toISOString(),
updated: now.toISOString(),
}
}
}

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory'
import {formatISO} from "date-fns"
import {faker} from '@faker-js/faker'
export class ListFactory extends Factory {
@ -13,8 +12,8 @@ export class ListFactory extends Factory {
title: faker.lorem.words(3),
owner_id: 1,
namespace_id: 1,
created: formatISO(now),
updated: formatISO(now)
created: now.toISOString(),
updated: now.toISOString(),
}
}
}

View File

@ -1,6 +1,5 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class NamespaceFactory extends Factory {
static table = 'namespaces'
@ -12,8 +11,8 @@ export class NamespaceFactory extends Factory {
id: '{increment}',
title: faker.lorem.words(3),
owner_id: 1,
created: formatISO(now),
updated: formatISO(now)
created: now.toISOString(),
updated: now.toISOString(),
}
}
}

View File

@ -1,6 +1,5 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class TaskFactory extends Factory {
static table = 'tasks'
@ -16,8 +15,8 @@ export class TaskFactory extends Factory {
created_by_id: 1,
index: '{increment}',
position: '{increment}',
created: formatISO(now),
updated: formatISO(now)
created: now.toISOString(),
updated: now.toISOString()
}
}
}

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class TaskAssigneeFactory extends Factory {
static table = 'task_assignees'
@ -11,7 +10,7 @@ export class TaskAssigneeFactory extends Factory {
id: '{increment}',
task_id: 1,
user_id: 1,
created: formatISO(now),
created: now.toISOString(),
}
}
}

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class TaskAttachmentFactory extends Factory {
static table = 'task_attachments'
@ -11,7 +10,7 @@ export class TaskAttachmentFactory extends Factory {
id: '{increment}',
task_id: 1,
file_id: 1,
created: formatISO(now),
created: now.toISOString(),
}
}
}

View File

@ -1,7 +1,6 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from "date-fns"
export class TaskCommentFactory extends Factory {
static table = 'task_comments'
@ -14,8 +13,8 @@ export class TaskCommentFactory extends Factory {
comment: faker.lorem.text(3),
author_id: 1,
task_id: 1,
created: formatISO(now),
updated: formatISO(now)
created: now.toISOString(),
updated: now.toISOString()
}
}
}

View File

@ -1,6 +1,5 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class TeamFactory extends Factory {
static table = 'teams'
@ -11,8 +10,8 @@ export class TeamFactory extends Factory {
return {
name: faker.lorem.words(3),
created_by_id: 1,
created: formatISO(now),
updated: formatISO(now)
created: now.toISOString(),
updated: now.toISOString(),
}
}
}

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'
export class TeamMemberFactory extends Factory {
static table = 'team_members'
@ -9,7 +8,7 @@ export class TeamMemberFactory extends Factory {
team_id: 1,
user_id: 1,
admin: false,
created: formatISO(new Date()),
created: new Date().toISOString(),
}
}
}

View File

@ -1,7 +1,6 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from "date-fns"
export class UserFactory extends Factory {
static table = 'users'
@ -15,8 +14,8 @@ export class UserFactory extends Factory {
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.', // 1234
status: 0,
issuer: 'local',
created: formatISO(now),
updated: formatISO(now)
created: now.toISOString(),
updated: now.toISOString(),
}
}
}

View File

@ -1,5 +1,4 @@
import {Factory} from '../support/factory'
import {formatISO} from "date-fns"
export class UserListFactory extends Factory {
static table = 'users_lists'
@ -12,8 +11,8 @@ export class UserListFactory extends Factory {
list_id: 1,
user_id: 1,
right: 0,
created: formatISO(now),
updated: formatISO(now)
created: now.toISOString(),
updated: now.toISOString(),
}
}
}

View File

@ -4,26 +4,32 @@
import {UserFactory} from '../factories/user'
let token
before(() => {
const users = UserFactory.create(1)
cy.request('POST', `${Cypress.env('API_URL')}/login`, {
username: users[0].username,
password: '1234',
})
.its('body')
.then(r => {
token = r.token
export function login(user, cacheAcrossSpecs = false) {
if (!user) {
throw new Error('Needs user')
}
// Caching session when logging in via page visit
cy.session(`user__${user.username}`, () => {
cy.request('POST', `${Cypress.env('API_URL')}/login`, {
username: user.username,
password: '1234',
}).then(({ body }) => {
window.localStorage.setItem('token', body.token)
})
})
}, {
cacheAcrossSpecs,
})
}
beforeEach(() => {
cy.log(`Using token ${token} to make authenticated requests`)
cy.visit('/', {
onBeforeLoad(win) {
win.localStorage.setItem('token', token)
},
export function createFakeUserAndLogin() {
let user
before(() => {
user = UserFactory.create(1)[0]
})
})
beforeEach(() => {
login(user, true)
})
return user
}

View File

@ -34,38 +34,4 @@
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
// }
// }
// }
/**
* Recursively gets an element, returning only after it's determined to be attached to the DOM for good.
*
* Source: https://github.com/cypress-io/cypress/issues/7306#issuecomment-850621378
*/
Cypress.Commands.add('getSettled', (selector, opts = {}) => {
const retries = opts.retries || 3
const delay = opts.delay || 100
const isAttached = (resolve, count = 0) => {
const el = Cypress.$(selector)
// is element attached to the DOM?
count = Cypress.dom.isAttached(el) ? count + 1 : 0
// hit our base case, return the element
if (count >= retries) {
return resolve(el)
}
// retry after a bit of a delay
setTimeout(() => isAttached(resolve, count), delay)
}
// wrap, so we can chain cypress commands off the result
return cy.wrap(null).then(() => {
return new Cypress.Promise((resolve) => {
return isAttached(resolve, 0)
}).then((el) => {
return cy.wrap(el)
})
})
})
// }

View File

@ -1,10 +0,0 @@
{
"extends": "@vue/tsconfig/tsconfig.web.json",
"include": ["./integration/**/*", "./support/**/*"],
"compilerOptions": {
"isolatedModules": false,
"target": "es5",
"lib": ["es5", "dom"],
"types": ["cypress"]
}
}

View File

@ -1,17 +0,0 @@
image: vikunja/frontend:unstable
manifests:
-
image: vikunja/frontend:unstable-linux-amd64
platform:
architecture: amd64
os: linux
-
image: vikunja/frontend:unstable-linux-arm64
platform:
architecture: arm64
os: linux
-
image: vikunja/frontend:unstable-linux-arm
platform:
architecture: arm
os: linux

View File

@ -1,23 +0,0 @@
image: vikunja/frontend:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
{{#if build.tags}}
tags:
{{#each build.tags}}
- {{this}}
{{/each}}
{{/if}}
manifests:
-
image: vikunja/frontend:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
platform:
architecture: amd64
os: linux
-
image: vikunja/frontend:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
platform:
architecture: arm64
os: linux
-
image: vikunja/frontend:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
platform:
architecture: arm
os: linux

9
env.config.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
declare module 'postcss-easings' {
import postcssEasings from 'postcss-easings'
export default postcssEasings
}
declare module 'postcss-easing-gradients' {
import postcssEasingGradients from 'postcss-easing-gradients'
export default postcssEasingGradients
}

11
env.d.ts vendored
View File

@ -1,3 +1,12 @@
/// <reference types="vite/client" />
/// <reference types="vite-svg-loader" />
/// <reference types="cypress" />
/// <reference types="cypress" />
/// <reference types="@histoire/plugin-vue/components" />
interface ImportMetaEnv {
readonly VITE_IS_ONLINE: boolean
}
interface ImportMeta {
readonly env: ImportMetaEnv
}

34
histoire.config.ts Normal file
View File

@ -0,0 +1,34 @@
import {defineConfig, defaultColors} from 'histoire'
import {HstVue} from '@histoire/plugin-vue'
import {HstScreenshot} from '@histoire/plugin-screenshot'
export default defineConfig({
setupFile: './src/histoire.setup.ts',
storyIgnored: [
'**/node_modules/**',
'**/dist/**',
// see https://kolaente.dev/vikunja/frontend/pulls/2724#issuecomment-42012
'**/.direnv/**',
],
plugins: [
HstVue(),
HstScreenshot({
// Options here
}),
],
theme: {
title: 'Vikunja',
colors: {
// https://histoire.dev/guide/config.html#builtin-colors
gray: defaultColors.zinc,
primary: defaultColors.cyan,
},
// logo: {
// square: './img/square.png',
// light: './img/light.png',
// dark: './img/dark.png',
// },
// logoHref: 'https://acme.com',
// favicon: './favicon.ico',
},
})

View File

@ -9,13 +9,9 @@
<link rel="icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="/images/icons/apple-touch-icon-180x180.png"/>
<link rel="preload" crossorigin="anonymous" href="/fonts/open-sans-v15-latin-700italic.woff2" as="font">
<link rel="preload" crossorigin="anonymous" href="/fonts/open-sans-v15-latin-italic.woff2" as="font">
<link rel="preload" crossorigin="anonymous" href="/fonts/quicksand-v7-latin-500.woff2" as="font">
<link rel="preload" crossorigin="anonymous" href="/fonts/quicksand-v7-latin-700.woff2" as="font">
<link rel="preload" crossorigin="anonymous" href="/fonts/open-sans-v15-latin-regular.woff2" as="font">
<link rel="preload" crossorigin="anonymous" href="/fonts/open-sans-v15-latin-700.woff2" as="font">
<link rel="preload" crossorigin="anonymous" href="/fonts/quicksand-v7-latin-regular.woff2" as="font">
<link rel="preload" crossorigin="anonymous" href="/src/assets/fonts/OpenSans[wght].woff2" as="font">
<link rel="preload" crossorigin="anonymous" href="/src/assets/fonts/OpenSans-Italic[wght].woff2" as="font">
<link rel="preload" crossorigin="anonymous" href="/src/assets/fonts/Quicksand[wght].woff2" as="font">
</head>
<body>
<noscript>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -4,58 +4,66 @@
"private": true,
"scripts": {
"serve": "vite",
"serve:dist-dev": "node scripts/serve-dist.js",
"serve:dist": "vite preview --port 4173",
"preview": "vite preview --port 4173",
"preview:dev": "vite preview --outDir dist-dev --mode development --port 4173",
"build": "vite build && workbox copyLibraries dist/",
"build:modern-only": "BUILD_MODERN_ONLY=true vite build && workbox copyLibraries dist/",
"build:dev": "vite build -m development --outDir dist-dev/",
"build:dev": "vite build --mode development --outDir dist-dev/",
"lint": "eslint --ignore-pattern '*.test.*' ./src --ext .vue,.js,.ts",
"cypress:open": "cypress open",
"test:unit": "vitest --run",
"test:unit-watch": "vitest watch",
"test:frontend": "cypress run",
"test:e2e": "start-server-and-test preview http://127.0.0.1:4173 'cypress run --e2e --browser chrome'",
"test:e2e-record": "start-server-and-test preview http://127.0.0.1:4173 'cypress run --e2e --browser chrome --record'",
"test:e2e-dev-dev": "start-server-and-test preview:dev http://127.0.0.1:4173 'cypress open --e2e'",
"test:e2e-dev": "start-server-and-test preview http://127.0.0.1:4173 'cypress open --e2e'",
"test:unit": "vitest",
"typecheck": "vue-tsc --noEmit && vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
"browserslist:update": "npx browserslist@latest --update-db"
"browserslist:update": "pnpm dlx browserslist@latest --update-db",
"fonts:update": "pnpm fonts:download && pnpm fonts:subset",
"fonts:download": "./scripts/fonts-download.sh",
"fonts:subset": "./scripts/fonts-subset.sh",
"story:dev": "histoire dev",
"story:build": "histoire build",
"story:preview": "histoire preview"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "6.2.0",
"@fortawesome/free-regular-svg-icons": "6.2.0",
"@fortawesome/free-solid-svg-icons": "6.2.0",
"@fortawesome/fontawesome-svg-core": "6.2.1",
"@fortawesome/free-regular-svg-icons": "6.2.1",
"@fortawesome/free-solid-svg-icons": "6.2.1",
"@fortawesome/vue-fontawesome": "3.0.2",
"@github/hotkey": "2.0.1",
"@infectoone/vue-ganttastic": "2.1.2",
"@kyvg/vue3-notification": "2.6.1",
"@sentry/tracing": "7.19.0",
"@sentry/vue": "7.19.0",
"@infectoone/vue-ganttastic": "2.1.3",
"@intlify/unplugin-vue-i18n": "0.8.1",
"@kyvg/vue3-notification": "2.7.0",
"@sentry/tracing": "7.29.0",
"@sentry/vue": "7.29.0",
"@types/is-touch-device": "1.0.0",
"@types/lodash.clonedeep": "4.5.7",
"@types/sortablejs": "1.15.0",
"@vueuse/core": "9.5.0",
"@vueuse/router": "9.5.0",
"axios": "0.27.2",
"@vueuse/core": "9.10.0",
"axios": "1.2.2",
"blurhash": "2.0.4",
"bulma-css-variables": "0.9.33",
"camel-case": "4.1.2",
"codemirror": "5.65.9",
"codemirror": "5.65.11",
"date-fns": "2.29.3",
"dayjs": "1.11.6",
"dompurify": "2.4.1",
"dayjs": "1.11.7",
"dompurify": "2.4.2",
"easymde": "2.18.0",
"fast-deep-equal": "3.1.3",
"flatpickr": "4.6.13",
"flexsearch": "0.7.31",
"floating-vue": "2.0.0-beta.20",
"highlight.js": "11.6.0",
"focus-within": "3.0.2",
"highlight.js": "11.7.0",
"is-touch-device": "1.0.1",
"lodash.clonedeep": "4.5.0",
"lodash.debounce": "4.0.8",
"marked": "4.2.2",
"marked": "4.2.5",
"minimist": "1.2.7",
"pinia": "2.0.23",
"pinia": "2.0.28",
"register-service-worker": "1.7.2",
"snake-case": "3.0.4",
"sortablejs": "1.15.0",
"ufo": "0.8.6",
"ufo": "1.0.1",
"vue": "3.2.45",
"vue-advanced-cropper": "2.8.6",
"vue-flatpickr-component": "11.0.1",
@ -65,50 +73,56 @@
"zhyswan-vuedraggable": "4.1.3"
},
"devDependencies": {
"@4tw/cypress-drag-drop": "2.2.1",
"@cypress/vite-dev-server": "4.0.1",
"@cypress/vue": "5.0.1",
"@4tw/cypress-drag-drop": "2.2.3",
"@cypress/vite-dev-server": "5.0.2",
"@cypress/vue": "5.0.3",
"@faker-js/faker": "7.6.0",
"@histoire/plugin-screenshot": "0.12.4",
"@histoire/plugin-vue": "0.12.4",
"@rushstack/eslint-patch": "1.2.0",
"@types/codemirror": "5.60.5",
"@types/dompurify": "2.3.4",
"@types/codemirror": "5.60.6",
"@types/dompurify": "2.4.0",
"@types/flexsearch": "0.7.3",
"@types/focus-within": "1.0.1",
"@types/lodash.debounce": "4.0.7",
"@types/marked": "4.0.7",
"@types/node": "18.11.9",
"@types/marked": "4.0.8",
"@types/node": "18.11.18",
"@types/postcss-preset-env": "7.7.0",
"@typescript-eslint/eslint-plugin": "5.42.1",
"@typescript-eslint/parser": "5.42.1",
"@vitejs/plugin-legacy": "2.3.1",
"@vitejs/plugin-vue": "3.2.0",
"@typescript-eslint/eslint-plugin": "5.48.0",
"@typescript-eslint/parser": "5.48.0",
"@vitejs/plugin-legacy": "3.0.1",
"@vitejs/plugin-vue": "4.0.0",
"@vue/eslint-config-typescript": "11.0.2",
"@vue/test-utils": "2.2.1",
"@vue/test-utils": "2.2.7",
"@vue/tsconfig": "0.1.3",
"autoprefixer": "10.4.13",
"browserslist": "4.21.4",
"caniuse-lite": "1.0.30001430",
"caniuse-lite": "1.0.30001441",
"csstype": "3.1.1",
"cypress": "11.0.1",
"esbuild": "0.15.13",
"eslint": "8.27.0",
"eslint-plugin-vue": "9.7.0",
"express": "4.18.2",
"happy-dom": "7.6.6",
"netlify-cli": "12.1.0",
"postcss": "8.4.19",
"postcss-preset-env": "7.8.2",
"rollup": "3.2.5",
"rollup-plugin-visualizer": "5.8.3",
"sass": "1.56.1",
"typescript": "4.8.4",
"vite": "3.2.3",
"vite-plugin-pwa": "0.13.3",
"vite-svg-loader": "3.6.0",
"vitest": "0.25.1",
"vue-tsc": "1.0.9",
"wait-on": "6.0.1",
"cypress": "12.3.0",
"esbuild": "0.16.14",
"eslint": "8.31.0",
"eslint-plugin-vue": "9.8.0",
"happy-dom": "8.1.1",
"histoire": "0.12.4",
"netlify-cli": "12.5.0",
"postcss": "8.4.20",
"postcss-easing-gradients": "3.0.1",
"postcss-easings": "3.0.1",
"postcss-preset-env": "7.8.3",
"rollup": "3.9.1",
"rollup-plugin-visualizer": "5.9.0",
"sass": "1.57.1",
"start-server-and-test": "1.15.2",
"typescript": "4.9.4",
"vite": "4.0.4",
"vite-plugin-pwa": "0.14.1",
"vite-svg-loader": "4.0.0",
"vitest": "0.26.3",
"vue-tsc": "1.0.22",
"wait-on": "7.0.1",
"workbox-cli": "6.5.4"
},
"license": "AGPL-3.0-or-later",
"packageManager": "pnpm@7.15.0"
"packageManager": "pnpm@7.22.0"
}

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,18 @@
const {exec} = require('child_process')
const axios = require('axios')
const { exec } = require('child_process')
function createSlug(string) {
return String(string)
.trim()
.normalize('NFKD')
.toLowerCase()
.replace(/[.\s/]/g, '-')
.replace(/[^A-Za-z\d-]/g, '')
}
const BOT_USER_ID = 513
const giteaToken = process.env.GITEA_TOKEN
const siteId = process.env.NETLIFY_SITE_ID
const branchSlug = String(process.env.DRONE_SOURCE_BRANCH)
.trim()
.normalize('NFKD')
.toLowerCase()
.replace(/[.\s/]/g, '-')
.replace(/[^A-Za-z\d-]/g, '')
const branchSlug = createSlug(process.env.DRONE_SOURCE_BRANCH)
const prNumber = process.env.DRONE_PULL_REQUEST
const prIssueCommentsUrl = `https://kolaente.dev/api/v1/repos/vikunja/frontend/issues/${prNumber}/comments`
@ -35,7 +38,7 @@ const promiseExec = cmd => {
stdout = await promiseExec(`./node_modules/.bin/netlify deploy --alias ${alias}`)
console.log(stdout)
const {data} = await axios.get(prIssueCommentsUrl)
const data = await fetch(prIssueCommentsUrl).then(response => response.json())
const hasComment = data.some(c => c.user.id === BOT_USER_ID)
if (hasComment) {
@ -43,8 +46,7 @@ const promiseExec = cmd => {
return
}
await axios.post(prIssueCommentsUrl, {
body: `
const message = `
Hi ${process.env.DRONE_COMMIT_AUTHOR}!
Thank you for creating a PR!
@ -57,14 +59,25 @@ You will need to manually connect this to an api running somehwere. The easiest
Have a nice day!
> Beep boop, I'm a bot.
`,
}, {
headers: {
'Content-Type': 'application/json',
'accept': 'application/json',
'Authorization': `token ${giteaToken}`,
},
})
`
console.log(`Preview comment sent successfully to PR #${prNumber}!`)
try {
const response = await fetch(prIssueCommentsUrl, {
method: 'POST',
body: JSON.stringify({
body: message,
}),
headers: {
'Content-Type': 'application/json',
'accept': 'application/json',
'Authorization': `token ${giteaToken}`,
},
})
if (!response.ok) {
throw new Error(`HTTP error, status = ${response.status}`)
}
console.log(`Preview comment sent successfully to PR #${prNumber}!`)
} catch (e) {
console.log(`Could not send preview comment to PR #${prNumber}! ${e.message}`)
}
})()

View File

@ -1 +1 @@
bb46342a0a08105b340ba7976cff9d80ef89901120ec0639669caa70bb7d2dbc43e78b1f635a7654ab2456e8358c98a4 ./scripts/deploy-preview-netlify.js
24df869e7a9282c76c9e1883071a39c0b11a53a57da68b37f2b918df25b1ae0f1b403e38a29c9cb694575bb9a7b52b6e ./scripts/deploy-preview-netlify.js

56
scripts/fonts-download.sh Executable file
View File

@ -0,0 +1,56 @@
#!/bin/sh
set -e
#
# This script downloads our original font files from their source repos
# and puts them in our originalMedia folder.
#
err_report() {
echo "Error on line $(caller)" >&2
}
trap err_report ERR
ORIGINAL_FONTS_DIR="./originalMedia/fonts"
# update these if there is a new version
FONT_URLS=(
"https://github.com/googlefonts/opensans/blob/27d060e1aad6886daeda67629ee28189f795f534/fonts/variable/OpenSans%5Bwdth%2Cwght%5D.ttf?raw=true"
"https://github.com/googlefonts/opensans/blob/27d060e1aad6886daeda67629ee28189f795f534/fonts/variable/OpenSans-Italic%5Bwdth%2Cwght%5D.ttf?raw=true"
"https://github.com/andrew-paglinawan/QuicksandFamily/blob/db6de44878582966f45a0debaef10d57108d93a7/fonts/Quicksand%5Bwght%5D.ttf?raw=true"
)
echo ""
echo "###################################################"
echo "# Download font files"
echo "###################################################"
echo ""
mkdir -p $ORIGINAL_FONTS_DIR
for URL in ${FONT_URLS[@]}; do
wget -L $URL \
--directory-prefix=$ORIGINAL_FONTS_DIR \
--quiet \
--timestamping \
--show-progress
done
echo ""
echo "###################################################"
echo "# Remove '?raw=true' filename suffix"
echo "###################################################"
echo ""
# Iterate over all files in directory with filetype ending in "?raw=true"
for file in $ORIGINAL_FONTS_DIR/*?raw=true; do
# Remove "?raw=true" from file name and store in variable
new_name=$(echo $file | sed 's/?raw=true//')
# Overwrite existing file with new name
mv -v $file $new_name
done
echo "Renaming files complete"

161
scripts/fonts-subset.sh Executable file
View File

@ -0,0 +1,161 @@
#!/bin/sh
set -e
#
# This script subsets our variable fonts,
# converts them to woff2 files and puts them in the
# fonts folder.
#
# We do have to update the font paths in the @font-face
# definitions manually since we use a checksum to make
#
# We use fonttools to create a partial instance of the
# variable font where we keep only our needed features.
# See more at:
# https://fonttools.readthedocs.io/en/latest/varLib/instancer.html
#
# fonttools requires python > 3.7. For up-to-date
# instructions see https://github.com/fonttools/fonttools#installation
#
# Lot's of info was gathered from:
# https://markoskon.com/creating-font-subsets/
# https://barrd.dev/article/create-a-variable-font-subset-for-smaller-file-size/
#
ORIGINAL_FONTS="./originalMedia/fonts"
TEMP_FOLDER="./.subset-fonts-temp"
FONT_FOLDER="./src/assets/fonts"
err_report() {
echo "Error on line $(caller)" >&2
}
trap err_report ERR
mkdir -p $TEMP_FOLDER
# the latin subset that google uses on GoogleFonts
# this is the same as the latin subset range that google uses on GoogleFonts
# see for examle the unicode-range definition here:
# https://fonts.googleapis.com/css2?family=Open+Sans
UNICODE_LATIN_SUBSET="U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,\
U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,\
U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD"
get_filename_without_type() {
filename=$1
dirname=$(dirname $filename)
# Extract the file type using parameter expansion
filetype=${filename##*.}
basename=$(basename $filename .$filetype)
echo $basename
}
# This function takes a font file and creates a subset of it using a specified set of unicode characters.
instance_and_subset () {
# Define default arguments for the subsetter.
DEFAULT_SUBSETTER_ARGS="--layout-features=* --unicodes=${UNICODE_LATIN_SUBSET}"
# Assign function arguments to variables with more descriptive names.
INPUT_FONT_FILE=$1
INSTANCER_ARGS=$2
OUTPUT_FONT_BASENAME=$3
OUTPUT_FOLDER=$FONT_FOLDER
# If the output font basename is not provided, use the input font file's basename as the output font basename.
if [ -z "$OUTPUT_FONT_BASENAME" ]; then
INPUT_FONT_BASENAME=$(get_filename_without_type $INPUT_FONT_FILE)
OUTPUT_FONT_BASENAME=$INPUT_FONT_BASENAME
fi
# Use the default subsetter arguments if no custom arguments are provided.
SUBSETTER_ARGS="${4:-$DEFAULT_SUBSETTER_ARGS}"
CHECKSUM=$(
# Concatenate the contents of the input font file, the instancer arguments, and the subsetter arguments
printf "%s%s" "$(cat $INPUT_FONT_FILE)" "$INSTANCER_ARGS" "$SUBSETTER_ARGS" |
# Calculate the Blake2b checksum of the concatenated string
b2sum |
# Extract the checksum from the output of b2sum (it's the first field)
awk '{print $1}'
)
# Limit the checksum to 8 characters.
CHECKSUM=$(echo "${CHECKSUM:0:8}")
# Construct the output font's filename
OUTPUT_FONT_BASENAME="${OUTPUT_FONT_BASENAME}_${CHECKSUM}"
OUTPUT_FONT_FILE="${OUTPUT_FOLDER}/${OUTPUT_FONT_BASENAME}.woff2"
# Check if the output font file already exists
if test -f $OUTPUT_FONT_FILE; then
echo "${OUTPUT_FONT_FILE} exists"
return 0
fi
FONT_INSTANCE="${TEMP_FOLDER}/${OUTPUT_FONT_BASENAME}.ttf"
if [ -n "$INSTANCER_ARGS" ]; then
# If the INSTANCER_ARGS variable is set, use fonttools to create a font instance
fonttools varLib.instancer --output $FONT_INSTANCE $INPUT_FONT_FILE $INSTANCER_ARGS
else
# Otherwise, just copy the input font file to the font instance file
cp $INPUT_FONT_FILE $FONT_INSTANCE
fi
# Use pyftsubset to create a subset of the font instance and save it to the output font file
pyftsubset $FONT_INSTANCE --output-file=$OUTPUT_FONT_FILE --flavor=woff2 $SUBSETTER_ARGS
echo "${OUTPUT_FONT_BASENAME} subsetted."
}
echo ""
echo "###################################################"
echo "# Install required libs"
echo "###################################################"
echo ""
pip install fonttools brotli
echo ""
echo "###################################################"
echo "# Create a partial instance of the variable font"
echo "# where we keep only our needed features and then"
echo "# subset fonts with latin unicode range and export"
echo "# as woff2 file"
echo "###################################################"
echo ""
mkdir -p $TEMP_FOLDER
echo "\nOpen Sans"
# we drop the wdth axis for all
instance_and_subset "${ORIGINAL_FONTS}/OpenSans[wdth,wght].ttf" "wdth=drop wght=400:700" "OpenSans[wght]"
# we restrict the wght range
instance_and_subset "${ORIGINAL_FONTS}/OpenSans[wdth,wght].ttf" "wdth=drop wght=400" "OpenSans-Regular"
instance_and_subset "${ORIGINAL_FONTS}/OpenSans[wdth,wght].ttf" "wdth=drop wght=700" "OpenSans-Bold"
echo "\nOpen Sans Italic"
# we drop the wdth axis for all
instance_and_subset "${ORIGINAL_FONTS}/OpenSans-Italic[wdth,wght].ttf" "wdth=drop wght=400:700" "OpenSans-Italic[wght]"
# we restrict the wght range
instance_and_subset "${ORIGINAL_FONTS}/OpenSans-Italic[wdth,wght].ttf" "wdth=drop wght=400" "OpenSans-RegularItalic"
instance_and_subset "${ORIGINAL_FONTS}/OpenSans-Italic[wdth,wght].ttf" "wdth=drop wght=700" "OpenSans-BoldItalic"
echo "\nQuicksand"
instance_and_subset "${ORIGINAL_FONTS}/Quicksand[wght].ttf" "wght=400:700"
# we restrict the wght range
instance_and_subset "${ORIGINAL_FONTS}/Quicksand[wght].ttf" "wght=400" "Quicksand-Regular"
instance_and_subset "${ORIGINAL_FONTS}/Quicksand[wght].ttf" "wght=600" "Quicksand-SemiBold"
instance_and_subset "${ORIGINAL_FONTS}/Quicksand[wght].ttf" "wght=700" "Quicksand-Bold"
echo "\nSubsetting files complete"
# remove temp folder
rm -r $TEMP_FOLDER

View File

@ -1,16 +0,0 @@
const path = require('path')
const express = require('express')
const app = express()
const p = path.join(__dirname, '..', 'dist-dev')
const port = 4173
app.use(express.static(p))
// Handle urls set by the frontend
app.get('*', (request, response, next) => {
response.sendFile(`${p}/index.html`)
})
app.listen(port, '127.0.0.1', () => {
console.log(`Serving files from ${p}`)
console.log(`Server started on port ${port}`)
})

View File

@ -15,9 +15,8 @@
</template>
<script lang="ts" setup>
import {computed, watch, type Ref} from 'vue'
import {useRouter} from 'vue-router'
import {useRouteQuery} from '@vueuse/router'
import {computed, watch} from 'vue'
import {useRoute, useRouter} from 'vue-router'
import {useI18n} from 'vue-i18n'
import isTouchDevice from 'is-touch-device'
import {success} from '@/message'
@ -41,6 +40,7 @@ import {useAuthStore} from './stores/auth'
const baseStore = useBaseStore()
const authStore = useAuthStore()
const router = useRouter()
const route = useRoute()
useBodyClass('is-touch', isTouchDevice())
const keyboardShortcutsActive = computed(() => baseStore.keyboardShortcutsActive)
@ -51,9 +51,9 @@ const authLinkShare = computed(() => authStore.authLinkShare)
const {t} = useI18n({useScope: 'global'})
// setup account deletion verification
const accountDeletionConfirm = useRouteQuery('accountDeletionConfirm') as Ref<null | string>
const accountDeletionConfirm = computed(() => route.query?.accountDeletionConfirm as (string | undefined))
watch(accountDeletionConfirm, async (accountDeletionConfirm) => {
if (accountDeletionConfirm === null) {
if (accountDeletionConfirm === undefined) {
return
}
@ -64,9 +64,9 @@ watch(accountDeletionConfirm, async (accountDeletionConfirm) => {
}, { immediate: true })
// setup password reset redirect
const userPasswordReset = useRouteQuery('userPasswordReset') as Ref<null | string>
const userPasswordReset = computed(() => route.query?.userPasswordReset as (string | undefined))
watch(userPasswordReset, (userPasswordReset) => {
if (userPasswordReset === null) {
if (userPasswordReset === undefined) {
return
}
@ -75,9 +75,9 @@ watch(userPasswordReset, (userPasswordReset) => {
}, { immediate: true })
// setup email verification redirect
const userEmailConfirm = useRouteQuery('userEmailConfirm') as Ref<null | string>
const userEmailConfirm = computed(() => route.query?.userEmailConfirm as (string | undefined))
watch(userEmailConfirm, (userEmailConfirm) => {
if (userEmailConfirm === null) {
if (userEmailConfirm === undefined) {
return
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,58 @@
<script lang="ts" setup>
import {logEvent} from 'histoire/client'
import {reactive} from 'vue'
import {createRouter, createMemoryHistory} from 'vue-router'
import BaseButton from './BaseButton.vue'
function setupApp({ app }) {
// Router mock
app.use(createRouter({
history: createMemoryHistory(),
routes: [
{ path: '/', name: 'home', component: { render: () => null } },
],
}))
}
const state = reactive({
disabled: false,
})
</script>
<template>
<Story :setup-app="setupApp" :layout="{ type: 'grid', width: '200px' }">
<Variant title="custom">
<template #controls>
<HstCheckbox v-model="state.disabled" title="Disabled" />
</template>
<BaseButton :disabled="state.disabled">
Hello!
</BaseButton>
</Variant>
<Variant title="disabled">
<BaseButton disabled>
Hello!
</BaseButton>
</Variant>
<Variant title="router link">
<BaseButton :to="'home'">
Hello!
</BaseButton>
</Variant>
<Variant title="external link">
<BaseButton href="https://vikunja.io">
Hello!
</BaseButton>
</Variant>
<Variant title="button">
<BaseButton @click="logEvent('Click', $event)">
Hello!
</BaseButton>
</Variant>
</Story>
</template>

View File

@ -61,12 +61,12 @@ export type BaseButtonTypes = typeof BASE_BUTTON_TYPES_MAP[keyof typeof BASE_BUT
import {unrefElement} from '@vueuse/core'
import {ref, type HTMLAttributes} from 'vue'
import type {RouteLocationNamedRaw} from 'vue-router'
import type {RouteLocationRaw} from 'vue-router'
export interface BaseButtonProps extends HTMLAttributes {
type?: BaseButtonTypes
disabled?: boolean
to?: RouteLocationNamedRaw
to?: RouteLocationRaw
href?: string
}

View File

@ -0,0 +1,179 @@
<template>
<transition
name="expandable-slide"
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@enter-cancelled="enterCancelled"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
@leave-cancelled="leaveCancelled"
>
<div
v-if="initialHeight"
class="expandable-initial-height"
:style="{ maxHeight: `${initialHeight}px` }"
:class="{ 'expandable-initial-height--expanded': open }"
>
<slot />
</div>
<div v-else-if="open" class="expandable">
<slot />
</div>
</transition>
</template>
<script setup lang="ts">
// the logic of this component is loosly based on this article
// https://gomakethings.com/how-to-add-transition-animations-to-vanilla-javascript-show-and-hide-methods/#putting-it-all-together
import {computed, ref} from 'vue'
import {getInheritedBackgroundColor} from '@/helpers/getInheritedBackgroundColor'
const props = defineProps({
/** Wheather the Expandable is open or not */
open: {
type: Boolean,
default: false,
},
/** If there is too much content, content will be cut of here. */
initialHeight: {
type: Number,
default: undefined,
},
/** The hidden content is indicated by a gradient. This is the color that the gradient fades to.
* Makes only sense if `initialHeight` is set. */
backgroundColor: {
type: String,
},
})
const wrapper = ref<HTMLElement | null>(null)
const computedBackgroundColor = computed(() => {
if (wrapper.value === null) {
return props.backgroundColor || '#fff'
}
return props.backgroundColor || getInheritedBackgroundColor(wrapper.value)
})
/**
* Get the natural height of the element
*/
function getHeight(el: HTMLElement) {
const { display } = el.style // save display property
el.style.display = 'block' // Make it visible
const height = `${el.scrollHeight}px` // Get its height
el.style.display = display // revert to original display property
return height
}
/**
* force layout of element changes
* https://gist.github.com/paulirish/5d52fb081b3570c81e3a
*/
function forceLayout(el: HTMLElement) {
el.offsetTop
}
/* ######################################################################
# The following functions are called by the js hooks of the transitions.
# They follow the orignal hook order of the vue transition component
# see: https://vuejs.org/guide/built-ins/transition.html#javascript-hooks
###################################################################### */
function beforeEnter(el: HTMLElement) {
el.style.height = '0'
el.style.willChange = 'height'
el.style.backfaceVisibility = 'hidden'
forceLayout(el)
}
// the done callback is optional when
// used in combination with CSS
function enter(el: HTMLElement) {
const height = getHeight(el) // Get the natural height
el.style.height = height // Update the height
}
function afterEnter(el: HTMLElement) {
removeHeight(el)
}
function enterCancelled(el: HTMLElement) {
removeHeight(el)
}
function beforeLeave(el: HTMLElement) {
// Give the element a height to change from
el.style.height = `${el.scrollHeight}px`
forceLayout(el)
}
function leave(el: HTMLElement) {
// Set the height back to 0
el.style.height = '0'
el.style.willChange = ''
el.style.backfaceVisibility = ''
}
function afterLeave(el: HTMLElement) {
removeHeight(el)
}
function leaveCancelled(el: HTMLElement) {
removeHeight(el)
}
function removeHeight(el: HTMLElement) {
el.style.height = ''
}
</script>
<style lang="scss" scoped>
$transition-time: 300ms;
.expandable-slide-enter-active,
.expandable-slide-leave-active {
transition:
opacity $transition-time ease-in-quint,
height $transition-time ease-in-out-quint;
overflow: hidden;
}
.expandable-slide-enter,
.expandable-slide-leave-to {
opacity: 0;
}
.expandable-initial-height {
padding: 5px;
margin: -5px;
overflow: hidden;
position: relative;
&::after {
content: "";
display: block;
background-image: linear-gradient(
to bottom,
transparent,
ease-in-out
v-bind(computedBackgroundColor)
);
position: absolute;
height: 40px;
width: 100%;
bottom: 0;
}
}
.expandable-initial-height--expanded {
height: 100% !important;
&::after {
display: none;
}
}
</style>

View File

@ -110,13 +110,13 @@
</template>
<script lang="ts" setup>
import { formatDate } from '@/helpers/time/formatDate'
import {formatDate} from '@/helpers/time/formatDate'
import BaseButton from '@/components/base/BaseButton.vue'
const exampleDate = formatDate(new Date(), 'yyyy-MM-dd')
</script>
<style scoped>
<style scoped lang="scss">
.how-it-works-modal {
font-size: 1rem;
}

View File

@ -54,8 +54,8 @@
</p>
<modal
@close="() => showHowItWorks = false"
:enabled="showHowItWorks"
@close="() => showHowItWorks = false"
transition-name="fade"
:overflow="true"
variant="hint-modal"

View File

@ -39,7 +39,7 @@
</router-view>
<modal
v-if="currentModal"
:enabled="Boolean(currentModal)"
@close="closeModal()"
variant="scrolling"
class="task-detail-view-modal"
@ -154,41 +154,36 @@ labelStore.loadAllLabels()
@media screen and (max-width: $tablet) {
padding-top: $navbar-height;
}
}
.app-content {
z-index: 10;
position: relative;
padding-top: 1rem;
.app-content {
z-index: 10;
position: relative;
padding: 1.5rem 0.5rem 1rem;
@media screen {
padding: $navbar-height + 1.5rem 1.5rem 1rem 1.5rem;
@media screen and (max-width: $tablet) {
margin-left: 0;
min-height: calc(100vh - 4rem);
}
@media screen and (min-width: $tablet) {
padding: $navbar-height + 1.5rem 1.5rem 1rem 1.5rem;
}
&.is-menu-enabled {
@media screen and (min-width: $tablet) {
margin-left: $navbar-width;
}
}
// Used to make sure the spinner is always in the middle while loading
> .loader-container {
min-height: calc(100vh - #{$navbar-height + 1.5rem + 1rem});
}
// Used to make sure the spinner is always in the middle while loading
> .loader-container {
min-height: calc(100vh - #{$navbar-height + 1.5rem + 1rem});
}
@media screen and (max-width: $tablet) {
margin-left: 0;
padding-top: 1.5rem;
min-height: calc(100vh - 4rem);
}
@media screen {
&.is-menu-enabled {
margin-left: $navbar-width;
@media screen and (max-width: $tablet) {
min-width: 100%;
margin-left: 0;
}
}
}
.card {
background: var(--white);
}
// FIXME: This should be somehow defined inside Card.vue
.card {
background: var(--white);
}
}
@ -235,6 +230,4 @@ labelStore.loadAllLabels()
.content-auth.z-unset {
z-index: unset;
}
@include modal-transition();
</style>

View File

@ -7,7 +7,7 @@
<ul class="menu-list">
<li>
<router-link :to="{ name: 'home'}" v-shortcut="'g o'">
<span class="icon">
<span class="menu-item-icon icon">
<icon icon="calendar"/>
</span>
{{ $t('navigation.overview') }}
@ -15,7 +15,7 @@
</li>
<li>
<router-link :to="{ name: 'tasks.range'}" v-shortcut="'g u'">
<span class="icon">
<span class="menu-item-icon icon">
<icon :icon="['far', 'calendar-alt']"/>
</span>
{{ $t('navigation.upcoming') }}
@ -23,7 +23,7 @@
</li>
<li>
<router-link :to="{ name: 'namespaces.index'}" v-shortcut="'g n'">
<span class="icon">
<span class="menu-item-icon icon">
<icon icon="layer-group"/>
</span>
{{ $t('namespace.title') }}
@ -31,7 +31,7 @@
</li>
<li>
<router-link :to="{ name: 'labels.index'}" v-shortcut="'g a'">
<span class="icon">
<span class="menu-item-icon icon">
<icon icon="tags"/>
</span>
{{ $t('label.title') }}
@ -39,7 +39,7 @@
</li>
<li>
<router-link :to="{ name: 'teams.index'}" v-shortcut="'g m'">
<span class="icon">
<span class="menu-item-icon icon">
<icon icon="users"/>
</span>
{{ $t('team.title') }}
@ -63,7 +63,7 @@
/>
<span class="name">{{ namespaceTitles[nk] }}</span>
<div
class="icon is-small toggle-lists-icon pl-2"
class="icon menu-item-icon is-small toggle-lists-icon pl-2"
:class="{'active': typeof listsVisible[n.id] !== 'undefined' ? listsVisible[n.id] : true}"
>
<icon icon="chevron-down"/>
@ -72,7 +72,7 @@
({{ namespaceListsCount[nk] }})
</span>
</BaseButton>
<namespace-settings-dropdown :namespace="n" v-if="n.id > 0"/>
<namespace-settings-dropdown class="menu-list-dropdown" :namespace="n" v-if="n.id > 0"/>
</div>
<!--
NOTE: a v-model / computed setter is not possible, since the updateActiveLists function
@ -111,11 +111,11 @@
class="list-menu-link"
:class="{'router-link-exact-active': currentList.id === l.id}"
>
<span class="icon handle">
<span class="icon menu-item-icon handle">
<icon icon="grip-lines"/>
</span>
<ColorBubble
v-if="l.hexColor !== ''"
v-if="l.hexColor !== ''"
:color="l.hexColor"
class="mr-1"
/>
@ -128,7 +128,13 @@
>
<icon :icon="l.isFavorite ? 'star' : ['far', 'star']"/>
</BaseButton>
<list-settings-dropdown :list="l" v-if="l.id > 0"/>
<list-settings-dropdown class="menu-list-dropdown" :list="l" v-if="l.id > 0">
<template #trigger="{toggleOpen}">
<BaseButton class="menu-list-dropdown-trigger" @click="toggleOpen">
<icon icon="ellipsis-h" class="icon"/>
</BaseButton>
</template>
</list-settings-dropdown>
<span class="list-setting-spacer" v-else></span>
</li>
</template>
@ -280,6 +286,18 @@ $vikunja-nav-background: var(--site-background);
$vikunja-nav-color: var(--grey-700);
$vikunja-nav-selected-width: 0.4rem;
.logo {
display: block;
padding-left: 1rem;
margin-right: 1rem;
margin-bottom: 1rem;
@media screen and (min-width: $tablet) {
display: none;
}
}
.namespace-container {
background: $vikunja-nav-background;
color: $vikunja-nav-color;
@ -303,248 +321,228 @@ $vikunja-nav-selected-width: 0.4rem;
transform: translateX(0);
transition: transform $transition-duration ease-out;
}
}
.menu {
.menu-label {
font-size: 1rem;
font-weight: 700;
font-weight: bold;
font-family: $vikunja-font;
color: $vikunja-nav-color;
font-weight: 500;
min-height: 2.5rem;
padding-top: 0;
padding-left: $navbar-padding;
// these are general menu styles
// should be in own components
.menu {
.menu-label,
.menu-list .list-menu-link,
.menu-list a {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
overflow: hidden;
}
.menu-label,
.menu-list .list-menu-link,
.menu-list a {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
.list-menu-title {
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
.color-bubble {
height: 12px;
flex: 0 0 12px;
}
}
.favorite {
margin-left: .25rem;
transition: opacity $transition, color $transition;
opacity: 0;
&:hover,
&.is-favorite {
color: var(--warning);
}
}
.favorite.is-favorite,
.list-menu:hover .favorite {
opacity: 1;
}
.menu-label {
.color-bubble {
width: 14px;
height: 14px;
flex-basis: auto;
}
.is-archived {
min-width: 85px;
}
}
.namespace-title {
display: flex;
align-items: center;
justify-content: space-between;
color: $vikunja-nav-color;
padding: 0 .25rem;
.menu-label {
margin-bottom: 0;
flex: 1 1 auto;
.name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: auto;
}
.count {
color: var(--grey-500);
margin-right: .5rem;
}
}
:deep(.dropdown-trigger) {
padding: .5rem;
cursor: pointer;
}
.toggle-lists-icon {
svg {
transition: all $transition;
transform: rotate(90deg);
opacity: 1;
}
&.active svg {
transform: rotate(0deg);
opacity: 0;
}
}
&:hover .toggle-lists-icon svg {
opacity: 1;
}
&:not(.has-menu) .toggle-lists-icon {
padding-right: 1rem;
}
}
.menu-label,
.nsettings,
.menu-list .list-menu-link,
.menu-list a {
color: $vikunja-nav-color;
}
.menu-list {
li {
height: 44px;
display: flex;
align-items: center;
&:hover {
background: var(--white);
}
:deep(.dropdown-trigger) {
opacity: 0;
padding: .5rem;
cursor: pointer;
transition: $transition;
}
&:hover :deep(.dropdown-trigger) {
opacity: 1;
}
}
.flip-list-move {
transition: transform $transition-duration;
}
.ghost {
background: var(--grey-200);
* {
opacity: 0;
}
}
a:hover {
background: transparent;
}
.list-menu-link, li > a {
padding: 0.75rem .5rem 0.75rem ($navbar-padding * 1.5 - 1.75rem);
transition: all 0.2s ease;
border-radius: 0;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 100%;
border-left: $vikunja-nav-selected-width solid transparent;
.icon {
height: 1rem;
vertical-align: middle;
padding-right: 0.5rem;
&.handle {
opacity: 0;
transition: opacity $transition;
margin-right: .25rem;
cursor: grab;
}
}
&:hover .icon.handle {
opacity: 1;
}
&.router-link-exact-active {
color: var(--primary);
border-left: $vikunja-nav-selected-width solid var(--primary);
.icon {
color: var(--primary);
}
}
&:hover {
border-left: $vikunja-nav-selected-width solid var(--primary);
}
}
}
.logo {
display: block;
padding-left: 1rem;
margin-right: 1rem;
margin-bottom: 1rem;
@media screen and (min-width: $tablet) {
display: none;
}
}
&.namespaces-lists {
padding-top: math.div($navbar-padding, 2);
}
.icon {
color: var(--grey-400) !important;
.color-bubble {
height: 12px;
flex: 0 0 12px;
}
}
.top-menu {
margin-top: math.div($navbar-padding, 2);
.menu-list {
li {
height: 44px;
display: flex;
align-items: center;
.menu-list {
li {
font-weight: 500;
font-family: $vikunja-font;
&:hover {
background: var(--white);
}
.list-menu-link, li > a {
padding-left: 2rem;
display: inline-block;
.menu-list-dropdown {
opacity: 0;
transition: $transition;
}
.icon {
padding-bottom: .25rem;
}
&:hover .menu-list-dropdown {
opacity: 1;
}
}
.menu-item-icon {
color: var(--grey-400);
}
.menu-list-dropdown-trigger {
display: flex;
padding: 0.5rem;
}
.flip-list-move {
transition: transform $transition-duration;
}
.ghost {
background: var(--grey-200);
* {
opacity: 0;
}
}
a:hover {
background: transparent;
}
.list-menu-link,
li > a {
color: $vikunja-nav-color;
padding: 0.75rem .5rem 0.75rem ($navbar-padding * 1.5 - 1.75rem);
transition: all 0.2s ease;
border-radius: 0;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 100%;
border-left: $vikunja-nav-selected-width solid transparent;
&:hover {
border-left: $vikunja-nav-selected-width solid var(--primary);
}
&.router-link-exact-active {
color: var(--primary);
border-left: $vikunja-nav-selected-width solid var(--primary);
}
.icon {
height: 1rem;
vertical-align: middle;
padding-right: 0.5rem;
}
&.router-link-exact-active .icon:not(.handle) {
color: var(--primary);
}
.handle {
opacity: 0;
transition: opacity $transition;
margin-right: .25rem;
cursor: grab;
}
&:hover .handle {
opacity: 1;
}
}
}
}
.top-menu {
margin-top: math.div($navbar-padding, 2);
.menu-list {
li {
font-weight: 600;
font-family: $vikunja-font;
}
.list-menu-link,
li > a {
padding-left: 2rem;
display: inline-block;
.icon {
padding-bottom: .25rem;
}
}
}
}
.namespaces-lists {
padding-top: math.div($navbar-padding, 2);
.menu-label {
font-size: 1rem;
font-weight: 700;
font-weight: bold;
font-family: $vikunja-font;
color: $vikunja-nav-color;
font-weight: 600;
min-height: 2.5rem;
padding-top: 0;
padding-left: $navbar-padding;
overflow: hidden;
margin-bottom: 0;
flex: 1 1 auto;
.name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: auto;
}
.count {
color: var(--grey-500);
margin-right: .5rem;
// align brackets with number
font-feature-settings: "case";
}
}
.favorite {
margin-left: .25rem;
transition: opacity $transition, color $transition;
opacity: 0;
&:hover,
&.is-favorite {
color: var(--warning);
}
}
.favorite.is-favorite,
.list-menu:hover .favorite {
opacity: 1;
}
.list-menu-title {
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
.color-bubble {
width: 14px;
height: 14px;
flex-basis: auto;
}
.is-archived {
min-width: 85px;
}
}
.namespace-title {
display: flex;
align-items: center;
justify-content: space-between;
color: $vikunja-nav-color;
padding: 0 .25rem;
.toggle-lists-icon {
svg {
transition: all $transition;
transform: rotate(90deg);
opacity: 1;
}
&.active svg {
transform: rotate(0deg);
opacity: 0;
}
}
&:hover .toggle-lists-icon svg {
opacity: 1;
}
&:not(.has-menu) .toggle-lists-icon {
padding-right: 1rem;
}
}

View File

@ -0,0 +1,26 @@
<script lang="ts" setup>
import {logEvent} from 'histoire/client'
import XButton from './button.vue'
</script>
<template>
<Story :layout="{ type: 'grid', width: '200px' }">
<Variant title="primary">
<XButton @click="logEvent('Click', $event)" variant="primary">
Order pizza!
</XButton>
</Variant>
<Variant title="secondary">
<XButton @click="logEvent('Click', $event)" variant="secondary">
Order spaghetti!
</XButton>
</Variant>
<Variant title="tertiary">
<XButton @click="logEvent('Click', $event)" variant="tertiary">
Order tortellini!
</XButton>
</Variant>
</Story>
</template>

View File

@ -0,0 +1,14 @@
<script lang="ts" setup>
import {reactive} from 'vue'
import ColorPicker from './ColorPicker.vue'
const state = reactive({
color: '#f2f2f2',
})
</script>
<template>
<Story :layout="{ type: 'grid', width: '200px' }">
<ColorPicker v-model="state.color" />
</Story>
</template>

View File

@ -37,6 +37,7 @@
<script setup lang="ts">
import {computed, ref, toRef, watch} from 'vue'
import {createRandomID} from '@/helpers/randomId'
import XButton from '@/components/input/button.vue'
const DEFAULT_COLORS = [
'#1973ff',

View File

@ -0,0 +1,63 @@
<template>
<multiselect
v-model="selectedLists"
:search-results="foundLists"
:loading="listService.loading"
:multiple="true"
:placeholder="$t('list.search')"
label="title"
@search="findLists"
/>
</template>
<script setup lang="ts">
import {computed, ref, shallowReactive, watchEffect, type PropType} from 'vue'
import Multiselect from '@/components/input/multiselect.vue'
import type {IList} from '@/modelTypes/IList'
import ListService from '@/services/list'
import {includesById} from '@/helpers/utils'
const props = defineProps({
modelValue: {
type: Array as PropType<IList[]>,
default: () => [],
},
})
const emit = defineEmits<{
(e: 'update:modelValue', value: IList[]): void
}>()
const lists = ref<IList[]>([])
watchEffect(() => {
lists.value = props.modelValue
})
const selectedLists = computed({
get() {
return lists.value
},
set: (value) => {
lists.value = value
emit('update:modelValue', value)
},
})
const listService = shallowReactive(new ListService())
const foundLists = ref<IList[]>([])
async function findLists(query: string) {
if (query === '') {
foundLists.value = []
return
}
const response = await listService.getAll({}, {s: query}) as IList[]
// Filter selected items from the results
foundLists.value = response.filter(({id}) => !includesById(lists.value, id))
}
</script>

View File

@ -0,0 +1,63 @@
<template>
<multiselect
v-model="selectedNamespaces"
:search-results="foundNamespaces"
:loading="namespaceService.loading"
:multiple="true"
:placeholder="$t('namespace.search')"
label="namespace"
@search="findNamespaces"
/>
</template>
<script setup lang="ts">
import {computed, ref, shallowReactive, watchEffect, type PropType} from 'vue'
import Multiselect from '@/components/input/multiselect.vue'
import type {INamespace} from '@/modelTypes/INamespace'
import NamespaceService from '@/services/namespace'
import {includesById} from '@/helpers/utils'
const props = defineProps({
modelValue: {
type: Array as PropType<INamespace[]>,
default: () => [],
},
})
const emit = defineEmits<{
(e: 'update:modelValue', value: INamespace[]): void
}>()
const namespaces = ref<INamespace[]>([])
watchEffect(() => {
namespaces.value = props.modelValue
})
const selectedNamespaces = computed({
get() {
return namespaces.value
},
set: (value) => {
namespaces.value = value
emit('update:modelValue', value)
},
})
const namespaceService = shallowReactive(new NamespaceService())
const foundNamespaces = ref<INamespace[]>([])
async function findNamespaces(query: string) {
if (query === '') {
foundNamespaces.value = []
return
}
const response = await namespaceService.getAll({}, {s: query}) as INamespace[]
// Filter selected items from the results
foundNamespaces.value = response.filter(({id}) => !includesById(namespaces.value, id))
}
</script>

View File

@ -0,0 +1,63 @@
<template>
<multiselect
v-model="selectedUsers"
:search-results="foundUsers"
:loading="userService.loading"
:multiple="true"
:placeholder="$t('team.edit.search')"
label="username"
@search="findUsers"
/>
</template>
<script setup lang="ts">
import {computed, ref, shallowReactive, watchEffect, type PropType} from 'vue'
import Multiselect from '@/components/input/multiselect.vue'
import type {IUser} from '@/modelTypes/IUser'
import UserService from '@/services/user'
import {includesById} from '@/helpers/utils'
const props = defineProps({
modelValue: {
type: Array as PropType<IUser[]>,
default: () => [],
},
})
const emit = defineEmits<{
(e: 'update:modelValue', value: IUser[]): void
}>()
const users = ref<IUser[]>([])
watchEffect(() => {
users.value = props.modelValue
})
const selectedUsers = computed({
get() {
return users.value
},
set: (value) => {
users.value = value
emit('update:modelValue', value)
},
})
const userService = shallowReactive(new UserService())
const foundUsers = ref<IUser[]>([])
async function findUsers(query: string) {
if (query === '') {
foundUsers.value = []
return
}
const response = await userService.getAll({}, {s: query}) as IUser[]
// Filter selected items from the results
foundUsers.value = response.filter(({id}) => !includesById(users.value, id))
}
</script>

View File

@ -4,7 +4,7 @@
{{ date === null ? chooseDateLabel : formatDateShort(date) }}
</BaseButton>
<transition name="fade">
<CustomTransition name="fade">
<div v-if="show" class="datepicker-popup" ref="datepickerPopup">
<BaseButton
@ -84,7 +84,7 @@
{{ $t('misc.confirm') }}
</x-button>
</div>
</transition>
</CustomTransition>
</div>
</template>
@ -94,6 +94,7 @@ import flatPickr from 'vue-flatpickr-component'
import 'flatpickr/dist/flatpickr.css'
import BaseButton from '@/components/base/BaseButton.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import {formatDate, formatDateShort} from '@/helpers/time/formatDate'
import {calculateDayInterval} from '@/helpers/time/calculateDayInterval'

View File

@ -9,6 +9,7 @@ export function createEasyMDEConfig({ placeholder, uploadImage, imageUploadFunct
uploadImage,
imageUploadFunction,
minHeight: '150px',
sideBySideFullscreen: false,
toolbar: [
{
name: 'heading-1',

View File

@ -9,7 +9,8 @@
<div class="control" :class="{'is-loading': loading || localLoading}">
<div
class="input-wrapper input"
:class="{'has-multiple': hasMultiple}">
:class="{'has-multiple': hasMultiple}"
>
<template v-if="Array.isArray(internalValue)">
<template v-for="(item, key) in internalValue">
<slot name="tag" :item="item">
@ -35,10 +36,10 @@
</div>
</div>
<transition name="fade">
<CustomTransition name="fade">
<div class="search-results" :class="{'search-results-inline': inline}" v-if="searchResultsVisible">
<BaseButton
class="is-fullwidth"
class="search-result-button is-fullwidth"
v-for="(data, index) in filteredSearchResults"
:key="index"
:ref="(el) => setResult(el, index)"
@ -58,7 +59,7 @@
<BaseButton
v-if="creatableAvailable"
class="is-fullwidth"
class="search-result-button is-fullwidth"
:ref="(el) => setResult(el, filteredSearchResults.length)"
@keydown.up.prevent="() => preSelect(filteredSearchResults.length - 1)"
@keydown.down.prevent="() => preSelect(filteredSearchResults.length + 1)"
@ -77,8 +78,7 @@
</span>
</BaseButton>
</div>
</transition>
</CustomTransition>
</div>
</template>
@ -89,6 +89,7 @@ import {useI18n} from 'vue-i18n'
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
import BaseButton from '@/components/base/BaseButton.vue'
import CustomTransition from '@/components/misc/CustomTransition.vue'
function elementInResults(elem: string | any, label: string, query: string): boolean {
// Don't make create available if we have an exact match in our search results.
@ -434,122 +435,125 @@ function focus() {
.control.is-loading::after {
top: .75rem;
}
}
&.has-search-results .input-wrapper {
border-radius: $radius $radius 0 0;
border-color: var(--primary) !important;
background: var(--white) !important;
.input-wrapper {
padding: 0;
background: var(--white);
border-color: var(--grey-200);
flex-wrap: wrap;
height: auto;
&, &:focus-within {
border-bottom-color: var(--grey-200) !important;
}
&:hover {
border-color: var(--grey-300) !important;
}
.input-wrapper {
padding: 0;
background: var(--white);
border-color: var(--grey-200);
flex-wrap: wrap;
.input {
display: flex;
max-width: 100%;
width: 100%;
align-items: center;
border: none !important;
background: transparent;
height: auto;
&:hover {
border-color: var(--grey-300) !important;
}
.input {
display: flex;
max-width: 100%;
width: 100%;
align-items: center;
border: none !important;
background: transparent;
height: auto;
&::placeholder {
font-style: normal !important;
}
}
&.has-multiple .input {
max-width: 250px;
input {
padding-left: 0;
}
}
&:focus-within {
border-color: var(--primary) !important;
background: var(--white) !important;
}
.loader {
margin: 0 .5rem;
&::placeholder {
font-style: normal !important;
}
}
.search-results {
background: var(--white);
border-radius: 0 0 $radius $radius;
border: 1px solid var(--primary);
border-top: none;
&.has-multiple .input {
max-width: 250px;
max-height: 50vh;
overflow-x: auto;
position: absolute;
z-index: 100;
max-width: 100%;
min-width: 100%;
&-inline {
position: static;
input {
padding-left: 0;
}
}
button {
background: transparent;
text-align: left;
box-shadow: none;
border-radius: 0;
text-transform: none;
font-family: $family-sans-serif;
font-weight: normal;
padding: .5rem;
border: none;
cursor: pointer;
color: var(--grey-800);
&:focus-within {
border-color: var(--primary) !important;
background: var(--white) !important;
}
display: flex;
justify-content: space-between;
align-items: center;
overflow: hidden;
.search-result {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
padding: .5rem .75rem;
}
.hint-text {
font-size: .75rem;
color: transparent;
transition: color $transition;
padding-left: .5rem;
}
&:focus, &:hover {
background: var(--grey-100);
box-shadow: none !important;
.hint-text {
color: var(--text);
}
}
&:active {
background: var(--grey-200);
}
}
// doesn't seem to be used. maybe inside the slot?
.loader {
margin: 0 .5rem;
}
}
.has-search-results .input-wrapper {
border-radius: $radius $radius 0 0;
border-color: var(--primary) !important;
background: var(--white) !important;
&, &:focus-within {
border-bottom-color: var(--grey-200) !important;
}
}
.search-results {
background: var(--white);
border-radius: 0 0 $radius $radius;
border: 1px solid var(--primary);
border-top: none;
max-height: 50vh;
overflow-x: auto;
position: absolute;
z-index: 100;
max-width: 100%;
min-width: 100%;
}
.search-results-inline {
position: static;
}
.search-result-button {
background: transparent;
text-align: left;
box-shadow: none;
border-radius: 0;
text-transform: none;
font-family: $family-sans-serif;
font-weight: normal;
padding: .5rem;
border: none;
cursor: pointer;
color: var(--grey-800);
display: flex;
justify-content: space-between;
align-items: center;
overflow: hidden;
&:focus,
&:hover {
background: var(--grey-100);
box-shadow: none !important;
.hint-text {
color: var(--text);
}
}
&:active {
background: var(--grey-200);
}
}
.search-result {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
padding: .5rem .75rem;
}
.hint-text {
font-size: .75rem;
color: transparent;
transition: color $transition;
padding-left: .5rem;
}
</style>

View File

@ -5,42 +5,50 @@
>
<div class="switch-view-container">
<div class="switch-view">
<router-link
<BaseButton
v-shortcut="'g l'"
:title="$t('keyboardShortcuts.list.switchToListView')"
class="switch-view-button"
:class="{'is-active': viewName === 'list'}"
:to="{ name: 'list.list', params: { listId } }">
:to="{ name: 'list.list', params: { listId } }"
>
{{ $t('list.list.title') }}
</router-link>
<router-link
</BaseButton>
<BaseButton
v-shortcut="'g g'"
:title="$t('keyboardShortcuts.list.switchToGanttView')"
class="switch-view-button"
:class="{'is-active': viewName === 'gantt'}"
:to="{ name: 'list.gantt', params: { listId } }">
:to="{ name: 'list.gantt', params: { listId } }"
>
{{ $t('list.gantt.title') }}
</router-link>
<router-link
</BaseButton>
<BaseButton
v-shortcut="'g t'"
:title="$t('keyboardShortcuts.list.switchToTableView')"
class="switch-view-button"
:class="{'is-active': viewName === 'table'}"
:to="{ name: 'list.table', params: { listId } }">
:to="{ name: 'list.table', params: { listId } }"
>
{{ $t('list.table.title') }}
</router-link>
<router-link
</BaseButton>
<BaseButton
v-shortcut="'g k'"
:title="$t('keyboardShortcuts.list.switchToKanbanView')"
class="switch-view-button"
:class="{'is-active': viewName === 'kanban'}"
:to="{ name: 'list.kanban', params: { listId } }">
:to="{ name: 'list.kanban', params: { listId } }"
>
{{ $t('list.kanban.title') }}
</router-link>
</BaseButton>
</div>
<slot name="header" />
</div>
<transition name="fade">
<CustomTransition name="fade">
<Message variant="warning" v-if="currentList.isArchived" class="mb-4">
{{ $t('list.archived') }}
</Message>
</transition>
</CustomTransition>
<slot v-if="loadedListId"/>
</div>
@ -50,7 +58,9 @@
import {ref, computed, watch} 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 ListModel from '@/models/list'
import ListService from '@/services/list'
@ -131,7 +141,7 @@ watch(
const list = new ListModel(listData)
try {
const loadedList = await listService.value.get(list)
await baseStore.handleSetCurrentList({list: loadedList})
baseStore.handleSetCurrentList({list: loadedList})
} finally {
loadedListId.value = props.listId
}
@ -158,35 +168,32 @@ watch(
height: $switch-view-height;
margin: 0 auto 1rem;
padding: .5rem;
a {
padding: .25rem .5rem;
display: block;
border-radius: $radius;
transition: all 100ms;
&:not(:last-child) {
margin-right: .5rem;
}
&.is-active,
&:hover {
color: var(--switch-view-color);
}
&.is-active {
background: var(--primary);
font-weight: bold;
box-shadow: var(--shadow-xs);
}
&:hover {
background: var(--primary);
}
}
}
.switch-view-button {
padding: .25rem .5rem;
display: block;
border-radius: $radius;
transition: all 100ms;
&:not(:last-child) {
margin-right: .5rem;
}
&:hover {
color: var(--switch-view-color);
background: var(--primary);
}
&.is-active {
color: var(--switch-view-color);
background: var(--primary);
font-weight: bold;
box-shadow: var(--shadow-xs);
}
}
// FIXME: this should be in notification and set via a prop
.is-archived .notification.is-warning {
margin-bottom: 1rem;
}

View File

@ -1,5 +1,13 @@
<template>
<dropdown>
<template #trigger="triggerProps">
<slot name="trigger" v-bind="triggerProps">
<BaseButton class="dropdown-trigger" @click="triggerProps.toggleOpen">
<icon icon="ellipsis-h" class="icon"/>
</BaseButton>
</slot>
</template>
<template v-if="isSavedFilter(list)">
<dropdown-item
:to="{ name: 'filter.settings.edit', params: { listId: list.id } }"
@ -78,6 +86,7 @@
<script setup lang="ts">
import {ref, computed, watchEffect, type PropType} from 'vue'
import BaseButton from '@/components/base/BaseButton.vue'
import Dropdown from '@/components/misc/dropdown.vue'
import DropdownItem from '@/components/misc/dropdown-item.vue'
import Subscription from '@/components/misc/subscription.vue'
@ -115,4 +124,4 @@ function setSubscriptionInStore(sub: ISubscription) {
listStore.setList(updatedList)
namespaceStore.setListInNamespaceById(updatedList)
}
</script>
</script>

View File

@ -0,0 +1,176 @@
<template>
<div
class="list-card"
:class="{
'has-light-text': background !== null,
'has-background': blurHashUrl !== '' || background !== null
}"
:style="{
'border-left': list.hexColor ? `0.25rem solid ${list.hexColor}` : undefined,
'background-image': blurHashUrl !== '' ? `url(${blurHashUrl})` : undefined,
}"
>
<div
class="list-background background-fade-in"
:class="{'is-visible': background}"
:style="{'background-image': background !== null ? `url(${background})` : undefined}"
/>
<span v-if="list.isArchived" class="is-archived" >{{ $t('namespace.archived') }}</span>
<div class="list-title" aria-hidden="true">{{ list.title }}</div>
<BaseButton
class="list-button"
:aria-label="list.title"
:title="list.description"
:to="{
name: 'list.index',
params: { listId: list.id}
}"
/>
<BaseButton
v-if="!list.isArchived"
class="favorite"
:class="{'is-favorite': list.isFavorite}"
@click.prevent.stop="listStore.toggleListFavorite(list)"
>
<icon :icon="list.isFavorite ? 'star' : ['far', 'star']" />
</BaseButton>
</div>
</template>
<script lang="ts" setup>
import {toRef, type PropType} from 'vue'
import type {IList} from '@/modelTypes/IList'
import BaseButton from '@/components/base/BaseButton.vue'
import {useListBackground} from './useListBackground'
import {useListStore} from '@/stores/lists'
const props = defineProps({
list: {
type: Object as PropType<IList>,
required: true,
},
})
const {background, blurHashUrl} = useListBackground(toRef(props, 'list'))
const listStore = useListStore()
</script>
<style lang="scss" scoped>
.list-card {
--list-card-padding: 1rem;
background: var(--white);
padding: var(--list-card-padding);
border-radius: $radius;
box-shadow: var(--shadow-sm);
transition: box-shadow $transition;
position: relative;
overflow: hidden; // hide background
display: flex;
justify-content: space-between;
flex-wrap: wrap;
&:hover {
box-shadow: var(--shadow-md);
}
&:active,
&:focus {
box-shadow: var(--shadow-xs) !important;
}
> * {
// so the elements are on top of the background
position: relative;
}
}
.has-background,
.list-background {
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.list-background,
.list-button {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.is-archived {
font-size: .75rem;
float: left;
}
.list-title {
align-self: flex-end;
font-family: $vikunja-font;
font-weight: 400;
font-size: 1.5rem;
line-height: var(--title-line-height);
color: var(--text);
width: 100%;
margin-bottom: 0;
max-height: calc(100% - (var(--list-card-padding) + 1rem)); // padding & height of the "is archived" badge
overflow: hidden;
text-overflow: ellipsis;
word-break: break-word;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
.has-light-text .list-title {
color: var(--grey-100);
}
.has-background .list-title {
text-shadow:
0 0 10px var(--black),
1px 1px 5px var(--grey-700),
-1px -1px 5px var(--grey-700);
color: var(--white);
}
.favorite {
position: absolute;
top: var(--list-card-padding);
right: var(--list-card-padding);
transition: opacity $transition, color $transition;
opacity: 0;
&:hover {
color: var(--warning);
}
&.is-favorite {
display: inline-block;
opacity: 1;
color: var(--warning);
}
}
.list-card:hover .favorite {
opacity: 1;
}
.background-fade-in {
opacity: 0;
transition: opacity $transition;
transition-delay: $transition-duration * 2; // To fake an appearing background
&.is-visible {
opacity: 1;
}
}
</style>

View File

@ -0,0 +1,77 @@
<template>
<ul class="list-grid">
<li
v-for="(item, index) in filteredLists"
:key="`list_${item.id}_${index}`"
class="list-grid-item"
>
<ListCard :list="item" />
</li>
</ul>
</template>
<script lang="ts" setup>
import {computed, type PropType} from 'vue'
import type {IList} from '@/modelTypes/IList'
import ListCard from './ListCard.vue'
const props = defineProps({
lists: {
type: Array as PropType<IList[]>,
default: () => [],
},
showArchived: {
default: false,
type: Boolean,
},
itemLimit: {
type: Boolean,
default: false,
},
})
const filteredLists = computed(() => {
return props.showArchived
? props.lists
: props.lists.filter(l => !l.isArchived)
})
</script>
<style lang="scss" scoped>
$list-height: 150px;
$list-spacing: 1rem;
.list-grid {
margin: 0; // reset li
list-style-type: none;
display: grid;
grid-template-columns: repeat(var(--list-columns), 1fr);
grid-auto-rows: $list-height;
gap: $list-spacing;
@media screen and (min-width: $mobile) {
--list-rows: 4;
--list-columns: 1;
}
@media screen and (min-width: $mobile) and (max-width: $tablet) {
--list-columns: 2;
}
@media screen and (min-width: $tablet) and (max-width: $widescreen) {
--list-columns: 3;
--list-rows: 3;
}
@media screen and (min-width: $widescreen) {
--list-columns: 5;
--list-rows: 2;
}
}
.list-grid-item {
display: grid;
margin-top: 0; // remove padding coming form .content li + li
}
</style>

View File

@ -14,11 +14,11 @@
{{ $t('filters.title') }}
</x-button>
<modal
@close="() => modalOpen = false"
:enabled="modalOpen"
transition-name="fade"
:overflow="true"
variant="hint-modal"
@close="() => modalOpen = false"
>
<filters
:has-title="true"

View File

@ -13,11 +13,14 @@
>
{{ $t('filters.attributes.requireAll') }}
</fancycheckbox>
<fancycheckbox v-model="filters.done" @update:model-value="setDoneFilter">
<fancycheckbox
v-model="filters.done"
@update:model-value="setDoneFilter"
>
{{ $t('filters.attributes.showDoneTasks') }}
</fancycheckbox>
<fancycheckbox
v-if="!$route.name.includes('list.kanban') || !$route.name.includes('list.table')"
v-if="!['list.kanban', 'list.table'].includes($route.name as string)"
v-model="sortAlphabetically"
@update:model-value="change()"
>
@ -40,9 +43,9 @@
<label class="label">{{ $t('task.attributes.priority') }}</label>
<div class="control single-value-control">
<priority-select
:disabled="!filters.usePriority || undefined"
v-model.number="filters.priority"
@update:model-value="setPriority"
:disabled="!filters.usePriority || undefined"
/>
<fancycheckbox
v-model="filters.usePriority"
@ -132,16 +135,10 @@
<div class="field">
<label class="label">{{ $t('task.attributes.assignees') }}</label>
<div class="control">
<multiselect
:loading="usersService.loading"
:placeholder="$t('team.edit.search')"
@search="query => find('users', query)"
:search-results="foundusers"
@select="() => add('users', 'assignees')"
label="username"
:multiple="true"
@remove="() => remove('users', 'assignees')"
v-model="users"
<SelectUser
v-model="entities.users"
@select="changeMultiselectFilter('users', 'assignees')"
@remove="changeMultiselectFilter('users', 'assignees')"
/>
</div>
</div>
@ -149,41 +146,32 @@
<div class="field">
<label class="label">{{ $t('task.attributes.labels') }}</label>
<div class="control labels-list">
<edit-labels v-model="labels" @update:model-value="changeLabelFilter"/>
<edit-labels
v-model="entities.labels"
@update:model-value="changeLabelFilter"
/>
</div>
</div>
<template
v-if="$route.name === 'filters.create' || $route.name === 'list.edit' || $route.name === 'filter.settings.edit'">
v-if="['filters.create', 'list.edit', 'filter.settings.edit'].includes($route.name as string)">
<div class="field">
<label class="label">{{ $t('list.lists') }}</label>
<div class="control">
<multiselect
:loading="listsService.loading"
:placeholder="$t('list.search')"
@search="query => find('lists', query)"
:search-results="foundlists"
@select="() => add('lists', 'list_id')"
label="title"
@remove="() => remove('lists', 'list_id')"
:multiple="true"
v-model="lists"
<SelectList
v-model="entities.lists"
@select="changeMultiselectFilter('lists', 'list_id')"
@remove="changeMultiselectFilter('lists', 'list_id')"
/>
</div>
</div>
<div class="field">
<label class="label">{{ $t('namespace.namespaces') }}</label>
<div class="control">
<multiselect
:loading="namespaceService.loading"
:placeholder="$t('namespace.search')"
@search="query => find('namespace', query)"
:search-results="foundnamespace"
@select="() => add('namespace', 'namespace')"
label="title"
@remove="() => remove('namespace', 'namespace')"
:multiple="true"
v-model="namespace"
<SelectNamespace
v-model="entities.namespace"
@select="changeMultiselectFilter('namespace', 'namespace')"
@remove="changeMultiselectFilter('namespace', 'namespace')"
/>
</div>
</div>
@ -192,28 +180,39 @@
</template>
<script lang="ts">
import {defineComponent} from 'vue'
export const ALPHABETICAL_SORT = 'title'
</script>
<script setup lang="ts">
import {computed, nextTick, onMounted, reactive, ref, shallowReactive, toRefs, watch} from 'vue'
import {camelCase} from 'camel-case'
import type {ILabel} from '@/modelTypes/ILabel'
import type {IUser} from '@/modelTypes/IUser'
import type {INamespace} from '@/modelTypes/INamespace'
import type {IList} from '@/modelTypes/IList'
import {useLabelStore} from '@/stores/labels'
import DatepickerWithRange from '@/components/date/datepickerWithRange.vue'
import Fancycheckbox from '@/components/input/fancycheckbox.vue'
import {includesById} from '@/helpers/utils'
import PrioritySelect from '@/components/tasks/partials/prioritySelect.vue'
import PercentDoneSelect from '@/components/tasks/partials/percentDoneSelect.vue'
import Multiselect from '@/components/input/multiselect.vue'
import EditLabels from '@/components/tasks/partials/editLabels.vue'
import Fancycheckbox from '@/components/input/fancycheckbox.vue'
import SelectUser from '@/components/input/SelectUser.vue'
import SelectList from '@/components/input/SelectList.vue'
import SelectNamespace from '@/components/input/SelectNamespace.vue'
import {parseDateOrString} from '@/helpers/time/parseDateOrString'
import {dateIsValid, formatISO} from '@/helpers/time/formatDate'
import {objectToSnakeCase} from '@/helpers/case'
import UserService from '@/services/user'
import ListService from '@/services/list'
import NamespaceService from '@/services/namespace'
import EditLabels from '@/components/tasks/partials/editLabels.vue'
import {dateIsValid, formatISO} from '@/helpers/time/formatDate'
import {objectToSnakeCase} from '@/helpers/case'
// FIXME: do not use this here for now. instead create new version from DEFAULT_PARAMS
import {getDefaultParams} from '@/composables/useTaskList'
import {camelCase} from 'camel-case'
// FIXME: merge with DEFAULT_PARAMS in taskList.js
const DEFAULT_PARAMS = {
@ -225,7 +224,7 @@ const DEFAULT_PARAMS = {
filter_include_nulls: true,
filter_concat: 'or',
s: '',
}
} as const
const DEFAULT_FILTERS = {
done: false,
@ -242,395 +241,350 @@ const DEFAULT_FILTERS = {
labels: '',
list_id: '',
namespace: '',
}
} as const
export const ALPHABETICAL_SORT = 'title'
export default defineComponent({
name: 'filters',
components: {
DatepickerWithRange,
EditLabels,
PrioritySelect,
Fancycheckbox,
PercentDoneSelect,
Multiselect,
const props = defineProps({
modelValue: {
required: true,
},
data() {
return {
params: DEFAULT_PARAMS,
filters: DEFAULT_FILTERS,
usersService: new UserService(),
foundusers: [],
users: [],
labelQuery: '',
labels: [],
listsService: new ListService(),
foundlists: [],
lists: [],
namespaceService: new NamespaceService(),
foundnamespace: [],
namespace: [],
}
},
mounted() {
this.filters.requireAllFilters = this.params.filter_concat === 'and'
},
props: {
modelValue: {
required: true,
},
hasTitle: {
type: Boolean,
default: false,
},
},
emits: ['update:modelValue'],
watch: {
modelValue: {
handler(value) {
// FIXME: filters should only be converted to snake case in
// the last moment
this.params = objectToSnakeCase(value)
this.prepareFilters()
},
immediate: true,
},
},
computed: {
sortAlphabetically: {
get() {
return this.params?.sort_by?.find(sortBy => sortBy === ALPHABETICAL_SORT) !== undefined
},
set(sortAlphabetically) {
this.params.sort_by = sortAlphabetically
? [ALPHABETICAL_SORT]
: getDefaultParams().sort_by
this.change()
},
},
foundLabels() {
const labelStore = useLabelStore()
return labelStore.filterLabelsByQuery(this.labels, this.labelQuery)
},
},
methods: {
change() {
const params = {...this.params}
params.filter_value = params.filter_value.map(v => v instanceof Date ? v.toISOString() : v)
this.$emit('update:modelValue', params)
},
prepareFilters() {
this.prepareDone()
this.prepareDate('due_date', 'dueDate')
this.prepareDate('start_date', 'startDate')
this.prepareDate('end_date', 'endDate')
this.prepareSingleValue('priority', 'priority', 'usePriority', true)
this.prepareSingleValue('percent_done', 'percentDone', 'usePercentDone', true)
this.prepareDate('reminders')
this.prepareRelatedObjectFilter('users', 'assignees')
this.prepareRelatedObjectFilter('lists', 'list_id')
this.prepareRelatedObjectFilter('namespace')
this.prepareSingleValue('labels')
const labels = typeof this.filters.labels === 'string'
? this.filters.labels
: ''
const labelIds = labels.split(',').map(i => parseInt(i))
const labelStore = useLabelStore()
this.labels = labelStore.getLabelsByIds(labelIds)
},
removePropertyFromFilter(propertyName) {
// Because of the way arrays work, we can only ever remove one element at once.
// To remove multiple filter elements of the same name this function has to be called multiple times.
for (const i in this.params.filter_by) {
if (this.params.filter_by[i] === propertyName) {
this.params.filter_by.splice(i, 1)
this.params.filter_comparator.splice(i, 1)
this.params.filter_value.splice(i, 1)
break
}
}
},
setDateFilter(filterName, {dateFrom, dateTo}) {
dateFrom = parseDateOrString(dateFrom, null)
dateTo = parseDateOrString(dateTo, null)
// Only filter if we have a date
if (dateFrom !== null && dateTo !== null) {
// Check if we already have values in params and only update them if we do
let foundStart = false
let foundEnd = false
this.params.filter_by.forEach((f, i) => {
if (f === filterName && this.params.filter_comparator[i] === 'greater_equals') {
foundStart = true
this.params.filter_value[i] = dateFrom
}
if (f === filterName && this.params.filter_comparator[i] === 'less_equals') {
foundEnd = true
this.params.filter_value[i] = dateTo
}
})
if (!foundStart) {
this.params.filter_by.push(filterName)
this.params.filter_comparator.push('greater_equals')
this.params.filter_value.push(dateFrom)
}
if (!foundEnd) {
this.params.filter_by.push(filterName)
this.params.filter_comparator.push('less_equals')
this.params.filter_value.push(dateTo)
}
this.filters[camelCase(filterName)] = {
// Passing the dates as string values avoids an endless loop between values changing
// in the datepicker (bubbling up to here) and changing here and bubbling down to the
// datepicker (because there's a new date instance every time this function gets called).
// See https://kolaente.dev/vikunja/frontend/issues/2384
dateFrom: dateIsValid(dateFrom) ? formatISO(dateFrom) : dateFrom,
dateTo: dateIsValid(dateTo) ? formatISO(dateTo) : dateTo,
}
this.change()
return
}
this.removePropertyFromFilter(filterName)
this.removePropertyFromFilter(filterName)
this.change()
},
prepareDate(filterName, variableName) {
if (typeof this.params.filter_by === 'undefined') {
return
}
let foundDateStart = false
let foundDateEnd = false
for (const i in this.params.filter_by) {
if (this.params.filter_by[i] === filterName && this.params.filter_comparator[i] === 'greater_equals') {
foundDateStart = i
}
if (this.params.filter_by[i] === filterName && this.params.filter_comparator[i] === 'less_equals') {
foundDateEnd = i
}
if (foundDateStart !== false && foundDateEnd !== false) {
break
}
}
if (foundDateStart !== false && foundDateEnd !== false) {
const startDate = new Date(this.params.filter_value[foundDateStart])
const endDate = new Date(this.params.filter_value[foundDateEnd])
this.filters[variableName] = {
dateFrom: !isNaN(startDate)
? `${startDate.getFullYear()}-${startDate.getMonth() + 1}-${startDate.getDate()}`
: this.params.filter_value[foundDateStart],
dateTo: !isNaN(endDate)
? `${endDate.getFullYear()}-${endDate.getMonth() + 1}-${endDate.getDate()}`
: this.params.filter_value[foundDateEnd],
}
}
},
setSingleValueFilter(filterName, variableName, useVariableName = '', comparator = 'equals') {
if (useVariableName !== '' && !this.filters[useVariableName]) {
this.removePropertyFromFilter(filterName)
return
}
let found = false
this.params.filter_by.forEach((f, i) => {
if (f === filterName) {
found = true
this.params.filter_value[i] = this.filters[variableName]
}
})
if (!found) {
this.params.filter_by.push(filterName)
this.params.filter_comparator.push(comparator)
this.params.filter_value.push(this.filters[variableName])
}
this.change()
},
/**
*
* @param filterName The filter name in the api.
* @param variableName The name of the variable in this.filters.
* @param useVariableName The name of the variable of the "Use this filter" variable. Will only be set if the parameter is not null.
* @param isNumber Toggles if the value should be parsed as a number.
*/
prepareSingleValue(filterName, variableName = null, useVariableName = null, isNumber = false) {
if (variableName === null) {
variableName = filterName
}
let found = false
for (const i in this.params.filter_by) {
if (this.params.filter_by[i] === filterName) {
found = i
break
}
}
if (found === false && useVariableName !== null) {
this.filters[useVariableName] = false
return
}
if (isNumber) {
this.filters[variableName] = Number(this.params.filter_value[found])
} else {
this.filters[variableName] = this.params.filter_value[found]
}
if (useVariableName !== null) {
this.filters[useVariableName] = true
}
},
prepareDone() {
// Set filters.done based on params
if (typeof this.params.filter_by === 'undefined') {
return
}
this.filters.done = this.params.filter_by.some((f) => f === 'done') === false
},
async prepareRelatedObjectFilter(kind, filterName = null, servicePrefix = null) {
if (filterName === null) {
filterName = kind
}
if (servicePrefix === null) {
servicePrefix = kind
}
this.prepareSingleValue(filterName)
if (typeof this.filters[filterName] === 'undefined' || this.filters[filterName] === '') {
return
}
// Don't load things if we already have something loaded.
// This is not the most ideal solution because it prevents a re-population when filters are changed
// from the outside. It is still fine because we're not changing them from the outside, other than
// loading them initially.
if (this[kind].length > 0) {
return
}
this[kind] = await this[`${servicePrefix}Service`].getAll({}, {s: this.filters[filterName]})
},
setDoneFilter() {
if (this.filters.done) {
this.removePropertyFromFilter('done')
} else {
this.params.filter_by.push('done')
this.params.filter_comparator.push('equals')
this.params.filter_value.push('false')
}
this.change()
},
setFilterConcat() {
if (this.filters.requireAllFilters) {
this.params.filter_concat = 'and'
} else {
this.params.filter_concat = 'or'
}
this.change()
},
setPriority() {
this.setSingleValueFilter('priority', 'priority', 'usePriority')
},
setPercentDoneFilter() {
this.setSingleValueFilter('percent_done', 'percentDone', 'usePercentDone')
},
clear(kind) {
this[`found${kind}`] = []
},
async find(kind, query) {
if (query === '') {
this.clear(kind)
return
}
const response = await this[`${kind}Service`].getAll({}, {s: query})
// Filter users from the results who are already assigned
this[`found${kind}`] = response.filter(({id}) => !includesById(this[kind], id))
},
add(kind, filterName) {
this.$nextTick(() => {
this.changeMultiselectFilter(kind, filterName)
})
},
remove(kind, filterName) {
this.$nextTick(() => {
this.changeMultiselectFilter(kind, filterName)
})
},
changeMultiselectFilter(kind, filterName) {
if (this[kind].length === 0) {
this.removePropertyFromFilter(filterName)
this.change()
return
}
const ids = []
this[kind].forEach(u => {
ids.push(kind === 'users' ? u.username : u.id)
})
this.filters[filterName] = ids.join(',')
this.setSingleValueFilter(filterName, filterName, '', 'in')
},
findLabels(query) {
this.labelQuery = query
},
addLabel() {
this.$nextTick(() => {
this.changeLabelFilter()
})
},
removeLabel(label) {
this.$nextTick(() => {
for (const l in this.labels) {
if (this.labels[l].id === label.id) {
this.labels.splice(l, 1)
}
break
}
this.changeLabelFilter()
})
},
changeLabelFilter() {
if (this.labels.length === 0) {
this.removePropertyFromFilter('labels')
this.change()
return
}
const labelIDs = []
this.labels.forEach(u => {
labelIDs.push(u.id)
})
this.filters.labels = labelIDs.join(',')
this.setSingleValueFilter('labels', 'labels', '', 'in')
},
hasTitle: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['update:modelValue'])
const {modelValue} = toRefs(props)
const labelStore = useLabelStore()
const params = ref({...DEFAULT_PARAMS})
const filters = ref({...DEFAULT_FILTERS})
const services = {
users: shallowReactive(new UserService()),
lists: shallowReactive(new ListService()),
namespace: shallowReactive(new NamespaceService()),
}
interface Entities {
users: IUser[]
labels: ILabel[]
lists: IList[]
namespace: INamespace[]
}
type EntityType = 'users' | 'labels' | 'lists' | 'namespace'
const entities: Entities = reactive({
users: [],
labels: [],
lists: [],
namespace: [],
})
onMounted(() => {
filters.value.requireAllFilters = params.value.filter_concat === 'and'
})
watch(
modelValue,
(value) => {
// FIXME: filters should only be converted to snake case in
// the last moment
params.value = objectToSnakeCase(value)
prepareFilters()
},
{immediate: true},
)
const sortAlphabetically = computed({
get() {
return params.value?.sort_by?.find(sortBy => sortBy === ALPHABETICAL_SORT) !== undefined
},
set(sortAlphabetically) {
params.value.sort_by = sortAlphabetically
? [ALPHABETICAL_SORT]
: getDefaultParams().sort_by
change()
},
})
function change() {
const newParams = {...params.value}
newParams.filter_value = newParams.filter_value.map(v => v instanceof Date ? v.toISOString() : v)
emit('update:modelValue', newParams)
}
function prepareFilters() {
prepareDone()
prepareDate('due_date', 'dueDate')
prepareDate('start_date', 'startDate')
prepareDate('end_date', 'endDate')
prepareSingleValue('priority', 'priority', 'usePriority', true)
prepareSingleValue('percent_done', 'percentDone', 'usePercentDone', true)
prepareDate('reminders')
prepareRelatedObjectFilter('users', 'assignees')
prepareRelatedObjectFilter('lists', 'list_id')
prepareRelatedObjectFilter('namespace')
prepareSingleValue('labels')
const newLabels = typeof filters.value.labels === 'string'
? filters.value.labels
: ''
const labelIds = newLabels.split(',').map(i => parseInt(i))
entities.labels = labelStore.getLabelsByIds(labelIds)
}
function removePropertyFromFilter(filterName) {
// Because of the way arrays work, we can only ever remove one element at once.
// To remove multiple filter elements of the same name this function has to be called multiple times.
for (const i in params.value.filter_by) {
if (params.value.filter_by[i] === filterName) {
params.value.filter_by.splice(i, 1)
params.value.filter_comparator.splice(i, 1)
params.value.filter_value.splice(i, 1)
break
}
}
}
function setDateFilter(filterName, {dateFrom, dateTo}) {
dateFrom = parseDateOrString(dateFrom, null)
dateTo = parseDateOrString(dateTo, null)
// Only filter if we have a date
if (dateFrom !== null && dateTo !== null) {
// Check if we already have values in params and only update them if we do
let foundStart = false
let foundEnd = false
params.value.filter_by.forEach((f, i) => {
if (f === filterName && params.value.filter_comparator[i] === 'greater_equals') {
foundStart = true
params.value.filter_value[i] = dateFrom
}
if (f === filterName && params.value.filter_comparator[i] === 'less_equals') {
foundEnd = true
params.value.filter_value[i] = dateTo
}
})
if (!foundStart) {
params.value.filter_by.push(filterName)
params.value.filter_comparator.push('greater_equals')
params.value.filter_value.push(dateFrom)
}
if (!foundEnd) {
params.value.filter_by.push(filterName)
params.value.filter_comparator.push('less_equals')
params.value.filter_value.push(dateTo)
}
filters.value[camelCase(filterName)] = {
// Passing the dates as string values avoids an endless loop between values changing
// in the datepicker (bubbling up to here) and changing here and bubbling down to the
// datepicker (because there's a new date instance every time this function gets called).
// See https://kolaente.dev/vikunja/frontend/issues/2384
dateFrom: dateIsValid(dateFrom) ? formatISO(dateFrom) : dateFrom,
dateTo: dateIsValid(dateTo) ? formatISO(dateTo) : dateTo,
}
change()
return
}
removePropertyFromFilter(filterName)
removePropertyFromFilter(filterName)
change()
}
function prepareDate(filterName, variableName) {
if (typeof params.value.filter_by === 'undefined') {
return
}
let foundDateStart = false
let foundDateEnd = false
for (const i in params.value.filter_by) {
if (params.value.filter_by[i] === filterName && params.value.filter_comparator[i] === 'greater_equals') {
foundDateStart = i
}
if (params.value.filter_by[i] === filterName && params.value.filter_comparator[i] === 'less_equals') {
foundDateEnd = i
}
if (foundDateStart !== false && foundDateEnd !== false) {
break
}
}
if (foundDateStart !== false && foundDateEnd !== false) {
const startDate = new Date(params.value.filter_value[foundDateStart])
const endDate = new Date(params.value.filter_value[foundDateEnd])
filters.value[variableName] = {
dateFrom: !isNaN(startDate)
? `${startDate.getFullYear()}-${startDate.getMonth() + 1}-${startDate.getDate()}`
: params.value.filter_value[foundDateStart],
dateTo: !isNaN(endDate)
? `${endDate.getFullYear()}-${endDate.getMonth() + 1}-${endDate.getDate()}`
: params.value.filter_value[foundDateEnd],
}
}
}
function setSingleValueFilter(filterName, variableName, useVariableName = '', comparator = 'equals') {
if (useVariableName !== '' && !filters.value[useVariableName]) {
removePropertyFromFilter(filterName)
return
}
let found = false
params.value.filter_by.forEach((f, i) => {
if (f === filterName) {
found = true
params.value.filter_value[i] = filters.value[variableName]
}
})
if (!found) {
params.value.filter_by.push(filterName)
params.value.filter_comparator.push(comparator)
params.value.filter_value.push(filters.value[variableName])
}
change()
}
function prepareSingleValue(
/** The filter name in the api. */
filterName,
/** The name of the variable in filters ref. */
variableName = null,
/** The name of the variable of the "Use this filter" variable. Will only be set if the parameter is not null. */
useVariableName = null,
/** Toggles if the value should be parsed as a number. */
isNumber = false,
) {
if (variableName === null) {
variableName = filterName
}
let found = false
for (const i in params.value.filter_by) {
if (params.value.filter_by[i] === filterName) {
found = i
break
}
}
if (found === false && useVariableName !== null) {
filters.value[useVariableName] = false
return
}
if (isNumber) {
filters.value[variableName] = Number(params.value.filter_value[found])
} else {
filters.value[variableName] = params.value.filter_value[found]
}
if (useVariableName !== null) {
filters.value[useVariableName] = true
}
}
function prepareDone() {
// Set filters.done based on params
if (typeof params.value.filter_by === 'undefined') {
return
}
filters.value.done = params.value.filter_by.some((f) => f === 'done') === false
}
async function prepareRelatedObjectFilter(kind: EntityType, filterName = null, servicePrefix: Omit<EntityType, 'labels'> | null = null) {
if (filterName === null) {
filterName = kind
}
if (servicePrefix === null) {
servicePrefix = kind
}
prepareSingleValue(filterName)
if (typeof filters.value[filterName] === 'undefined' || filters.value[filterName] === '') {
return
}
// Don't load things if we already have something loaded.
// This is not the most ideal solution because it prevents a re-population when filters are changed
// from the outside. It is still fine because we're not changing them from the outside, other than
// loading them initially.
if (entities[kind].length > 0) {
return
}
entities[kind] = await services[servicePrefix].getAll({}, {s: filters.value[filterName]})
}
function setDoneFilter() {
if (filters.value.done) {
removePropertyFromFilter('done')
} else {
params.value.filter_by.push('done')
params.value.filter_comparator.push('equals')
params.value.filter_value.push('false')
}
change()
}
function setFilterConcat() {
if (filters.value.requireAllFilters) {
params.value.filter_concat = 'and'
} else {
params.value.filter_concat = 'or'
}
change()
}
function setPriority() {
setSingleValueFilter('priority', 'priority', 'usePriority')
}
function setPercentDoneFilter() {
setSingleValueFilter('percent_done', 'percentDone', 'usePercentDone')
}
async function changeMultiselectFilter(kind: EntityType, filterName) {
await nextTick()
if (entities[kind].length === 0) {
removePropertyFromFilter(filterName)
change()
return
}
const ids = entities[kind].map(u => kind === 'users' ? u.username : u.id)
filters.value[filterName] = ids.join(',')
setSingleValueFilter(filterName, filterName, '', 'in')
}
function changeLabelFilter() {
if (entities.labels.length === 0) {
removePropertyFromFilter('labels')
change()
return
}
const labelIDs = entities.labels.map(u => u.id)
filters.value.labels = labelIDs.join(',')
setSingleValueFilter('labels', 'labels', '', 'in')
}
</script>
<style lang="scss" scoped>

Some files were not shown because too many files have changed in this diff Show More