diff --git a/.drone.yml b/.drone.yml index 30c4b76fe..8599f574b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -4,7 +4,7 @@ name: build trigger: branch: include: - - master + - main event: include: - push @@ -37,7 +37,7 @@ steps: - '.cache' - name: dependencies - image: node:12 + image: node:16 pull: true environment: YARN_CACHE_FOLDER: .cache/yarn/ @@ -67,20 +67,41 @@ steps: depends_on: - dependencies - - name: build - image: node:12 + - name: lint + image: node:16 pull: true environment: YARN_CACHE_FOLDER: .cache/yarn/ CYPRESS_CACHE_FOLDER: .cache/cypress/ commands: - yarn run lint - - yarn run build + depends_on: + - dependencies + + # Building in dev mode to avoid the service worker for testing + - name: build-dev + image: node:16 + pull: true + environment: + YARN_CACHE_FOLDER: .cache/yarn/ + CYPRESS_CACHE_FOLDER: .cache/cypress/ + commands: + - yarn build:dev + depends_on: + - dependencies + + - name: build-prod + image: node:16 + pull: true + environment: + YARN_CACHE_FOLDER: .cache/yarn/ + commands: + - yarn build --dest dist-prod depends_on: - dependencies - name: test-unit - image: node:12 + image: node:16 pull: true commands: - yarn test:unit @@ -88,20 +109,21 @@ steps: - dependencies - name: test-frontend - image: cypress/browsers:node12.18.3-chrome87-ff82 + image: cypress/browsers:node14.17.0-chrome91-ff89 pull: true environment: CYPRESS_API_URL: http://api:3456/api/v1 CYPRESS_TEST_SECRET: averyLongSecretToSe33dtheDB YARN_CACHE_FOLDER: .cache/yarn/ CYPRESS_CACHE_FOLDER: .cache/cypress/ - CYPRESS_DEFAULT_COMMAND_TIMEOUT: 10000 + CYPRESS_DEFAULT_COMMAND_TIMEOUT: 60000 commands: - - sed -i 's/localhost/api/g' public/index.html - - yarn serve & npx wait-on http://localhost:8080 + - sed -i 's/localhost/api/g' dist-dev/index.html + - yarn serve:dist-dev & npx wait-on http://localhost:5000 - yarn test:frontend --browser chrome depends_on: - dependencies + - build-dev - name: upload-test-results image: plugins/s3:1 @@ -118,7 +140,7 @@ steps: source: cypress/screenshots/**/**/* strip_prefix: cypress/screenshots/ target: /${DRONE_REPO}/${DRONE_PULL_REQUEST}_${DRONE_BRANCH}/${DRONE_BUILD_NUMBER}/ - depends_on: + depends_on: - test-frontend when: status: @@ -134,7 +156,7 @@ depends_on: trigger: branch: - - master + - main event: - push @@ -163,7 +185,7 @@ steps: - '.cache' - name: build - image: node:12 + image: node:16 pull: true group: build-static environment: @@ -174,13 +196,15 @@ steps: - "echo '{\"VERSION\": \"'$(git describe --tags --always --abbrev=10 | sed 's/-/+/' | sed 's/^v//' | sed 's/-g/-/')'\"}' > src/version.json" - yarn run build - sed -i 's/http\:\\/\\/localhost\\:3456\\/api\\/v1/\\/api\\/v1/g' dist/index.html # Override the default api url used for developing + depends_on: + - restore-cache - name: static image: kolaente/zip pull: true commands: - cd dist - - zip -r ../vikunja-frontend-master.zip * + - zip -r ../vikunja-frontend-unstable.zip * - cd .. depends_on: [ build ] @@ -196,7 +220,7 @@ steps: endpoint: https://s3.fr-par.scw.cloud region: fr-par path_style: true - source: vikunja-frontend-master.zip + source: vikunja-frontend-unstable.zip target: /frontend/ depends_on: [ static ] @@ -236,7 +260,7 @@ steps: - '.cache' - name: build - image: node:12 + image: node:16 pull: true group: build-static environment: @@ -247,6 +271,8 @@ steps: - "echo '{\"VERSION\": \"'$(git describe --tags --always --abbrev=10 | sed 's/-/+/' | sed 's/^v//' | sed 's/-g/-/')'\"}' > src/version.json" - yarn run build - sed -i 's/http\:\\/\\/localhost\\:3456\\/api\\/v1/\\/api\\/v1/g' dist/index.html # Override the default api url used for developing + depends_on: + - restore-cache - name: static image: kolaente/zip @@ -279,12 +305,12 @@ name: trigger-desktop-update trigger: branch: - - master + - main event: - push depends_on: - - release-latest + - release-latest steps: - name: trigger @@ -294,7 +320,7 @@ steps: token: from_secret: drone_token repositories: - - vikunja/desktop@master + - vikunja/desktop@main --- kind: pipeline @@ -311,11 +337,11 @@ platform: trigger: ref: - - refs/heads/master + - refs/heads/main - "refs/tags/**" steps: - - name: docker-latest + - name: docker-unstable image: plugins/docker:linux-arm pull: true settings: @@ -324,14 +350,13 @@ steps: password: from_secret: docker_password repo: vikunja/frontend - auto_tag: true - auto_tag_suffix: linux-arm + tags: unstable-linux-arm build_args: - USE_RELEASE=true - - RELEASE_VERSION=master + - RELEASE_VERSION=unstable when: ref: - - refs/heads/master + - refs/heads/main depends_on: - clone @@ -355,7 +380,7 @@ steps: depends_on: - clone - - name: docker-latest-arm64 + - name: docker-unstable-arm64 image: plugins/docker:linux-arm64 pull: true settings: @@ -364,14 +389,13 @@ steps: password: from_secret: docker_password repo: vikunja/frontend - auto_tag: true - auto_tag_suffix: linux-arm64 + tags: unstable-linux-arm64 build_args: - USE_RELEASE=true - - RELEASE_VERSION=master + - RELEASE_VERSION=unstable when: ref: - - refs/heads/master + - refs/heads/main depends_on: - clone @@ -410,11 +434,11 @@ depends_on: trigger: ref: - - refs/heads/master + - refs/heads/main - "refs/tags/**" steps: - - name: docker-latest + - name: docker-unstable image: plugins/docker:linux-amd64 pull: true settings: @@ -423,14 +447,13 @@ steps: password: from_secret: docker_password repo: vikunja/frontend - auto_tag: true - auto_tag_suffix: linux-amd64 + tags: unstable-linux-amd64 build_args: - USE_RELEASE=true - - RELEASE_VERSION=master + - RELEASE_VERSION=unstable when: ref: - - refs/heads/master + - refs/heads/main - name: docker-version image: plugins/docker:linux-amd64 @@ -457,7 +480,7 @@ name: docker-manifest trigger: ref: - - refs/heads/master + - refs/heads/main - "refs/tags/**" depends_on: @@ -465,7 +488,21 @@ depends_on: - docker-arm-release steps: - - name: manifest + - name: manifest-unstable + pull: always + image: plugins/manifest + settings: + tags: unstable + spec: docker-manifest-unstable.tmpl + password: + from_secret: docker_password + username: + from_secret: docker_username + when: + ref: + - refs/heads/main + + - name: manifest-release pull: always image: plugins/manifest settings: @@ -476,6 +513,26 @@ steps: from_secret: docker_password username: from_secret: docker_username + when: + ref: + - "refs/tags/**" + + - name: manifest-release-latest + pull: always + image: plugins/manifest + depends_on: + - clone + settings: + tags: latest + ignore_missing: true + spec: docker-manifest.tmpl + password: + from_secret: docker_password + username: + from_secret: docker_username + when: + ref: + - "refs/tags/**" --- kind: pipeline @@ -484,27 +541,92 @@ name: notify trigger: ref: - - refs/heads/master + - refs/heads/main - "refs/tags/**" depends_on: + - build - release-version - release-latest + - trigger-desktop-update + - docker-arm-release + - docker-amd64-release - docker-manifest steps: - - name: telegram - image: appleboy/drone-telegram:1-linux-amd64 + - name: notify + image: plugins/matrix settings: - token: - from_secret: TELEGRAM_TOKEN - to: - from_secret: TELEGRAM_TO - message: > - {{repo.owner}}/{{repo.name}}: \[{{build.status}}] Build {{build.number}} - {{commit.author}} pushed to {{commit.branch}} {{commit.sha}}: `{{commit.message}}` - Build started at {{datetime build.started "2006-Jan-02T15:04:05Z" "GMT+2"}} finished at {{datetime build.finished "2006-Jan-02T15:04:05Z" "GMT+2"}}. + homeserver: https://matrix.org + roomid: WqBDCxzghKcNflkErL:matrix.org + username: + from_secret: matrix_username + password: + from_secret: matrix_password when: status: - success - failure +--- +kind: pipeline +type: docker +name: update-translations + +depends_on: + - build + +trigger: + branch: + - main + event: + - push + +steps: + - name: download + pull: always + image: jonasfranz/crowdin + settings: + download: true + export_dir: src/i18n/lang/ + ignore_branch: true + project_identifier: vikunja + environment: + CROWDIN_KEY: + from_secret: crowdin_key + + - name: move-files + pull: always + image: bash + depends_on: + - download + commands: + - mv src/i18n/lang/*/*.json src/i18n/lang + + - name: push + pull: always + image: appleboy/drone-git-push + depends_on: + - move-files + settings: + author_email: "frederik@vikunja.io" + author_name: Frederick [Bot] + branch: main + commit: true + commit_message: "[skip ci] Updated translations via Crowdin" + remote: "ssh://git@kolaente.dev:9022/vikunja/frontend.git" + ssh_key: + from_secret: translation_git_push_ssh_key + + - name: upload + pull: always + image: jonasfranz/crowdin + depends_on: + - clone + settings: + files: + en.json: src/i18n/lang/en.json + ignore_branch: true + project_identifier: vikunja + environment: + CROWDIN_KEY: + from_secret: crowdin_key diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..95bef4270 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,22 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = tab +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = false +insert_final_newline = false + +[*.vue] +indent_style = tab + +[*.{yaml,yml}] +indent_style = space +indent_size = 2 + +[*.json] +indent_style = space +indent_size = 2 \ No newline at end of file diff --git a/.gitignore b/.gitignore index aad7d2856..3ae9059a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ .DS_Store node_modules -/dist +/dist* *.zip # local env files @@ -11,6 +11,7 @@ node_modules npm-debug.log* yarn-debug.log* yarn-error.log* +stats.html # Editor directories and files .idea @@ -20,6 +21,7 @@ yarn-error.log* *.njsproj *.sln *.sw* +!rollup.sw.js # Test files cypress/screenshots diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c93f06af..311a521f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,613 @@ All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres +to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 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.18.1] - 2021-09-08 + +### Added + +* feat: make it possible to fake online state via dev env (#720) + +### Fixed + +* fix: call to /null from background image (#714) +* Fix data export download progress +* fix: kanban-card mutatation violation (#712) +* Fix missing translation when creating a new task on the kanban board +* Fix rearranging tasks in a kanban bucket when its limit was reached +* Fix sort order for table view +* Fix task attributes overridden when saving the task title with enter +* Fix translation badge + +### Dependency Updates + +* Update dependency @4tw/cypress-drag-drop to v2 (#711) +* Update dependency axios to v0.21.4 (#705) +* Update dependency jest to v27.1.1 (#716) +* Update dependency vite-plugin-vue2 to v1.8.2 (#707) +* Update dependency vite to v2.5.4 (#708) +* Update dependency vite to v2.5.5 (#709) +* Update typescript-eslint monorepo to v4.31.0 (#706) + + +## [0.18.0] - 2021-09-05 + +### Added + +* Add a button to copy an attachment url from the attachment overview +* Add collapsing kanban buckets +* Add confirm with enter when setting a new password +* Add default list setting & creating tasks from home (#520) +* Add depends_on for push step +* Add depends_on for upload step +* Add drag delay on mobile +* Add express for serve:dev +* Add filters for quick action bar +* Add frontend tests for list history +* Add making tasks favorite from the task detail view +* Add missing position property to list and bucket models +* Add more debug logs for gantt charts +* Add more global state tests (#521) +* Add proofread languages to available languages +* Add quick action bar shortcut to shortcut overview +* Add setting for the first day of the week +* Add showing version info in GUI +* Add syncing translations to crowdin +* Add timeout to fix race condition when authenticating as a link share and renewing the token simultaneously +* Add translations (#562) +* Add typescript support for helper functions (#598) +* Add vite (#416) +* Allow failure of the weblate update step +* Always set the kanban board to full width for share links +* Another day, another js date edge-case +* Automatically update approved translations from crowdin +* Break long list titles in list overview +* Preload labels and use locally stored in vuex +* PWA improvments (#622) +* Quick Actions & global search (#528) +* Quick add magic for tasks (#570) +* Reorder tasks, lists and kanban buckets (#620) +* Show last visited list on home page +* Show recently visited lists in quick actions +* Show salutation based on the time of day +* Sort labels alphabetically on tasks +* Switch the :latest docker image tag to contain the latest release instead of the latest unstable + +### Changed + +* Change building latest docker image +* Change desktop downstream trigger plugin with our own debug build +* Change menu hamburger icon +* Change quick add magic characters to be more familiar with the todoist ones +* Change the docker builder image to a working one on arm +* chore: discard old font file formats (#673) +* chore: only import common languages (#671) +* Cleanup broken sw functions +* Cleanup drone pipeline +* Cleanup old vue cli config +* Configure tests retries +* Decrease page padding on task detail page +* Directly redirect to the openid auth provider if that's the only auth method +* Don't allow dragging a list when the user does not have the rights +* Don't load already loaded task attachments again when saving an edited task description +* Don't prefetch all i18n files +* Don't show archived lists/namespaces in quick actions +* feat: provide global variables in all components (#669) +* Hide favorite list edit menu +* Hide keyboard shortcuts indicator on mobile +* Improve chunk size +* Improve some translations (#581) +* Improve tests +* Indicate done tasks in quick actions +* Load list background in list card +* Make editor edit button at the bottom the default and make sure the done button stands out more +* Make saving a text edit a button +* Make sure highlight.js is always lazy-loaded +* Make sure the task popup view takes up all the space it can on mobile +* Make tests less flaky +* Make the logo smaller on link shared lists +* Make the progress bar color lighter +* Move creation of new items to the bottom of the multiselect list +* Move general settings to the top +* Move translated files after downloading them +* Move weblate ping to shell script +* Only add a drag delay if on mobile instead of setting it to 0 +* Only build a bundle for modern browsers +* Refactor success and error messages +* Refactor success and error notifications to prevent html in them +* Remove logout button for link shares +* Run frontend-tests with dist in ci (#605) +* Save auth tokens from link shares only in memory, don't persist them to localStorage +* Search namespaces locally only when duplicating a list +* Show errors from openid provider +* Show labels alphabetically sorted in the overview +* Small cleanups & code improvements +* TOTP UX improvements & translation fixes + +### Fixed + +* Fix changing the repeat mode of a task when no value is entered yet +* Fix comment on different task after clicking on a task notification +* Fix CTA spacings +* Fix date parsing parsing words with weekdays in them (#607) +* fix(deps): update dependency marked to v3.0.1 (#677) +* fix(deps): update dependency marked to v3.0.2 (#682) +* Fix error property already defined as a function +* Fix flickering pre-loaded search results when focusing the search input +* Fix Gantt layout overflowsing on mobile +* Fix gantt months being wrong +* Fix git push remote to update crowdin translations +* Fix global mutation of has tasks state +* Fix header layout for long list titles +* Fix highlight.js in editor +* Fix home page tests +* Fix keyboard shortcuts not working on the task detail page +* Fix label changes appearing to be saved immediately when editing them +* Fix labels list in saved filter spacing +* Fix lint +* Fix list archived notification mobile layout +* Fix list settings not being available when list backgrounds are disabled +* Fix lists showing up multiple times in history +* Fix llama background url +* Fix loading a list when it was already partially saved in vuex +* Fix loading & disabled state on inputs when creating a new task +* Fix loading labels when editing a saved filter +* Fix menu styles +* Fix missing background for tasks on a shared list with a background +* Fix multiselect search padding +* Fix new lists created with quick actions not showing up in the menu +* fix: non unique ids (#672) +* Fix not reloading tasks of a saved filter after editing it +* Fix not updating list name in store when changing it +* Fix other values getting pushed away when creating a new one through multiselect +* Fix padding for kanban cards +* Fix parsing dates on the last day of the month +* Fix populating task details ater updating the description +* Fix quick actions not opening +* Fix quick actions not working when nonexisting lists where left over in history +* Fix redirecting to /login for some routes +* Fix removing a namespace from state after it was deleted +* Fix resetting date filters from upcoming after viewing a task detail page (popup) +* Fix sass division +* Fix saving showing archived setting +* Fix selecting a single value from multiselect +* Fix sending openid scopes when authenticating +* Fix sending the user back to the list view they came from when opening a task in detail view +* Fix setting a task as favorite button +* Fix setting delete button for newly created task comments +* Fix setting filters for reminders +* Fix setting secret for updating translations +* Fix setting task favorite status in test fixtures +* Fix showing an editor save button in cases where it wasn't required +* Fix showing edit buttons when the user does not have the rights to use them +* Fix showing import tasks cta when tasks are loading +* Fix some translation strings +* Fix sorting labels +* Fix spacing for task detail view in lists with a background +* Fix table headers wrapping in table view +* Fix table text alignment in task detail page +* Fix table view scrolling on mobile +* Fix test for saving a task description +* Fix tests failing on thursdays +* Fix token in storage not getting renewed +* Fix translating dates +* Fix usage of / in sass +* Fix user name and avatar alignment in navbar +* Fix users not removed from the list in settings when unshared +* Fix user test fixtures +* fix: vuex mutation violation from draggable (#674) + +### Dependency Updates + +* chore(deps): update dependency @4tw/cypress-drag-drop to v1.8.1 (#693) +* chore(deps): update dependency autoprefixer to v10.3.3 (#684) +* chore(deps): update dependency autoprefixer to v10.3.4 (#697) +* chore(deps): update dependency axios to v0.21.2 (#698) +* chore(deps): update dependency axios to v0.21.3 (#700) +* chore(deps): update dependency cypress to v8.3.1 (#689) +* chore(deps): update dependency esbuild to v0.12.23 (#683) +* chore(deps): update dependency esbuild to v0.12.24 (#688) +* chore(deps): update dependency esbuild to v0.12.25 (#696) +* chore(deps): update dependency eslint-plugin-vue to v7.17.0 (#686) +* chore(deps): update dependency jest to v27.1.0 (#687) +* chore(deps): update dependency sass to v1.38.1 (#679) +* chore(deps): update dependency sass to v1.38.2 (#690) +* chore(deps): update dependency sass to v1.39.0 (#695) +* chore(deps): update dependency typescript to v4.4.2 (#685) +* chore(deps): update dependency vite-plugin-pwa to v0.11.2 (#681) +* chore(deps): update dependency vite to v2.5.1 (#680) +* chore(deps): update dependency vite to v2.5.2 (#692) +* chore(deps): update dependency vite to v2.5.3 (#694) +* chore(deps): update typescript-eslint monorepo to v4.29.3 (#676) +* chore(deps): update typescript-eslint monorepo to v4.30.0 (#691) +* Update dependency autoprefixer to v10.3.2 (#670) +* Update dependency browserslist to v4.16.7 (#634) +* Update dependency browserslist to v4.16.8 (#664) +* Update dependency browserslist to v4.17.0 (#701) +* Update dependency bulma to v0.9.3 (#554) +* Update dependency cypress-file-upload to v5.0.8 (#556) +* Update dependency cypress to v7.3.0 (#507) +* Update dependency cypress to v7.4.0 (#517) +* Update dependency cypress to v7.5.0 (#541) +* Update dependency cypress to v7.6.0 (#561) +* Update dependency cypress to v7.7.0 (#577) +* Update dependency cypress to v8.1.0 (#624) +* Update dependency cypress to v8.2.0 (#637) +* Update dependency cypress to v8.3.0 (#660) +* Update dependency cypress to v8 (#601) +* Update dependency date-fns to v2.22.0 (#523) +* Update dependency date-fns to v2.22.1 (#524) +* Update dependency date-fns to v2.23.0 (#604) +* Update dependency dompurify to v2.2.9 (#529) +* Update dependency dompurify to v2.3.0 (#573) +* Update dependency dompurify to v2.3.1 (#655) +* Update dependency esbuild to v0.12.15 (#610) +* Update dependency esbuild to v0.12.16 (#614) +* Update dependency esbuild to v0.12.17 (#623) +* Update dependency esbuild to v0.12.18 (#638) +* Update dependency esbuild to v0.12.19 (#643) +* Update dependency esbuild to v0.12.20 (#654) +* Update dependency esbuild to v0.12.21 (#666) +* Update dependency esbuild to v0.12.22 (#668) +* Update dependency eslint-plugin-vue to v7.10.0 (#525) +* Update dependency eslint-plugin-vue to v7.11.0 (#547) +* Update dependency eslint-plugin-vue to v7.11.1 (#548) +* Update dependency eslint-plugin-vue to v7.12.1 (#565) +* Update dependency eslint-plugin-vue to v7.13.0 (#574) +* Update dependency eslint-plugin-vue to v7.14.0 (#597) +* Update dependency eslint-plugin-vue to v7.15.0 (#625) +* Update dependency eslint-plugin-vue to v7.15.1 (#633) +* Update dependency eslint-plugin-vue to v7.16.0 (#648) +* Update dependency eslint to v7.27.0 (#514) +* Update dependency eslint to v7.28.0 (#539) +* Update dependency eslint to v7.29.0 (#555) +* Update dependency eslint to v7.30.0 (#571) +* Update dependency eslint to v7.31.0 (#596) +* Update dependency eslint to v7.32.0 (#627) +* Update dependency highlight.js to v11.0.1 (#538) +* Update dependency highlight.js to v11.1.0 (#582) +* Update dependency highlight.js to v11.2.0 (#630) +* Update dependency highlight.js to v11 (#527) +* Update dependency jest to v27.0.3 (#526) +* Update dependency jest to v27.0.4 (#535) +* Update dependency jest to v27.0.5 (#558) +* Update dependency jest to v27.0.6 (#569) +* Update dependency jest to v27 (#519) +* Update dependency marked to v2.0.4 (#510) +* Update dependency marked to v2.0.5 (#513) +* Update dependency marked to v2.0.6 (#522) +* Update dependency marked to v2.0.7 (#532) +* Update dependency marked to v2.1.0 (#552) +* Update dependency marked to v2.1.1 (#553) +* Update dependency marked to v2.1.2 (#559) +* Update dependency marked to v2.1.3 (#567) +* Update dependency marked to v3 (#657) +* Update dependency @rollup/plugin-commonjs to v19.0.2 (#617) +* Update dependency sass to v1.33.0 (#512) +* Update dependency sass to v1.34.0 (#515) +* Update dependency sass to v1.34.1 (#534) +* Update dependency sass to v1.35.0 (#550) +* Update dependency sass to v1.35.1 (#551) +* Update dependency sass to v1.35.2 (#579) +* Update dependency sass to v1.36.0 (#606) +* Update dependency sass to v1.37.0 (#628) +* Update dependency sass to v1.37.2 (#632) +* Update dependency sass to v1.37.5 (#635) +* Update dependency sass to v1.38.0 (#661) +* Update dependency ts-jest to v27.0.4 (#602) +* Update dependency ts-jest to v27.0.5 (#662) +* Update dependency @types/jest to v27.0.1 (#653) +* Update dependency @types/jest to v27 (#650) +* Update dependency vite-plugin-pwa to v0.10.0 (#644) +* Update dependency vite-plugin-pwa to v0.11.0 (#667) +* Update dependency vite-plugin-pwa to v0.8.2 (#612) +* Update dependency vite-plugin-pwa to v0.9.3 (#629) +* Update dependency vite-plugin-vue2 to v1.7.3 (#613) +* Update dependency vite-plugin-vue2 to v1.8.0 (#646) +* Update dependency vite-plugin-vue2 to v1.8.1 (#656) +* Update dependency vite to v2.4.3 (#611) +* Update dependency vite to v2.4.4 (#619) +* Update dependency vite to v2.5.0 (#658) +* Update dependency vue-advanced-cropper to v1.6.0 (#516) +* Update dependency vue-advanced-cropper to v1.7.0 (#543) +* Update dependency vue-advanced-cropper to v1.8.0 (#641) +* Update dependency vue-advanced-cropper to v1.8.1 (#642) +* Update dependency vue-advanced-cropper to v1.8.2 (#645) +* Update dependency vue-flatpickr-component to v8.1.7 (#572) +* Update dependency vue-i18n to v8.24.5 (#564) +* Update dependency vue-i18n to v8.25.0 (#595) +* Update dependency vue-router to v3.5.2 (#557) +* Update dependency wait-on to v6 (#568) +* Update dependency workbox-cli to v6.1.5 (#609) +* Update Font Awesome (#636) +* Update Node.js (#549) +* Update Node.js to v16.4.1 (#576) +* Update Node.js to v16.4.2 (#578) +* Update typescript-eslint monorepo to v4.28.4 (#600) +* Update typescript-eslint monorepo to v4.28.5 (#618) +* Update typescript-eslint monorepo to v4.29.0 (#631) +* Update typescript-eslint monorepo to v4.29.1 (#647) +* Update typescript-eslint monorepo to v4.29.2 (#659) +* Update vue monorepo to v2.6.13 (#530) +* Update vue monorepo to v2.6.14 (#540) +* Update workbox monorepo to v6.2.0 (#639) +* Update workbox monorepo to v6.2.2 (#640) +* Update workbox monorepo to v6.2.4 (#649) +* User account deletion (#651) +* User Data Export and import (#699) + +## [0.17.0 - 2021-05-14] + +### Added + +* Add a "done" option to kanban buckets (#440) +* Add arm64 builds +* Add button to un-archive a namespace +* Add clearer call to action when no lists are available yet +* Add code highlighting for rendered user input text +* Add github sponsoring +* Add link share password authentication (#466) +* Add names to link shares when creating them (#456) +* Add notifications overview (#414) +* Add option to remove a list background +* Add overdue task reminder notification setting +* Add repeat after one-click intervals +* Add repeat mode setting for tasks +* Add security information to readme +* Add separate manifest template for latest +* Add settings for user search (#458) +* Add success message when modifying buckets +* Add "today" task filter +* Add view image modal for image attachments +* Pagingation for tasks in kanban buckets (#419) +* Persist show archived state +* Play a sound when marking a task as done + +### Fixed + +* Fix adding a label twice when selecting it and pressing enter +* Fix attachment hover +* Fix attachment not being added if the task was not a kanban task +* Fix attachments being added mutliple times +* Fix bucket test fixture when moving tasks between lists test +* Fix button height +* Fix caldav url not containing the api url if the frontend and api are on the same domain +* Fix checking for undefined behaviour when viewing a task +* Fix closing popups when clicking outside of them (#378) +* Fix "create new list" and import buttons on home page +* Fix create new list test +* Fix create new namespace test +* Fix current password id being available twice +* Fix datepicker popup not fully aligned on mobile +* Fix defer due date popup +* Fix delete buttons in forms +* Fix deleting task relations +* Fix editor buttons alignment +* Fix editor placeholder color +* Fix edit task description test +* Fix empty call to actions +* Fix filter container positioning +* Fix filter container positioning in link shares +* Fix flaky test +* Fix flaky test part 2 +* Fix font caching in docker image +* Fix formatting invalid dates +* Fix getting back to the default task view when navigating back from a task modal +* Fix getting back to the kanban board after closing a task popup +* Fix iterating over check boxes and attachment images in the editor rendering +* Fix kanban board slightly scrolling +* Fix kanban height on mobile +* Fix kanban infinite scrolling on chrome +* Fix label spacing +* Fix labels randomly changing color after saving +* Fix list counter in the navigation counting archived lists +* Fix list layout when the list has no background for link shares +* Fix login or register not working when pressing enter +* Fix logout test +* Fix map_hash_max_size for docker images +* Fix misspelling (#415) +* Fix multiselect on mobile +* Fix namespace actions alignment in the menu +* Fix no color selected in the color picket +* Fix notification parsing for team memeber added +* Fix notification styling +* Fix pasting text into task comments or task descriptions +* Fix priority label width in task list +* Fix release pipeline steps +* Fix reloading the task list after changing a filter +* Fix removing dates from a filter +* Fix resetting colors from the color picker +* Fix setting a default color when none was saved +* Fix setting dates in safari +* Fix showing and hiding lists in the menu +* Fix sorting task by due date on task overview +* Fix spacing for lists with no rights to add new tasks +* Fix table names in test fixtures +* Fix task detail view spacings +* Fix task filter toggle button if the list has a background +* Fix task icon size +* Fix task icons on kanban if there were multiple different ones +* Fix task id spacing +* Fix task pagination +* Fix task relation search test +* Fix tasks moving infinitely in gantt chart (#493) +* Fix tasks not disappearing from the kanban board when moving them between lists +* Fix task title heading ux +* Fix team edit test +* Fix team edit test (#382) +* Fix team name in team member added notification +* Fix test +* Fix tests after changing button classes +* Fix text color +* Fix transition between pages +* Fix undo when marking a task as done +* Fix waiting for dependency step when building +* Fix yarn.lock +* Only check for token renew when the user is authenticated +* Only show the llama background for unauthenticated users +* Only use dark shadows for buttons +* Prevent setting a bucket limit < 0 + +### Changed + +* Automatically go back after saving from a popup +* Better wording of new namespace and list buttons +* Bring up the keyboard shortcuts when pressing ? +* Change bucket background color +* Change main branch to main +* Cleanup font caching and requesting +* Don't hide all lists of namespaces when loosing network connectivity +* Don't save the editor text when it is loaded +* Don't show the list color in the list view +* Don't show the "new bucket" button when buckets are still loading +* Focus task detail elements when they show up +* Hide new related tasks form when related tasks exist +* Hide task elements while the task is loading +* Hide the bucket limit input when clicked away +* Hide the login form if no api url is configured +* Improve consistency of the layout (#386) +* Inline mutliselect search input for multiple elements +* Make filter buttons look better on mobile +* Make full task in task list clickable +* Make hidden lists in the menu more compact +* Make message undo button secondary +* Make release steps on master depend on building/testing +* Make sure all arm64 build steps run in parallel +* Make sure all empty pages have a call to action +* Make sure all popups & dropdowns are animated +* Make sure attachements are only added once to the list after uploading + Make sure the attachment list shows up every + time after adding an attachment +* Make sure no cta's are visible while the page is loading +* Make sure the loading spinner is always visible at the end of the page +* Make the button shadow lighter +* Make the icons in the menu light grey +* Make the input full width by default +* Make the scrollbars a lighter grey (#394) +* Make the "upload attachment" button less obvious +* Move all content to cards (#387) +* Move all create views to better looking popups (#383) +* Move buttons to separate component (#380) +* Move list edit/namespace to separate pages and in a menu (#397) +* Move the search input to filters +* Open links to external sites in a new window +* Rearrange task actions +* Reduce quick task edit fields +* Remove the shadow at the "+" button for related tasks +* Rename .noshadow to .has-no-shadow +* Rework attachments list to look great everywhere +* Set user info from api instead of only relying on the info encoded in the jwt token +* Show call to action for task description if there is none +* Show label colors when searching for labels +* Show list if the search result for a task belongs to a different list +* Show "powered by Vikunja" in link shares +* Subscriptions and notifications for namespaces, tasks and lists (#410) +* Switch node-sass to sass +* Switch telegram notifications to matrix +* Update ShowTasks view to sort tasks by ascending (#406) +* Use a lighter grey for comment created dates +* Use buttons more consistently +* Use mousedown instead of click event to close modals +* Work around auto tag for main branch + +### Dependency Updates + +* Pin dependency browserslist to 4.16.6 (#500) +* Pin dependency highlight.js to 10.5.0 (#371) +* Update browserlist and caniuse-lite db +* Update dependency bulma to v0.9.2 (#392) +* Update dependency cypress-file-upload to v5.0.3 (#437) +* Update dependency cypress-file-upload to v5.0.4 (#455) +* Update dependency cypress-file-upload to v5.0.5 (#461) +* Update dependency cypress-file-upload to v5.0.6 (#481) +* Update dependency cypress-file-upload to v5.0.7 (#498) +* Update dependency cypress-file-upload to v5 (#379) +* Update dependency cypress to v6.3.0 (#381) +* Update dependency cypress to v6.4.0 (#399) +* Update dependency cypress to v6.5.0 (#412) +* Update dependency cypress to v6.6.0 (#421) +* Update dependency cypress to v6.7.1 (#430) +* Update dependency cypress to v6.8.0 (#435) +* Update dependency cypress to v6.9.1 (#452) +* Update dependency cypress to v7.1.0 (#472) +* Update dependency cypress to v7.2.0 (#494) +* Update dependency cypress to v7 (#453) +* Update dependency date-fns to v2.17.0 (#403) +* Update dependency date-fns to v2.18.0 (#420) +* Update dependency date-fns to v2.19.0 (#423) +* Update dependency date-fns to v2.20.0 (#459) +* Update dependency date-fns to v2.20.1 (#463) +* Update dependency date-fns to v2.20.2 (#470) +* Update dependency date-fns to v2.20.3 (#473) +* Update dependency date-fns to v2.21.0 (#477) +* Update dependency date-fns to v2.21.1 (#482) +* Update dependency date-fns to v2.21.2 (#499) +* Update dependency date-fns to v2.21.3 (#505) +* Update dependency dompurify to v2.2.7 (#426) +* Update dependency dompurify to v2.2.8 (#496) +* Update dependency eslint-plugin-vue to v7.5.0 (#384) +* Update dependency eslint-plugin-vue to v7.6.0 (#411) +* Update dependency eslint-plugin-vue to v7.7.0 (#422) +* Update dependency eslint-plugin-vue to v7.8.0 (#438) +* Update dependency eslint-plugin-vue to v7.9.0 (#469) +* Update dependency eslint to v7.18.0 (#376) +* Update dependency eslint to v7.19.0 (#398) +* Update dependency eslint to v7.20.0 (#409) +* Update dependency eslint to v7.21.0 (#418) +* Update dependency eslint to v7.22.0 (#427) +* Update dependency eslint to v7.23.0 (#443) +* Update dependency eslint to v7.24.0 (#464) +* Update dependency eslint to v7.25.0 (#490) +* Update dependency eslint to v7.26.0 (#504) +* Update dependency faker to v5.2.0 (#389) +* Update dependency faker to v5.3.1 (#400) +* Update dependency faker to v5.4.0 (#408) +* Update dependency faker to v5.5.0 (#442) +* Update dependency faker to v5.5.1 (#444) +* Update dependency faker to v5.5.2 (#450) +* Update dependency faker to v5.5.3 (#462) +* Update dependency highlight.js to v10.6.0 (#407) +* Update dependency highlight.js to v10.7.1 (#436) +* Update dependency highlight.js to v10.7.2 (#451) +* Update dependency lodash to v4.17.21 (#413) +* Update dependency marked to v1.2.8 (#391) +* Update dependency marked to v1.2.9 (#401) +* Update dependency marked to v2.0.1 (#417) +* Update dependency marked to v2.0.2 (#465) +* Update dependency marked to v2.0.3 (#468) +* Update dependency marked to v2 (#405) +* Update dependency sass-loader to v10.1.1 (#372) +* Update dependency sass-loader to v10.2.0 (#506) +* Update dependency sass to v1.32.13 (#509) +* Update dependency vue-advanced-cropper to v1.3.0 (#404) +* Update dependency vue-advanced-cropper to v1.3.1 (#424) +* Update dependency vue-advanced-cropper to v1.3.2 (#425) +* Update dependency vue-advanced-cropper to v1.3.3 (#439) +* Update dependency vue-advanced-cropper to v1.3.4 (#441) +* Update dependency vue-advanced-cropper to v1 (#393) +* Update dependency vue-advanced-cropper to v1.4.0 (#454) +* Update dependency vue-advanced-cropper to v1.4.1 (#460) +* Update dependency vue-advanced-cropper to v1.5.0 (#471) +* Update dependency vue-advanced-cropper to v1.5.1 (#495) +* Update dependency vue-advanced-cropper to v1.5.2 (#497) +* Update dependency vue-drag-resize to v1.5.1 (#457) +* Update dependency vue-drag-resize to v1.5.2 (#501) +* Update dependency vue-drag-resize to v1.5.4 (#502) +* Update dependency vue-easymde to v1.4.0 (#449) +* Update dependency vue-router to v3.5.0 (#388) +* Update dependency wait-on to v5.3.0 (#434) +* Update Font Awesome (#374) +* Update Font Awesome (#432) +* Update vue monorepo (#390) +* Update vue monorepo to v4.5.11 (#385) +* Update vue monorepo to v4.5.12 (#433) +* Update vue monorepo to v4.5.13 (#503) + ## [0.16.0 - 2021-01-10] ### Added @@ -410,7 +1010,7 @@ The releases aim at the api versions which is why there are missing versions. * Hide totp settings if it is disabled server side * Increase network timeout when building docker image * Make sure the version includes the tag when building docker images -* #PrideMonth +* # PrideMonth * Only renew user token on tab focus events * Redirect the user to login page if the token expired when the tab gets focus again * Remove title length restrictions @@ -445,7 +1045,7 @@ The releases aim at the api versions which is why there are missing versions. ## [0.13] - 2020-05-12 -#### Added +#### Added * Add docker run script to change api url on startup * Add github token for renovate (#89) @@ -790,6 +1390,7 @@ The releases aim at the api versions which is why there are missing versions. * Use email instead of username when resetting a password ### Fixed + * Fixed trying to verify an email when there was none * Fixed loading tasks when the user was not authenticated diff --git a/Dockerfile b/Dockerfile index 1d4b3850c..d73a4fe80 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,10 @@ # Stage 1: Build application -FROM node:13.14.0 AS compile-image +FROM node:16 AS compile-image WORKDIR /build ARG USE_RELEASE=false -ARG RELEASE_VERSION=master +ARG RELEASE_VERSION=main ENV YARN_CACHE_FOLDER .cache/yarn/ COPY . ./ diff --git a/README.md b/README.md index f9911e3be..4b57b4698 100644 --- a/README.md +++ b/README.md @@ -4,32 +4,41 @@ [![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.16.0-brightgreen.svg)](https://dl.vikunja.io) +[![Download](https://img.shields.io/badge/download-v0.18.1-brightgreen.svg)](https://dl.vikunja.io) +[![Translation](https://badges.crowdin.net/vikunja/localized.svg)](https://crowdin.com/project/vikunja) This is the web frontend for Vikunja, written in Vue.js. Take a look at [our roadmap](https://my.vikunja.cloud/share/UrdhKPqumxDXUbYpEGJLSIyNTwAnbBzVlwdDpRbv/auth) (hosted on Vikunja!) for a list of things we're currently working on! +## Security Reports + +If you find any security-related issues you don't want to disclose publicly, please use [the contact information on our website](https://vikunja.io/contact/#security). + ## Docker There is a [docker image available](https://hub.docker.com/r/vikunja/api) with support for http/2 and aggressive caching enabled. ## Project setup -``` + +```shell yarn install ``` ### Compiles and hot-reloads for development -``` + +```shell yarn run serve ``` ### Compiles and minifies for production -``` + +```shell yarn run build ``` ### Lints and fixes files -``` + +```shell yarn run lint ``` diff --git a/babel.config.js b/babel.config.js index ba179669a..d39e57b42 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,5 +1,5 @@ module.exports = { presets: [ - '@vue/app' - ] + '@vue/app', + ], } diff --git a/cypress.json b/cypress.json index 9497a81ea..404249f38 100644 --- a/cypress.json +++ b/cypress.json @@ -1,8 +1,11 @@ { - "baseUrl": "http://localhost:8080", + "baseUrl": "http://localhost:5000", "env": { "API_URL": "http://localhost:3456/api/v1", "TEST_SECRET": "testingS3cr3et" }, - "video": false + "video": false, + "retries": { + "runMode": 2 + } } diff --git a/cypress/factories/label_task.js b/cypress/factories/label_task.js index 069358ef1..65cd47058 100644 --- a/cypress/factories/label_task.js +++ b/cypress/factories/label_task.js @@ -2,7 +2,7 @@ import {Factory} from '../support/factory' import {formatISO} from 'date-fns' export class LabelTaskFactory extends Factory { - static table = 'label_task' + static table = 'label_tasks' static factory() { const now = new Date() diff --git a/cypress/factories/link_sharing.js b/cypress/factories/link_sharing.js index 66102b1b9..e2c01dd07 100644 --- a/cypress/factories/link_sharing.js +++ b/cypress/factories/link_sharing.js @@ -3,7 +3,7 @@ import {formatISO} from "date-fns" import faker from 'faker' export class LinkShareFactory extends Factory { - static table = 'link_sharing' + static table = 'link_shares' static factory() { const now = new Date() diff --git a/cypress/factories/list.js b/cypress/factories/list.js index 784d63b50..f93cdba4c 100644 --- a/cypress/factories/list.js +++ b/cypress/factories/list.js @@ -3,7 +3,7 @@ import {formatISO} from "date-fns" import faker from 'faker' export class ListFactory extends Factory { - static table = 'list' + static table = 'lists' static factory() { const now = new Date() diff --git a/cypress/factories/task.js b/cypress/factories/task.js index 8e0d7b59d..6fa8d5b67 100644 --- a/cypress/factories/task.js +++ b/cypress/factories/task.js @@ -14,7 +14,6 @@ export class TaskFactory extends Factory { done: false, list_id: 1, created_by_id: 1, - is_favorite: false, index: '{increment}', created: formatISO(now), updated: formatISO(now) diff --git a/cypress/factories/user.js b/cypress/factories/user.js index ca8bb896e..37fcaaab4 100644 --- a/cypress/factories/user.js +++ b/cypress/factories/user.js @@ -13,7 +13,7 @@ export class UserFactory extends Factory { id: '{increment}', username: faker.lorem.word(10) + faker.random.uuid(), password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.', // 1234 - is_active: true, + status: 0, created: formatISO(now), updated: formatISO(now) } diff --git a/cypress/factories/users_list.js b/cypress/factories/users_list.js index e583cbed7..5eecd2d76 100644 --- a/cypress/factories/users_list.js +++ b/cypress/factories/users_list.js @@ -2,7 +2,7 @@ import {Factory} from '../support/factory' import {formatISO} from "date-fns" export class UserListFactory extends Factory { - static table = 'users_list' + static table = 'users_lists' static factory() { const now = new Date() diff --git a/cypress/integration/list/list.spec.js b/cypress/integration/list/list.spec.js index 28b6b5091..8242984e6 100644 --- a/cypress/integration/list/list.spec.js +++ b/cypress/integration/list/list.spec.js @@ -10,10 +10,12 @@ import {BucketFactory} from '../../factories/bucket' import '../../support/authenticateUser' describe('Lists', () => { + let lists + beforeEach(() => { UserFactory.create(1) NamespaceFactory.create(1) - const lists = ListFactory.create(1, { + lists = ListFactory.create(1, { title: 'First List' }) TaskFactory.truncate() @@ -54,6 +56,64 @@ describe('Lists', () => { .should('contain', '/lists/1/kanban') }) + it('Should rename the list in all places', () => { + const tasks = TaskFactory.create(5, { + id: '{increment}', + list_id: 1, + }) + const newListName = 'New list name' + + cy.visit('/lists/1') + cy.get('.list-title h1') + .should('contain', 'First List') + + cy.get('.namespace-container .menu.namespaces-lists .more-container .menu-list li:first-child .dropdown .dropdown-trigger') + .click() + cy.get('.namespace-container .menu.namespaces-lists .more-container .menu-list li:first-child .dropdown .dropdown-content') + .contains('Edit') + .click() + cy.get('#title') + .type(`{selectall}${newListName}`) + cy.get('footer.modal-card-foot .button') + .contains('Save') + .click() + + cy.get('.global-notification') + .should('contain', 'Success') + cy.get('.list-title h1') + .should('contain', newListName) + .should('not.contain', lists[0].title) + cy.get('.namespace-container .menu.namespaces-lists .more-container .menu-list li:first-child') + .should('contain', newListName) + .should('not.contain', lists[0].title) + cy.visit('/') + cy.get('.card-content .tasks') + .should('contain', newListName) + .should('not.contain', lists[0].title) + }) + + it('Should remove a list', () => { + cy.visit(`/lists/${lists[0].id}`) + + cy.get('.namespace-container .menu.namespaces-lists .more-container .menu-list li:first-child .dropdown .dropdown-trigger') + .click() + cy.get('.namespace-container .menu.namespaces-lists .more-container .menu-list li:first-child .dropdown .dropdown-content') + .contains('Delete') + .click() + cy.url() + .should('contain', '/settings/delete') + cy.get('.modal-mask .modal-container .modal-content .actions a.button') + .contains('Do it') + .click() + + cy.get('.global-notification') + .should('contain', 'Success') + cy.get('.namespace-container .menu.namespaces-lists .more-container .menu-list') + .should('not.contain', lists[0].title) + cy.location('pathname') + .should('equal', '/') + }) + describe('List View', () => { it('Should be an empty list', () => { cy.visit('/lists/1') @@ -102,6 +162,44 @@ describe('Lists', () => { cy.get('input.input[placeholder="Add a new task..."') .should('not.exist') }) + + it('Should only show the color of a list in the navigation and not in the list view', () => { + const lists = ListFactory.create(1, { + hex_color: '00db60', + }) + TaskFactory.create(10, { + list_id: lists[0].id, + }) + cy.visit(`/lists/${lists[0].id}/`) + + cy.get('.menu-list li .list-menu-link .color-bubble') + .should('have.css', 'background-color', 'rgb(0, 219, 96)') + cy.get('.tasks-container .tasks .color-bubble') + .should('not.exist') + }) + + it('Should paginate for > 50 tasks', () => { + const tasks = TaskFactory.create(100, { + id: '{increment}', + title: i => `task${i}`, + list_id: 1, + }) + cy.visit('/lists/1/list') + + cy.get('.tasks-container .tasks') + .should('contain', tasks[99].title) + + cy.get('.card-content .pagination .pagination-link') + .contains('2') + .click() + + cy.url() + .should('contain', '?page=2') + cy.get('.tasks-container .tasks') + .should('contain', tasks[1].title) + cy.get('.tasks-container .tasks') + .should('not.contain', tasks[99].title) + }) }) describe('Table View', () => { @@ -155,20 +253,24 @@ describe('Lists', () => { describe('Gantt View', () => { it('Hides tasks with no dates', () => { - TaskFactory.create(1) + const tasks = TaskFactory.create(1) cy.visit('/lists/1/gantt') cy.get('.gantt-chart-container .gantt-chart .tasks') - .should('be.empty') + .should('not.contain', tasks[0].title) }) it('Shows tasks from the current and next month', () => { const now = new Date() + const nextMonth = now + nextMonth.setDate(1) + nextMonth.setMonth(now.getMonth() + 1) + cy.visit('/lists/1/gantt') cy.get('.gantt-chart-container .gantt-chart .months') .should('contain', format(now, 'MMMM')) - .should('contain', format(now.setMonth(now.getMonth() + 1), 'MMMM')) + .should('contain', format(nextMonth, 'MMMM')) }) it('Shows tasks with dates', () => { @@ -286,7 +388,7 @@ describe('Lists', () => { .first() .click() cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item') - .contains('Limit: Not set') + .contains('Limit: Not Set') .click() cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item .field input.input') .first() @@ -334,26 +436,23 @@ describe('Lists', () => { .should('exist') }) + it('Can drag tasks around', () => { + const tasks = TaskFactory.create(2, { + list_id: 1, + bucket_id: 1, + }) + cy.visit('/lists/1/kanban') - // The following test does not work. It seems like vue-smooth-dnd does not use either mousemove or dragstart - // (not sure why this actually works at all?) and as I'm planning to swap that out for vuedraggable/sortable.js - // anyway, I figured it wouldn't be worth the hassle right now. - -// it('Can drag tasks around', () => { -// const tasks = TaskFactory.create(2, { -// list_id: 1, -// bucket_id: 1, -// }) -// cy.visit('/lists/1/kanban') -// -// cy.get('.kanban .bucket .tasks .task') -// .contains(tasks[0].title) -// .first() -// .drag('.kanban .bucket:nth-child(2) .tasks .smooth-dnd-container.vertical') -// .trigger('mousedown', {which: 1}) -// .trigger('mousemove', {clientX: 500, clientY: 0}) -// .trigger('mouseup', {force: true}) -// }) + cy.get('.kanban .bucket .tasks .task') + .contains(tasks[0].title) + .first() + .drag('.kanban .bucket:nth-child(2) .tasks .dropper div') + + cy.get('.kanban .bucket:nth-child(2) .tasks') + .should('contain', tasks[0].title) + cy.get('.kanban .bucket:nth-child(1) .tasks') + .should('not.contain', tasks[0].title) + }) it('Should navigate to the task when the task card is clicked', () => { const tasks = TaskFactory.create(5, { @@ -363,7 +462,7 @@ describe('Lists', () => { }) cy.visit('/lists/1/kanban') - cy.getAttached('.kanban .bucket .tasks .task') + cy.getSettled('.kanban .bucket .tasks .task') .contains(tasks[0].title) .should('be.visible') .click() @@ -371,5 +470,72 @@ describe('Lists', () => { cy.url() .should('contain', `/tasks/${tasks[0].id}`) }) + + it('Should remove a task from the kanban board when moving it to another list', () => { + const lists = ListFactory.create(2) + BucketFactory.create(2, { + list_id: '{increment}', + }) + const tasks = TaskFactory.create(5, { + id: '{increment}', + list_id: 1, + bucket_id: 1, + }) + const task = tasks[0] + cy.visit('/lists/1/kanban') + + cy.getSettled('.kanban .bucket .tasks .task') + .contains(task.title) + .should('be.visible') + .click() + + cy.get('.task-view .action-buttons .button') + .contains('Move task') + .click() + cy.get('.task-view .content.details .field .multiselect.control .input-wrapper input') + .type(`${lists[1].title}{enter}`) + // The requests happen with a 200ms timeout. Because of that, the results are not yet there when cypress + // presses enter and we can't simulate pressing on enter to select the item. + cy.get('.task-view .content.details .field .multiselect.control .search-results') + .children() + .first() + .click() + + cy.get('.global-notification') + .should('contain', 'Success') + cy.go('back') + cy.get('.kanban .bucket') + .should('not.contain', task.title) + }) + }) + + describe('List history', () => { + it('should show a list history on the home page', () => { + const lists = ListFactory.create(6) + + cy.visit('/') + cy.get('h3') + .contains('Last viewed') + .should('not.exist') + + cy.visit(`/lists/${lists[0].id}`) + cy.visit(`/lists/${lists[1].id}`) + cy.visit(`/lists/${lists[2].id}`) + cy.visit(`/lists/${lists[3].id}`) + cy.visit(`/lists/${lists[4].id}`) + cy.visit(`/lists/${lists[5].id}`) + + cy.visit('/') + cy.get('h3') + .contains('Last viewed') + .should('exist') + cy.get('.list-cards-wrapper-2-rows') + .should('not.contain', lists[0].title) + .should('contain', lists[1].title) + .should('contain', lists[2].title) + .should('contain', lists[3].title) + .should('contain', lists[4].title) + .should('contain', lists[5].title) + }) }) }) diff --git a/cypress/integration/list/namespaces.spec.js b/cypress/integration/list/namespaces.spec.js index 9dba7b431..e8c15443e 100644 --- a/cypress/integration/list/namespaces.spec.js +++ b/cypress/integration/list/namespaces.spec.js @@ -20,20 +20,126 @@ describe('Namepaces', () => { }) it('Should create a new Namespace', () => { + const newNamespaceTitle = 'New Namespace' + cy.visit('/namespaces') cy.get('a.button') - .contains('Create namespace') + .contains('Create a new namespace') .click() + cy.url() .should('contain', '/namespaces/new') cy.get('.card-header-title') .should('contain', 'Create a new namespace') cy.get('input.input') - .type('New Namespace') + .type(newNamespaceTitle) cy.get('.button') .contains('Create') .click() + + cy.get('.global-notification') + .should('contain', 'Success') + cy.get('.namespace-container') + .should('contain', newNamespaceTitle) cy.url() .should('contain', '/namespaces') }) + + it('Should rename the namespace all places', () => { + const newNamespaces = NamespaceFactory.create(5) + const newNamespaceName = 'New namespace name' + + cy.visit('/namespaces') + + cy.get(`.namespace-container .menu.namespaces-lists .namespace-title:contains(${newNamespaces[0].title}) .dropdown .dropdown-trigger`) + .click() + cy.get('.namespace-container .menu.namespaces-lists .namespace-title .dropdown .dropdown-content') + .contains('Edit') + .click() + cy.url() + .should('contain', '/settings/edit') + cy.get('#namespacetext') + .invoke('val') + .should('equal', newNamespaces[0].title) // wait until the namespace data is loaded + cy.get('#namespacetext') + .type(`{selectall}${newNamespaceName}`) + cy.get('footer.modal-card-foot .button') + .contains('Save') + .click() + + cy.get('.global-notification') + .should('contain', 'Success') + cy.get('.namespace-container .menu.namespaces-lists') + .should('contain', newNamespaceName) + .should('not.contain', newNamespaces[0].title) + cy.get('.content.namespaces-list') + .should('contain', newNamespaceName) + .should('not.contain', newNamespaces[0].title) + }) + + it('Should remove a namespace when deleting it', () => { + const newNamespaces = NamespaceFactory.create(5) + + cy.visit('/') + + cy.get(`.namespace-container .menu.namespaces-lists .namespace-title:contains(${newNamespaces[0].title}) .dropdown .dropdown-trigger`) + .click() + cy.get('.namespace-container .menu.namespaces-lists .namespace-title .dropdown .dropdown-content') + .contains('Delete') + .click() + cy.url() + .should('contain', '/settings/delete') + cy.get('.modal-mask .modal-container .modal-content .actions a.button') + .contains('Do it') + .click() + + cy.get('.global-notification') + .should('contain', 'Success') + cy.get('.namespace-container .menu.namespaces-lists') + .should('not.contain', newNamespaces[0].title) + }) + + it('Should not show archived lists & namespaces if the filter is not checked', () => { + const n = NamespaceFactory.create(1, { + id: 2, + is_archived: true, + }, false) + ListFactory.create(1, { + id: 2, + namespace_id: n[0].id, + }, false) + + ListFactory.create(1, { + id: 3, + is_archived: true, + }, false) + + // Initial + cy.visit('/namespaces') + cy.get('.namespaces-list .namespace') + .should('not.contain', 'Archived') + + // Show archived + cy.get('.namespaces-list .fancycheckbox.show-archived-check label.check span') + .should('be.visible') + .click() + cy.get('.namespaces-list .fancycheckbox.show-archived-check input') + .should('be.checked') + cy.get('.namespaces-list .namespace') + .should('contain', 'Archived') + + // Don't show archived + cy.get('.namespaces-list .fancycheckbox.show-archived-check label.check span') + .should('be.visible') + .click() + cy.get('.namespaces-list .fancycheckbox.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') + .should('not.be.checked') + cy.get('.namespaces-list .namespace') + .should('not.contain', 'Archived') + }) }) diff --git a/cypress/integration/misc/home.spec.js b/cypress/integration/misc/home.spec.js new file mode 100644 index 000000000..82cbeed22 --- /dev/null +++ b/cypress/integration/misc/home.spec.js @@ -0,0 +1,35 @@ +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') + }) +}) \ No newline at end of file diff --git a/cypress/integration/sharing/team.spec.js b/cypress/integration/sharing/team.spec.js index 094556355..7c48a59aa 100644 --- a/cypress/integration/sharing/team.spec.js +++ b/cypress/integration/sharing/team.spec.js @@ -11,7 +11,7 @@ describe('Team', () => { const newTeamName = 'New Team' cy.get('a.button') - .contains('New Team') + .contains('Create a new team') .click() cy.url() .should('contain', '/teams/new') @@ -113,7 +113,7 @@ describe('Team', () => { cy.get('.card') .contains('Team Members') .get('.card-content .button') - .contains('Add To Team') + .contains('Add to team') .click() cy.get('table.table td') diff --git a/cypress/integration/task/task.spec.js b/cypress/integration/task/task.spec.js index 34967d10e..98664e183 100644 --- a/cypress/integration/task/task.spec.js +++ b/cypress/integration/task/task.spec.js @@ -11,6 +11,7 @@ import '../../support/authenticateUser' import {TaskAssigneeFactory} from '../../factories/task_assignee' import {LabelFactory} from '../../factories/labels' import {LabelTaskFactory} from '../../factories/label_task' +import {BucketFactory} from '../../factories/bucket' describe('Task', () => { let namespaces @@ -26,7 +27,7 @@ describe('Task', () => { it('Should be created new', () => { cy.visit('/lists/1/list') - cy.get('input.input[placeholder="Add a new task..."') + cy.get('input.input[placeholder="Add a new task…"') .type('New Task') cy.get('.button') .contains('Add') @@ -42,7 +43,7 @@ describe('Task', () => { cy.visit('/lists/1/list') cy.get('.list-is-empty-notice') .should('not.exist') - cy.get('input.input[placeholder="Add a new task..."') + cy.get('input.input[placeholder="Add a new task…"') .type('New Task') cy.get('.button') .contains('Add') @@ -112,9 +113,10 @@ describe('Task', () => { cy.visit(`/tasks/${tasks[0].id}`) cy.get('.task-view .heading .is-done') - .should('exist') + .should('be.visible') .should('contain', 'Done') cy.get('.task-view .action-buttons p.created') + .should('be.visible') .should('contain', 'Done') }) @@ -167,7 +169,7 @@ describe('Task', () => { 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') - .contains('Done') + .contains('Save') .click() cy.get('.task-view .details.content.description h3 span.is-small.has-text-success') @@ -182,9 +184,11 @@ describe('Task', () => { cy.visit(`/tasks/${tasks[0].id}`) cy.get('.task-view .comments .media.comment .editor .vue-easymde .EasyMDEContainer .CodeMirror-scroll') + .should('be.visible') .type('{selectall}New Comment') cy.get('.task-view .comments .media.comment .button:not([disabled])') .contains('Comment') + .should('be.visible') .click() cy.get('.task-view .comments .media.comment .editor') @@ -195,6 +199,9 @@ describe('Task', () => { it('Can move a task to another list', () => { const lists = ListFactory.create(2) + BucketFactory.create(2, { + list_id: '{increment}' + }) const tasks = TaskFactory.create(1, { id: 1, list_id: lists[0].id, @@ -228,6 +235,7 @@ describe('Task', () => { cy.visit(`/tasks/${tasks[0].id}`) cy.get('.task-view .action-buttons .button') + .should('be.visible') .contains('Delete task') .click() cy.get('.modal-mask .modal-container .modal-content .header') @@ -310,6 +318,7 @@ describe('Task', () => { cy.get('.task-view .action-buttons .button') .contains('Add labels') + .should('be.visible') .click() cy.get('.task-view .details.labels-list .multiselect input') .type(newLabelText) @@ -365,6 +374,7 @@ describe('Task', () => { cy.visit(`/tasks/${tasks[0].id}`) cy.get('.task-view .details.labels-list .multiselect .input-wrapper') + .should('be.visible') .should('contain', labels[0].title) cy.get('.task-view .details.labels-list .multiselect .input-wrapper') .children() diff --git a/cypress/integration/user/login.spec.js b/cypress/integration/user/login.spec.js index d1cde64ef..ce6086ce0 100644 --- a/cypress/integration/user/login.spec.js +++ b/cypress/integration/user/login.spec.js @@ -34,6 +34,7 @@ context('Login', () => { cy.get('input[id=password]').type(fixture.password) cy.get('.button').contains('Login').click() cy.url().should('include', '/') + cy.clock(1625656161057) // 13:00 cy.get('h2').should('contain', `Hi ${fixture.username}!`) }) diff --git a/cypress/integration/user/registration.spec.js b/cypress/integration/user/registration.spec.js index 37c238e34..3e7cf1f54 100644 --- a/cypress/integration/user/registration.spec.js +++ b/cypress/integration/user/registration.spec.js @@ -28,6 +28,7 @@ context('Registration', () => { cy.get('#password2').type(fixture.password) cy.get('#register-submit').click() cy.url().should('include', '/') + cy.clock(1625656161057) // 13:00 cy.get('h2').should('contain', `Hi ${fixture.username}!`) }) diff --git a/cypress/integration/user/settings.spec.js b/cypress/integration/user/settings.spec.js index c2d20d087..36467bae7 100644 --- a/cypress/integration/user/settings.spec.js +++ b/cypress/integration/user/settings.spec.js @@ -36,7 +36,6 @@ describe('User Settings', () => { .contains('Save') .click() - cy.wait(3000) // Wait for the request to finish cy.get('.global-notification') .should('contain', 'Success') cy.get('.navbar .user .username') diff --git a/cypress/support/commands.js b/cypress/support/commands.js index ccdc6f366..4bc18b684 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -1,17 +1,33 @@ /** - * getAttached(selector) - * getAttached(selectorFn) + * Recursively gets an element, returning only after it's determined to be attached to the DOM for good. * - * Waits until the selector finds an attached element, then yields it (wrapped). - * selectorFn, if provided, is passed $(document). Don't use cy methods inside selectorFn. - * - * Source: https://github.com/cypress-io/cypress/issues/5743#issuecomment-650421731 + * Source: https://github.com/cypress-io/cypress/issues/7306#issuecomment-850621378 */ -Cypress.Commands.add('getAttached', selector => { - const getElement = typeof selector === 'function' ? selector : $d => $d.find(selector); - let $el = null; - return cy.document().should($d => { - $el = getElement(Cypress.$($d)); - expect(Cypress.dom.isDetached($el)).to.be.false; - }).then(() => cy.wrap($el)); -}); +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) + }) + }) +}) diff --git a/cypress/support/factory.js b/cypress/support/factory.js index 7dc1f7189..0c50bf8fc 100644 --- a/cypress/support/factory.js +++ b/cypress/support/factory.js @@ -21,12 +21,16 @@ export class Factory { * @param override * @returns {[]} */ - static create(count = 1, override = {}) { + static create(count = 1, override = {}, truncate = true) { const data = [] for (let i = 1; i <= count; i++) { const entry = merge(this.factory(), override) for (const e in entry) { + if(typeof entry[e] === 'function') { + entry[e] = entry[e](i) + continue + } if (entry[e] === '{increment}') { entry[e] = i } @@ -34,7 +38,7 @@ export class Factory { data.push(entry) } - seed(this.table, data) + seed(this.table, data, truncate) return data } diff --git a/cypress/support/index.js b/cypress/support/index.js index 74c1400d7..22ec961fa 100644 --- a/cypress/support/index.js +++ b/cypress/support/index.js @@ -1,3 +1,4 @@ import './commands' import 'cypress-file-upload' +import '@4tw/cypress-drag-drop' diff --git a/cypress/support/seed.js b/cypress/support/seed.js index acb1b2df4..d86152e2b 100644 --- a/cypress/support/seed.js +++ b/cypress/support/seed.js @@ -8,14 +8,14 @@ * @param table * @param data */ -export function seed(table, data = {}) { - if(data === null) { +export function seed(table, data = {}, truncate = true) { + if (data === null) { data = [] } cy.request({ method: 'PATCH', - url: `${Cypress.env('API_URL')}/test/${table}`, + url: `${Cypress.env('API_URL')}/test/${table}?truncate=${truncate ? 'true' : 'false'}`, headers: { 'Authorization': Cypress.env('TEST_SECRET'), }, diff --git a/docker-manifest-unstable.tmpl b/docker-manifest-unstable.tmpl new file mode 100644 index 000000000..10ded1e16 --- /dev/null +++ b/docker-manifest-unstable.tmpl @@ -0,0 +1,17 @@ +image: vikunja/frontend:unstable +manifests: + - + image: vikunja/frontend:unstable-linux-amd64 + platform: + architecture: amd64 + os: linux + - + image: vikunja/frontend:unstable-linux-arm64 + platform: + architecture: arm64 + os: linux + - + image: vikunja/frontend:unstable-linux-arm + platform: + architecture: arm + os: linux diff --git a/index.html b/index.html new file mode 100644 index 000000000..016ea547d --- /dev/null +++ b/index.html @@ -0,0 +1,37 @@ + + + + Vikunja + + + + + + + + + + + + + + + + + + + +
+ + + + diff --git a/package.json b/package.json index c71fa63c6..be80935be 100644 --- a/package.json +++ b/package.json @@ -3,60 +3,76 @@ "version": "0.10.0", "private": true, "scripts": { - "serve": "vue-cli-service serve", - "serve:dist": "node scripts/serve-dist.js", - "build": "vue-cli-service build --modern", - "build:report": "vue-cli-service build --report", - "lint": "vue-cli-service lint --ignore-pattern '*.test.*'", + "serve": "vite", + "serve:dist-dev": "node scripts/serve-dist.js", + "serve:dist": "vite preview", + "build": "vite build && workbox copyLibraries dist/", + "build:dev": "vite build -m development --outDir dist-dev/", + "lint": "eslint --ignore-pattern '*.test.*' ./src --ext .vue,.js,.ts", "cypress:open": "cypress open", "test:unit": "jest", "test:frontend": "cypress run" }, "dependencies": { - "bulma": "0.9.2", + "browserslist": "4.17.0", + "bulma": "0.9.3", "camel-case": "4.1.2", "copy-to-clipboard": "3.3.1", - "date-fns": "2.17.0", - "dompurify": "2.2.6", - "highlight.js": "10.6.0", - "lodash": "4.17.20", - "marked": "2.0.0", + "date-fns": "2.23.0", + "dompurify": "2.3.1", + "highlight.js": "11.2.0", + "is-touch-device": "1.0.1", + "lodash": "4.17.21", + "marked": "3.0.3", "register-service-worker": "1.7.2", "snake-case": "3.0.4", "verte": "0.0.12", - "vue": "2.6.12", - "vue-advanced-cropper": "1.3.0", - "vue-drag-resize": "1.4.2", - "vue-easymde": "1.3.2", + "vue": "2.6.14", + "vue-advanced-cropper": "1.8.2", + "vue-drag-resize": "1.5.4", + "vue-easymde": "1.4.0", + "vue-i18n": "8.25.0", "vue-shortkey": "3.1.7", - "vue-smooth-dnd": "0.8.1", - "vuex": "3.6.2" + "vuedraggable": "2.24.3", + "vuex": "3.6.2", + "workbox-precaching": "6.2.4" }, "devDependencies": { - "@fortawesome/fontawesome-svg-core": "1.2.34", - "@fortawesome/free-regular-svg-icons": "5.15.2", - "@fortawesome/free-solid-svg-icons": "5.15.2", + "@4tw/cypress-drag-drop": "2.0.0", + "@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": "2.0.2", - "@vue/cli": "4.5.11", - "@vue/cli-plugin-babel": "4.5.11", - "@vue/cli-plugin-eslint": "4.5.11", - "@vue/cli-plugin-pwa": "4.5.11", - "@vue/cli-service": "4.5.11", - "axios": "0.21.1", + "@types/jest": "27.0.1", + "@typescript-eslint/eslint-plugin": "4.31.0", + "@typescript-eslint/parser": "4.31.0", + "@vue/babel-preset-app": "4.5.13", + "@vue/eslint-config-typescript": "7.0.0", + "autoprefixer": "10.3.4", + "axios": "0.21.4", "babel-eslint": "10.1.0", - "cypress": "6.4.0", - "cypress-file-upload": "5.0.2", - "eslint": "7.19.0", - "eslint-plugin-vue": "7.5.0", - "faker": "5.3.1", - "jest": "26.6.3", - "node-sass": "5.0.0", - "sass-loader": "10.1.1", - "vue-flatpickr-component": "8.1.6", + "cypress": "8.3.1", + "cypress-file-upload": "5.0.8", + "esbuild": "0.12.25", + "eslint": "7.32.0", + "eslint-plugin-vue": "7.17.0", + "express": "4.17.1", + "faker": "5.5.3", + "jest": "27.1.1", + "rollup-plugin-terser": "7.0.2", + "rollup-plugin-visualizer": "5.5.2", + "sass": "1.39.0", + "ts-jest": "27.0.5", + "typescript": "4.4.2", + "vite": "2.5.6", + "vite-plugin-pwa": "0.11.2", + "vite-plugin-vue2": "1.8.2", + "vue-flatpickr-component": "8.1.7", "vue-notification": "1.3.20", - "vue-router": "3.5.1", - "vue-template-compiler": "2.6.12", - "wait-on": "5.2.1" + "vue-router": "3.5.2", + "vue-template-compiler": "2.6.14", + "wait-on": "6.0.0", + "workbox-cli": "6.2.4" }, "eslintConfig": { "root": true, @@ -65,14 +81,32 @@ }, "extends": [ "plugin:vue/essential", - "eslint:recommended" + "eslint:recommended", + "@vue/typescript" ], - "rules": {}, + "rules": { + "vue/html-quotes": [ + "error", + "double" + ], + "quotes": [ + "error", + "single" + ], + "comma-dangle": [ + "error", + "always-multiline" + ], + "semi": [ + "error", + "never" + ] + }, "parserOptions": { - "parser": "babel-eslint" + "parser": "@typescript-eslint/parser" }, "ignorePatterns": [ - "*.test.js", + "*.test.*", "cypress/*" ] }, @@ -84,12 +118,27 @@ "browserslist": [ "> 1%", "last 2 versions", - "not ie < 11" + "not ie > 0", + "not dead", + "Firefox ESR" ], - "license": "AGPL-3.0-or-later", "jest": { "testPathIgnorePatterns": [ "cypress" + ], + "testEnvironment": "jsdom", + "preset": "ts-jest", + "roots": [ + "/src" + ], + "transform": { + "^.+\\.(js|tsx?)$": "ts-jest" + }, + "moduleFileExtensions": [ + "ts", + "js", + "json" ] - } + }, + "license": "AGPL-3.0-or-later" } diff --git a/ping-weblate.sh b/ping-weblate.sh new file mode 100755 index 000000000..af0e2e019 --- /dev/null +++ b/ping-weblate.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e + +# Shell script because yaml doesn't understand the header is a string literal and not a yaml symbol + +curl -d operation=pull -H "Authorization: Token $WEBLATE_TOKEN" https://hosted.weblate.org/api/projects/vikunja/repository/ +curl -d operation=push -H "Authorization: Token $WEBLATE_TOKEN" https://hosted.weblate.org/api/projects/vikunja/repository/ diff --git a/public/fonts/open-sans-v15-latin-700.ttf b/public/fonts/open-sans-v15-latin-700.ttf deleted file mode 100644 index 11aec0f49..000000000 Binary files a/public/fonts/open-sans-v15-latin-700.ttf and /dev/null differ diff --git a/public/fonts/open-sans-v15-latin-700.woff b/public/fonts/open-sans-v15-latin-700.woff deleted file mode 100644 index 2523e953c..000000000 Binary files a/public/fonts/open-sans-v15-latin-700.woff and /dev/null differ diff --git a/public/fonts/open-sans-v15-latin-700italic.ttf b/public/fonts/open-sans-v15-latin-700italic.ttf deleted file mode 100644 index 10a48d3f9..000000000 Binary files a/public/fonts/open-sans-v15-latin-700italic.ttf and /dev/null differ diff --git a/public/fonts/open-sans-v15-latin-700italic.woff b/public/fonts/open-sans-v15-latin-700italic.woff deleted file mode 100644 index 3838429bd..000000000 Binary files a/public/fonts/open-sans-v15-latin-700italic.woff and /dev/null differ diff --git a/public/fonts/open-sans-v15-latin-italic.ttf b/public/fonts/open-sans-v15-latin-italic.ttf deleted file mode 100644 index fe87c2151..000000000 Binary files a/public/fonts/open-sans-v15-latin-italic.ttf and /dev/null differ diff --git a/public/fonts/open-sans-v15-latin-italic.woff b/public/fonts/open-sans-v15-latin-italic.woff deleted file mode 100644 index cf8b191c0..000000000 Binary files a/public/fonts/open-sans-v15-latin-italic.woff and /dev/null differ diff --git a/public/fonts/open-sans-v15-latin-regular.ttf b/public/fonts/open-sans-v15-latin-regular.ttf deleted file mode 100644 index 9d4e8e526..000000000 Binary files a/public/fonts/open-sans-v15-latin-regular.ttf and /dev/null differ diff --git a/public/fonts/open-sans-v15-latin-regular.woff b/public/fonts/open-sans-v15-latin-regular.woff deleted file mode 100644 index e495e6f01..000000000 Binary files a/public/fonts/open-sans-v15-latin-regular.woff and /dev/null differ diff --git a/public/fonts/quicksand-v7-latin-300.ttf b/public/fonts/quicksand-v7-latin-300.ttf deleted file mode 100644 index 9a61dfd08..000000000 Binary files a/public/fonts/quicksand-v7-latin-300.ttf and /dev/null differ diff --git a/public/fonts/quicksand-v7-latin-300.woff b/public/fonts/quicksand-v7-latin-300.woff deleted file mode 100644 index 4dd750c0a..000000000 Binary files a/public/fonts/quicksand-v7-latin-300.woff and /dev/null differ diff --git a/public/fonts/quicksand-v7-latin-500.ttf b/public/fonts/quicksand-v7-latin-500.ttf deleted file mode 100644 index 900c661eb..000000000 Binary files a/public/fonts/quicksand-v7-latin-500.ttf and /dev/null differ diff --git a/public/fonts/quicksand-v7-latin-500.woff b/public/fonts/quicksand-v7-latin-500.woff deleted file mode 100644 index 6dc18a7ef..000000000 Binary files a/public/fonts/quicksand-v7-latin-500.woff and /dev/null differ diff --git a/public/fonts/quicksand-v7-latin-700.ttf b/public/fonts/quicksand-v7-latin-700.ttf deleted file mode 100644 index d6e84fe91..000000000 Binary files a/public/fonts/quicksand-v7-latin-700.ttf and /dev/null differ diff --git a/public/fonts/quicksand-v7-latin-700.woff b/public/fonts/quicksand-v7-latin-700.woff deleted file mode 100644 index bfbd14fb8..000000000 Binary files a/public/fonts/quicksand-v7-latin-700.woff and /dev/null differ diff --git a/public/fonts/quicksand-v7-latin-regular.ttf b/public/fonts/quicksand-v7-latin-regular.ttf deleted file mode 100644 index 91c1d599a..000000000 Binary files a/public/fonts/quicksand-v7-latin-regular.ttf and /dev/null differ diff --git a/public/fonts/quicksand-v7-latin-regular.woff b/public/fonts/quicksand-v7-latin-regular.woff deleted file mode 100644 index be507ea8c..000000000 Binary files a/public/fonts/quicksand-v7-latin-regular.woff and /dev/null differ diff --git a/public/images/llama-nightscape.svg b/public/images/llama-nightscape.svg index 0321075e8..1dd1a814d 100644 --- a/public/images/llama-nightscape.svg +++ b/public/images/llama-nightscape.svg @@ -16,9 +16,6 @@ height="1066.6667" viewBox="0 0 1066.6667 1066.6667" sodipodi:docname="llama-nightscape.svg" - inkscape:export-filename="/home/konrad/www/vikunja/frontend/public/images/llama-nightscape.png" - inkscape:export-xdpi="172.8" - inkscape:export-ydpi="172.8" inkscape:version="0.92.4 (5da689c313, 2019-01-14)">image/svg+xml - - - Vikunja - - - - - - - - - - - - - - - - - - -
- - - - diff --git a/scripts/serve-dist.js b/scripts/serve-dist.js index 842f634f1..e0303dd7f 100644 --- a/scripts/serve-dist.js +++ b/scripts/serve-dist.js @@ -2,8 +2,8 @@ const path = require('path') const express = require('express') const app = express() -const p = path.join(__dirname, '..', 'dist') -const port = 8080 +const p = path.join(__dirname, '..', 'dist-dev') +const port = 5000 app.use(express.static(p)) // Handle urls set by the frontend diff --git a/src/App.vue b/src/App.vue index e99669116..f11135358 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,6 +1,6 @@