diff --git a/.drone.yml b/.drone.yml index e6982e971..692cf23fa 100644 --- a/.drone.yml +++ b/.drone.yml @@ -96,7 +96,7 @@ steps: - dependencies - name: test-frontend - image: cypress/browsers:node18.12.0-chrome106-ff106 + image: cypress/browsers:node18.12.0-chrome107 pull: always environment: CYPRESS_API_URL: http://api:3456/api/v1 @@ -110,8 +110,7 @@ steps: - sed -i 's/localhost/api/g' dist/index.html - corepack enable && pnpm config set store-dir .cache/pnpm - pnpm cypress install - - pnpm run serve:dist & npx wait-on http://localhost:4173 - - pnpm run test:frontend --browser chrome --record + - pnpm run test:e2e-record depends_on: - build-prod @@ -150,8 +149,10 @@ steps: # Override the default api url used for preview - sed -i 's|http://localhost:3456|https://try.vikunja.io|g' dist-preview/index.html - apk add --no-cache perl-utils - - shasum -a 384 -c ./scripts/deploy-preview-netlify.js.sha384 - - node ./scripts/deploy-preview-netlify.js + # create via: + # `shasum -a 384 ./scripts/deploy-preview-netlify.mjs > ./scripts/deploy-preview-netlify.mjs.sha384` + - shasum -a 384 -c ./scripts/deploy-preview-netlify.mjs.sha384 + - node ./scripts/deploy-preview-netlify.mjs depends_on: - build-prod when: @@ -204,7 +205,7 @@ steps: PNPM_CACHE_FOLDER: .cache/pnpm commands: - apk add git - - corepack enable && pnpm config set store-dir .cache/.pnpm + - corepack enable && pnpm config set store-dir .cache/pnpm - pnpm install --fetch-timeout 100000 --frozen-lockfile - pnpm run lint - "echo '{\"VERSION\": \"'$(git describe --tags --always --abbrev=10 | sed 's/-/+/' | sed 's/^v//' | sed 's/-g/-/')'\"}' > src/version.json" @@ -365,7 +366,7 @@ steps: - name: docker-unstable image: thegeeklab/drone-docker-buildx privileged: true - pull: true + pull: always settings: username: from_secret: docker_username @@ -387,17 +388,27 @@ steps: ref: - refs/heads/main + - name: generate-tags + image: thegeeklab/docker-autotag + environment: + DOCKER_AUTOTAG_VERSION: ${DRONE_TAG} + DOCKER_AUTOTAG_EXTRA_TAGS: latest + DOCKER_AUTOTAG_OUTPUT_FILE: .tags + depends_on: [ fetch-tags ] + when: + ref: + - "refs/tags/**" + - name: docker-release image: thegeeklab/drone-docker-buildx privileged: true - pull: true + pull: always settings: username: from_secret: docker_username password: from_secret: docker_password repo: vikunja/frontend - auto_tag: true build_args: - USE_RELEASE=true - RELEASE_VERSION=${DRONE_TAG##v} @@ -407,7 +418,7 @@ steps: - linux/arm/v6 - linux/arm/v7 - linux/arm64/v8 - depends_on: [ fetch-tags ] + depends_on: [ generate-tags ] when: ref: - "refs/tags/**" @@ -451,9 +462,6 @@ kind: pipeline type: docker name: update-translations -depends_on: - - build - trigger: branch: - main @@ -513,6 +521,6 @@ steps: from_secret: crowdin_key --- kind: signature -hmac: 9f26b5af73e3464e9ee1b5fbcb96854ca8a7e5f8d6ee2d85fd8376aad951b446 +hmac: 971875b90c7bb1649d1b00d022d0b594ba9b68f927bf8f0dbe840190816d676b ... diff --git a/.env.local.example b/.env.local.example new file mode 100644 index 000000000..1abd202a5 --- /dev/null +++ b/.env.local.example @@ -0,0 +1,8 @@ +# Duplicate this file and remove the '.example' suffix. +# Adjust the values as needed. + +VITE_IS_ONLINE=true +VITE_WORKBOX_DEBUG=false +SENTRY_AUTH_TOKEN=YOUR_TOKEN +SENTRY_ORG=vikunja +SENTRY_PROJECT=frontend-oss \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index ff6a0a9e5..3e44205c2 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,6 +1,7 @@ name: Bug Report description: Found something you weren't expecting? Report it here! -labels: kind/bug +labels: + - kind/bug body: - type: markdown attributes: diff --git a/.gitignore b/.gitignore index 7936c4538..ace110b86 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,31 @@ -.DS_Store -node_modules -/dist* -*.zip -.direnv/ - -# local env files -.env.local -.env.*.local - -# Log files +# Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* -stats.html pnpm-debug.log* lerna-debug.log* +stats.html + +node_modules +.DS_Store +/dist* +coverage +*.zip +.direnv/ + +# Test files +cypress/screenshots +cypress/videos + +# local env files +.env.local +.env.*.local # Editor directories and files -.idea .vscode +.idea *.suo *.ntvs* *.njsproj @@ -28,9 +33,9 @@ lerna-debug.log* *.sw* !rollup.sw.js -# Test files -cypress/screenshots -cypress/videos # Local Netlify folder .netlify + +# histoire +.histoire \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f4cf21d2..77b41a779 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,378 @@ All releases can be found on https://code.vikunja.io/frontend/releases. The releases aim at the api versions which is why there are missing versions. +## [0.20.3] - 2023-01-24 + +### Bug Fixes + +* *(BaseButton)* Prop type +* *(ci)* Make sure the i18n sync cron job actually runs +* *(ci)* Sign drone config +* *(ci)* Sign drone config +* *(ci)* Tagging logic for release docker images +* *(ci)* Sign drone config +* *(cypress)* Use ts for updateUserSettings +* *(cypress)* Use env for API_URL (#2925) +* *(drone)* Use correct property value (#2920) +* *(drone)* Pnpm cache folder path (#2932) +* *(faker)* Remove mock types (#2921) +* *(i18n)* Incorrect translation string +* *(migration)* Actually pass migration oauth code from query param +* *(quick add magic)* Make sure assignees which don't exist are not removed from task title +* *(task)* Update task description when switching between related tasks +* *(task)* Don't show the list color on the task when only viewing the list (#2975) +* *(useOnline)* Only log if actually faking state (#2924) +* Close button hover for sidebar (#2981) ([9922fcb](9922fcba65c8dc2c46c4f085813c2fbc0d0a7df6)) + + +### Dependencies + +* *(deps)* Update dependency vite to v4.0.2 (#2861) +* *(deps)* Update dependency netlify-cli to v12.4.0 (#2862) +* *(deps)* Update typescript-eslint monorepo to v5.47.0 (#2864) +* *(deps)* Update dependency esbuild to v0.16.10 (#2865) +* *(deps)* Update dependency sass to v1.57.1 (#2866) +* *(deps)* Update dependency vue-tsc to v1.0.16 (#2867) +* *(deps)* Update dependency codemirror to v5.65.11 +* *(deps)* Update dependency @vueuse/core to v9.8.0 +* *(deps)* Update dependency vitest to v0.26.1 +* *(deps)* Update dependency @vueuse/core to v9.8.1 (#2870) +* *(deps)* Update dependency @vueuse/core to v9.8.2 +* *(deps)* Update sentry-javascript monorepo to v7.28.0 +* *(deps)* Update dependency cypress to v12.2.0 (#2873) +* *(deps)* Update dependency vitest to v0.26.2 (#2874) +* *(deps)* Update dependency vite to v4.0.3 (#2876) +* *(deps)* Update pnpm to v7.19.0 (#2875) +* *(deps)* Update dependency rollup to v3.8.0 (#2877) +* *(deps)* Update sentry-javascript monorepo to v7.28.1 (#2878) +* *(deps)* Update dependency @vueuse/core to v9.9.0 (#2881) +* *(deps)* Update dependency rollup to v3.8.1 (#2879) +* *(deps)* Update dependency vite-svg-loader to v4 (#2882) +* *(deps)* Update dependency vue-tsc to v1.0.17 (#2883) +* *(deps)* Update dependency caniuse-lite to v1.0.30001441 (#2884) +* *(deps)* Update dependency netlify-cli to v12.5.0 (#2886) +* *(deps)* Update pnpm to v7.20.0 (#2887) +* *(deps)* Update dependency vue-tsc to v1.0.18 (#2888) +* *(deps)* Update dependency happy-dom to v8.1.1 (#2885) +* *(deps)* Update dependency @types/node to v18.11.18 (#2889) +* *(deps)* Update typescript-eslint monorepo to v5.47.1 (#2890) +* *(deps)* Update dependency esbuild to v0.16.11 +* *(deps)* Update dependency esbuild to v0.16.12 (#2893) +* *(deps)* Update dependency rollup to v3.9.0 (#2894) +* *(deps)* Update dependency rollup-plugin-visualizer to v5.9.0 (#2896) +* *(deps)* Update dependency marked to v4.2.5 (#2880) +* *(deps)* Update pnpm to v7.21.0 (#2895) +* *(deps)* Update dependency eslint to v8.31.0 +* *(deps)* Update dependency vue-tsc to v1.0.19 +* *(deps)* Update dependency @types/codemirror to v5.60.6 +* *(deps)* Update dependency rollup to v3.9.1 +* *(deps)* Update dependency vitest to v0.26.3 +* *(deps)* Update dependency vite-plugin-pwa to v0.14.1 (#2909) +* *(deps)* Update dependency esbuild to v0.16.13 (#2907) +* *(deps)* Update typescript-eslint monorepo to v5.48.0 (#2906) +* *(deps)* Update dependency vue-tsc to v1.0.20 +* *(deps)* Update dependency cypress to v12.3.0 +* *(deps)* Update dependency @vueuse/core to v9.10.0 (#2911) +* *(deps)* Update pnpm to v7.22.0 (#2910) +* *(deps)* Update dependency @vue/test-utils to v2.2.7 (#2914) +* *(deps)* Update dependency vite to v4.0.4 (#2908) +* *(deps)* Update sentry-javascript monorepo to v7.29.0 (#2915) +* *(deps)* Update dependency esbuild to v0.16.14 +* *(deps)* Update dependency axios to v1 +* *(deps)* Update dependency vue-tsc to v1.0.21 +* *(deps)* Update dependency vue-tsc to v1.0.22 +* *(deps)* Update dependency dompurify to v2.4.2 +* *(deps)* Update dependency dompurify to v2.4.3 (#2931) +* *(deps)* Update dependency postcss to v8.4.21 (#2933) +* *(deps)* Update dependency esbuild to v0.16.15 (#2934) +* *(deps)* Update dependency vue-tsc to v1.0.24 +* *(deps)* Update pnpm to v7.23.0 (#2940) +* *(deps)* Update dependency happy-dom to v8.1.3 (#2939) +* *(deps)* Update dependency esbuild to v0.16.16 (#2937) +* *(deps)* Update dependency caniuse-lite to v1.0.30001442 (#2938) +* *(deps)* Update dependency vitest to v0.27.0 (#2941) +* *(deps)* Update typescript-eslint monorepo to v5.48.1 (#2942) +* *(deps)* Update pnpm to v7.24.2 (#2944) +* *(deps)* Update sentry-javascript monorepo to v7.30.0 (#2945) +* *(deps)* Update pnpm to v7.24.3 (#2946) +* *(deps)* Update dependency vitest to v0.27.1 (#2947) +* *(deps)* Update dependency esbuild to v0.16.17 (#2948) +* *(deps)* Update dependency rollup to v3.10.0 (#2949) +* *(deps)* Update dependency eslint-plugin-vue to v9.9.0 (#2950) +* *(deps)* Update pnpm to v7.25.0 (#2951) +* *(deps)* Update dependency marked to v4.2.12 (#2952) +* *(deps)* Update dependency esbuild to v0.17.0 (#2953) +* *(deps)* Update dependency eslint to v8.32.0 (#2954) +* *(deps)* Update dependency vue-advanced-cropper to v2.8.8 (#2955) +* *(deps)* Update dependency pinia to v2.0.29 (#2956) +* *(deps)* Update dependency @kyvg/vue3-notification to v2.8.0 (#2957) +* *(deps)* Update dependency caniuse-lite to v1.0.30001445 (#2958) +* *(deps)* Update dependency happy-dom to v8.1.4 (#2959) +* *(deps)* Update dependency netlify-cli to v12.7.2 (#2960) +* *(deps)* Update sentry-javascript monorepo to v7.31.0 +* *(deps)* Update dependency esbuild to v0.17.1 (#2963) +* *(deps)* Update typescript-eslint monorepo to v5.48.2 (#2962) +* *(deps)* Update dependency esbuild to v0.17.2 (#2965) +* *(deps)* Update dependency vitest to v0.27.2 (#2966) +* *(deps)* Update dependency @vueuse/core to v9.11.0 (#2967) +* *(deps)* Update sentry-javascript monorepo to v7.31.1 (#2973) +* *(deps)* Update dependency axios to v1.2.3 (#2974) +* *(deps)* Update dependency esbuild to v0.17.3 (#2976) +* *(deps)* Update pnpm to v7.25.1 (#2977) +* *(deps)* Update dependency @vueuse/core to v9.11.1 +* *(deps)* Update dependency rollup to v3.10.1 +* *(deps)* Update dependency vite-plugin-inject-preload to v1.2.0 (#2983) +* *(deps)* Update dependency vitest to v0.27.3 (#2984) +* *(deps)* Update dependency esbuild to v0.17.4 (#2985) +* *(deps)* Update dependency caniuse-lite to v1.0.30001447 (#2986) +* *(deps)* Update dependency happy-dom to v8.1.5 (#2987) +* *(deps)* Update dependency netlify-cli to v12.9.1 (#2988) +* *(deps)* Update sentry-javascript monorepo to v7.32.1 (#2991) +* *(deps)* Update dependency vitest to v0.28.1 (#2990) +* *(deps)* Update dependency @types/codemirror to v5.60.7 (#2993) +* *(deps)* Update typescript-eslint monorepo to v5.49.0 (#2994) +* *(deps)* Update dependency start-server-and-test to v1.15.3 +* *(deps)* Update dependency @fortawesome/vue-fontawesome to v3.0.3 (#3003) + +### Features + +* *(cypress)* Remove getSettled +* *(cypress)* Use cy.session +* *(i18n)* Add Norwegian translation +* *(netlify)* Abstract createSlug helper function (#2923) +* *(postcss)* Mock plugin types (#2930) +* Enable ts for rollup-plugin-visualizer (#2897) ([09d1352](09d13520b060e47be18640865befde44f59332e3)) +* Remove date-fns formatISO (#2899) ([1f25386](1f25386f54f376357722e1e589d3a8bd8288a033)) +* Add-task usability improvements (#2767) ([4be53b0](4be53b098ca909194aefb464a93b6dae99f4b9ab)) +* Remove formatISO from list-view-gantt.spec (#2922) ([a29131e](a29131e7d4be2c83c3e9046549924d1f7692c95e)) +* Add histoire ([7be8e89](7be8e892e2480f17cb5de6a69d35287906151c0f)) +* Add XButton story ([ccc85b9](ccc85b9a828488dc849758f1e89f3ba3f75967d1)) +* Add card story ([35cfb2f](35cfb2f3ca42ac83a9b943fc59818c978ee95fcc)) +* Add histoire (#2724) ([a4424e0](a4424e089cdfadb4ab3b753e6fdca818bbe82dc4)) +* Add describe project better in package.json (#2971) ([14466bf](14466bf9b7b8a3fc455c0d601205abbaf8cba4f5)) +* Add .env.local.example (#2972) ([e1b35ff](e1b35ff023679a7cb8448a06e9edeb8eccc2f727)) +* Fix broken font preloading (#2980) ([4890149](489014944a1544846875910d7d5e17e3d71b7e2d)) + +### Miscellaneous Tasks + +* *(config)* Remove unused URL_PREFIX const (#2926) +* *(package)* Use pnpm commands (#2919) +* *(tests)* Fix macos cypress and align with create vite (#2898) +* Improve migrate title (#2968) ([56fd25e](56fd25e888cae8343f64a4c14ac5a3a760bdc7be)) +* Add has content="false" to gantt charts (#2969) ([903e9a9](903e9a9904c18ced59962fc03b4c36e5ac8cd688)) +* Use es6 imports for deploy-preview-netlify (#2970) ([2a2c27a](2a2c27af9226f441ec80d9d4f560b55cd357126c)) + +### Other + +* *(other)* [skip ci] Updated translations via Crowdin +* *(other)* Redirect to oidc provider if configured correctly (#2805) + + +## [0.20.2] - 2022-12-18 + +### Bug Fixes + +* *(bug-report.yml)* List (#2845) +* *(quick add magic)* Don't create a new label multiple times if it is used in multiple tasks +* *(task)* Pass a list specified via quick add magic down to all subtasks created via indention +* *(task)* Move task color bubble next to task index and done badge on mobile +* *(tasks)* Remove a task from its bucket when it is in the first kanban bucket +* *(tasks)* Missing space when showing parent tasks and list title +* *(tasks)* Translation for multiple related tasks now works +* Move createdUpdated styles to component (#2685) ([4c458a1](4c458a1ad0761920868e3863982d5175664b3e6e)) +* Move heading styles to component (#2686) ([293402b](293402b6fdfc699661c7f287ff1759a9ce5bea17)) +* Use scss for datemathHelp (#2690) ([06775cf](06775cf4c72cf81a125b91d49c8d81e8649af661)) +* Reactive const assignment (#2692) ([4c4adfd](4c4adfdf4e79eff3e101d9f0bd68bc3e5bb76495)) +* Remove vuex leftover from setModuleLoading (#2716) ([3aaacf4](3aaacf4533c761864d3081edb92c9380df43f8b1)) +* Icon offset and color ([74ad98d](74ad98de680f8b56e42886cd1e33874bd05772fa)) +* Only load buckets if listId set (#2741) ([7db79ff](7db79ff04e4ce87d62cae7f93b67570bbc5c13be)) +* Add all json files in src (#2737) ([422e731](422e731fe0d44c2e3be603b549538a05a695b95c)) +* Vite.config imports (#2843) ([318e8c8](318e8c83a68bcb2f7953553c036f677a97b01c21)) + +### Dependencies + +* *(deps)* Update dependency rollup to v3.3.0 (#2689) +* *(deps)* Update dependency @types/dompurify to v2.4.0 (#2688) +* *(deps)* Update dependency @vue/test-utils to v2.2.2 (#2696) +* *(deps)* Update dependency caniuse-lite to v1.0.30001431 +* *(deps)* Update dependency happy-dom to v7.7.0 +* *(deps)* Update dependency netlify-cli to v12.1.1 (#2699) +* *(deps)* Update dependency postcss-preset-env to v7.8.3 (#2701) +* *(deps)* Update dependency vitest to v0.25.2 (#2702) +* *(deps)* Update pnpm to v7.16.0 (#2703) +* *(deps)* Update typescript-eslint monorepo to v5.43.0 +* *(deps)* Update dependency ufo to v1 +* *(deps)* Update dependency esbuild to v0.15.14 (#2706) +* *(deps)* Update dependency @vue/test-utils to v2.2.3 (#2707) +* *(deps)* Update dependency vite to v3.2.4 +* *(deps)* Update dependency typescript to v4.9.3 +* *(deps)* Update dependency cypress to v11.1.0 +* *(deps)* Update font awesome to v6.2.1 (#2712) +* *(deps)* Update pnpm to v7.16.1 (#2717) +* *(deps)* Update dependency pinia to v2.0.24 +* *(deps)* Update sentry-javascript monorepo to v7.20.0 (#2720) +* *(deps)* Update dependency eslint to v8.28.0 +* *(deps)* Update dependency esbuild to v0.15.15 +* *(deps)* Update dependency netlify-cli to v12.2.4 +* *(deps)* Update dependency @vue/test-utils to v2.2.4 +* *(deps)* Update pnpm to v7.17.0 +* *(deps)* Update dependency marked to v4.2.3 +* *(deps)* Update dependency codemirror to v5.65.10 +* *(deps)* Update sentry-javascript monorepo to v7.20.1 +* *(deps)* Update dependency pinia to v2.0.25 +* *(deps)* Update dependency rollup to v3.4.0 +* *(deps)* Update typescript-eslint monorepo to v5.44.0 +* *(deps)* Update vueuse to v9.6.0 (#2742) +* *(deps)* Update dependency vitest to v0.25.3 (#2743) +* *(deps)* Update dependency cypress to v11.2.0 +* *(deps)* Update sentry-javascript monorepo to v7.21.0 +* *(deps)* Update dependency @4tw/cypress-drag-drop to v2.2.2 +* *(deps)* Update sentry-javascript monorepo to v7.21.1 (#2747) +* *(deps)* Update dependency pinia to v2.0.26 +* *(deps)* Update dependency @cypress/vue to v5.0.2 +* *(deps)* Update dependency highlight.js to v11.7.0 (#2752) +* *(deps)* Update dependency eslint-plugin-vue to v9.8.0 (#2753) +* *(deps)* Update dependency @infectoone/vue-ganttastic to v2.1.3 +* *(deps)* Update dependency rollup to v3.5.0 (#2756) +* *(deps)* Update pnpm to v7.17.1 (#2755) +* *(deps)* Update dependency esbuild to v0.15.16 +* *(deps)* Update dependency pinia to v2.0.27 (#2757) +* *(deps)* Update dependency caniuse-lite to v1.0.30001434 (#2759) +* *(deps)* Update dependency netlify-cli to v12.2.7 (#2760) +* *(deps)* Update dependency @kyvg/vue3-notification to v2.7.0 (#2761) +* *(deps)* Update typescript-eslint monorepo to v5.45.0 (#2762) +* *(deps)* Update dependency ufo to v1.0.1 (#2763) +* *(deps)* Update dependency vue-tsc to v1.0.10 (#2764) +* *(deps)* Update sentry-javascript monorepo to v7.22.0 (#2765) +* *(deps)* Update dependency @types/node to v18.11.10 (#2768) +* *(deps)* Update dependency rollup to v3.5.1 (#2769) +* *(deps)* Update sentry-javascript monorepo to v7.23.0 +* *(deps)* Update dependency @vue/test-utils to v2.2.5 (#2773) +* *(deps)* Update dependency eslint to v8.29.0 (#2774) +* *(deps)* Update dependency @cypress/vue to v5.0.3 (#2775) +* *(deps)* Update dependency vue-tsc to v1.0.11 (#2777) +* *(deps)* Update dependency @cypress/vite-dev-server to v5 (#2776) +* *(deps)* Update pnpm to v7.18.0 (#2778) +* *(deps)* Update dependency esbuild to v0.15.17 (#2779) +* *(deps)* Update dependency caniuse-lite to v1.0.30001436 (#2780) +* *(deps)* Update dependency @vue/test-utils to v2.2.6 (#2784) +* *(deps)* Update dependency esbuild to v0.15.18 (#2783) +* *(deps)* Update dependency netlify-cli to v12.2.8 (#2782) +* *(deps)* Update dependency happy-dom to v7.7.2 (#2781) +* *(deps)* Update dependency vite to v3.2.5 (#2785) +* *(deps)* Update dependency rollup to v3.6.0 (#2786) +* *(deps)* Update typescript-eslint monorepo to v5.45.1 (#2787) +* *(deps)* Update dependency vitest to v0.25.4 (#2788) +* *(deps)* Update dependency @types/node to v18.11.11 (#2789) +* *(deps)* Update pnpm to v7.18.1 (#2790) +* *(deps)* Update dependency dayjs to v1.11.7 (#2791) +* *(deps)* Update dependency cypress to v12 (#2792) +* *(deps)* Update dependency vitest to v0.25.5 (#2793) +* *(deps)* Update dependency marked to v4.2.4 (#2796) +* *(deps)* Update dependency esbuild to v0.16.1 (#2795) +* *(deps)* Update dependency cypress to v12.0.1 (#2794) +* *(deps)* Update sentry-javascript monorepo to v7.24.0 (#2797) +* *(deps)* Update sentry-javascript monorepo to v7.24.1 (#2798) +* *(deps)* Update sentry-javascript monorepo to v7.24.2 (#2799) +* *(deps)* Update dependency typescript to v4.9.4 (#2800) +* *(deps)* Update dependency rollup to v3.7.0 (#2801) +* *(deps)* Update dependency esbuild to v0.16.2 (#2802) +* *(deps)* Update typescript-eslint monorepo to v5.46.0 (#2803) +* *(deps)* Update dependency vitest to v0.25.6 (#2804) +* *(deps)* Update dependency @cypress/vite-dev-server to v5.0.1 (#2806) +* *(deps)* Update dependency esbuild to v0.16.3 (#2809) +* *(deps)* Update dependency sass to v1.56.2 (#2810) +* *(deps)* Update dependency @types/marked to v4.0.8 (#2812) +* *(deps)* Update dependency vue-tsc to v1.0.12 (#2811) +* *(deps)* Update dependency @types/node to v18.11.12 (#2808) +* *(deps)* Update dependency cypress to v12.0.2 (#2807) +* *(deps)* Update dependency @vitejs/plugin-vue to v4 (#2814) +* *(deps)* Update dependency @vitejs/plugin-legacy to v3 (#2813) +* *(deps)* Update dependency pinia to v2.0.28 (#2815) +* *(deps)* Update dependency @vitejs/plugin-legacy to v3.0.1 (#2818) +* *(deps)* Update dependency @cypress/vite-dev-server to v5.0.2 (#2819) +* *(deps)* Update dependency rollup to v3.7.1 (#2820) +* *(deps)* Update dependency rollup to v3.7.2 (#2822) +* *(deps)* Update dependency esbuild to v0.16.4 (#2821) +* *(deps)* Update dependency vitest to v0.25.7 (#2824) +* *(deps)* Update dependency @types/node to v18.11.13 (#2823) +* *(deps)* Update dependency happy-dom to v8 (#2831) +* *(deps)* Update dependency postcss to v8.4.20 (#2827) +* *(deps)* Update dependency caniuse-lite to v1.0.30001439 (#2828) +* *(deps)* Update dependency @intlify/unplugin-vue-i18n to v0.8.1 (#2826) +* *(deps)* Update dependency netlify-cli to v12.2.10 (#2829) +* *(deps)* Update dependency vite-plugin-pwa to v0.14.0 (#2833) +* *(deps)* Update dependency rollup to v3.7.3 (#2825) +* *(deps)* Update dependency vue-tsc to v1.0.13 (#2832) +* *(deps)* Update sentry-javascript monorepo to v7.25.0 +* *(deps)* Update dependency vite to v4 (#2816) +* *(deps)* Update pnpm to v7.18.2 (#2834) +* *(deps)* Update typescript-eslint monorepo to v5.46.1 (#2837) +* *(deps)* Update dependency @4tw/cypress-drag-drop to v2.2.3 (#2836) +* *(deps)* Update dependency @types/node to v18.11.14 (#2839) +* *(deps)* Update dependency cypress to v12.1.0 (#2838) +* *(deps)* Update dependency rollup to v3.7.4 (#2840) +* *(deps)* Update dependency vitest to v0.25.8 +* *(deps)* Update sentry-javascript monorepo to v7.26.0 +* *(deps)* Update dependency esbuild to v0.16.5 (#2846) +* *(deps)* Update dependency @types/node to v18.11.15 +* *(deps)* Update dependency esbuild to v0.16.6 (#2848) +* *(deps)* Update dependency esbuild to v0.16.7 +* *(deps)* Update sentry-javascript monorepo to v7.27.0 (#2850) +* *(deps)* Update dependency @vueuse/core to v9.7.0 (#2851) +* *(deps)* Update dependency wait-on to v7 (#2852) +* *(deps)* Update dependency @types/node to v18.11.16 (#2853) +* *(deps)* Update dependency eslint to v8.30.0 +* *(deps)* Update dependency rollup to v3.7.5 (#2857) +* *(deps)* Update dependency esbuild to v0.16.8 (#2854) +* *(deps)* Update dependency sass to v1.57.0 (#2856) +* *(deps)* Update dependency vue-tsc to v1.0.14 (#2860) +* *(deps)* Update dependency esbuild to v0.16.9 (#2859) +* *(deps)* Update dependency @types/node to v18.11.17 (#2858) + +### Features + +* *(ci)* Use docker buildx for multiarch builds* Filters script setup ([4bad685](4bad685f39388d59fdd8ff79a1766c55f75262c2)) +* Move select filters to dedicated components ([bb58dba](bb58dba8e07d683c75637ec88a378e873711eb29)) +* Add vite build target esnext (#2674) ([163d936](163d9366d3061c40b5db7f3aad5c2cea01948403)) +* Filters script setup (#2671) ([4a550da](4a550da6a69a50126b9d4a555b6713687347c2d3)) +* Reduce multiselect selector specificity (#2678) ([9f0f0b3](9f0f0b39f8eea399b7b03003afa5893d0b8016f8)) +* Reduce contentAuth selector specifity (#2677) ([12a8f7e](12a8f7ebe9fc556a7b0bc6e2d74e81d424ccfcf8)) +* Reduce ListWrapper selector specificity (#2679) ([599c1ba](599c1ba4b5b0861d89755addf016e8f797b49dfe)) +* Reduce dropdown-item selector specificity (#2680) ([eb4c2a4](eb4c2a4b9df93ee35404cd7143cc88b3d44f9d59)) +* Reduce attachments selector specificity (#2682) ([0f1f131](0f1f131f7a2a38ee57175edfd5ed1c932225af16)) +* Reduce ready selector specificity (#2683) ([9d604f7](9d604f7a3bc057bbe27ac19e73ac59736154d9b7)) +* Use img for logo so that it's not part of the main bundle (#2684) ([02de481](02de481297502ad4b0b2eb2fa3e06366cce6d630)) +* Improve user component (#2687) ([708ef2d](708ef2d72efbdfe6261322937b0a8f76ee19b9e4)) +* Reduce TaskDetailView selector specificity ([fba402f](fba402fcd056ee397ce54f97ed4fec98845c7933)) +* Move transition in own component ([631a19f](631a19fa923dba2759603e6a8b224cb4d3e1a038)) +* Feature/load-views-async (#2672) +* Use transition component everywhere ([8c44ed8](8c44ed83e6530f67cc923a5e6d1a26c14575884a)) +* Move transition in component (#2694) ([77ff0aa](77ff0aa256fbf388210af09d88673475386b3553)) +* Disable fullscreen for EasyMDE side-by-side mode (#2710) ([98b38af](98b38af43c3acc9822f167ebca295f5aecb4908d)) +* Only automatically redirect to provider if the url contains ?redirectToProvider=true and it's the only one ([3891d5b](3891d5b87634c890265477680fafaa04ff06cc3e)) +* Improve loadTask logic (#2715) ([8ef3092](8ef309243db4e37d306167455987572006858cad)) +* Remove edit-task from list view (#2721) ([45ec162](45ec1623d525ed31a49b6be6d609802c341fad27)) +* Move useAutoHeightTextarea to composable (#2723) ([33d4efe](33d4efecc45ef8da5360fb878b7d365d1901b56c)) +* More horizontal space on mobile (#2722) ([b42e4cc](b42e4cca59e338278261bc3ec613eefedde6fcce)) +* Change list-content style (#91) ([4b47478](4b47478440d0af1bf24c44ea614c0f62f20723f7)) +* Grid for list cards ([42e9f30](42e9f306e84120ba51d9b527c7868148730bf892)) +* Move avatar class to where it is used (#2725) ([da8df8b](da8df8b667fc57798c1de7d78c1a7f88b0419d38)) +* Undent and order navigation css ([66be0e6](66be0e6ac4bcf48124b33267224187b56ac9320a)) +* Outdent navigation logo styles ([ff9efe7](ff9efe7889256706ac86bb1face842cd2de6f935)) +* Group navigation styles further ([4fc7b9c](4fc7b9c67e2088e82760005cd530ea97cf796a4c)) +* Move link color location together ([d9984b2](d9984b28f7d01da0f9d8f0afd5b6f0edf35823c2)) +* Use fetch instead of axios for deploy preview (#2719) ([93d95b0](93d95b0821f39719c4a28c144ebb583c2eac754e)) +* Remove useRouteQuery (#2751) ([3ee0bc3](3ee0bc345d6cd65769789ec029c50e652d80e1ca)) +* Use Intl.DateTimeFormat for gantt weekdays (#2766) ([3b95824](3b95824f5834d7de50210414c56b07889db895c7)) +* Add @intlify/unplugin-vue-i18n (#2772) ([b44d11c](b44d11cfc04712b9f9ec9479ba3a77a26c453532)) +* Use vite preview for serve:dist:dev (#2842) ([f6c6f52](f6c6f52abe71674fa5f3951cc0ba61798758bd03)) +* Use variable fonts with subsetting (#2817) ([b6a89a0](b6a89a0cde3c769e38146b05c33ff4ca4e97bca2)) + +### Other + +* *(other)* [skip ci] Updated translations via Crowdin + ## [0.20.1] - 2022-11-11 ### Bug Fixes diff --git a/README.md b/README.md index 417a8a4cb..a62b837db 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Build Status](https://drone.kolaente.de/api/badges/vikunja/frontend/status.svg)](https://drone.kolaente.de/vikunja/frontend) [![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](LICENSE) -[![Download](https://img.shields.io/badge/download-v0.20.1-brightgreen.svg)](https://dl.vikunja.io) +[![Download](https://img.shields.io/badge/download-v0.20.3-brightgreen.svg)](https://dl.vikunja.io) [![Translation](https://badges.crowdin.net/vikunja/localized.svg)](https://crowdin.com/project/vikunja) This is the web frontend for Vikunja, written in Vue.js. diff --git a/cypress.config.ts b/cypress.config.ts index ce74e11f3..16f7ab8ef 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -11,8 +11,10 @@ export default defineConfig({ }, projectId: '181c7x', e2e: { - baseUrl: 'http://localhost:4173', - specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}', + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://127.0.0.1:4173', + experimentalRunAllSpecs: true, + // testIsolation: false, }, component: { devServer: { diff --git a/cypress/README.md b/cypress/README.md index 3421b98b2..ae17732e4 100644 --- a/cypress/README.md +++ b/cypress/README.md @@ -36,7 +36,7 @@ to get a shell inside the cypress container. In that shell you can then execute the tests with ```shell -pnpm run test:frontend +pnpm run test:e2e ``` ### Using The Cypress Dashboard @@ -44,5 +44,5 @@ pnpm run test:frontend To open the Cypress Dashboard and run tests from there, run ```shell -pnpm run cypress:open +pnpm run test:e2e:dev ``` diff --git a/cypress/docker-compose.yml b/cypress/docker-compose.yml index d30e22e16..7a06106fd 100644 --- a/cypress/docker-compose.yml +++ b/cypress/docker-compose.yml @@ -9,7 +9,7 @@ services: ports: - 3456:3456 cypress: - image: cypress/browsers:node16.14.0-chrome99-ff97 + image: cypress/browsers:node18.12.0-chrome107 volumes: - ..:/project - $HOME/.cache:/home/node/.cache/ diff --git a/cypress/e2e/list/list-history.spec.ts b/cypress/e2e/list/list-history.spec.ts index 4f614ea01..69592a84b 100644 --- a/cypress/e2e/list/list-history.spec.ts +++ b/cypress/e2e/list/list-history.spec.ts @@ -1,9 +1,10 @@ -import {ListFactory} from '../../factories/list' +import {createFakeUserAndLogin} from '../../support/authenticateUser' -import '../../support/authenticateUser' +import {ListFactory} from '../../factories/list' import {prepareLists} from './prepareLists' describe('List History', () => { + createFakeUserAndLogin() prepareLists() it('should show a list history on the home page', () => { diff --git a/cypress/e2e/list/list-view-gantt.spec.ts b/cypress/e2e/list/list-view-gantt.spec.ts index f5ce93fb1..177f791ad 100644 --- a/cypress/e2e/list/list-view-gantt.spec.ts +++ b/cypress/e2e/list/list-view-gantt.spec.ts @@ -1,10 +1,12 @@ import {formatISO, format} from 'date-fns' + +import {createFakeUserAndLogin} from '../../support/authenticateUser' + import {TaskFactory} from '../../factories/task' import {prepareLists} from './prepareLists' -import '../../support/authenticateUser' - describe('List View Gantt', () => { + createFakeUserAndLogin() prepareLists() it('Hides tasks with no dates', () => { @@ -33,8 +35,8 @@ describe('List View Gantt', () => { it('Shows tasks with dates', () => { const now = new Date() const tasks = TaskFactory.create(1, { - start_date: formatISO(now), - end_date: formatISO(now.setDate(now.getDate() + 4)), + start_date: now.toISOString(), + end_date: new Date(new Date(now).setDate(now.getDate() + 4)).toISOString(), }) cy.visit('/lists/1/gantt') @@ -60,13 +62,12 @@ describe('List View Gantt', () => { }) it('Drags a task around', () => { - cy.intercept('**/api/v1/tasks/*') - .as('taskUpdate') + cy.intercept(Cypress.env('API_URL') + '/tasks/*').as('taskUpdate') const now = new Date() TaskFactory.create(1, { - start_date: formatISO(now), - end_date: formatISO(now.setDate(now.getDate() + 4)), + start_date: now.toISOString(), + end_date: new Date(new Date(now).setDate(now.getDate() + 4)).toISOString(), }) cy.visit('/lists/1/gantt') diff --git a/cypress/e2e/list/list-view-kanban.spec.ts b/cypress/e2e/list/list-view-kanban.spec.ts index ffa4cca9a..c2677c689 100644 --- a/cypress/e2e/list/list-view-kanban.spec.ts +++ b/cypress/e2e/list/list-view-kanban.spec.ts @@ -1,14 +1,15 @@ +import {createFakeUserAndLogin} from '../../support/authenticateUser' + import {BucketFactory} from '../../factories/bucket' import {ListFactory} from '../../factories/list' import {TaskFactory} from '../../factories/task' import {prepareLists} from './prepareLists' -import '../../support/authenticateUser' - describe('List View Kanban', () => { - let buckets + createFakeUserAndLogin() prepareLists() - + + let buckets beforeEach(() => { buckets = BucketFactory.create(2) }) @@ -38,7 +39,7 @@ describe('List View Kanban', () => { }) cy.visit('/lists/1/kanban') - cy.getSettled('.kanban .bucket') + cy.get('.kanban .bucket') .contains(buckets[0].title) .get('.bucket-footer .button') .contains('Add another task') @@ -70,7 +71,7 @@ describe('List View Kanban', () => { it('Can set a bucket limit', () => { cy.visit('/lists/1/kanban') - cy.getSettled('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger') + cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger') .first() .click() cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item') @@ -91,7 +92,7 @@ describe('List View Kanban', () => { it('Can rename a bucket', () => { cy.visit('/lists/1/kanban') - cy.getSettled('.kanban .bucket .bucket-header .title') + cy.get('.kanban .bucket .bucket-header .title') .first() .type('{selectall}New Bucket Title{enter}') cy.get('.kanban .bucket .bucket-header .title') @@ -102,7 +103,7 @@ describe('List View Kanban', () => { it('Can delete a bucket', () => { cy.visit('/lists/1/kanban') - cy.getSettled('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger') + cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger') .first() .click() cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item') @@ -129,7 +130,7 @@ describe('List View Kanban', () => { }) cy.visit('/lists/1/kanban') - cy.getSettled('.kanban .bucket .tasks .task') + cy.get('.kanban .bucket .tasks .task') .contains(tasks[0].title) .first() .drag('.kanban .bucket:nth-child(2) .tasks') @@ -148,7 +149,7 @@ describe('List View Kanban', () => { }) cy.visit('/lists/1/kanban') - cy.getSettled('.kanban .bucket .tasks .task') + cy.get('.kanban .bucket .tasks .task') .contains(tasks[0].title) .should('be.visible') .click() @@ -170,7 +171,7 @@ describe('List View Kanban', () => { const task = tasks[0] cy.visit('/lists/1/kanban') - cy.getSettled('.kanban .bucket .tasks .task') + cy.get('.kanban .bucket .tasks .task') .contains(task.title) .should('be.visible') .click() @@ -217,7 +218,7 @@ describe('List View Kanban', () => { const task = tasks[0] cy.visit('/lists/1/kanban') - cy.getSettled('.kanban .bucket .tasks .task') + cy.get('.kanban .bucket .tasks .task') .contains(task.title) .should('be.visible') .click() @@ -234,7 +235,7 @@ describe('List View Kanban', () => { cy.get('.global-notification') .should('contain', 'Success') - cy.getSettled('.kanban .bucket .tasks') + cy.get('.kanban .bucket .tasks') .should('not.contain', task.title) }) }) \ No newline at end of file diff --git a/cypress/e2e/list/list-view-list.spec.ts b/cypress/e2e/list/list-view-list.spec.ts index d980b3bd3..0601894d4 100644 --- a/cypress/e2e/list/list-view-list.spec.ts +++ b/cypress/e2e/list/list-view-list.spec.ts @@ -1,12 +1,13 @@ +import {createFakeUserAndLogin} from '../../support/authenticateUser' + import {UserListFactory} from '../../factories/users_list' import {TaskFactory} from '../../factories/task' import {UserFactory} from '../../factories/user' import {ListFactory} from '../../factories/list' import {prepareLists} from './prepareLists' -import '../../support/authenticateUser' - describe('List View List', () => { + createFakeUserAndLogin() prepareLists() it('Should be an empty list', () => { diff --git a/cypress/e2e/list/list-view-table.spec.ts b/cypress/e2e/list/list-view-table.spec.ts index e0336efc5..dac79224d 100644 --- a/cypress/e2e/list/list-view-table.spec.ts +++ b/cypress/e2e/list/list-view-table.spec.ts @@ -1,8 +1,10 @@ +import {createFakeUserAndLogin} from '../../support/authenticateUser' + import {TaskFactory} from '../../factories/task' -import '../../support/authenticateUser' - describe('List View Table', () => { + createFakeUserAndLogin() + it('Should show a table with tasks', () => { const tasks = TaskFactory.create(1) cy.visit('/lists/1/table') diff --git a/cypress/e2e/list/list.spec.ts b/cypress/e2e/list/list.spec.ts index fc7f1b201..6f7c0b3a4 100644 --- a/cypress/e2e/list/list.spec.ts +++ b/cypress/e2e/list/list.spec.ts @@ -1,9 +1,11 @@ +import {createFakeUserAndLogin} from '../../support/authenticateUser' + import {TaskFactory} from '../../factories/task' import {prepareLists} from './prepareLists' -import '../../support/authenticateUser' - describe('Lists', () => { + createFakeUserAndLogin() + let lists prepareLists((newLists) => (lists = newLists)) diff --git a/cypress/e2e/list/namespaces.spec.ts b/cypress/e2e/list/namespaces.spec.ts index 6bcf8b231..58d57159b 100644 --- a/cypress/e2e/list/namespaces.spec.ts +++ b/cypress/e2e/list/namespaces.spec.ts @@ -1,14 +1,14 @@ -import {UserFactory} from '../../factories/user' +import {createFakeUserAndLogin} from '../../support/authenticateUser' -import '../../support/authenticateUser' import {ListFactory} from '../../factories/list' import {NamespaceFactory} from '../../factories/namespace' describe('Namepaces', () => { + createFakeUserAndLogin() + let namespaces beforeEach(() => { - UserFactory.create(1) namespaces = NamespaceFactory.create(1) ListFactory.create(1) }) diff --git a/cypress/e2e/list/prepareLists.ts b/cypress/e2e/list/prepareLists.ts index d40dc9d08..8fa70e9c7 100644 --- a/cypress/e2e/list/prepareLists.ts +++ b/cypress/e2e/list/prepareLists.ts @@ -1,10 +1,8 @@ import {ListFactory} from '../../factories/list' -import {UserFactory} from '../../factories/user' import {NamespaceFactory} from '../../factories/namespace' import {TaskFactory} from '../../factories/task' export function createLists() { - UserFactory.create(1) NamespaceFactory.create(1) const lists = ListFactory.create(1, { title: 'First List' diff --git a/cypress/e2e/misc/editor.spec.ts b/cypress/e2e/misc/editor.spec.ts index 253e64dcc..c1edb37e3 100644 --- a/cypress/e2e/misc/editor.spec.ts +++ b/cypress/e2e/misc/editor.spec.ts @@ -1,14 +1,16 @@ +import {createFakeUserAndLogin} from '../../support/authenticateUser' + import {TaskFactory} from '../../factories/task' import {ListFactory} from '../../factories/list' import {NamespaceFactory} from '../../factories/namespace' import {UserListFactory} from '../../factories/users_list' -import '../../support/authenticateUser' - describe('Editor', () => { + createFakeUserAndLogin() + beforeEach(() => { NamespaceFactory.create(1) - const lists = ListFactory.create(1) + ListFactory.create(1) TaskFactory.truncate() UserListFactory.truncate() }) diff --git a/cypress/e2e/misc/menu.spec.ts b/cypress/e2e/misc/menu.spec.ts index 86e3ab57f..bb7b3d774 100644 --- a/cypress/e2e/misc/menu.spec.ts +++ b/cypress/e2e/misc/menu.spec.ts @@ -1,6 +1,12 @@ -import '../../support/authenticateUser' +import {createFakeUserAndLogin} from '../../support/authenticateUser' describe('The Menu', () => { + createFakeUserAndLogin() + + beforeEach(() => { + cy.visit('/') + }) + it('Is visible by default on desktop', () => { cy.get('.namespace-container') .should('have.class', 'is-active') diff --git a/cypress/e2e/sharing/team.spec.ts b/cypress/e2e/sharing/team.spec.ts index 7c48a59aa..95ea13c83 100644 --- a/cypress/e2e/sharing/team.spec.ts +++ b/cypress/e2e/sharing/team.spec.ts @@ -1,9 +1,12 @@ +import {createFakeUserAndLogin} from '../../support/authenticateUser' + import {TeamFactory} from '../../factories/team' import {TeamMemberFactory} from '../../factories/team_member' import {UserFactory} from '../../factories/user' -import '../../support/authenticateUser' describe('Team', () => { + createFakeUserAndLogin() + it('Creates a new team', () => { TeamFactory.truncate() cy.visit('/teams') diff --git a/cypress/e2e/task/overview.spec.ts b/cypress/e2e/task/overview.spec.ts index a84eb36ef..39153c191 100644 --- a/cypress/e2e/task/overview.spec.ts +++ b/cypress/e2e/task/overview.spec.ts @@ -1,16 +1,13 @@ +import {createFakeUserAndLogin} from '../../support/authenticateUser' + import {ListFactory} from '../../factories/list' import {seed} from '../../support/seed' import {TaskFactory} from '../../factories/task' -import {formatISO} from 'date-fns' -import {UserFactory} from '../../factories/user' import {NamespaceFactory} from '../../factories/namespace' import {BucketFactory} from '../../factories/bucket' import {updateUserSettings} from '../../support/updateUserSettings' -import '../../support/authenticateUser' - -function seedTasks(numberOfTasks = 100, startDueDate = new Date()) { - UserFactory.create(1) +function seedTasks(numberOfTasks = 50, startDueDate = new Date()) { NamespaceFactory.create(1) const list = ListFactory.create()[0] BucketFactory.create(1, { @@ -20,7 +17,7 @@ function seedTasks(numberOfTasks = 100, startDueDate = new Date()) { let dueDate = startDueDate for (let i = 0; i < numberOfTasks; i++) { const now = new Date() - dueDate = (new Date(dueDate.valueOf())).setDate((new Date(dueDate.valueOf())).getDate() + 2) + dueDate = new Date(new Date(dueDate).setDate(dueDate.getDate() + 2)) tasks.push({ id: i + 1, list_id: list.id, @@ -28,9 +25,9 @@ function seedTasks(numberOfTasks = 100, startDueDate = new Date()) { created_by_id: 1, title: 'Test Task ' + i, index: i + 1, - due_date: formatISO(dueDate), - created: formatISO(now), - updated: formatISO(now), + due_date: dueDate.toISOString(), + created: now.toISOString(), + updated: now.toISOString(), }) } seed(TaskFactory.table, tasks) @@ -38,8 +35,11 @@ function seedTasks(numberOfTasks = 100, startDueDate = new Date()) { } describe('Home Page Task Overview', () => { + createFakeUserAndLogin() + it('Should show tasks with a near due date first on the home page overview', () => { - const {tasks} = seedTasks() + const taskCount = 50 + const {tasks} = seedTasks(taskCount) cy.visit('/') cy.get('[data-cy="showTasks"] .card .task') @@ -49,8 +49,10 @@ describe('Home Page Task Overview', () => { }) it('Should show overdue tasks first, then show other tasks', () => { - const oldDate = (new Date()).setDate((new Date()).getDate() - 14) - const {tasks} = seedTasks(100, oldDate) + const now = new Date() + const oldDate = new Date(new Date(now).setDate(now.getDate() - 14)) + const taskCount = 50 + const {tasks} = seedTasks(taskCount, oldDate) cy.visit('/') cy.get('[data-cy="showTasks"] .card .task') @@ -68,7 +70,7 @@ describe('Home Page Task Overview', () => { TaskFactory.create(1, { id: 999, title: newTaskTitle, - due_date: formatISO(new Date()), + due_date: new Date().toISOString(), }, false) cy.visit(`/lists/${tasks[0].list_id}/list`) @@ -83,7 +85,7 @@ describe('Home Page Task Overview', () => { it('Should not show a new task without a date at the bottom when there are > 50 tasks', () => { // We're not using the api here to create the task in order to verify the flow - const {tasks} = seedTasks() + const {tasks} = seedTasks(100) const newTaskTitle = 'New Task' cy.visit('/') diff --git a/cypress/e2e/task/task.spec.ts b/cypress/e2e/task/task.spec.ts index 2752e651b..f441dc742 100644 --- a/cypress/e2e/task/task.spec.ts +++ b/cypress/e2e/task/task.spec.ts @@ -1,4 +1,4 @@ -import {formatISO} from 'date-fns' +import {createFakeUserAndLogin} from '../../support/authenticateUser' import {TaskFactory} from '../../factories/task' import {ListFactory} from '../../factories/list' @@ -11,7 +11,6 @@ import {LabelFactory} from '../../factories/labels' import {LabelTaskFactory} from '../../factories/label_task' import {BucketFactory} from '../../factories/bucket' -import '../../support/authenticateUser' import {TaskAttachmentFactory} from '../../factories/task_attachments' function addLabelToTaskAndVerify(labelTitle: string) { @@ -46,12 +45,14 @@ function uploadAttachmentAndVerify(taskId: number) { } describe('Task', () => { + createFakeUserAndLogin() + let namespaces let lists let buckets beforeEach(() => { - UserFactory.create(1) + // UserFactory.create(1) namespaces = NamespaceFactory.create(1) lists = ListFactory.create(1) buckets = BucketFactory.create(1, { @@ -145,7 +146,7 @@ describe('Task', () => { id: 1, index: 1, done: true, - done_at: formatISO(new Date()) + done_at: new Date().toISOString() }) cy.visit(`/tasks/${tasks[0].id}`) @@ -421,10 +422,10 @@ describe('Task', () => { cy.visit(`/tasks/${tasks[0].id}`) - cy.getSettled('.task-view .details.labels-list .multiselect .input-wrapper') + cy.get('.task-view .details.labels-list .multiselect .input-wrapper') .should('be.visible') .should('contain', labels[0].title) - cy.getSettled('.task-view .details.labels-list .multiselect .input-wrapper') + cy.get('.task-view .details.labels-list .multiselect .input-wrapper') .children() .first() .get('[data-cy="taskDetail.removeLabel"]') diff --git a/cypress/e2e/tsconfig.json b/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..4c26a2fd0 --- /dev/null +++ b/cypress/e2e/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "@vue/tsconfig/tsconfig.web.json", + "include": ["./**/*", "../support/**/*", "../factories/**/*"], + "compilerOptions": { + "baseUrl": ".", + "isolatedModules": false, + "target": "ES2015", + "lib": ["ESNext", "dom"], + "types": ["cypress"] + } +} diff --git a/cypress/e2e/user/login.spec.ts b/cypress/e2e/user/login.spec.ts index 80bf231e7..97df3e17d 100644 --- a/cypress/e2e/user/login.spec.ts +++ b/cypress/e2e/user/login.spec.ts @@ -11,16 +11,11 @@ const testAndAssertFailed = fixture => { cy.get('div.message.danger').contains('Wrong username or password.') } +const username = 'test' + context('Login', () => { beforeEach(() => { - UserFactory.create(1, { - username: 'test', - }) - cy.visit('/', { - onBeforeLoad(win) { - win.localStorage.removeItem('token') - }, - }) + UserFactory.create(1, {username}) }) it('Should log in with the right credentials', () => { diff --git a/cypress/e2e/user/logout.spec.ts b/cypress/e2e/user/logout.spec.ts index 2f45f0bf1..aeb07e587 100644 --- a/cypress/e2e/user/logout.spec.ts +++ b/cypress/e2e/user/logout.spec.ts @@ -1,4 +1,4 @@ -import '../../support/authenticateUser' +import {createFakeUserAndLogin} from '../../support/authenticateUser' import {createLists} from '../list/prepareLists' function logout() { @@ -10,6 +10,8 @@ function logout() { } describe('Log out', () => { + createFakeUserAndLogin() + it('Logs the user out', () => { cy.visit('/') diff --git a/cypress/e2e/user/settings.spec.ts b/cypress/e2e/user/settings.spec.ts index 21bd9c1d9..ca4c3427a 100644 --- a/cypress/e2e/user/settings.spec.ts +++ b/cypress/e2e/user/settings.spec.ts @@ -1,11 +1,7 @@ -import {UserFactory} from '../../factories/user' - -import '../../support/authenticateUser' +import {createFakeUserAndLogin} from '../../support/authenticateUser' describe('User Settings', () => { - beforeEach(() => { - UserFactory.create(1) - }) + createFakeUserAndLogin() it('Changes the user avatar', () => { cy.intercept(`${Cypress.env('API_URL')}/user/settings/avatar/upload`).as('uploadAvatar') diff --git a/cypress/factories/bucket.ts b/cypress/factories/bucket.ts index 418774016..d333531bf 100644 --- a/cypress/factories/bucket.ts +++ b/cypress/factories/bucket.ts @@ -1,6 +1,5 @@ import {faker} from '@faker-js/faker' import {Factory} from '../support/factory' -import {formatISO} from 'date-fns' export class BucketFactory extends Factory { static table = 'buckets' @@ -13,8 +12,8 @@ export class BucketFactory extends Factory { title: faker.lorem.words(3), list_id: 1, created_by_id: 1, - created: formatISO(now), - updated: formatISO(now) + created: now.toISOString(), + updated: now.toISOString(), } } } diff --git a/cypress/factories/label_task.ts b/cypress/factories/label_task.ts index 65cd47058..28569c820 100644 --- a/cypress/factories/label_task.ts +++ b/cypress/factories/label_task.ts @@ -1,5 +1,4 @@ import {Factory} from '../support/factory' -import {formatISO} from 'date-fns' export class LabelTaskFactory extends Factory { static table = 'label_tasks' @@ -11,7 +10,7 @@ export class LabelTaskFactory extends Factory { id: '{increment}', task_id: 1, label_id: 1, - created: formatISO(now), + created: now.toISOString(), } } } \ No newline at end of file diff --git a/cypress/factories/labels.ts b/cypress/factories/labels.ts index 5840a205c..4d9d67541 100644 --- a/cypress/factories/labels.ts +++ b/cypress/factories/labels.ts @@ -1,7 +1,6 @@ import {faker} from '@faker-js/faker' import {Factory} from '../support/factory' -import {formatISO} from 'date-fns' export class LabelFactory extends Factory { static table = 'labels' @@ -15,8 +14,8 @@ export class LabelFactory extends Factory { description: faker.lorem.text(10), hex_color: (Math.random()*0xFFFFFF<<0).toString(16), // random 6-digit hex number created_by_id: 1, - created: formatISO(now), - updated: formatISO(now), + created: now.toISOString(), + updated: now.toISOString(), } } } \ No newline at end of file diff --git a/cypress/factories/link_sharing.ts b/cypress/factories/link_sharing.ts index 170af6981..672d2fc14 100644 --- a/cypress/factories/link_sharing.ts +++ b/cypress/factories/link_sharing.ts @@ -1,5 +1,4 @@ import {Factory} from '../support/factory' -import {formatISO} from "date-fns" import {faker} from '@faker-js/faker' export class LinkShareFactory extends Factory { @@ -15,8 +14,8 @@ export class LinkShareFactory extends Factory { right: 0, sharing_type: 0, shared_by_id: 1, - created: formatISO(now), - updated: formatISO(now) + created: now.toISOString(), + updated: now.toISOString(), } } } diff --git a/cypress/factories/list.ts b/cypress/factories/list.ts index a91debea8..aff7167c5 100644 --- a/cypress/factories/list.ts +++ b/cypress/factories/list.ts @@ -1,5 +1,4 @@ import {Factory} from '../support/factory' -import {formatISO} from "date-fns" import {faker} from '@faker-js/faker' export class ListFactory extends Factory { @@ -13,8 +12,8 @@ export class ListFactory extends Factory { title: faker.lorem.words(3), owner_id: 1, namespace_id: 1, - created: formatISO(now), - updated: formatISO(now) + created: now.toISOString(), + updated: now.toISOString(), } } } \ No newline at end of file diff --git a/cypress/factories/namespace.ts b/cypress/factories/namespace.ts index a63947b7e..964faff14 100644 --- a/cypress/factories/namespace.ts +++ b/cypress/factories/namespace.ts @@ -1,6 +1,5 @@ import {faker} from '@faker-js/faker' import {Factory} from '../support/factory' -import {formatISO} from 'date-fns' export class NamespaceFactory extends Factory { static table = 'namespaces' @@ -12,8 +11,8 @@ export class NamespaceFactory extends Factory { id: '{increment}', title: faker.lorem.words(3), owner_id: 1, - created: formatISO(now), - updated: formatISO(now) + created: now.toISOString(), + updated: now.toISOString(), } } } diff --git a/cypress/factories/task.ts b/cypress/factories/task.ts index 46c8e8654..e7c5769eb 100644 --- a/cypress/factories/task.ts +++ b/cypress/factories/task.ts @@ -1,6 +1,5 @@ import {faker} from '@faker-js/faker' import {Factory} from '../support/factory' -import {formatISO} from 'date-fns' export class TaskFactory extends Factory { static table = 'tasks' @@ -16,8 +15,8 @@ export class TaskFactory extends Factory { created_by_id: 1, index: '{increment}', position: '{increment}', - created: formatISO(now), - updated: formatISO(now) + created: now.toISOString(), + updated: now.toISOString() } } } diff --git a/cypress/factories/task_assignee.ts b/cypress/factories/task_assignee.ts index 08034e557..5efda9676 100644 --- a/cypress/factories/task_assignee.ts +++ b/cypress/factories/task_assignee.ts @@ -1,5 +1,4 @@ import {Factory} from '../support/factory' -import {formatISO} from 'date-fns' export class TaskAssigneeFactory extends Factory { static table = 'task_assignees' @@ -11,7 +10,7 @@ export class TaskAssigneeFactory extends Factory { id: '{increment}', task_id: 1, user_id: 1, - created: formatISO(now), + created: now.toISOString(), } } } \ No newline at end of file diff --git a/cypress/factories/task_attachments.ts b/cypress/factories/task_attachments.ts index 2db80781c..5c0fa0ff5 100644 --- a/cypress/factories/task_attachments.ts +++ b/cypress/factories/task_attachments.ts @@ -1,5 +1,4 @@ import {Factory} from '../support/factory' -import {formatISO} from 'date-fns' export class TaskAttachmentFactory extends Factory { static table = 'task_attachments' @@ -11,7 +10,7 @@ export class TaskAttachmentFactory extends Factory { id: '{increment}', task_id: 1, file_id: 1, - created: formatISO(now), + created: now.toISOString(), } } } \ No newline at end of file diff --git a/cypress/factories/task_comment.ts b/cypress/factories/task_comment.ts index 34356d626..362316e92 100644 --- a/cypress/factories/task_comment.ts +++ b/cypress/factories/task_comment.ts @@ -1,7 +1,6 @@ import {faker} from '@faker-js/faker' import {Factory} from '../support/factory' -import {formatISO} from "date-fns" export class TaskCommentFactory extends Factory { static table = 'task_comments' @@ -14,8 +13,8 @@ export class TaskCommentFactory extends Factory { comment: faker.lorem.text(3), author_id: 1, task_id: 1, - created: formatISO(now), - updated: formatISO(now) + created: now.toISOString(), + updated: now.toISOString() } } } diff --git a/cypress/factories/team.ts b/cypress/factories/team.ts index 4c698a301..c59f0b924 100644 --- a/cypress/factories/team.ts +++ b/cypress/factories/team.ts @@ -1,6 +1,5 @@ import {faker} from '@faker-js/faker' import {Factory} from '../support/factory' -import {formatISO} from 'date-fns' export class TeamFactory extends Factory { static table = 'teams' @@ -11,8 +10,8 @@ export class TeamFactory extends Factory { return { name: faker.lorem.words(3), created_by_id: 1, - created: formatISO(now), - updated: formatISO(now) + created: now.toISOString(), + updated: now.toISOString(), } } } diff --git a/cypress/factories/team_member.ts b/cypress/factories/team_member.ts index 08da679d3..18465b886 100644 --- a/cypress/factories/team_member.ts +++ b/cypress/factories/team_member.ts @@ -1,5 +1,4 @@ import {Factory} from '../support/factory' -import {formatISO} from 'date-fns' export class TeamMemberFactory extends Factory { static table = 'team_members' @@ -9,7 +8,7 @@ export class TeamMemberFactory extends Factory { team_id: 1, user_id: 1, admin: false, - created: formatISO(new Date()), + created: new Date().toISOString(), } } } \ No newline at end of file diff --git a/cypress/factories/user.ts b/cypress/factories/user.ts index 46629c533..02d9069fa 100644 --- a/cypress/factories/user.ts +++ b/cypress/factories/user.ts @@ -1,7 +1,6 @@ import {faker} from '@faker-js/faker' import {Factory} from '../support/factory' -import {formatISO} from "date-fns" export class UserFactory extends Factory { static table = 'users' @@ -15,8 +14,8 @@ export class UserFactory extends Factory { password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.', // 1234 status: 0, issuer: 'local', - created: formatISO(now), - updated: formatISO(now) + created: now.toISOString(), + updated: now.toISOString(), } } } \ No newline at end of file diff --git a/cypress/factories/users_list.ts b/cypress/factories/users_list.ts index 5eecd2d76..60b08be50 100644 --- a/cypress/factories/users_list.ts +++ b/cypress/factories/users_list.ts @@ -1,5 +1,4 @@ import {Factory} from '../support/factory' -import {formatISO} from "date-fns" export class UserListFactory extends Factory { static table = 'users_lists' @@ -12,8 +11,8 @@ export class UserListFactory extends Factory { list_id: 1, user_id: 1, right: 0, - created: formatISO(now), - updated: formatISO(now) + created: now.toISOString(), + updated: now.toISOString(), } } } \ No newline at end of file diff --git a/cypress/support/authenticateUser.ts b/cypress/support/authenticateUser.ts index 5f2423a46..22839ae33 100644 --- a/cypress/support/authenticateUser.ts +++ b/cypress/support/authenticateUser.ts @@ -4,26 +4,32 @@ import {UserFactory} from '../factories/user' -let token - -before(() => { - const users = UserFactory.create(1) - - cy.request('POST', `${Cypress.env('API_URL')}/login`, { - username: users[0].username, - password: '1234', - }) - .its('body') - .then(r => { - token = r.token +export function login(user, cacheAcrossSpecs = false) { + if (!user) { + throw new Error('Needs user') + } + // Caching session when logging in via page visit + cy.session(`user__${user.username}`, () => { + cy.request('POST', `${Cypress.env('API_URL')}/login`, { + username: user.username, + password: '1234', + }).then(({ body }) => { + window.localStorage.setItem('token', body.token) }) -}) + }, { + cacheAcrossSpecs, + }) +} -beforeEach(() => { - cy.log(`Using token ${token} to make authenticated requests`) - cy.visit('/', { - onBeforeLoad(win) { - win.localStorage.setItem('token', token) - }, +export function createFakeUserAndLogin() { + let user + before(() => { + user = UserFactory.create(1)[0] }) -}) + + beforeEach(() => { + login(user, true) + }) + + return user +} \ No newline at end of file diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index aa0c8be97..698b01a42 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -34,38 +34,4 @@ // visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable // } // } -// } - -/** - * Recursively gets an element, returning only after it's determined to be attached to the DOM for good. - * - * Source: https://github.com/cypress-io/cypress/issues/7306#issuecomment-850621378 - */ -Cypress.Commands.add('getSettled', (selector, opts = {}) => { - const retries = opts.retries || 3 - const delay = opts.delay || 100 - - const isAttached = (resolve, count = 0) => { - const el = Cypress.$(selector) - - // is element attached to the DOM? - count = Cypress.dom.isAttached(el) ? count + 1 : 0 - - // hit our base case, return the element - if (count >= retries) { - return resolve(el) - } - - // retry after a bit of a delay - setTimeout(() => isAttached(resolve, count), delay) - } - - // wrap, so we can chain cypress commands off the result - return cy.wrap(null).then(() => { - return new Cypress.Promise((resolve) => { - return isAttached(resolve, 0) - }).then((el) => { - return cy.wrap(el) - }) - }) -}) +// } \ No newline at end of file diff --git a/cypress/support/updateUserSettings.js b/cypress/support/updateUserSettings.ts similarity index 100% rename from cypress/support/updateUserSettings.js rename to cypress/support/updateUserSettings.ts diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json deleted file mode 100644 index e0f01636c..000000000 --- a/cypress/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "@vue/tsconfig/tsconfig.web.json", - "include": ["./integration/**/*", "./support/**/*"], - "compilerOptions": { - "isolatedModules": false, - "target": "es5", - "lib": ["es5", "dom"], - "types": ["cypress"] - } -} \ No newline at end of file diff --git a/env.config.d.ts b/env.config.d.ts new file mode 100644 index 000000000..754c31853 --- /dev/null +++ b/env.config.d.ts @@ -0,0 +1,9 @@ +declare module 'postcss-easings' { + import postcssEasings from 'postcss-easings' + export default postcssEasings +} + +declare module 'postcss-easing-gradients' { + import postcssEasingGradients from 'postcss-easing-gradients' + export default postcssEasingGradients +} \ No newline at end of file diff --git a/env.d.ts b/env.d.ts index 2d7de3f6a..adf078af2 100644 --- a/env.d.ts +++ b/env.d.ts @@ -1,3 +1,12 @@ /// /// -/// \ No newline at end of file +/// +/// + +interface ImportMetaEnv { + readonly VITE_IS_ONLINE: boolean +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} \ No newline at end of file diff --git a/histoire.config.ts b/histoire.config.ts new file mode 100644 index 000000000..654c699d8 --- /dev/null +++ b/histoire.config.ts @@ -0,0 +1,34 @@ +import {defineConfig, defaultColors} from 'histoire' +import {HstVue} from '@histoire/plugin-vue' +import {HstScreenshot} from '@histoire/plugin-screenshot' + +export default defineConfig({ + setupFile: './src/histoire.setup.ts', + storyIgnored: [ + '**/node_modules/**', + '**/dist/**', + // see https://kolaente.dev/vikunja/frontend/pulls/2724#issuecomment-42012 + '**/.direnv/**', + ], + plugins: [ + HstVue(), + HstScreenshot({ + // Options here + }), + ], + theme: { + title: 'Vikunja', + colors: { + // https://histoire.dev/guide/config.html#builtin-colors + gray: defaultColors.zinc, + primary: defaultColors.cyan, + }, + // logo: { + // square: './img/square.png', + // light: './img/light.png', + // dark: './img/dark.png', + // }, + // logoHref: 'https://acme.com', + // favicon: './favicon.ico', + }, +}) \ No newline at end of file diff --git a/index.html b/index.html index ddd35968d..a400eff88 100644 --- a/index.html +++ b/index.html @@ -9,13 +9,7 @@ - - - - - - - +