Compare commits

...

258 Commits

Author SHA1 Message Date
bc2ac3e3d8 chore(deps): update dependency eslint-plugin-vue to v8.4.1 (#1486)
Reviewed-on: vikunja/frontend#1486
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-04 14:36:42 +00:00
42b2cded82 chore(deps): update dependency caniuse-lite to v1.0.30001307 (#1484)
Reviewed-on: vikunja/frontend#1484
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-04 07:16:07 +00:00
2a431507dc chore(deps): update dependency vitest to v0.2.7 (#1485)
Reviewed-on: vikunja/frontend#1485
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-04 07:15:49 +00:00
fdcb6b31cb chore(deps): update dependency postcss-preset-env to v7.3.1 (#1483)
Reviewed-on: vikunja/frontend#1483
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-03 10:20:37 +00:00
a68ebff8df chore(deps): update dependency caniuse-lite to v1.0.30001306 (#1482)
Reviewed-on: vikunja/frontend#1482
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-03 08:43:04 +00:00
7f7126b8be chore(deps): update dependency vitest to v0.2.6 (#1481)
Reviewed-on: vikunja/frontend#1481
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-03 06:46:49 +00:00
39094ec968 chore(deps): update dependency esbuild to v0.14.18 (#1480)
Reviewed-on: vikunja/frontend#1480
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-02 20:11:05 +00:00
64425b5c6e fix(deps): update sentry-javascript monorepo to v6.17.4 (#1479)
Reviewed-on: vikunja/frontend#1479
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-02 18:34:45 +00:00
6629cdd009 chore(deps): update dependency rollup to v2.67.0 (#1478)
Reviewed-on: vikunja/frontend#1478
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-02 07:41:15 +00:00
6a833bd8c4 chore(deps): update dependency esbuild to v0.14.17 (#1477)
Reviewed-on: vikunja/frontend#1477
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-02 07:40:45 +00:00
fed852baec chore(deps): update dependency caniuse-lite to v1.0.30001305 (#1476)
Reviewed-on: vikunja/frontend#1476
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-02 06:58:15 +00:00
25011e57d6 chore(deps): update dependency sass to v1.49.7 (#1475)
Reviewed-on: vikunja/frontend#1475
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-02 06:57:55 +00:00
766a6e1fce chore(deps): update dependency sass to v1.49.6 (#1474)
Reviewed-on: vikunja/frontend#1474
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-01 22:19:02 +00:00
bf239849ba chore(deps): update dependency sass to v1.49.5 2022-02-01 21:02:40 +00:00
1269cfeb5b chore(deps): update dependency postcss to v8.4.6 2022-02-01 12:02:39 +00:00
95a560584f chore(deps): update dependency sass to v1.49.4 (#1470)
Reviewed-on: vikunja/frontend#1470
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-01 06:58:03 +00:00
782e45eb8f chore(deps): update dependency esbuild to v0.14.16 (#1469)
Reviewed-on: vikunja/frontend#1469
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-01 06:56:12 +00:00
1e19cf7f8b fix(deps): update dependency @github/hotkey to v2 (#1471)
Reviewed-on: vikunja/frontend#1471
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-02-01 06:55:24 +00:00
7150e20d45 chore(deps): update dependency cypress to v9.4.1 2022-01-31 22:02:49 +00:00
0dedbfa901 chore(deps): update typescript-eslint monorepo to v5.10.2 2022-01-31 19:02:56 +00:00
749eb2e6a7 fix(deps): update dependency ufo to v0.7.10 (#1466)
Reviewed-on: vikunja/frontend#1466
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-31 13:05:03 +00:00
aea910e1e4 chore(deps): update dependency happy-dom to v2.31.1 (#1465)
Reviewed-on: vikunja/frontend#1465
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-31 10:35:08 +00:00
110f48ebd7 chore(deps): update dependency postcss-preset-env to v7.3.0 (#1464)
Reviewed-on: vikunja/frontend#1464
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-31 09:20:00 +00:00
8242527d0f chore(deps): update dependency netlify-cli to v8.15.0 (#1463)
Reviewed-on: vikunja/frontend#1463
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-31 06:52:45 +00:00
20a9ad2c9e
fix: related task within the same namespace 2022-01-30 23:12:42 +01:00
92864fa5c1
chore(tests): remove test result upload to s3 since we now have cypress dashboard 2022-01-30 22:35:17 +01:00
c21f236249 feat: add cypress dashboard record (#1462)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/frontend#1462
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
2022-01-30 21:33:27 +00:00
ea710e227a chore(deps): update dependency happy-dom to v2.31.0 (#1461)
Reviewed-on: vikunja/frontend#1461
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-30 18:13:34 +00:00
81cf8f2f29 feat(tests): replace cypress-file-upload with .selectFile() (#1460)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/frontend#1460
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
2022-01-30 16:17:03 +00:00
d913fa1745
fix: edge cases for dates where the next month had fewer days than the current one 2022-01-30 12:38:17 +01:00
931941359b
fix: don't try to parse date numbers with letters around them 2022-01-30 12:37:14 +01:00
b3697cb9bf
fix: subscription icon not rendered correctly
The computed property "icon" which holds the icon string to be rendered was overriding the <icon> component. Therefore, the component wasn't rendered at all, instead vue would render a html tag with the icon name.
2022-01-29 22:30:47 +01:00
c98ab42e75 feat: move lists between namespaces (#1430)
Frontend implementation of vikunja/api#1096

I've implemented this re-using the drag and drop part of rearranging the list position in the menu. The only problem we have is there's no way to check if a namespace is read-only and disable dropping a list into it. I hope to solve this in the future on the api but for now you can drop a list into it and get an error message. I felt like properly handling the error and restoring the list and its position given this will change anyway.

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/frontend#1430
Reviewed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
2022-01-29 21:12:46 +00:00
f5a92d1aec chore(deps): update dependency caniuse-lite to v1.0.30001304 (#1459)
Reviewed-on: vikunja/frontend#1459
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-29 20:54:49 +00:00
fb17adcfe3 chore(deps): update dependency eslint to v8.8.0 (#1458)
Reviewed-on: vikunja/frontend#1458
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-28 22:45:24 +00:00
198c97af57 fix(deps): update sentry-javascript monorepo to v6.17.3 (#1457)
Reviewed-on: vikunja/frontend#1457
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-28 20:05:01 +00:00
3ff4f3516f chore(deps): update dependency vitest to v0.2.5 (#1456)
Reviewed-on: vikunja/frontend#1456
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-28 14:02:34 +00:00
ab5d768895 fix(deps): update dependency vue-i18n to v9.2.0-beta.30 (#1454)
Reviewed-on: vikunja/frontend#1454
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-27 20:04:32 +00:00
0d2ff42673 chore(deps): update dependency caniuse-lite to v1.0.30001303 (#1453)
Reviewed-on: vikunja/frontend#1453
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-27 09:29:26 +00:00
aeb548ee09 fix(deps): update dependency marked to v4.0.12 (#1452)
Reviewed-on: vikunja/frontend#1452
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-27 09:29:08 +00:00
f168e36f68 chore(deps): update dependency eslint-plugin-vue to v8.4.0 (#1451)
Reviewed-on: vikunja/frontend#1451
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-27 09:28:49 +00:00
691644a3a3 chore(deps): update dependency vitest to v0.2.4 (#1450)
Reviewed-on: vikunja/frontend#1450
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-27 09:28:11 +00:00
0075ca0c99 fix(deps): update dependency marked to v4.0.11 (#1449)
Reviewed-on: vikunja/frontend#1449
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-26 22:14:59 +00:00
83676f51b5 fix(deps): update dependency dompurify to v2.3.5 (#1448)
Reviewed-on: vikunja/frontend#1448
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-26 19:26:16 +00:00
fdd2e7e538
fix: vuex store mutation violation when archiving a namespace 2022-01-26 14:36:32 +01:00
9e4ea9e597 chore(deps): update dependency caniuse-lite to v1.0.30001302 (#1447)
Reviewed-on: vikunja/frontend#1447
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-26 08:27:25 +00:00
e0141f4a38 chore(deps): update dependency esbuild to v0.14.14 (#1446)
Reviewed-on: vikunja/frontend#1446
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-26 07:12:23 +00:00
d3e95adc32 chore(deps): update dependency happy-dom to v2.30.1 (#1445)
Reviewed-on: vikunja/frontend#1445
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-25 22:11:13 +00:00
07ac1245a9 fix(deps): update sentry-javascript monorepo to v6.17.2 (#1444)
Reviewed-on: vikunja/frontend#1444
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-25 21:18:23 +00:00
075a7875bf fix(deps): update dependency @vueuse/core to v7.5.5 (#1442)
Reviewed-on: vikunja/frontend#1442
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-25 17:28:08 +00:00
43a537ef5b fix(deps): update dependency @vueuse/router to v7.5.5 (#1443)
Reviewed-on: vikunja/frontend#1443
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-25 16:25:34 +00:00
52a613bf7f chore(deps): update dependency @faker-js/faker to v6.0.0-alpha.5 (#1436)
Reviewed-on: vikunja/frontend#1436
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-25 16:00:36 +00:00
8e806f9308 chore(deps): update dependency vitest to v0.2.3 (#1441)
Reviewed-on: vikunja/frontend#1441
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-25 13:29:11 +00:00
df5300fa02 chore(deps): update dependency vitest to v0.2.2 (#1440)
Reviewed-on: vikunja/frontend#1440
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-25 10:40:43 +00:00
f469cac4d1 chore(deps): update dependency rollup to v2.66.1 (#1439)
Reviewed-on: vikunja/frontend#1439
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-25 09:21:08 +00:00
7ad200179b fix(deps): update dependency vue-i18n to v9.2.0-beta.29 (#1438)
Reviewed-on: vikunja/frontend#1438
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-25 08:08:40 +00:00
f9eceeb6b6 chore(deps): update dependency happy-dom to v2.30.0 (#1437)
Reviewed-on: vikunja/frontend#1437
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-25 08:07:43 +00:00
3a82fd4ad9 fix(deps): update sentry-javascript monorepo to v6.17.1 (#1434)
Reviewed-on: vikunja/frontend#1434
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-24 19:47:51 +00:00
733e3c20c6 chore(deps): update typescript-eslint monorepo to v5.10.1 (#1435)
Reviewed-on: vikunja/frontend#1435
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-24 19:47:34 +00:00
842249eb2c chore(deps): update dependency vitest to v0.2.1 (#1433)
Reviewed-on: vikunja/frontend#1433
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-24 12:28:34 +00:00
7458130ee3 fix(deps): update sentry-javascript monorepo to v6.17.0 (#1432)
Reviewed-on: vikunja/frontend#1432
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-24 08:19:48 +00:00
19fd2d603b chore(deps): update dependency netlify-cli to v8.13.0 (#1431)
Reviewed-on: vikunja/frontend#1431
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-24 07:26:48 +00:00
fc1f3966e6 fix(deps): update dependency vue to v3.2.29 (#1429)
Reviewed-on: vikunja/frontend#1429
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-23 15:57:32 +00:00
5886577108 fix(deps): update dependency @vue/compat to v3.2.29 (#1428)
Reviewed-on: vikunja/frontend#1428
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-23 15:57:20 +00:00
e87311c746 fix(deps): update dependency vue-advanced-cropper to v2.8.0 (#1425)
Reviewed-on: vikunja/frontend#1425
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-23 13:00:10 +00:00
7c1c6b7dfc chore(deps): update dependency vitest to v0.2.0 (#1427)
Reviewed-on: vikunja/frontend#1427
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-23 13:00:01 +00:00
55b77725df chore(deps): update dependency rollup to v2.66.0 (#1424)
Reviewed-on: vikunja/frontend#1424
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-23 11:34:17 +00:00
55b710dbfa chore(deps): update dependency esbuild to v0.14.13 (#1426)
Reviewed-on: vikunja/frontend#1426
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-23 11:34:08 +00:00
af6c48fd2e chore(deps): update dependency vue-tsc to v0.31.1 (#1423)
Reviewed-on: vikunja/frontend#1423
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-23 11:33:50 +00:00
692722d826 chore(deps): update dependency vitest to v0.1.27 (#1422)
Reviewed-on: vikunja/frontend#1422
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-22 06:42:01 +00:00
3f7fd3b9c0 chore(deps): update dependency @vitejs/plugin-vue to v2.1.0 (#1421)
Reviewed-on: vikunja/frontend#1421
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-22 06:41:09 +00:00
2f18d742e0 fix(deps): update dependency @vueuse/core to v7.5.4 (#1419)
Reviewed-on: vikunja/frontend#1419
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-21 13:00:05 +00:00
aa182d1517 fix(deps): update dependency @vueuse/router to v7.5.4 (#1420)
Reviewed-on: vikunja/frontend#1420
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-21 11:33:51 +00:00
3ad133c5d6 chore(deps): update dependency vitest to v0.1.26 (#1418)
Reviewed-on: vikunja/frontend#1418
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-21 10:22:40 +00:00
3d1f2d8a77 fix(deps): update dependency vue to v3.2.28 (#1417)
Reviewed-on: vikunja/frontend#1417
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-21 10:08:00 +00:00
3e415cd7c9 fix(deps): update dependency @vue/compat to v3.2.28 (#1416)
Reviewed-on: vikunja/frontend#1416
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-21 10:07:29 +00:00
0215b4bcf9 chore(deps): update dependency rollup to v2.65.0 (#1415)
Reviewed-on: vikunja/frontend#1415
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-21 08:35:27 +00:00
9236a7cec8 chore(deps): update dependency vitest to v0.1.25 (#1411)
Reviewed-on: vikunja/frontend#1411
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-21 08:35:05 +00:00
8a2694a2f0 chore(deps): update dependency caniuse-lite to v1.0.30001301 (#1414)
Reviewed-on: vikunja/frontend#1414
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-21 08:34:41 +00:00
240ab2a72f chore(deps): update dependency happy-dom to v2.28.0 (#1412)
Reviewed-on: vikunja/frontend#1412
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-21 07:12:22 +00:00
9f5754ee42 chore(deps): update dependency esbuild to v0.14.12 (#1413)
Reviewed-on: vikunja/frontend#1413
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-21 07:11:56 +00:00
f10152718c chore(deps): update dependency typescript to v4.5.5 (#1410)
Reviewed-on: vikunja/frontend#1410
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-20 19:35:54 +00:00
365a017efe fix(deps): update dependency codemirror to v5.65.1 (#1409)
Reviewed-on: vikunja/frontend#1409
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-20 13:33:38 +00:00
Dominik Pschenitschni
6db0559b81 fix: replace faker with community fork faker-js/faker (#1408)
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: vikunja/frontend#1408
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-01-20 07:54:39 +00:00
cae351d9bd chore(deps): update dependency vitest to v0.1.24 2022-01-19 20:02:33 +00:00
faa34ee692 chore(deps): update dependency happy-dom to v2.27.2 (#1406)
Reviewed-on: vikunja/frontend#1406
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-19 19:27:00 +00:00
136ded9f73 chore(deps): update dependency sass to v1.49.0 (#1403)
Reviewed-on: vikunja/frontend#1403
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-19 08:53:05 +00:00
5661b352c0 chore(deps): update dependency vitest to v0.1.23 (#1405)
Reviewed-on: vikunja/frontend#1405
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-19 08:52:45 +00:00
02c551fdbc chore(deps): update dependency vue-tsc to v0.30.6 (#1404)
Reviewed-on: vikunja/frontend#1404
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-19 07:00:25 +00:00
2d7cafd329 chore(deps): update dependency cypress to v9.3.1 (#1402)
Reviewed-on: vikunja/frontend#1402
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-19 06:59:47 +00:00
7107044cc6 chore(deps): update dependency vite to v2.7.13 (#1401)
Reviewed-on: vikunja/frontend#1401
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-19 06:58:13 +00:00
Dominik Pschenitschni
375c3adfb1 fix: show namespace count for long titles (#1057)
When the namespace title is to long the count was only shown in the toolip. With this pull request the count is separated from the title and always shown.

Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Co-authored-by: kolaente <k@knt.li>
Co-authored-by: konrad <k@knt.li>
Reviewed-on: vikunja/frontend#1057
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
2022-01-19 06:57:45 +00:00
637f2e9742 [skip ci] Updated translations via Crowdin 2022-01-18 22:22:48 +00:00
0548649257
fix: lint 2022-01-18 23:12:28 +01:00
4a290214c0 chore(deps): update dependency vitest to v0.1.21 (#1400)
Reviewed-on: vikunja/frontend#1400
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-18 21:54:50 +00:00
ca938b8615
fix: subscription prop validation 2022-01-18 22:26:27 +01:00
6a6203f553
fix: label edit spacing 2022-01-18 22:22:32 +01:00
ff9e1b3fca
fix: vuex store manipulation warning when modifying task labels 2022-01-18 22:12:08 +01:00
1818ed3648
fix: scrolling to heading if it wasn't available 2022-01-18 22:00:13 +01:00
50c3bcd793 fix: don't try to format invalid dates as ISO 2022-01-18 20:43:52 +00:00
2e77df2db2 fix(a11y): remove wrong aria-label 2022-01-18 20:43:52 +00:00
56d321e513 feat(a11y): make sure the contrast for the primary color works with dark and light themes 2022-01-18 20:43:52 +00:00
cb776872aa feat(a11y): honor prefer-reduced-motion 2022-01-18 20:43:52 +00:00
c255e3f025 feat(a11y): add aria-expanded 2022-01-18 20:43:52 +00:00
b96af50338 feat(a11y): use better markup tags everywhere 2022-01-18 20:43:52 +00:00
0e47cebed5 feat(a11y): use <time> tag for dates everywhere 2022-01-18 20:43:52 +00:00
443a9c14b9
fix: attachment meta data not aligned properly 2022-01-18 21:42:43 +01:00
cc3fcdf1c3
fix: keyboard shortcut message bottom margin 2022-01-18 21:33:10 +01:00
b73165fce4
fix: update available text color in dark mode 2022-01-18 21:31:40 +01:00
729432bceb [skip ci] Updated translations via Crowdin 2022-01-18 18:18:15 +00:00
eddccc709d [skip ci] Updated translations via Crowdin 2022-01-18 14:18:13 +00:00
559ff5f7f7 chore(deps): update typescript-eslint monorepo to v5.10.0 (#1396)
Reviewed-on: vikunja/frontend#1396
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-18 09:04:07 +00:00
b5661de152 chore(deps): update dependency happy-dom to v2.27.0 (#1397)
Reviewed-on: vikunja/frontend#1397
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-18 09:03:20 +00:00
3a1ce7458b chore(deps): update dependency vitest to v0.1.20 (#1398)
Reviewed-on: vikunja/frontend#1398
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-18 09:02:59 +00:00
2f938fe695 chore(deps): update dependency axios to v0.25.0 (#1399)
Reviewed-on: vikunja/frontend#1399
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-18 09:02:28 +00:00
f2d7ee2be0 chore(deps): update dependency vitest to v0.1.19 2022-01-17 16:05:17 +00:00
d673150d8a chore(deps): update dependency vitest to v0.1.18 (#1393)
Reviewed-on: vikunja/frontend#1393
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-17 10:50:27 +00:00
2ca5b3c817 chore(deps): update dependency caniuse-lite to v1.0.30001300 (#1391)
Reviewed-on: vikunja/frontend#1391
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-17 08:42:06 +00:00
017f82dad7 chore(deps): update dependency vue-tsc to v0.30.5 (#1392)
Reviewed-on: vikunja/frontend#1392
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-17 08:41:49 +00:00
26a94c7e8c
fix: some typechecks
Most of what's still left now is related to models not exporting visible properties for typescript, that's a problem for another day.
2022-01-16 22:24:51 +01:00
654f5f8f57 chore(deps): update dependency vue-tsc to v0.30.4 (#1389)
Reviewed-on: vikunja/frontend#1389
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-16 16:16:12 +00:00
e3ed0b2f1f fix(deps): update vue monorepo to v3.2.27 (#1387)
Reviewed-on: vikunja/frontend#1387
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-16 15:24:20 +00:00
2e99a0ed29 chore(deps): update dependency vue-tsc to v0.30.3 (#1386)
Reviewed-on: vikunja/frontend#1386
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-16 14:16:17 +00:00
d450096303 chore(deps): update dependency vitest to v0.1.17 (#1385)
Reviewed-on: vikunja/frontend#1385
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-16 10:49:54 +00:00
315a50e5b2 chore(deps): update dependency eslint to v8.7.0 (#1384)
Reviewed-on: vikunja/frontend#1384
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-16 10:49:36 +00:00
5e4a9cca0c fix(deps): update dependency easymde to v2.16.1 2022-01-15 22:02:00 +00:00
864669fd3f chore(deps): update dependency vitest to v0.1.16 (#1382)
Reviewed-on: vikunja/frontend#1382
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-15 21:09:55 +00:00
010c4a2a3d chore(deps): update dependency rollup-plugin-visualizer to v5.5.4 (#1381)
Reviewed-on: vikunja/frontend#1381
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-15 21:09:48 +00:00
9446550ce9
chore: update netlify-cli only weekly 2022-01-14 22:20:32 +01:00
c7ac81a99f
fix: save user language when it wasn't saved previously 2022-01-14 22:11:13 +01:00
c8558e6b25 chore(deps): update dependency rollup to v2.64.0 (#1377)
Reviewed-on: vikunja/frontend#1377
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-14 15:09:06 +00:00
97ef78f1b0 chore(deps): update dependency netlify-cli to v8.8.2 (#1376)
Reviewed-on: vikunja/frontend#1376
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-14 15:08:51 +00:00
8a97483dc2 chore(deps): update dependency vitest to v0.1.13 (#1375)
Reviewed-on: vikunja/frontend#1375
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-14 10:08:50 +00:00
47b9878846 chore(deps): update dependency netlify-cli to v8.8.1 (#1374)
Reviewed-on: vikunja/frontend#1374
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-13 21:16:19 +00:00
e8086aac39 chore(deps): update dependency vite to v2.7.12 (#1373)
Reviewed-on: vikunja/frontend#1373
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-13 20:23:21 +00:00
b0ac968fbf chore(deps): update dependency netlify-cli to v8.8.0 (#1372)
Reviewed-on: vikunja/frontend#1372
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-13 15:15:48 +00:00
ea8a5df0b5 chore(deps): update dependency vite to v2.7.11 2022-01-13 12:02:46 +00:00
a03b7be194 fix(deps): update dependency marked to v4.0.10 2022-01-13 11:12:34 +00:00
3128e76e7a chore(deps): update dependency happy-dom to v2.25.2 2022-01-13 11:12:11 +00:00
b17b7ec296 chore(deps): update dependency sass to v1.48.0 2022-01-13 11:11:43 +00:00
ecd61cca63 chore(deps): update dependency vitest to v0.1.12 2022-01-13 11:11:19 +00:00
411847cd79 fix(deps): update dependency vue-i18n to v9.2.0-beta.28 2022-01-13 10:03:07 +00:00
1fe5e4bd8e chore(deps): update dependency vitest to v0.0.142 (#1365)
Reviewed-on: vikunja/frontend#1365
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-12 21:29:09 +00:00
b6788d9367 [skip ci] Updated translations via Crowdin 2022-01-12 21:10:32 +00:00
796a56d5d8
fix: translation typo 2022-01-12 19:53:02 +01:00
9d1ebd675d chore(deps): update dependency netlify-cli to v8.6.23 (#1363)
Reviewed-on: vikunja/frontend#1363
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-12 18:15:26 +00:00
33cefd2c3e chore(deps): update dependency vite-plugin-pwa to v0.11.13 (#1364)
Reviewed-on: vikunja/frontend#1364
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-12 18:13:32 +00:00
1484c282eb chore(deps): update dependency postcss-preset-env to v7.2.3 (#1361)
Reviewed-on: vikunja/frontend#1361
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-12 16:39:59 +00:00
f2c0460fdb fix(deps): update dependency v-tooltip to v4.0.0-beta.17 (#1362)
Reviewed-on: vikunja/frontend#1362
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-12 16:39:43 +00:00
6d6843fe96 chore(deps): update dependency netlify-cli to v8.6.22 (#1359)
Reviewed-on: vikunja/frontend#1359
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-12 14:27:00 +00:00
e278bb4840 chore(deps): update dependency eslint-plugin-vue to v8.3.0 (#1360)
Reviewed-on: vikunja/frontend#1360
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-12 14:01:29 +00:00
14f999ba55 chore(deps): update dependency postcss-preset-env to v7.2.2 (#1358)
Reviewed-on: vikunja/frontend#1358
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-12 14:00:41 +00:00
c85d1c241e chore(deps): update dependency caniuse-lite to v1.0.30001299 (#1357)
Reviewed-on: vikunja/frontend#1357
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-12 14:00:05 +00:00
fa4560d4af fix(deps): update dependency easymde to v2.16.0 (#1356)
Reviewed-on: vikunja/frontend#1356
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-11 22:20:19 +00:00
bd5483f100 chore(deps): update dependency netlify-cli to v8.6.21 (#1353)
Reviewed-on: vikunja/frontend#1353
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-11 20:41:12 +00:00
9c50fb3f4e fix(deps): update dependency v-tooltip to v4.0.0-beta.16 (#1354)
Reviewed-on: vikunja/frontend#1354
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-11 20:40:47 +00:00
23dc74b373 chore(deps): update dependency vitest to v0.0.141 (#1355)
Reviewed-on: vikunja/frontend#1355
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-11 20:40:15 +00:00
7ec5023c45 chore(deps): update dependency netlify-cli to v8.6.19 (#1352)
Reviewed-on: vikunja/frontend#1352
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-11 15:28:20 +00:00
9dbec1e11d chore(deps): update dependency vite-svg-loader to v3.1.2 (#1351)
Reviewed-on: vikunja/frontend#1351
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-11 13:14:31 +00:00
31ddc6cc5a chore(deps): update dependency netlify-cli to v8.6.18 (#1350)
Reviewed-on: vikunja/frontend#1350
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-11 06:59:09 +00:00
c4bd5702ad chore(deps): update dependency cypress to v9.2.1 (#1349)
Reviewed-on: vikunja/frontend#1349
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-11 06:58:49 +00:00
9bb6360e05 chore(deps): update typescript-eslint monorepo to v5.9.1 (#1347)
Reviewed-on: vikunja/frontend#1347
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-10 21:25:43 +00:00
1570cccc36 chore(deps): update dependency vitest to v0.0.140 (#1348)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [vitest](https://github.com/vitest-dev/vitest) | devDependencies | patch | [`0.0.139` -> `0.0.140`](https://renovatebot.com/diffs/npm/vitest/0.0.139/0.0.140) |

---

### Release Notes

<details>
<summary>vitest-dev/vitest</summary>

### [`v0.0.140`](https://github.com/vitest-dev/vitest/releases/v0.0.140)

[Compare Source](https://github.com/vitest-dev/vitest/compare/v0.0.139...v0.0.140)

##### Bug Fixes

-   inline snapshot if not called inside suite ([6d743c5](https://github.com/vitest-dev/vitest/commit/6d743c5)), closes [#&#8203;484](https://github.com/vitest-dev/vitest/issues/484)
-   **ui:** flex / percentage based layout ([#&#8203;492](https://github.com/vitest-dev/vitest/issues/492)) ([c43ebaf](https://github.com/vitest-dev/vitest/commit/c43ebaf))
-   correctly inline shapshot with properties ([4603ffd](https://github.com/vitest-dev/vitest/commit/4603ffd))
-   mocking is lost with threads: false ([28b97d8](https://github.com/vitest-dev/vitest/commit/28b97d8)), closes [#&#8203;482](https://github.com/vitest-dev/vitest/issues/482)
-   Reflect.get called on non-object ([3c9073a](https://github.com/vitest-dev/vitest/commit/3c9073a)), closes [#&#8203;479](https://github.com/vitest-dev/vitest/issues/479)
-   snapshot ignores indentation ([aff1481](https://github.com/vitest-dev/vitest/commit/aff1481))
-   **ui:** reduce graph container size ([#&#8203;478](https://github.com/vitest-dev/vitest/issues/478)) ([23e1e62](https://github.com/vitest-dev/vitest/commit/23e1e62))

##### Features

-   global setup ([#&#8203;372](https://github.com/vitest-dev/vitest/issues/372)) ([eaa119f](https://github.com/vitest-dev/vitest/commit/eaa119f))
-   **ui:** tasks state group ([7782e7d](https://github.com/vitest-dev/vitest/commit/7782e7d))

</details>

---

### Configuration

📅 **Schedule**: At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box.

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).

Reviewed-on: vikunja/frontend#1348
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-10 21:23:42 +00:00
b31008fe20 fix(deps): update dependency v-tooltip to v4.0.0-beta.15 (#1346)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [v-tooltip](https://github.com/Akryum/vue-tooltip) | dependencies | patch | [`4.0.0-beta.14` -> `4.0.0-beta.15`](https://renovatebot.com/diffs/npm/v-tooltip/4.0.0-beta.14/4.0.0-beta.15) |

---

### Release Notes

<details>
<summary>Akryum/vue-tooltip</summary>

### [`v4.0.0-beta.15`](https://github.com/Akryum/vue-tooltip/compare/v4.0.0-beta.14...v4.0.0-beta.15)

[Compare Source](https://github.com/Akryum/vue-tooltip/compare/v4.0.0-beta.14...v4.0.0-beta.15)

</details>

---

### Configuration

📅 **Schedule**: At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box.

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).

Reviewed-on: vikunja/frontend#1346
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-10 18:45:24 +00:00
d3efcb499f chore(deps): update dependency netlify-cli to v8.6.17 (#1345)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [netlify-cli](https://github.com/netlify/cli) | devDependencies | patch | [`8.6.16` -> `8.6.17`](https://renovatebot.com/diffs/npm/netlify-cli/8.6.16/8.6.17) |

---

### Release Notes

<details>
<summary>netlify/cli</summary>

### [`v8.6.17`](https://github.com/netlify/cli/blob/master/CHANGELOG.md#&#8203;8617-httpsgithubcomnetlifyclicomparev8616v8617-2022-01-10)

[Compare Source](https://github.com/netlify/cli/compare/v8.6.16...v8.6.17)

</details>

---

### Configuration

📅 **Schedule**: At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box.

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).

Reviewed-on: vikunja/frontend#1345
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-10 13:22:00 +00:00
23e2550534 fix(deps): update dependency v-tooltip to v4.0.0-beta.14 (#1344)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [v-tooltip](https://github.com/Akryum/vue-tooltip) | dependencies | patch | [`4.0.0-beta.13` -> `4.0.0-beta.14`](https://renovatebot.com/diffs/npm/v-tooltip/4.0.0-beta.13/4.0.0-beta.14) |

---

### Release Notes

<details>
<summary>Akryum/vue-tooltip</summary>

### [`v4.0.0-beta.14`](https://github.com/Akryum/vue-tooltip/compare/v4.0.0-beta.13...v4.0.0-beta.14)

[Compare Source](https://github.com/Akryum/vue-tooltip/compare/v4.0.0-beta.13...v4.0.0-beta.14)

</details>

---

### Configuration

📅 **Schedule**: At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box.

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).

Reviewed-on: vikunja/frontend#1344
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-10 13:07:52 +00:00
c3bc2e470c chore(deps): update dependency netlify-cli to v8.6.16 (#1343)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [netlify-cli](https://github.com/netlify/cli) | devDependencies | patch | [`8.6.15` -> `8.6.16`](https://renovatebot.com/diffs/npm/netlify-cli/8.6.15/8.6.16) |

---

### Release Notes

<details>
<summary>netlify/cli</summary>

### [`v8.6.16`](https://github.com/netlify/cli/blob/master/CHANGELOG.md#&#8203;8616-httpsgithubcomnetlifyclicomparev8615v8616-2022-01-10)

[Compare Source](https://github.com/netlify/cli/compare/v8.6.15...v8.6.16)

</details>

---

### Configuration

📅 **Schedule**: At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box.

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).

Reviewed-on: vikunja/frontend#1343
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-10 12:07:57 +00:00
8d811fcf19 [skip ci] Updated translations via Crowdin 2022-01-09 10:29:59 +00:00
6080e49f26 fix: flatpickr date not updating (#1336)
Fixes https://github.com/go-vikunja/api/issues/16

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/frontend#1336
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
2022-01-09 10:17:18 +00:00
ed88fb91bc fix: don't recognize emails in quick add magic (#1335)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/frontend#1335
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
2022-01-09 10:17:01 +00:00
76fe2ceac6 fix: editor color in dark mode (#1338)
This PR fixes the editor colors in dark mode. It bothered me enough to finally fix it :)
The implementation is probably only "good enough" as we'll replace the editor anyway in the future.

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/frontend#1338
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
2022-01-09 10:16:13 +00:00
99da6bb19a chore(deps): update dependency esbuild to v0.14.11 (#1341)
Reviewed-on: vikunja/frontend#1341
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-09 08:01:25 +00:00
c2e4fc1e3c [skip ci] Updated translations via Crowdin 2022-01-08 22:31:19 +00:00
044f2b927d feat: changed green "Done" button to read "Mark task done" (#1340)
The green button can be confusing because the wording "Done" can be interpreted as "done editing the task" or "the task should be marked as done". Changing the text in the button makes the description more precise.

Co-authored-by: David Morlitz <david@morlitz.com>
Reviewed-on: vikunja/frontend#1340
Reviewed-by: konrad <k@knt.li>
Co-authored-by: dmorlitz <david@morlitz.com>
Co-committed-by: dmorlitz <david@morlitz.com>
2022-01-08 21:18:06 +00:00
0473c385d6
fix: editor cursor color 2022-01-08 17:34:13 +01:00
68a76faacc
fix: don't reset active fields when saving
Resolves #590
2022-01-08 15:13:49 +01:00
4579dd3ce7
fix: button size on task detail view 2022-01-08 15:11:55 +01:00
f4fee26fe4 chore(deps): update dependency sass to v1.47.0 (#1333)
Reviewed-on: vikunja/frontend#1333
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-08 11:03:51 +00:00
00398085fd chore(deps): update dependency caniuse-lite to v1.0.30001298 (#1334)
Reviewed-on: vikunja/frontend#1334
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-08 10:54:58 +00:00
13c8e6dbcd fix(deps): update dependency v-tooltip to v4.0.0-beta.13 (#1332)
Reviewed-on: vikunja/frontend#1332
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-07 16:21:41 +00:00
1b5f8a069b chore(deps): update dependency netlify-cli to v8.6.15 (#1331)
Reviewed-on: vikunja/frontend#1331
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-07 16:21:27 +00:00
21fec9461d chore(deps): update dependency vitest to v0.0.139 (#1330)
Reviewed-on: vikunja/frontend#1330
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-07 16:21:11 +00:00
df3af739f8 chore(deps): update dependency autoprefixer to v10.4.2 (#1329)
Reviewed-on: vikunja/frontend#1329
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-07 16:20:45 +00:00
b08d34bc96 fix(deps): update dependency v-tooltip to v4.0.0-beta.11 (#1326)
Reviewed-on: vikunja/frontend#1326
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-07 08:26:54 +00:00
be03efd015 chore(deps): update dependency caniuse-lite to v1.0.30001297 (#1327)
Reviewed-on: vikunja/frontend#1327
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-07 08:26:35 +00:00
c353fd151d chore(deps): update dependency vitest to v0.0.136 (#1325)
Reviewed-on: vikunja/frontend#1325
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-06 21:23:31 +00:00
c32e9badf0 chore(deps): update dependency netlify-cli to v8.6.12 (#1322)
Reviewed-on: vikunja/frontend#1322
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-06 19:39:31 +00:00
8f64ab5dce chore(deps): update dependency vitest to v0.0.135 (#1323)
Reviewed-on: vikunja/frontend#1323
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-06 19:39:11 +00:00
63ca8ffc7c fix(deps): update dependency v-tooltip to v4.0.0-beta.10 (#1324)
Reviewed-on: vikunja/frontend#1324
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-06 19:38:46 +00:00
fe9ddf33ca fix(deps): update dependency marked to v4.0.9 (#1321)
Reviewed-on: vikunja/frontend#1321
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-06 16:26:02 +00:00
74777d6bed chore(deps): update dependency netlify-cli to v8.6.9 (#1320)
Reviewed-on: vikunja/frontend#1320
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-06 16:25:44 +00:00
76d1c56fab chore(deps): update dependency netlify-cli to v8.6.8 (#1318)
Reviewed-on: vikunja/frontend#1318
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-06 15:23:22 +00:00
f75e9135c2 fix(deps): update dependency highlight.js to v11.4.0 (#1319)
Reviewed-on: vikunja/frontend#1319
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-06 15:23:08 +00:00
480f0f8da9 fix(deps): update dependency v-tooltip to v4.0.0-beta.8 (#1317)
Reviewed-on: vikunja/frontend#1317
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-06 14:05:02 +00:00
ac832186d6 chore(deps): update dependency netlify-cli to v8.6.6 (#1316)
Reviewed-on: vikunja/frontend#1316
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-06 11:38:23 +00:00
738e1e8370 chore(deps): update dependency sass to v1.46.0 (#1315)
Reviewed-on: vikunja/frontend#1315
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-06 11:10:06 +00:00
Dominik Pschenitschni
9b85817ddb feat: run vue-tsc in ci (#1295)
We had this in for a while already, but never cared for the result.
Might make sense to integrate in the pipeline.

To make things easy from the start we could add [`failure: ignore`](https://docs.drone.io/pipeline/macstadium/syntax/steps/#failure) to the step

Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: vikunja/frontend#1295
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-01-06 10:37:51 +00:00
Dominik Pschenitschni
49a6569db0 fix: remove obsolet code (#1312)
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: vikunja/frontend#1312
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-01-06 10:34:14 +00:00
e762f7f073 chore(deps): update dependency vitest to v0.0.134 (#1314)
Reviewed-on: vikunja/frontend#1314
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-06 10:33:07 +00:00
e5d2b23cb3 chore(deps): update dependency netlify-cli to v8.6.5 2022-01-05 21:05:56 +00:00
6eddf23c0d fix(deps): update dependency vue-advanced-cropper to v2.7.1 2022-01-05 17:03:11 +00:00
70934c6a0b fix(deps): pin dependency @types/is-touch-device to 1.0.0 (#1308)
Reviewed-on: vikunja/frontend#1308
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-05 16:45:48 +00:00
49955eb03a
fix: remove some of the typescript warnings 2022-01-05 16:17:14 +01:00
2b302974cc chore(deps): update dependency vitest to v0.0.133 2022-01-05 14:52:22 +00:00
Dominik Pschenitschni
64d632b0a5 [skip ci] Updated translations via Crowdin 2022-01-05 14:36:24 +00:00
Dominik Pschenitschni
e28f0f5be4 chore(addTask) improve order (#1297)
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: vikunja/frontend#1297
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-01-05 13:14:50 +00:00
c618b7e0b6 fix: namespace new buttons on mobile (#1262)
Before:

![image](/attachments/7626e28d-8a13-4f92-b162-697676f765c7)

After:

![image](/attachments/5331af47-4887-4ba5-98d7-ee70311e20d7)

Co-authored-by: kolaente <k@knt.li>
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: vikunja/frontend#1262
Reviewed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
2022-01-05 12:46:33 +00:00
380af7fbf2 fix(deps): update dependency @vueuse/router to v7.5.3 (#1303)
Reviewed-on: vikunja/frontend#1303
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2022-01-05 11:44:12 +00:00
9d3ef30be6 fix(deps): update dependency @vueuse/core to v7.5.2 2022-01-05 10:03:09 +00:00
fc00169863 chore(deps): update dependency vitest to v0.0.132 2022-01-05 09:21:26 +00:00
b652225a12 fix(deps): update dependency @vueuse/router to v7.5.2 2022-01-05 08:02:58 +00:00
29d8422e94
fix(ready): remove class form fragment 2022-01-04 21:15:02 +01:00
Dominik Pschenitschni
cdbd1c2ac4 feat: create BaseButton component (#1123)
Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: vikunja/frontend#1123
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-01-04 18:58:06 +00:00
cb37fd773d feat: convert to composable useDateTimeSalutation 2022-01-04 18:44:07 +00:00
d2577f1df6 feat: use useNow to provide auto updates 2022-01-04 18:44:07 +00:00
27534a98e9 feat: return full translation key 2022-01-04 18:44:07 +00:00
de77393905 feat: move the calculation of the current salutation to a different function 2022-01-04 18:44:07 +00:00
dd450263fb chore(deps): pin dependency happy-dom to 2.25.1 2022-01-04 18:03:16 +00:00
d8106dcb73 chore(deps): update dependency vitest to v0.0.131 2022-01-04 14:03:26 +00:00
8114012997
feat: replace jest with vitest 2022-01-04 14:16:47 +01:00
bc4ea82639 chore(deps): update dependency netlify-cli to v8.6.4 2022-01-04 13:03:16 +00:00
cd97cfe612 chore(deps): update dependency netlify-cli to v8.6.3 2022-01-04 12:03:19 +00:00
e6136fdee4 chore(deps): update dependency caniuse-lite to v1.0.30001296 2022-01-04 11:48:22 +00:00
2c395c720a chore(deps): update dependency vue-tsc to v0.30.2 2022-01-04 11:48:01 +00:00
8b639fd4af chore(deps): update dependency rollup to v2.63.0 2022-01-04 08:03:11 +00:00
f7bd5f13ac fix(deps): update dependency v-tooltip to v4.0.0-beta.6 2022-01-03 20:03:15 +00:00
0ae774b95c chore(deps): update typescript-eslint monorepo to v5.9.0 2022-01-03 19:04:33 +00:00
be899c3eb0 chore(deps): update dependency eslint to v8.6.0 2022-01-03 15:40:28 +00:00
dc02827a33 chore(deps): update dependency slugify to v1.6.5 2022-01-03 15:39:59 +00:00
951e511bf9
chore(deps): update dependency postcss-preset-env to v7.2.0 2022-01-03 16:21:43 +01:00
5f1d936ca4 fix(deps): update dependency v-tooltip to v4.0.0-beta.5 2022-01-03 15:15:05 +00:00
c3845e5690 chore(deps): update dependency netlify-cli to v8.6.1 2022-01-03 14:03:10 +00:00
f4db2df37b chore(deps): update dependency caniuse-lite to v1.0.30001295 2022-01-02 00:02:54 +00:00
5668fc7a2c chore(deps): update dependency esbuild to v0.14.10 2021-12-31 17:02:57 +00:00
12a0099fbf chore(deps): update dependency sass to v1.45.2 (#1271)
Reviewed-on: vikunja/frontend#1271
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-31 15:31:03 +00:00
7f4027cbe8 fix(deps): update dependency @vueuse/core to v7.5.1 (#1272)
Reviewed-on: vikunja/frontend#1272
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-31 15:30:46 +00:00
b57aa33cae fix(deps): update dependency @vueuse/router to v7.5.1 (#1273)
Reviewed-on: vikunja/frontend#1273
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-31 13:06:00 +00:00
b80de79594 fix(deps): update dependency @vueuse/router to v7.4.3 2021-12-31 00:02:51 +00:00
ead3e45a59 chore(deps): update dependency @types/jest to v27.4.0 2021-12-30 21:02:53 +00:00
4a7d2d8414 feat: save and restore the user language on the server (#1181)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/frontend#1181
Reviewed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
2021-12-30 20:20:45 +00:00
0befa58908 fix: blockquote styling in dark mode 2021-12-30 15:59:59 +00:00
8ae84eaf42 fix: padding and centering of the kanban limit and dropdown 2021-12-30 15:59:59 +00:00
cd10bc9d7a fix(gantt): use function to create default date 2021-12-30 13:05:29 +00:00
f4545fbe2f fix(deps): update dependency @vueuse/core to v7.4.3 (#1266)
Reviewed-on: vikunja/frontend#1266
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-30 12:04:16 +00:00
c6ffe8acab chore(deps): update dependency vite to v2.7.10 (#1265)
Reviewed-on: vikunja/frontend#1265
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-30 08:52:41 +00:00
2fb16f9a77 fix(deps): update dependency vue-i18n to v9.2.0-beta.26 (#1263)
Reviewed-on: vikunja/frontend#1263
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-29 23:13:35 +00:00
be427449e4 chore(deps): update dependency netlify-cli to v8.6.0 (#1259)
Reviewed-on: vikunja/frontend#1259
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-29 20:56:08 +00:00
5e889ebe36 chore(deps): update dependency autoprefixer to v10.4.1 (#1260)
Reviewed-on: vikunja/frontend#1260
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-29 20:06:07 +00:00
8c62c96109 chore(deps): update dependency esbuild to v0.14.9 (#1258)
Reviewed-on: vikunja/frontend#1258
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-29 13:34:16 +00:00
7908a1e657 chore(deps): update dependency caniuse-lite to v1.0.30001294 (#1257)
Reviewed-on: vikunja/frontend#1257
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-28 22:03:48 +00:00
09b62da2ae fix(deps): update dependency date-fns to v2.28.0 (#1256)
Reviewed-on: vikunja/frontend#1256
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-28 17:30:07 +00:00
076494afa5 chore(deps): update dependency netlify-cli to v8.5.0 (#1255)
Reviewed-on: vikunja/frontend#1255
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-28 17:12:35 +00:00
b604d5da75 chore(deps): update dependency vite to v2.7.9 (#1254)
Reviewed-on: vikunja/frontend#1254
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-28 17:11:48 +00:00
59889cccf3 chore(deps): update typescript-eslint monorepo to v5.8.1 (#1253)
Reviewed-on: vikunja/frontend#1253
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-27 19:19:38 +00:00
f8ffb428d3 chore(deps): update dependency rollup to v2.62.0 (#1246)
Reviewed-on: vikunja/frontend#1246
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-27 11:00:46 +00:00
c2ea932c09 [skip ci] Updated translations via Crowdin 2021-12-26 19:09:18 +00:00
033d97e919 chore(deps): update dependency @vue/eslint-config-typescript to v10 (#1243)
Reviewed-on: vikunja/frontend#1243
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-26 17:45:55 +00:00
4694c14760 chore(deps): update dependency vue-tsc to v0.30.1 (#1248)
Reviewed-on: vikunja/frontend#1248
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-12-26 17:45:33 +00:00
127 changed files with 2930 additions and 3386 deletions

View File

@ -98,6 +98,15 @@ steps:
depends_on:
- dependencies
- name: typecheck
failure: ignore
image: node:16
pull: true
commands:
- yarn typecheck
depends_on:
- dependencies
- name: test-frontend
image: cypress/browsers:node16.5.0-chrome94-ff93
pull: true
@ -107,36 +116,16 @@ steps:
YARN_CACHE_FOLDER: .cache/yarn/
CYPRESS_CACHE_FOLDER: .cache/cypress/
CYPRESS_DEFAULT_COMMAND_TIMEOUT: 60000
CYPRESS_RECORD_KEY:
from_secret: cypress_project_key
commands:
- sed -i 's/localhost/api/g' dist/index.html
- yarn serve:dist & npx wait-on http://localhost:5000
- yarn test:frontend --browser chrome
- yarn test:frontend --browser chrome --record
depends_on:
- dependencies
- build-prod
- name: upload-test-results
image: plugins/s3
pull: true
settings:
bucket: drone-test-results
access_key:
from_secret: test_results_aws_access_key_id
secret_key:
from_secret: test_results_aws_secret_access_key
endpoint: https://s3.fr-par.scw.cloud
region: fr-par
path_style: true
source: cypress/screenshots/**/**/*
strip_prefix: cypress/screenshots/
target: /${DRONE_REPO}/${DRONE_PULL_REQUEST}_${DRONE_BRANCH}/${DRONE_BUILD_NUMBER}/
depends_on:
- test-frontend
when:
status:
- failure
- success
- name: deploy-preview
image: node:16
pull: true
@ -656,6 +645,6 @@ steps:
from_secret: crowdin_key
---
kind: signature
hmac: 188ee90100c5fc5922a445e531e7a47453121edddb2a64a182eb23ed2bf602de
hmac: 997e1badebe484ac29557c4af356e63db4d3d57f3d32e92d482f117f8cec64da
...

View File

@ -7,5 +7,6 @@
"video": false,
"retries": {
"runMode": 2
}
},
"projectId": "181c7x"
}

View File

@ -1,4 +1,4 @@
import faker from 'faker'
import faker from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'

View File

@ -1,4 +1,4 @@
import faker from 'faker'
import faker from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'

View File

@ -1,6 +1,6 @@
import {Factory} from '../support/factory'
import {formatISO} from "date-fns"
import faker from 'faker'
import faker from '@faker-js/faker'
export class LinkShareFactory extends Factory {
static table = 'link_shares'

View File

@ -1,6 +1,6 @@
import {Factory} from '../support/factory'
import {formatISO} from "date-fns"
import faker from 'faker'
import faker from '@faker-js/faker'
export class ListFactory extends Factory {
static table = 'lists'

View File

@ -1,4 +1,4 @@
import faker from 'faker'
import faker from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'

View File

@ -1,4 +1,4 @@
import faker from 'faker'
import faker from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'

View File

@ -1,4 +1,4 @@
import faker from 'faker'
import faker from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from "date-fns"

View File

@ -1,4 +1,4 @@
import faker from 'faker'
import faker from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from 'date-fns'

View File

@ -1,4 +1,4 @@
import faker from 'faker'
import faker from '@faker-js/faker'
import {Factory} from '../support/factory'
import {formatISO} from "date-fns"

View File

@ -31,7 +31,7 @@ describe('Lists', () => {
cy.url()
.should('contain', '/namespaces/1/list')
cy.get('.card-header-title')
.contains('Create a new list')
.contains('New list')
cy.get('input.input')
.type('New List')
cy.get('.button')
@ -101,7 +101,7 @@ describe('Lists', () => {
.click()
cy.url()
.should('contain', '/settings/delete')
cy.get('.modal-mask .modal-container .modal-content .actions a.button')
cy.get('[data-cy="modalPrimary"]')
.contains('Do it')
.click()
@ -392,7 +392,7 @@ describe('Lists', () => {
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item .field input.input')
.first()
.type(3)
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item .field a.button.is-primary')
cy.get('[data-cy="setBucketLimit"]')
.first()
.click()

View File

@ -15,7 +15,7 @@ describe('Namepaces', () => {
it('Should be all there', () => {
cy.visit('/namespaces')
cy.get('.namespace h1 span')
cy.get('[data-cy="namespace-title"]')
.should('contain', namespaces[0].title)
})
@ -23,14 +23,14 @@ describe('Namepaces', () => {
const newNamespaceTitle = 'New Namespace'
cy.visit('/namespaces')
cy.get('a.button')
.contains('Create a new namespace')
cy.get('[data-cy="new-namespace"]')
.should('contain', 'New namespace')
.click()
cy.url()
.should('contain', '/namespaces/new')
cy.get('.card-header-title')
.should('contain', 'Create a new namespace')
.should('contain', 'New namespace')
cy.get('input.input')
.type(newNamespaceTitle)
cy.get('.button')
@ -72,7 +72,7 @@ describe('Namepaces', () => {
cy.get('.namespace-container .menu.namespaces-lists')
.should('contain', newNamespaceName)
.should('not.contain', newNamespaces[0].title)
cy.get('.content.namespaces-list')
cy.get('[data-cy="namespaces-list"]')
.should('contain', newNamespaceName)
.should('not.contain', newNamespaces[0].title)
})
@ -89,7 +89,7 @@ describe('Namepaces', () => {
.click()
cy.url()
.should('contain', '/settings/delete')
cy.get('.modal-mask .modal-container .modal-content .actions a.button')
cy.get('[data-cy="modalPrimary"]')
.contains('Do it')
.click()
@ -116,30 +116,30 @@ describe('Namepaces', () => {
// Initial
cy.visit('/namespaces')
cy.get('.namespaces-list .namespace')
cy.get('.namespace')
.should('not.contain', 'Archived')
// Show archived
cy.get('.namespaces-list .fancycheckbox.show-archived-check label.check span')
cy.get('[data-cy="show-archived-check"] label.check span')
.should('be.visible')
.click()
cy.get('.namespaces-list .fancycheckbox.show-archived-check input')
cy.get('[data-cy="show-archived-check"] input')
.should('be.checked')
cy.get('.namespaces-list .namespace')
cy.get('.namespace')
.should('contain', 'Archived')
// Don't show archived
cy.get('.namespaces-list .fancycheckbox.show-archived-check label.check span')
cy.get('[data-cy="show-archived-check"] label.check span')
.should('be.visible')
.click()
cy.get('.namespaces-list .fancycheckbox.show-archived-check input')
cy.get('[data-cy="show-archived-check"] input')
.should('not.be.checked')
// Second time visiting after unchecking
cy.visit('/namespaces')
cy.get('.namespaces-list .fancycheckbox.show-archived-check input')
cy.get('[data-cy="show-archived-check"] input')
.should('not.be.checked')
cy.get('.namespaces-list .namespace')
cy.get('.namespace')
.should('not.contain', 'Archived')
})
})

View File

@ -1,35 +0,0 @@
import '../../support/authenticateUser'
const setHours = hours => {
const date = new Date()
date.setHours(hours)
cy.clock(+date)
}
describe('Home Page', () => {
it('shows the right salutation in the night', () => {
setHours(4)
cy.visit('/')
cy.get('h2').should('contain', 'Good Night')
})
it('shows the right salutation in the morning', () => {
setHours(8)
cy.visit('/')
cy.get('h2').should('contain', 'Good Morning')
})
it('shows the right salutation in the day', () => {
setHours(13)
cy.visit('/')
cy.get('h2').should('contain', 'Hi')
})
it('shows the right salutation in the night', () => {
setHours(20)
cy.visit('/')
cy.get('h2').should('contain', 'Good Evening')
})
it('shows the right salutation in the night again', () => {
setHours(23)
cy.visit('/')
cy.get('h2').should('contain', 'Good Night')
})
})

View File

@ -128,7 +128,7 @@ describe('Task', () => {
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .action-buttons .button')
.contains('Done!')
.contains('Mark task done!')
.click()
cy.get('.task-view .heading .is-done')
@ -168,7 +168,7 @@ describe('Task', () => {
.click()
cy.get('.task-view .details.content.description .editor .vue-easymde .EasyMDEContainer .CodeMirror-scroll')
.type('{selectall}New Description')
cy.get('.task-view .details.content.description .editor a')
cy.get('[data-cy="saveEditor"]')
.contains('Save')
.click()
@ -404,7 +404,7 @@ describe('Task', () => {
cy.get('.datepicker .datepicker-popup a')
.contains('Tomorrow')
.click()
cy.get('.datepicker .datepicker-popup a.button')
cy.get('[data-cy="closeDatepicker"]')
.contains('Confirm')
.click()

View File

@ -8,21 +8,23 @@ describe('User Settings', () => {
})
it('Changes the user avatar', () => {
cy.intercept(`${Cypress.env('API_URL')}/user/settings/avatar/upload`).as('uploadAvatar')
cy.visit('/user/settings/avatar')
cy.get('input[name=avatarProvider][value=upload]')
.click()
cy.get('input[type=file]', { timeout: 1000 })
.attachFile('image.jpg')
cy.get('input[type=file]', {timeout: 1000})
.selectFile('cypress/fixtures/image.jpg', {force: true}) // The input is not visible, but on purpose
cy.get('.vue-handler-wrapper.vue-handler-wrapper--south .vue-simple-handler.vue-simple-handler--south')
.trigger('mousedown', {which: 1})
.trigger('mousemove', {clientY: 100})
.trigger('mouseup')
cy.get('a.button.is-primary')
cy.get('[data-cy="uploadAvatar"]')
.contains('Upload Avatar')
.click()
cy.wait(3000) // Wait for the request to finish
cy.wait('@uploadAvatar')
cy.get('.global-notification')
.should('contain', 'Success')
})
@ -33,7 +35,7 @@ describe('User Settings', () => {
cy.get('.general-settings .control input.input')
.first()
.type('Lorem Ipsum')
cy.get('.card.general-settings .button.is-primary')
cy.get('[data-cy="saveGeneralSettings"]')
.contains('Save')
.click()

View File

@ -1,6 +1,5 @@
import './commands'
import 'cypress-file-upload'
import '@4tw/cypress-drag-drop'
// see https://github.com/cypress-io/cypress/issues/702#issuecomment-587127275

View File

@ -9,44 +9,46 @@
"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/",
"typecheck": "vue-tsc --noEmit",
"lint": "eslint --ignore-pattern '*.test.*' ./src --ext .vue,.js,.ts",
"lint:markup": "vue-tsc --noEmit",
"cypress:open": "cypress open",
"test:unit": "jest",
"test:unit": "vitest run",
"test:unit-watch": "vitest watch",
"test:frontend": "cypress run",
"browserslist:update": "npx browserslist@latest --update-db"
},
"dependencies": {
"@github/hotkey": "1.6.1",
"@github/hotkey": "2.0.0",
"@kyvg/vue3-notification": "2.3.4",
"@sentry/tracing": "6.16.1",
"@sentry/vue": "6.16.1",
"@vue/compat": "3.2.26",
"@vueuse/core": "7.4.1",
"@vueuse/router": "7.4.1",
"@sentry/tracing": "6.17.4",
"@sentry/vue": "6.17.4",
"@types/is-touch-device": "1.0.0",
"@vue/compat": "3.2.29",
"@vueuse/core": "7.5.5",
"@vueuse/router": "7.5.5",
"bulma-css-variables": "0.9.33",
"camel-case": "4.1.2",
"codemirror": "5.65.0",
"codemirror": "5.65.1",
"copy-to-clipboard": "3.3.1",
"date-fns": "2.27.0",
"dompurify": "2.3.4",
"easymde": "2.15.0",
"date-fns": "2.28.0",
"dompurify": "2.3.5",
"easymde": "2.16.1",
"flatpickr": "4.6.9",
"flexsearch": "0.7.21",
"highlight.js": "11.3.1",
"highlight.js": "11.4.0",
"is-touch-device": "1.0.1",
"lodash.clonedeep": "4.5.0",
"lodash.debounce": "4.0.8",
"marked": "4.0.8",
"marked": "4.0.12",
"register-service-worker": "1.7.2",
"snake-case": "3.0.4",
"ufo": "0.7.9",
"v-tooltip": "4.0.0-beta.2",
"vue": "3.2.26",
"vue-advanced-cropper": "2.7.0",
"ufo": "0.7.10",
"v-tooltip": "4.0.0-beta.17",
"vue": "3.2.29",
"vue-advanced-cropper": "2.8.0",
"vue-drag-resize": "2.0.3",
"vue-flatpickr-component": "9.0.5",
"vue-i18n": "9.2.0-beta.25",
"vue-i18n": "9.2.0-beta.30",
"vue-router": "4.0.12",
"vuedraggable": "4.1.0",
"vuex": "4.0.2",
@ -54,42 +56,40 @@
},
"devDependencies": {
"@4tw/cypress-drag-drop": "2.1.0",
"@faker-js/faker": "6.0.0-alpha.5",
"@fortawesome/fontawesome-svg-core": "1.2.36",
"@fortawesome/free-regular-svg-icons": "5.15.4",
"@fortawesome/free-solid-svg-icons": "5.15.4",
"@fortawesome/vue-fontawesome": "3.0.0-5",
"@types/flexsearch": "0.7.2",
"@types/jest": "27.0.3",
"@typescript-eslint/eslint-plugin": "5.8.0",
"@typescript-eslint/parser": "5.8.0",
"@typescript-eslint/eslint-plugin": "5.10.2",
"@typescript-eslint/parser": "5.10.2",
"@vitejs/plugin-legacy": "1.6.4",
"@vitejs/plugin-vue": "2.0.1",
"@vue/eslint-config-typescript": "9.1.0",
"autoprefixer": "10.4.0",
"axios": "0.24.0",
"@vitejs/plugin-vue": "2.1.0",
"@vue/eslint-config-typescript": "10.0.0",
"autoprefixer": "10.4.2",
"axios": "0.25.0",
"browserslist": "4.19.1",
"caniuse-lite": "1.0.30001292",
"cypress": "9.2.0",
"cypress-file-upload": "5.0.8",
"esbuild": "0.14.8",
"eslint": "8.5.0",
"eslint-plugin-vue": "8.2.0",
"caniuse-lite": "1.0.30001307",
"cypress": "9.4.1",
"esbuild": "0.14.18",
"eslint": "8.8.0",
"eslint-plugin-vue": "8.4.1",
"express": "4.17.2",
"faker": "5.5.3",
"jest": "27.4.5",
"netlify-cli": "8.4.2",
"postcss": "8.4.5",
"postcss-preset-env": "7.1.0",
"rollup": "2.61.1",
"rollup-plugin-visualizer": "5.5.2",
"sass": "1.45.1",
"slugify": "1.6.4",
"ts-jest": "27.1.2",
"typescript": "4.5.4",
"vite": "2.7.7",
"vite-plugin-pwa": "0.11.12",
"vite-svg-loader": "3.1.1",
"vue-tsc": "0.30.0",
"happy-dom": "2.31.1",
"netlify-cli": "8.15.0",
"postcss": "8.4.6",
"postcss-preset-env": "7.3.1",
"rollup": "2.67.0",
"rollup-plugin-visualizer": "5.5.4",
"sass": "1.49.7",
"slugify": "1.6.5",
"typescript": "4.5.5",
"vite": "2.7.13",
"vite-plugin-pwa": "0.11.13",
"vite-svg-loader": "3.1.2",
"vitest": "0.2.7",
"vue-tsc": "0.31.1",
"wait-on": "6.0.0",
"workbox-cli": "6.4.2"
},
@ -144,24 +144,6 @@
"autoprefixer": {}
}
},
"jest": {
"testPathIgnorePatterns": [
"cypress"
],
"testEnvironment": "jsdom",
"preset": "ts-jest",
"roots": [
"<rootDir>/src"
],
"transform": {
"^.+\\.(js|tsx?)$": "ts-jest"
},
"moduleFileExtensions": [
"ts",
"js",
"json"
]
},
"license": "AGPL-3.0-or-later",
"packageManager": "yarn@1.22.17"
}

View File

@ -3,5 +3,11 @@
"labels": ["dependencies"],
"extends": [
"config:base"
],
"packageRules": [
{
"matchPackageNames": ["netlify-cli"],
"extends": ["schedule:weekly"]
}
]
}

View File

@ -1,16 +1,14 @@
<template>
<ready :class="{'is-touch': isTouch}">
<div :class="{'is-hidden': !online}">
<template v-if="authUser">
<top-navigation/>
<content-auth/>
</template>
<content-link-share v-else-if="authLinkShare"/>
<no-auth-wrapper v-else>
<router-view/>
</no-auth-wrapper>
<Notification/>
</div>
<ready>
<template v-if="authUser">
<top-navigation/>
<content-auth/>
</template>
<content-link-share v-else-if="authLinkShare"/>
<no-auth-wrapper v-else>
<router-view/>
</no-auth-wrapper>
<Notification/>
<transition name="fade">
<keyboard-shortcuts v-if="keyboardShortcutsActive"/>
@ -19,12 +17,11 @@
</template>
<script lang="ts" setup>
import {computed, watch, watchEffect, Ref} from 'vue'
import {computed, watch, Ref} from 'vue'
import {useRouter} from 'vue-router'
import {useRouteQuery} from '@vueuse/router'
import {useStore} from 'vuex'
import {useI18n} from 'vue-i18n'
import {useOnline} from '@vueuse/core'
import isTouchDevice from 'is-touch-device'
import {success} from '@/message'
@ -38,17 +35,14 @@ import Ready from '@/components/misc/ready.vue'
import {setLanguage} from './i18n'
import AccountDeleteService from '@/services/accountDelete'
import {ONLINE} from '@/store/mutation-types'
import {useColorScheme} from '@/composables/useColorScheme'
import {useBodyClass} from '@/composables/useBodyClass'
const store = useStore()
const online = useOnline()
watchEffect(() => store.commit(ONLINE, online.value))
const router = useRouter()
const isTouch = computed(isTouchDevice)
useBodyClass('is-touch', isTouchDevice())
const keyboardShortcutsActive = computed(() => store.state.keyboardShortcutsActive)
const authUser = computed(() => store.getters['auth/authUser'])

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -0,0 +1,118 @@
<template>
<component
:is="componentNodeName"
class="base-button"
:class="{ 'base-button--type-button': isButton }"
v-bind="elementBindings"
:disabled="disabled || undefined"
>
<slot />
</component>
</template>
<script lang="ts">
// see https://v3.vuejs.org/api/sfc-script-setup.html#usage-alongside-normal-script
export default {
inheritAttrs: false,
}
</script>
<script lang="ts" setup>
// this component removes styling differences between links / vue-router links and button elements
// by doing so we make it easy abstract the functionality from style and enable easier and semantic
// correct button and link usage. Also see: https://css-tricks.com/a-complete-guide-to-links-and-buttons/#accessibility-considerations
// the component tries to heuristically determine what it should be checking the props (see the
// componentNodeName and elementBindings ref for this).
// NOTE: Do NOT use buttons with @click to push routes. => Use router-links instead!
import { ref, watchEffect, computed, useAttrs, PropType } from 'vue'
const BASE_BUTTON_TYPES_MAP = Object.freeze({
button: 'button',
submit: 'submit',
})
type BaseButtonTypes = keyof typeof BASE_BUTTON_TYPES_MAP
const props = defineProps({
type: {
type: String as PropType<BaseButtonTypes>,
default: 'button',
},
disabled: {
type: Boolean,
default: false,
},
})
const componentNodeName = ref<Node['nodeName']>('button')
interface ElementBindings {
type?: string;
rel?: string,
}
const elementBindings = ref({})
const attrs = useAttrs()
watchEffect(() => {
// by default this component is a button element with the attribute of the type "button" (default prop value)
let nodeName = 'button'
let bindings: ElementBindings = {type: props.type}
// if we find a "to" prop we set it as router-link
if ('to' in attrs) {
nodeName = 'router-link'
bindings = {}
}
// if there is a href we assume the user wants an external link via a link element
// we also set the attribute rel to "noopener" but make it possible to overwrite this by the user.
if ('href' in attrs) {
nodeName = 'a'
bindings = {rel: 'noopener'}
}
componentNodeName.value = nodeName
elementBindings.value = {
...bindings,
...attrs,
}
})
const isButton = computed(() => componentNodeName.value === 'button')
</script>
<style lang="scss">
// NOTE: we do not use scoped styles to reduce specifity and make it easy to overwrite
// We reset the default styles of a button element to enable easier styling
:where(.base-button--type-button) {
border: 0;
margin: 0;
padding: 0;
text-decoration: none;
background-color: transparent;
text-align: center;
appearance: none;
}
:where(.base-button) {
cursor: pointer;
display: block;
color: inherit;
font: inherit;
user-select: none;
pointer-events: auto; // disable possible resets
&:focus {
outline: transparent;
}
&[disabled] {
cursor: default;
}
}
</style>

View File

@ -9,7 +9,7 @@
class="app-container"
>
<navigation/>
<div
<main
:class="[
{ 'is-menu-enabled': menuActive },
$route.name,
@ -35,7 +35,7 @@
>
<icon icon="keyboard"/>
</a>
</div>
</main>
</div>
</div>
</template>

View File

@ -1,6 +1,6 @@
<template>
<div
:class="[background ? 'has-background' : '', $route.name+'-view']"
:class="[background ? 'has-background' : '', $route.name as string +'-view']"
:style="{'background-image': `url(${background})`}"
class="link-share-container"
>

View File

@ -1,8 +1,8 @@
<template>
<div :class="{'is-active': menuActive}" class="namespace-container">
<div class="menu top-menu">
<aside :class="{'is-active': menuActive}" class="namespace-container">
<nav class="menu top-menu">
<router-link :to="{name: 'home'}" class="logo">
<Logo width="164" height="48" />
<Logo width="164" height="48"/>
</router-link>
<ul class="menu-list">
<li>
@ -46,31 +46,35 @@
</router-link>
</li>
</ul>
</div>
</nav>
<aside class="menu namespaces-lists loader-container is-loading-small" :class="{'is-loading': loading}">
<template v-for="(n, nk) in namespaces" :key="n.id" >
<nav class="menu namespaces-lists loader-container is-loading-small" :class="{'is-loading': loading}">
<template v-for="(n, nk) in namespaces" :key="n.id">
<div class="namespace-title" :class="{'has-menu': n.id > 0}">
<span
@click="toggleLists(n.id)"
class="menu-label"
v-tooltip="namespaceTitles[nk]">
v-tooltip="namespaceTitles[nk]"
>
<span
v-if="n.hexColor !== ''"
:style="{ backgroundColor: n.hexColor }"
class="color-bubble"
/>
<span class="name">
<span
:style="{ backgroundColor: n.hexColor }"
class="color-bubble"
v-if="n.hexColor !== ''">
</span>
{{ namespaceTitles[nk] }}
</span>
<a
class="icon is-small toggle-lists-icon pl-2"
:class="{'active': typeof listsVisible[n.id] !== 'undefined' ? listsVisible[n.id] : true}"
@click="toggleLists(n.id)"
>
<icon icon="chevron-down"/>
</a>
<span class="count" :class="{'ml-2 mr-0': n.id > 0}">
({{ namespaceListsCount[nk] }})
</span>
</span>
<a
class="icon is-small toggle-lists-icon"
:class="{'active': typeof listsVisible[n.id] !== 'undefined' ? listsVisible[n.id] : true}"
@click="toggleLists(n.id)"
>
<icon icon="chevron-down"/>
</a>
<namespace-settings-dropdown :namespace="n" v-if="n.id > 0"/>
</div>
<div
@ -81,18 +85,20 @@
<!--
NOTE: a v-model / computed setter is not possible, since the updateActiveLists function
triggered by the change needs to have access to the current namespace
-->
-->
<draggable
v-bind="dragOptions"
:modelValue="activeLists[nk]"
@update:modelValue="(lists) => updateActiveLists(n, lists)"
:group="`namespace-${n.id}-lists`"
group="namespace-lists"
@start="() => drag = true"
@end="e => saveListPosition(e, nk)"
@end="saveListPosition"
handle=".handle"
:disabled="n.id < 0 || null"
tag="transition-group"
item-key="id"
:data-namespace-id="n.id"
:data-namespace-index="nk"
:component-data="{
type: 'transition',
tag: 'ul',
@ -134,7 +140,7 @@
:class="{'is-favorite': l.isFavorite}"
@click.prevent.stop="toggleFavoriteList(l)"
class="favorite">
<icon :icon="l.isFavorite ? 'star' : ['far', 'star']" />
<icon :icon="l.isFavorite ? 'star' : ['far', 'star']"/>
</span>
</a>
</router-link>
@ -145,9 +151,9 @@
</draggable>
</div>
</template>
</aside>
<PoweredByLink />
</div>
</nav>
<PoweredByLink/>
</aside>
</template>
<script>
@ -194,13 +200,13 @@ export default {
loading: state => state[LOADING] && state[LOADING_MODULE] === 'namespaces',
}),
activeLists() {
return this.namespaces.map(({lists}) => lists?.filter(item => !item.isArchived))
return this.namespaces.map(({lists}) => lists?.filter(item => typeof item !== 'undefined' && !item.isArchived))
},
namespaceTitles() {
return this.namespaces.map((namespace, index) => {
const title = this.getNamespaceTitle(namespace)
return `${title} (${this.activeLists[index]?.length ?? 0})`
})
return this.namespaces.map((namespace) => this.getNamespaceTitle(namespace))
},
namespaceListsCount() {
return this.namespaces.map((_, index) => this.activeLists[index]?.length ?? 0)
},
},
beforeCreate() {
@ -237,15 +243,15 @@ export default {
this.listsVisible[namespaceId] = !this.listsVisible[namespaceId]
},
updateActiveLists(namespace, activeLists) {
// this is a bit hacky: since we do have to filter out the archived items from the list
// This is a bit hacky: since we do have to filter out the archived items from the list
// for vue draggable updating it is not as simple as replacing it.
// instead we iterate over the non archived items in the old list and replace them with the ones in their new order
const lists = namespace.lists.map((item) => {
if (item.isArchived) {
return item
}
return activeLists.shift()
})
// To work around this, we merge the active lists with the archived ones. Doing so breaks the order
// because now all archived lists are sorted after the active ones. This is fine because they are sorted
// later when showing them anyway, and it makes the merging happening here a lot easier.
const lists = [
...activeLists,
...namespace.lists.filter(l => l.isArchived),
]
const newNamespace = {
...namespace,
@ -255,8 +261,11 @@ export default {
this.$store.commit('namespaces/setNamespaceById', newNamespace)
},
async saveListPosition(e, namespaceIndex) {
const listsActive = this.activeLists[namespaceIndex]
async saveListPosition(e) {
const namespaceId = parseInt(e.to.dataset.namespaceId)
const newNamespaceIndex = parseInt(e.to.dataset.namespaceIndex)
const listsActive = this.activeLists[newNamespaceIndex]
const list = listsActive[e.newIndex]
const listBefore = listsActive[e.newIndex - 1] ?? null
const listAfter = listsActive[e.newIndex + 1] ?? null
@ -269,6 +278,7 @@ export default {
await this.$store.dispatch('lists/updateList', {
...list,
position,
namespaceId,
})
} finally {
this.listUpdating[list.id] = false
@ -365,8 +375,9 @@ $vikunja-nav-selected-width: 0.4rem;
.menu-label {
.color-bubble {
width: 14px !important;
height: 14px !important;
width: 14px;
height: 14px;
flex-basis: auto;
}
.is-archived {
@ -387,6 +398,12 @@ $vikunja-nav-selected-width: 0.4rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: auto;
}
.count {
color: var(--grey-500);
margin-right: .5rem;
}
}
@ -482,7 +499,7 @@ $vikunja-nav-selected-width: 0.4rem;
height: 1rem;
vertical-align: middle;
padding-right: 0.5rem;
&.handle {
opacity: 0;
transition: opacity $transition;
@ -490,7 +507,7 @@ $vikunja-nav-selected-width: 0.4rem;
cursor: grab;
}
}
&:hover .icon.handle {
opacity: 1;
}
@ -542,7 +559,7 @@ $vikunja-nav-selected-width: 0.4rem;
span.list-menu-link, li > a {
padding-left: 2rem;
display: inline-block;
.icon {
padding-bottom: .25rem;
}
@ -555,4 +572,8 @@ $vikunja-nav-selected-width: 0.4rem;
width: 32px;
flex-shrink: 0;
}
.namespaces-list.loader-container.is-loading {
min-height: calc(100vh - #{$navbar-height + 1.5rem + 1rem + 1.5rem});
}
</style>

View File

@ -1,9 +1,8 @@
<template>
<nav
<header
:class="{'has-background': background}"
aria-label="main navigation"
class="navbar main-theme is-fixed-top"
role="navigation"
>
<router-link :to="{name: 'home'}" class="logo-link">
<Logo width="164" height="48"/>
@ -37,7 +36,7 @@
<dropdown class="is-right" ref="usernameDropdown">
<template #trigger>
<x-button
type="secondary"
variant="secondary"
:shadow="false">
<span class="username">{{ userInfo.name !== '' ? userInfo.name : userInfo.username }}</span>
<span class="icon is-small">
@ -77,7 +76,7 @@
</dropdown>
</div>
</div>
</nav>
</header>
</template>
<script>

View File

@ -85,4 +85,8 @@ export default {
margin-left: .5rem;
}
}
.dark .update-notification {
color: var(--grey-200);
}
</style>

View File

@ -1,79 +1,64 @@
<template>
<a
<BaseButton
class="button"
:class="{
'is-loading': loading,
'has-no-shadow': !shadow,
'is-primary': type === 'primary',
'is-outlined': type === 'secondary',
'is-text is-inverted has-no-shadow underline-none':
type === 'tertary',
}"
:disabled="disabled || null"
@click="click"
:href="href !== '' ? href : null"
:class="[
variantClass,
{
'is-loading': loading,
'has-no-shadow': !shadow || variant === 'tertiary',
}
]"
>
<icon :icon="icon" v-if="showIconOnly"/>
<span class="icon is-small" v-else-if="icon !== ''">
<icon :icon="icon"/>
</span>
<slot></slot>
</a>
<slot />
</BaseButton>
</template>
<script>
<script lang="ts">
export default {
name: 'x-button',
props: {
type: {
type: String,
default: 'primary',
},
href: {
type: String,
default: '',
},
to: {
default: false,
},
icon: {
default: '',
},
loading: {
type: Boolean,
default: false,
},
shadow: {
type: Boolean,
default: true,
},
disabled: {
type: Boolean,
default: false,
},
},
emits: ['click'],
computed: {
showIconOnly() {
return this.icon !== '' && typeof this.$slots.default === 'undefined'
},
},
methods: {
click(e) {
if (this.disabled) {
return
}
if (this.to !== false) {
this.$router.push(this.to)
}
this.$emit('click', e)
},
},
}
</script>
<script setup lang="ts">
import {computed, useSlots, PropType} from 'vue'
import BaseButton from '@/components/base/BaseButton.vue'
const BUTTON_TYPES_MAP = Object.freeze({
primary: 'is-primary',
secondary: 'is-outlined',
tertiary: 'is-text is-inverted underline-none',
})
type ButtonTypes = keyof typeof BUTTON_TYPES_MAP
const props = defineProps({
variant: {
type: String as PropType<ButtonTypes>,
default: 'primary',
},
icon: {
default: '',
},
loading: {
type: Boolean,
default: false,
},
shadow: {
type: Boolean,
default: true,
},
})
const variantClass = computed(() => BUTTON_TYPES_MAP[props.variant])
const slots = useSlots()
const showIconOnly = computed(() => props.icon !== '' && typeof slots.default === 'undefined')
</script>
<style lang="scss" scoped>
.button {
transition: all $transition;
@ -83,8 +68,8 @@ export default {
font-weight: bold;
height: $button-height;
box-shadow: var(--shadow-sm);
display: inline-flex;
&.is-hovered,
&:hover {
box-shadow: var(--shadow-md);
}
@ -106,9 +91,10 @@ export default {
color: var(--white);
}
&.is-small {
border-radius: $radius;
}
}
.is-small {
border-radius: $radius;
}
.underline-none {

View File

@ -27,7 +27,7 @@
@click="reset"
class="is-small ml-2"
:shadow="false"
type="secondary"
variant="secondary"
>
{{ $t('input.resetColor') }}
</x-button>

View File

@ -101,6 +101,7 @@
class="is-fullwidth"
:shadow="false"
@click="close"
v-cy="'closeDatepicker'"
>
{{ $t('misc.confirm') }}
</x-button>
@ -127,10 +128,6 @@ export default {
date: null,
show: false,
changed: false,
// Since flatpickr dates are strings, we need to convert them to native date objects.
// To make that work, we need a separate variable since flatpickr does not have a change event.
flatPickrDate: null,
}
},
components: {
@ -163,10 +160,6 @@ export default {
handler: 'setDateValue',
immediate: true,
},
flatPickrDate(newVal) {
this.date = createDateFromString(newVal)
this.updateData()
},
},
computed: {
flatPickerConfig() {
@ -182,6 +175,17 @@ export default {
},
}
},
// Since flatpickr dates are strings, we need to convert them to native date objects.
// To make that work, we need a separate variable since flatpickr does not have a change event.
flatPickrDate: {
set(newValue) {
this.date = createDateFromString(newValue)
this.updateData()
},
get() {
return format(this.date, 'yyy-LL-dd H:mm')
},
},
},
methods: {
setDateValue(newVal) {

View File

@ -35,7 +35,7 @@
<a @click="toggleEdit">{{ $t('input.editor.edit') }}</a>
</li>
</ul>
<x-button v-else-if="isEditActive" @click="toggleEdit" type="secondary" :shadow="false">
<x-button v-else-if="isEditActive" @click="toggleEdit" variant="secondary" :shadow="false" v-cy="'saveEditor'">
{{ $t('misc.save') }}
</x-button>
</template>
@ -312,8 +312,6 @@ export default {
@import './vue-easymde/vue-easymde.css';
@import 'highlight.js/scss/base16/equilibrium-gray-light';
$editor-border-color: #ddd;
.editor {
.clear {
clear: both;
@ -337,7 +335,7 @@ $editor-border-color: #ddd;
.CodeMirror {
padding: .5rem;
border: 1px solid $editor-border-color;
border: 1px solid var(--grey-200) !important;
background: var(--white);
&-lines pre {
@ -348,6 +346,10 @@ $editor-border-color: #ddd;
color: var(--grey-400) !important;
font-style: italic;
}
&-cursor {
border-color: var(--grey-700);
}
}
.editor-preview {
@ -359,12 +361,13 @@ $editor-border-color: #ddd;
}
.editor-toolbar {
background: #ffffff;
border-top: 1px solid $editor-border-color;
border-left: 1px solid $editor-border-color;
border-right: 1px solid $editor-border-color;
background: var(--grey-50);
border: 1px solid var(--grey-200);
border-bottom: none;
button {
color: var(--grey-700);
svg {
vertical-align: middle;
@ -379,6 +382,15 @@ $editor-border-color: #ddd;
top: 24px;
margin-left: -3px;
}
&:hover {
background: var(--grey-200);
border-color: var(--grey-300);
}
}
i.separator {
border-color: var(--grey-200) !important;
}
}

View File

@ -14,112 +14,112 @@ export function createEasyMDEConfig({ placeholder, uploadImage, imageUploadFunct
name: 'heading-1',
action: EasyMDE.toggleHeading1,
title: i18n.global.t('input.editor.heading1'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M18.2773 19.25L12.5773 4.34995C12.5773 4.34995 12.5773 4.24995 12.4773 4.24995C12.4773 4.24995 12.4773 4.14995 12.3773 4.14995C12.3773 4.14995 12.2773 4.14995 12.2773 4.04995L12.1773 3.94995H12.0773H11.9773C11.8773 3.94995 11.8773 3.94995 11.8773 3.94995H11.7773C11.6773 4.04995 11.6773 4.14995 11.5773 4.14995C11.5773 4.14995 11.5773 4.14995 11.4773 4.14995C11.4773 4.14995 11.4773 4.24995 11.3773 4.24995L11.2773 4.34995L5.67733 19.25C5.57733 19.55 5.67733 19.95 5.97733 20.05C6.07733 20.05 6.07733 20.05 6.17733 20.05C6.37733 20.05 6.67733 19.95 6.77733 19.65L7.87733 16.85H16.1773L17.2773 19.65C17.3773 19.85 17.5773 20.05 17.8773 20.05C17.9773 20.05 17.9773 20.05 18.0773 20.05C18.2773 19.85 18.4773 19.55 18.2773 19.25ZM8.27733 15.65L11.9773 6.24995L15.6773 15.65H8.27733Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M18.2773 19.25L12.5773 4.34995C12.5773 4.34995 12.5773 4.24995 12.4773 4.24995C12.4773 4.24995 12.4773 4.14995 12.3773 4.14995C12.3773 4.14995 12.2773 4.14995 12.2773 4.04995L12.1773 3.94995H12.0773H11.9773C11.8773 3.94995 11.8773 3.94995 11.8773 3.94995H11.7773C11.6773 4.04995 11.6773 4.14995 11.5773 4.14995C11.5773 4.14995 11.5773 4.14995 11.4773 4.14995C11.4773 4.14995 11.4773 4.24995 11.3773 4.24995L11.2773 4.34995L5.67733 19.25C5.57733 19.55 5.67733 19.95 5.97733 20.05C6.07733 20.05 6.07733 20.05 6.17733 20.05C6.37733 20.05 6.67733 19.95 6.77733 19.65L7.87733 16.85H16.1773L17.2773 19.65C17.3773 19.85 17.5773 20.05 17.8773 20.05C17.9773 20.05 17.9773 20.05 18.0773 20.05C18.2773 19.85 18.4773 19.55 18.2773 19.25ZM8.27733 15.65L11.9773 6.24995L15.6773 15.65H8.27733Z"/></svg>',
},
{
name: 'heading-2',
action: EasyMDE.toggleHeading2,
title: i18n.global.t('input.editor.heading2'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M18.2773 19.25L12.5773 4.34995C12.5773 4.34995 12.5773 4.24995 12.4773 4.24995C12.4773 4.24995 12.4773 4.14995 12.3773 4.14995C12.3773 4.14995 12.2773 4.14995 12.2773 4.04995L12.1773 3.94995H12.0773H11.9773C11.8773 3.94995 11.8773 3.94995 11.8773 3.94995H11.7773C11.6773 4.04995 11.6773 4.14995 11.5773 4.14995C11.5773 4.14995 11.5773 4.14995 11.4773 4.14995C11.4773 4.14995 11.4773 4.24995 11.3773 4.24995L11.2773 4.34995L5.67733 19.25C5.57733 19.55 5.67733 19.95 5.97733 20.05C6.07733 20.05 6.07733 20.05 6.17733 20.05C6.37733 20.05 6.67733 19.95 6.77733 19.65L7.87733 16.85H16.1773L17.2773 19.65C17.3773 19.85 17.5773 20.05 17.8773 20.05C17.9773 20.05 17.9773 20.05 18.0773 20.05C18.2773 19.85 18.4773 19.55 18.2773 19.25ZM8.27733 15.65L11.9773 6.24995L15.6773 15.65H8.27733Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M18.2773 19.25L12.5773 4.34995C12.5773 4.34995 12.5773 4.24995 12.4773 4.24995C12.4773 4.24995 12.4773 4.14995 12.3773 4.14995C12.3773 4.14995 12.2773 4.14995 12.2773 4.04995L12.1773 3.94995H12.0773H11.9773C11.8773 3.94995 11.8773 3.94995 11.8773 3.94995H11.7773C11.6773 4.04995 11.6773 4.14995 11.5773 4.14995C11.5773 4.14995 11.5773 4.14995 11.4773 4.14995C11.4773 4.14995 11.4773 4.24995 11.3773 4.24995L11.2773 4.34995L5.67733 19.25C5.57733 19.55 5.67733 19.95 5.97733 20.05C6.07733 20.05 6.07733 20.05 6.17733 20.05C6.37733 20.05 6.67733 19.95 6.77733 19.65L7.87733 16.85H16.1773L17.2773 19.65C17.3773 19.85 17.5773 20.05 17.8773 20.05C17.9773 20.05 17.9773 20.05 18.0773 20.05C18.2773 19.85 18.4773 19.55 18.2773 19.25ZM8.27733 15.65L11.9773 6.24995L15.6773 15.65H8.27733Z"/></svg>',
},
{
name: 'heading-3',
action: EasyMDE.toggleHeading3,
title: i18n.global.t('input.editor.heading3'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M18.2773 19.25L12.5773 4.34995C12.5773 4.34995 12.5773 4.24995 12.4773 4.24995C12.4773 4.24995 12.4773 4.14995 12.3773 4.14995C12.3773 4.14995 12.2773 4.14995 12.2773 4.04995L12.1773 3.94995H12.0773H11.9773C11.8773 3.94995 11.8773 3.94995 11.8773 3.94995H11.7773C11.6773 4.04995 11.6773 4.14995 11.5773 4.14995C11.5773 4.14995 11.5773 4.14995 11.4773 4.14995C11.4773 4.14995 11.4773 4.24995 11.3773 4.24995L11.2773 4.34995L5.67733 19.25C5.57733 19.55 5.67733 19.95 5.97733 20.05C6.07733 20.05 6.07733 20.05 6.17733 20.05C6.37733 20.05 6.67733 19.95 6.77733 19.65L7.87733 16.85H16.1773L17.2773 19.65C17.3773 19.85 17.5773 20.05 17.8773 20.05C17.9773 20.05 17.9773 20.05 18.0773 20.05C18.2773 19.85 18.4773 19.55 18.2773 19.25ZM8.27733 15.65L11.9773 6.24995L15.6773 15.65H8.27733Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M18.2773 19.25L12.5773 4.34995C12.5773 4.34995 12.5773 4.24995 12.4773 4.24995C12.4773 4.24995 12.4773 4.14995 12.3773 4.14995C12.3773 4.14995 12.2773 4.14995 12.2773 4.04995L12.1773 3.94995H12.0773H11.9773C11.8773 3.94995 11.8773 3.94995 11.8773 3.94995H11.7773C11.6773 4.04995 11.6773 4.14995 11.5773 4.14995C11.5773 4.14995 11.5773 4.14995 11.4773 4.14995C11.4773 4.14995 11.4773 4.24995 11.3773 4.24995L11.2773 4.34995L5.67733 19.25C5.57733 19.55 5.67733 19.95 5.97733 20.05C6.07733 20.05 6.07733 20.05 6.17733 20.05C6.37733 20.05 6.67733 19.95 6.77733 19.65L7.87733 16.85H16.1773L17.2773 19.65C17.3773 19.85 17.5773 20.05 17.8773 20.05C17.9773 20.05 17.9773 20.05 18.0773 20.05C18.2773 19.85 18.4773 19.55 18.2773 19.25ZM8.27733 15.65L11.9773 6.24995L15.6773 15.65H8.27733Z"/></svg>',
},
{
name: 'heading-smaller',
action: EasyMDE.toggleHeadingSmaller,
title: i18n.global.t('input.editor.headingSmaller'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M18.2773 19.25L12.5773 4.34995C12.5773 4.34995 12.5773 4.24995 12.4773 4.24995C12.4773 4.24995 12.4773 4.14995 12.3773 4.14995C12.3773 4.14995 12.2773 4.14995 12.2773 4.04995L12.1773 3.94995H12.0773H11.9773C11.8773 3.94995 11.8773 3.94995 11.8773 3.94995H11.7773C11.6773 4.04995 11.6773 4.14995 11.5773 4.14995C11.5773 4.14995 11.5773 4.14995 11.4773 4.14995C11.4773 4.14995 11.4773 4.24995 11.3773 4.24995L11.2773 4.34995L5.67733 19.25C5.57733 19.55 5.67733 19.95 5.97733 20.05C6.07733 20.05 6.07733 20.05 6.17733 20.05C6.37733 20.05 6.67733 19.95 6.77733 19.65L7.87733 16.85H16.1773L17.2773 19.65C17.3773 19.85 17.5773 20.05 17.8773 20.05C17.9773 20.05 17.9773 20.05 18.0773 20.05C18.2773 19.85 18.4773 19.55 18.2773 19.25ZM8.27733 15.65L11.9773 6.24995L15.6773 15.65H8.27733Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M18.2773 19.25L12.5773 4.34995C12.5773 4.34995 12.5773 4.24995 12.4773 4.24995C12.4773 4.24995 12.4773 4.14995 12.3773 4.14995C12.3773 4.14995 12.2773 4.14995 12.2773 4.04995L12.1773 3.94995H12.0773H11.9773C11.8773 3.94995 11.8773 3.94995 11.8773 3.94995H11.7773C11.6773 4.04995 11.6773 4.14995 11.5773 4.14995C11.5773 4.14995 11.5773 4.14995 11.4773 4.14995C11.4773 4.14995 11.4773 4.24995 11.3773 4.24995L11.2773 4.34995L5.67733 19.25C5.57733 19.55 5.67733 19.95 5.97733 20.05C6.07733 20.05 6.07733 20.05 6.17733 20.05C6.37733 20.05 6.67733 19.95 6.77733 19.65L7.87733 16.85H16.1773L17.2773 19.65C17.3773 19.85 17.5773 20.05 17.8773 20.05C17.9773 20.05 17.9773 20.05 18.0773 20.05C18.2773 19.85 18.4773 19.55 18.2773 19.25ZM8.27733 15.65L11.9773 6.24995L15.6773 15.65H8.27733Z"/></svg>',
},
{
name: 'heading-bigger',
action: EasyMDE.toggleHeadingBigger,
title: i18n.global.t('input.editor.headingBigger'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M18.2773 19.25L12.5773 4.34995C12.5773 4.34995 12.5773 4.24995 12.4773 4.24995C12.4773 4.24995 12.4773 4.14995 12.3773 4.14995C12.3773 4.14995 12.2773 4.14995 12.2773 4.04995L12.1773 3.94995H12.0773H11.9773C11.8773 3.94995 11.8773 3.94995 11.8773 3.94995H11.7773C11.6773 4.04995 11.6773 4.14995 11.5773 4.14995C11.5773 4.14995 11.5773 4.14995 11.4773 4.14995C11.4773 4.14995 11.4773 4.24995 11.3773 4.24995L11.2773 4.34995L5.67733 19.25C5.57733 19.55 5.67733 19.95 5.97733 20.05C6.07733 20.05 6.07733 20.05 6.17733 20.05C6.37733 20.05 6.67733 19.95 6.77733 19.65L7.87733 16.85H16.1773L17.2773 19.65C17.3773 19.85 17.5773 20.05 17.8773 20.05C17.9773 20.05 17.9773 20.05 18.0773 20.05C18.2773 19.85 18.4773 19.55 18.2773 19.25ZM8.27733 15.65L11.9773 6.24995L15.6773 15.65H8.27733Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M18.2773 19.25L12.5773 4.34995C12.5773 4.34995 12.5773 4.24995 12.4773 4.24995C12.4773 4.24995 12.4773 4.14995 12.3773 4.14995C12.3773 4.14995 12.2773 4.14995 12.2773 4.04995L12.1773 3.94995H12.0773H11.9773C11.8773 3.94995 11.8773 3.94995 11.8773 3.94995H11.7773C11.6773 4.04995 11.6773 4.14995 11.5773 4.14995C11.5773 4.14995 11.5773 4.14995 11.4773 4.14995C11.4773 4.14995 11.4773 4.24995 11.3773 4.24995L11.2773 4.34995L5.67733 19.25C5.57733 19.55 5.67733 19.95 5.97733 20.05C6.07733 20.05 6.07733 20.05 6.17733 20.05C6.37733 20.05 6.67733 19.95 6.77733 19.65L7.87733 16.85H16.1773L17.2773 19.65C17.3773 19.85 17.5773 20.05 17.8773 20.05C17.9773 20.05 17.9773 20.05 18.0773 20.05C18.2773 19.85 18.4773 19.55 18.2773 19.25ZM8.27733 15.65L11.9773 6.24995L15.6773 15.65H8.27733Z"/></svg>',
},
'|',
{
name: 'bold',
action: EasyMDE.toggleBold,
title: i18n.global.t('input.editor.bold'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M3.5 3H6.5H15.25C18.15 3 20.5 5.36 20.5 8.25C20.5 9.8 19.81 11.19 18.73 12.15C20.37 13.04 21.5 14.76 21.5 16.75C21.5 19.64 19.15 22 16.25 22H6.5H3.5C2.95 22 2.5 21.55 2.5 21C2.5 20.45 2.95 20 3.5 20H5.5V5H3.5C2.95 5 2.5 4.55 2.5 4C2.5 3.45 2.95 3 3.5 3ZM7.5 20H16.25C18.04 20 19.5 18.54 19.5 16.75C19.5 14.96 18.04 13.5 16.25 13.5H7.5V20ZM7.5 11.5H15.25C17.04 11.5 18.5 10.04 18.5 8.25C18.5 6.46 17.04 5 15.25 5H7.5V11.5Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M3.5 3H6.5H15.25C18.15 3 20.5 5.36 20.5 8.25C20.5 9.8 19.81 11.19 18.73 12.15C20.37 13.04 21.5 14.76 21.5 16.75C21.5 19.64 19.15 22 16.25 22H6.5H3.5C2.95 22 2.5 21.55 2.5 21C2.5 20.45 2.95 20 3.5 20H5.5V5H3.5C2.95 5 2.5 4.55 2.5 4C2.5 3.45 2.95 3 3.5 3ZM7.5 20H16.25C18.04 20 19.5 18.54 19.5 16.75C19.5 14.96 18.04 13.5 16.25 13.5H7.5V20ZM7.5 11.5H15.25C17.04 11.5 18.5 10.04 18.5 8.25C18.5 6.46 17.04 5 15.25 5H7.5V11.5Z"/></svg>',
},
{
name: 'italic',
action: EasyMDE.toggleItalic,
title: i18n.global.t('input.editor.italic'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M14.0967 4.2H17.0001C17.3301 4.2 17.6001 3.93 17.6001 3.6C17.6001 3.27 17.3301 3 17.0001 3H10.2001C9.8701 3 9.6001 3.27 9.6001 3.6C9.6001 3.93 9.8701 4.2 10.2001 4.2H12.8748L9.90335 19.8H6.9999C6.6699 19.8 6.3999 20.07 6.3999 20.4C6.3999 20.73 6.6699 21 6.9999 21H13.7999C14.1299 21 14.3999 20.73 14.3999 20.4C14.3999 20.07 14.1299 19.8 13.7999 19.8H11.1253L14.0967 4.2Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M14.0967 4.2H17.0001C17.3301 4.2 17.6001 3.93 17.6001 3.6C17.6001 3.27 17.3301 3 17.0001 3H10.2001C9.8701 3 9.6001 3.27 9.6001 3.6C9.6001 3.93 9.8701 4.2 10.2001 4.2H12.8748L9.90335 19.8H6.9999C6.6699 19.8 6.3999 20.07 6.3999 20.4C6.3999 20.73 6.6699 21 6.9999 21H13.7999C14.1299 21 14.3999 20.73 14.3999 20.4C14.3999 20.07 14.1299 19.8 13.7999 19.8H11.1253L14.0967 4.2Z"/></svg>',
},
{
name: 'strikethrough',
action: EasyMDE.toggleStrikethrough,
title: i18n.global.t('input.editor.strikethrough'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M18.25 7.17005C18.25 7.50005 17.98 7.77005 17.65 7.77005C17.32 7.77005 17.05 7.50005 17.05 7.17005V5.96005C15.97 5.12005 14.17 4.56005 12.79 4.31005C11.1 4.00005 9.51 4.30005 8.41 5.12005C7.2 6.03005 6.67 7.67005 7.19 8.88005C7.56 9.73005 8.37 10.31 8.98 10.64C9.57215 10.9644 10.1961 11.2013 10.8465 11.3999H20.4C20.73 11.3999 21 11.6699 21 11.9999C21 12.3299 20.73 12.5999 20.4 12.5999H15.3012C16.6583 13.0929 17.5255 13.7765 17.95 14.69C18.73 16.36 17.74 18.33 16.36 19.41C15.05 20.4401 13.35 21 11.54 21H11.16C9.78 20.9401 8.34 20.5301 6.95 19.85V20.3601C6.95 20.6901 6.68 20.96 6.35 20.96C6.02 20.96 5.75 20.6901 5.75 20.3601V17.36C5.75 17.03 6.02 16.76 6.35 16.76C6.68 16.76 6.95 17.03 6.95 17.36V18.5C8.35 19.2801 9.81 19.74 11.21 19.8C12.86 19.89 14.46 19.39 15.62 18.48C16.6 17.71 17.37 16.3 16.86 15.21C16.55 14.54 15.8 14.0201 14.58 13.63C13.9711 13.4331 13.3222 13.2762 12.6906 13.1235C12.6168 13.1056 12.5432 13.0878 12.47 13.07C12.4313 13.0607 12.3925 13.0514 12.3537 13.0421C11.7861 12.9055 11.2108 12.767 10.6413 12.5999H3.6C3.27 12.5999 3 12.3299 3 11.9999C3 11.6699 3.27 11.3999 3.6 11.3999H7.90288C7.04984 10.8343 6.42752 10.1363 6.09 9.36005C5.34 7.63005 6.03 5.40005 7.69 4.16005C9.05 3.15005 10.99 2.77005 13 3.13005C13.64 3.25005 15.53 3.66005 17.05 4.53005V4.17005C17.05 3.84005 17.32 3.57005 17.65 3.57005C17.98 3.57005 18.25 3.84005 18.25 4.17005V7.17005Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M18.25 7.17005C18.25 7.50005 17.98 7.77005 17.65 7.77005C17.32 7.77005 17.05 7.50005 17.05 7.17005V5.96005C15.97 5.12005 14.17 4.56005 12.79 4.31005C11.1 4.00005 9.51 4.30005 8.41 5.12005C7.2 6.03005 6.67 7.67005 7.19 8.88005C7.56 9.73005 8.37 10.31 8.98 10.64C9.57215 10.9644 10.1961 11.2013 10.8465 11.3999H20.4C20.73 11.3999 21 11.6699 21 11.9999C21 12.3299 20.73 12.5999 20.4 12.5999H15.3012C16.6583 13.0929 17.5255 13.7765 17.95 14.69C18.73 16.36 17.74 18.33 16.36 19.41C15.05 20.4401 13.35 21 11.54 21H11.16C9.78 20.9401 8.34 20.5301 6.95 19.85V20.3601C6.95 20.6901 6.68 20.96 6.35 20.96C6.02 20.96 5.75 20.6901 5.75 20.3601V17.36C5.75 17.03 6.02 16.76 6.35 16.76C6.68 16.76 6.95 17.03 6.95 17.36V18.5C8.35 19.2801 9.81 19.74 11.21 19.8C12.86 19.89 14.46 19.39 15.62 18.48C16.6 17.71 17.37 16.3 16.86 15.21C16.55 14.54 15.8 14.0201 14.58 13.63C13.9711 13.4331 13.3222 13.2762 12.6906 13.1235C12.6168 13.1056 12.5432 13.0878 12.47 13.07C12.4313 13.0607 12.3925 13.0514 12.3537 13.0421C11.7861 12.9055 11.2108 12.767 10.6413 12.5999H3.6C3.27 12.5999 3 12.3299 3 11.9999C3 11.6699 3.27 11.3999 3.6 11.3999H7.90288C7.04984 10.8343 6.42752 10.1363 6.09 9.36005C5.34 7.63005 6.03 5.40005 7.69 4.16005C9.05 3.15005 10.99 2.77005 13 3.13005C13.64 3.25005 15.53 3.66005 17.05 4.53005V4.17005C17.05 3.84005 17.32 3.57005 17.65 3.57005C17.98 3.57005 18.25 3.84005 18.25 4.17005V7.17005Z"/></svg>',
},
{
name: 'code',
action: EasyMDE.toggleCodeBlock,
title: i18n.global.t('input.editor.code'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8.57 20.9601C8.64 20.9901 8.71 21.0001 8.78 21.0001C9.02 21.0001 9.24 20.8501 9.34 20.6101L15.79 3.81005C15.9 3.50005 15.75 3.15005 15.44 3.03005C15.14 2.92005 14.79 3.07005 14.67 3.38005L8.22 20.1801C8.11 20.4901 8.26 20.8401 8.57 20.9601ZM7.00007 18.0001C6.85007 18.0001 6.69007 17.9401 6.58007 17.8201L1.18007 12.4201C0.950068 12.1901 0.950068 11.8101 1.18007 11.5701L6.58007 6.17006C6.81007 5.94006 7.19007 5.94006 7.43007 6.17006C7.66007 6.40006 7.66007 6.78006 7.43007 7.02006L2.45007 12.0001L7.43007 16.9801C7.66007 17.2101 7.66007 17.5901 7.43007 17.8301C7.31007 17.9401 7.15007 18.0001 7.00007 18.0001ZM17 18.0001C16.85 18.0001 16.69 17.9401 16.58 17.8201C16.35 17.5901 16.35 17.2101 16.58 16.9701L21.55 12.0001L16.57 7.02006C16.34 6.79006 16.34 6.41006 16.57 6.17006C16.81 5.94006 17.19 5.94006 17.42 6.17006L22.82 11.5701C23.05 11.8001 23.05 12.1801 22.82 12.4201L17.42 17.8201C17.31 17.9401 17.15 18.0001 17 18.0001Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M8.57 20.9601C8.64 20.9901 8.71 21.0001 8.78 21.0001C9.02 21.0001 9.24 20.8501 9.34 20.6101L15.79 3.81005C15.9 3.50005 15.75 3.15005 15.44 3.03005C15.14 2.92005 14.79 3.07005 14.67 3.38005L8.22 20.1801C8.11 20.4901 8.26 20.8401 8.57 20.9601ZM7.00007 18.0001C6.85007 18.0001 6.69007 17.9401 6.58007 17.8201L1.18007 12.4201C0.950068 12.1901 0.950068 11.8101 1.18007 11.5701L6.58007 6.17006C6.81007 5.94006 7.19007 5.94006 7.43007 6.17006C7.66007 6.40006 7.66007 6.78006 7.43007 7.02006L2.45007 12.0001L7.43007 16.9801C7.66007 17.2101 7.66007 17.5901 7.43007 17.8301C7.31007 17.9401 7.15007 18.0001 7.00007 18.0001ZM17 18.0001C16.85 18.0001 16.69 17.9401 16.58 17.8201C16.35 17.5901 16.35 17.2101 16.58 16.9701L21.55 12.0001L16.57 7.02006C16.34 6.79006 16.34 6.41006 16.57 6.17006C16.81 5.94006 17.19 5.94006 17.42 6.17006L22.82 11.5701C23.05 11.8001 23.05 12.1801 22.82 12.4201L17.42 17.8201C17.31 17.9401 17.15 18.0001 17 18.0001Z"/></svg>',
},
{
name: 'quote',
action: EasyMDE.toggleBlockquote,
title: i18n.global.t('input.editor.quote'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M19.373 5.16357H5.62695C4.79102 5.16357 4.11133 5.84326 4.11133 6.6792V16.2095C4.11133 17.0464 4.79102 17.7261 5.62695 17.7261H6.8877V21.1245C6.8877 21.3667 7.0332 21.5854 7.25684 21.6782C7.33203 21.7095 7.41016 21.7241 7.4873 21.7241C7.64258 21.7241 7.7959 21.6636 7.91113 21.5493L11.748 17.7261H19.373C20.209 17.7261 20.8887 17.0464 20.8887 16.2095V6.6792C20.8887 5.84326 20.209 5.16357 19.373 5.16357ZM19.6895 16.2095C19.6895 16.3843 19.5469 16.5269 19.373 16.5269H11.5C11.3408 16.5269 11.1895 16.5894 11.0762 16.7017L8.08691 19.6802V17.1265C8.08691 16.7954 7.81836 16.5269 7.4873 16.5269H5.62695C5.45312 16.5269 5.31055 16.3843 5.31055 16.2095V6.6792C5.31055 6.50537 5.45312 6.36279 5.62695 6.36279H19.373C19.5469 6.36279 19.6895 6.50537 19.6895 6.6792V16.2095ZM10.3431 8.45264C9.46326 8.45264 8.75 9.16589 8.75 10.0458C8.75 10.9257 9.46326 11.639 10.3431 11.639C10.4775 11.639 10.6058 11.6173 10.7305 11.5861V11.6195C10.7305 12.1322 10.3135 12.5492 9.75586 12.5492C9.4248 12.5492 9.17871 12.8177 9.17871 13.1488C9.17871 13.4799 9.46973 13.7484 9.80078 13.7484C10.9746 13.7484 11.9297 12.7933 11.9297 11.6195V10.1176L11.9294 10.1165L11.9292 10.1155C11.9297 10.1049 11.9312 10.0946 11.9326 10.0843L11.9326 10.0843C11.9345 10.0716 11.9363 10.059 11.9363 10.0458C11.9363 9.16589 11.223 8.45264 10.3431 8.45264ZM13.0637 10.0458C13.0637 9.16589 13.7771 8.45264 14.657 8.45264C15.5369 8.45264 16.2501 9.16589 16.2501 10.0458C16.2501 10.0584 16.2484 10.0706 16.2466 10.0828C16.2452 10.0929 16.2437 10.103 16.2433 10.1134C16.2433 10.1149 16.2441 10.1161 16.2441 10.1176V11.6195C16.2441 12.7933 15.2891 13.7484 14.1152 13.7484C13.7842 13.7484 13.4922 13.4799 13.4922 13.1488C13.4922 12.8177 13.7383 12.5492 14.0693 12.5492C14.6279 12.5492 15.0449 12.1322 15.0449 11.6195V11.5858C14.9202 11.6173 14.7915 11.639 14.657 11.639C13.7771 11.639 13.0637 10.9257 13.0637 10.0458Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M19.373 5.16357H5.62695C4.79102 5.16357 4.11133 5.84326 4.11133 6.6792V16.2095C4.11133 17.0464 4.79102 17.7261 5.62695 17.7261H6.8877V21.1245C6.8877 21.3667 7.0332 21.5854 7.25684 21.6782C7.33203 21.7095 7.41016 21.7241 7.4873 21.7241C7.64258 21.7241 7.7959 21.6636 7.91113 21.5493L11.748 17.7261H19.373C20.209 17.7261 20.8887 17.0464 20.8887 16.2095V6.6792C20.8887 5.84326 20.209 5.16357 19.373 5.16357ZM19.6895 16.2095C19.6895 16.3843 19.5469 16.5269 19.373 16.5269H11.5C11.3408 16.5269 11.1895 16.5894 11.0762 16.7017L8.08691 19.6802V17.1265C8.08691 16.7954 7.81836 16.5269 7.4873 16.5269H5.62695C5.45312 16.5269 5.31055 16.3843 5.31055 16.2095V6.6792C5.31055 6.50537 5.45312 6.36279 5.62695 6.36279H19.373C19.5469 6.36279 19.6895 6.50537 19.6895 6.6792V16.2095ZM10.3431 8.45264C9.46326 8.45264 8.75 9.16589 8.75 10.0458C8.75 10.9257 9.46326 11.639 10.3431 11.639C10.4775 11.639 10.6058 11.6173 10.7305 11.5861V11.6195C10.7305 12.1322 10.3135 12.5492 9.75586 12.5492C9.4248 12.5492 9.17871 12.8177 9.17871 13.1488C9.17871 13.4799 9.46973 13.7484 9.80078 13.7484C10.9746 13.7484 11.9297 12.7933 11.9297 11.6195V10.1176L11.9294 10.1165L11.9292 10.1155C11.9297 10.1049 11.9312 10.0946 11.9326 10.0843L11.9326 10.0843C11.9345 10.0716 11.9363 10.059 11.9363 10.0458C11.9363 9.16589 11.223 8.45264 10.3431 8.45264ZM13.0637 10.0458C13.0637 9.16589 13.7771 8.45264 14.657 8.45264C15.5369 8.45264 16.2501 9.16589 16.2501 10.0458C16.2501 10.0584 16.2484 10.0706 16.2466 10.0828C16.2452 10.0929 16.2437 10.103 16.2433 10.1134C16.2433 10.1149 16.2441 10.1161 16.2441 10.1176V11.6195C16.2441 12.7933 15.2891 13.7484 14.1152 13.7484C13.7842 13.7484 13.4922 13.4799 13.4922 13.1488C13.4922 12.8177 13.7383 12.5492 14.0693 12.5492C14.6279 12.5492 15.0449 12.1322 15.0449 11.6195V11.5858C14.9202 11.6173 14.7915 11.639 14.657 11.639C13.7771 11.639 13.0637 10.9257 13.0637 10.0458Z"/></svg>',
},
{
name: 'unordered-list',
action: EasyMDE.toggleUnorderedList,
title: i18n.global.t('input.editor.unorderedList'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M6.5281 3.7002H3.5281C3.1981 3.7002 2.9281 3.9702 2.9281 4.3002V7.3002C2.9281 7.6302 3.1981 7.9002 3.5281 7.9002H6.5281C6.8581 7.9002 7.1281 7.6302 7.1281 7.3002V4.3002C7.1281 3.9702 6.8581 3.7002 6.5281 3.7002ZM5.9281 6.7002H4.1281V4.9002H5.9281V6.7002ZM3.5281 9.90015H6.5281C6.8581 9.90015 7.1281 10.1701 7.1281 10.5001V13.5001C7.1281 13.8301 6.8581 14.1001 6.5281 14.1001H3.5281C3.1981 14.1001 2.9281 13.8301 2.9281 13.5001V10.5001C2.9281 10.1701 3.1981 9.90015 3.5281 9.90015ZM4.1281 12.9001H5.9281V11.1001H4.1281V12.9001ZM3.5281 16.1001H6.5281C6.8581 16.1001 7.1281 16.3701 7.1281 16.7001V19.7001C7.1281 20.0301 6.8581 20.3001 6.5281 20.3001H3.5281C3.1981 20.3001 2.9281 20.0301 2.9281 19.7001V16.7001C2.9281 16.3701 3.1981 16.1001 3.5281 16.1001ZM4.1281 19.1001H5.9281V17.3001H4.1281V19.1001ZM9.72817 6.4002H20.7282C21.0582 6.4002 21.3282 6.1302 21.3282 5.8002C21.3282 5.4702 21.0582 5.2002 20.7282 5.2002H9.72817C9.39817 5.2002 9.12817 5.4702 9.12817 5.8002C9.12817 6.1302 9.39817 6.4002 9.72817 6.4002ZM9.72817 11.4001H20.7282C21.0582 11.4001 21.3282 11.6701 21.3282 12.0001C21.3282 12.3301 21.0582 12.6001 20.7282 12.6001H9.72817C9.39817 12.6001 9.12817 12.3301 9.12817 12.0001C9.12817 11.6701 9.39817 11.4001 9.72817 11.4001ZM9.72817 17.6001H20.7282C21.0582 17.6001 21.3282 17.8701 21.3282 18.2001C21.3282 18.5301 21.0582 18.8001 20.7282 18.8001H9.72817C9.39817 18.8001 9.12817 18.5301 9.12817 18.2001C9.12817 17.8701 9.39817 17.6001 9.72817 17.6001Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M6.5281 3.7002H3.5281C3.1981 3.7002 2.9281 3.9702 2.9281 4.3002V7.3002C2.9281 7.6302 3.1981 7.9002 3.5281 7.9002H6.5281C6.8581 7.9002 7.1281 7.6302 7.1281 7.3002V4.3002C7.1281 3.9702 6.8581 3.7002 6.5281 3.7002ZM5.9281 6.7002H4.1281V4.9002H5.9281V6.7002ZM3.5281 9.90015H6.5281C6.8581 9.90015 7.1281 10.1701 7.1281 10.5001V13.5001C7.1281 13.8301 6.8581 14.1001 6.5281 14.1001H3.5281C3.1981 14.1001 2.9281 13.8301 2.9281 13.5001V10.5001C2.9281 10.1701 3.1981 9.90015 3.5281 9.90015ZM4.1281 12.9001H5.9281V11.1001H4.1281V12.9001ZM3.5281 16.1001H6.5281C6.8581 16.1001 7.1281 16.3701 7.1281 16.7001V19.7001C7.1281 20.0301 6.8581 20.3001 6.5281 20.3001H3.5281C3.1981 20.3001 2.9281 20.0301 2.9281 19.7001V16.7001C2.9281 16.3701 3.1981 16.1001 3.5281 16.1001ZM4.1281 19.1001H5.9281V17.3001H4.1281V19.1001ZM9.72817 6.4002H20.7282C21.0582 6.4002 21.3282 6.1302 21.3282 5.8002C21.3282 5.4702 21.0582 5.2002 20.7282 5.2002H9.72817C9.39817 5.2002 9.12817 5.4702 9.12817 5.8002C9.12817 6.1302 9.39817 6.4002 9.72817 6.4002ZM9.72817 11.4001H20.7282C21.0582 11.4001 21.3282 11.6701 21.3282 12.0001C21.3282 12.3301 21.0582 12.6001 20.7282 12.6001H9.72817C9.39817 12.6001 9.12817 12.3301 9.12817 12.0001C9.12817 11.6701 9.39817 11.4001 9.72817 11.4001ZM9.72817 17.6001H20.7282C21.0582 17.6001 21.3282 17.8701 21.3282 18.2001C21.3282 18.5301 21.0582 18.8001 20.7282 18.8001H9.72817C9.39817 18.8001 9.12817 18.5301 9.12817 18.2001C9.12817 17.8701 9.39817 17.6001 9.72817 17.6001Z"/></svg>',
},
{
name: 'ordered-list',
action: EasyMDE.toggleOrderedList,
title: i18n.global.t('input.editor.orderedList'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M4.19494 8.29994H5.99494C6.26494 8.29994 6.49494 8.07995 6.49494 7.79994C6.49494 7.51995 6.27494 7.29994 5.99494 7.29994H5.59494V3.79994C5.59494 3.62994 5.50494 3.46994 5.36494 3.37994C5.22494 3.28994 5.04494 3.26994 4.89494 3.33994L3.89494 3.76994C3.64494 3.87994 3.52494 4.17994 3.63494 4.42994C3.74494 4.67994 4.03494 4.79994 4.29494 4.68994L4.59494 4.55994V7.29994H4.19494C3.91494 7.29994 3.69494 7.51995 3.69494 7.79994C3.69494 8.07995 3.91494 8.29994 4.19494 8.29994ZM20.195 6.39995H9.19497C8.86497 6.39995 8.59497 6.12995 8.59497 5.79995C8.59497 5.46995 8.86497 5.19995 9.19497 5.19995H20.195C20.525 5.19995 20.795 5.46995 20.795 5.79995C20.795 6.12995 20.525 6.39995 20.195 6.39995ZM3.78486 14.36H6.37486C6.65486 14.36 6.87486 14.14 6.87486 13.86C6.87486 13.58 6.65486 13.36 6.37486 13.36H4.88486C5.00486 13.23 5.12486 13.09 5.23486 12.95C5.26626 12.9151 5.29645 12.8802 5.32626 12.8458L5.32629 12.8457C5.38192 12.7814 5.43627 12.7186 5.49486 12.66C5.73486 12.4 5.98486 12.12 6.17486 11.79C6.47486 11.25 6.41486 10.63 6.01486 10.17C5.57486 9.66 4.86486 9.5 4.24486 9.74C3.74486 9.95 3.39486 10.35 3.22486 10.91C3.14486 11.18 3.29486 11.46 3.56486 11.54C3.82486 11.61 4.10486 11.46 4.18486 11.2C4.29486 10.85 4.48486 10.73 4.62486 10.67C4.88486 10.57 5.13486 10.68 5.26486 10.82C5.38486 10.96 5.40486 11.12 5.30486 11.29C5.17595 11.5202 4.99618 11.7165 4.80458 11.9257L4.75486 11.98C4.67298 12.0801 4.58283 12.1801 4.49946 12.2727L4.49945 12.2727L4.47486 12.3C4.12486 12.72 3.76486 13.13 3.40486 13.53C3.27486 13.68 3.23486 13.9 3.32486 14.07C3.41486 14.24 3.58486 14.36 3.78486 14.36ZM3.68486 20.3699C4.04486 20.5899 4.46486 20.6999 4.87486 20.6999C5.13486 20.6999 5.38486 20.6499 5.61486 20.5499C6.31486 20.2799 6.73486 19.5599 6.60486 18.8799C6.53486 18.5499 6.35486 18.2899 6.12486 18.0899C6.32486 17.8999 6.45486 17.6499 6.50486 17.3799C6.57486 17.0099 6.49486 16.6299 6.27486 16.3099C5.85486 15.6899 5.07486 15.5199 4.10486 15.8299C3.83486 15.9199 3.69486 16.1999 3.77486 16.4599C3.86486 16.7299 4.14486 16.8699 4.40486 16.7899C4.70486 16.6999 5.24486 16.5799 5.45486 16.8899C5.51486 16.9899 5.54486 17.0999 5.52486 17.1999C5.51486 17.2699 5.47486 17.3599 5.36486 17.4299C5.26486 17.4999 5.12486 17.5399 4.95486 17.5799L4.77486 17.6299C4.54486 17.6999 4.40486 17.9099 4.41486 18.1499C4.42486 18.3899 4.61486 18.5799 4.84486 18.6099C5.20486 18.6599 5.58486 18.8299 5.63486 19.0799C5.67486 19.2999 5.46486 19.5499 5.25486 19.6299C4.94486 19.7599 4.52486 19.7099 4.21486 19.5199C3.97486 19.3699 3.67486 19.4399 3.52486 19.6799C3.37486 19.9199 3.44486 20.2299 3.68486 20.3699ZM20.195 18.7999H9.19497C8.86497 18.7999 8.59497 18.5299 8.59497 18.1999C8.59497 17.8699 8.86497 17.5999 9.19497 17.5999H20.195C20.525 17.5999 20.795 17.8699 20.795 18.1999C20.795 18.5299 20.525 18.7999 20.195 18.7999ZM9.19497 12.5999H20.195C20.525 12.5999 20.795 12.3299 20.795 11.9999C20.795 11.6699 20.525 11.3999 20.195 11.3999H9.19497C8.86497 11.3999 8.59497 11.6699 8.59497 11.9999C8.59497 12.3299 8.86497 12.5999 9.19497 12.5999Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M4.19494 8.29994H5.99494C6.26494 8.29994 6.49494 8.07995 6.49494 7.79994C6.49494 7.51995 6.27494 7.29994 5.99494 7.29994H5.59494V3.79994C5.59494 3.62994 5.50494 3.46994 5.36494 3.37994C5.22494 3.28994 5.04494 3.26994 4.89494 3.33994L3.89494 3.76994C3.64494 3.87994 3.52494 4.17994 3.63494 4.42994C3.74494 4.67994 4.03494 4.79994 4.29494 4.68994L4.59494 4.55994V7.29994H4.19494C3.91494 7.29994 3.69494 7.51995 3.69494 7.79994C3.69494 8.07995 3.91494 8.29994 4.19494 8.29994ZM20.195 6.39995H9.19497C8.86497 6.39995 8.59497 6.12995 8.59497 5.79995C8.59497 5.46995 8.86497 5.19995 9.19497 5.19995H20.195C20.525 5.19995 20.795 5.46995 20.795 5.79995C20.795 6.12995 20.525 6.39995 20.195 6.39995ZM3.78486 14.36H6.37486C6.65486 14.36 6.87486 14.14 6.87486 13.86C6.87486 13.58 6.65486 13.36 6.37486 13.36H4.88486C5.00486 13.23 5.12486 13.09 5.23486 12.95C5.26626 12.9151 5.29645 12.8802 5.32626 12.8458L5.32629 12.8457C5.38192 12.7814 5.43627 12.7186 5.49486 12.66C5.73486 12.4 5.98486 12.12 6.17486 11.79C6.47486 11.25 6.41486 10.63 6.01486 10.17C5.57486 9.66 4.86486 9.5 4.24486 9.74C3.74486 9.95 3.39486 10.35 3.22486 10.91C3.14486 11.18 3.29486 11.46 3.56486 11.54C3.82486 11.61 4.10486 11.46 4.18486 11.2C4.29486 10.85 4.48486 10.73 4.62486 10.67C4.88486 10.57 5.13486 10.68 5.26486 10.82C5.38486 10.96 5.40486 11.12 5.30486 11.29C5.17595 11.5202 4.99618 11.7165 4.80458 11.9257L4.75486 11.98C4.67298 12.0801 4.58283 12.1801 4.49946 12.2727L4.49945 12.2727L4.47486 12.3C4.12486 12.72 3.76486 13.13 3.40486 13.53C3.27486 13.68 3.23486 13.9 3.32486 14.07C3.41486 14.24 3.58486 14.36 3.78486 14.36ZM3.68486 20.3699C4.04486 20.5899 4.46486 20.6999 4.87486 20.6999C5.13486 20.6999 5.38486 20.6499 5.61486 20.5499C6.31486 20.2799 6.73486 19.5599 6.60486 18.8799C6.53486 18.5499 6.35486 18.2899 6.12486 18.0899C6.32486 17.8999 6.45486 17.6499 6.50486 17.3799C6.57486 17.0099 6.49486 16.6299 6.27486 16.3099C5.85486 15.6899 5.07486 15.5199 4.10486 15.8299C3.83486 15.9199 3.69486 16.1999 3.77486 16.4599C3.86486 16.7299 4.14486 16.8699 4.40486 16.7899C4.70486 16.6999 5.24486 16.5799 5.45486 16.8899C5.51486 16.9899 5.54486 17.0999 5.52486 17.1999C5.51486 17.2699 5.47486 17.3599 5.36486 17.4299C5.26486 17.4999 5.12486 17.5399 4.95486 17.5799L4.77486 17.6299C4.54486 17.6999 4.40486 17.9099 4.41486 18.1499C4.42486 18.3899 4.61486 18.5799 4.84486 18.6099C5.20486 18.6599 5.58486 18.8299 5.63486 19.0799C5.67486 19.2999 5.46486 19.5499 5.25486 19.6299C4.94486 19.7599 4.52486 19.7099 4.21486 19.5199C3.97486 19.3699 3.67486 19.4399 3.52486 19.6799C3.37486 19.9199 3.44486 20.2299 3.68486 20.3699ZM20.195 18.7999H9.19497C8.86497 18.7999 8.59497 18.5299 8.59497 18.1999C8.59497 17.8699 8.86497 17.5999 9.19497 17.5999H20.195C20.525 17.5999 20.795 17.8699 20.795 18.1999C20.795 18.5299 20.525 18.7999 20.195 18.7999ZM9.19497 12.5999H20.195C20.525 12.5999 20.795 12.3299 20.795 11.9999C20.795 11.6699 20.525 11.3999 20.195 11.3999H9.19497C8.86497 11.3999 8.59497 11.6699 8.59497 11.9999C8.59497 12.3299 8.86497 12.5999 9.19497 12.5999Z"/></svg>',
},
'|',
{
name: 'clean-block',
action: EasyMDE.cleanBlock,
title: i18n.global.t('input.editor.cleanBlock'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M9.25989 6.18384H20.4513C20.7823 6.18384 21.0509 6.45239 21.0509 6.78345V17.9749C21.0509 18.3059 20.7823 18.5745 20.4513 18.5745H9.25989C9.0929 18.5745 8.93469 18.5061 8.82043 18.384L3.6095 12.7883C3.39563 12.5579 3.39563 12.2004 3.6095 11.97L8.82043 6.37427C8.93469 6.2522 9.0929 6.18384 9.25989 6.18384ZM9.52063 17.3752H19.8517V7.38306H9.52063L4.86926 12.3792L9.52063 17.3752ZM12.7755 15.0686C12.6222 15.0686 12.4679 15.01 12.3517 14.8928C12.1173 14.6584 12.1173 14.2786 12.3517 14.0452L14.0503 12.3469L12.3517 10.6487C12.1173 10.4153 12.1173 10.0354 12.3517 9.80103C12.5841 9.56665 12.965 9.56665 13.1993 9.80103L14.8981 11.4994L16.5968 9.80103C16.8312 9.56665 17.212 9.56665 17.4445 9.80103C17.6788 10.0354 17.6788 10.4153 17.4445 10.6487L15.7458 12.3469L17.4445 14.0452C17.6788 14.2786 17.6788 14.6584 17.4445 14.8928C17.3282 15.01 17.174 15.0686 17.0206 15.0686C16.8673 15.0686 16.714 15.01 16.5968 14.8928L14.8981 13.1945L13.1993 14.8928C13.0822 15.01 12.9288 15.0686 12.7755 15.0686Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M9.25989 6.18384H20.4513C20.7823 6.18384 21.0509 6.45239 21.0509 6.78345V17.9749C21.0509 18.3059 20.7823 18.5745 20.4513 18.5745H9.25989C9.0929 18.5745 8.93469 18.5061 8.82043 18.384L3.6095 12.7883C3.39563 12.5579 3.39563 12.2004 3.6095 11.97L8.82043 6.37427C8.93469 6.2522 9.0929 6.18384 9.25989 6.18384ZM9.52063 17.3752H19.8517V7.38306H9.52063L4.86926 12.3792L9.52063 17.3752ZM12.7755 15.0686C12.6222 15.0686 12.4679 15.01 12.3517 14.8928C12.1173 14.6584 12.1173 14.2786 12.3517 14.0452L14.0503 12.3469L12.3517 10.6487C12.1173 10.4153 12.1173 10.0354 12.3517 9.80103C12.5841 9.56665 12.965 9.56665 13.1993 9.80103L14.8981 11.4994L16.5968 9.80103C16.8312 9.56665 17.212 9.56665 17.4445 9.80103C17.6788 10.0354 17.6788 10.4153 17.4445 10.6487L15.7458 12.3469L17.4445 14.0452C17.6788 14.2786 17.6788 14.6584 17.4445 14.8928C17.3282 15.01 17.174 15.0686 17.0206 15.0686C16.8673 15.0686 16.714 15.01 16.5968 14.8928L14.8981 13.1945L13.1993 14.8928C13.0822 15.01 12.9288 15.0686 12.7755 15.0686Z"/></svg>',
},
{
name: 'link',
action: EasyMDE.drawLink,
title: i18n.global.t('input.editor.link'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M11.4399 15.3452C11.4999 15.3652 11.5699 15.3752 11.6299 15.3752C11.8799 15.3752 12.1199 15.2152 12.1999 14.9652C12.2999 14.6452 12.1299 14.3052 11.8199 14.2052C11.3499 14.0452 10.9299 13.7852 10.5699 13.4152C10.1999 13.0552 9.9399 12.6452 9.7799 12.1552C9.6599 11.8252 9.5999 11.4652 9.5999 11.0952C9.5999 10.2152 9.9399 9.38518 10.5699 8.75518L15.1599 4.15518C16.4499 2.87518 18.5399 2.87518 19.8299 4.15518C20.4499 4.78518 20.7899 5.61518 20.7899 6.49518C20.7899 7.37518 20.4499 8.20518 19.8299 8.82518L16.7399 11.9052C16.5099 12.1452 16.5099 12.5252 16.7399 12.7552C16.9799 12.9852 17.3599 12.9852 17.5899 12.7552L20.6799 9.67518C21.5299 8.83518 21.9999 7.69518 21.9999 6.49518C21.9999 5.29518 21.5299 4.16518 20.6899 3.30518C18.9299 1.55518 16.0799 1.55518 14.3199 3.30518L9.7299 7.90518C8.8699 8.75518 8.3999 9.88518 8.3999 11.0952C8.3999 11.6152 8.4899 12.1152 8.6499 12.5552C8.8599 13.1952 9.2399 13.7952 9.7199 14.2652C10.1999 14.7552 10.7999 15.1352 11.4399 15.3452ZM3.32 20.6851C4.2 21.5551 5.35 21.9951 6.5 21.9951C7.65 21.9951 8.81 21.5551 9.69 20.7051L14.28 16.1051C15.14 15.2551 15.61 14.1251 15.61 12.9151C15.61 12.4551 15.54 11.9951 15.4 11.5551C15.17 10.8651 14.8 10.2551 14.28 9.73509C13.76 9.21509 13.15 8.84509 12.46 8.61509C12.14 8.51509 11.8 8.68509 11.7 8.99509C11.6 9.30509 11.77 9.64509 12.1 9.75509C12.61 9.91509 13.06 10.1951 13.44 10.5751C13.82 10.9551 14.09 11.4051 14.26 11.9151C14.36 12.2351 14.41 12.5651 14.41 12.9051C14.41 13.7951 14.06 14.6251 13.43 15.2451L8.84 19.8451C7.55 21.1251 5.46 21.1251 4.17 19.8451C3.55 19.2151 3.21 18.3951 3.21 17.5051C3.21 16.6151 3.55 15.7851 4.17 15.1651L7.35 11.9851C7.58 11.7451 7.59 11.3651 7.35 11.1351C7.11 10.9051 6.73 10.9051 6.5 11.1351L3.32 14.3151C2.47 15.1551 2 16.2851 2 17.4951C2 18.7051 2.47 19.8351 3.32 20.6851Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M11.4399 15.3452C11.4999 15.3652 11.5699 15.3752 11.6299 15.3752C11.8799 15.3752 12.1199 15.2152 12.1999 14.9652C12.2999 14.6452 12.1299 14.3052 11.8199 14.2052C11.3499 14.0452 10.9299 13.7852 10.5699 13.4152C10.1999 13.0552 9.9399 12.6452 9.7799 12.1552C9.6599 11.8252 9.5999 11.4652 9.5999 11.0952C9.5999 10.2152 9.9399 9.38518 10.5699 8.75518L15.1599 4.15518C16.4499 2.87518 18.5399 2.87518 19.8299 4.15518C20.4499 4.78518 20.7899 5.61518 20.7899 6.49518C20.7899 7.37518 20.4499 8.20518 19.8299 8.82518L16.7399 11.9052C16.5099 12.1452 16.5099 12.5252 16.7399 12.7552C16.9799 12.9852 17.3599 12.9852 17.5899 12.7552L20.6799 9.67518C21.5299 8.83518 21.9999 7.69518 21.9999 6.49518C21.9999 5.29518 21.5299 4.16518 20.6899 3.30518C18.9299 1.55518 16.0799 1.55518 14.3199 3.30518L9.7299 7.90518C8.8699 8.75518 8.3999 9.88518 8.3999 11.0952C8.3999 11.6152 8.4899 12.1152 8.6499 12.5552C8.8599 13.1952 9.2399 13.7952 9.7199 14.2652C10.1999 14.7552 10.7999 15.1352 11.4399 15.3452ZM3.32 20.6851C4.2 21.5551 5.35 21.9951 6.5 21.9951C7.65 21.9951 8.81 21.5551 9.69 20.7051L14.28 16.1051C15.14 15.2551 15.61 14.1251 15.61 12.9151C15.61 12.4551 15.54 11.9951 15.4 11.5551C15.17 10.8651 14.8 10.2551 14.28 9.73509C13.76 9.21509 13.15 8.84509 12.46 8.61509C12.14 8.51509 11.8 8.68509 11.7 8.99509C11.6 9.30509 11.77 9.64509 12.1 9.75509C12.61 9.91509 13.06 10.1951 13.44 10.5751C13.82 10.9551 14.09 11.4051 14.26 11.9151C14.36 12.2351 14.41 12.5651 14.41 12.9051C14.41 13.7951 14.06 14.6251 13.43 15.2451L8.84 19.8451C7.55 21.1251 5.46 21.1251 4.17 19.8451C3.55 19.2151 3.21 18.3951 3.21 17.5051C3.21 16.6151 3.55 15.7851 4.17 15.1651L7.35 11.9851C7.58 11.7451 7.59 11.3651 7.35 11.1351C7.11 10.9051 6.73 10.9051 6.5 11.1351L3.32 14.3151C2.47 15.1551 2 16.2851 2 17.4951C2 18.7051 2.47 19.8351 3.32 20.6851Z"/></svg>',
},
{
name: 'image',
action: EasyMDE.drawImage,
title: i18n.global.t('input.editor.image'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M4 4C2.89543 4 2 4.89543 2 6V16V17.5152V18C2 19.1046 2.89543 20 4 20H20C21.0528 20 21.9156 19.1866 21.9942 18.1539L22 18.1632V18V16V6C22 4.89543 21.1046 4 20 4H4ZM3.2 17.7V16.5642L6.78192 13.7254C6.8616 13.6622 6.97597 13.6689 7.04776 13.7409L10.3126 17.0146C10.7026 17.4056 11.3357 17.4065 11.7268 17.0165C11.7606 16.9827 11.792 16.9465 11.8207 16.9083L16.736 10.352C16.8023 10.2636 16.9277 10.2457 17.016 10.312C17.0355 10.3265 17.0521 10.3445 17.0651 10.365L20.8 16.2669V17.7C20.8 18.3075 20.3075 18.8 19.7 18.8H4.3C3.69249 18.8 3.2 18.3075 3.2 17.7ZM17.3865 8.61836L20.8 14.08V6.3C20.8 5.69249 20.3075 5.2 19.7 5.2H4.3C3.69249 5.2 3.2 5.69249 3.2 6.3V15.04L6.65054 12.2796C6.84949 12.1204 7.13629 12.1363 7.31645 12.3164L10.8369 15.8369C10.915 15.915 11.0417 15.915 11.1198 15.8369C11.1265 15.8302 16.5625 8.58336 16.5625 8.58336C16.7282 8.36245 17.0416 8.31768 17.2625 8.48336C17.3118 8.52034 17.3538 8.56611 17.3865 8.61836ZM8 8.5C8 9.32843 7.32843 10 6.5 10C5.67157 10 5 9.32843 5 8.5C5 7.67157 5.67157 7 6.5 7C7.32843 7 8 7.67157 8 8.5Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M4 4C2.89543 4 2 4.89543 2 6V16V17.5152V18C2 19.1046 2.89543 20 4 20H20C21.0528 20 21.9156 19.1866 21.9942 18.1539L22 18.1632V18V16V6C22 4.89543 21.1046 4 20 4H4ZM3.2 17.7V16.5642L6.78192 13.7254C6.8616 13.6622 6.97597 13.6689 7.04776 13.7409L10.3126 17.0146C10.7026 17.4056 11.3357 17.4065 11.7268 17.0165C11.7606 16.9827 11.792 16.9465 11.8207 16.9083L16.736 10.352C16.8023 10.2636 16.9277 10.2457 17.016 10.312C17.0355 10.3265 17.0521 10.3445 17.0651 10.365L20.8 16.2669V17.7C20.8 18.3075 20.3075 18.8 19.7 18.8H4.3C3.69249 18.8 3.2 18.3075 3.2 17.7ZM17.3865 8.61836L20.8 14.08V6.3C20.8 5.69249 20.3075 5.2 19.7 5.2H4.3C3.69249 5.2 3.2 5.69249 3.2 6.3V15.04L6.65054 12.2796C6.84949 12.1204 7.13629 12.1363 7.31645 12.3164L10.8369 15.8369C10.915 15.915 11.0417 15.915 11.1198 15.8369C11.1265 15.8302 16.5625 8.58336 16.5625 8.58336C16.7282 8.36245 17.0416 8.31768 17.2625 8.48336C17.3118 8.52034 17.3538 8.56611 17.3865 8.61836ZM8 8.5C8 9.32843 7.32843 10 6.5 10C5.67157 10 5 9.32843 5 8.5C5 7.67157 5.67157 7 6.5 7C7.32843 7 8 7.67157 8 8.5Z"/></svg>',
},
{
name: 'table',
action: EasyMDE.drawTable,
title: i18n.global.t('input.editor.table'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M6.18524 3.08496H19.4152C20.6752 3.08496 21.7152 4.11496 21.7152 5.38496V18.615C21.7152 19.885 20.6852 20.915 19.4152 20.915H6.18524C4.91524 20.915 3.88525 19.885 3.88525 18.615V5.38496C3.88525 4.11496 4.91524 3.08496 6.18524 3.08496ZM19.4052 19.705C20.0152 19.705 20.5052 19.215 20.5052 18.605H20.5153V5.38496C20.5153 4.77496 20.0252 4.28496 19.4152 4.28496H6.18524C5.57524 4.28496 5.08521 4.77496 5.08521 5.38496V18.605C5.08521 19.215 5.57524 19.705 6.18524 19.705H19.4052ZM17.4453 9.15503H8.15527C7.82527 9.15503 7.5553 9.42503 7.5553 9.75503C7.5553 10.085 7.82527 10.355 8.15527 10.355H17.4453C17.7753 10.355 18.0453 10.085 18.0453 9.75503C18.0453 9.42503 17.7753 9.15503 17.4453 9.15503ZM17.4453 13.635H8.15527C7.82527 13.635 7.5553 13.905 7.5553 14.235C7.5553 14.565 7.82527 14.835 8.15527 14.835H17.4453C17.7753 14.835 18.0453 14.565 18.0453 14.235C18.0453 13.905 17.7753 13.635 17.4453 13.635Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M6.18524 3.08496H19.4152C20.6752 3.08496 21.7152 4.11496 21.7152 5.38496V18.615C21.7152 19.885 20.6852 20.915 19.4152 20.915H6.18524C4.91524 20.915 3.88525 19.885 3.88525 18.615V5.38496C3.88525 4.11496 4.91524 3.08496 6.18524 3.08496ZM19.4052 19.705C20.0152 19.705 20.5052 19.215 20.5052 18.605H20.5153V5.38496C20.5153 4.77496 20.0252 4.28496 19.4152 4.28496H6.18524C5.57524 4.28496 5.08521 4.77496 5.08521 5.38496V18.605C5.08521 19.215 5.57524 19.705 6.18524 19.705H19.4052ZM17.4453 9.15503H8.15527C7.82527 9.15503 7.5553 9.42503 7.5553 9.75503C7.5553 10.085 7.82527 10.355 8.15527 10.355H17.4453C17.7753 10.355 18.0453 10.085 18.0453 9.75503C18.0453 9.42503 17.7753 9.15503 17.4453 9.15503ZM17.4453 13.635H8.15527C7.82527 13.635 7.5553 13.905 7.5553 14.235C7.5553 14.565 7.82527 14.835 8.15527 14.835H17.4453C17.7753 14.835 18.0453 14.565 18.0453 14.235C18.0453 13.905 17.7753 13.635 17.4453 13.635Z"/></svg>',
},
{
name: 'horizontal-rule',
action: EasyMDE.drawHorizontalRule,
title: i18n.global.t('input.editor.horizontalRule'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21 13H3C2.45 13 2 12.55 2 12C2 11.45 2.45 11 3 11H21C21.55 11 22 11.45 22 12C22 12.55 21.55 13 21 13Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M21 13H3C2.45 13 2 12.55 2 12C2 11.45 2.45 11 3 11H21C21.55 11 22 11.45 22 12C22 12.55 21.55 13 21 13Z"/></svg>',
},
'|',
{
name: 'side-by-side',
action: EasyMDE.toggleSideBySide,
title: i18n.global.t('input.editor.sideBySide'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M18.4787 14.58C18.3587 14.69 18.2987 14.85 18.2987 15C18.2987 15.15 18.3587 15.31 18.4787 15.42C18.7187 15.65 19.0987 15.65 19.3287 15.42L22.3287 12.42C22.5587 12.18 22.5587 11.8 22.3287 11.57L19.3287 8.56996C19.0887 8.33996 18.7087 8.33996 18.4787 8.56996C18.2487 8.80996 18.2487 9.18996 18.4787 9.41996L20.451 11.3999L14.4487 11.3999L14.4487 4.6C14.4487 4.27 14.1787 4 13.8487 4C13.5187 4 13.2487 4.27 13.2487 4.6L13.2487 19.4C13.2487 19.73 13.5187 20 13.8487 20C14.1787 20 14.4487 19.73 14.4487 19.4L14.4487 12.5999L20.4511 12.5999L18.4787 14.58ZM9.54878 19.4L9.54878 12.5999L3.5486 12.5999L5.52867 14.58C5.75867 14.81 5.75867 15.19 5.52867 15.43C5.29867 15.66 4.91867 15.66 4.67867 15.43L1.67867 12.43C1.63274 12.384 1.5956 12.3323 1.56725 12.2774C1.53058 12.2077 1.50724 12.1299 1.50068 12.0477C1.49934 12.0317 1.49867 12.0158 1.49867 12C1.49867 11.9841 1.49933 11.9682 1.50067 11.9522C1.51454 11.778 1.60365 11.6242 1.73526 11.5234L4.67867 8.57997C4.90867 8.34997 5.28867 8.34997 5.52867 8.57997C5.75867 8.80997 5.75867 9.18997 5.52867 9.42997L3.55107 11.3999L9.54878 11.3999L9.54878 4.6C9.54878 4.27 9.81878 4 10.1488 4C10.4788 4 10.7488 4.27 10.7488 4.6L10.7488 11.9999L10.7488 19.4C10.7488 19.73 10.4788 20 10.1488 20C9.81878 20 9.54878 19.73 9.54878 19.4Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M18.4787 14.58C18.3587 14.69 18.2987 14.85 18.2987 15C18.2987 15.15 18.3587 15.31 18.4787 15.42C18.7187 15.65 19.0987 15.65 19.3287 15.42L22.3287 12.42C22.5587 12.18 22.5587 11.8 22.3287 11.57L19.3287 8.56996C19.0887 8.33996 18.7087 8.33996 18.4787 8.56996C18.2487 8.80996 18.2487 9.18996 18.4787 9.41996L20.451 11.3999L14.4487 11.3999L14.4487 4.6C14.4487 4.27 14.1787 4 13.8487 4C13.5187 4 13.2487 4.27 13.2487 4.6L13.2487 19.4C13.2487 19.73 13.5187 20 13.8487 20C14.1787 20 14.4487 19.73 14.4487 19.4L14.4487 12.5999L20.4511 12.5999L18.4787 14.58ZM9.54878 19.4L9.54878 12.5999L3.5486 12.5999L5.52867 14.58C5.75867 14.81 5.75867 15.19 5.52867 15.43C5.29867 15.66 4.91867 15.66 4.67867 15.43L1.67867 12.43C1.63274 12.384 1.5956 12.3323 1.56725 12.2774C1.53058 12.2077 1.50724 12.1299 1.50068 12.0477C1.49934 12.0317 1.49867 12.0158 1.49867 12C1.49867 11.9841 1.49933 11.9682 1.50067 11.9522C1.51454 11.778 1.60365 11.6242 1.73526 11.5234L4.67867 8.57997C4.90867 8.34997 5.28867 8.34997 5.52867 8.57997C5.75867 8.80997 5.75867 9.18997 5.52867 9.42997L3.55107 11.3999L9.54878 11.3999L9.54878 4.6C9.54878 4.27 9.81878 4 10.1488 4C10.4788 4 10.7488 4.27 10.7488 4.6L10.7488 11.9999L10.7488 19.4C10.7488 19.73 10.4788 20 10.1488 20C9.81878 20 9.54878 19.73 9.54878 19.4Z"/></svg>',
},
{
name: 'guide',
@ -127,7 +127,7 @@ export function createEasyMDEConfig({ placeholder, uploadImage, imageUploadFunct
window.open('https://www.markdownguide.org/basic-syntax/', '_blank')
},
title: i18n.global.t('input.editor.guide'),
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill-rule="evenodd" clip-rule="evenodd" d="M19.4999 2.3999H6.4999C5.0699 2.3999 3.8999 3.5699 3.8999 4.9999V18.9999C3.8999 20.4299 5.0699 21.5999 6.4999 21.5999H19.4999C19.8299 21.5999 20.0999 21.3299 20.0999 20.9999V16.9999V2.9999C20.0999 2.6699 19.8299 2.3999 19.4999 2.3999ZM5.0999 4.9999V16.8118C5.50468 16.5513 5.98546 16.3999 6.4999 16.3999H18.8999V3.5999H6.4999C5.7299 3.5999 5.0999 4.2299 5.0999 4.9999ZM6.4999 17.5999H18.8999V20.3999H6.4999C5.7299 20.3999 5.0999 19.7699 5.0999 18.9999C5.0999 18.2299 5.7299 17.5999 6.4999 17.5999ZM8.4999 8.5999H15.4999C15.8299 8.5999 16.0999 8.3299 16.0999 7.9999C16.0999 7.6699 15.8299 7.3999 15.4999 7.3999H8.4999C8.1699 7.3999 7.8999 7.6699 7.8999 7.9999C7.8999 8.3299 8.1699 8.5999 8.4999 8.5999ZM15.4999 11.3999H8.4999C8.1699 11.3999 7.8999 11.6699 7.8999 11.9999C7.8999 12.3299 8.1699 12.5999 8.4999 12.5999H15.4999C15.8299 12.5999 16.0999 12.3299 16.0999 11.9999C16.0999 11.6699 15.8299 11.3999 15.4999 11.3999Z"/></svg>',
icon: '<svg viewBox="0 0 24 24"><rect fill="none" rx="0" ry="0"/><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M19.4999 2.3999H6.4999C5.0699 2.3999 3.8999 3.5699 3.8999 4.9999V18.9999C3.8999 20.4299 5.0699 21.5999 6.4999 21.5999H19.4999C19.8299 21.5999 20.0999 21.3299 20.0999 20.9999V16.9999V2.9999C20.0999 2.6699 19.8299 2.3999 19.4999 2.3999ZM5.0999 4.9999V16.8118C5.50468 16.5513 5.98546 16.3999 6.4999 16.3999H18.8999V3.5999H6.4999C5.7299 3.5999 5.0999 4.2299 5.0999 4.9999ZM6.4999 17.5999H18.8999V20.3999H6.4999C5.7299 20.3999 5.0999 19.7699 5.0999 18.9999C5.0999 18.2299 5.7299 17.5999 6.4999 17.5999ZM8.4999 8.5999H15.4999C15.8299 8.5999 16.0999 8.3299 16.0999 7.9999C16.0999 7.6699 15.8299 7.3999 15.4999 7.3999H8.4999C8.1699 7.3999 7.8999 7.6699 7.8999 7.9999C7.8999 8.3299 8.1699 8.5999 8.4999 8.5999ZM15.4999 11.3999H8.4999C8.1699 11.3999 7.8999 11.6699 7.8999 11.9999C7.8999 12.3299 8.1699 12.5999 8.4999 12.5999H15.4999C15.8299 12.5999 16.0999 12.3299 16.0999 11.9999C16.0999 11.6699 15.8299 11.3999 15.4999 11.3999Z"/></svg>',
},
],
}

View File

@ -1,7 +1,7 @@
<template>
<x-button
v-if="hasFilters"
type="secondary"
variant="secondary"
@click="clearFilters"
>
{{ $t('filters.clear') }}
@ -10,7 +10,7 @@
<template #trigger="{toggle}">
<x-button
@click.prevent.stop="toggle()"
type="secondary"
variant="secondary"
icon="filter"
>
{{ $t('filters.title') }}

View File

@ -28,17 +28,20 @@
</template>
<script lang="ts" setup>
import {ref, watch} from 'vue'
import {PropType, ref, watch} from 'vue'
import {useStore} from 'vuex'
import ListService from '@/services/list'
const background = ref(null)
import {colorIsDark} from '@/helpers/color/colorIsDark'
import ListModel from '@/models/list'
const background = ref<string | null>(null)
const backgroundLoading = ref(false)
const props = defineProps({
list: {
type: Object,
type: Object as PropType<ListModel>,
required: true,
},
showArchived: {
@ -66,7 +69,7 @@ async function loadBackground() {
const store = useStore()
function toggleFavoriteList(list) {
function toggleFavoriteList(list: ListModel) {
// The favorites pseudo list is always favorite
// Archived lists cannot be marked favorite
if (list.id === -1 || list.isArchived) {

View File

@ -14,25 +14,25 @@
</div>
<footer class="modal-card-foot is-flex is-justify-content-flex-end">
<x-button
v-if="tertiary !== ''"
:shadow="false"
type="tertary"
@click.prevent.stop="$emit('tertary')"
v-if="tertary !== ''"
variant="tertiary"
@click.prevent.stop="$emit('tertiary')"
>
{{ tertary }}
{{ tertiary }}
</x-button>
<x-button
type="secondary"
variant="secondary"
@click.prevent.stop="$router.back()"
>
{{ $t('misc.cancel') }}
</x-button>
<x-button
type="primary"
v-if="primaryLabel !== ''"
variant="primary"
@click.prevent.stop="primary"
:icon="primaryIcon"
:disabled="primaryDisabled"
v-if="primaryLabel !== ''"
>
{{ primaryLabel }}
</x-button>
@ -65,7 +65,7 @@ export default {
type: Boolean,
default: false,
},
tertary: {
tertiary: {
type: String,
default: '',
},
@ -78,7 +78,7 @@ export default {
default: false,
},
},
emits: ['create', 'primary', 'tertary'],
emits: ['create', 'primary', 'tertiary'],
methods: {
primary() {
this.$emit('create')

View File

@ -1,6 +1,6 @@
<template>
<div class="dropdown is-right is-active" ref="dropdown">
<div class="dropdown-trigger" @click="open = !open">
<div class="dropdown-trigger is-flex" @click="open = !open">
<slot name="trigger" :close="close">
<icon :icon="triggerIcon" class="icon"/>
</slot>

View File

@ -4,7 +4,7 @@
<template v-for="(s, i) in shortcuts" :key="i">
<h3>{{ $t(s.title) }}</h3>
<message>
<message class="mb-4">
{{
s.available($route) ? $t('keyboardShortcuts.currentPageOnly') : $t('keyboardShortcuts.allPages')
}}

View File

@ -13,7 +13,7 @@
<section class="content">
<div>
<h2 class="title" v-if="title">{{ title }}</h2>
<api-config @foundApi="hasApiUrl = true"/>
<api-config/>
<slot/>
</div>
<legal/>
@ -23,9 +23,9 @@
</template>
<script lang="ts" setup>
import Logo from '@/components/home/Logo'
import Message from '@/components/misc/message'
import Legal from '@/components/misc/legal'
import Logo from '@/components/home/Logo.vue'
import Message from '@/components/misc/message.vue'
import Legal from '@/components/misc/legal.vue'
import ApiConfig from '@/components/misc/api-config.vue'
import {useStore} from 'vuex'
import {computed} from 'vue'

View File

@ -26,7 +26,7 @@
@click="action.callback"
:shadow="false"
class="is-small"
type="secondary"
variant="secondary"
v-for="(action, i) in item.data.actions"
>
{{ action.title }}

View File

@ -50,11 +50,12 @@ import Message from '@/components/misc/message.vue'
import NoAuthWrapper from '@/components/misc/no-auth-wrapper.vue'
import {ERROR_NO_API_URL} from '@/helpers/checkAndSetApiUrl'
import {useOnline} from '@/composables/useOnline'
const store = useStore()
const ready = computed(() => store.state.vikunjaReady)
const online = computed(() => store.state.online)
const online = useOnline()
const error = ref('')
const showLoading = computed(() => !ready.value && error.value === '')

View File

@ -1,7 +1,7 @@
<template>
<x-button
type="secondary"
:icon="icon"
variant="secondary"
:icon="iconName"
v-tooltip="tooltipText"
@click="changeSubscription"
:disabled="disabled || null"
@ -16,7 +16,7 @@
v-else
>
<span class="icon">
<icon :icon="icon"/>
<icon :icon="iconName"/>
</span>
{{ buttonText }}
</a>
@ -38,9 +38,13 @@ const props = defineProps({
},
subscription: {
required: true,
validator(value) {
return value instanceof SubscriptionModel || value === null
},
},
entityId: {
required: true,
type: Number,
},
isButton: {
type: Boolean,
@ -48,6 +52,8 @@ const props = defineProps({
},
})
const subscriptionEntity = computed<string>(() => props.subscription.entity)
const emit = defineEmits(['change'])
const subscriptionService = shallowRef(new SubscriptionService())
@ -57,7 +63,7 @@ const tooltipText = computed(() => {
if (disabled.value) {
return t('task.subscription.subscribedThroughParent', {
entity: props.entity,
parent: props.subscription.entity,
parent: subscriptionEntity.value,
})
}
@ -67,13 +73,13 @@ const tooltipText = computed(() => {
})
const buttonText = computed(() => props.subscription !== null ? t('task.subscription.unsubscribe') : t('task.subscription.subscribe'))
const icon = computed(() => props.subscription !== null ? ['far', 'bell-slash'] : 'bell')
const iconName = computed(() => props.subscription !== null ? ['far', 'bell-slash'] : 'bell')
const disabled = computed(() => {
if (props.subscription === null) {
return false
}
return props.subscription.entity !== props.entity
return subscriptionEntity.value !== props.entity
})
function changeSubscription() {

View File

@ -31,14 +31,15 @@
<div class="actions">
<x-button
@click="$emit('close')"
type="tertary"
variant="tertiary"
class="has-text-danger"
>
{{ $t('misc.cancel') }}
</x-button>
<x-button
@click="$emit('submit')"
type="primary"
variant="primary"
v-cy="'modalPrimary'"
:shadow="false"
>
{{ $t('misc.doit') }}

View File

@ -13,6 +13,7 @@
import {ref, computed} from 'vue'
import {useStore} from 'vuex'
import Multiselect from '@/components/input/multiselect.vue'
import NamespaceModel from '@/models/namespace'
const emit = defineEmits(['selected'])
@ -25,7 +26,7 @@ function findNamespaces(newQuery: string) {
query.value = newQuery
}
function select(namespace) {
function select(namespace: NamespaceModel) {
emit('selected', namespace)
}
</script>

View File

@ -42,7 +42,7 @@ import {useI18n} from 'vue-i18n'
import {useStore} from 'vuex'
import { tryOnMounted, debouncedWatch, useWindowSize, MaybeRef } from '@vueuse/core'
import TaskService from '../../services/task'
import TaskService from '@/services/task'
import QuickAddMagic from '@/components/tasks/partials/quick-add-magic.vue'
function cleanupTitle(title: string) {
@ -117,9 +117,6 @@ function useAutoHeightTextarea(value: MaybeRef<string>) {
return textarea
}
const emit = defineEmits(['taskAdded'])
const props = defineProps({
defaultPosition: {
type: Number,
@ -127,8 +124,7 @@ const props = defineProps({
},
})
const taskService = shallowReactive(new TaskService())
const errorMessage = ref('')
const emit = defineEmits(['taskAdded'])
const newTaskTitle = ref('')
const newTaskInput = useAutoHeightTextarea(newTaskTitle)
@ -136,6 +132,9 @@ const newTaskInput = useAutoHeightTextarea(newTaskTitle)
const { t } = useI18n()
const store = useStore()
const taskService = shallowReactive(new TaskService())
const errorMessage = ref('')
async function addTask() {
if (newTaskTitle.value === '') {
errorMessage.value = t('list.create.addTitleRequired')

View File

@ -78,7 +78,6 @@
<script>
import AsyncEditor from '@/components/input/AsyncEditor'
import ListService from '../../services/list'
import TaskService from '../../services/task'
import TaskModel from '../../models/task'
import priorities from '../../models/constants/priorities'
@ -90,14 +89,10 @@ export default {
name: 'edit-task',
data() {
return {
listId: this.$route.params.id,
listService: new ListService(),
taskService: new TaskService(),
priorities: priorities,
list: {},
editorActive: false,
newTask: new TaskModel(),
isTaskEdit: false,
taskEditTask: TaskModel,
}

View File

@ -183,6 +183,8 @@ import {mapState} from 'vuex'
import Rights from '../../models/constants/rights.json'
import FilterPopup from '@/components/list/partials/filter-popup.vue'
import {colorIsDark} from '@/helpers/color/colorIsDark'
export default {
name: 'GanttChart',
components: {
@ -201,10 +203,10 @@ export default {
default: false,
},
dateFrom: {
default: new Date(new Date().setDate(new Date().getDate() - 15)),
default: () => new Date(new Date().setDate(new Date().getDate() - 15)),
},
dateTo: {
default: new Date(new Date().setDate(new Date().getDate() + 30)),
default: () => new Date(new Date().setDate(new Date().getDate() + 30)),
},
// The width of a day in pixels, used to calculate all sorts of things.
dayWidth: {
@ -252,6 +254,7 @@ export default {
canWrite: (state) => state.currentList.maxRight > Rights.READ,
}),
methods: {
colorIsDark,
buildTheGanttChart() {
this.setDates()
this.prepareGanttDays()

View File

@ -34,7 +34,7 @@
>
<div class="filename">{{ a.file.name }}</div>
<div class="info">
<p class="collapses">
<p class="attachment-info-meta">
<i18n-t keypath="task.attachment.createdBy">
<span v-tooltip="formatDate(a.created)">
{{ formatDateSince(a.created) }}
@ -83,7 +83,7 @@
@click="$refs.files.click()"
class="mb-4"
icon="cloud-upload-alt"
type="secondary"
variant="secondary"
:shadow="false"
>
{{ $t('task.attachment.upload') }}
@ -289,21 +289,6 @@ export default {
content: '·';
padding: 0 .25rem;
}
@media screen and (max-width: $mobile) {
&.collapses {
flex-direction: column;
> span:not(:last-child):after,
> a:not(:last-child):after {
display: none;
}
.user .username {
display: none;
}
}
}
}
}
}
@ -341,6 +326,10 @@ export default {
height: auto;
text-shadow: var(--shadow-md);
animation: bounce 2s infinite;
@media (prefers-reduced-motion: reduce) {
animation: none;
}
}
.hint {
@ -357,6 +346,35 @@ export default {
}
}
.attachment-info-meta {
display: flex;
align-items: center;
:deep(.user) {
display: flex !important;
align-items: center;
margin: 0 .5rem;
}
@media screen and (max-width: $mobile) {
flex-direction: column;
align-items: flex-start;
:deep(.user) {
margin: .5rem 0;
}
> span:not(:last-child):after,
> a:not(:last-child):after {
display: none;
}
.user .username {
display: none;
}
}
}
@keyframes bounce {
from,
20%,

View File

@ -1,6 +1,8 @@
<template>
<td v-tooltip="+date === 0 ? '' : formatDate(date)">
{{ +date === 0 ? '-' : formatDateSince(date) }}
<time :datetime="date ? formatISO(date) : null">
{{ +date === 0 ? '-' : formatDateSince(date) }}
</time>
</td>
</template>

View File

@ -8,21 +8,21 @@
<x-button
@click.prevent.stop="() => deferDays(1)"
:shadow="false"
type="secondary"
variant="secondary"
>
{{ $t('task.deferDueDate.1day') }}
</x-button>
<x-button
@click.prevent.stop="() => deferDays(3)"
:shadow="false"
type="secondary"
variant="secondary"
>
{{ $t('task.deferDueDate.3days') }}
</x-button>
<x-button
@click.prevent.stop="() => deferDays(7)"
:shadow="false"
type="secondary"
variant="secondary"
>
{{ $t('task.deferDueDate.1week') }}
</x-button>

View File

@ -25,13 +25,13 @@
<template #searchResult="props">
<span
v-if="typeof props.option === 'string'"
class="tag">
class="tag search-result">
<span>{{ props.option }}</span>
</span>
<span
v-else
:style="{'background': props.option.hexColor, 'color': props.option.textColor}"
class="tag">
class="tag search-result">
<span>{{ props.option.title }}</span>
</span>
</template>
@ -152,6 +152,18 @@ export default {
<style lang="scss" scoped>
.tag {
margin: .5rem 0 0 .5rem;
margin: .25rem !important;
}
.tag.search-result {
margin: 0 !important;
}
:deep(.input-wrapper) {
padding: .25rem !important;
}
:deep(input.input) {
padding: 0 .5rem;
}
</style>

View File

@ -28,9 +28,9 @@
<span class="icon">
<icon :icon="['far', 'calendar-alt']"/>
</span>
<span>
<time :datetime="formatISO(task.dueDate)">
{{ formatDateSince(task.dueDate) }}
</span>
</time>
</span>
<h3>{{ task.title }}</h3>
<progress
@ -73,6 +73,8 @@ import Done from '@/components/misc/Done.vue'
import Labels from '../../../components/tasks/partials/labels'
import ChecklistSummary from './checklist-summary'
import {colorIsDark} from '@/helpers/color/colorIsDark'
export default {
name: 'kanban-card',
components: {
@ -98,6 +100,7 @@ export default {
},
},
methods: {
colorIsDark,
async toggleTaskDone(task) {
this.loadingInternal = true
try {

View File

@ -6,7 +6,7 @@
class="is-pulled-right add-task-relation-button"
:class="{'is-active': showNewRelationForm}"
v-tooltip="$t('task.relation.add')"
type="secondary"
variant="secondary"
icon="plus"
:shadow="false"
/>
@ -274,10 +274,11 @@ export default {
return tasks
.map(task => {
// by doing this here once we can save a lot of duplicate calls in the template
const listAndNamespace = this.$store.getters['namespaces/getListAndNamespaceById'](task.listId, true)
const {
list,
namespace,
} = this.$store.getters['namespaces/getListAndNamespaceById'](task.listId, true)
} = listAndNamespace === null ? {list: null, namespace: null} : listAndNamespace
return {
...task,

View File

@ -1,9 +1,9 @@
<template>
<div class="control repeat-after-input">
<div class="buttons has-addons is-centered mt-2">
<x-button type="secondary" class="is-small" @click="() => setRepeatAfter(1, 'days')">{{ $t('task.repeat.everyDay') }}</x-button>
<x-button type="secondary" class="is-small" @click="() => setRepeatAfter(1, 'weeks')">{{ $t('task.repeat.everyWeek') }}</x-button>
<x-button type="secondary" class="is-small" @click="() => setRepeatAfter(1, 'months')">{{ $t('task.repeat.everyMonth') }}</x-button>
<x-button variant="secondary" class="is-small" @click="() => setRepeatAfter(1, 'days')">{{ $t('task.repeat.everyDay') }}</x-button>
<x-button variant="secondary" class="is-small" @click="() => setRepeatAfter(1, 'weeks')">{{ $t('task.repeat.everyWeek') }}</x-button>
<x-button variant="secondary" class="is-small" @click="() => setRepeatAfter(1, 'months')">{{ $t('task.repeat.everyMonth') }}</x-button>
</div>
<div class="is-flex is-align-items-center mb-2">
<label for="repeatMode" class="is-fullwidth">

View File

@ -39,14 +39,17 @@
:user="a"
v-for="(a, i) in task.assignees"
/>
<i
<time
:datetime="formatISO(task.dueDate)"
:class="{'overdue': task.dueDate <= new Date() && !task.done}"
class="is-italic"
@click.prevent.stop="showDefer = !showDefer"
v-if="+new Date(task.dueDate) > 0"
v-tooltip="formatDate(task.dueDate)"
:aria-expanded="showDefer ? 'true' : 'false'"
>
- {{ $t('task.detail.due', {at: formatDateSince(task.dueDate)}) }}
</i>
</time>
<transition name="fade">
<defer-task v-if="+new Date(task.dueDate) > 0 && showDefer" v-model="task" ref="deferDueDate"/>
</transition>

View File

@ -0,0 +1,16 @@
import {ref, watchEffect} from 'vue'
import {tryOnBeforeUnmount} from '@vueuse/core'
export function useBodyClass(className: string, defaultValue = false) {
const isActive = ref(defaultValue)
watchEffect(() => {
isActive.value
? document.body.classList.add(className)
: document.body.classList.remove(className)
})
tryOnBeforeUnmount(() => isActive.value && document.body.classList.remove(className))
return isActive
}

View File

@ -1,9 +1,9 @@
import {computed, watch, readonly} from 'vue'
import {useStorage, createSharedComposable, ColorSchema, usePreferredColorScheme, tryOnMounted} from '@vueuse/core'
import {useStorage, createSharedComposable, BasicColorSchema, usePreferredColorScheme, tryOnMounted} from '@vueuse/core'
const STORAGE_KEY = 'color-scheme'
const DEFAULT_COLOR_SCHEME_SETTING: ColorSchema = 'light'
const DEFAULT_COLOR_SCHEME_SETTING: BasicColorSchema = 'light'
const CLASS_DARK = 'dark'
const CLASS_LIGHT = 'light'
@ -16,7 +16,7 @@ const CLASS_LIGHT = 'light'
// - value is synced via `createSharedComposable`
// https://github.com/vueuse/vueuse/blob/main/packages/core/useDark/index.ts
export const useColorScheme = createSharedComposable(() => {
const store = useStorage<ColorSchema>(STORAGE_KEY, DEFAULT_COLOR_SCHEME_SETTING)
const store = useStorage<BasicColorSchema>(STORAGE_KEY, DEFAULT_COLOR_SCHEME_SETTING)
const preferredColorScheme = usePreferredColorScheme()

View File

@ -0,0 +1,31 @@
import {describe, it, expect} from 'vitest'
import {hourToSalutation} from './useDateTimeSalutation'
const dateWithHour = (hours: number): Date => {
const date = new Date()
date.setHours(hours)
return date
}
describe('Salutation', () => {
it('shows the right salutation in the night', () => {
const salutation = hourToSalutation(dateWithHour(4))
expect(salutation).toBe('home.welcomeNight')
})
it('shows the right salutation in the morning', () => {
const salutation = hourToSalutation(dateWithHour(8))
expect(salutation).toBe('home.welcomeMorning')
})
it('shows the right salutation in the day', () => {
const salutation = hourToSalutation(dateWithHour(13))
expect(salutation).toBe('home.welcomeDay')
})
it('shows the right salutation in the night', () => {
const salutation = hourToSalutation(dateWithHour(20))
expect(salutation).toBe('home.welcomeEvening')
})
it('shows the right salutation in the night again', () => {
const salutation = hourToSalutation(dateWithHour(23))
expect(salutation).toBe('home.welcomeNight')
})
})

View File

@ -0,0 +1,31 @@
import {computed} from 'vue'
import {useNow} from '@vueuse/core'
const TRANSLATION_KEY_PREFIX = 'home.welcome'
export function hourToSalutation(now: Date) {
const hours = now.getHours()
if (hours < 5) {
return `${TRANSLATION_KEY_PREFIX}Night`
}
if (hours < 11) {
return `${TRANSLATION_KEY_PREFIX}Morning`
}
if (hours < 18) {
return `${TRANSLATION_KEY_PREFIX}Day`
}
if (hours < 23) {
return `${TRANSLATION_KEY_PREFIX}Evening`
}
return `${TRANSLATION_KEY_PREFIX}Night`
}
export function useDateTimeSalutation() {
const now = useNow()
return computed(() => hourToSalutation(now.value))
}

View File

@ -0,0 +1,14 @@
import {ref} from 'vue'
import {useOnline as useNetworkOnline, ConfigurableWindow} from '@vueuse/core'
export function useOnline(options?: ConfigurableWindow) {
const fakeOnlineState = !!import.meta.env.VITE_IS_ONLINE
if (fakeOnlineState) {
console.log('Setting fake online state', fakeOnlineState)
}
return fakeOnlineState
? ref(true)
: useNetworkOnline(options)
}

View File

@ -1,3 +1,5 @@
import {it, expect} from 'vitest'
import {calculateItemPosition} from './calculateItemPosition'
it('should calculate the task position', () => {

View File

@ -1,3 +1,5 @@
import {describe, it, expect} from 'vitest'
import {findCheckboxesInText, getChecklistStatistics} from './checklistFromText'
describe('Find checklists in text', () => {

View File

@ -1,3 +1,5 @@
import {test, expect} from 'vitest'
import {colorFromHex} from './colorFromHex'
test('hex', () => {

View File

@ -1,3 +1,5 @@
import {test, expect} from 'vitest'
import {colorIsDark} from './colorIsDark'
test('dark color', () => {

View File

@ -1,3 +1,5 @@
import {describe, it, expect} from 'vitest'
import {filterLabelsByQuery} from './labels'
import {createNewIndexer} from '../indexes'

View File

@ -1,3 +1,5 @@
import {test, expect} from 'vitest'
import {calculateDayInterval} from './calculateDayInterval'
const days = {

View File

@ -1,3 +1,5 @@
import {test, expect} from 'vitest'
import {calculateNearestHours} from './calculateNearestHours'
test('5:00', () => {

View File

@ -1,3 +1,5 @@
import {test, expect} from 'vitest'
import {createDateFromString} from './createDateFromString'
test('YYYY-MM-DD HH:MM', () => {

View File

@ -1,5 +1,5 @@
import {createDateFromString} from '@/helpers/time/createDateFromString'
import {format, formatDistanceToNow} from 'date-fns'
import {format, formatDistanceToNow, formatISO as formatISOfns} from 'date-fns'
import {enGB, de, fr, ru} from 'date-fns/locale'
import {i18n} from '@/i18n'
@ -44,3 +44,7 @@ export const formatDateSince = (date) => {
addSuffix: true,
})
}
export function formatISO(date) {
return date ? formatISOfns(date) : ''
}

View File

@ -288,7 +288,7 @@ const getDateFromWeekday = (text: string): dateFoundResult => {
}
const getDayFromText = (text: string) => {
const matcher = /(([1-2][0-9])|(3[01])|(0?[1-9]))(st|nd|rd|th|\.)/ig
const matcher = /($| )(([1-2][0-9])|(3[01])|(0?[1-9]))(st|nd|rd|th|\.)($| )/ig
const results = matcher.exec(text)
if (results === null) {
return {
@ -302,17 +302,17 @@ const getDayFromText = (text: string) => {
const day = parseInt(results[0])
date.setDate(day)
// If the parsed day is the 31st but the next month only has 30 days, setting the day to 31 will "overflow" the
// date to the next month, but the first.
// If the parsed day is the 31st (or 29+ and the next month is february) but the next month only has 30 days,
// setting the day to 31 will "overflow" the date to the next month, but the first.
// This would look like a very weired bug. Now, to prevent that, we check if the day is the same as parsed after
// setting it for the first time and set it again if it isn't - that would mean the month overflowed.
if (day === 31 && date.getDate() !== day) {
date.setDate(day)
}
if (date < now) {
while (date < now) {
date.setMonth(date.getMonth() + 1)
}
if (date.getDate() !== day) {
date.setDate(day)
}
return {
foundText: results[0],

View File

@ -7,7 +7,7 @@
"lastViewed": "Naposledy zobrazeno",
"list": {
"newText": "Můžete vytvořit nový seznam pro své nové úkoly:",
"new": "Vytvořit nový seznam",
"new": "Nový seznam",
"importText": "Nebo importujte své seznamy a úkoly z jiných služeb:",
"import": "Importujte svá data do Vikunja"
}
@ -157,7 +157,7 @@
"searchSelect": "Klikněte nebo stiskněte Enter pro výběr tohoto seznamu",
"shared": "Sdílené seznamy",
"create": {
"header": "Vytvořit nový seznam",
"header": "Nový seznam",
"titlePlaceholder": "Název seznamu přijde sem…",
"addTitleRequired": "Uveďte prosím název.",
"createdSuccess": "Seznam byl úspěšně vytvořen.",
@ -315,7 +315,7 @@
"namespaces": "Prostory",
"search": "Začni psát pro vyhledání prostoru…",
"create": {
"title": "Vytvořit nový prostor",
"title": "Nový prostor",
"titleRequired": "Uveďte prosím název.",
"explanation": "Prostor je kolekce seznamů, které můžete sdílet a používat k organizaci seznamů. Každý seznam patří do nějakého prostoru.",
"tooltip": "Co je prostor?",
@ -383,7 +383,7 @@
"reminderRange": "Připomínky - období"
},
"create": {
"title": "Vytvořit uložený filtr",
"title": "Nový uložený filtr",
"description": "Uložený filtr je virtuální seznam, který se počítá ze sady filtrů pokaždé, když je přístupný. Jakmile bude vytvořen, objeví se ve speciálním prostoru.",
"action": "Vytvořit uložený filtr"
},
@ -545,7 +545,7 @@
"chooseStartDate": "Klikněte zde pro nastavení počátečního data",
"chooseEndDate": "Klikněte zde pro nastavení data ukončení",
"move": "Přesunout úkol do jiného seznamu",
"done": "Hotovo!",
"done": "Označit úkol jako hotový!",
"undone": "Označit jako znovu otevřené",
"created": "Vytvořeno {0} uživatelem {1}",
"updated": "Aktualizováno {0}",
@ -781,7 +781,7 @@
"then": "potom",
"task": {
"title": "Stránka úkolů",
"done": "Označit úkol jako hotový",
"done": "Hotovo",
"assign": "Přiřadit uživateli",
"labels": "Přidat štítky k tomuto úkolu",
"dueDate": "Změnit termín tohoto úkolu",
@ -899,7 +899,7 @@
"4015": "Komentář k úkolu neexistuje.",
"4016": "Neplatné pole úkolu.",
"4017": "Neplatný komparátor filtru úkolů.",
"4018": "Neplatný koncatinátor filtru úkolů.",
"4018": "Invalid task filter concatenator.",
"4019": "Neplatná hodnota filtru úkolů.",
"5001": "Prostor neexistuje.",
"5003": "Nemáte přístup ke zvolenému prostoru.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Zuletzt angesehen",
"list": {
"newText": "Du kannst eine neue Liste für deine neuen Aufgaben erstellen:",
"new": "Eine neue Liste erstellen",
"new": "Neue Liste",
"importText": "Oder importiere deine Listen und Aufgaben aus anderen Diensten in Vikunja:",
"import": "Deine Daten in Vikunja importieren"
}
@ -36,7 +36,7 @@
"password": "Passwort",
"passwordRepeat": "Gib dein Passwort erneut ein",
"passwordPlaceholder": "z.B. •••••••••••",
"forgotPassword": "Forgot your password?",
"forgotPassword": "Passwort vergessen?",
"resetPassword": "Setze dein Passwort zurück",
"resetPasswordAction": "Sende mir einen Link zum Zurücksetzen des Passworts",
"resetPasswordSuccess": "Prüfe deinen Posteingang! Du solltest eine E-Mail mit Anweisungen zum Zurücksetzen deines Passworts erhalten haben.",
@ -103,7 +103,7 @@
"title": "Avatar",
"initials": "Initialen",
"gravatar": "Gravatar",
"marble": "Marble",
"marble": "Murmel",
"upload": "Hochladen",
"uploadAvatar": "Avatar hochladen",
"statusUpdateSuccess": "Avatar-Status wurde erfolgreich aktualisiert.",
@ -157,7 +157,7 @@
"searchSelect": "Klicke auf oder drücke die Eingabetaste, um diese Liste auszuwählen",
"shared": "Geteilte Listen",
"create": {
"header": "Eine neue Liste erstellen",
"header": "Neue Liste",
"titlePlaceholder": "Der Titel der Liste steht hier…",
"addTitleRequired": "Bitte gebe einen Namen an.",
"createdSuccess": "Die Liste wurde erfolgreich erstellt.",
@ -315,7 +315,7 @@
"namespaces": "Namespaces",
"search": "Beginne zu schreiben, um einen Namespace zu suchen…",
"create": {
"title": "Einen neuen Namespace erstellen",
"title": "Neuer Namespace",
"titleRequired": "Bitte gebe einen Titel an.",
"explanation": "Ein Namespace ist eine Sammlung von Listen, die du teilen und zur Organisation verwenden kannst. Jede Liste zu einem Namespace.",
"tooltip": "Was ist ein Namespace?",
@ -374,7 +374,7 @@
"includeNulls": "Aufgaben ohne Werte einbeziehen",
"requireAll": "Alle Filterkriterien müssen erfüllt sein, damit eine Aufgabe angezeigt wird",
"showDoneTasks": "Erledigte Aufgaben anzeigen",
"sortAlphabetically": "Sort Alphabetically",
"sortAlphabetically": "Alphabetisch sortieren",
"enablePriority": "Filter nach Priorität aktivieren",
"enablePercentDone": "Filter nach % Erledigt aktivieren",
"dueDateRange": "Fälligkeitsbereich",
@ -383,7 +383,7 @@
"reminderRange": "Erinnerungs-Datumsbereich"
},
"create": {
"title": "Einen gespeicherten Filter erstellen",
"title": "Neuer gespeicherter Filter",
"description": "Ein gespeicherter Filter ist eine virtuelle Liste, die bei jedem Zugriff aus einem Satz von Filtern errechnet wird. Einmal erstellt, erscheint diese in einem speziellen Namespace.",
"action": "Neuen gespeicherten Filter erstellen"
},
@ -475,8 +475,8 @@
"download": "Herunterladen",
"showMenu": "Menü anzeigen",
"hideMenu": "Menü ausblenden",
"forExample": "For example:",
"welcomeBack": "Welcome Back!"
"forExample": "Zum Beispiel:",
"welcomeBack": "Willkommen zurück!"
},
"input": {
"resetColor": "Farbe zurücksetzen",
@ -545,7 +545,7 @@
"chooseStartDate": "Klicke hier, um ein Startdatum zu setzen",
"chooseEndDate": "Klicke hier, um ein Enddatum zu setzen",
"move": "Aufgabe in eine andere Liste verschieben",
"done": "Fertig!",
"done": "Als erledigt markieren!",
"undone": "Als nicht erledigt markieren",
"created": "Erstellt {0} von {1}",
"updated": "Aktualisiert {0}",
@ -726,8 +726,8 @@
"dateCurrentYear": "wird das laufende Jahr nutzen",
"dateNth": "wird den {day}. des aktuellen Monats verwenden",
"dateTime": "Kombiniere eines der Datumsformate mit \"{time}\" (oder {timePM}), um eine Zeit festzulegen.",
"repeats": "Repeating tasks",
"repeatsDescription": "To set a task as repeating in an interval, simply add '{suffix}' to the task text. The amount needs to be a number and can be omitted to use just the type (see examples)."
"repeats": "Wiederholende Aufgaben",
"repeatsDescription": "Um eine Aufgabe als Wiederholung in einem Intervall festzulegen, füge einfach '{suffix}' dem Aufgabentext hinzu. Der Betrag muss eine Zahl sein und kann weggelassen werden, um nur den Typ zu verwenden (siehe Beispiele)."
}
},
"team": {
@ -781,7 +781,7 @@
"then": "dann",
"task": {
"title": "Aufgabenseite",
"done": "Eine Aufgabe als erledigt markieren",
"done": "Fertig",
"assign": "Benutzer:in zuweisen",
"labels": "Dieser Aufgabe ein Label hinzufügen",
"dueDate": "Ändere das Fälligkeitsdatum dieser Aufgabe",
@ -814,7 +814,7 @@
"url": "Vikunja-URL",
"urlPlaceholder": "z.B. https://localhost:3456",
"change": "ändern",
"use": "Using Vikunja installation at {0}",
"use": "Verwende die Vikunja-Installation unter „{0}“",
"error": "Konnte keine Vikunja-Installation unter „{domain}“ finden oder verwenden. Bitte probiere eine andere Url.",
"success": "Verwende die Vikunja-Installation unter „{domain}“.",
"urlRequired": "Eine Url ist erforderlich."
@ -899,7 +899,7 @@
"4015": "Dieser Aufgabenkommentar existiert nicht.",
"4016": "Ungültiges Aufgabenfeld.",
"4017": "Ungültiger Aufgabenfilter (Vergleichskriterium).",
"4018": "Ungültiger Aufgabenfilter (Kombination).",
"4018": "Ungültige Verkettung von Aufgabenfiltern.",
"4019": "Ungültiger Aufgabenfilter (Wert).",
"5001": "Dieser Namespace existiert nicht.",
"5003": "Du hast keinen Zugriff auf den Namespace.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Zletscht ahglueget",
"list": {
"newText": "Du chasch e Liste für dini neue Uufgabe erstelle:",
"new": "Neui Liste erstelle",
"new": "Neue Liste",
"importText": "Oder importier dini Liste und Uufgabe us anderne Dienst nach Vikunja:",
"import": "Dini Date in Vikunja importiere"
}
@ -36,7 +36,7 @@
"password": "Passwort",
"passwordRepeat": "Gib dis Passwort nomal iih",
"passwordPlaceholder": "z.B. •••••••••••",
"forgotPassword": "Forgot your password?",
"forgotPassword": "Passwort vergessen?",
"resetPassword": "Setz diis Passwort zrugg",
"resetPasswordAction": "Schick mir en Passwort zruggsetz Link",
"resetPasswordSuccess": "Prüfe deinen Posteingang! Du solltest eine E-Mail mit Anweisungen zum Zurücksetzen deines Passworts erhalten haben.",
@ -103,7 +103,7 @@
"title": "Herr Der Elemente",
"initials": "Initialä",
"gravatar": "Gravatar",
"marble": "Marble",
"marble": "Murmel",
"upload": "Ufeladä",
"uploadAvatar": "Profiilbild ufeladä",
"statusUpdateSuccess": "Avatar Zuestand erfolgriich aktualisiert!",
@ -157,7 +157,7 @@
"searchSelect": "Druck uf Enter um die Liste uuszwähle",
"shared": "Teilti Liste",
"create": {
"header": "Neui Liste erstelle",
"header": "Neue Liste",
"titlePlaceholder": "Listetitl da ahgeh…",
"addTitleRequired": "Bitte gib en Titl ah.",
"createdSuccess": "Liste erfolgriich erstellt.",
@ -315,7 +315,7 @@
"namespaces": "Namensrüüm",
"search": "Schriib, um nachemne Namensruum z'sueche…",
"create": {
"title": "Neue Namensruum erstelle",
"title": "Neuer Namespace",
"titleRequired": "Bitte gib en Titl ah.",
"explanation": "En Namensruum isch e Gruppe vo Liste, wo du chasch zur Organisation benutze. Tatsächlich sind alli Listene emne Namensruum zuegwise.",
"tooltip": "Was isch en Namensruum?",
@ -374,7 +374,7 @@
"includeNulls": "Uufgabe ohni Wert iihbezieh",
"requireAll": "Alli Filter mend wahr sii, demits die Uufgab ahzeigt",
"showDoneTasks": "Zeig die fertige Uufgabe",
"sortAlphabetically": "Sort Alphabetically",
"sortAlphabetically": "Alphabetisch sortieren",
"enablePriority": "Filter nach Priorität aktiviere",
"enablePercentDone": "Filter nach Prozent iihschalte",
"dueDateRange": "Fälligkeitsberiich",
@ -383,7 +383,7 @@
"reminderRange": "Errinnerigs Datumbereich"
},
"create": {
"title": "Neue gspeicherete Filter erstelle",
"title": "Neuer gespeicherter Filter",
"description": "En gspeicherete Filter isch e virtuelli Liste, welche vomene Satz a Filter zemmegsetzt wird, sobald me uf sie zuegriift. Wenn sie mal erstellt worde isch, erhaltet si ihren eigene Namensruum.",
"action": "Neue gspeicherete Filter erstelle"
},
@ -475,8 +475,8 @@
"download": "Herunterladen",
"showMenu": "Menü anzeigen",
"hideMenu": "Menü ausblenden",
"forExample": "For example:",
"welcomeBack": "Welcome Back!"
"forExample": "Zum Beispiel:",
"welcomeBack": "Willkommen zurück!"
},
"input": {
"resetColor": "Farb zruggsetze",
@ -545,7 +545,7 @@
"chooseStartDate": "Druck dah, um es Startdatum z'setze",
"chooseEndDate": "Druck da, um es Enddatum z'setze",
"move": "Schieb die Uufgab in e anderi Liste",
"done": "Fertig!",
"done": "Als erledigt markieren!",
"undone": "Als unerledigt markierä",
"created": "Erstellt am {0} vo {1}",
"updated": "{0} g'updatet",
@ -726,8 +726,8 @@
"dateCurrentYear": "nimmt das laufende Jahr",
"dateNth": "nimmt de {day}ti vom jetzige Monet",
"dateTime": "Kombiniere irgendeis vo dene Datumsformat mit \"{time}\" (oder {timePM}) um e Ziit z'setze.",
"repeats": "Repeating tasks",
"repeatsDescription": "To set a task as repeating in an interval, simply add '{suffix}' to the task text. The amount needs to be a number and can be omitted to use just the type (see examples)."
"repeats": "Wiederholende Aufgaben",
"repeatsDescription": "Um eine Aufgabe als Wiederholung in einem Intervall festzulegen, füge einfach '{suffix}' dem Aufgabentext hinzu. Der Betrag muss eine Zahl sein und kann weggelassen werden, um nur den Typ zu verwenden (siehe Beispiele)."
}
},
"team": {
@ -781,7 +781,7 @@
"then": "dann",
"task": {
"title": "Uufgabesiite",
"done": "Uufgab als erledigt markiere",
"done": "Fertig",
"assign": "Benutzer:in zuweisen",
"labels": "Labels ennere Uufgab hinzuefüege",
"dueDate": "S'Fälligkeitsdatum für die Uufgab ändere",
@ -814,7 +814,7 @@
"url": "Vikunja URL",
"urlPlaceholder": "z.B. https://localhost:3456",
"change": "ändere",
"use": "Using Vikunja installation at {0}",
"use": "Verwende die Vikunja-Installation unter „{0}“",
"error": "Konnte keine Vikunja-Installation unter „{domain}“ finden oder verwenden. Bitte probiere eine andere Url.",
"success": "Benutze d'Vikunja Installation uf \"{domain}\".",
"urlRequired": "Eine Url ist erforderlich."
@ -899,7 +899,7 @@
"4015": "De Uufgabe Kommentar giz nid.",
"4016": "Ungültigs Uufgabefeld.",
"4017": "Ungültige Uufgabefilter vergliich.",
"4018": "Ungültige Uufgabefilter Zemmezug.",
"4018": "Ungültige Verkettung von Aufgabenfiltern.",
"4019": "Ungültigi Uufgabe Filter Wert.",
"5001": "De Namensruum existiert nid.",
"5003": "Du hesch kei Zuegriff zu dem Namensruum.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Last viewed",
"list": {
"newText": "You can create a new list for your new tasks:",
"new": "Create a new list",
"new": "New list",
"importText": "Or import your lists and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja"
}
@ -157,7 +157,7 @@
"searchSelect": "Click or press enter to select this list",
"shared": "Shared Lists",
"create": {
"header": "Create a new list",
"header": "New list",
"titlePlaceholder": "The list's title goes here…",
"addTitleRequired": "Please specify a title.",
"createdSuccess": "The list was successfully created.",
@ -315,7 +315,7 @@
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "Create a new namespace",
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of lists you can share and use to organize your lists with. In fact, every list belongs to a namepace.",
"tooltip": "What's a namespace?",
@ -383,7 +383,7 @@
"reminderRange": "Reminder Date Range"
},
"create": {
"title": "Create A Saved Filter",
"title": "New Saved Filter",
"description": "A saved filter is a virtual list which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.",
"action": "Create new saved filter"
},
@ -545,7 +545,7 @@
"chooseStartDate": "Click here to set a start date",
"chooseEndDate": "Click here to set an end date",
"move": "Move task to a different list",
"done": "Done!",
"done": "Mark task done!",
"undone": "Mark as undone",
"created": "Created {0} by {1}",
"updated": "Updated {0}",
@ -781,7 +781,7 @@
"then": "then",
"task": {
"title": "Task Page",
"done": "Mark a task as done",
"done": "Done",
"assign": "Assign to a user",
"labels": "Add labels to this task",
"dueDate": "Change the due date of this task",
@ -899,7 +899,7 @@
"4015": "The task comment does not exist.",
"4016": "Invalid task field.",
"4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatinator.",
"4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Last viewed",
"list": {
"newText": "You can create a new list for your new tasks:",
"new": "Create a new list",
"new": "New list",
"importText": "Or import your lists and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja"
}
@ -157,7 +157,7 @@
"searchSelect": "Click or press enter to select this list",
"shared": "Shared Lists",
"create": {
"header": "Create a new list",
"header": "New list",
"titlePlaceholder": "The list's title goes here…",
"addTitleRequired": "Please specify a title.",
"createdSuccess": "The list was successfully created.",
@ -315,7 +315,7 @@
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "Create a new namespace",
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of lists you can share and use to organize your lists with. In fact, every list belongs to a namepace.",
"tooltip": "What's a namespace?",
@ -383,7 +383,7 @@
"reminderRange": "Reminder Date Range"
},
"create": {
"title": "Create A Saved Filter",
"title": "New Saved Filter",
"description": "A saved filter is a virtual list which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.",
"action": "Create new saved filter"
},
@ -545,7 +545,7 @@
"chooseStartDate": "Click here to set a start date",
"chooseEndDate": "Click here to set an end date",
"move": "Move task to a different list",
"done": "Done!",
"done": "Mark task done!",
"undone": "Mark as undone",
"created": "Created {0} by {1}",
"updated": "Updated {0}",
@ -781,7 +781,7 @@
"then": "then",
"task": {
"title": "Task Page",
"done": "Mark a task as done",
"done": "Done",
"assign": "Assign to a user",
"labels": "Add labels to this task",
"dueDate": "Change the due date of this task",
@ -899,7 +899,7 @@
"4015": "The task comment does not exist.",
"4016": "Invalid task field.",
"4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatinator.",
"4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Dernière consultation",
"list": {
"newText": "Tu peux créer une nouvelle liste pour tes nouvelles tâches :",
"new": "Créer une nouvelle liste",
"new": "New list",
"importText": "Ou importe tes listes et tâches dautres services dans Vikunja :",
"import": "Importer tes données dans Vikunja"
}
@ -116,12 +116,12 @@
"vikunja": "Vikunja"
},
"appearance": {
"title": "Color Scheme",
"setSuccess": "Saved change of color scheme to {colorScheme}",
"title": "Jeu de couleurs",
"setSuccess": "Changement du jeu de couleurs enregistré vers {colorScheme}",
"colorScheme": {
"light": "Light",
"system": "System",
"dark": "Dark"
"light": "Clair",
"system": "Système",
"dark": "Sombre"
}
}
},
@ -157,7 +157,7 @@
"searchSelect": "Clique ou appuie sur la touche Entrée pour sélectionner cette liste",
"shared": "Listes partagées",
"create": {
"header": "Créer une nouvelle liste",
"header": "New list",
"titlePlaceholder": "Entre le nom de la liste…",
"addTitleRequired": "Indique un nom.",
"createdSuccess": "Liste créée.",
@ -315,7 +315,7 @@
"namespaces": "Espaces de noms",
"search": "Écris pour rechercher un espace de noms…",
"create": {
"title": "Créer un nouvel espace de noms",
"title": "New namespace",
"titleRequired": "Indique un nom.",
"explanation": "Des collections de listes pour partager et organiser vos listes. En fait, chaque liste appartient à un espace de noms.",
"tooltip": "Quest-ce quun espace de noms ?",
@ -383,7 +383,7 @@
"reminderRange": "Plage de dates de rappel"
},
"create": {
"title": "Créer un filtre enregistré",
"title": "New Saved Filter",
"description": "Un filtre enregistré est une liste virtuelle qui est calculée à partir dun ensemble de filtres à chaque fois quon y accède. Une fois créé, il apparaît dans un espace de noms spécial.",
"action": "Créer un nouveau filtre enregistré"
},
@ -475,7 +475,7 @@
"download": "Télécharger",
"showMenu": "Afficher le menu",
"hideMenu": "Masquer le menu",
"forExample": "For example:",
"forExample": "Par exemple :",
"welcomeBack": "Welcome Back!"
},
"input": {
@ -545,7 +545,7 @@
"chooseStartDate": "Clique ici pour fixer une date de début",
"chooseEndDate": "Clique ici pour fixer une date de fin",
"move": "Déplacer une tâche vers une autre liste",
"done": "Terminé !",
"done": "Mark task done!",
"undone": "Marquer comme inachevé",
"created": "Créé {0} par {1}",
"updated": "Mis à jour {0}",
@ -561,7 +561,7 @@
"text2": "Ceci supprimera également toutes les pièces jointes, les rappels et les relations associés à cette tâche et ne pourra pas être annulé !"
},
"actions": {
"assign": "Assign to a user",
"assign": "Attribuer à un utilisateur",
"label": "Ajouter des étiquettes",
"priority": "Définir la priorité",
"dueDate": "Définir léchéance",
@ -726,8 +726,8 @@
"dateCurrentYear": "utilisera lannée en cours",
"dateNth": "utilisera le {day}e du mois en cours",
"dateTime": "Combinez nimporte lequel des formats de date avec « {time} » (ou {timePM}) pour définir une heure.",
"repeats": "Repeating tasks",
"repeatsDescription": "To set a task as repeating in an interval, simply add '{suffix}' to the task text. The amount needs to be a number and can be omitted to use just the type (see examples)."
"repeats": "Tâches répétitives",
"repeatsDescription": "Pour définir une tâche comme répétitive dans un intervalle, il suffit d'ajouter « {suffix} » au texte de la tâche. Le montant doit être un nombre et peut être omis pour utiliser uniquement le type (voir exemples)."
}
},
"team": {
@ -781,8 +781,8 @@
"then": "puis",
"task": {
"title": "Page de tâche",
"done": "Marquer une tâche comme terminée",
"assign": "Assign to a user",
"done": "Done",
"assign": "Attribuer à un utilisateur",
"labels": "Ajouter des étiquettes à cette tâche",
"dueDate": "Modifier la date déchéance de cette tâche",
"attachment": "Ajouter une pièce jointe à cette tâche",
@ -899,7 +899,7 @@
"4015": "Le commentaire de la tâche nexiste pas.",
"4016": "Champ de tâche invalide.",
"4017": "Comparateur de filtre de tâche invalide.",
"4018": "Concaténateur de filtre de tâche invalide.",
"4018": "Invalid task filter concatenator.",
"4019": "Valeur de filtre de tâche invalide.",
"5001": "Lespace de noms nexiste pas.",
"5003": "Tu nas pas accès à lespace de noms indiqué.",
@ -908,7 +908,7 @@
"5010": "Cette équipe na pas accès à cet espace de noms.",
"5011": "Cet·e utilisateur·rice a déjà accès à cet espace de noms.",
"5012": "Lespace de noms est archivé et ne peut donc être consulté quen lecture seule.",
"6001": "The team name cannot be empty.",
"6001": "Le nom de l'équipe ne peut pas être vide.",
"6002": "Léquipe nexiste pas.",
"6004": "Léquipe a déjà accès à cet espace de noms ou à cette liste.",
"6005": "Lutilisateur·rice est déjà membre de cette équipe.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Ultima visualizzazione",
"list": {
"newText": "È possibile creare una nuova lista per le nuove attività:",
"new": "Crea una nuova lista",
"new": "Nuova lista",
"importText": "O importare le liste e le attività da altri servizi in Vikunja:",
"import": "Importa i tuoi dati in Vikunja"
}
@ -17,14 +17,14 @@
"text": "La pagina richiesta non esiste."
},
"ready": {
"loading": "Vikunja is loading…",
"errorOccured": "An error occured:",
"checkApiUrl": "Please check if the api url is correct.",
"noApiUrlConfigured": "No API url was configured. Please set one below:"
"loading": "Vikunja sta caricando…",
"errorOccured": "Si è verificato un errore:",
"checkApiUrl": "Controlla se l'URL API è corretto.",
"noApiUrlConfigured": "Nessun URL API configurato. Impostane uno qui sotto:"
},
"offline": {
"title": "You are offline.",
"text": "Please check your network connection and try again."
"title": "Sei offline.",
"text": "Controlla la connessione di rete e riprova."
},
"user": {
"auth": {
@ -36,7 +36,7 @@
"password": "Password",
"passwordRepeat": "Digita di nuovo la tua password",
"passwordPlaceholder": "es. ••••••••••••",
"forgotPassword": "Forgot your password?",
"forgotPassword": "Password dimenticata?",
"resetPassword": "Reimposta la tua password",
"resetPasswordAction": "Inviami il link per reimpostare la password",
"resetPasswordSuccess": "Controlla la tua casella di posta! Dovresti avere un'e-mail con le istruzioni su come reimpostare la password.",
@ -48,7 +48,7 @@
"register": "Registrati",
"loginWith": "Accedi con {provider}",
"authenticating": "Autenticazione…",
"openIdStateError": "State does not match, refusing to continue!",
"openIdStateError": "Stato non corrispondente, impossibile continuare!",
"openIdGeneralError": "Si è verificato un errore durante l'autenticazione con terze parti.",
"logout": "Esci"
},
@ -103,31 +103,31 @@
"title": "Avatar",
"initials": "Iniziali",
"gravatar": "Gravatar",
"marble": "Marble",
"marble": "Marmo",
"upload": "Carica",
"uploadAvatar": "Carica Avatar",
"statusUpdateSuccess": "Avatar status was updated successfully!",
"statusUpdateSuccess": "Avatar aggiornato!",
"setSuccess": "L'avatar è stato impostato con successo!"
},
"quickAddMagic": {
"title": "Quick Add Magic Mode",
"title": "Modalità Aggiunta Rapida Magica",
"disabled": "Disabilitato",
"todoist": "Todoist",
"vikunja": "Vikunja"
},
"appearance": {
"title": "Color Scheme",
"setSuccess": "Saved change of color scheme to {colorScheme}",
"title": "Tema",
"setSuccess": "Tema cambiato in {colorScheme}",
"colorScheme": {
"light": "Light",
"system": "System",
"dark": "Dark"
"light": "Chiaro",
"system": "Sistema",
"dark": "Scuro"
}
}
},
"deletion": {
"title": "Delete your Vikunja Account",
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your namespaces, lists, tasks and everything associated with it.",
"title": "Elimina il tuo Account Vikunja",
"text1": "La cancellazione del tuo account è permanente e non può essere annullata. Elimineremo tutti i tuoi namespace, liste, attività e tutto ciò che è ad esso associato.",
"text2": "Per continuare, inserisci la tua password. Riceverai un'e-mail con ulteriori istruzioni.",
"confirm": "Elimina il mio profilo",
"requestSuccess": "Richiesta riuscita. Riceverai un'e-mail con ulteriori istruzioni.",
@ -141,7 +141,7 @@
},
"export": {
"title": "Esporta i tuoi dati Vikunja",
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
"description": "Puoi richiedere una copia di tutti i tuoi dati all'interno di Vikunja. Questo include i Namespace, le Liste, le Attività e tutto ciò che è loro associato. È possibile importare questi dati in qualsiasi istanza Vikunja attraverso la funzione di migrazione.",
"descriptionPasswordRequired": "Inserisci la tua password per procedere:",
"request": "Richiedi una copia dei miei dati Vikunja",
"success": "Hai richiesto con successo i tuoi dati Vikunja! Ti invieremo un'e-mail una volta che saranno pronti da scaricare.",
@ -157,7 +157,7 @@
"searchSelect": "Fare clic o premere invio per selezionare questa lista",
"shared": "Liste Condivise",
"create": {
"header": "Crea una nuova lista",
"header": "Nuova lista",
"titlePlaceholder": "Il titolo della lista va qui…",
"addTitleRequired": "Specifica un titolo.",
"createdSuccess": "La lista è stata creata correttamente.",
@ -191,7 +191,7 @@
"duplicate": {
"title": "Duplica questa lista",
"label": "Duplica",
"text": "Select a namespace which should hold the duplicated list:",
"text": "Seleziona un namespace che dovrebbe contenere l'elenco duplicato:",
"success": "Lista duplicata."
},
"edit": {
@ -279,23 +279,23 @@
"title": "Kanban",
"limit": "Limite: {limit}",
"noLimit": "Non Impostato",
"doneBucket": "Done bucket",
"doneBucketHint": "All tasks moved into this bucket will automatically marked as done.",
"doneBucketHintExtended": "All tasks moved into the done bucket will be marked as done automatically. All tasks marked as done from elsewhere will be moved as well.",
"doneBucketSavedSuccess": "The done bucket has been saved successfully.",
"deleteLast": "You cannot remove the last bucket.",
"addTaskPlaceholder": "Enter the new task title…",
"doneBucket": "Colonna attività completate",
"doneBucketHint": "Tutte le attività spostate in questa colonna verranno automaticamente contrassegnate come completate.",
"doneBucketHintExtended": "Tutte le attività spostate nella colonna attività completate saranno contrassegnate automaticamente come completate. Tutte le attività contrassegnate come completate altrove verranno anche spostate.",
"doneBucketSavedSuccess": "Colonna attività completate salvata.",
"deleteLast": "Impossibile eliminare l'ultima colonna.",
"addTaskPlaceholder": "Inserisci il nuovo titolo dell'attività…",
"addTask": "Aggiungi un'attività",
"addAnotherTask": "Aggiungi un'altra attività",
"addBucket": "Create a new bucket",
"addBucketPlaceholder": "Enter the new bucket title…",
"deleteHeaderBucket": "Delete the bucket",
"deleteBucketText1": "Are you sure you want to delete this bucket?",
"deleteBucketText2": "This will not delete any tasks but move them into the default bucket.",
"deleteBucketSuccess": "The bucket has been deleted successfully.",
"bucketTitleSavedSuccess": "The bucket title has been saved successfully.",
"bucketLimitSavedSuccess": "The bucket limit been saved successfully.",
"collapse": "Collapse this bucket"
"addBucket": "Crea una nuova colonna",
"addBucketPlaceholder": "Inserisci il titolo della nuova colonna…",
"deleteHeaderBucket": "Elimina la colonna",
"deleteBucketText1": "Confermi di voler eliminare questa colonna?",
"deleteBucketText2": "Questo non eliminerà nessuna attività, ma la sposterà nel bucket predefinito.",
"deleteBucketSuccess": "Colonna eliminata.",
"bucketTitleSavedSuccess": "Titolo della colonna salvato.",
"bucketLimitSavedSuccess": "Limite della colonna salvato.",
"collapse": "Comprimi questa colonna"
},
"pseudo": {
"favorites": {
@ -304,52 +304,52 @@
}
},
"namespace": {
"title": "Namespaces & Lists",
"title": "Namespace e Liste",
"namespace": "Namespace",
"showArchived": "Show Archived",
"noneAvailable": "You don't have any namespaces right now.",
"unarchive": "Un-Archive",
"archived": "Archived",
"noLists": "This namespace does not contain any lists.",
"createList": "Create a new list in this namespace.",
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"showArchived": "Mostra Archiviati",
"noneAvailable": "Non hai alcun namespace in questo momento.",
"unarchive": "De-Archivia",
"archived": "Archiviato",
"noLists": "Questo namespace non contiene alcuna lista.",
"createList": "Crea una nuova lista in questo namespace.",
"namespaces": "Namespace",
"search": "Digita per cercare un namespace…",
"create": {
"title": "Create a new namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of lists you can share and use to organize your lists with. In fact, every list belongs to a namepace.",
"tooltip": "What's a namespace?",
"success": "The namespace was successfully created."
"title": "Nuovo namespace",
"titleRequired": "Specifica un titolo.",
"explanation": "Un namespace è una raccolta di liste che puoi condividere e che puoi usare per organizzare le tue liste. Infatti, ogni lista appartiene a un namespace.",
"tooltip": "Che cos'è un namespace?",
"success": "Namespace creato."
},
"archive": {
"titleArchive": "Archivia \"{namespace}\"",
"titleUnarchive": "Un-Archive \"{namespace}\"",
"archiveText": "You won't be able to edit this namespace or create new lists until you un-archive it. This will also archive all lists in this namespace.",
"unarchiveText": "You will be able to create new lists or edit it.",
"success": "The namespace was successfully archived.",
"description": "If a namespace is archived, you cannot create new lists or edit it."
"titleUnarchive": "Disarchivia \"{namespace}\"",
"archiveText": "Non sarà possibile modificare questo namespace o creare nuove liste fino a quando non verrà disarchiviato. Questo archivierà anche tutte le liste in questo namespace.",
"unarchiveText": "Potrai creare nuove liste o modificarle.",
"success": "Namespace creato.",
"description": "Se un namespace è archiviato, non è possibile creare nuove liste o modificarlo."
},
"delete": {
"title": "Delete \"{namespace}\"",
"text1": "Are you sure you want to delete this namespace and all of its contents?",
"title": "Elimina \"{namespace}\"",
"text1": "Sei sicuro di voler rimuovere questo namespace e tutto il relativo contenuto?",
"text2": "Questo include tutte le liste e le attività e NON PUÒ ESSERE RIPRISTINATO!",
"success": "The namespace was successfully deleted."
"success": "Namespace eliminato."
},
"edit": {
"title": "Modifica \"{namespace}\"",
"success": "The namespace was successfully updated."
"success": "Namespace aggiornato."
},
"share": {
"title": "Condividi \"{namespace}\""
},
"attributes": {
"title": "Namespace Title",
"titlePlaceholder": "The namespace title goes here…",
"title": "Titolo del Namespace",
"titlePlaceholder": "Il titolo del namespace va qui…",
"description": "Descrizione",
"descriptionPlaceholder": "The namespaces description goes here…",
"descriptionPlaceholder": "La descrizione del namespace va qui…",
"color": "Colore",
"archived": "Is Archived",
"isArchived": "This namespace is archived"
"archived": "Archiviato",
"isArchived": "Questo namespace è archiviato"
},
"pseudo": {
"sharedLists": {
@ -365,7 +365,7 @@
},
"filters": {
"title": "Filtri",
"clear": "Clear Filters",
"clear": "Pulisci Filtri",
"attributes": {
"title": "Titolo",
"titlePlaceholder": "Il titolo del filtro salvato va qui…",
@ -374,17 +374,17 @@
"includeNulls": "Includi attività che non hanno un valore impostato",
"requireAll": "Tutti i filtri devono essere veri affinché l'attività venga mostrata",
"showDoneTasks": "Mostra Attività Fatte",
"sortAlphabetically": "Sort Alphabetically",
"sortAlphabetically": "Ordine alfabetico",
"enablePriority": "Abilita Filtro Per Priorità",
"enablePercentDone": "Abilitare Filtro Per Percentuale Fatta",
"dueDateRange": "Intervallo Data Di Scadenza",
"startDateRange": "Intervallo Data Iniziale",
"endDateRange": "Intervallo Data Finale",
"reminderRange": "Reminder Date Range"
"reminderRange": "Intervallo date dei promemoria"
},
"create": {
"title": "Crea Un Filtro Salvato",
"description": "A saved filter is a virtual list which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.",
"title": "Nuovo Filtro Salvato",
"description": "Un filtro salvato è una lista virtuale che viene calcolata da un insieme di filtri di volta in volta. Una volta creato, apparirà in un namespace speciale.",
"action": "Crea nuovo filtro salvato"
},
"delete": {
@ -446,9 +446,9 @@
},
"navigation": {
"overview": "Panoramica",
"upcoming": "Upcoming",
"upcoming": "Prossimamente",
"settings": "Impostazioni",
"imprint": "Imprint",
"imprint": "Informazioni legali",
"privacy": "Politica sulla Privacy"
},
"misc": {
@ -464,19 +464,19 @@
"searchPlaceholder": "Digita per cercare…",
"previous": "Precedente",
"next": "Successivo",
"poweredBy": "Powered by Vikunja",
"poweredBy": "Creato con Vikunja",
"info": "Info",
"create": "Create",
"create": "Crea",
"doit": "Fallo!",
"saving": "Salvataggio…",
"saved": "Salvato!",
"default": "Predefinito",
"close": "Chiudi",
"download": "Scarica",
"showMenu": "Show the menu",
"hideMenu": "Hide the menu",
"forExample": "For example:",
"welcomeBack": "Welcome Back!"
"showMenu": "Mostra il menu",
"hideMenu": "Nascondi il menù",
"forExample": "Ad esempio:",
"welcomeBack": "Bentornato!"
},
"input": {
"resetColor": "Ripristina Colore",
@ -485,9 +485,9 @@
"tomorrow": "Domani",
"nextMonday": "Lunedì Prossimo",
"thisWeekend": "Questo fine settimana",
"laterThisWeek": "Later This Week",
"laterThisWeek": "Alla fine di questa settimana",
"nextWeek": "Prossima Settimana",
"chooseDate": "Choose a date"
"chooseDate": "Seleziona una data"
},
"editor": {
"edit": "Modifica",
@ -504,16 +504,16 @@
"quote": "Citazione",
"unorderedList": "Elenco puntato",
"orderedList": "Elenco numerato",
"cleanBlock": "Clean Block",
"cleanBlock": "Pulisci Blocco",
"link": "Link",
"image": "Immagine",
"table": "Tabella",
"horizontalRule": "Horizontal Rule",
"sideBySide": "Side By Side",
"guide": "Guide"
"horizontalRule": "Divisore Orizzontale",
"sideBySide": "Affianca",
"guide": "Guida"
},
"multiselect": {
"createPlaceholder": "Create new",
"createPlaceholder": "Crea nuovo",
"selectPlaceholder": "Clicca o premere invio per selezionare"
}
},
@ -533,19 +533,19 @@
"titleDates": "Attività dal {from} al {to}",
"noDates": "Mostra attività senza date",
"current": "Attività attuali",
"from": "Tasks from",
"until": "until",
"from": "Attività dal",
"until": "fino al",
"today": "Oggi",
"nextWeek": "Settimana Prossima",
"nextMonth": "Prossimo Mese",
"noTasks": "Nothing to do — Have a nice day!"
"noTasks": "Nessuna attività — Buona giornata!"
},
"detail": {
"chooseDueDate": "Clicca qui per impostare una data di scadenza",
"chooseStartDate": "Clicca qui per impostare una data di inizio",
"chooseEndDate": "Clicca qui per impostare una data di fine",
"move": "Sposta attività in un'altra lista",
"done": "Fatto!",
"done": "Segna attività fatta!",
"undone": "Segna come non completato",
"created": "Creato {0} da {1}",
"updated": "Aggiornato {0}",
@ -554,21 +554,21 @@
"deleteSuccess": "L'attività è stata eliminata con successo.",
"belongsToList": "Questa attività appartiene alla lista '{list}'",
"due": "Scadenza {at}",
"closePopup": "Close popup",
"closePopup": "Chiudi popup",
"delete": {
"header": "Elimina questa attività",
"text1": "Sei sicuro di voler eliminare questa attività?",
"text2": "Questo rimuoverà anche tutti gli allegati, i promemoria e le relazioni associati a questa attività e non può essere ripristinato!"
},
"actions": {
"assign": "Assign to a user",
"assign": "Assegna ad un utente",
"label": "Aggiungi etichette",
"priority": "Imposta Priorità",
"dueDate": "Imposta data di scadenza",
"startDate": "Imposta una data di inizio",
"endDate": "Imposta una data di fine",
"reminders": "Imposta promemoria",
"repeatAfter": "Set a repeating interval",
"repeatAfter": "Imposta ricorrenza",
"percentDone": "Imposta Percentuale Completata",
"attachments": "Aggiungi allegati",
"relatedTasks": "Aggiungi attività collegate",
@ -599,13 +599,13 @@
"updated": "Aggiornato"
},
"subscription": {
"subscribedThroughParent": "You can't unsubscribe here because you are subscribed to this {entity} through its {parent}.",
"subscribed": "You are currently subscribed to this {entity} and will receive notifications for changes.",
"notSubscribed": "You are not subscribed to this {entity} and won't receive notifications for changes.",
"subscribe": "Subscribe",
"unsubscribe": "Unsubscribe",
"subscribeSuccess": "You are now subscribed to this {entity}",
"unsubscribeSuccess": "You are now unsubscribed to this {entity}"
"subscribedThroughParent": "Non puoi annullare l'iscrizione qui perché sei iscritto a questo {entity} attraverso il suo {parent}.",
"subscribed": "Sei attualmente iscritto a questo {entity} e riceverai notifiche per le modifiche.",
"notSubscribed": "Non sei iscritto a questo {entity} e non riceverai notifiche per le modifiche.",
"subscribe": "Iscriviti",
"unsubscribe": "Disiscriviti",
"subscribeSuccess": "Ti sei iscritto a questo {entity}",
"unsubscribeSuccess": "Ti sei disiscritto a questo {entity}"
},
"attachment": {
"title": "Allegati",
@ -623,41 +623,41 @@
"comment": {
"title": "Commenti",
"loading": "Caricamento commenti…",
"edited": "edited {date}",
"edited": "modificato il {date}",
"creating": "Creazione del commento…",
"placeholder": "Aggiungi un commento…",
"comment": "Comment",
"comment": "Commenta",
"delete": "Elimina questo commento",
"deleteText1": "Sei sicuro di voler eliminare questo commento?",
"deleteText2": "Questa azione non può essere annullata!",
"addedSuccess": "Il commento è stato aggiunto correttamente."
},
"deferDueDate": {
"title": "Defer due date",
"title": "Rinvia data di scadenza",
"1day": "1 giorno",
"3days": "3 giorni",
"1week": "1 settimana"
},
"description": {
"placeholder": "Click here to enter a description…",
"empty": "No description available yet."
"placeholder": "Clicca qui per inserire una descrizione…",
"empty": "Nessuna descrizione."
},
"assignee": {
"placeholder": "Type to assign a user…",
"placeholder": "Digita per assegnare un utente…",
"selectPlaceholder": "Assegna questo utente",
"assignSuccess": "The user has been assigned successfully.",
"unassignSuccess": "The user has been unassigned successfully."
"assignSuccess": "Utente assegnato.",
"unassignSuccess": "Utente disassegnato."
},
"label": {
"placeholder": "Type to add a new label…",
"createPlaceholder": "Add this as new label",
"placeholder": "Digita per aggiungere una nuova etichetta…",
"createPlaceholder": "Aggiungila come nuova etichetta",
"addSuccess": "Etichetta aggiunta.",
"createSuccess": "Etichetta creata.",
"removeSuccess": "Etichetta eliminata.",
"addCreateSuccess": "Etichetta creata e aggiunta."
},
"priority": {
"unset": "Unset",
"unset": "Azzera",
"low": "Bassa",
"medium": "Media",
"high": "Alta",
@ -665,38 +665,38 @@
"doNow": "FARE ORA"
},
"relation": {
"add": "Add a New Task Relation",
"new": "New Task Relation",
"searchPlaceholder": "Type search for a new task to add as related…",
"createPlaceholder": "Add this as new related task",
"differentList": "This task belongs to a different list.",
"differentNamespace": "This task belongs to a different namespace.",
"noneYet": "No task relations yet.",
"delete": "Delete Task Relation",
"deleteText1": "Are you sure you want to delete this task relation?",
"add": "Aggiungi Attività Collegata",
"new": "Nuova Attività Collegata",
"searchPlaceholder": "Digita per cercare un'attività da aggiungere come collegata…",
"createPlaceholder": "Aggiungi come attività collegata",
"differentList": "Questa attività è di una lista diversa.",
"differentNamespace": "Questa attività appartiene ad un namespace diverso.",
"noneYet": "Nessuna attività collegata.",
"delete": "Elimina Collegamento Attività",
"deleteText1": "Confermi di voler eliminare questo collegamento attività?",
"deleteText2": "Questa azione non può essere annullata!",
"select": "Select a relation kind",
"select": "Seleziona un tipo di collegamento",
"kinds": {
"subtask": "Subtask | Subtasks",
"parenttask": "Parent Task | Parent Tasks",
"related": "Related Task | Related Tasks",
"subtask": "Sotto-attività | Sotto-attività",
"parenttask": "Attività Principale | Attività Principale",
"related": "Attività Correlata | Attività Correlata",
"duplicateof": "Duplicato Di | Duplicati Di",
"duplicates": "Duplicates | Duplicates",
"blocking": "Blocking | Blocking",
"blocked": "Blocked By | Blocked By",
"precedes": "Precedes | Precedes",
"follows": "Follows | Follows",
"copiedfrom": "Copied From | Copied From",
"copiedto": "Copied To | Copied To"
"duplicates": "Duplicato | Duplicati",
"blocking": "Bloccante | Bloccanti",
"blocked": "Bloccato Da | Bloccati Da",
"precedes": "Precede | Precede",
"follows": "Segue | Segue",
"copiedfrom": "Copiata Da | Copiate Da",
"copiedto": "Copiata In | Copiate In"
}
},
"repeat": {
"everyDay": "Ogni Giorno",
"everyWeek": "Ogni Settimana",
"everyMonth": "Ogni Mese",
"mode": "Repeat mode",
"mode": "Modalità Ripetizione",
"monthly": "Mensilmente",
"fromCurrentDate": "From Current Date",
"fromCurrentDate": "Dalla Data Attuale",
"each": "Ogni",
"specifyAmount": "Specifica una quantità…",
"hours": "Ore",
@ -706,32 +706,32 @@
"years": "Anni"
},
"quickAddMagic": {
"hint": "You can use Quick Add Magic",
"hint": "Puoi usare l'Aggiunta Rapida Magica",
"what": "Cosa?",
"title": "Quick Add Magic",
"intro": "When creating a task, you can use special keywords to directly add attributes to the newly created task. This allows to add commonly used attributes to tasks much faster.",
"title": "Aggiunta Rapida Magica",
"intro": "Quando si crea un'attività, è possibile utilizzare parole chiave speciali per aggiungere direttamente attributi all'attività appena creata. Questo permette di aggiungere gli attributi comuni molto più velocemente.",
"multiple": "Puoi usarlo più volte.",
"label1": "To add a label, simply prefix the name of the label with {prefix}.",
"label2": "Vikunja will first check if the label already exist and create it if not.",
"label3": "To use spaces, simply add a \" around the label name.",
"label4": "For example: {prefix}\"Label with spaces\".",
"priority1": "To set a task's priority, add a number 1-5, prefixed with a {prefix}.",
"priority2": "The higher the number, the higher the priority.",
"assignees": "To directly assign the task to a user, add their username prefixed with {prefix} to the task.",
"list1": "To set a list for the task to appear in, enter its name prefixed with {prefix}.",
"list2": "This will return an error if the list does not exist.",
"label1": "Per aggiungere un'etichetta, basta aggiungere il nome dell'etichetta preceduto da {prefix}.",
"label2": "Vikunja controllerà prima se l'etichetta esiste già e nel caso la creerà.",
"label3": "Per usare gli spazi, basta \" prima e dopo del nome dell'etichetta.",
"label4": "Per esempio: {prefix}\"Etichetta con spazi\".",
"priority1": "Per impostare la priorità di un'attività, aggiungi un numero 1-5, preceduto da {prefix}.",
"priority2": "Più alto è il numero, più alta è la priorità.",
"assignees": "Per assegnare direttamente l'attività a un utente, aggiungere il suo nome utente preceduto da {prefix} all'attività.",
"list1": "Per impostare una lista di appartenenza all'attività, inserisci il suo nome prefisso con {prefix}.",
"list2": "Ciò restituirà un errore se la lista non esiste.",
"dateAndTime": "Data e ora",
"date": "Any date will be used as the due date of the new task. You can use dates in any of these formats:",
"dateWeekday": "any weekday, will use the next date with that date",
"dateCurrentYear": "will use the current year",
"dateNth": "will use the {day}th of the current month",
"dateTime": "Combine any of the date formats with \"{time}\" (or {timePM}) to set a time.",
"repeats": "Repeating tasks",
"repeatsDescription": "To set a task as repeating in an interval, simply add '{suffix}' to the task text. The amount needs to be a number and can be omitted to use just the type (see examples)."
"date": "Qualsiasi data verrà utilizzata come data di scadenza della nuova attività. È possibile utilizzare le date in uno qualsiasi di questi formati:",
"dateWeekday": "qualsiasi giorno della settimana, userà la data più vicina",
"dateCurrentYear": "userà lanno corrente",
"dateNth": "userà il {day} del mese corrente",
"dateTime": "Combina uno qualsiasi dei formati di data con \"{time}\" (o {timePM}) per impostare un orario.",
"repeats": "Attività ricorrenti",
"repeatsDescription": "Per impostare un'attività come ricorrente in un intervallo, basta aggiungere '{suffix}' al testo dell'attività. La quantità deve essere un numero e può essere omesso per usare solo il tipo (vedi esempi)."
}
},
"team": {
"title": "Teams",
"title": "Gruppi",
"noTeams": "Non fai parte di nessun gruppo.",
"create": {
"title": "Crea un nuovo gruppo",
@ -746,23 +746,23 @@
"makeAdmin": "Rendi Amministratore",
"success": "Gruppo aggiornato.",
"userAddedSuccess": "Membro del gruppo aggiunto.",
"madeMember": "The team member was successfully made member.",
"madeAdmin": "The team member was successfully made admin.",
"madeMember": "Membro del gruppo reso membro.",
"madeAdmin": "Membro del gruppo reso amministratore.",
"delete": {
"header": "Elimina il gruppo",
"text1": "Sei sicuro di voler eliminare questo gruppo e tutti i suoi membri?",
"text2": "All team members will lose access to lists and namespaces shared with this team. This CANNOT BE UNDONE!",
"text2": "Tutti i membri del gruppo perderanno l'accesso alle liste e ai namespace condivisi con questo gruppo. NON PUÒ ESSERE RIPRISTINATO!",
"success": "Gruppo eliminato."
},
"deleteUser": {
"header": "Rimuovi un utente dal gruppo",
"text1": "Confermi di voler rimuovere questo utente dal gruppo?",
"text2": "They will lose access to all lists and namespaces this team has access to. This CANNOT BE UNDONE!",
"text2": "Perderanno l'accesso a tutte le liste e i namespace a cui questo gruppo ha accesso. NON PUÒ ESSERE RIPRISTINATO!",
"success": "Utente rimosso dal gruppo."
}
},
"attributes": {
"name": "Team Name",
"name": "Nome Gruppo",
"namePlaceholder": "Il nome del gruppo va qui…",
"nameRequired": "Specifica un nome.",
"description": "Descrizione",
@ -772,32 +772,32 @@
}
},
"keyboardShortcuts": {
"title": "Keyboard Shortcuts",
"general": "General",
"title": "Tasti Rapidi",
"general": "Generali",
"allPages": "Queste scorciatoie funzionano in tutte le pagine.",
"currentPageOnly": "Queste scorciatoie funzionano solo nella pagina attuale.",
"toggleMenu": "Attiva/Disattiva Menu",
"quickSearch": "Apri la barra di ricerca/azione rapida",
"then": "then",
"then": "e dopo",
"task": {
"title": "Task Page",
"done": "Mark a task as done",
"assign": "Assign to a user",
"labels": "Add labels to this task",
"dueDate": "Change the due date of this task",
"attachment": "Add an attachment to this task",
"related": "Modify related tasks of this task"
"title": "Pagina Attività",
"done": "Fatto",
"assign": "Assegna a un utente",
"labels": "Aggiungi etichette a questa attività",
"dueDate": "Modifica la data di scadenza di questa attività",
"attachment": "Aggiungi un allegato a questa attività",
"related": "Modifica le attività collegate a questa"
},
"list": {
"title": "List Views",
"switchToListView": "Switch to list view",
"switchToGanttView": "Switch to gantt view",
"switchToKanbanView": "Switch to kanban view",
"switchToTableView": "Switch to table view"
"title": "Viste Liste",
"switchToListView": "Passa alla vista Lista",
"switchToGanttView": "Passa alla vista Gantt",
"switchToKanbanView": "Passa alla vista Kanban",
"switchToTableView": "Passa alla vista Tabella"
}
},
"update": {
"available": "There is an update for Vikunja available!",
"available": "È disponibile un aggiornamento per Vikunja!",
"do": "Aggiorna Adesso"
},
"menu": {
@ -805,136 +805,136 @@
"archive": "Archivia",
"duplicate": "Duplica",
"delete": "Elimina",
"unarchive": "Un-Archive",
"setBackground": "Set background",
"unarchive": "Disarchivia",
"setBackground": "Imposta sfondo",
"share": "Condividi",
"newList": "Nuova lista"
},
"apiConfig": {
"url": "URL Vikunja",
"urlPlaceholder": "es. http://localhost:8080",
"change": "change",
"use": "Using Vikunja installation at {0}",
"error": "Could not find or use Vikunja installation at \"{domain}\". Please try a different url.",
"success": "Using Vikunja installation at \"{domain}\".",
"urlRequired": "A url is required."
"change": "modifica",
"use": "Usa l'installazione di Vikunja a {0}",
"error": "Impossibile trovare o usare l'installazione di Vikunja su \"{domain}\". Prova per favore con un altro Url.",
"success": "Utilizzando l'installazione di Vikunja su \"{domain}\".",
"urlRequired": "L'URL è obbligatorio."
},
"loadingError": {
"failed": "Loading failed, please {0}. If the error persists, please {1}.",
"tryAgain": "try again",
"contact": "contact us"
"failed": "Caricamento non riuscito, si prega di {0}. Se l'errore persiste, per favore {1}.",
"tryAgain": "riprova",
"contact": "Contattaci"
},
"notification": {
"title": "Notifications",
"none": "You don't have any notifications. Have a nice day!",
"explainer": "Notifications will appear here when actions on namespaces, lists or tasks you subscribed to happen."
"title": "Notifiche",
"none": "Nessuna notifica. Buona giornata!",
"explainer": "Le notifiche appariranno qui quando le azioni su Namespace, liste o attività a cui hai sottoscritto la sottoscrizione avvengono."
},
"quickActions": {
"commands": "Commands",
"placeholder": "Type a command or search…",
"hint": "You can use {list} to limit the search to a list. Combine {list} or {label} (labels) with a search query to search for a task with these labels or on that list. Use {assignee} to only search for teams.",
"tasks": "Tasks",
"commands": "Comandi",
"placeholder": "Digita un comando o cerca…",
"hint": "Puoi usare {list} per limitare la ricerca a una lista. Unisci {list} o {label} (etichette) alla ricerca per trovare un'attività con quelle etichette o in quella lista. Usa {assignee} per cercare solo i gruppi.",
"tasks": "Attivitá",
"lists": "Liste",
"teams": "Teams",
"newList": "Enter the title of the new list…",
"newTask": "Enter the title of the new task…",
"newNamespace": "Enter the title of the new namespace…",
"newTeam": "Enter the name of the new team…",
"createTask": "Create a task in the current list ({title})",
"createList": "Create a list in the current namespace ({title})",
"teams": "Gruppi",
"newList": "Inserisci il titolo della nuova lista…",
"newTask": "Inserisci il titolo della nuova attività…",
"newNamespace": "Inserisci il titolo del nuovo namespace…",
"newTeam": "Inserisci il nome del nuovo gruppo…",
"createTask": "Crea un'attività nella lista attuale ({title})",
"createList": "Crea una lista nel namespace attuale ({title})",
"cmds": {
"newTask": "New task",
"newList": "New list",
"newNamespace": "New namespace",
"newTeam": "New team"
"newTask": "Nuova attività",
"newList": "Nuova lista",
"newNamespace": "Nuovo Namespace",
"newTeam": "Nuovo gruppo"
}
},
"date": {
"locale": "en",
"locale": "it",
"altFormatLong": "j M Y H:i",
"altFormatShort": "j M Y"
},
"error": {
"error": "Errore",
"success": "Success",
"success": "Fatto",
"0001": "Non ti è permesso farlo.",
"1001": "A user with this username already exists.",
"1001": "Esiste già un utente con questo nome utente.",
"1002": "Un utente con questo indirizzo e-mail esiste già.",
"1004": "No username and password specified.",
"1004": "Nessun nome utente e password specificati.",
"1005": "L'utente non esiste.",
"1006": "Impossibile ottenere l'id utente.",
"1008": "No password reset token provided.",
"1009": "Invalid password reset token.",
"1008": "Nessun codice di reimpostazione password fornito.",
"1009": "Codice di reimpostazione password non valido.",
"1010": "Token di conferma dell'e-mail non valido.",
"1011": "Wrong username or password.",
"1011": "Nome utente o password errati.",
"1012": "Indirizzo e-mail dell'utente non confermato.",
"1013": "La nuova password è vuota.",
"1014": "La vecchia password è vuota.",
"1015": "Autenticazione TOTP già abilitata per questo utente.",
"1016": "Autenticazione TOTP non abilitata per questo utente.",
"1017": "Codice TOTP non valido.",
"1018": "The user avatar type setting is invalid.",
"1018": "L'impostazione del tipo di avatar utente non è valida.",
"2001": "L'ID non può essere vuoto o 0.",
"2002": "Alcuni dati della richiesta non erano validi.",
"3001": "La lista non esiste.",
"3004": "You need to have read permissions on that list to perform that action.",
"3004": "Devi avere i permessi di lettura su quella lista per eseguire quell'azione.",
"3005": "Il titolo della lista non può essere vuoto.",
"3006": "The list share does not exist.",
"3006": "La condivisione della lista non esiste.",
"3007": "Esiste già una lista con questo identificatore.",
"3008": "The list is archived and can therefore only be accessed read only. This is also true for all tasks associated with this list.",
"4001": "The list task text cannot be empty.",
"4002": "The list task does not exist.",
"3008": "La lista è archiviata e può quindi essere consultata solo in sola lettura. Questo vale anche per tutte le attività associate a questa lista.",
"4001": "Il testo delle attività della lista non può essere vuoto.",
"4002": "Lista di attività non esistente.",
"4003": "Tutte le attività di modifica in blocco devono appartenere alla stessa lista.",
"4004": "Hai bisogno di almeno un'attività quando si modificano in blocco le attività.",
"4005": "Non hai il permesso di vedere l'attività.",
"4006": "You can't set a parent task as the task itself.",
"4007": "You can't create a task relation with an invalid kind of relation.",
"4008": "You can't create a task relation which already exists.",
"4009": "The task relation does not exist.",
"4010": "Cannot relate a task with itself.",
"4011": "The task attachment does not exist.",
"4012": "The task attachment is too large.",
"4013": "The task sort param is invalid.",
"4014": "The task sort order is invalid.",
"4015": "The task comment does not exist.",
"4016": "Invalid task field.",
"4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatinator.",
"4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",
"5006": "The namespace name cannot be empty.",
"5009": "You need to have namespace read access to perform that action.",
"5010": "This team does not have access to that namespace.",
"5011": "This user has already access to that namespace.",
"5012": "The namespace is archived and can therefore only be accessed read only.",
"6001": "The team name cannot be empty.",
"6002": "The team does not exist.",
"6004": "The team already has access to that namespace or list.",
"6005": "The user is already a member of that team.",
"6006": "Cannot delete the last team member.",
"6007": "The team does not have access to the list to perform that action.",
"7002": "The user already has access to that list.",
"4006": "Non è possibile impostare un'attività principale come l'attività stessa.",
"4007": "Non è possibile creare una relazione di attività con un tipo di relazione non valido.",
"4008": "Non è possibile creare una relazione di attività già esistente.",
"4009": "La relazione di attività non esiste.",
"4010": "Non è possibile relazionare un'attività con se stessa.",
"4011": "L'allegato dell'attività non esiste.",
"4012": "L'allegato dell'attività è troppo grande.",
"4013": "Il parametro di ordinamento dei task non è valido.",
"4014": "L' ordinamento dei task non è valido.",
"4015": "Il commento all'attività non esiste.",
"4016": "Campo attività non valido.",
"4017": "Comparatore di filtri attività non valido.",
"4018": "Concatenatore filtro attività non valido.",
"4019": "Filtro attività non valido.",
"5001": "Il namespace non esiste.",
"5003": "Non hai accesso a questo namespace.",
"5006": "Il nome del namespace non può essere vuoto.",
"5009": "Devi avere accesso in lettura al namespace per effettuare questa operazione.",
"5010": "Il tuo gruppo non ha accesso a questo namespace.",
"5011": "Questo utente ha già accesso a quel namespace.",
"5012": "Il namespace è archiviato e può quindi essere accessibile solo in sola lettura.",
"6001": "Il nome del gruppo non può essere vuoto.",
"6002": "Gruppo non esistente.",
"6004": "Il team ha già accesso a questo namespace o lista.",
"6005": "L'utente è già membro di quel gruppo.",
"6006": "Non è possibile eliminare l'ultimo membro del gruppo.",
"6007": "Il gruppo non ha accesso alla lista per eseguire quell'azione.",
"7002": "L'utente ha già accesso a quella lista.",
"7003": "Non hai accesso a quella lista.",
"8001": "Questa etichetta esiste già in quell'attività.",
"8002": "L'etichetta non esiste.",
"8003": "Non hai accesso a questa etichetta.",
"9001": "The right is invalid.",
"10001": "The bucket does not exist.",
"10002": "The bucket does not belong to that list.",
"10003": "You cannot remove the last bucket on a list.",
"10004": "You cannot add the task to this bucket as it already exceeded the limit of tasks it can hold.",
"10005": "There can be only one done bucket per list.",
"11001": "The saved filter does not exist.",
"11002": "Saved filters are not available for link shares.",
"12001": "The subscription entity type is invalid.",
"12002": "You are already subscribed to the entity itself or a parent entity.",
"13001": "This link share requires a password for authentication, but none was provided.",
"13002": "The provided link share password was invalid."
"9001": "Permesso non valido.",
"10001": "Colonna non esistente.",
"10002": "La colonna non appartiene a quella lista.",
"10003": "Non puoi rimuovere l'ultima colonna di una lista.",
"10004": "Non puoi aggiungere l'attività a questa colonna perché ha già superato il limite di attività che può contenere.",
"10005": "Ci può essere solo una colonna completati per lista.",
"11001": "Filtro salvato non esistente.",
"11002": "I filtri salvati non sono disponibili per i link di condivisione.",
"12001": "Il tipo di entità sottoscritto non è valido.",
"12002": "Sei già iscritto all'entità stessa o a un'entità principale.",
"13001": "Questa condivisione di link richiede una password per l'autenticazione, ma non è stato inserita.",
"13002": "La password inserita per il link di condivisione è valida."
},
"about": {
"title": "About",
"frontendVersion": "Frontend Version: {version}",
"apiVersion": "API Version: {version}"
"title": "Informazioni",
"frontendVersion": "Versione Frontend: {version}",
"apiVersion": "Versione API: {version}"
}
}

View File

@ -7,7 +7,7 @@
"lastViewed": "Last viewed",
"list": {
"newText": "You can create a new list for your new tasks:",
"new": "Create a new list",
"new": "New list",
"importText": "Or import your lists and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja"
}
@ -157,7 +157,7 @@
"searchSelect": "Click or press enter to select this list",
"shared": "Shared Lists",
"create": {
"header": "Create a new list",
"header": "New list",
"titlePlaceholder": "The list's title goes here…",
"addTitleRequired": "Please specify a title.",
"createdSuccess": "The list was successfully created.",
@ -315,7 +315,7 @@
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "Create a new namespace",
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of lists you can share and use to organize your lists with. In fact, every list belongs to a namepace.",
"tooltip": "What's a namespace?",
@ -383,7 +383,7 @@
"reminderRange": "Reminder Date Range"
},
"create": {
"title": "Create A Saved Filter",
"title": "New Saved Filter",
"description": "A saved filter is a virtual list which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.",
"action": "Create new saved filter"
},
@ -545,7 +545,7 @@
"chooseStartDate": "Click here to set a start date",
"chooseEndDate": "Click here to set an end date",
"move": "Move task to a different list",
"done": "Done!",
"done": "Mark task done!",
"undone": "Mark as undone",
"created": "Created {0} by {1}",
"updated": "Updated {0}",
@ -781,7 +781,7 @@
"then": "then",
"task": {
"title": "Task Page",
"done": "Mark a task as done",
"done": "Done",
"assign": "Assign to a user",
"labels": "Add labels to this task",
"dueDate": "Change the due date of this task",
@ -899,7 +899,7 @@
"4015": "The task comment does not exist.",
"4016": "Invalid task field.",
"4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatinator.",
"4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Last viewed",
"list": {
"newText": "You can create a new list for your new tasks:",
"new": "Create a new list",
"new": "New list",
"importText": "Or import your lists and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja"
}
@ -157,7 +157,7 @@
"searchSelect": "Click or press enter to select this list",
"shared": "Shared Lists",
"create": {
"header": "Create a new list",
"header": "New list",
"titlePlaceholder": "The list's title goes here…",
"addTitleRequired": "Please specify a title.",
"createdSuccess": "The list was successfully created.",
@ -315,7 +315,7 @@
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "Create a new namespace",
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of lists you can share and use to organize your lists with. In fact, every list belongs to a namepace.",
"tooltip": "What's a namespace?",
@ -383,7 +383,7 @@
"reminderRange": "Reminder Date Range"
},
"create": {
"title": "Create A Saved Filter",
"title": "New Saved Filter",
"description": "A saved filter is a virtual list which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.",
"action": "Create new saved filter"
},
@ -545,7 +545,7 @@
"chooseStartDate": "Click here to set a start date",
"chooseEndDate": "Click here to set an end date",
"move": "Move task to a different list",
"done": "Done!",
"done": "Mark task done!",
"undone": "Mark as undone",
"created": "Created {0} by {1}",
"updated": "Updated {0}",
@ -781,7 +781,7 @@
"then": "then",
"task": {
"title": "Task Page",
"done": "Mark a task as done",
"done": "Done",
"assign": "Assign to a user",
"labels": "Add labels to this task",
"dueDate": "Change the due date of this task",
@ -899,7 +899,7 @@
"4015": "The task comment does not exist.",
"4016": "Invalid task field.",
"4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatinator.",
"4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Last viewed",
"list": {
"newText": "You can create a new list for your new tasks:",
"new": "Create a new list",
"new": "New list",
"importText": "Or import your lists and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja"
}
@ -157,7 +157,7 @@
"searchSelect": "Click or press enter to select this list",
"shared": "Shared Lists",
"create": {
"header": "Create a new list",
"header": "New list",
"titlePlaceholder": "The list's title goes here…",
"addTitleRequired": "Please specify a title.",
"createdSuccess": "The list was successfully created.",
@ -315,7 +315,7 @@
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "Create a new namespace",
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of lists you can share and use to organize your lists with. In fact, every list belongs to a namepace.",
"tooltip": "What's a namespace?",
@ -383,7 +383,7 @@
"reminderRange": "Reminder Date Range"
},
"create": {
"title": "Create A Saved Filter",
"title": "New Saved Filter",
"description": "A saved filter is a virtual list which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.",
"action": "Create new saved filter"
},
@ -545,7 +545,7 @@
"chooseStartDate": "Click here to set a start date",
"chooseEndDate": "Click here to set an end date",
"move": "Move task to a different list",
"done": "Done!",
"done": "Mark task done!",
"undone": "Mark as undone",
"created": "Created {0} by {1}",
"updated": "Updated {0}",
@ -781,7 +781,7 @@
"then": "then",
"task": {
"title": "Task Page",
"done": "Mark a task as done",
"done": "Done",
"assign": "Assign to a user",
"labels": "Add labels to this task",
"dueDate": "Change the due date of this task",
@ -899,7 +899,7 @@
"4015": "The task comment does not exist.",
"4016": "Invalid task field.",
"4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatinator.",
"4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Last viewed",
"list": {
"newText": "You can create a new list for your new tasks:",
"new": "Create a new list",
"new": "New list",
"importText": "Or import your lists and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja"
}
@ -157,7 +157,7 @@
"searchSelect": "Click or press enter to select this list",
"shared": "Shared Lists",
"create": {
"header": "Create a new list",
"header": "New list",
"titlePlaceholder": "The list's title goes here…",
"addTitleRequired": "Please specify a title.",
"createdSuccess": "The list was successfully created.",
@ -315,7 +315,7 @@
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "Create a new namespace",
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of lists you can share and use to organize your lists with. In fact, every list belongs to a namepace.",
"tooltip": "What's a namespace?",
@ -383,7 +383,7 @@
"reminderRange": "Reminder Date Range"
},
"create": {
"title": "Create A Saved Filter",
"title": "New Saved Filter",
"description": "A saved filter is a virtual list which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.",
"action": "Create new saved filter"
},
@ -545,7 +545,7 @@
"chooseStartDate": "Click here to set a start date",
"chooseEndDate": "Click here to set an end date",
"move": "Move task to a different list",
"done": "Done!",
"done": "Mark task done!",
"undone": "Mark as undone",
"created": "Created {0} by {1}",
"updated": "Updated {0}",
@ -781,7 +781,7 @@
"then": "then",
"task": {
"title": "Task Page",
"done": "Mark a task as done",
"done": "Done",
"assign": "Assign to a user",
"labels": "Add labels to this task",
"dueDate": "Change the due date of this task",
@ -899,7 +899,7 @@
"4015": "The task comment does not exist.",
"4016": "Invalid task field.",
"4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatinator.",
"4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Последние просмотренные",
"list": {
"newText": "Ты можешь создать новый список для своих задач:",
"new": "Создать новый список",
"new": "New list",
"importText": "Или импортировать списки и задачи из других сервисов в Vikunja:",
"import": "Импорт данных в Vikunja"
}
@ -157,7 +157,7 @@
"searchSelect": "Кликни или нажми Enter для выбора этого списка",
"shared": "Общие списки",
"create": {
"header": "Создать новый список",
"header": "New list",
"titlePlaceholder": "Введи имя списка…",
"addTitleRequired": "Укажи название.",
"createdSuccess": "Список создан.",
@ -315,7 +315,7 @@
"namespaces": "Пространства имён",
"search": "Введи запрос для поиска пространства имён…",
"create": {
"title": "Создать новое пространство имён",
"title": "New namespace",
"titleRequired": "Укажи название.",
"explanation": "Коллекции списков для совместного использования и организации ваших списков. Фактически, каждый список принадлежит какому-нибудь пространству имён.",
"tooltip": "Что такое пространство имён?",
@ -383,7 +383,7 @@
"reminderRange": "Диапазон даты напоминания"
},
"create": {
"title": "Создать сохранённый фильтр",
"title": "New Saved Filter",
"description": "Сохраненный фильтр это виртуальный список, построенный из набора фильтров. При создании отображается в специальном пространстве имен.",
"action": "Создать новый сохранённый фильтр"
},
@ -545,7 +545,7 @@
"chooseStartDate": "Нажми для выбора даты начала",
"chooseEndDate": "Нажми для выбора даты завершения",
"move": "Переместить задачу в другой список",
"done": "Завершено!",
"done": "Mark task done!",
"undone": "Не завершено",
"created": "Создана {0} пользователем {1}",
"updated": "Обновлено {0}",
@ -781,7 +781,7 @@
"then": "then",
"task": {
"title": "Страница задачи",
"done": "Пометить задачу завершённой",
"done": "Done",
"assign": "Assign to a user",
"labels": "Добавить метки этой задаче",
"dueDate": "Изменить срок этой задачи",
@ -899,7 +899,7 @@
"4015": "Комментарий не существует.",
"4016": "Неверное поле задачи.",
"4017": "Неверный сравнитель фильтров задач.",
"4018": "Неверный соединитель фильтров задач.",
"4018": "Invalid task filter concatenator.",
"4019": "Неверное значение фильтра задач.",
"5001": "Пространство имён не существует.",
"5003": "Нет доступа к указанному пространству имён.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Last viewed",
"list": {
"newText": "You can create a new list for your new tasks:",
"new": "Create a new list",
"new": "New list",
"importText": "Or import your lists and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja"
}
@ -157,7 +157,7 @@
"searchSelect": "Click or press enter to select this list",
"shared": "Shared Lists",
"create": {
"header": "Create a new list",
"header": "New list",
"titlePlaceholder": "The list's title goes here…",
"addTitleRequired": "Please specify a title.",
"createdSuccess": "The list was successfully created.",
@ -315,7 +315,7 @@
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "Create a new namespace",
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of lists you can share and use to organize your lists with. In fact, every list belongs to a namepace.",
"tooltip": "What's a namespace?",
@ -383,7 +383,7 @@
"reminderRange": "Reminder Date Range"
},
"create": {
"title": "Create A Saved Filter",
"title": "New Saved Filter",
"description": "A saved filter is a virtual list which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.",
"action": "Create new saved filter"
},
@ -545,7 +545,7 @@
"chooseStartDate": "Click here to set a start date",
"chooseEndDate": "Click here to set an end date",
"move": "Move task to a different list",
"done": "Done!",
"done": "Mark task done!",
"undone": "Mark as undone",
"created": "Created {0} by {1}",
"updated": "Updated {0}",
@ -781,7 +781,7 @@
"then": "then",
"task": {
"title": "Task Page",
"done": "Mark a task as done",
"done": "Done",
"assign": "Assign to a user",
"labels": "Add labels to this task",
"dueDate": "Change the due date of this task",
@ -899,7 +899,7 @@
"4015": "The task comment does not exist.",
"4016": "Invalid task field.",
"4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatinator.",
"4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Last viewed",
"list": {
"newText": "You can create a new list for your new tasks:",
"new": "Create a new list",
"new": "New list",
"importText": "Or import your lists and tasks from other services into Vikunja:",
"import": "Import your data into Vikunja"
}
@ -157,7 +157,7 @@
"searchSelect": "Click or press enter to select this list",
"shared": "Shared Lists",
"create": {
"header": "Create a new list",
"header": "New list",
"titlePlaceholder": "The list's title goes here…",
"addTitleRequired": "Please specify a title.",
"createdSuccess": "The list was successfully created.",
@ -315,7 +315,7 @@
"namespaces": "Namespaces",
"search": "Type to search for a namespace…",
"create": {
"title": "Create a new namespace",
"title": "New namespace",
"titleRequired": "Please specify a title.",
"explanation": "A namespace is a collection of lists you can share and use to organize your lists with. In fact, every list belongs to a namepace.",
"tooltip": "What's a namespace?",
@ -383,7 +383,7 @@
"reminderRange": "Reminder Date Range"
},
"create": {
"title": "Create A Saved Filter",
"title": "New Saved Filter",
"description": "A saved filter is a virtual list which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.",
"action": "Create new saved filter"
},
@ -545,7 +545,7 @@
"chooseStartDate": "Click here to set a start date",
"chooseEndDate": "Click here to set an end date",
"move": "Move task to a different list",
"done": "Done!",
"done": "Mark task done!",
"undone": "Mark as undone",
"created": "Created {0} by {1}",
"updated": "Updated {0}",
@ -781,7 +781,7 @@
"then": "then",
"task": {
"title": "Task Page",
"done": "Mark a task as done",
"done": "Done",
"assign": "Assign to a user",
"labels": "Add labels to this task",
"dueDate": "Change the due date of this task",
@ -899,7 +899,7 @@
"4015": "The task comment does not exist.",
"4016": "Invalid task field.",
"4017": "Invalid task filter comparator.",
"4018": "Invalid task filter concatinator.",
"4018": "Invalid task filter concatenator.",
"4019": "Invalid task filter value.",
"5001": "The namespace does not exist.",
"5003": "You do not have access to the specified namespace.",

View File

@ -7,7 +7,7 @@
"lastViewed": "Xem gần đây",
"list": {
"newText": "Bạn có thể tạo một danh sách công việc mới cho mình:",
"new": "Tạo một danh sách mới",
"new": "New list",
"importText": "Hoặc nhập danh sách và nhiệm vụ của bạn từ các dịch vụ khác vào Vikunja:",
"import": "Nhập dữ liệu của bạn vào Vikunja"
}
@ -157,7 +157,7 @@
"searchSelect": "Nhấp hoặc nhấn enter để chọn danh sách này",
"shared": "Đang tham gia",
"create": {
"header": "Tạo một danh sách mới",
"header": "New list",
"titlePlaceholder": "Tên danh sách ở đây…",
"addTitleRequired": "Hãy xác định một tên.",
"createdSuccess": "Danh sách đã được tạo thành công.",
@ -315,7 +315,7 @@
"namespaces": "Góc làm việc",
"search": "Gõ để tìm kiếm một góc làm việc…",
"create": {
"title": "Tạo một góc làm việc mới",
"title": "New namespace",
"titleRequired": "Hãy đặt một tiêu đề.",
"explanation": "Góc làm việc là một tập hợp các danh sách mà bạn có thể chia sẻ và sử dụng để sắp xếp các danh sách của mình. Trên thực tế, mọi danh sách đều thuộc về một góc làm việc.",
"tooltip": "Góc làm việc là gì?",
@ -383,7 +383,7 @@
"reminderRange": "Phạm vi Ngày nhắc nhở"
},
"create": {
"title": "Tạo một Bộ lọc sẵn",
"title": "New Saved Filter",
"description": "Bộ lọc sẵn là một danh sách ảo được chọn từ một tập hợp các bộ lọc. Sau khi được tạo, nó sẽ xuất hiện trong một không gian làm việc đặc biệt.",
"action": "Tạo thêm bộ lọc sẵn"
},
@ -545,7 +545,7 @@
"chooseStartDate": "Bấm vào đây để đặt ngày bắt đầu",
"chooseEndDate": "Bấm vào đây để đặt ngày kết thúc",
"move": "Di chuyển công việc sang một danh sách khác",
"done": "Xong!",
"done": "Mark task done!",
"undone": "Đánh dấu Chưa xong",
"created": "Đã tạo được {0} bởi {1}",
"updated": "Đã cập nhật {0}",
@ -781,7 +781,7 @@
"then": "sau đó",
"task": {
"title": "Trang công việc",
"done": "Đánh dấu hoàn thành",
"done": "Done",
"assign": "Chỉ định một người",
"labels": "Thêm nhãn cho công việc này",
"dueDate": "Thay đổi ngày hết hạn của công việc này",
@ -899,7 +899,7 @@
"4015": "Bình luận không tồn tại.",
"4016": "Trường công việc không hợp lệ.",
"4017": "Bộ so sánh bộ lọc công việc không hợp lệ.",
"4018": "Bộ lọc kết hợp không hợp lệ.",
"4018": "Invalid task filter concatenator.",
"4019": "Giá trị bộ lọc công việc không hợp lệ.",
"5001": "Góc làm việc không có nữa.",
"5003": "Bạn chưa được phép bước vào vào góc làm việc được chỉ định.",

View File

@ -1,11 +1,8 @@
import {createApp, configureCompat} from 'vue'
// default everything to Vue 3 behavior
configureCompat({
COMPONENT_V_MODEL: false,
COMPONENT_ASYNC: false,
RENDER_FUNCTION: false,
WATCH_ARRAY: false, // TODO: check this again; this might lead to some problemes
TRANSITION_GROUP_ROOT: false,
MODE: 3,
})
import App from './App.vue'
@ -21,7 +18,7 @@ declare global {
}
}
import {formatDate, formatDateShort, formatDateLong, formatDateSince} from '@/helpers/time/formatDate'
import {formatDate, formatDateShort, formatDateLong, formatDateSince, formatISO} from '@/helpers/time/formatDate'
// @ts-ignore
import {VERSION} from './version.json'
@ -55,6 +52,7 @@ app.use(Notifications)
// directives
import focus from '@/directives/focus'
// @ts-ignore The export does exist, ts just doesn't find it.
import { VTooltip } from 'v-tooltip'
import 'v-tooltip/dist/v-tooltip.css'
import shortcut from '@/directives/shortcut'
@ -79,7 +77,6 @@ app.component('card', Card)
// Mixins
import {getNamespaceTitle} from './helpers/getNamespaceTitle'
import {getListTitle} from './helpers/getListTitle'
import {colorIsDark} from './helpers/color/colorIsDark'
import {setTitle} from './helpers/setTitle'
app.mixin({
@ -88,9 +85,9 @@ app.mixin({
format: formatDate,
formatDate: formatDateLong,
formatDateShort: formatDateShort,
formatISO,
getNamespaceTitle,
getListTitle,
colorIsDark,
setTitle,
},
})

View File

@ -1,14 +1,15 @@
import {test, expect, fn} from 'vitest'
import {getHistory, removeListFromHistory, saveListToHistory} from './listHistory'
test('return an empty history when none was saved', () => {
Storage.prototype.getItem = jest.fn(() => null)
Storage.prototype.getItem = fn(() => null)
const h = getHistory()
expect(h).toStrictEqual([])
})
test('return a saved history', () => {
const saved = [{id: 1}, {id: 2}]
Storage.prototype.getItem = jest.fn(() => JSON.stringify(saved))
Storage.prototype.getItem = fn(() => JSON.stringify(saved))
const h = getHistory()
expect(h).toStrictEqual(saved)
@ -16,8 +17,8 @@ test('return a saved history', () => {
test('store list in history', () => {
let saved = {}
Storage.prototype.getItem = jest.fn(() => null)
Storage.prototype.setItem = jest.fn((key, lists) => {
Storage.prototype.getItem = fn(() => null)
Storage.prototype.setItem = fn((key, lists) => {
saved = lists
})
@ -27,8 +28,8 @@ test('store list in history', () => {
test('store only the last 5 lists in history', () => {
let saved: string | null = null
Storage.prototype.getItem = jest.fn(() => saved)
Storage.prototype.setItem = jest.fn((key: string, lists: string) => {
Storage.prototype.getItem = fn(() => saved)
Storage.prototype.setItem = fn((key: string, lists: string) => {
saved = lists
})
@ -43,8 +44,8 @@ test('store only the last 5 lists in history', () => {
test('don\'t store the same list twice', () => {
let saved: string | null = null
Storage.prototype.getItem = jest.fn(() => saved)
Storage.prototype.setItem = jest.fn((key: string, lists: string) => {
Storage.prototype.getItem = fn(() => saved)
Storage.prototype.setItem = fn((key: string, lists: string) => {
saved = lists
})
@ -55,8 +56,8 @@ test('don\'t store the same list twice', () => {
test('move a list to the beginning when storing it multiple times', () => {
let saved: string | null = null
Storage.prototype.getItem = jest.fn(() => saved)
Storage.prototype.setItem = jest.fn((key: string, lists: string) => {
Storage.prototype.getItem = fn(() => saved)
Storage.prototype.setItem = fn((key: string, lists: string) => {
saved = lists
})
@ -68,11 +69,11 @@ test('move a list to the beginning when storing it multiple times', () => {
test('remove list from history', () => {
let saved: string | null = '[{"id": 1}]'
Storage.prototype.getItem = jest.fn(() => null)
Storage.prototype.setItem = jest.fn((key: string, lists: string) => {
Storage.prototype.getItem = fn(() => null)
Storage.prototype.setItem = fn((key: string, lists: string) => {
saved = lists
})
Storage.prototype.removeItem = jest.fn((key: string) => {
Storage.prototype.removeItem = fn((key: string) => {
saved = null
})

View File

@ -1,9 +1,19 @@
import {beforeEach, afterEach, describe, it, expect, vi} from 'vitest'
import {parseTaskText} from './parseTaskText'
import {getDateFromText, getDateFromTextIn} from '../helpers/time/parseDate'
import {calculateDayInterval} from '../helpers/time/calculateDayInterval'
import priorities from '../models/constants/priorities.json'
describe('Parse Task Text', () => {
beforeEach(() => {
vi.useFakeTimers()
})
afterEach(() => {
vi.useRealTimers()
})
it('should return text with no intents as is', () => {
expect(parseTaskText('Lorem Ipsum').text).toBe('Lorem Ipsum')
})
@ -31,6 +41,13 @@ describe('Parse Task Text', () => {
expect(result.assignees[0]).toBe('user')
})
it('should ignore email addresses', () => {
const text = 'Lorem Ipsum email@example.com'
const result = parseTaskText(text)
expect(result.text).toBe(text)
})
describe('Date Parsing', () => {
it('should not return any date if none was provided', () => {
const result = parseTaskText('Lorem Ipsum')
@ -202,17 +219,36 @@ describe('Parse Task Text', () => {
expect(`${result.date.getHours()}:${result.date.getMinutes()}`).toBe('14:0')
})
it('should recognize dates of the month in the past but next month', () => {
const date = new Date()
date.setDate(date.getDate() - 1)
const result = parseTaskText(`Lorem Ipsum ${date.getDate()}nd`)
const time = new Date(2022, 0, 15)
vi.setSystemTime(time)
const result = parseTaskText(`Lorem Ipsum ${time.getDate() - 1}th`)
expect(result.text).toBe('Lorem Ipsum')
expect(result.date.getDate()).toBe(date.getDate())
expect(result.date.getDate()).toBe(time.getDate() - 1)
expect(result.date.getMonth()).toBe(time.getMonth() + 1)
})
it('should recognize dates of the month in the past but next month when february is the next month', () => {
const jan = new Date(2022, 0, 30)
vi.setSystemTime(jan)
const nextMonthWithDate = result.date.getDate() === 31
? (date.getMonth() + 2) % 12
: (date.getMonth() + 1) % 12
expect(result.date.getMonth()).toBe(nextMonthWithDate)
const result = parseTaskText(`Lorem Ipsum ${jan.getDate() - 1}th`)
const expectedDate = new Date(2022, 2, jan.getDate() - 1)
expect(result.text).toBe('Lorem Ipsum')
expect(result.date.getDate()).toBe(expectedDate.getDate())
expect(result.date.getMonth()).toBe(expectedDate.getMonth())
})
it('should recognize dates of the month in the past but next month when the next month has less days than this one', () => {
const mar = new Date(2022, 2, 32)
vi.setSystemTime(mar)
const result = parseTaskText(`Lorem Ipsum 31st`)
const expectedDate = new Date(2022, 4, 31)
expect(result.text).toBe('Lorem Ipsum')
expect(result.date.getDate()).toBe(expectedDate.getDate())
expect(result.date.getMonth()).toBe(expectedDate.getMonth())
})
it('should recognize dates of the month in the future', () => {
const nextDay = new Date(+new Date() + 60 * 60 * 24 * 1000)
@ -233,6 +269,12 @@ describe('Parse Task Text', () => {
expect(result.text).toBe('Lorem Ipsum github')
expect(result.date).toBeNull()
})
it('should not recognize date number with no spacing around them', () => {
const result = parseTaskText('Lorem Ispum v1.1.1')
expect(result.text).toBe('Lorem Ispum v1.1.1')
expect(result.date).toBeNull()
})
describe('Parse weekdays', () => {

View File

@ -117,23 +117,30 @@ export const parseTaskText = (text: string, prefixesMode: PrefixMode = PrefixMod
const getItemsFromPrefix = (text: string, prefix: string): string[] => {
const items: string[] = []
const itemParts = text.split(prefix)
const itemParts = text.split(' ' + prefix)
if (text.startsWith(prefix)) {
const firstItem = text.split(prefix)[1]
itemParts.unshift(firstItem)
}
itemParts.forEach((p, index) => {
// First part contains the rest
if (index < 1) {
return
}
let labelText
p = p.replace(prefix, '')
let itemText
if (p.charAt(0) === '\'') {
labelText = p.split('\'')[1]
itemText = p.split('\'')[1]
} else if (p.charAt(0) === '"') {
labelText = p.split('"')[1]
itemText = p.split('"')[1]
} else {
// Only until the next space
labelText = p.split(' ')[0]
itemText = p.split(' ')[0]
}
items.push(labelText)
items.push(itemText)
})
return Array.from(new Set(items))

View File

@ -2,73 +2,73 @@ import { createRouter, createWebHistory, RouteLocation } from 'vue-router'
import {saveLastVisited} from '@/helpers/saveLastVisited'
import {store} from '@/store'
import HomeComponent from '../views/Home'
import NotFoundComponent from '../views/404'
import About from '../views/About'
import HomeComponent from '../views/Home.vue'
import NotFoundComponent from '../views/404.vue'
import About from '../views/About.vue'
// User Handling
import LoginComponent from '../views/user/Login'
import RegisterComponent from '../views/user/Register'
import OpenIdAuth from '../views/user/OpenIdAuth'
import DataExportDownload from '../views/user/DataExportDownload'
import LoginComponent from '../views/user/Login.vue'
import RegisterComponent from '../views/user/Register.vue'
import OpenIdAuth from '../views/user/OpenIdAuth.vue'
import DataExportDownload from '../views/user/DataExportDownload.vue'
// Tasks
import ShowTasksInRangeComponent from '../views/tasks/ShowTasksInRange'
import LinkShareAuthComponent from '../views/sharing/LinkSharingAuth'
import TaskDetailViewModal from '../views/tasks/TaskDetailViewModal'
import TaskDetailView from '../views/tasks/TaskDetailView'
import ListNamespaces from '../views/namespaces/ListNamespaces'
import ShowTasksInRangeComponent from '../views/tasks/ShowTasksInRange.vue'
import LinkShareAuthComponent from '../views/sharing/LinkSharingAuth.vue'
import TaskDetailViewModal from '../views/tasks/TaskDetailViewModal.vue'
import TaskDetailView from '../views/tasks/TaskDetailView.vue'
import ListNamespaces from '../views/namespaces/ListNamespaces.vue'
// Team Handling
import ListTeamsComponent from '../views/teams/ListTeams'
import ListTeamsComponent from '../views/teams/ListTeams.vue'
// Label Handling
import ListLabelsComponent from '../views/labels/ListLabels'
import NewLabelComponent from '../views/labels/NewLabel'
import ListLabelsComponent from '../views/labels/ListLabels.vue'
import NewLabelComponent from '../views/labels/NewLabel.vue'
// Migration
import MigrationComponent from '../views/migrator/Migrate'
import MigrateServiceComponent from '../views/migrator/MigrateService'
import MigrationComponent from '../views/migrator/Migrate.vue'
import MigrateServiceComponent from '../views/migrator/MigrateService.vue'
// List Views
import ShowListComponent from '../views/list/ShowList'
import Kanban from '../views/list/views/Kanban'
import List from '../views/list/views/List'
import Gantt from '../views/list/views/Gantt'
import Table from '../views/list/views/Table'
import ShowListComponent from '../views/list/ShowList.vue'
import Kanban from '../views/list/views/Kanban.vue'
import List from '../views/list/views/List.vue'
import Gantt from '../views/list/views/Gantt.vue'
import Table from '../views/list/views/Table.vue'
// List Settings
import ListSettingEdit from '../views/list/settings/edit'
import ListSettingBackground from '../views/list/settings/background'
import ListSettingDuplicate from '../views/list/settings/duplicate'
import ListSettingShare from '../views/list/settings/share'
import ListSettingDelete from '../views/list/settings/delete'
import ListSettingArchive from '../views/list/settings/archive'
import ListSettingEdit from '../views/list/settings/edit.vue'
import ListSettingBackground from '../views/list/settings/background.vue'
import ListSettingDuplicate from '../views/list/settings/duplicate.vue'
import ListSettingShare from '../views/list/settings/share.vue'
import ListSettingDelete from '../views/list/settings/delete.vue'
import ListSettingArchive from '../views/list/settings/archive.vue'
// Namespace Settings
import NamespaceSettingEdit from '../views/namespaces/settings/edit'
import NamespaceSettingShare from '../views/namespaces/settings/share'
import NamespaceSettingArchive from '../views/namespaces/settings/archive'
import NamespaceSettingDelete from '../views/namespaces/settings/delete'
import NamespaceSettingEdit from '../views/namespaces/settings/edit.vue'
import NamespaceSettingShare from '../views/namespaces/settings/share.vue'
import NamespaceSettingArchive from '../views/namespaces/settings/archive.vue'
import NamespaceSettingDelete from '../views/namespaces/settings/delete.vue'
// Saved Filters
import FilterNew from '@/views/filters/FilterNew'
import FilterEdit from '@/views/filters/FilterEdit'
import FilterDelete from '@/views/filters/FilterDelete'
import FilterNew from '@/views/filters/FilterNew.vue'
import FilterEdit from '@/views/filters/FilterEdit.vue'
import FilterDelete from '@/views/filters/FilterDelete.vue'
const PasswordResetComponent = () => import('../views/user/PasswordReset')
const GetPasswordResetComponent = () => import('../views/user/RequestPasswordReset')
const UserSettingsComponent = () => import('../views/user/Settings')
const UserSettingsAvatarComponent = () => import('../views/user/settings/Avatar')
const UserSettingsCaldavComponent = () => import('../views/user/settings/Caldav')
const UserSettingsDataExportComponent = () => import('../views/user/settings/DataExport')
const UserSettingsDeletionComponent = () => import('../views/user/settings/Deletion')
const UserSettingsEmailUpdateComponent = () => import('../views/user/settings/EmailUpdate')
const UserSettingsGeneralComponent = () => import('../views/user/settings/General')
const UserSettingsPasswordUpdateComponent = () => import('../views/user/settings/PasswordUpdate')
const UserSettingsTOTPComponent = () => import('../views/user/settings/TOTP')
const PasswordResetComponent = () => import('../views/user/PasswordReset.vue')
const GetPasswordResetComponent = () => import('../views/user/RequestPasswordReset.vue')
const UserSettingsComponent = () => import('../views/user/Settings.vue')
const UserSettingsAvatarComponent = () => import('../views/user/settings/Avatar.vue')
const UserSettingsCaldavComponent = () => import('../views/user/settings/Caldav.vue')
const UserSettingsDataExportComponent = () => import('../views/user/settings/DataExport.vue')
const UserSettingsDeletionComponent = () => import('../views/user/settings/Deletion.vue')
const UserSettingsEmailUpdateComponent = () => import('../views/user/settings/EmailUpdate.vue')
const UserSettingsGeneralComponent = () => import('../views/user/settings/General.vue')
const UserSettingsPasswordUpdateComponent = () => import('../views/user/settings/PasswordUpdate.vue')
const UserSettingsTOTPComponent = () => import('../views/user/settings/TOTP.vue')
// List Handling
const NewListComponent = () => import('../views/list/NewList')
const NewListComponent = () => import('../views/list/NewList.vue')
// Namespace Handling
const NewNamespaceComponent = () => import('../views/namespaces/NewNamespace')
const NewNamespaceComponent = () => import('../views/namespaces/NewNamespace.vue')
const EditTeamComponent = () => import('../views/teams/EditTeam')
const NewTeamComponent = () => import('../views/teams/NewTeam')
const EditTeamComponent = () => import('../views/teams/EditTeam.vue')
const NewTeamComponent = () => import('../views/teams/NewTeam.vue')
const router = createRouter({
history: createWebHistory(),

View File

@ -7,7 +7,7 @@ import {
LOADING,
LOADING_MODULE,
MENU_ACTIVE,
ONLINE, QUICK_ACTIONS_ACTIVE,
QUICK_ACTIONS_ACTIVE,
} from './mutation-types'
import config from './modules/config'
import auth from './modules/auth'
@ -36,7 +36,6 @@ export const store = createStore({
state: {
loading: false,
loadingModule: null,
online: true,
// This is used to highlight the current list in menu for all list related views
currentList: {id: 0},
background: '',
@ -53,12 +52,6 @@ export const store = createStore({
[LOADING_MODULE](state, module) {
state.loadingModule = module
},
[ONLINE](state, online) {
if (import.meta.env.VITE_IS_ONLINE) {
console.log('Setting fake online state', import.meta.env.VITE_IS_ONLINE)
}
state.online = !!import.meta.env.VITE_IS_ONLINE || online
},
[CURRENT_LIST](state, currentList) {
// Server updates don't return the right. Therefore the right is reset after updating the list which is
// confusing because all the buttons will disappear in that case. To prevent this, we're keeping the right

View File

@ -1,7 +1,12 @@
import {HTTPFactory} from '@/http-common'
import {getCurrentLanguage, saveLanguage} from '@/i18n'
import {LOADING} from '../mutation-types'
import UserModel from '../../models/user'
import UserModel from '@/models/user'
import UserSettingsService from '@/services/userSettings'
import {getToken, refreshToken, removeToken, saveToken} from '@/helpers/auth'
import {setLoading} from '@/store/helper'
import {i18n} from '@/i18n'
import {success} from '@/message'
const AUTH_TYPES = {
'UNKNOWN': 0,
@ -98,10 +103,10 @@ export default {
const response = await HTTP.post('login', data)
// Save the token to local storage for later use
saveToken(response.data.token, true)
// Tell others the user is autheticated
ctx.dispatch('checkAuth')
} catch(e) {
} catch (e) {
if (
e.response &&
e.response.data.code === 1017 &&
@ -124,7 +129,7 @@ export default {
try {
await HTTP.post('register', credentials)
return ctx.dispatch('login', credentials)
} catch(e) {
} catch (e) {
if (e.response?.data?.message) {
throw e.response.data
}
@ -149,7 +154,7 @@ export default {
const response = await HTTP.post(`/auth/openid/${provider}/callback`, data)
// Save the token to local storage for later use
saveToken(response.data.token, true)
// Tell others the user is autheticated
ctx.dispatch('checkAuth')
} finally {
@ -200,7 +205,7 @@ export default {
}
},
async refreshUserInfo(ctx) {
async refreshUserInfo({state, commit, dispatch}) {
const jwt = getToken()
if (!jwt) {
return
@ -208,22 +213,53 @@ export default {
const HTTP = HTTPFactory()
try {
const response = await HTTP.get('user', {
headers: {
Authorization: `Bearer ${jwt}`,
},
})
const info = new UserModel(response.data)
info.type = ctx.state.info.type
info.email = ctx.state.info.email
info.exp = ctx.state.info.exp
ctx.commit('info', info)
ctx.commit('lastUserRefresh')
info.type = state.info.type
info.email = state.info.email
info.exp = state.info.exp
commit('info', info)
commit('lastUserRefresh')
if (typeof info.settings.language === 'undefined' || info.settings.language === '') {
// save current language
await dispatch('saveUserSettings', {
settings: {
...state.settings,
language: getCurrentLanguage(),
},
showMessage: false,
})
}
return info
} catch(e) {
throw new Error('Error while refreshing user info:', { cause: e })
} catch (e) {
throw new Error('Error while refreshing user info:', {cause: e})
}
},
async saveUserSettings(ctx, payload) {
const {settings} = payload
const showMessage = payload.showMessage ?? true
const userSettingsService = new UserSettingsService()
const cancel = setLoading(ctx, 'general-settings')
try {
saveLanguage(settings.language)
await userSettingsService.update(settings)
ctx.commit('setUserSettings', {...settings})
if (showMessage) {
success({message: i18n.global.t('user.settings.general.savedSuccess')})
}
} catch (e) {
throw new Error('Error while saving user settings:', {cause: e})
} finally {
cancel()
}
},
@ -240,7 +276,7 @@ export default {
try {
await refreshToken(!ctx.state.isLinkShareAuth)
ctx.dispatch('checkAuth')
} catch(e) {
} catch (e) {
// Don't logout on network errors as the user would then get logged out if they don't have
// internet for a short period of time - such as when the laptop is still reconnecting
if (e?.request?.status) {

View File

@ -23,8 +23,6 @@ export default {
return
}
// FIXME: direct manipulation of the prop
// might not be a problem since this is happening in the mutation
if (!namespace.lists || namespace.lists.length === 0) {
namespace.lists = state.namespaces[namespaceIndex].lists
}
@ -136,8 +134,8 @@ export default {
},
loadNamespacesIfFavoritesDontExist(ctx) {
// The first namespace should be the one holding all favorites
if (ctx.state.namespaces[0].id !== -2) {
// The first or second namespace should be the one holding all favorites
if (ctx.state.namespaces[0].id !== -2 && ctx.state.namespaces[1]?.id !== -2) {
return ctx.dispatch('loadNamespaces')
}
},

View File

@ -179,9 +179,18 @@ export default {
console.debug('Could not add label to task in kanban, task not found', t)
return r
}
// FIXME: direct store manipulation (task)
t.task.labels.push(label)
ctx.commit('kanban/setTaskInBucketByIndex', t, { root: true })
const labels = [...t.task.labels]
labels.push(label)
ctx.commit('kanban/setTaskInBucketByIndex', {
task: {
labels,
...t.task,
},
...t,
}, { root: true })
return r
},
@ -200,15 +209,21 @@ export default {
}
// Remove the label from the list
for (const l in t.task.labels) {
if (t.task.labels[l].id === label.id) {
// FIXME: direct store manipulation (task)
t.task.labels.splice(l, 1)
const labels = [...t.task.labels]
for (const l in labels) {
if (labels[l].id === label.id) {
labels.splice(l, 1)
break
}
}
ctx.commit('kanban/setTaskInBucketByIndex', t, {root: true})
ctx.commit('kanban/setTaskInBucketByIndex', {
task: {
labels,
...t.task,
},
...t,
}, {root: true})
return response
},

View File

@ -1,6 +1,5 @@
export const LOADING = 'loading'
export const LOADING_MODULE = 'loadingModule'
export const ONLINE = 'online'
export const CURRENT_LIST = 'currentList'
export const HAS_TASKS = 'hasTasks'
export const MENU_ACTIVE = 'menuActive'

View File

@ -2,5 +2,4 @@
@import "labels";
@import "list";
@import "task";
@import "tasks";
@import "namespaces";
@import "tasks";

View File

@ -1,4 +0,0 @@
// FIXME: used in navigation.vue and in ListNamespaces.vue
.namespaces-list.loader-container.is-loading {
min-height: calc(100vh - #{$navbar-height + 1.5rem + 1rem + 1.5rem});
}

View File

@ -60,9 +60,9 @@
--danger: hsla(var(--danger-h), var(--danger-s), var(--danger-l), var(--danger-a));
// var(--primary) / $blue is #1973ff
--primary-h: 216.5deg;
--primary-s: 100%;
--primary-l: 54.9%;
--primary-h: 217deg;
--primary-s: 98%;
--primary-l: 53%;
--primary-a: 1;
--primary-hsl: var(--primary-h), var(--primary-s), var(--primary-l);
--primary: hsla(var(--primary-h), var(--primary-s), var(--primary-l), var(--primary-a));
@ -122,5 +122,10 @@
// Custom color variables we need to override
--card-border-color: hsla(var(--grey-100-hsl), 0.3);
--logo-text-color: var(--grey-700);
// Slightly different primary color to make sure it has a sufficent contrast ratio
--primary-h: 217deg;
--primary-s: 98%;
--primary-l: 58%;
}
}

View File

@ -24,3 +24,7 @@
max-width: $widescreen;
}
.content blockquote {
background-color: var(--grey-200);
border-left: .25rem solid var(--grey-300);
}

4
src/types/faker.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
declare module '@faker-js/faker' {
import faker from 'faker'
export default faker
}

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