forked from vikunja/frontend
Compare commits
1 Commits
main
...
feature/cr
Author | SHA1 | Date |
---|---|---|
kolaente | acf52fbe16 |
51
.drone.yml
51
.drone.yml
|
@ -341,7 +341,7 @@ trigger:
|
||||||
- "refs/tags/**"
|
- "refs/tags/**"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: docker-unstable
|
- name: docker-latest
|
||||||
image: plugins/docker:linux-arm
|
image: plugins/docker:linux-arm
|
||||||
pull: true
|
pull: true
|
||||||
settings:
|
settings:
|
||||||
|
@ -350,7 +350,7 @@ steps:
|
||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
repo: vikunja/frontend
|
repo: vikunja/frontend
|
||||||
tags: unstable-linux-arm
|
tags: latest-linux-arm
|
||||||
build_args:
|
build_args:
|
||||||
- USE_RELEASE=true
|
- USE_RELEASE=true
|
||||||
- RELEASE_VERSION=unstable
|
- RELEASE_VERSION=unstable
|
||||||
|
@ -380,7 +380,7 @@ steps:
|
||||||
depends_on:
|
depends_on:
|
||||||
- clone
|
- clone
|
||||||
|
|
||||||
- name: docker-unstable-arm64
|
- name: docker-latest-arm64
|
||||||
image: plugins/docker:linux-arm64
|
image: plugins/docker:linux-arm64
|
||||||
pull: true
|
pull: true
|
||||||
settings:
|
settings:
|
||||||
|
@ -389,7 +389,7 @@ steps:
|
||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
repo: vikunja/frontend
|
repo: vikunja/frontend
|
||||||
tags: unstable-linux-arm64
|
tags: latest-linux-arm64
|
||||||
build_args:
|
build_args:
|
||||||
- USE_RELEASE=true
|
- USE_RELEASE=true
|
||||||
- RELEASE_VERSION=unstable
|
- RELEASE_VERSION=unstable
|
||||||
|
@ -438,7 +438,7 @@ trigger:
|
||||||
- "refs/tags/**"
|
- "refs/tags/**"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: docker-unstable
|
- name: docker-latest
|
||||||
image: plugins/docker:linux-amd64
|
image: plugins/docker:linux-amd64
|
||||||
pull: true
|
pull: true
|
||||||
settings:
|
settings:
|
||||||
|
@ -447,7 +447,7 @@ steps:
|
||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
repo: vikunja/frontend
|
repo: vikunja/frontend
|
||||||
tags: unstable-linux-amd64
|
tags: latest-linux-amd64
|
||||||
build_args:
|
build_args:
|
||||||
- USE_RELEASE=true
|
- USE_RELEASE=true
|
||||||
- RELEASE_VERSION=unstable
|
- RELEASE_VERSION=unstable
|
||||||
|
@ -488,12 +488,12 @@ depends_on:
|
||||||
- docker-arm-release
|
- docker-arm-release
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: manifest-unstable
|
- name: manifest-latest
|
||||||
pull: always
|
pull: always
|
||||||
image: plugins/manifest
|
image: plugins/manifest
|
||||||
settings:
|
settings:
|
||||||
tags: unstable
|
tags: latest
|
||||||
spec: docker-manifest-unstable.tmpl
|
spec: docker-manifest-latest.tmpl
|
||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
username:
|
username:
|
||||||
|
@ -516,23 +516,6 @@ steps:
|
||||||
when:
|
when:
|
||||||
ref:
|
ref:
|
||||||
- "refs/tags/**"
|
- "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
|
kind: pipeline
|
||||||
|
@ -572,8 +555,8 @@ kind: pipeline
|
||||||
type: docker
|
type: docker
|
||||||
name: update-translations
|
name: update-translations
|
||||||
|
|
||||||
depends_on:
|
#depends_on:
|
||||||
- build
|
# - build
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
|
@ -594,19 +577,9 @@ steps:
|
||||||
CROWDIN_KEY:
|
CROWDIN_KEY:
|
||||||
from_secret: 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
|
- name: push
|
||||||
pull: always
|
pull: always
|
||||||
image: appleboy/drone-git-push
|
image: appleboy/drone-git-push
|
||||||
depends_on:
|
|
||||||
- move-files
|
|
||||||
settings:
|
settings:
|
||||||
author_email: "frederik@vikunja.io"
|
author_email: "frederik@vikunja.io"
|
||||||
author_name: Frederick [Bot]
|
author_name: Frederick [Bot]
|
||||||
|
@ -620,8 +593,6 @@ steps:
|
||||||
- name: upload
|
- name: upload
|
||||||
pull: always
|
pull: always
|
||||||
image: jonasfranz/crowdin
|
image: jonasfranz/crowdin
|
||||||
depends_on:
|
|
||||||
- clone
|
|
||||||
settings:
|
settings:
|
||||||
files:
|
files:
|
||||||
en.json: src/i18n/lang/en.json
|
en.json: src/i18n/lang/en.json
|
||||||
|
|
346
CHANGELOG.md
346
CHANGELOG.md
|
@ -2,347 +2,13 @@
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
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
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
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.
|
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.
|
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]
|
## [0.17.0 - 2021-05-14]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -482,8 +148,7 @@ The releases aim at the api versions which is why there are missing versions.
|
||||||
* Make sure all arm64 build steps run in parallel
|
* Make sure all arm64 build steps run in parallel
|
||||||
* Make sure all empty pages have a call to action
|
* Make sure all empty pages have a call to action
|
||||||
* Make sure all popups & dropdowns are animated
|
* 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
|
* 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
|
||||||
time after adding an attachment
|
|
||||||
* Make sure no cta's are visible while the page is loading
|
* 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 sure the loading spinner is always visible at the end of the page
|
||||||
* Make the button shadow lighter
|
* Make the button shadow lighter
|
||||||
|
@ -1010,7 +675,7 @@ The releases aim at the api versions which is why there are missing versions.
|
||||||
* Hide totp settings if it is disabled server side
|
* Hide totp settings if it is disabled server side
|
||||||
* Increase network timeout when building docker image
|
* Increase network timeout when building docker image
|
||||||
* Make sure the version includes the tag when building docker images
|
* Make sure the version includes the tag when building docker images
|
||||||
* # PrideMonth
|
* #PrideMonth
|
||||||
* Only renew user token on tab focus events
|
* Only renew user token on tab focus events
|
||||||
* Redirect the user to login page if the token expired when the tab gets focus again
|
* Redirect the user to login page if the token expired when the tab gets focus again
|
||||||
* Remove title length restrictions
|
* Remove title length restrictions
|
||||||
|
@ -1045,7 +710,7 @@ The releases aim at the api versions which is why there are missing versions.
|
||||||
|
|
||||||
## [0.13] - 2020-05-12
|
## [0.13] - 2020-05-12
|
||||||
|
|
||||||
#### Added
|
#### Added
|
||||||
|
|
||||||
* Add docker run script to change api url on startup
|
* Add docker run script to change api url on startup
|
||||||
* Add github token for renovate (#89)
|
* Add github token for renovate (#89)
|
||||||
|
@ -1390,7 +1055,6 @@ The releases aim at the api versions which is why there are missing versions.
|
||||||
* Use email instead of username when resetting a password
|
* Use email instead of username when resetting a password
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
* Fixed trying to verify an email when there was none
|
* Fixed trying to verify an email when there was none
|
||||||
* Fixed loading tasks when the user was not authenticated
|
* Fixed loading tasks when the user was not authenticated
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
[![Build Status](https://drone.kolaente.de/api/badges/vikunja/frontend/status.svg)](https://drone.kolaente.de/vikunja/frontend)
|
[![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)
|
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](LICENSE)
|
||||||
[![Download](https://img.shields.io/badge/download-v0.18.1-brightgreen.svg)](https://dl.vikunja.io)
|
[![Download](https://img.shields.io/badge/download-v0.17.0-brightgreen.svg)](https://dl.vikunja.io)
|
||||||
[![Translation](https://badges.crowdin.net/vikunja/localized.svg)](https://crowdin.com/project/vikunja)
|
[![Translation](https://hosted.weblate.org/widgets/vikunja/-/frontend/svg-badge.svg)](https://hosted.weblate.org/engage/vikunja/)
|
||||||
|
|
||||||
This is the web frontend for Vikunja, written in Vue.js.
|
This is the web frontend for Vikunja, written in Vue.js.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
project_id: 462614
|
||||||
|
api_token_env: CROWDIN_API_TOKEN
|
||||||
|
base_path: .
|
||||||
|
base_url: https://api.crowdin.com
|
||||||
|
|
||||||
|
preserve_hierarchy: false
|
||||||
|
|
||||||
|
files:
|
||||||
|
- source: /src/i18n/lang/*.json
|
||||||
|
#
|
||||||
|
# Where translations will be placed
|
||||||
|
# e.g. "/resources/%two_letters_code%/%original_file_name%"
|
||||||
|
#
|
||||||
|
translation: /src/i18n/lang/%two_letters_code%/%original_file_name%
|
||||||
|
#
|
||||||
|
# files or directories for ignore
|
||||||
|
# e.g. ["/**/?.txt", "/**/[0-9].txt", "/**/*\?*.txt"]
|
||||||
|
#
|
||||||
|
#"ignore" : [],
|
||||||
|
#
|
||||||
|
# The dest allows you to specify a file name in Crowdin
|
||||||
|
# e.g. "/messages.json"
|
||||||
|
#
|
||||||
|
#"dest" : "",
|
|
@ -1,17 +1,17 @@
|
||||||
image: vikunja/frontend:unstable
|
image: vikunja/frontend:latest
|
||||||
manifests:
|
manifests:
|
||||||
-
|
-
|
||||||
image: vikunja/frontend:unstable-linux-amd64
|
image: vikunja/frontend:latest-linux-amd64
|
||||||
platform:
|
platform:
|
||||||
architecture: amd64
|
architecture: amd64
|
||||||
os: linux
|
os: linux
|
||||||
-
|
-
|
||||||
image: vikunja/frontend:unstable-linux-arm64
|
image: vikunja/frontend:latest-linux-arm64
|
||||||
platform:
|
platform:
|
||||||
architecture: arm64
|
architecture: arm64
|
||||||
os: linux
|
os: linux
|
||||||
-
|
-
|
||||||
image: vikunja/frontend:unstable-linux-arm
|
image: vikunja/frontend:latest-linux-arm
|
||||||
platform:
|
platform:
|
||||||
architecture: arm
|
architecture: arm
|
||||||
os: linux
|
os: linux
|
26
package.json
26
package.json
|
@ -14,7 +14,7 @@
|
||||||
"test:frontend": "cypress run"
|
"test:frontend": "cypress run"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"browserslist": "4.17.0",
|
"browserslist": "4.16.8",
|
||||||
"bulma": "0.9.3",
|
"bulma": "0.9.3",
|
||||||
"camel-case": "4.1.2",
|
"camel-case": "4.1.2",
|
||||||
"copy-to-clipboard": "3.3.1",
|
"copy-to-clipboard": "3.3.1",
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
"highlight.js": "11.2.0",
|
"highlight.js": "11.2.0",
|
||||||
"is-touch-device": "1.0.1",
|
"is-touch-device": "1.0.1",
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"marked": "3.0.3",
|
"marked": "3.0.2",
|
||||||
"register-service-worker": "1.7.2",
|
"register-service-worker": "1.7.2",
|
||||||
"snake-case": "3.0.4",
|
"snake-case": "3.0.4",
|
||||||
"verte": "0.0.12",
|
"verte": "0.0.12",
|
||||||
|
@ -35,44 +35,44 @@
|
||||||
"vue-shortkey": "3.1.7",
|
"vue-shortkey": "3.1.7",
|
||||||
"vuedraggable": "2.24.3",
|
"vuedraggable": "2.24.3",
|
||||||
"vuex": "3.6.2",
|
"vuex": "3.6.2",
|
||||||
"workbox-precaching": "6.3.0"
|
"workbox-precaching": "6.2.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@4tw/cypress-drag-drop": "2.0.0",
|
"@4tw/cypress-drag-drop": "1.8.1",
|
||||||
"@fortawesome/fontawesome-svg-core": "1.2.36",
|
"@fortawesome/fontawesome-svg-core": "1.2.36",
|
||||||
"@fortawesome/free-regular-svg-icons": "5.15.4",
|
"@fortawesome/free-regular-svg-icons": "5.15.4",
|
||||||
"@fortawesome/free-solid-svg-icons": "5.15.4",
|
"@fortawesome/free-solid-svg-icons": "5.15.4",
|
||||||
"@fortawesome/vue-fontawesome": "2.0.2",
|
"@fortawesome/vue-fontawesome": "2.0.2",
|
||||||
"@types/jest": "27.0.1",
|
"@types/jest": "27.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "4.31.0",
|
"@typescript-eslint/eslint-plugin": "4.30.0",
|
||||||
"@typescript-eslint/parser": "4.31.0",
|
"@typescript-eslint/parser": "4.30.0",
|
||||||
"@vue/babel-preset-app": "4.5.13",
|
"@vue/babel-preset-app": "4.5.13",
|
||||||
"@vue/eslint-config-typescript": "7.0.0",
|
"@vue/eslint-config-typescript": "7.0.0",
|
||||||
"autoprefixer": "10.3.4",
|
"autoprefixer": "10.3.4",
|
||||||
"axios": "0.21.4",
|
"axios": "0.21.3",
|
||||||
"babel-eslint": "10.1.0",
|
"babel-eslint": "10.1.0",
|
||||||
"cypress": "8.3.1",
|
"cypress": "8.3.1",
|
||||||
"cypress-file-upload": "5.0.8",
|
"cypress-file-upload": "5.0.8",
|
||||||
"esbuild": "0.12.26",
|
"esbuild": "0.12.25",
|
||||||
"eslint": "7.32.0",
|
"eslint": "7.32.0",
|
||||||
"eslint-plugin-vue": "7.17.0",
|
"eslint-plugin-vue": "7.17.0",
|
||||||
"express": "4.17.1",
|
"express": "4.17.1",
|
||||||
"faker": "5.5.3",
|
"faker": "5.5.3",
|
||||||
"jest": "27.1.1",
|
"jest": "27.1.0",
|
||||||
"rollup-plugin-terser": "7.0.2",
|
"rollup-plugin-terser": "7.0.2",
|
||||||
"rollup-plugin-visualizer": "5.5.2",
|
"rollup-plugin-visualizer": "5.5.2",
|
||||||
"sass": "1.39.2",
|
"sass": "1.39.0",
|
||||||
"ts-jest": "27.0.5",
|
"ts-jest": "27.0.5",
|
||||||
"typescript": "4.4.2",
|
"typescript": "4.4.2",
|
||||||
"vite": "2.5.6",
|
"vite": "2.5.3",
|
||||||
"vite-plugin-pwa": "0.11.2",
|
"vite-plugin-pwa": "0.11.2",
|
||||||
"vite-plugin-vue2": "1.8.2",
|
"vite-plugin-vue2": "1.8.1",
|
||||||
"vue-flatpickr-component": "8.1.7",
|
"vue-flatpickr-component": "8.1.7",
|
||||||
"vue-notification": "1.3.20",
|
"vue-notification": "1.3.20",
|
||||||
"vue-router": "3.5.2",
|
"vue-router": "3.5.2",
|
||||||
"vue-template-compiler": "2.6.14",
|
"vue-template-compiler": "2.6.14",
|
||||||
"wait-on": "6.0.0",
|
"wait-on": "6.0.0",
|
||||||
"workbox-cli": "6.3.0"
|
"workbox-cli": "6.2.4"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"root": true,
|
"root": true,
|
||||||
|
|
10
src/App.vue
10
src/App.vue
|
@ -23,9 +23,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {mapState, mapGetters} from 'vuex'
|
import {mapState} from 'vuex'
|
||||||
import isTouchDevice from 'is-touch-device'
|
import isTouchDevice from 'is-touch-device'
|
||||||
|
|
||||||
|
import authTypes from './models/authTypes'
|
||||||
|
|
||||||
import Notification from './components/misc/notification'
|
import Notification from './components/misc/notification'
|
||||||
import {KEYBOARD_SHORTCUTS_ACTIVE, ONLINE} from './store/mutation-types'
|
import {KEYBOARD_SHORTCUTS_ACTIVE, ONLINE} from './store/mutation-types'
|
||||||
import KeyboardShortcuts from './components/misc/keyboard-shortcuts'
|
import KeyboardShortcuts from './components/misc/keyboard-shortcuts'
|
||||||
|
@ -72,13 +74,11 @@ export default {
|
||||||
return isTouchDevice()
|
return isTouchDevice()
|
||||||
},
|
},
|
||||||
...mapState({
|
...mapState({
|
||||||
|
authUser: state => state.auth.authenticated && (state.auth.info && state.auth.info.type === authTypes.USER),
|
||||||
|
authLinkShare: state => state.auth.authenticated && (state.auth.info && state.auth.info.type === authTypes.LINK_SHARE),
|
||||||
online: ONLINE,
|
online: ONLINE,
|
||||||
keyboardShortcutsActive: KEYBOARD_SHORTCUTS_ACTIVE,
|
keyboardShortcutsActive: KEYBOARD_SHORTCUTS_ACTIVE,
|
||||||
}),
|
}),
|
||||||
...mapGetters('auth', [
|
|
||||||
'authUser',
|
|
||||||
'authLinkShare',
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setupOnlineStatus() {
|
setupOnlineStatus() {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</a>
|
</a>
|
||||||
<div
|
<div
|
||||||
:class="{'has-background': background}"
|
:class="{'has-background': background}"
|
||||||
:style="{'background-image': background && `url(${background})`}"
|
:style="{'background-image': `url(${background})`}"
|
||||||
class="app-container"
|
class="app-container"
|
||||||
>
|
>
|
||||||
<navigation/>
|
<navigation/>
|
||||||
|
@ -62,7 +62,7 @@ export default {
|
||||||
return state.namespaces.namespaces.filter(n => !n.isArchived)
|
return state.namespaces.namespaces.filter(n => !n.isArchived)
|
||||||
},
|
},
|
||||||
currentList: CURRENT_LIST,
|
currentList: CURRENT_LIST,
|
||||||
background: 'background',
|
background: 'background', // FIXME: Return the full thing or nothing at all to prevent calls to /null
|
||||||
menuActive: MENU_ACTIVE,
|
menuActive: MENU_ACTIVE,
|
||||||
userInfo: state => state.auth.info,
|
userInfo: state => state.auth.info,
|
||||||
authenticated: state => state.auth.authenticated,
|
authenticated: state => state.auth.authenticated,
|
||||||
|
|
|
@ -97,7 +97,7 @@
|
||||||
<script>
|
<script>
|
||||||
import {mapState} from 'vuex'
|
import {mapState} from 'vuex'
|
||||||
import {CURRENT_LIST, QUICK_ACTIONS_ACTIVE} from '@/store/mutation-types'
|
import {CURRENT_LIST, QUICK_ACTIONS_ACTIVE} from '@/store/mutation-types'
|
||||||
import Rights from '@/models/constants/rights.json'
|
import Rights from '@/models/rights.json'
|
||||||
import Update from '@/components/home/update.vue'
|
import Update from '@/components/home/update.vue'
|
||||||
import ListSettingsDropdown from '@/components/list/list-settings-dropdown.vue'
|
import ListSettingsDropdown from '@/components/list/list-settings-dropdown.vue'
|
||||||
import Dropdown from '@/components/misc/dropdown.vue'
|
import Dropdown from '@/components/misc/dropdown.vue'
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
:checked="checked"
|
:checked="checked"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:id="checkBoxId"
|
:id="checkBoxId"
|
||||||
@change="(event) => updateData(event.target.checked)"
|
@change="updateData"
|
||||||
style="display: none;"
|
style="display: none;"
|
||||||
type="checkbox"/>
|
type="checkbox"/>
|
||||||
<label :for="checkBoxId" class="check">
|
<label :for="checkBoxId" class="check">
|
||||||
|
@ -51,10 +51,10 @@ export default {
|
||||||
this.checkBoxId = 'fancycheckbox' + Math.random()
|
this.checkBoxId = 'fancycheckbox' + Math.random()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateData(checked) {
|
updateData(e) {
|
||||||
this.checked = checked
|
this.checked = e.target.checked
|
||||||
this.$emit('input', checked)
|
this.$emit('input', this.checked)
|
||||||
this.$emit('change', checked)
|
this.$emit('change', e.target.checked)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,35 +190,6 @@ import ListService from '@/services/list'
|
||||||
import NamespaceService from '@/services/namespace'
|
import NamespaceService from '@/services/namespace'
|
||||||
import EditLabels from '@/components/tasks/partials/editLabels.vue'
|
import EditLabels from '@/components/tasks/partials/editLabels.vue'
|
||||||
|
|
||||||
// FIXME: merge with DEFAULT_PARAMS in taskList.js
|
|
||||||
const DEFAULT_PARAMS = {
|
|
||||||
sort_by: [],
|
|
||||||
order_by: [],
|
|
||||||
filter_by: [],
|
|
||||||
filter_value: [],
|
|
||||||
filter_comparator: [],
|
|
||||||
filter_include_nulls: true,
|
|
||||||
filter_concat: 'or',
|
|
||||||
s: '',
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEFAULT_FILTERS = {
|
|
||||||
done: false,
|
|
||||||
dueDate: '',
|
|
||||||
requireAllFilters: false,
|
|
||||||
priority: 0,
|
|
||||||
usePriority: false,
|
|
||||||
startDate: '',
|
|
||||||
endDate: '',
|
|
||||||
percentDone: 0,
|
|
||||||
usePercentDone: false,
|
|
||||||
reminders: '',
|
|
||||||
assignees: '',
|
|
||||||
labels: '',
|
|
||||||
list_id: '',
|
|
||||||
namespace: '',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'filters',
|
name: 'filters',
|
||||||
components: {
|
components: {
|
||||||
|
@ -231,8 +202,32 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
params: DEFAULT_PARAMS,
|
params: {
|
||||||
filters: DEFAULT_FILTERS,
|
sort_by: [],
|
||||||
|
order_by: [],
|
||||||
|
filter_by: [],
|
||||||
|
filter_value: [],
|
||||||
|
filter_comparator: [],
|
||||||
|
filter_include_nulls: true,
|
||||||
|
filter_concat: 'or',
|
||||||
|
s: '',
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
done: false,
|
||||||
|
dueDate: '',
|
||||||
|
requireAllFilters: false,
|
||||||
|
priority: 0,
|
||||||
|
usePriority: false,
|
||||||
|
startDate: '',
|
||||||
|
endDate: '',
|
||||||
|
percentDone: 0,
|
||||||
|
usePercentDone: false,
|
||||||
|
reminders: '',
|
||||||
|
assignees: '',
|
||||||
|
labels: '',
|
||||||
|
list_id: '',
|
||||||
|
namespace: '',
|
||||||
|
},
|
||||||
|
|
||||||
usersService: UserService,
|
usersService: UserService,
|
||||||
foundusers: [],
|
foundusers: [],
|
||||||
|
|
|
@ -36,7 +36,14 @@
|
||||||
<div class="migration-in-progress">
|
<div class="migration-in-progress">
|
||||||
<img :alt="name" :src="`/images/migration/${identifier}.png`"/>
|
<img :alt="name" :src="`/images/migration/${identifier}.png`"/>
|
||||||
<div class="progress-dots">
|
<div class="progress-dots">
|
||||||
<span v-for="i in progressDotsCount" :key="i" />
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
<img alt="Vikunja" src="/images/logo.svg">
|
<img alt="Vikunja" src="/images/logo.svg">
|
||||||
</div>
|
</div>
|
||||||
|
@ -67,19 +74,15 @@
|
||||||
import AbstractMigrationService from '../../services/migrator/abstractMigration'
|
import AbstractMigrationService from '../../services/migrator/abstractMigration'
|
||||||
import AbstractMigrationFileService from '../../services/migrator/abstractMigrationFile'
|
import AbstractMigrationFileService from '../../services/migrator/abstractMigrationFile'
|
||||||
|
|
||||||
const PROGRESS_DOTS_COUNT = 8
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'migration',
|
name: 'migration',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
progressDotsCount: PROGRESS_DOTS_COUNT,
|
|
||||||
authUrl: '',
|
authUrl: '',
|
||||||
isMigrating: false,
|
isMigrating: false,
|
||||||
lastMigrationDate: null,
|
lastMigrationDate: null,
|
||||||
message: '',
|
message: '',
|
||||||
migratorAuthCode: '',
|
migratorAuthCode: '',
|
||||||
migrationService: null,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="api-url-info" v-else>
|
<div class="api-url-info" v-else>
|
||||||
<i18n path="apiConfig.signInOn">
|
<i18n path="apiConfig.signInOn">
|
||||||
<span class="url" v-tooltip="apiUrl"> {{ apiDomain }} </span>
|
<span class="url" v-tooltip="apiUrl"> {{ apiDomain() }} </span>
|
||||||
</i18n>
|
</i18n>
|
||||||
<br />
|
<br />
|
||||||
<a @click="() => (configureApi = true)">{{ $t('apiConfig.change') }}</a>
|
<a @click="() => (configureApi = true)">{{ $t('apiConfig.change') }}</a>
|
||||||
|
@ -46,24 +46,23 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const API_DEFAULT_PORT = 3456
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'apiConfig',
|
name: 'apiConfig',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
configureApi: false,
|
configureApi: false,
|
||||||
apiUrl: window.API_URL,
|
apiUrl: '',
|
||||||
errorMsg: '',
|
errorMsg: '',
|
||||||
successMsg: '',
|
successMsg: '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
this.apiUrl = window.API_URL
|
||||||
if (this.apiUrl === '') {
|
if (this.apiUrl === '') {
|
||||||
this.configureApi = true
|
this.configureApi = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
methods: {
|
||||||
apiDomain() {
|
apiDomain() {
|
||||||
if (window.API_URL.startsWith('/api/v1')) {
|
if (window.API_URL.startsWith('/api/v1')) {
|
||||||
return window.location.host
|
return window.location.host
|
||||||
|
@ -73,8 +72,6 @@ export default {
|
||||||
.split(/[/?#]/)
|
.split(/[/?#]/)
|
||||||
return urlParts[0]
|
return urlParts[0]
|
||||||
},
|
},
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setApiUrl() {
|
setApiUrl() {
|
||||||
if (this.apiUrl === '') {
|
if (this.apiUrl === '') {
|
||||||
return
|
return
|
||||||
|
@ -134,17 +131,17 @@ export default {
|
||||||
return Promise.reject(e)
|
return Promise.reject(e)
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
// Check if it is reachable at port API_DEFAULT_PORT and https
|
// Check if it is reachable at port 3456 and https
|
||||||
if (urlToCheck.port !== API_DEFAULT_PORT) {
|
if (urlToCheck.port !== 3456) {
|
||||||
urlToCheck.protocol = 'https:'
|
urlToCheck.protocol = 'https:'
|
||||||
urlToCheck.port = API_DEFAULT_PORT
|
urlToCheck.port = 3456
|
||||||
window.API_URL = urlToCheck.toString()
|
window.API_URL = urlToCheck.toString()
|
||||||
return this.$store.dispatch('config/update')
|
return this.$store.dispatch('config/update')
|
||||||
}
|
}
|
||||||
return Promise.reject(e)
|
return Promise.reject(e)
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
// Check if it is reachable at :API_DEFAULT_PORT and /api/v1 and https
|
// Check if it is reachable at :3456 and /api/v1 and https
|
||||||
urlToCheck.pathname = origUrlToCheck.pathname
|
urlToCheck.pathname = origUrlToCheck.pathname
|
||||||
if (
|
if (
|
||||||
!urlToCheck.pathname.endsWith('/api/v1') &&
|
!urlToCheck.pathname.endsWith('/api/v1') &&
|
||||||
|
@ -157,17 +154,17 @@ export default {
|
||||||
return Promise.reject(e)
|
return Promise.reject(e)
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
// Check if it is reachable at port API_DEFAULT_PORT and http
|
// Check if it is reachable at port 3456 and http
|
||||||
if (urlToCheck.port !== API_DEFAULT_PORT) {
|
if (urlToCheck.port !== 3456) {
|
||||||
urlToCheck.protocol = 'http:'
|
urlToCheck.protocol = 'http:'
|
||||||
urlToCheck.port = API_DEFAULT_PORT
|
urlToCheck.port = 3456
|
||||||
window.API_URL = urlToCheck.toString()
|
window.API_URL = urlToCheck.toString()
|
||||||
return this.$store.dispatch('config/update')
|
return this.$store.dispatch('config/update')
|
||||||
}
|
}
|
||||||
return Promise.reject(e)
|
return Promise.reject(e)
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
// Check if it is reachable at :API_DEFAULT_PORT and /api/v1 and http
|
// Check if it is reachable at :3456 and /api/v1 and http
|
||||||
urlToCheck.pathname = origUrlToCheck.pathname
|
urlToCheck.pathname = origUrlToCheck.pathname
|
||||||
if (
|
if (
|
||||||
!urlToCheck.pathname.endsWith('/api/v1') &&
|
!urlToCheck.pathname.endsWith('/api/v1') &&
|
||||||
|
@ -182,14 +179,14 @@ export default {
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
// Still not found, url is still invalid
|
// Still not found, url is still invalid
|
||||||
this.successMsg = ''
|
this.successMsg = ''
|
||||||
this.errorMsg = this.$t('apiConfig.error', {domain: this.apiDomain})
|
this.errorMsg = this.$t('apiConfig.error', {domain: this.apiDomain()})
|
||||||
window.API_URL = oldUrl
|
window.API_URL = oldUrl
|
||||||
})
|
})
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
if (typeof r !== 'undefined') {
|
if (typeof r !== 'undefined') {
|
||||||
// Set it + save it to local storage to save us the hoops
|
// Set it + save it to local storage to save us the hoops
|
||||||
this.errorMsg = ''
|
this.errorMsg = ''
|
||||||
this.successMsg = this.$t('apiConfig.success', {domain: this.apiDomain})
|
this.successMsg = this.$t('apiConfig.success', {domain: this.apiDomain()})
|
||||||
localStorage.setItem('API_URL', window.API_URL)
|
localStorage.setItem('API_URL', window.API_URL)
|
||||||
this.configureApi = false
|
this.configureApi = false
|
||||||
this.apiUrl = window.API_URL
|
this.apiUrl = window.API_URL
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
<script>
|
<script>
|
||||||
import NotificationService from '@/services/notification'
|
import NotificationService from '@/services/notification'
|
||||||
import User from '@/components/misc/user.vue'
|
import User from '@/components/misc/user.vue'
|
||||||
import names from '@/models/constants/notificationNames.json'
|
import names from '@/models/notificationNames.json'
|
||||||
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
||||||
import {mapState} from 'vuex'
|
import {mapState} from 'vuex'
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import rights from '../../models/constants/rights'
|
import rights from '../../models/rights'
|
||||||
|
|
||||||
import LinkShareService from '../../services/linkShare'
|
import LinkShareService from '../../services/linkShare'
|
||||||
import LinkShareModel from '../../models/linkShare'
|
import LinkShareModel from '../../models/linkShare'
|
||||||
|
|
|
@ -145,7 +145,7 @@ import TeamListService from '../../services/teamList'
|
||||||
import TeamService from '../../services/team'
|
import TeamService from '../../services/team'
|
||||||
import TeamModel from '../../models/team'
|
import TeamModel from '../../models/team'
|
||||||
|
|
||||||
import rights from '../../models/constants/rights.json'
|
import rights from '../../models/rights'
|
||||||
import Multiselect from '@/components/input/multiselect.vue'
|
import Multiselect from '@/components/input/multiselect.vue'
|
||||||
import Nothing from '@/components/misc/nothing.vue'
|
import Nothing from '@/components/misc/nothing.vue'
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
import ListService from '../../services/list'
|
import ListService from '../../services/list'
|
||||||
import TaskService from '../../services/task'
|
import TaskService from '../../services/task'
|
||||||
import TaskModel from '../../models/task'
|
import TaskModel from '../../models/task'
|
||||||
import priorities from '../../models/constants/priorities'
|
import priorities from '../../models/priorities'
|
||||||
import EditLabels from './partials/editLabels'
|
import EditLabels from './partials/editLabels'
|
||||||
import Reminders from './partials/reminders'
|
import Reminders from './partials/reminders'
|
||||||
import ColorPicker from '../input/colorPicker'
|
import ColorPicker from '../input/colorPicker'
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</x-button>
|
</x-button>
|
||||||
</div>
|
</div>
|
||||||
<filter-popup
|
<filter-popup
|
||||||
@change="loadTasks()"
|
@change="loadTasks"
|
||||||
:visible="showTaskFilter"
|
:visible="showTaskFilter"
|
||||||
v-model="params"
|
v-model="params"
|
||||||
/>
|
/>
|
||||||
|
@ -24,7 +24,10 @@
|
||||||
class="month"
|
class="month"
|
||||||
v-for="(m, mk) in days[yk]"
|
v-for="(m, mk) in days[yk]"
|
||||||
>
|
>
|
||||||
{{ formatYear(new Date(`${yk}-${parseInt(mk) + 1}-01`)) }}
|
{{
|
||||||
|
new Date(new Date(`${yk}-${parseInt(mk) + 1}-01`)).toLocaleString('en-us', {month: 'long'})
|
||||||
|
}},
|
||||||
|
{{ new Date(yk).getFullYear() }}
|
||||||
<div class="days">
|
<div class="days">
|
||||||
<div
|
<div
|
||||||
:class="{ today: d.toDateString() === now.toDateString() }"
|
:class="{ today: d.toDateString() === now.toDateString() }"
|
||||||
|
@ -188,13 +191,12 @@ import EditTask from './edit-task'
|
||||||
|
|
||||||
import TaskService from '../../services/task'
|
import TaskService from '../../services/task'
|
||||||
import TaskModel from '../../models/task'
|
import TaskModel from '../../models/task'
|
||||||
import priorities from '../../models/constants/priorities'
|
import priorities from '../../models/priorities'
|
||||||
import PriorityLabel from './partials/priorityLabel'
|
import PriorityLabel from './partials/priorityLabel'
|
||||||
import TaskCollectionService from '../../services/taskCollection'
|
import TaskCollectionService from '../../services/taskCollection'
|
||||||
import {mapState} from 'vuex'
|
import {mapState} from 'vuex'
|
||||||
import Rights from '../../models/constants/rights.json'
|
import Rights from '../../models/rights.json'
|
||||||
import FilterPopup from '@/components/list/partials/filter-popup.vue'
|
import FilterPopup from '@/components/list/partials/filter-popup.vue'
|
||||||
import {format} from 'date-fns'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'GanttChart',
|
name: 'GanttChart',
|
||||||
|
@ -479,9 +481,6 @@ export default {
|
||||||
this.error(e)
|
this.error(e)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
formatYear(date) {
|
|
||||||
return format(date, 'MMMM, yyyy')
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,70 +1,17 @@
|
||||||
import TaskCollectionService from '@/services/taskCollection'
|
import TaskCollectionService from '../../../services/taskCollection'
|
||||||
import cloneDeep from 'lodash/cloneDeep'
|
import cloneDeep from 'lodash/cloneDeep'
|
||||||
import {calculateItemPosition} from '../../../helpers/calculateItemPosition'
|
import {calculateItemPosition} from '../../../helpers/calculateItemPosition'
|
||||||
|
|
||||||
// FIXME: merge with DEFAULT_PARAMS in filters.vue
|
|
||||||
const DEFAULT_PARAMS = {
|
|
||||||
sort_by: ['position', 'id'],
|
|
||||||
order_by: ['asc', 'desc'],
|
|
||||||
filter_by: ['done'],
|
|
||||||
filter_value: ['false'],
|
|
||||||
filter_comparator: ['equals'],
|
|
||||||
filter_concat: 'and',
|
|
||||||
}
|
|
||||||
|
|
||||||
function createPagination(totalPages, currentPage) {
|
|
||||||
const pages = []
|
|
||||||
for (let i = 0; i < totalPages; i++) {
|
|
||||||
|
|
||||||
// Show ellipsis instead of all pages
|
|
||||||
if (
|
|
||||||
i > 0 && // Always at least the first page
|
|
||||||
(i + 1) < totalPages && // And the last page
|
|
||||||
(
|
|
||||||
// And the current with current + 1 and current - 1
|
|
||||||
(i + 1) > currentPage + 1 ||
|
|
||||||
(i + 1) < currentPage - 1
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
// Only add an ellipsis if the last page isn't already one
|
|
||||||
if (pages[i - 1] && !pages[i - 1].isEllipsis) {
|
|
||||||
pages.push({
|
|
||||||
number: 0,
|
|
||||||
isEllipsis: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
pages.push({
|
|
||||||
number: i + 1,
|
|
||||||
isEllipsis: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return pages
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getRouteForPagination(page = 1, type = 'list') {
|
|
||||||
return {
|
|
||||||
name: 'list.' + type,
|
|
||||||
params: {
|
|
||||||
type: type,
|
|
||||||
},
|
|
||||||
query: {
|
|
||||||
page: page,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This mixin provides a base set of methods and properties to get tasks on a list.
|
* This mixin provides a base set of methods and properties to get tasks on a list.
|
||||||
*/
|
*/
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
taskCollectionService: new TaskCollectionService(),
|
taskCollectionService: TaskCollectionService,
|
||||||
tasks: [],
|
tasks: [],
|
||||||
|
|
||||||
|
pages: [],
|
||||||
currentPage: 0,
|
currentPage: 0,
|
||||||
|
|
||||||
loadedList: null,
|
loadedList: null,
|
||||||
|
@ -73,21 +20,27 @@ export default {
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
|
|
||||||
showTaskFilter: false,
|
showTaskFilter: false,
|
||||||
params: DEFAULT_PARAMS,
|
params: {
|
||||||
|
sort_by: ['position', 'id'],
|
||||||
|
order_by: ['asc', 'desc'],
|
||||||
|
filter_by: ['done'],
|
||||||
|
filter_value: ['false'],
|
||||||
|
filter_comparator: ['equals'],
|
||||||
|
filter_concat: 'and',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
// Only listen for query path changes
|
'$route.query': 'loadTasksForPage', // Only listen for query path changes
|
||||||
'$route.query': {
|
|
||||||
handler: 'loadTasksForPage',
|
|
||||||
immediate: true,
|
|
||||||
},
|
|
||||||
'$route.path': 'loadTasksOnSavedFilter',
|
'$route.path': 'loadTasksOnSavedFilter',
|
||||||
},
|
},
|
||||||
computed: {
|
beforeMount() {
|
||||||
pages() {
|
// Triggering loading the tasks in beforeMount lets the component maintain the current page, therefore the page
|
||||||
return createPagination(this.taskCollectionService.totalPages, this.currentPage)
|
// is not lost after navigating back from a task detail page for example.
|
||||||
},
|
this.loadTasksForPage(this.$route.query)
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.taskCollectionService = new TaskCollectionService()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loadTasks(
|
loadTasks(
|
||||||
|
@ -127,20 +80,48 @@ export default {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tasks = []
|
this.$set(this, 'tasks', [])
|
||||||
|
|
||||||
this.taskCollectionService.getAll(list, params, page)
|
this.taskCollectionService.getAll(list, params, page)
|
||||||
.then(r => {
|
.then(r => {
|
||||||
this.tasks = r
|
this.$set(this, 'tasks', r)
|
||||||
|
this.$set(this, 'pages', [])
|
||||||
this.currentPage = page
|
this.currentPage = page
|
||||||
|
|
||||||
|
for (let i = 0; i < this.taskCollectionService.totalPages; i++) {
|
||||||
|
|
||||||
|
// Show ellipsis instead of all pages
|
||||||
|
if (
|
||||||
|
i > 0 && // Always at least the first page
|
||||||
|
(i + 1) < this.taskCollectionService.totalPages && // And the last page
|
||||||
|
(
|
||||||
|
// And the current with current + 1 and current - 1
|
||||||
|
(i + 1) > this.currentPage + 1 ||
|
||||||
|
(i + 1) < this.currentPage - 1
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// Only add an ellipsis if the last page isn't already one
|
||||||
|
if (this.pages[i - 1] && !this.pages[i - 1].isEllipsis) {
|
||||||
|
this.pages.push({
|
||||||
|
number: 0,
|
||||||
|
isEllipsis: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pages.push({
|
||||||
|
number: i + 1,
|
||||||
|
isEllipsis: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
this.loadedList = cloneDeep(currentList)
|
this.loadedList = cloneDeep(currentList)
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
this.error(e)
|
this.error(e)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
loadTasksForPage(e) {
|
loadTasksForPage(e) {
|
||||||
// The page parameter can be undefined, in the case where the user loads a new list from the side bar menu
|
// The page parameter can be undefined, in the case where the user loads a new list from the side bar menu
|
||||||
let page = Number(e.page)
|
let page = Number(e.page)
|
||||||
|
@ -196,6 +177,17 @@ export default {
|
||||||
this.showTaskSearch = false
|
this.showTaskSearch = false
|
||||||
}, 200)
|
}, 200)
|
||||||
},
|
},
|
||||||
|
getRouteForPagination(page = 1, type = 'list') {
|
||||||
|
return {
|
||||||
|
name: 'list.' + type,
|
||||||
|
params: {
|
||||||
|
type: type,
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
page: page,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
saveTaskPosition(e) {
|
saveTaskPosition(e) {
|
||||||
this.drag = false
|
this.drag = false
|
||||||
|
|
||||||
|
@ -213,6 +205,5 @@ export default {
|
||||||
this.error(e)
|
this.error(e)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getRouteForPagination,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
|
@ -7,17 +7,16 @@
|
||||||
<h1
|
<h1
|
||||||
class="title input"
|
class="title input"
|
||||||
:class="{'disabled': !canWrite}"
|
:class="{'disabled': !canWrite}"
|
||||||
@blur="save($event.target.textContent)"
|
@focusout="save()"
|
||||||
@keydown.enter.prevent.stop="$event.target.blur()"
|
@keydown.enter.prevent.stop="save()"
|
||||||
:contenteditable="canWrite ? 'true' : 'false'"
|
:contenteditable="canWrite ? 'true' : 'false'"
|
||||||
spellcheck="false"
|
|
||||||
ref="taskTitle">{{ task.title.trim() }}</h1>
|
ref="taskTitle">{{ task.title.trim() }}</h1>
|
||||||
<transition name="fade">
|
<transition name="fade">
|
||||||
<span class="is-inline-flex is-align-items-center" v-if="loading && saving">
|
<span class="is-inline-flex is-align-items-center" v-if="loading && saving">
|
||||||
<span class="loader is-inline-block mr-2"></span>
|
<span class="loader is-inline-block mr-2"></span>
|
||||||
{{ $t('misc.saving') }}
|
{{ $t('misc.saving') }}
|
||||||
</span>
|
</span>
|
||||||
<span class="has-text-success is-inline-flex is-align-content-center" v-if="!loading && showSavedMessage">
|
<span class="has-text-success is-inline-flex is-align-content-center" v-if="!loading && saved">
|
||||||
<icon icon="check" class="mr-2"/>
|
<icon icon="check" class="mr-2"/>
|
||||||
{{ $t('misc.saved') }}
|
{{ $t('misc.saved') }}
|
||||||
</span>
|
</span>
|
||||||
|
@ -26,22 +25,22 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {LOADING} from '@/store/mutation-types'
|
||||||
import {mapState} from 'vuex'
|
import {mapState} from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'heading',
|
name: 'heading',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showSavedMessage: false,
|
task: {title: '', identifier: '', index:''},
|
||||||
|
taskTitle: '',
|
||||||
|
saved: false,
|
||||||
saving: false, // Since loading is global state, this variable ensures we're only showing the saving icon when saving the description.
|
saving: false, // Since loading is global state, this variable ensures we're only showing the saving icon when saving the description.
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: mapState({
|
||||||
...mapState(['loading']),
|
loading: LOADING,
|
||||||
task() {
|
}),
|
||||||
return this.value
|
|
||||||
},
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -51,29 +50,43 @@ export default {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
value(newVal) {
|
||||||
|
this.task = newVal
|
||||||
|
this.taskTitle = this.task.title
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.task = this.value
|
||||||
|
this.taskTitle = this.task.title
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
save(title) {
|
save() {
|
||||||
// We only want to save if the title was actually changed.
|
this.$refs.taskTitle.spellcheck = false
|
||||||
// Because the contenteditable does not have a change event
|
|
||||||
// we're building it ourselves and only continue
|
|
||||||
// if the task title changed.
|
|
||||||
if (title === this.task.title) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Pull the task title from the contenteditable
|
||||||
|
let taskTitle = this.$refs.taskTitle.textContent
|
||||||
|
this.task.title = taskTitle
|
||||||
|
|
||||||
|
// We only want to save if the title was actually change.
|
||||||
|
// Because the contenteditable does not have a change event,
|
||||||
|
// we're building it ourselves and only calling saveTask()
|
||||||
|
// if the task title changed.
|
||||||
|
if (this.task.title !== this.taskTitle) {
|
||||||
|
this.$refs.taskTitle.blur()
|
||||||
|
this.saveTask()
|
||||||
|
this.taskTitle = taskTitle
|
||||||
|
}
|
||||||
|
},
|
||||||
|
saveTask() {
|
||||||
this.saving = true
|
this.saving = true
|
||||||
|
|
||||||
const newTask = {
|
this.$store.dispatch('tasks/update', this.task)
|
||||||
...this.task,
|
.then(() => {
|
||||||
title,
|
this.$emit('input', this.task)
|
||||||
}
|
this.saved = true
|
||||||
|
|
||||||
this.$store.dispatch('tasks/update', newTask)
|
|
||||||
.then((task) => {
|
|
||||||
this.$emit('input', task)
|
|
||||||
this.showSavedMessage = true
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.showSavedMessage = false
|
this.saved = false
|
||||||
}, 2000)
|
}, 2000)
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
|
|
|
@ -92,10 +92,8 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
markTaskAsDone(task) {
|
markTaskAsDone(task) {
|
||||||
this.loadingInternal = true
|
this.loadingInternal = true
|
||||||
this.$store.dispatch('tasks/update', {
|
task.done = !task.done
|
||||||
...task,
|
this.$store.dispatch('tasks/update', task)
|
||||||
done: !task.done,
|
|
||||||
})
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (task.done) {
|
if (task.done) {
|
||||||
playPop()
|
playPop()
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import priorites from '../../../models/constants/priorities'
|
import priorites from '../../../models/priorities'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'priorityLabel',
|
name: 'priorityLabel',
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import priorites from '../../../models/constants/priorities'
|
import priorites from '../../../models/priorities'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'prioritySelect',
|
name: 'prioritySelect',
|
||||||
|
|
|
@ -122,7 +122,7 @@
|
||||||
import TaskService from '../../../services/task'
|
import TaskService from '../../../services/task'
|
||||||
import TaskModel from '../../../models/task'
|
import TaskModel from '../../../models/task'
|
||||||
import TaskRelationService from '../../../services/taskRelation'
|
import TaskRelationService from '../../../services/taskRelation'
|
||||||
import relationKinds from '../../../models/constants/relationKinds'
|
import relationKinds from '../../../models/relationKinds'
|
||||||
import TaskRelationModel from '../../../models/taskRelation'
|
import TaskRelationModel from '../../../models/taskRelation'
|
||||||
|
|
||||||
import Multiselect from '@/components/input/multiselect.vue'
|
import Multiselect from '@/components/input/multiselect.vue'
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import repeatModes from '@/models/constants/taskRepeatModes'
|
import repeatModes from '@/models/taskRepeatModes'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'repeatAfter',
|
name: 'repeatAfter',
|
||||||
|
@ -62,7 +62,7 @@ export default {
|
||||||
amount: 0,
|
amount: 0,
|
||||||
type: '',
|
type: '',
|
||||||
},
|
},
|
||||||
repeatModes,
|
repeatModes: repeatModes,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
export function findIndexById(array : [], id : string | number) {
|
|
||||||
return array.findIndex(({id: currentId}) => currentId === id)
|
|
||||||
}
|
|
|
@ -113,12 +113,11 @@
|
||||||
"scheduledCancelSuccess": "Wir werden deinen Account nicht löschen."
|
"scheduledCancelSuccess": "Wir werden deinen Account nicht löschen."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"title": "Export your Vikunja data",
|
"title": "Exportiere die Daten deines Vikunja-Accounts",
|
||||||
"description": "Du kannst eine Kopie deiner Daten bei Vikunja anfordern. Dazu gehören Namespaces, Listen, Aufgaben und alles, was damit zusammenhängt. Du kannst diese Daten dann in jeder Vikunja-Instanz über die Migrationsfunktion importieren.",
|
"description": "Du kannst eine Kopie deiner Daten bei Vikunja anfordern. Dazu gehören Namespaces, Listen, Aufgaben und alles, was damit zusammenhängt. Du kannst diese Daten dann in jeder Vikunja-Instanz über die Migrationsfunktion importieren.",
|
||||||
"descriptionPasswordRequired": "Bitte gib dein Passwort ein, um fortzufahren:",
|
"descriptionPasswordRequired": "Bitte gib dein Passwort ein, um fortzufahren:",
|
||||||
"request": "Eine Kopie meiner Vikunja Daten anfordern",
|
"request": "Eine Kopie meiner Vikunja Daten anfordern",
|
||||||
"success": "Du hast deine Daten bei Vikunja erfolgreich angefordert! Wir schicken dir eine E-Mail, sobald sie zum Download bereitstehen.",
|
"success": "Du hast deine Daten bei Vikunja erfolgreich angefordert! Wir schicken dir eine E-Mail, sobald sie zum Download bereitstehen."
|
||||||
"downloadTitle": "Download your exported Vikunja data"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
|
@ -0,0 +1,309 @@
|
||||||
|
{
|
||||||
|
"404": {
|
||||||
|
"title": "Nicht gefunden",
|
||||||
|
"text": "Die angeforderte Seite existiert nicht."
|
||||||
|
},
|
||||||
|
"filters": {
|
||||||
|
"create": {
|
||||||
|
"action": "Neuen gespeicherten Filter erstellen",
|
||||||
|
"description": "Ein gespeicherter Filter ist eine virtuelle Liste, die bei jedem Zugriff aus einem Satz von Filtern errechnet wird. Einmal erstellt, erscheint er in einem speziellen Namensraum.",
|
||||||
|
"title": "Einen gespeicherten Filter erstellen"
|
||||||
|
},
|
||||||
|
"attributes": {
|
||||||
|
"descriptionPlaceholder": "Die Beschreibung steht hier …",
|
||||||
|
"description": "Beschreibung",
|
||||||
|
"titlePlaceholder": "Der gespeicherte Filtertitel steht hier …",
|
||||||
|
"title": "Titel"
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"header": "Diesen gespeicherten Filter löschen",
|
||||||
|
"success": "Der Filter wurde erfolgreich gelöscht."
|
||||||
|
},
|
||||||
|
"edit": {
|
||||||
|
"success": "Der Filter wurde erfolgreich gespeichert.",
|
||||||
|
"title": "Diesen gespeicherten Filter bearbeiten"
|
||||||
|
},
|
||||||
|
"title": "Filter"
|
||||||
|
},
|
||||||
|
"sharing": {
|
||||||
|
"authenticating": "Authentifizierung …",
|
||||||
|
"invalidPassword": "Das Passwort ist ungültig.",
|
||||||
|
"error": "Es ist ein Fehler aufgetreten."
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"attributes": {
|
||||||
|
"color": "Farbe",
|
||||||
|
"description": "Beschreibung",
|
||||||
|
"title": "Titel"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"misc": {
|
||||||
|
"search": "Suchen",
|
||||||
|
"copy": "In Zwischenablage kopieren",
|
||||||
|
"disable": "Deaktivieren",
|
||||||
|
"confirm": "Bestätigen",
|
||||||
|
"delete": "Löschen",
|
||||||
|
"save": "Speichern",
|
||||||
|
"loading": "Wird geladen …",
|
||||||
|
"previous": "Vorherige",
|
||||||
|
"next": "Weiter"
|
||||||
|
},
|
||||||
|
"task": {
|
||||||
|
"delete": "Diese Aufgabe löschen",
|
||||||
|
"new": "Eine neue Aufgabe erstellen",
|
||||||
|
"task": "Aufgabe",
|
||||||
|
"show": {
|
||||||
|
"titleCurrent": "Aktuelle Aufgaben",
|
||||||
|
"noTasks": "Nichts zu tun – Einen schönen Tag noch!",
|
||||||
|
"today": "Heute",
|
||||||
|
"nextWeek": "Nächste Woche"
|
||||||
|
},
|
||||||
|
"detail": {
|
||||||
|
"created": "Erstellt {0} von {1}",
|
||||||
|
"undone": "Als unerledigt markieren",
|
||||||
|
"done": "Fertig!",
|
||||||
|
"move": "Aufgabe in eine andere Liste verschieben",
|
||||||
|
"delete": {
|
||||||
|
"header": "Diese Aufgabe löschen"
|
||||||
|
},
|
||||||
|
"deleteSuccess": "Die Aufgabe wurde erfolgreich gelöscht.",
|
||||||
|
"updateSuccess": "Die Aufgabe wurde erfolgreich gespeichert.",
|
||||||
|
"doneAt": "Erledigt {0}",
|
||||||
|
"updated": "Aktualisiert {0}",
|
||||||
|
"actions": {
|
||||||
|
"priority": "Priorität einstellen",
|
||||||
|
"reminders": "Erinnerungen einstellen",
|
||||||
|
"relatedTasks": "Aufgabenbeziehungen hinzufügen",
|
||||||
|
"attachments": "Anhänge hinzufügen",
|
||||||
|
"delete": "Aufgabe löschen",
|
||||||
|
"color": "Taskfarbe einstellen",
|
||||||
|
"moveList": "Aufgabe verschieben"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"attributes": {
|
||||||
|
"color": "Farbe",
|
||||||
|
"done": "Fertig",
|
||||||
|
"createdBy": "Erstellt von",
|
||||||
|
"created": "Erstellt",
|
||||||
|
"endDate": "Enddatum",
|
||||||
|
"dueDate": "Fälligkeitsdatum",
|
||||||
|
"title": "Titel",
|
||||||
|
"startDate": "Anfangsdatum",
|
||||||
|
"relatedTasks": "Verwandte Aufgaben",
|
||||||
|
"priority": "Priorität",
|
||||||
|
"percentDone": "% erledigt",
|
||||||
|
"repeat": "Wiederholen",
|
||||||
|
"reminders": "Erinnerungen",
|
||||||
|
"updated": "Aktualisiert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"team": {
|
||||||
|
"edit": {
|
||||||
|
"delete": {
|
||||||
|
"header": "Team löschen",
|
||||||
|
"success": "Das Team wurde erfolgreich gelöscht."
|
||||||
|
},
|
||||||
|
"madeAdmin": "Das Teammitglied wurde erfolgreich zum Admin gemacht.",
|
||||||
|
"madeMember": "Das Teammitglied wurde erfolgreich zum Mitglied gemacht.",
|
||||||
|
"userAddedSuccess": "Das Teammitglied wurde erfolgreich hinzugefügt.",
|
||||||
|
"success": "Das Team wurde erfolgreich aktualisiert.",
|
||||||
|
"addUser": "Zum Team hinzufügen",
|
||||||
|
"members": "Teammitglieder",
|
||||||
|
"title": "Team „{team}“ bearbeiten",
|
||||||
|
"deleteUser": {
|
||||||
|
"header": "Benutzer aus dem Team entfernen"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"create": {
|
||||||
|
"success": "Das Team wurde erfolgreich erstellt.",
|
||||||
|
"title": "Ein neues Team erstellen"
|
||||||
|
},
|
||||||
|
"title": "Teams",
|
||||||
|
"attributes": {
|
||||||
|
"description": "Beschreibung",
|
||||||
|
"descriptionPlaceholder": "Die Beschreibung des Teams steht hier …",
|
||||||
|
"member": "Mitglied",
|
||||||
|
"admin": "Admin",
|
||||||
|
"name": "Teamname",
|
||||||
|
"namePlaceholder": "Der Name des Teams steht hier …"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"namespace": {
|
||||||
|
"create": {
|
||||||
|
"explanation": "Ein Namensraum ist eine Sammlung von Listen, die man teilen und verwenden kann, um seine Listen zu organisieren. Tatsächlich gehört jede Liste zu einem Namensraum.",
|
||||||
|
"success": "Der Namensraum wurde erfolgreich angelegt.",
|
||||||
|
"tooltip": "Was ist ein Namensraum?",
|
||||||
|
"title": "Einen neuen Namensraum erstellen"
|
||||||
|
},
|
||||||
|
"attributes": {
|
||||||
|
"isArchived": "Dieser Namensraum wird archiviert",
|
||||||
|
"archived": "Ist archiviert",
|
||||||
|
"color": "Farbe",
|
||||||
|
"descriptionPlaceholder": "Die Beschreibung des Namensraums steht hier …",
|
||||||
|
"description": "Beschreibung",
|
||||||
|
"titlePlaceholder": "Der Titel des Namensraums steht hier …",
|
||||||
|
"title": "Namensraumtitel"
|
||||||
|
},
|
||||||
|
"share": {
|
||||||
|
"title": "„{namespace}“ teilen"
|
||||||
|
},
|
||||||
|
"edit": {
|
||||||
|
"success": "Der Namensraum wurde erfolgreich aktualisiert.",
|
||||||
|
"title": "„{namespace}“ bearbeiten"
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"success": "Der Namensraum wurde erfolgreich gelöscht.",
|
||||||
|
"text2": "Dies umfasst alle Listen und Aufgaben und kann NICHT rückgängig gemacht werden!",
|
||||||
|
"title": "„{namespace}“ löschen"
|
||||||
|
},
|
||||||
|
"archive": {
|
||||||
|
"description": "Wenn ein Namensraum archiviert ist, kann man keine neuen Listen erstellen oder ihn bearbeiten.",
|
||||||
|
"success": "Der Namensraum wurde erfolgreich archiviert.",
|
||||||
|
"titleUnarchive": "Archivierung von „{namespace}“ aufheben",
|
||||||
|
"titleArchive": "„{namespace}“ archivieren"
|
||||||
|
},
|
||||||
|
"noLists": "Dieser Namensraum enthält keine Listen.",
|
||||||
|
"title": "Namensräume & Listen",
|
||||||
|
"unarchive": "Archivierung aufheben",
|
||||||
|
"archived": "Archiviert",
|
||||||
|
"showArchived": "Archivierte anzeigen"
|
||||||
|
},
|
||||||
|
"list": {
|
||||||
|
"kanban": {
|
||||||
|
"bucketTitleSavedSuccess": "Der Eimertitel wurde erfolgreich gespeichert.",
|
||||||
|
"deleteBucketSuccess": "Der Eimer wurde erfolgreich gelöscht.",
|
||||||
|
"deleteBucketText2": "Dies löscht keine Aufgaben, sondern verschiebt sie in den Standard-Eimer.",
|
||||||
|
"deleteHeaderBucket": "Den Eimer löschen",
|
||||||
|
"addBucket": "Einen neuen Eimer erstellen",
|
||||||
|
"addAnotherTask": "Weitere Aufgabe hinzufügen",
|
||||||
|
"addTask": "Eine Aufgabe hinzufügen",
|
||||||
|
"doneBucket": "Erledigte-Dinge-Eimer",
|
||||||
|
"noLimit": "Nicht eingestellt"
|
||||||
|
},
|
||||||
|
"table": {
|
||||||
|
"columns": "Spalten",
|
||||||
|
"title": "Tabelle"
|
||||||
|
},
|
||||||
|
"gantt": {
|
||||||
|
"to": "An",
|
||||||
|
"from": "Von",
|
||||||
|
"day": "Tag",
|
||||||
|
"month": "Monat",
|
||||||
|
"default": "Standard",
|
||||||
|
"size": "Größe",
|
||||||
|
"showTasksWithoutDates": "Aufgaben anzeigen, für die keine Termine festgelegt sind",
|
||||||
|
"title": "Gantt"
|
||||||
|
},
|
||||||
|
"list": {
|
||||||
|
"empty": "Diese Liste ist derzeit leer.",
|
||||||
|
"addPlaceholder": "Eine neue Aufgabe hinzufügen …",
|
||||||
|
"add": "Hinzufügen",
|
||||||
|
"title": "Liste"
|
||||||
|
},
|
||||||
|
"share": {
|
||||||
|
"title": "„{Liste}“ teilen",
|
||||||
|
"header": "Diese Liste teilen"
|
||||||
|
},
|
||||||
|
"edit": {
|
||||||
|
"success": "Die Liste wurde erfolgreich aktualisiert.",
|
||||||
|
"color": "Farbe",
|
||||||
|
"descriptionPlaceholder": "Die Listenbeschreibung geht hier …",
|
||||||
|
"description": "Beschreibung",
|
||||||
|
"identifierPlaceholder": "Der Listenbezeichner geht hier …",
|
||||||
|
"identifier": "Listebezeichner",
|
||||||
|
"identifierTooltip": "Der Listenbezeichner kann zur eindeutigen Identifizierung einer Aufgabe über Listen hinweg verwendet werden. Man kann ihn auf leer setzen, um ihn zu deaktivieren.",
|
||||||
|
"titlePlaceholder": "Der Titel der Liste steht hier …",
|
||||||
|
"title": "„{list}“ bearbeiten",
|
||||||
|
"header": "Diese Liste bearbeiten"
|
||||||
|
},
|
||||||
|
"duplicate": {
|
||||||
|
"success": "Die Liste wurde erfolgreich dupliziert.",
|
||||||
|
"label": "Duplizieren",
|
||||||
|
"title": "Diese Liste duplizieren"
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"success": "Die Liste wurde erfolgreich gelöscht.",
|
||||||
|
"text2": "Dies umfasst alle Aufgaben und kann NICHT rückgängig gemacht werden!",
|
||||||
|
"header": "Diese Liste löschen",
|
||||||
|
"title": "„{list}“ löschen"
|
||||||
|
},
|
||||||
|
"background": {
|
||||||
|
"removeSuccess": "Der Hintergrund ist erfolgreich entfernt worden!",
|
||||||
|
"success": "Der Hintergrund ist erfolgreich eingestellt worden!",
|
||||||
|
"loadMore": "Mehr Fotos laden",
|
||||||
|
"poweredByUnsplash": "Angetrieben von Unsplash",
|
||||||
|
"searchPlaceholder": "Nach einem Hintergrund suchen …",
|
||||||
|
"remove": "Hintergrund entfernen",
|
||||||
|
"title": "Listenhintergrund festlegen"
|
||||||
|
},
|
||||||
|
"archive": {
|
||||||
|
"success": "Die Liste wurde erfolgreich archiviert.",
|
||||||
|
"unarchive": "Archivierung dieser Liste aufheben",
|
||||||
|
"archive": "Diese Liste archivieren",
|
||||||
|
"title": "„{Liste}“ archivieren"
|
||||||
|
},
|
||||||
|
"create": {
|
||||||
|
"createdSuccess": "Die Liste wurde erfolgreich erstellt.",
|
||||||
|
"titlePlaceholder": "Der Titel der Liste steht hier …",
|
||||||
|
"header": "Eine neue Liste erstellen"
|
||||||
|
},
|
||||||
|
"color": "Farbe"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"settings": {
|
||||||
|
"caldav": {
|
||||||
|
"title": "Caldav"
|
||||||
|
},
|
||||||
|
"totp": {
|
||||||
|
"disableSuccess": "Die Zwei-Faktor-Authentifizierung wurde erfolgreich deaktiviert.",
|
||||||
|
"passcode": "Passcode",
|
||||||
|
"enroll": "Einschreiben",
|
||||||
|
"title": "Zwei-Faktor-Authentifizierung"
|
||||||
|
},
|
||||||
|
"general": {
|
||||||
|
"weekStartMonday": "Montag",
|
||||||
|
"weekStartSunday": "Sonntag",
|
||||||
|
"weekStart": "Woche beginnt am",
|
||||||
|
"playSoundWhenDone": "Einen Ton abspielen, wenn Aufgaben als erledigt markiert werden",
|
||||||
|
"discoverableByEmail": "Andere Benutzer mich finden lassen, wenn sie nach meiner vollständigen E-Mail suchen",
|
||||||
|
"discoverableByName": "Andere Benutzer mich finden lassen, wenn sie nach meinem Namen suchen",
|
||||||
|
"overdueReminders": "Mir jeden Morgen Erinnerungen für überfällige unerledigte Aufgaben per E-Mail senden",
|
||||||
|
"emailReminders": "Mir Erinnerungen für Aufgaben per E-Mail senden",
|
||||||
|
"savedSuccess": "Die Einstellungen wurden erfolgreich aktualisiert.",
|
||||||
|
"newName": "Der neue Name",
|
||||||
|
"name": "Name",
|
||||||
|
"title": "Allgemeine Einstellungen"
|
||||||
|
},
|
||||||
|
"updateEmailNew": "Neue E-Mail-Adresse",
|
||||||
|
"passwordUpdateSuccess": "Das Passwort wurde erfolgreich aktualisiert.",
|
||||||
|
"passwordsDontMatch": "Das neue Passwort und seine Bestätigung stimmen nicht überein.",
|
||||||
|
"currentPassword": "Aktuelles Passwort",
|
||||||
|
"newPasswordConfirm": "Neue Passwortbestätigung",
|
||||||
|
"newPassword": "Neues Passwort",
|
||||||
|
"title": "Einstellungen"
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"openIdStateError": "Zustand stimmt nicht überein, weigert sich fortzufahren!",
|
||||||
|
"authenticating": "Authentifizierung …",
|
||||||
|
"loginWith": "Mit {provider} anmelden",
|
||||||
|
"register": "Registrieren",
|
||||||
|
"login": "Anmelden",
|
||||||
|
"totpPlaceholder": "z.B. 123456",
|
||||||
|
"totpTitle": "Zwei-Faktor-Authentifizierungscode",
|
||||||
|
"passwordsDontMatch": "Passwörter stimmen nicht überein",
|
||||||
|
"passwordPlaceholder": "z.B. •••••••••••",
|
||||||
|
"password": "Passwort",
|
||||||
|
"emailPlaceholder": "z.B. frederic@vikunja.io",
|
||||||
|
"email": "E-Mail-Adresse",
|
||||||
|
"usernamePlaceholder": "z.B. frederick",
|
||||||
|
"usernameEmail": "Benutzername oder E-Mail-Adresse",
|
||||||
|
"username": "Benutzername"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"home": {
|
||||||
|
"list": {
|
||||||
|
"new": "Eine neue Liste erstellen"
|
||||||
|
},
|
||||||
|
"welcome": "Hallo {username}"
|
||||||
|
}
|
||||||
|
}
|
|
@ -113,12 +113,11 @@
|
||||||
"scheduledCancelSuccess": "Wir werden deinen Account nicht löschen."
|
"scheduledCancelSuccess": "Wir werden deinen Account nicht löschen."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"title": "Export your Vikunja data",
|
"title": "Exportiere die Daten deines Vikunja-Accounts",
|
||||||
"description": "Du kannst eine Kopie deiner Daten bei Vikunja anfordern. Dazu gehören Namespaces, Listen, Aufgaben und alles, was damit zusammenhängt. Du kannst diese Daten dann in jeder Vikunja-Instanz über die Migrationsfunktion importieren.",
|
"description": "Du kannst eine Kopie deiner Daten bei Vikunja anfordern. Dazu gehören Namespaces, Listen, Aufgaben und alles, was damit zusammenhängt. Du kannst diese Daten dann in jeder Vikunja-Instanz über die Migrationsfunktion importieren.",
|
||||||
"descriptionPasswordRequired": "Bitte gib dein Passwort ein, um fortzufahren:",
|
"descriptionPasswordRequired": "Bitte gib dein Passwort ein, um fortzufahren:",
|
||||||
"request": "Eine Kopie meiner Vikunja Daten anfordern",
|
"request": "Eine Kopie meiner Vikunja Daten anfordern",
|
||||||
"success": "Du hast deine Daten bei Vikunja erfolgreich angefordert! Wir schicken dir eine E-Mail, sobald sie zum Download bereitstehen.",
|
"success": "Du hast deine Daten bei Vikunja erfolgreich angefordert! Wir schicken dir eine E-Mail, sobald sie zum Download bereitstehen."
|
||||||
"downloadTitle": "Download your exported Vikunja data"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
|
@ -113,12 +113,11 @@
|
||||||
"scheduledCancelSuccess": "We will not delete your account."
|
"scheduledCancelSuccess": "We will not delete your account."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"title": "Export your Vikunja data",
|
"title": "Export your Vikunja Data",
|
||||||
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
||||||
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
||||||
"request": "Request a copy of my Vikunja Data",
|
"request": "Request a copy of my Vikunja Data",
|
||||||
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
|
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download."
|
||||||
"downloadTitle": "Download your exported Vikunja data"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
|
|
|
@ -1,101 +1,101 @@
|
||||||
{
|
{
|
||||||
"home": {
|
"home": {
|
||||||
"welcomeNight": "Good Night {username}",
|
"welcomeNight": "Buenas noches {username}",
|
||||||
"welcomeMorning": "Good Morning {username}",
|
"welcomeMorning": "Buenos días {username}",
|
||||||
"welcomeDay": "Hi {username}",
|
"welcomeDay": "Hola {username}",
|
||||||
"welcomeEvening": "Good Evening {username}",
|
"welcomeEvening": "Buenas tardes {username}",
|
||||||
"lastViewed": "Last viewed",
|
"lastViewed": "Visto por última vez",
|
||||||
"list": {
|
"list": {
|
||||||
"newText": "You can create a new list for your new tasks:",
|
"newText": "Puedes crear una nueva lista para las tareas nuevas:",
|
||||||
"new": "Create a new list",
|
"new": "Crear una lista nueva",
|
||||||
"importText": "Or import your lists and tasks from other services into Vikunja:",
|
"importText": "O importa tus listas y tareas de otros servicios a Vikunja:",
|
||||||
"import": "Import your data into Vikunja"
|
"import": "Importa tus datos a Vikunja"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"title": "Not found",
|
"title": "No encontrado",
|
||||||
"text": "The page you requested does not exist."
|
"text": "La página solicitada no existe."
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"auth": {
|
"auth": {
|
||||||
"username": "Username",
|
"username": "Nombre de usuario",
|
||||||
"usernameEmail": "Username Or Email Address",
|
"usernameEmail": "Nombre de usuario o dirección de correo electrónico",
|
||||||
"usernamePlaceholder": "e.g. frederick",
|
"usernamePlaceholder": "p/ej. Federico",
|
||||||
"email": "E-mail address",
|
"email": "Correo electrónico",
|
||||||
"emailPlaceholder": "e.g. frederic@vikunja.io",
|
"emailPlaceholder": "p/ej. frederic@vikunja.io",
|
||||||
"password": "Password",
|
"password": "Contraseña",
|
||||||
"passwordRepeat": "Retype your password",
|
"passwordRepeat": "Reescribe tu contraseña",
|
||||||
"passwordPlaceholder": "e.g. •••••••••••",
|
"passwordPlaceholder": "p/ej. •••••••••••",
|
||||||
"resetPassword": "Reset your password",
|
"resetPassword": "Restablecer tu contraseña",
|
||||||
"resetPasswordAction": "Send me a password reset link",
|
"resetPasswordAction": "Envíame un enlace para restablecer la contraseña",
|
||||||
"resetPasswordSuccess": "Check your inbox! You should have an e-mail with instructions on how to reset your password.",
|
"resetPasswordSuccess": "¡Revisa tu bandeja de entrada! Debes tener un correo electrónico con instrucciones para restablecer tu contraseña.",
|
||||||
"passwordsDontMatch": "Passwords don't match",
|
"passwordsDontMatch": "Las contraseñas no coinciden",
|
||||||
"confirmEmailSuccess": "You successfully confirmed your email! You can log in now.",
|
"confirmEmailSuccess": "Has confirmado correctamente tu correo electrónico. Ya puedes conectarte.",
|
||||||
"totpTitle": "Two Factor Authentication Code",
|
"totpTitle": "Código de autenticación de dos factores",
|
||||||
"totpPlaceholder": "e.g. 123456",
|
"totpPlaceholder": "p/ej. 123456",
|
||||||
"login": "Login",
|
"login": "Ingresar",
|
||||||
"register": "Register",
|
"register": "Registrarse",
|
||||||
"loginWith": "Log in with {provider}",
|
"loginWith": "Inicie sesión con {provider}",
|
||||||
"authenticating": "Authenticating…",
|
"authenticating": "Autenticando…",
|
||||||
"openIdStateError": "State does not match, refusing to continue!",
|
"openIdStateError": "¡El estado no coincide, negándome a continuar!",
|
||||||
"openIdGeneralError": "An error occured while authenticating against the third party.",
|
"openIdGeneralError": "An error occured while authenticating against the third party.",
|
||||||
"logout": "Logout"
|
"logout": "Cerrar sesión"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"title": "Settings",
|
"title": "Opciones",
|
||||||
"newPasswordTitle": "Update Your Password",
|
"newPasswordTitle": "Actualiza tu contraseña",
|
||||||
"newPassword": "New Password",
|
"newPassword": "Nueva contraseña",
|
||||||
"newPasswordConfirm": "New Password Confirmation",
|
"newPasswordConfirm": "Confirmar contraseña",
|
||||||
"currentPassword": "Current Password",
|
"currentPassword": "Contraseña actual",
|
||||||
"currentPasswordPlaceholder": "Your current password",
|
"currentPasswordPlaceholder": "Tu contraseña actual",
|
||||||
"passwordsDontMatch": "The new password and its confirmation don't match.",
|
"passwordsDontMatch": "La contraseña nueva y su confirmación no emparejan.",
|
||||||
"passwordUpdateSuccess": "The password was successfully updated.",
|
"passwordUpdateSuccess": "La contraseña se actualizó correctamente.",
|
||||||
"updateEmailTitle": "Update Your E-Mail Address",
|
"updateEmailTitle": "Actualiza tu dirección de correo electrónico",
|
||||||
"updateEmailNew": "New Email Address",
|
"updateEmailNew": "Nueva dirección de correo electrónico",
|
||||||
"updateEmailSuccess": "Your email address was successfully updated. We've sent you a link to confirm it.",
|
"updateEmailSuccess": "Dirección de correo electrónico actualizada. Haga clic en el enlace del correo electrónico que se te ha enviado para confirmarlo.",
|
||||||
"general": {
|
"general": {
|
||||||
"title": "General Settings",
|
"title": "Configuración General",
|
||||||
"name": "Name",
|
"name": "Nombre",
|
||||||
"newName": "The new Name",
|
"newName": "El nombre nuevo",
|
||||||
"savedSuccess": "The settings were successfully updated.",
|
"savedSuccess": "Configuración actualizada.",
|
||||||
"emailReminders": "Send me reminders for tasks via Email",
|
"emailReminders": "Enviarme recordatorios para tareas por correo electrónico",
|
||||||
"overdueReminders": "Send me reminders for overdue undone tasks via email each morning",
|
"overdueReminders": "Enviarme recordatorios de tareas pendientes atrasadas por correo cada mañana",
|
||||||
"discoverableByName": "Let other users find me when they search for my name",
|
"discoverableByName": "Permitir que otros usuarios me encuentren cuando busquen mi nombre",
|
||||||
"discoverableByEmail": "Let other users find me when they search for my full email",
|
"discoverableByEmail": "Permitir que otros usuarios me encuentren cuando busquen mi correo electrónico completo",
|
||||||
"playSoundWhenDone": "Play a sound when marking tasks as done",
|
"playSoundWhenDone": "Reproducir un sonido cuando marcas tareas como hechas",
|
||||||
"weekStart": "Week starts on",
|
"weekStart": "La semana empieza en",
|
||||||
"weekStartSunday": "Sunday",
|
"weekStartSunday": "domingo",
|
||||||
"weekStartMonday": "Monday",
|
"weekStartMonday": "lunes",
|
||||||
"language": "Language",
|
"language": "Idioma",
|
||||||
"defaultList": "Default List"
|
"defaultList": "Lista predeterminada"
|
||||||
},
|
},
|
||||||
"totp": {
|
"totp": {
|
||||||
"title": "Two Factor Authentication",
|
"title": "Autenticación de dos factores",
|
||||||
"enroll": "Enroll",
|
"enroll": "Inscribirse",
|
||||||
"finishSetupPart1": "To finish your setup, use this secret in your totp app (Google Authenticator or similar):",
|
"finishSetupPart1": "Para finalizar tu configuración, utiliza este secreto en tu aplicación totp (Google Authenticator o similar):",
|
||||||
"finishSetupPart2": "After that, enter a code from your app below.",
|
"finishSetupPart2": "Después, introduce un código de tu aplicación abajo.",
|
||||||
"scanQR": "Alternatively you can scan this QR code:",
|
"scanQR": "Alternativamente, escanea este código QR:",
|
||||||
"passcode": "Passcode",
|
"passcode": "Código de acceso",
|
||||||
"passcodePlaceholder": "A code generated by your totp application",
|
"passcodePlaceholder": "Un código generado por tu aplicación totp",
|
||||||
"setupSuccess": "You've sucessfully set up two factor authentication!",
|
"setupSuccess": "¡Has configurado con éxito la autenticación de dos factores!",
|
||||||
"enterPassword": "Please Enter Your Password",
|
"enterPassword": "Por favor, introduce tu contraseña",
|
||||||
"disable": "Disable two factor authentication",
|
"disable": "Desactivar la autenticación en dos pasos",
|
||||||
"confirmSuccess": "You've successfully confirmed your totp setup and can use it from now on!",
|
"confirmSuccess": "¡Has confirmado con éxito tu configuración totp y puedes usarla a partir de ahora!",
|
||||||
"disableSuccess": "Two factor authentication was sucessfully disabled."
|
"disableSuccess": "La autenticación de dos factores se desactivó correctamente."
|
||||||
},
|
},
|
||||||
"caldav": {
|
"caldav": {
|
||||||
"title": "Caldav",
|
"title": "Caldav",
|
||||||
"howTo": "You can connect Vikunja to caldav clients to view and manage all tasks from different clients. Enter this url into your client:",
|
"howTo": "Puedes conectar Vikunja a los clientes caldav para ver y gestionar todas las tareas desde diferentes clientes. Introduce esta url en tu cliente:",
|
||||||
"more": "More information about caldav in Vikunja"
|
"more": "Más información sobre caldav en Vikunja"
|
||||||
},
|
},
|
||||||
"avatar": {
|
"avatar": {
|
||||||
"title": "Avatar",
|
"title": "Avatar",
|
||||||
"initials": "Initials",
|
"initials": "Iniciales",
|
||||||
"gravatar": "Gravatar",
|
"gravatar": "Gravatar",
|
||||||
"upload": "Upload",
|
"upload": "Subir",
|
||||||
"uploadAvatar": "Upload Avatar",
|
"uploadAvatar": "Subir Avatar",
|
||||||
"statusUpdateSuccess": "Avatar status was updated successfully!",
|
"statusUpdateSuccess": "¡El estado del avatar se ha actualizado correctamente!",
|
||||||
"setSuccess": "The avatar has been set successfully!"
|
"setSuccess": "¡El avatar se ha establecido correctamente!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deletion": {
|
"deletion": {
|
||||||
|
@ -113,153 +113,152 @@
|
||||||
"scheduledCancelSuccess": "We will not delete your account."
|
"scheduledCancelSuccess": "We will not delete your account."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"title": "Export your Vikunja data",
|
"title": "Export your Vikunja Data",
|
||||||
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
||||||
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
||||||
"request": "Request a copy of my Vikunja Data",
|
"request": "Request a copy of my Vikunja Data",
|
||||||
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
|
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download."
|
||||||
"downloadTitle": "Download your exported Vikunja data"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"archived": "This list is archived. It is not possible to create new or edit tasks or it.",
|
"archived": "Esta lista está archivada. No es posible crear nuevas o editar tareas o ello.",
|
||||||
"title": "List Title",
|
"title": "Título de Lista",
|
||||||
"color": "Color",
|
"color": "Color",
|
||||||
"lists": "Lists",
|
"lists": "Listas",
|
||||||
"search": "Type to search for a list…",
|
"search": "Escribe para buscar una lista…",
|
||||||
"searchSelect": "Click or press enter to select this list",
|
"searchSelect": "Haga clic o presione enter para seleccionar esta lista",
|
||||||
"shared": "Shared Lists",
|
"shared": "Listas compartidas",
|
||||||
"create": {
|
"create": {
|
||||||
"header": "Create a new list",
|
"header": "Crear una nueva lista",
|
||||||
"titlePlaceholder": "The list's title goes here…",
|
"titlePlaceholder": "El título de la lista va aquí…",
|
||||||
"addTitleRequired": "Please specify a title.",
|
"addTitleRequired": "Por favor, especifica un título.",
|
||||||
"createdSuccess": "The list was successfully created.",
|
"createdSuccess": "La lista se ha creado correctamente.",
|
||||||
"addListRequired": "Please specify a list or set a default list in the settings."
|
"addListRequired": "Por favor, especifique una lista o establezca una lista por defecto en la configuración."
|
||||||
},
|
},
|
||||||
"archive": {
|
"archive": {
|
||||||
"title": "Archive \"{list}\"",
|
"title": "Archivar \"{list}\"",
|
||||||
"archive": "Archive this list",
|
"archive": "Archivar esta lista",
|
||||||
"unarchive": "Un-Archive this list",
|
"unarchive": "Desarchivar esta lista",
|
||||||
"unarchiveText": "You will be able to create new tasks or edit it.",
|
"unarchiveText": "Podrás crear tareas nuevas o editarlas.",
|
||||||
"archiveText": "You won't be able to edit this list or create new tasks until you un-archive it.",
|
"archiveText": "No podrás editar esta lista ni crear nuevas tareas hasta que la des-archives.",
|
||||||
"success": "The list was successfully archived."
|
"success": "La lista fue archivada exitosamente."
|
||||||
},
|
},
|
||||||
"background": {
|
"background": {
|
||||||
"title": "Set list background",
|
"title": "Establecer el fondo de la lista",
|
||||||
"remove": "Remove Background",
|
"remove": "Eliminar fondo",
|
||||||
"upload": "Choose a background from your pc",
|
"upload": "Elige un fondo de tu pc",
|
||||||
"searchPlaceholder": "Search for a background…",
|
"searchPlaceholder": "Buscar un fondo…",
|
||||||
"poweredByUnsplash": "Powered by Unsplash",
|
"poweredByUnsplash": "Con tecnología de Unsplash",
|
||||||
"loadMore": "Load more photos",
|
"loadMore": "Cargar más fotos",
|
||||||
"success": "The background has been set successfully!",
|
"success": "¡El fondo se ha establecido correctamente!",
|
||||||
"removeSuccess": "The background has been removed successfully!"
|
"removeSuccess": "¡El fondo se ha eliminado exitosamente!"
|
||||||
},
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
"title": "Delete \"{list}\"",
|
"title": "Eliminar \"{list}\"",
|
||||||
"header": "Delete this list",
|
"header": "Eliminar esta lista",
|
||||||
"text1": "Are you sure you want to delete this list and all of its contents?",
|
"text1": "¿Estás seguro de que quieres eliminar esta lista y todo su contenido?",
|
||||||
"text2": "This includes all tasks and CANNOT BE UNDONE!",
|
"text2": "¡Esto incluye todas las tareas y NO PUEDE SER DESHACIDO!",
|
||||||
"success": "The list was successfully deleted."
|
"success": "La lista se ha eliminado correctamente."
|
||||||
},
|
},
|
||||||
"duplicate": {
|
"duplicate": {
|
||||||
"title": "Duplicate this list",
|
"title": "Duplicar esta lista",
|
||||||
"label": "Duplicate",
|
"label": "Duplicar",
|
||||||
"text": "Select a namespace which should hold the duplicated list:",
|
"text": "Select a namespace which should hold the duplicated list:",
|
||||||
"success": "The list was successfully duplicated."
|
"success": "La lista se ha duplicado exitosamente."
|
||||||
},
|
},
|
||||||
"edit": {
|
"edit": {
|
||||||
"header": "Edit This List",
|
"header": "Editar esta lista",
|
||||||
"title": "Edit \"{list}\"",
|
"title": "Editar \"{list}\"",
|
||||||
"titlePlaceholder": "The list title goes here…",
|
"titlePlaceholder": "El título de la lista va aquí…",
|
||||||
"identifierTooltip": "The list identifier can be used to uniquely identify a task across lists. You can set it to empty to disable it.",
|
"identifierTooltip": "El identificador de lista se puede usar para identificar una tarea de forma única a través de las listas. Puedes establecerlo en blanco para desactivarlo.",
|
||||||
"identifier": "List Identifier",
|
"identifier": "Identificador de la lista",
|
||||||
"identifierPlaceholder": "The list identifier goes here…",
|
"identifierPlaceholder": "El identificador de la lista va aquí…",
|
||||||
"description": "Description",
|
"description": "Descripción",
|
||||||
"descriptionPlaceholder": "The lists description goes here…",
|
"descriptionPlaceholder": "La descripción de la lista va aquí…",
|
||||||
"color": "Color",
|
"color": "Color",
|
||||||
"success": "The list was successfully updated."
|
"success": "La lista se ha actualizado correctamente."
|
||||||
},
|
},
|
||||||
"share": {
|
"share": {
|
||||||
"header": "Share this list",
|
"header": "Compartir esta lista",
|
||||||
"title": "Share \"{list}\"",
|
"title": "Compartir \"{list}\"",
|
||||||
"share": "Share",
|
"share": "Compartir",
|
||||||
"links": {
|
"links": {
|
||||||
"title": "Share Links",
|
"title": "Compartir enlaces",
|
||||||
"what": "What is a share link?",
|
"what": "¿Qué es un enlace compartido?",
|
||||||
"explanation": "Share Links allow you to easily share a list with other users who don't have an account on Vikunja.",
|
"explanation": "Enlaces compartidos te permiten compartir fácilmente una lista con otros usuarios que no tienen una cuenta de Vikunja.",
|
||||||
"create": "Create a new link share",
|
"create": "Crear un nuevo enlace compartido",
|
||||||
"name": "Name (optional)",
|
"name": "Nombre (opcional)",
|
||||||
"namePlaceholder": "e.g. Lorem Ipsum",
|
"namePlaceholder": "e.g. Lorem Ipsum",
|
||||||
"nameExplanation": "All actions done by this link share will show up with the name.",
|
"nameExplanation": "All actions done by this link share will show up with the name.",
|
||||||
"password": "Password (optional)",
|
"password": "Contraseña (opcional)",
|
||||||
"passwordExplanation": "When authenticating, the user will be required to enter this password.",
|
"passwordExplanation": "When authenticating, the user will be required to enter this password.",
|
||||||
"noName": "No name set",
|
"noName": "Sin nombre establecido",
|
||||||
"remove": "Remove a link share",
|
"remove": "Eliminar un enlace compartido",
|
||||||
"removeText": "Are you sure you want to remove this link share? It will no longer be possible to access this list with this link share. This cannot be undone!",
|
"removeText": "¿Está seguro de que desea eliminar este enlace compartido? Ya no será posible acceder a esta lista con este enlace compartido. ¡Esto no se puede deshacer!",
|
||||||
"createSuccess": "The link share was successfully created.",
|
"createSuccess": "El enlace compartido se ha creado correctamente.",
|
||||||
"deleteSuccess": "The link share was successfully deleted"
|
"deleteSuccess": "El enlace compartido se ha eliminado correctamente"
|
||||||
},
|
},
|
||||||
"userTeam": {
|
"userTeam": {
|
||||||
"typeUser": "user | users",
|
"typeUser": "usuario | usuarios",
|
||||||
"typeTeam": "team | teams",
|
"typeTeam": "equipo | equipos",
|
||||||
"shared": "Shared with these {type}",
|
"shared": "Compartido con estos {type}",
|
||||||
"you": "You",
|
"you": "Tú",
|
||||||
"notShared": "Not shared with any {type} yet.",
|
"notShared": "Aún no se ha compartido con {type}.",
|
||||||
"removeHeader": "Remove a {type} from the {sharable}",
|
"removeHeader": "Eliminar un {type} de la {sharable}",
|
||||||
"removeText": "Are you sure you want to remove this {sharable} from the {type}? This cannot be undone!",
|
"removeText": "¿Estás seguro de que quieres eliminar este {sharable} del {type}? ¡Esto no se puede deshacer!",
|
||||||
"removeSuccess": "The {sharable} was successfully removed from the {type}.",
|
"removeSuccess": "El {sharable} fue eliminado correctamente de {type}.",
|
||||||
"addedSuccess": "The {type} was successfully added.",
|
"addedSuccess": "El {type} se ha añadido correctamente.",
|
||||||
"updatedSuccess": "The {type} was successfully added."
|
"updatedSuccess": "El {type} fue añadido correctamente."
|
||||||
},
|
},
|
||||||
"right": {
|
"right": {
|
||||||
"title": "Right",
|
"title": "Correcto",
|
||||||
"read": "Read only",
|
"read": "Solo lectura",
|
||||||
"readWrite": "Read & write",
|
"readWrite": "Lectura y escritura",
|
||||||
"admin": "Admin"
|
"admin": "Admin"
|
||||||
},
|
},
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"link": "Link",
|
"link": "Enlace",
|
||||||
"name": "Name",
|
"name": "Nombre",
|
||||||
"sharedBy": "Shared by",
|
"sharedBy": "Compartido por",
|
||||||
"right": "Right",
|
"right": "Correcto",
|
||||||
"delete": "Delete"
|
"delete": "Eliminar"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"title": "List",
|
"title": "Lista",
|
||||||
"add": "Add",
|
"add": "Añadir",
|
||||||
"addPlaceholder": "Add a new task…",
|
"addPlaceholder": "Añadir una nueva tarea…",
|
||||||
"empty": "This list is currently empty.",
|
"empty": "Esta lista está vacía actualmente.",
|
||||||
"newTaskCta": "Create a new task.",
|
"newTaskCta": "Crear una nueva tarea.",
|
||||||
"editTask": "Edit Task"
|
"editTask": "Editar Tarea"
|
||||||
},
|
},
|
||||||
"gantt": {
|
"gantt": {
|
||||||
"title": "Gantt",
|
"title": "Gantt",
|
||||||
"showTasksWithoutDates": "Show tasks which don't have dates set",
|
"showTasksWithoutDates": "Mostrar tareas que no tienen fechas establecidas",
|
||||||
"size": "Size",
|
"size": "Tamaño",
|
||||||
"default": "Default",
|
"default": "Predeterminado",
|
||||||
"month": "Month",
|
"month": "Mes",
|
||||||
"day": "Day",
|
"day": "Día",
|
||||||
"from": "From",
|
"from": "Desde",
|
||||||
"to": "To",
|
"to": "Hasta",
|
||||||
"noDates": "This task has no dates set."
|
"noDates": "Esta tarea no tiene fechas establecidas."
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
"title": "Table",
|
"title": "Tabla",
|
||||||
"columns": "Columns"
|
"columns": "Columnas"
|
||||||
},
|
},
|
||||||
"kanban": {
|
"kanban": {
|
||||||
"title": "Kanban",
|
"title": "Kanban",
|
||||||
"limit": "Limit: {limit}",
|
"limit": "Límite: {limit}",
|
||||||
"noLimit": "Not Set",
|
"noLimit": "No establecido",
|
||||||
"doneBucket": "Done bucket",
|
"doneBucket": "Done bucket",
|
||||||
"doneBucketHint": "All tasks moved into this bucket will automatically marked as done.",
|
"doneBucketHint": "All tasks moved into this bucket will automatically marked as done.",
|
||||||
"doneBucketHintExtended": "All tasks moved into the done bucket will be marked as done automatically. All tasks marked as done from elsewhere will be moved as well.",
|
"doneBucketHintExtended": "Todas las tareas que se trasladen al depósito de finalizadas se marcarán como realizadas automáticamente. Todas las tareas marcadas como realizadas desde otro lugar también se moverán.",
|
||||||
"doneBucketSavedSuccess": "The done bucket has been saved successfully.",
|
"doneBucketSavedSuccess": "The done bucket has been saved successfully.",
|
||||||
"deleteLast": "You cannot remove the last bucket.",
|
"deleteLast": "You cannot remove the last bucket.",
|
||||||
"addTaskPlaceholder": "Enter the new task title…",
|
"addTaskPlaceholder": "Introduce el nuevo título de la tarea…",
|
||||||
"addTask": "Add a task",
|
"addTask": "Añadir una tarea",
|
||||||
"addAnotherTask": "Add another task",
|
"addAnotherTask": "Añadir otra tarea",
|
||||||
"addBucket": "Create a new bucket",
|
"addBucket": "Create a new bucket",
|
||||||
"addBucketPlaceholder": "Enter the new bucket title…",
|
"addBucketPlaceholder": "Enter the new bucket title…",
|
||||||
"deleteHeaderBucket": "Delete the bucket",
|
"deleteHeaderBucket": "Delete the bucket",
|
||||||
|
@ -272,82 +271,82 @@
|
||||||
},
|
},
|
||||||
"pseudo": {
|
"pseudo": {
|
||||||
"favorites": {
|
"favorites": {
|
||||||
"title": "Favorites"
|
"title": "Favoritos"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"namespace": {
|
"namespace": {
|
||||||
"title": "Namespaces & Lists",
|
"title": "Namespaces & Lists",
|
||||||
"namespace": "Namespace",
|
"namespace": "Namespace",
|
||||||
"showArchived": "Show Archived",
|
"showArchived": "Mostrar archivados",
|
||||||
"noneAvailable": "You don't have any namespaces right now.",
|
"noneAvailable": "You don't have any namespaces right now.",
|
||||||
"unarchive": "Un-Archive",
|
"unarchive": "Des-archivar",
|
||||||
"archived": "Archived",
|
"archived": "Archivado",
|
||||||
"noLists": "This namespace does not contain any lists.",
|
"noLists": "This namespace does not contain any lists.",
|
||||||
"createList": "Create a new list in this namespace.",
|
"createList": "Create a new list in this namespace.",
|
||||||
"namespaces": "Namespaces",
|
"namespaces": "Namespaces",
|
||||||
"search": "Type to search for a namespace…",
|
"search": "Type to search for a namespace…",
|
||||||
"create": {
|
"create": {
|
||||||
"title": "Create a new namespace",
|
"title": "Create a new namespace",
|
||||||
"titleRequired": "Please specify a title.",
|
"titleRequired": "Por favor, especifica un título.",
|
||||||
"explanation": "A namespace is a collection of lists you can share and use to organize your lists with. In fact, every list belongs to a namepace.",
|
"explanation": "A namespace is a collection of lists you can share and use to organize your lists with. In fact, every list belongs to a namepace.",
|
||||||
"tooltip": "What's a namespace?",
|
"tooltip": "What's a namespace?",
|
||||||
"success": "The namespace was successfully created."
|
"success": "The namespace was successfully created."
|
||||||
},
|
},
|
||||||
"archive": {
|
"archive": {
|
||||||
"titleArchive": "Archive \"{namespace}\"",
|
"titleArchive": "Archivar \"{namespace}\"",
|
||||||
"titleUnarchive": "Un-Archive \"{namespace}\"",
|
"titleUnarchive": "Des-archivar \"{namespace}\"",
|
||||||
"archiveText": "You won't be able to edit this namespace or create new lists until you un-archive it. This will also archive all lists in this namespace.",
|
"archiveText": "You won't be able to edit this namespace or create new lists until you un-archive it. This will also archive all lists in this namespace.",
|
||||||
"unarchiveText": "You will be able to create new lists or edit it.",
|
"unarchiveText": "You will be able to create new lists or edit it.",
|
||||||
"success": "The namespace was successfully archived.",
|
"success": "The namespace was successfully archived.",
|
||||||
"description": "If a namespace is archived, you cannot create new lists or edit it."
|
"description": "If a namespace is archived, you cannot create new lists or edit it."
|
||||||
},
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
"title": "Delete \"{namespace}\"",
|
"title": "Eliminar \"{namespace}\"",
|
||||||
"text1": "Are you sure you want to delete this namespace and all of its contents?",
|
"text1": "Are you sure you want to delete this namespace and all of its contents?",
|
||||||
"text2": "This includes all lists and tasks and CANNOT BE UNDONE!",
|
"text2": "This includes all lists and tasks and CANNOT BE UNDONE!",
|
||||||
"success": "The namespace was successfully deleted."
|
"success": "The namespace was successfully deleted."
|
||||||
},
|
},
|
||||||
"edit": {
|
"edit": {
|
||||||
"title": "Edit \"{namespace}\"",
|
"title": "Editar \"{namespace}\"",
|
||||||
"success": "The namespace was successfully updated."
|
"success": "The namespace was successfully updated."
|
||||||
},
|
},
|
||||||
"share": {
|
"share": {
|
||||||
"title": "Share \"{namespace}\""
|
"title": "Compartir \"{namespace}\""
|
||||||
},
|
},
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"title": "Namespace Title",
|
"title": "Namespace Title",
|
||||||
"titlePlaceholder": "The namespace title goes here…",
|
"titlePlaceholder": "The namespace title goes here…",
|
||||||
"description": "Description",
|
"description": "Descripción",
|
||||||
"descriptionPlaceholder": "The namespaces description goes here…",
|
"descriptionPlaceholder": "The namespaces description goes here…",
|
||||||
"color": "Color",
|
"color": "Color",
|
||||||
"archived": "Is Archived",
|
"archived": "Está archivado",
|
||||||
"isArchived": "This namespace is archived"
|
"isArchived": "This namespace is archived"
|
||||||
},
|
},
|
||||||
"pseudo": {
|
"pseudo": {
|
||||||
"sharedLists": {
|
"sharedLists": {
|
||||||
"title": "Shared Lists"
|
"title": "Listas compartidas"
|
||||||
},
|
},
|
||||||
"favorites": {
|
"favorites": {
|
||||||
"title": "Favorites"
|
"title": "Favoritos"
|
||||||
},
|
},
|
||||||
"savedFilters": {
|
"savedFilters": {
|
||||||
"title": "Filters"
|
"title": "Filtros"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"filters": {
|
"filters": {
|
||||||
"title": "Filters",
|
"title": "Filtros",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"title": "Title",
|
"title": "Título",
|
||||||
"titlePlaceholder": "The saved filter title goes here…",
|
"titlePlaceholder": "El título del filtro guardado va acá…",
|
||||||
"description": "Description",
|
"description": "Descripción",
|
||||||
"descriptionPlaceholder": "The description goes here…",
|
"descriptionPlaceholder": "La descripción va aquí…",
|
||||||
"includeNulls": "Include Tasks which don't have a value set",
|
"includeNulls": "Include Tasks which don't have a value set",
|
||||||
"requireAll": "Require all filters to be true for a task to show up",
|
"requireAll": "Require all filters to be true for a task to show up",
|
||||||
"showDoneTasks": "Show Done Tasks",
|
"showDoneTasks": "Mostrar tareas completadas",
|
||||||
"enablePriority": "Enable Filter By Priority",
|
"enablePriority": "Activar filtro por prioridad",
|
||||||
"enablePercentDone": "Enable Filter By Percent Done",
|
"enablePercentDone": "Activar filtro por porcentaje completado",
|
||||||
"dueDateRange": "Due Date Range",
|
"dueDateRange": "Due Date Range",
|
||||||
"startDateRange": "Start Date Range",
|
"startDateRange": "Start Date Range",
|
||||||
"endDateRange": "End Date Range",
|
"endDateRange": "End Date Range",
|
||||||
|
@ -355,11 +354,11 @@
|
||||||
},
|
},
|
||||||
"create": {
|
"create": {
|
||||||
"title": "Create A Saved Filter",
|
"title": "Create A Saved Filter",
|
||||||
"description": "A saved filter is a virtual list which is computed from a set of filters each time it is accessed. Once created, it will appear in a special namespace.",
|
"description": "Un filtro guardado es una lista virtual que se calcula a partir de un conjunto de filtros cada vez que se accede a él. Una vez creado, aparecerá en un espacio de nombres especial.",
|
||||||
"action": "Create new saved filter"
|
"action": "Create new saved filter"
|
||||||
},
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
"header": "Delete this saved filter",
|
"header": "Eliminar este filtro guardado",
|
||||||
"text": "Are you sure you want to delete this saved filter?",
|
"text": "Are you sure you want to delete this saved filter?",
|
||||||
"success": "The filter was deleted successfully."
|
"success": "The filter was deleted successfully."
|
||||||
},
|
},
|
||||||
|
@ -375,37 +374,37 @@
|
||||||
"description": "Click on the logo of one of the third-party services below to get started.",
|
"description": "Click on the logo of one of the third-party services below to get started.",
|
||||||
"descriptionDo": "Vikunja will import all lists, tasks, notes, reminders and files you have access to.",
|
"descriptionDo": "Vikunja will import all lists, tasks, notes, reminders and files you have access to.",
|
||||||
"authorize": "To authorize Vikunja to access your {name} Account, click the button below.",
|
"authorize": "To authorize Vikunja to access your {name} Account, click the button below.",
|
||||||
"getStarted": "Get Started",
|
"getStarted": "Empecemos",
|
||||||
"inProgress": "Importing in progress…",
|
"inProgress": "Importando…",
|
||||||
"alreadyMigrated1": "It looks like you've already imported your stuff from {name} at {date}.",
|
"alreadyMigrated1": "It looks like you've already imported your stuff from {name} at {date}.",
|
||||||
"alreadyMigrated2": "Importing again is possible, but might create duplicates. Are you sure?",
|
"alreadyMigrated2": "Importing again is possible, but might create duplicates. Are you sure?",
|
||||||
"confirm": "I am sure, please start migrating now!",
|
"confirm": "¡Estoy seguro de que empiece a migrar ahora!",
|
||||||
"importUpload": "To import data from {name} into Vikunja, click the button below to select a file.",
|
"importUpload": "To import data from {name} into Vikunja, click the button below to select a file.",
|
||||||
"upload": "Upload file"
|
"upload": "Upload file"
|
||||||
},
|
},
|
||||||
"label": {
|
"label": {
|
||||||
"title": "Labels",
|
"title": "Etiquetas",
|
||||||
"manage": "Manage labels",
|
"manage": "Administrar etiquetas",
|
||||||
"description": "Click on a label to edit it. You can edit all labels you created, you can use all labels which are associated with a task to whose list you have access.",
|
"description": "Click on a label to edit it. You can edit all labels you created, you can use all labels which are associated with a task to whose list you have access.",
|
||||||
"newCTA": "You currently do not have any labels.",
|
"newCTA": "You currently do not have any labels.",
|
||||||
"search": "Type to search for a label…",
|
"search": "Escribe para buscar una etiqueta…",
|
||||||
"create": {
|
"create": {
|
||||||
"header": "New label",
|
"header": "Nueva etiqueta",
|
||||||
"title": "Create a new label",
|
"title": "Crear una nueva etiqueta",
|
||||||
"titleRequired": "Please specify a title.",
|
"titleRequired": "Por favor, especifica un título.",
|
||||||
"success": "The label was successfully created."
|
"success": "La etiqueta se ha creado correctamente."
|
||||||
},
|
},
|
||||||
"edit": {
|
"edit": {
|
||||||
"header": "Edit Label",
|
"header": "Editar etiqueta",
|
||||||
"forbidden": "You are not allowed to edit this label because you dont own it.",
|
"forbidden": "You are not allowed to edit this label because you dont own it.",
|
||||||
"success": "The label was successfully updated."
|
"success": "La etiqueta se ha actualizado correctamente."
|
||||||
},
|
},
|
||||||
"deleteSuccess": "The label was successfully deleted.",
|
"deleteSuccess": "La etiqueta se ha eliminado correctamente.",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"title": "Title",
|
"title": "Título",
|
||||||
"titlePlaceholder": "The label title goes here…",
|
"titlePlaceholder": "El título de la etiqueta va aquí…",
|
||||||
"description": "Description",
|
"description": "Descripción",
|
||||||
"descriptionPlaceholder": "Label description",
|
"descriptionPlaceholder": "Descripción de la etiqueta",
|
||||||
"color": "Color"
|
"color": "Color"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -418,78 +417,78 @@
|
||||||
"navigation": {
|
"navigation": {
|
||||||
"overview": "Overview",
|
"overview": "Overview",
|
||||||
"upcoming": "Upcoming",
|
"upcoming": "Upcoming",
|
||||||
"settings": "Settings",
|
"settings": "Opciones",
|
||||||
"imprint": "Imprint",
|
"imprint": "Imprint",
|
||||||
"privacy": "Privacy Policy"
|
"privacy": "Política de privacidad"
|
||||||
},
|
},
|
||||||
"misc": {
|
"misc": {
|
||||||
"loading": "Loading…",
|
"loading": "Cargando…",
|
||||||
"save": "Save",
|
"save": "Guardar",
|
||||||
"delete": "Delete",
|
"delete": "Eliminar",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirmar",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancelar",
|
||||||
"refresh": "Refresh",
|
"refresh": "Recargar",
|
||||||
"disable": "Disable",
|
"disable": "Desactivar",
|
||||||
"copy": "Copy to clipboard",
|
"copy": "Copiar al portapapeles",
|
||||||
"search": "Search",
|
"search": "Buscar",
|
||||||
"searchPlaceholder": "Type to search…",
|
"searchPlaceholder": "Type to search…",
|
||||||
"previous": "Previous",
|
"previous": "Anterior",
|
||||||
"next": "Next",
|
"next": "Siguiente",
|
||||||
"poweredBy": "Powered by Vikunja",
|
"poweredBy": "Powered by Vikunja",
|
||||||
"info": "Info",
|
"info": "Información",
|
||||||
"create": "Create",
|
"create": "Crear",
|
||||||
"doit": "Do it!",
|
"doit": "¡Hazlo!",
|
||||||
"saving": "Saving…",
|
"saving": "Guardando…",
|
||||||
"saved": "Saved!",
|
"saved": "¡Guardado!",
|
||||||
"default": "Default",
|
"default": "Predeterminado",
|
||||||
"close": "Close",
|
"close": "Cerrar",
|
||||||
"download": "Download"
|
"download": "Download"
|
||||||
},
|
},
|
||||||
"input": {
|
"input": {
|
||||||
"resetColor": "Reset Color",
|
"resetColor": "Restablecer color",
|
||||||
"datepicker": {
|
"datepicker": {
|
||||||
"today": "Today",
|
"today": "Hoy",
|
||||||
"tomorrow": "Tomorrow",
|
"tomorrow": "Mañana",
|
||||||
"nextMonday": "Next Monday",
|
"nextMonday": "El próximo lunes",
|
||||||
"thisWeekend": "This Weekend",
|
"thisWeekend": "Este fin de semana",
|
||||||
"laterThisWeek": "Later This Week",
|
"laterThisWeek": "Más tarde esta semana",
|
||||||
"nextWeek": "Next Week",
|
"nextWeek": "La próxima semana",
|
||||||
"chooseDate": "Choose a date"
|
"chooseDate": "Elige una fecha"
|
||||||
},
|
},
|
||||||
"editor": {
|
"editor": {
|
||||||
"edit": "Edit",
|
"edit": "Editar",
|
||||||
"done": "Done",
|
"done": "Hecho",
|
||||||
"heading1": "Heading 1",
|
"heading1": "Heading 1",
|
||||||
"heading2": "Heading 2",
|
"heading2": "Heading 2",
|
||||||
"heading3": "Heading 3",
|
"heading3": "Heading 3",
|
||||||
"headingSmaller": "Heading Smaller",
|
"headingSmaller": "Heading Smaller",
|
||||||
"headingBigger": "Heading Bigger",
|
"headingBigger": "Heading Bigger",
|
||||||
"bold": "Bold",
|
"bold": "Negrita",
|
||||||
"italic": "Italic",
|
"italic": "Cursiva",
|
||||||
"strikethrough": "Strikethrough",
|
"strikethrough": "Tachado",
|
||||||
"code": "Code",
|
"code": "Código",
|
||||||
"quote": "Quote",
|
"quote": "Cita",
|
||||||
"unorderedList": "Unordered List",
|
"unorderedList": "Unordered List",
|
||||||
"orderedList": "Ordered List",
|
"orderedList": "Ordered List",
|
||||||
"cleanBlock": "Clean Block",
|
"cleanBlock": "Clean Block",
|
||||||
"link": "Link",
|
"link": "Enlace",
|
||||||
"image": "Image",
|
"image": "Imagen",
|
||||||
"table": "Table",
|
"table": "Tabla",
|
||||||
"horizontalRule": "Horizontal Rule",
|
"horizontalRule": "Horizontal Rule",
|
||||||
"sideBySide": "Side By Side",
|
"sideBySide": "Side By Side",
|
||||||
"guide": "Guide"
|
"guide": "Guide"
|
||||||
},
|
},
|
||||||
"multiselect": {
|
"multiselect": {
|
||||||
"createPlaceholder": "Create new",
|
"createPlaceholder": "Crear nuevo",
|
||||||
"selectPlaceholder": "Click or press enter to select"
|
"selectPlaceholder": "Click or press enter to select"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"task": {
|
"task": {
|
||||||
"task": "Task",
|
"task": "Tarea",
|
||||||
"new": "Create a new task",
|
"new": "Crear una nueva tarea",
|
||||||
"delete": "Delete this task",
|
"delete": "Eliminar esta tarea",
|
||||||
"createSuccess": "The task was successfully created.",
|
"createSuccess": "The task was successfully created.",
|
||||||
"addReminder": "Add a new reminder…",
|
"addReminder": "Añadir un nuevo recordatorio…",
|
||||||
"doneSuccess": "The task was successfully marked as done.",
|
"doneSuccess": "The task was successfully marked as done.",
|
||||||
"undoneSuccess": "The task was successfully un-marked as done.",
|
"undoneSuccess": "The task was successfully un-marked as done.",
|
||||||
"openDetail": "Open task detail view",
|
"openDetail": "Open task detail view",
|
||||||
|
@ -499,35 +498,35 @@
|
||||||
"noDates": "Show tasks without dates",
|
"noDates": "Show tasks without dates",
|
||||||
"current": "Current tasks",
|
"current": "Current tasks",
|
||||||
"from": "Tasks from",
|
"from": "Tasks from",
|
||||||
"until": "until",
|
"until": "hasta",
|
||||||
"today": "Today",
|
"today": "Hoy",
|
||||||
"nextWeek": "Next Week",
|
"nextWeek": "La próxima semana",
|
||||||
"nextMonth": "Next Month",
|
"nextMonth": "El próximo mes",
|
||||||
"noTasks": "Nothing to do - Have a nice day!"
|
"noTasks": "Nada que hacer - ¡Que tengas un buen día!"
|
||||||
},
|
},
|
||||||
"detail": {
|
"detail": {
|
||||||
"chooseDueDate": "Click here to set a due date",
|
"chooseDueDate": "Click here to set a due date",
|
||||||
"chooseStartDate": "Click here to set a start date",
|
"chooseStartDate": "Click here to set a start date",
|
||||||
"chooseEndDate": "Click here to set an end date",
|
"chooseEndDate": "Click here to set an end date",
|
||||||
"move": "Move task to a different list",
|
"move": "Move task to a different list",
|
||||||
"done": "Done!",
|
"done": "¡Hecho!",
|
||||||
"undone": "Mark as undone",
|
"undone": "Mark as undone",
|
||||||
"created": "Created {0} by {1}",
|
"created": "Created {0} by {1}",
|
||||||
"updated": "Updated {0}",
|
"updated": "Actualizado {0}",
|
||||||
"doneAt": "Done {0}",
|
"doneAt": "Hecho {0}",
|
||||||
"updateSuccess": "The task was saved successfully.",
|
"updateSuccess": "The task was saved successfully.",
|
||||||
"deleteSuccess": "The task has been deleted successfully.",
|
"deleteSuccess": "The task has been deleted successfully.",
|
||||||
"belongsToList": "This task belongs to list '{list}'",
|
"belongsToList": "This task belongs to list '{list}'",
|
||||||
"due": "Due {at}",
|
"due": "Due {at}",
|
||||||
"delete": {
|
"delete": {
|
||||||
"header": "Delete this task",
|
"header": "Eliminar esta tarea",
|
||||||
"text1": "Are you sure you want to remove this task?",
|
"text1": "Are you sure you want to remove this task?",
|
||||||
"text2": "This will also remove all attachments, reminders and relations associated with this task and cannot be undone!"
|
"text2": "This will also remove all attachments, reminders and relations associated with this task and cannot be undone!"
|
||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
"assign": "Assign this task to a user",
|
"assign": "Assign this task to a user",
|
||||||
"label": "Add labels",
|
"label": "Añadir etiquetas",
|
||||||
"priority": "Set Priority",
|
"priority": "Establecer prioridad",
|
||||||
"dueDate": "Set Due Date",
|
"dueDate": "Set Due Date",
|
||||||
"startDate": "Set a Start Date",
|
"startDate": "Set a Start Date",
|
||||||
"endDate": "Set an End Date",
|
"endDate": "Set an End Date",
|
||||||
|
@ -536,7 +535,7 @@
|
||||||
"percentDone": "Set Percent Done",
|
"percentDone": "Set Percent Done",
|
||||||
"attachments": "Add attachments",
|
"attachments": "Add attachments",
|
||||||
"relatedTasks": "Add task relations",
|
"relatedTasks": "Add task relations",
|
||||||
"moveList": "Move task",
|
"moveList": "Mover tarea",
|
||||||
"color": "Set task color",
|
"color": "Set task color",
|
||||||
"delete": "Delete task",
|
"delete": "Delete task",
|
||||||
"favorite": "Save as favorite",
|
"favorite": "Save as favorite",
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -113,12 +113,11 @@
|
||||||
"scheduledCancelSuccess": "We will not delete your account."
|
"scheduledCancelSuccess": "We will not delete your account."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"title": "Export your Vikunja data",
|
"title": "Export your Vikunja Data",
|
||||||
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
||||||
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
||||||
"request": "Request a copy of my Vikunja Data",
|
"request": "Request a copy of my Vikunja Data",
|
||||||
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
|
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download."
|
||||||
"downloadTitle": "Download your exported Vikunja data"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
|
@ -113,12 +113,11 @@
|
||||||
"scheduledCancelSuccess": "We will not delete your account."
|
"scheduledCancelSuccess": "We will not delete your account."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"title": "Export your Vikunja data",
|
"title": "Export your Vikunja Data",
|
||||||
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
||||||
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
||||||
"request": "Request a copy of my Vikunja Data",
|
"request": "Request a copy of my Vikunja Data",
|
||||||
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
|
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download."
|
||||||
"downloadTitle": "Download your exported Vikunja data"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
|
@ -1,34 +1,34 @@
|
||||||
{
|
{
|
||||||
"home": {
|
"home": {
|
||||||
"welcomeNight": "Good Night {username}",
|
"welcomeNight": "Boa noite {username}",
|
||||||
"welcomeMorning": "Good Morning {username}",
|
"welcomeMorning": "Bom dia {username}",
|
||||||
"welcomeDay": "Hi {username}",
|
"welcomeDay": "Olá {username}",
|
||||||
"welcomeEvening": "Good Evening {username}",
|
"welcomeEvening": "Boa tarde {username}",
|
||||||
"lastViewed": "Last viewed",
|
"lastViewed": "Recentes",
|
||||||
"list": {
|
"list": {
|
||||||
"newText": "You can create a new list for your new tasks:",
|
"newText": "Você pode criar uma nova lista para suas novas tarefas:",
|
||||||
"new": "Create a new list",
|
"new": "Criar uma nova lista",
|
||||||
"importText": "Or import your lists and tasks from other services into Vikunja:",
|
"importText": "Ou importe suas listas e tarefas de outros serviços no Vikunja:",
|
||||||
"import": "Import your data into Vikunja"
|
"import": "Importe seus dados para o Vikunja"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"title": "Not found",
|
"title": "Não encontrado",
|
||||||
"text": "The page you requested does not exist."
|
"text": "A página solicitada não existe."
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"auth": {
|
"auth": {
|
||||||
"username": "Username",
|
"username": "Usuário",
|
||||||
"usernameEmail": "Username Or Email Address",
|
"usernameEmail": "Usuário ou Email",
|
||||||
"usernamePlaceholder": "e.g. frederick",
|
"usernamePlaceholder": "ex: lucas",
|
||||||
"email": "E-mail address",
|
"email": "Endereço de e-mail",
|
||||||
"emailPlaceholder": "e.g. frederic@vikunja.io",
|
"emailPlaceholder": "ex: lucas@vikunja.io",
|
||||||
"password": "Password",
|
"password": "Senha",
|
||||||
"passwordRepeat": "Retype your password",
|
"passwordRepeat": "Digite novamente sua senha",
|
||||||
"passwordPlaceholder": "e.g. •••••••••••",
|
"passwordPlaceholder": "ex.: •••••••••••••",
|
||||||
"resetPassword": "Reset your password",
|
"resetPassword": "Redefinir sua senha",
|
||||||
"resetPasswordAction": "Send me a password reset link",
|
"resetPasswordAction": "Envie-me um link para redefinição de senha",
|
||||||
"resetPasswordSuccess": "Check your inbox! You should have an e-mail with instructions on how to reset your password.",
|
"resetPasswordSuccess": "Verifique sua caixa de entrada! Você deve ter um e-mail com instruções sobre como redefinir sua senha.",
|
||||||
"passwordsDontMatch": "Passwords don't match",
|
"passwordsDontMatch": "Passwords don't match",
|
||||||
"confirmEmailSuccess": "You successfully confirmed your email! You can log in now.",
|
"confirmEmailSuccess": "You successfully confirmed your email! You can log in now.",
|
||||||
"totpTitle": "Two Factor Authentication Code",
|
"totpTitle": "Two Factor Authentication Code",
|
||||||
|
@ -113,12 +113,11 @@
|
||||||
"scheduledCancelSuccess": "We will not delete your account."
|
"scheduledCancelSuccess": "We will not delete your account."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"title": "Export your Vikunja data",
|
"title": "Export your Vikunja Data",
|
||||||
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
||||||
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
||||||
"request": "Request a copy of my Vikunja Data",
|
"request": "Request a copy of my Vikunja Data",
|
||||||
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
|
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download."
|
||||||
"downloadTitle": "Download your exported Vikunja data"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -113,12 +113,11 @@
|
||||||
"scheduledCancelSuccess": "We will not delete your account."
|
"scheduledCancelSuccess": "We will not delete your account."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"title": "Export your Vikunja data",
|
"title": "Export your Vikunja Data",
|
||||||
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
"description": "You can request a copy of all your Vikunja data. This include Namespaces, Lists, Tasks and everything associated to them. You can import this data in any Vikunja instance through the migration function.",
|
||||||
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
"descriptionPasswordRequired": "Please enter your password to proceed:",
|
||||||
"request": "Request a copy of my Vikunja Data",
|
"request": "Request a copy of my Vikunja Data",
|
||||||
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download.",
|
"success": "You've successfully requested your Vikunja Data! We will send you an email once it's ready to download."
|
||||||
"downloadTitle": "Download your exported Vikunja data"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -113,12 +113,11 @@
|
||||||
"scheduledCancelSuccess": "Мы не будем удалять твой аккаунт."
|
"scheduledCancelSuccess": "Мы не будем удалять твой аккаунт."
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"title": "Export your Vikunja data",
|
"title": "Экспорт данных Vikunja",
|
||||||
"description": "Ты можешь запросить копию всех своих данных Vikunja. Это включает в себя пространства имён, списки, задачи и всё связанное с ними. Эти данные можно будет импортировать на любом экземпляре Vikunja через функцию миграции.",
|
"description": "Ты можешь запросить копию всех своих данных Vikunja. Это включает в себя пространства имён, списки, задачи и всё связанное с ними. Эти данные можно будет импортировать на любом экземпляре Vikunja через функцию миграции.",
|
||||||
"descriptionPasswordRequired": "Для продолжения введи свой пароль:",
|
"descriptionPasswordRequired": "Для продолжения введи свой пароль:",
|
||||||
"request": "Запросить копию моих данных Vikunja",
|
"request": "Запросить копию моих данных Vikunja",
|
||||||
"success": "Данные Vikunja успешно запрошены! Мы отправим тебе письмо, когда они будут готовы для скачивания.",
|
"success": "Данные Vikunja успешно запрошены! Мы отправим тебе письмо, когда они будут готовы для скачивания."
|
||||||
"downloadTitle": "Download your exported Vikunja data"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
|
@ -14,10 +14,7 @@ export const i18n = new VueI18n({
|
||||||
|
|
||||||
export const availableLanguages = {
|
export const availableLanguages = {
|
||||||
en: 'English',
|
en: 'English',
|
||||||
'de-DE': 'Deutsch',
|
de: 'Deutsch',
|
||||||
'de-swiss': 'Schwizertütsch',
|
|
||||||
'ru-RU': 'Русский',
|
|
||||||
'fr-FR': 'Français',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadedLanguages = ['en'] // our default language that is preloaded
|
const loadedLanguages = ['en'] // our default language that is preloaded
|
||||||
|
@ -51,16 +48,18 @@ export const loadLanguageAsync = lang => {
|
||||||
|
|
||||||
export const getCurrentLanguage = () => {
|
export const getCurrentLanguage = () => {
|
||||||
const savedLanguage = localStorage.getItem('language')
|
const savedLanguage = localStorage.getItem('language')
|
||||||
if (savedLanguage !== null) {
|
if(savedLanguage !== null) {
|
||||||
return savedLanguage
|
return savedLanguage
|
||||||
}
|
}
|
||||||
|
|
||||||
let browserLanguage = navigator.language || navigator.userLanguage
|
let browserLanguage = navigator.language || navigator.userLanguage
|
||||||
|
|
||||||
for (let k in availableLanguages) {
|
if (browserLanguage.startsWith('en-')) {
|
||||||
if (browserLanguage[k] === browserLanguage || k.startsWith(browserLanguage + '-')) {
|
browserLanguage = 'en'
|
||||||
return k
|
}
|
||||||
}
|
|
||||||
|
if (typeof availableLanguages[browserLanguage] !== 'undefined') {
|
||||||
|
return browserLanguage
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'en'
|
return 'en'
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"UNKNOWN": 0,
|
||||||
|
"USER": 1,
|
||||||
|
"LINK_SHARE": 2
|
||||||
|
}
|
|
@ -2,15 +2,12 @@ import AbstractModel from './abstractModel'
|
||||||
import UserModel from './user'
|
import UserModel from './user'
|
||||||
import {colorIsDark} from '@/helpers/color/colorIsDark'
|
import {colorIsDark} from '@/helpers/color/colorIsDark'
|
||||||
|
|
||||||
const DEFAULT_LABEL_BACKGROUND_COLOR = 'e8e8e8'
|
|
||||||
export default class LabelModel extends AbstractModel {
|
export default class LabelModel extends AbstractModel {
|
||||||
constructor(data) {
|
constructor(data) {
|
||||||
super(data)
|
super(data)
|
||||||
// FIXME: this should be empty and be definied in the client.
|
|
||||||
// that way it get's never send to the server db and is easier to change in future versions.
|
|
||||||
// Set the default color
|
// Set the default color
|
||||||
if (this.hexColor === '') {
|
if (this.hexColor === '') {
|
||||||
this.hexColor = DEFAULT_LABEL_BACKGROUND_COLOR
|
this.hexColor = 'e8e8e8'
|
||||||
}
|
}
|
||||||
if (this.hexColor.substring(0, 1) !== '#') {
|
if (this.hexColor.substring(0, 1) !== '#') {
|
||||||
this.hexColor = '#' + this.hexColor
|
this.hexColor = '#' + this.hexColor
|
||||||
|
|
|
@ -5,7 +5,7 @@ import TaskModel from '@/models/task'
|
||||||
import TaskCommentModel from '@/models/taskComment'
|
import TaskCommentModel from '@/models/taskComment'
|
||||||
import ListModel from '@/models/list'
|
import ListModel from '@/models/list'
|
||||||
import TeamModel from '@/models/team'
|
import TeamModel from '@/models/team'
|
||||||
import names from './constants/notificationNames.json'
|
import names from './notificationNames.json'
|
||||||
|
|
||||||
export default class NotificationModel extends AbstractModel {
|
export default class NotificationModel extends AbstractModel {
|
||||||
constructor(data) {
|
constructor(data) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import AbstractModel from './abstractModel'
|
||||||
import UserModel from './user'
|
import UserModel from './user'
|
||||||
import LabelModel from './label'
|
import LabelModel from './label'
|
||||||
import AttachmentModel from './attachment'
|
import AttachmentModel from './attachment'
|
||||||
import {REPEAT_MODE_DEFAULT} from './constants/taskRepeatModes'
|
import {REPEAT_MODE_DEFAULT} from './taskRepeatModes'
|
||||||
|
|
||||||
import SubscriptionModel from '@/models/subscription'
|
import SubscriptionModel from '@/models/subscription'
|
||||||
import {parseDateOrNull} from '@/helpers/parseDateOrNull'
|
import {parseDateOrNull} from '@/helpers/parseDateOrNull'
|
||||||
|
@ -15,7 +15,6 @@ export default class TaskModel extends AbstractModel {
|
||||||
super(data)
|
super(data)
|
||||||
|
|
||||||
this.id = Number(this.id)
|
this.id = Number(this.id)
|
||||||
this.title = this.title?.trim()
|
|
||||||
this.listId = Number(this.listId)
|
this.listId = Number(this.listId)
|
||||||
|
|
||||||
// Make date objects from timestamps
|
// Make date objects from timestamps
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {parseTaskText} from './parseTaskText'
|
import {parseTaskText} from './parseTaskText'
|
||||||
import {getDateFromText, getDateFromTextIn} from '../helpers/time/parseDate'
|
import {getDateFromText, getDateFromTextIn} from '../helpers/time/parseDate'
|
||||||
import {calculateDayInterval} from '../helpers/time/calculateDayInterval'
|
import {calculateDayInterval} from '../helpers/time/calculateDayInterval'
|
||||||
import priorities from '../models/constants/priorities.json'
|
import priorities from '../models/priorities.json'
|
||||||
|
|
||||||
describe('Parse Task Text', () => {
|
describe('Parse Task Text', () => {
|
||||||
it('should return text with no intents as is', () => {
|
it('should return text with no intents as is', () => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {parseDate} from '../helpers/time/parseDate'
|
import {parseDate} from '../helpers/time/parseDate'
|
||||||
import _priorities from '../models/constants/priorities.json'
|
import _priorities from '../models/priorities.json'
|
||||||
|
|
||||||
const LABEL_PREFIX: string = '@'
|
const LABEL_PREFIX: string = '@'
|
||||||
const LIST_PREFIX: string = '#'
|
const LIST_PREFIX: string = '#'
|
||||||
|
|
|
@ -7,9 +7,7 @@ export default class DataExportService extends AbstractService {
|
||||||
}
|
}
|
||||||
|
|
||||||
download(password) {
|
download(password) {
|
||||||
const clear = this.setLoading()
|
|
||||||
return this.getBlobUrl('/user/export/download', 'POST', {password})
|
return this.getBlobUrl('/user/export/download', 'POST', {password})
|
||||||
.then(url => downloadBlob(url, 'vikunja-export.zip'))
|
.then(url => downloadBlob(url, 'vikunja-export.zip'))
|
||||||
.finally(() => clear())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -39,8 +39,6 @@ export default class TaskService extends AbstractService {
|
||||||
|
|
||||||
processModel(model) {
|
processModel(model) {
|
||||||
|
|
||||||
model.title = model.title?.trim()
|
|
||||||
|
|
||||||
// Ensure that listId is an int
|
// Ensure that listId is an int
|
||||||
model.listId = Number(model.listId)
|
model.listId = Number(model.listId)
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ export const store = new Vuex.Store({
|
||||||
state.errorMessage = error
|
state.errorMessage = error
|
||||||
},
|
},
|
||||||
[ONLINE](state, online) {
|
[ONLINE](state, online) {
|
||||||
state.online = import.meta.env.VITE_IS_ONLINE || online
|
state.online = online
|
||||||
},
|
},
|
||||||
[CURRENT_LIST](state, currentList) {
|
[CURRENT_LIST](state, currentList) {
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
|
||||||
import {findIndexById} from '@/helpers/find'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
state: () => ({
|
state: () => ({
|
||||||
|
@ -17,9 +15,13 @@ export default {
|
||||||
state.attachments.push(attachment)
|
state.attachments.push(attachment)
|
||||||
},
|
},
|
||||||
removeById(state, id) {
|
removeById(state, id) {
|
||||||
const attachmentIndex = findIndexById(state.attachments, id)
|
for (const a in state.attachments) {
|
||||||
state.attachments.splice(attachmentIndex, 1)
|
if (state.attachments[a].id === id) {
|
||||||
console.debug('Remove attachement', id)
|
state.attachments.splice(a, 1)
|
||||||
|
console.debug('Remove attachement', id)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
|
@ -3,12 +3,6 @@ import {ERROR_MESSAGE, LOADING} from '../mutation-types'
|
||||||
import UserModel from '../../models/user'
|
import UserModel from '../../models/user'
|
||||||
import {getToken, refreshToken, removeToken, saveToken} from '@/helpers/auth'
|
import {getToken, refreshToken, removeToken, saveToken} from '@/helpers/auth'
|
||||||
|
|
||||||
const AUTH_TYPES = {
|
|
||||||
'UNKNOWN': 0,
|
|
||||||
'USER': 1,
|
|
||||||
'LINK_SHARE': 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultSettings = settings => {
|
const defaultSettings = settings => {
|
||||||
if (typeof settings.weekStart === 'undefined' || settings.weekStart === '') {
|
if (typeof settings.weekStart === 'undefined' || settings.weekStart === '') {
|
||||||
settings.weekStart = 0
|
settings.weekStart = 0
|
||||||
|
@ -27,20 +21,6 @@ export default {
|
||||||
lastUserInfoRefresh: null,
|
lastUserInfoRefresh: null,
|
||||||
settings: {},
|
settings: {},
|
||||||
}),
|
}),
|
||||||
getters: {
|
|
||||||
authUser(state) {
|
|
||||||
return state.authenticated && (
|
|
||||||
state.info &&
|
|
||||||
state.info.type === AUTH_TYPES.USER
|
|
||||||
)
|
|
||||||
},
|
|
||||||
authLinkShare(state) {
|
|
||||||
return state.authenticated && (
|
|
||||||
state.info &&
|
|
||||||
state.info.type === AUTH_TYPES.LINK_SHARE
|
|
||||||
)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mutations: {
|
mutations: {
|
||||||
info(state, info) {
|
info(state, info) {
|
||||||
state.info = info
|
state.info = info
|
||||||
|
|
|
@ -1,12 +1,4 @@
|
||||||
// utilities are imported in variables.scss
|
@import "../../../node_modules/bulma/bulma";
|
||||||
@import "../../../node_modules/bulma/sass/base/_all";
|
|
||||||
@import "../../../node_modules/bulma/sass/elements/_all";
|
|
||||||
@import "../../../node_modules/bulma/sass/form/_all";
|
|
||||||
@import "../../../node_modules/bulma/sass/components/_all";
|
|
||||||
@import "../../../node_modules/bulma/sass/grid/_all";
|
|
||||||
@import "../../../node_modules/bulma/sass/helpers/_all";
|
|
||||||
@import "../../../node_modules/bulma/sass/layout/_all";
|
|
||||||
|
|
||||||
|
|
||||||
@import "fonts";
|
@import "fonts";
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
@import "../../../node_modules/bulma/sass/utilities/_all";
|
|
||||||
|
|
||||||
@import 'colors';
|
@import 'colors';
|
||||||
@import 'shadows';
|
@import 'shadows';
|
||||||
@import 'variables';
|
@import 'variables';
|
|
@ -1,7 +1,7 @@
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
/* eslint-disable no-undef */
|
/* eslint-disable no-undef */
|
||||||
|
|
||||||
const workboxVersion = 'v6.3.0'
|
const workboxVersion = 'v6.2.4'
|
||||||
importScripts( `/workbox-${workboxVersion}/workbox-sw.js`)
|
importScripts( `/workbox-${workboxVersion}/workbox-sw.js`)
|
||||||
workbox.setConfig({modulePathPrefix: `/workbox-${workboxVersion}`})
|
workbox.setConfig({modulePathPrefix: `/workbox-${workboxVersion}`})
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@
|
||||||
<div :ref="`tasks-container${bucket.id}`" class="tasks">
|
<div :ref="`tasks-container${bucket.id}`" class="tasks">
|
||||||
<draggable
|
<draggable
|
||||||
v-model="bucket.tasks"
|
v-model="bucket.tasks"
|
||||||
@start="() => dragstart(bucket)"
|
@start="() => drag = true"
|
||||||
@end="updateTaskPosition"
|
@end="updateTaskPosition"
|
||||||
:group="{name: 'tasks', put: shouldAcceptDrop(bucket) && !dragBucket}"
|
:group="{name: 'tasks', put: shouldAcceptDrop(bucket) && !dragBucket}"
|
||||||
v-bind="dragOptions"
|
v-bind="dragOptions"
|
||||||
|
@ -164,7 +164,7 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<p class="help is-danger" v-if="newTaskError[bucket.id] && newTaskText === ''">
|
<p class="help is-danger" v-if="newTaskError[bucket.id] && newTaskText === ''">
|
||||||
{{ $t('list.create.addTitleRequired') }}
|
{{ $t('list.list.addTitleRequired') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<x-button
|
<x-button
|
||||||
|
@ -232,13 +232,14 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import isTouchDevice from 'is-touch-device'
|
||||||
import draggable from 'vuedraggable'
|
import draggable from 'vuedraggable'
|
||||||
|
|
||||||
import BucketModel from '../../../models/bucket'
|
import BucketModel from '../../../models/bucket'
|
||||||
import {filterObject} from '@/helpers/filterObject'
|
import {filterObject} from '@/helpers/filterObject'
|
||||||
import {mapState} from 'vuex'
|
import {mapState} from 'vuex'
|
||||||
import {saveListView} from '@/helpers/saveListView'
|
import {saveListView} from '@/helpers/saveListView'
|
||||||
import Rights from '../../../models/constants/rights.json'
|
import Rights from '../../../models/rights.json'
|
||||||
import {LOADING, LOADING_MODULE} from '@/store/mutation-types'
|
import {LOADING, LOADING_MODULE} from '@/store/mutation-types'
|
||||||
import FilterPopup from '@/components/list/partials/filter-popup.vue'
|
import FilterPopup from '@/components/list/partials/filter-popup.vue'
|
||||||
import Dropdown from '@/components/misc/dropdown.vue'
|
import Dropdown from '@/components/misc/dropdown.vue'
|
||||||
|
@ -314,8 +315,10 @@ export default {
|
||||||
animation: 150,
|
animation: 150,
|
||||||
ghostClass: 'ghost',
|
ghostClass: 'ghost',
|
||||||
dragClass: 'task-dragging',
|
dragClass: 'task-dragging',
|
||||||
delay: 150,
|
}
|
||||||
delayOnTouchOnly: true,
|
|
||||||
|
if (isTouchDevice()) {
|
||||||
|
options.delay = 150
|
||||||
}
|
}
|
||||||
|
|
||||||
return options
|
return options
|
||||||
|
@ -539,10 +542,6 @@ export default {
|
||||||
bucket.limit === 0 || // If there is no limit set, dragging & dropping should always work
|
bucket.limit === 0 || // If there is no limit set, dragging & dropping should always work
|
||||||
bucket.tasks.length < bucket.limit // Disallow dropping to buckets which have their limit reached
|
bucket.tasks.length < bucket.limit // Disallow dropping to buckets which have their limit reached
|
||||||
},
|
},
|
||||||
dragstart(bucket) {
|
|
||||||
this.drag = true
|
|
||||||
this.sourceBucket = bucket.id
|
|
||||||
},
|
|
||||||
toggleDoneBucket(bucket) {
|
toggleDoneBucket(bucket) {
|
||||||
bucket.isDoneBucket = !bucket.isDoneBucket
|
bucket.isDoneBucket = !bucket.isDoneBucket
|
||||||
this.$store.dispatch('kanban/updateBucket', bucket)
|
this.$store.dispatch('kanban/updateBucket', bucket)
|
||||||
|
|
|
@ -177,7 +177,7 @@ import AddTask from '../../../components/tasks/add-task'
|
||||||
import SingleTaskInList from '../../../components/tasks/partials/singleTaskInList'
|
import SingleTaskInList from '../../../components/tasks/partials/singleTaskInList'
|
||||||
import taskList from '../../../components/tasks/mixins/taskList'
|
import taskList from '../../../components/tasks/mixins/taskList'
|
||||||
import {saveListView} from '@/helpers/saveListView'
|
import {saveListView} from '@/helpers/saveListView'
|
||||||
import Rights from '../../../models/constants/rights.json'
|
import Rights from '../../../models/rights.json'
|
||||||
import FilterPopup from '@/components/list/partials/filter-popup.vue'
|
import FilterPopup from '@/components/list/partials/filter-popup.vue'
|
||||||
import {HAS_TASKS} from '@/store/mutation-types'
|
import {HAS_TASKS} from '@/store/mutation-types'
|
||||||
import Nothing from '@/components/misc/nothing.vue'
|
import Nothing from '@/components/misc/nothing.vue'
|
||||||
|
|
|
@ -286,26 +286,10 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initTasks(page, search = '') {
|
initTasks(page, search = '') {
|
||||||
// This makes sure an id sort order is always sorted last.
|
|
||||||
// When tasks would be sorted first by id and then by whatever else was specified, the id sort takes
|
|
||||||
// precedence over everything else, making any other sort columns pretty useless.
|
|
||||||
const sortKeys = Object.keys(this.sortBy)
|
|
||||||
let hasIdFilter = false
|
|
||||||
for (const s of sortKeys) {
|
|
||||||
if (s === 'id') {
|
|
||||||
sortKeys.splice(s, 1)
|
|
||||||
hasIdFilter = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hasIdFilter) {
|
|
||||||
sortKeys.push('id')
|
|
||||||
}
|
|
||||||
|
|
||||||
const params = this.params
|
const params = this.params
|
||||||
params.sort_by = []
|
params.sort_by = []
|
||||||
params.order_by = []
|
params.order_by = []
|
||||||
sortKeys.map(s => {
|
Object.keys(this.sortBy).map(s => {
|
||||||
params.sort_by.push(s)
|
params.sort_by.push(s)
|
||||||
params.order_by.push(this.sortBy[s])
|
params.order_by.push(this.sortBy[s])
|
||||||
})
|
})
|
||||||
|
|
|
@ -33,7 +33,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {mapGetters} from 'vuex'
|
import {mapState} from 'vuex'
|
||||||
|
import authTypes from '@/models/authTypes.json'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'LinkSharingAuth',
|
name: 'LinkSharingAuth',
|
||||||
|
@ -53,9 +54,9 @@ export default {
|
||||||
mounted() {
|
mounted() {
|
||||||
this.setTitle(this.$t('sharing.authenticating'))
|
this.setTitle(this.$t('sharing.authenticating'))
|
||||||
},
|
},
|
||||||
computed: mapGetters('auth', [
|
computed: mapState({
|
||||||
'authLinkShare',
|
authLinkShare: state => state.auth.authenticated && (state.auth.info && state.auth.info.type === authTypes.LINK_SHARE),
|
||||||
]),
|
}),
|
||||||
methods: {
|
methods: {
|
||||||
auth() {
|
auth() {
|
||||||
this.errorMessage = ''
|
this.errorMessage = ''
|
||||||
|
|
|
@ -419,10 +419,10 @@
|
||||||
<script>
|
<script>
|
||||||
import TaskService from '../../services/task'
|
import TaskService from '../../services/task'
|
||||||
import TaskModel from '../../models/task'
|
import TaskModel from '../../models/task'
|
||||||
import relationKinds from '../../models/constants/relationKinds.json'
|
import relationKinds from '../../models/relationKinds.json'
|
||||||
|
|
||||||
import priorites from '../../models/constants/priorities.json'
|
import priorites from '../../models/priorities.json'
|
||||||
import rights from '../../models/constants/rights.json'
|
import rights from '../../models/rights.json'
|
||||||
|
|
||||||
import PrioritySelect from '../../components/tasks/partials/prioritySelect'
|
import PrioritySelect from '../../components/tasks/partials/prioritySelect'
|
||||||
import PercentDoneSelect from '../../components/tasks/partials/percentDoneSelect'
|
import PercentDoneSelect from '../../components/tasks/partials/percentDoneSelect'
|
||||||
|
|
|
@ -167,7 +167,7 @@ import TeamMemberService from '../../services/teamMember'
|
||||||
import TeamMemberModel from '../../models/teamMember'
|
import TeamMemberModel from '../../models/teamMember'
|
||||||
import UserModel from '../../models/user'
|
import UserModel from '../../models/user'
|
||||||
import UserService from '../../services/user'
|
import UserService from '../../services/user'
|
||||||
import Rights from '../../models/constants/rights.json'
|
import Rights from '../../models/rights.json'
|
||||||
|
|
||||||
import LoadingComponent from '../../components/misc/loading'
|
import LoadingComponent from '../../components/misc/loading'
|
||||||
import ErrorComponent from '../../components/misc/error'
|
import ErrorComponent from '../../components/misc/error'
|
||||||
|
|
|
@ -71,8 +71,8 @@
|
||||||
{{ $t('user.settings.general.language') }}
|
{{ $t('user.settings.general.language') }}
|
||||||
</span>
|
</span>
|
||||||
<div class="select ml-2">
|
<div class="select ml-2">
|
||||||
<select v-model="language">
|
<select v-model.number="language">
|
||||||
<option :value="lang.code" v-for="lang in availableLanguages" :key="lang.code">{{ lang.title }}</option>
|
<option :value="l" v-for="(lang, l) in availableLanguages" :key="l">{{ lang }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
@ -288,7 +288,7 @@ import TotpService from '../../services/totp'
|
||||||
import UserSettingsService from '../../services/userSettings'
|
import UserSettingsService from '../../services/userSettings'
|
||||||
import UserSettingsModel from '../../models/userSettings'
|
import UserSettingsModel from '../../models/userSettings'
|
||||||
import {playSoundWhenDoneKey} from '@/helpers/playPop'
|
import {playSoundWhenDoneKey} from '@/helpers/playPop'
|
||||||
import {availableLanguages, saveLanguage, getCurrentLanguage} from '../../i18n/setup'
|
import {availableLanguages, saveLanguage, getCurrentLanguage} from '@/i18n/setup'
|
||||||
|
|
||||||
import {mapState} from 'vuex'
|
import {mapState} from 'vuex'
|
||||||
|
|
||||||
|
@ -367,9 +367,7 @@ export default {
|
||||||
return `${apiBase}/dav/principals/${this.userInfo.username}/`
|
return `${apiBase}/dav/principals/${this.userInfo.username}/`
|
||||||
},
|
},
|
||||||
availableLanguages() {
|
availableLanguages() {
|
||||||
return Object.entries(availableLanguages)
|
return availableLanguages
|
||||||
.map(l => ({code: l[0], title: l[1]}))
|
|
||||||
.sort((a, b) => a.title > b.title)
|
|
||||||
},
|
},
|
||||||
...mapState({
|
...mapState({
|
||||||
totpEnabled: state => state.config.totpEnabled,
|
totpEnabled: state => state.config.totpEnabled,
|
||||||
|
|
Loading…
Reference in New Issue