Merge branch 'main' into feature/caldav-tokens
This commit is contained in:
commit
9820fcba31
26
package.json
26
package.json
|
@ -22,8 +22,8 @@
|
|||
"@sentry/tracing": "6.16.1",
|
||||
"@sentry/vue": "6.16.1",
|
||||
"@vue/compat": "3.2.26",
|
||||
"@vueuse/core": "7.4.0",
|
||||
"@vueuse/router": "7.4.0",
|
||||
"@vueuse/core": "7.4.1",
|
||||
"@vueuse/router": "7.4.1",
|
||||
"bulma-css-variables": "0.9.33",
|
||||
"camel-case": "4.1.2",
|
||||
"codemirror": "5.65.0",
|
||||
|
@ -46,7 +46,7 @@
|
|||
"vue-advanced-cropper": "2.7.0",
|
||||
"vue-drag-resize": "2.0.3",
|
||||
"vue-flatpickr-component": "9.0.5",
|
||||
"vue-i18n": "9.2.0-beta.23",
|
||||
"vue-i18n": "9.2.0-beta.25",
|
||||
"vue-router": "4.0.12",
|
||||
"vuedraggable": "4.1.0",
|
||||
"vuex": "4.0.2",
|
||||
|
@ -60,36 +60,36 @@
|
|||
"@fortawesome/vue-fontawesome": "3.0.0-5",
|
||||
"@types/flexsearch": "0.7.2",
|
||||
"@types/jest": "27.0.3",
|
||||
"@typescript-eslint/eslint-plugin": "5.7.0",
|
||||
"@typescript-eslint/parser": "5.7.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.8.0",
|
||||
"@typescript-eslint/parser": "5.8.0",
|
||||
"@vitejs/plugin-legacy": "1.6.4",
|
||||
"@vitejs/plugin-vue": "2.0.1",
|
||||
"@vue/eslint-config-typescript": "9.1.0",
|
||||
"autoprefixer": "10.4.0",
|
||||
"axios": "0.24.0",
|
||||
"browserslist": "4.19.1",
|
||||
"caniuse-lite": "1.0.30001291",
|
||||
"cypress": "9.1.1",
|
||||
"caniuse-lite": "1.0.30001292",
|
||||
"cypress": "9.2.0",
|
||||
"cypress-file-upload": "5.0.8",
|
||||
"esbuild": "0.14.6",
|
||||
"esbuild": "0.14.8",
|
||||
"eslint": "8.5.0",
|
||||
"eslint-plugin-vue": "8.2.0",
|
||||
"express": "4.17.2",
|
||||
"faker": "5.5.3",
|
||||
"jest": "27.4.5",
|
||||
"netlify-cli": "8.2.0",
|
||||
"netlify-cli": "8.4.2",
|
||||
"postcss": "8.4.5",
|
||||
"postcss-preset-env": "7.0.2",
|
||||
"postcss-preset-env": "7.1.0",
|
||||
"rollup": "2.61.1",
|
||||
"rollup-plugin-visualizer": "5.5.2",
|
||||
"sass": "1.45.0",
|
||||
"sass": "1.45.1",
|
||||
"slugify": "1.6.4",
|
||||
"ts-jest": "27.1.2",
|
||||
"typescript": "4.5.4",
|
||||
"vite": "2.7.4",
|
||||
"vite": "2.7.7",
|
||||
"vite-plugin-pwa": "0.11.12",
|
||||
"vite-svg-loader": "3.1.1",
|
||||
"vue-tsc": "0.29.8",
|
||||
"vue-tsc": "0.30.0",
|
||||
"wait-on": "6.0.0",
|
||||
"workbox-cli": "6.4.2"
|
||||
},
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
<content-auth/>
|
||||
</template>
|
||||
<content-link-share v-else-if="authLinkShare"/>
|
||||
<content-no-auth v-else/>
|
||||
<notification/>
|
||||
<no-auth-wrapper v-else>
|
||||
<router-view/>
|
||||
</no-auth-wrapper>
|
||||
<Notification/>
|
||||
</div>
|
||||
|
||||
<transition name="fade">
|
||||
|
@ -31,7 +33,7 @@ import KeyboardShortcuts from './components/misc/keyboard-shortcuts/index.vue'
|
|||
import TopNavigation from './components/home/topNavigation.vue'
|
||||
import ContentAuth from './components/home/contentAuth.vue'
|
||||
import ContentLinkShare from './components/home/contentLinkShare.vue'
|
||||
import ContentNoAuth from './components/home/contentNoAuth.vue'
|
||||
import NoAuthWrapper from '@/components/misc/no-auth-wrapper.vue'
|
||||
import Ready from '@/components/misc/ready.vue'
|
||||
|
||||
import {setLanguage} from './i18n'
|
||||
|
|
|
@ -64,21 +64,25 @@ const route = useRoute()
|
|||
// hide menu on mobile
|
||||
watch(() => route.fullPath, () => window.innerWidth < 769 && store.commit(MENU_ACTIVE, false))
|
||||
|
||||
// FIXME: this is really error prone
|
||||
// Reset the current list highlight in menu if the current route is not list related.
|
||||
watch(() => route.fullPath, () => {
|
||||
watch(() => route.name as string, (routeName) => {
|
||||
if (
|
||||
[
|
||||
'home',
|
||||
'namespace.edit',
|
||||
'teams.index',
|
||||
'teams.edit',
|
||||
'tasks.range',
|
||||
'labels.index',
|
||||
'migrate.start',
|
||||
'migrate.wunderlist',
|
||||
'namespaces.index',
|
||||
].includes(route.name) ||
|
||||
route.name.startsWith('user.settings')
|
||||
routeName &&
|
||||
(
|
||||
[
|
||||
'home',
|
||||
'namespace.edit',
|
||||
'teams.index',
|
||||
'teams.edit',
|
||||
'tasks.range',
|
||||
'labels.index',
|
||||
'migrate.start',
|
||||
'migrate.wunderlist',
|
||||
'namespaces.index',
|
||||
].includes(routeName) ||
|
||||
routeName.startsWith('user.settings')
|
||||
)
|
||||
) {
|
||||
store.dispatch(CURRENT_LIST, null)
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
<template>
|
||||
<no-auth-wrapper>
|
||||
<router-view/>
|
||||
</no-auth-wrapper>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {watchEffect} from 'vue'
|
||||
import {useRoute, useRouter} from 'vue-router'
|
||||
|
||||
import NoAuthWrapper from '@/components/misc/no-auth-wrapper'
|
||||
|
||||
import {saveLastVisited} from '@/helpers/saveLastVisited'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
watchEffect(() => {
|
||||
if (!route.name) return
|
||||
redirectToHome()
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
function redirectToHome() {
|
||||
// Check if the user is already logged in and redirect them to the home page if not
|
||||
if (
|
||||
![
|
||||
'user.login',
|
||||
'user.password-reset.request',
|
||||
'user.password-reset.reset',
|
||||
'user.register',
|
||||
'link-share.auth',
|
||||
'openid.auth',
|
||||
].includes(route.name) &&
|
||||
localStorage.getItem('passwordResetToken') === null &&
|
||||
localStorage.getItem('emailConfirmToken') === null
|
||||
) {
|
||||
saveLastVisited(route.name, route.params)
|
||||
router.push({name: 'user.login'})
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,23 +1,24 @@
|
|||
<template>
|
||||
<card class="filters has-overflow">
|
||||
<fancycheckbox v-model="params.filter_include_nulls">
|
||||
{{ $t('filters.attributes.includeNulls') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox
|
||||
v-model="filters.requireAllFilters"
|
||||
@change="setFilterConcat()"
|
||||
>
|
||||
{{ $t('filters.attributes.requireAll') }}
|
||||
</fancycheckbox>
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
<fancycheckbox v-model="params.filter_include_nulls">
|
||||
{{ $t('filters.attributes.includeNulls') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox
|
||||
v-model="filters.requireAllFilters"
|
||||
@change="setFilterConcat()"
|
||||
>
|
||||
{{ $t('filters.attributes.requireAll') }}
|
||||
</fancycheckbox>
|
||||
<fancycheckbox @change="setDoneFilter" v-model="filters.done">
|
||||
{{ $t('filters.attributes.showDoneTasks') }}
|
||||
</label>
|
||||
<div class="control">
|
||||
<fancycheckbox @change="setDoneFilter" v-model="filters.done">
|
||||
{{ $t('filters.attributes.showDoneTasks') }}
|
||||
</fancycheckbox>
|
||||
</div>
|
||||
</fancycheckbox>
|
||||
<fancycheckbox
|
||||
v-if="!$route.name.includes('list.kanban') || !$route.name.includes('list.table')"
|
||||
v-model="sortAlphabetically"
|
||||
>
|
||||
{{ $t('filters.attributes.sortAlphabetically') }}
|
||||
</fancycheckbox>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">{{ $t('misc.search') }}</label>
|
||||
|
@ -190,6 +191,7 @@ import NamespaceService from '@/services/namespace'
|
|||
import EditLabels from '@/components/tasks/partials/editLabels.vue'
|
||||
|
||||
import {objectToSnakeCase} from '@/helpers/case'
|
||||
import {getDefaultParams} from '@/components/tasks/mixins/taskList'
|
||||
|
||||
// FIXME: merge with DEFAULT_PARAMS in taskList.js
|
||||
const DEFAULT_PARAMS = {
|
||||
|
@ -220,6 +222,8 @@ const DEFAULT_FILTERS = {
|
|||
namespace: '',
|
||||
}
|
||||
|
||||
export const ALPHABETICAL_SORT = 'title'
|
||||
|
||||
export default {
|
||||
name: 'filters',
|
||||
components: {
|
||||
|
@ -272,6 +276,18 @@ export default {
|
|||
},
|
||||
},
|
||||
computed: {
|
||||
sortAlphabetically: {
|
||||
get() {
|
||||
return this.params?.sort_by?.find(sortBy => sortBy === ALPHABETICAL_SORT) !== undefined
|
||||
},
|
||||
set(sortAlphabetically) {
|
||||
this.params.sort_by = sortAlphabetically
|
||||
? [ALPHABETICAL_SORT]
|
||||
: getDefaultParams().sort_by
|
||||
|
||||
this.change()
|
||||
},
|
||||
},
|
||||
foundLabels() {
|
||||
return this.$store.getters['labels/filterLabelsByQuery'](this.labels, this.query)
|
||||
},
|
||||
|
|
|
@ -44,7 +44,6 @@ export default {
|
|||
params = null,
|
||||
forceLoading = false,
|
||||
) {
|
||||
|
||||
// Because this function is triggered every time on topNavigation, we're putting a condition here to only load it when we actually want to show tasks
|
||||
// FIXME: This is a bit hacky -> Cleanup.
|
||||
if (
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
export const playSoundWhenDoneKey = 'playSoundWhenTaskDone'
|
||||
|
||||
export const playPop = () => {
|
||||
const enabled = localStorage.getItem(playSoundWhenDoneKey) === 'true' || localStorage.getItem(playSoundWhenDoneKey) === null
|
||||
if(!enabled) {
|
||||
return
|
||||
}
|
||||
|
||||
const popSound = new Audio('/audio/pop.mp3')
|
||||
popSound.play()
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import popSoundFile from '@/assets/audio/pop.mp3'
|
||||
|
||||
export const playSoundWhenDoneKey = 'playSoundWhenTaskDone'
|
||||
|
||||
export function playPop() {
|
||||
const enabled = Boolean(localStorage.getItem(playSoundWhenDoneKey))
|
||||
if(!enabled) {
|
||||
return
|
||||
}
|
||||
|
||||
const popSound = new Audio(popSoundFile)
|
||||
popSound.play()
|
||||
}
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Zahrnout úkoly, které nemají nastavenou hodnotu",
|
||||
"requireAll": "Vyžaduje aby všechny filtry odpovídaly, aby se úkol zobrazil",
|
||||
"showDoneTasks": "Zobrazit dokončené úkoly",
|
||||
"sortAlphabetically": "Řadit podle abecedy",
|
||||
"enablePriority": "Povolit filtrování podle priority",
|
||||
"enablePercentDone": "Povolit filtrování dle dokončenosti",
|
||||
"dueDateRange": "Rozsah termínu",
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Aufgaben ohne Werte einbeziehen",
|
||||
"requireAll": "Alle Filterkriterien müssen erfüllt sein, damit eine Aufgabe angezeigt wird",
|
||||
"showDoneTasks": "Erledigte Aufgaben anzeigen",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Filter nach Priorität aktivieren",
|
||||
"enablePercentDone": "Filter nach % Erledigt aktivieren",
|
||||
"dueDateRange": "Fälligkeitsbereich",
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Uufgabe ohni Wert iihbezieh",
|
||||
"requireAll": "Alli Filter mend wahr sii, demits die Uufgab ahzeigt",
|
||||
"showDoneTasks": "Zeig die fertige Uufgabe",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Filter nach Priorität aktiviere",
|
||||
"enablePercentDone": "Filter nach Prozent iihschalte",
|
||||
"dueDateRange": "Fälligkeitsberiich",
|
||||
|
|
|
@ -381,6 +381,7 @@
|
|||
"includeNulls": "Include Tasks which don't have a value set",
|
||||
"requireAll": "Require all filters to be true for a task to show up",
|
||||
"showDoneTasks": "Show Done Tasks",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Enable Filter By Priority",
|
||||
"enablePercentDone": "Enable Filter By Percent Done",
|
||||
"dueDateRange": "Due Date Range",
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Include Tasks which don't have a value set",
|
||||
"requireAll": "Require all filters to be true for a task to show up",
|
||||
"showDoneTasks": "Show Done Tasks",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Enable Filter By Priority",
|
||||
"enablePercentDone": "Enable Filter By Percent Done",
|
||||
"dueDateRange": "Due Date Range",
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Inclure les tâches sans valeurs",
|
||||
"requireAll": "Exiger tous les filtres pour qu’une tâche s’affiche",
|
||||
"showDoneTasks": "Afficher les tâches terminées",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Activer le filtre par priorité",
|
||||
"enablePercentDone": "Par % d’achèvement",
|
||||
"dueDateRange": "Plage de dates d’échéance",
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Includi attività che non hanno un valore impostato",
|
||||
"requireAll": "Tutti i filtri devono essere veri affinché l'attività venga mostrata",
|
||||
"showDoneTasks": "Mostra Attività Fatte",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Abilita Filtro Per Priorità",
|
||||
"enablePercentDone": "Abilitare Filtro Per Percentuale Fatta",
|
||||
"dueDateRange": "Intervallo Data Di Scadenza",
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Include Tasks which don't have a value set",
|
||||
"requireAll": "Require all filters to be true for a task to show up",
|
||||
"showDoneTasks": "Show Done Tasks",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Enable Filter By Priority",
|
||||
"enablePercentDone": "Enable Filter By Percent Done",
|
||||
"dueDateRange": "Due Date Range",
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Include Tasks which don't have a value set",
|
||||
"requireAll": "Require all filters to be true for a task to show up",
|
||||
"showDoneTasks": "Show Done Tasks",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Enable Filter By Priority",
|
||||
"enablePercentDone": "Enable Filter By Percent Done",
|
||||
"dueDateRange": "Due Date Range",
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Include Tasks which don't have a value set",
|
||||
"requireAll": "Require all filters to be true for a task to show up",
|
||||
"showDoneTasks": "Show Done Tasks",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Enable Filter By Priority",
|
||||
"enablePercentDone": "Enable Filter By Percent Done",
|
||||
"dueDateRange": "Due Date Range",
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Include Tasks which don't have a value set",
|
||||
"requireAll": "Require all filters to be true for a task to show up",
|
||||
"showDoneTasks": "Show Done Tasks",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Enable Filter By Priority",
|
||||
"enablePercentDone": "Enable Filter By Percent Done",
|
||||
"dueDateRange": "Due Date Range",
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Включать задачи, у которых не установлено значение",
|
||||
"requireAll": "Для отображения задачи требовать истинность всех фильтров",
|
||||
"showDoneTasks": "Показывать завершённые задачи",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Вкл. фильтр по приоритету",
|
||||
"enablePercentDone": "По % завершения",
|
||||
"dueDateRange": "Диапазон срока",
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Include Tasks which don't have a value set",
|
||||
"requireAll": "Require all filters to be true for a task to show up",
|
||||
"showDoneTasks": "Show Done Tasks",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Enable Filter By Priority",
|
||||
"enablePercentDone": "Enable Filter By Percent Done",
|
||||
"dueDateRange": "Due Date Range",
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Include Tasks which don't have a value set",
|
||||
"requireAll": "Require all filters to be true for a task to show up",
|
||||
"showDoneTasks": "Show Done Tasks",
|
||||
"sortAlphabetically": "Sort Alphabetically",
|
||||
"enablePriority": "Enable Filter By Priority",
|
||||
"enablePercentDone": "Enable Filter By Percent Done",
|
||||
"dueDateRange": "Due Date Range",
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
"password": "Mật khẩu",
|
||||
"passwordRepeat": "Nhập lại mật khẩu",
|
||||
"passwordPlaceholder": "ví dụ: •••••••••••",
|
||||
"forgotPassword": "Forgot your password?",
|
||||
"forgotPassword": "Bạn quên mật khẩu?",
|
||||
"resetPassword": "Reset mật khẩu của bạn",
|
||||
"resetPasswordAction": "Gửi cho tôi liên kết reset mật khẩu",
|
||||
"resetPasswordSuccess": "Kiểm tra hộp thư của bạn! Bạn sẽ nhận một e-mail với hướng dẫn reset mật khẩu của mình.",
|
||||
|
@ -103,7 +103,7 @@
|
|||
"title": "Avatar",
|
||||
"initials": "Chữ cái viết tắt",
|
||||
"gravatar": "Gravatar",
|
||||
"marble": "Marble",
|
||||
"marble": "Cẩm thạch",
|
||||
"upload": "Tải lên",
|
||||
"uploadAvatar": "Tải lên Avatar",
|
||||
"statusUpdateSuccess": "Avatar đã được cập nhật!",
|
||||
|
@ -374,6 +374,7 @@
|
|||
"includeNulls": "Bao gồm các Công việc không có bộ giá trị",
|
||||
"requireAll": "Yêu cầu tất cả các bộ lọc phải đúng để một công việc được hiển thị",
|
||||
"showDoneTasks": "Hiển thị các công việc đã hoàn thành",
|
||||
"sortAlphabetically": "Xếp theo bảng chữ cái",
|
||||
"enablePriority": "Bật Bộ lọc theo mức độ ưu tiên",
|
||||
"enablePercentDone": "Bật Bộ lọc theo tỉ lệ % hoàn thành",
|
||||
"dueDateRange": "Phạm vi ngày đến hạn",
|
||||
|
@ -474,8 +475,8 @@
|
|||
"download": "Tải về",
|
||||
"showMenu": "Hiển thị menu",
|
||||
"hideMenu": "Ẩn menu",
|
||||
"forExample": "For example:",
|
||||
"welcomeBack": "Welcome Back!"
|
||||
"forExample": "Ví dụ:",
|
||||
"welcomeBack": "Mừng quá! Bạn trở lại rồi."
|
||||
},
|
||||
"input": {
|
||||
"resetColor": "Đặt lại màu",
|
||||
|
@ -725,8 +726,8 @@
|
|||
"dateCurrentYear": "sẽ sử dụng năm hiện tại",
|
||||
"dateNth": "sẽ sử dụng ngày {day} của tháng hiện tại",
|
||||
"dateTime": "Kết hợp bất kì đinh dạng ngày với \"{time}\" (hoặc {timePM}) để thiết lập thời gian.",
|
||||
"repeats": "Repeating tasks",
|
||||
"repeatsDescription": "To set a task as repeating in an interval, simply add '{suffix}' to the task text. The amount needs to be a number and can be omitted to use just the type (see examples)."
|
||||
"repeats": "Công việc định kỳ",
|
||||
"repeatsDescription": "Để cài một công việc được lặp lại trong các khoảng thời gian, chỉ cần thêm '{suffix}' vào văn bản công việc. Số lượng phải là một số và có thể được bỏ qua để chỉ sử dụng loại (xem ví dụ)."
|
||||
}
|
||||
},
|
||||
"team": {
|
||||
|
@ -813,7 +814,7 @@
|
|||
"url": "URL Vikunja",
|
||||
"urlPlaceholder": "ví dụ: https://localhost:3456",
|
||||
"change": "thay đổi",
|
||||
"use": "Using Vikunja installation at {0}",
|
||||
"use": "Sử dụng cài đặt Vikunja tại {0}",
|
||||
"error": "Không thể tìm thấy hoặc sử dụng cài đặt Vikunja tại \"{domain}\". Vui lòng thử một url khác.",
|
||||
"success": "Sử dụng cài đặt Vikunja tại \"{domain}\".",
|
||||
"urlRequired": "Cần có một url."
|
||||
|
@ -907,7 +908,7 @@
|
|||
"5010": "Team này không có quyền bước vào góc làm việc đó.",
|
||||
"5011": "Người này đã có quyền bước vào góc làm việc đó.",
|
||||
"5012": "Góc làm việc đã được lưu trữ nên chỉ có thể vào đó để đọc.",
|
||||
"6001": "The team name cannot be empty.",
|
||||
"6001": "Tên của Team không được để trống.",
|
||||
"6002": "Team không tồn tại.",
|
||||
"6004": "Team đã có quyền bước vào góc làm việc và xem danh sách.",
|
||||
"6005": "Người này đã là thành viên của Team đó rồi.",
|
||||
|
|
|
@ -133,8 +133,8 @@ if (window.SENTRY_ENABLED) {
|
|||
import('./sentry').then(sentry => sentry.default(app, router))
|
||||
}
|
||||
|
||||
app.use(router)
|
||||
app.use(store)
|
||||
app.use(router)
|
||||
app.use(i18n)
|
||||
|
||||
app.mount('#app')
|
|
@ -1,4 +1,6 @@
|
|||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { createRouter, createWebHistory, RouteLocation } from 'vue-router'
|
||||
import {saveLastVisited} from '@/helpers/saveLastVisited'
|
||||
import {store} from '@/store'
|
||||
|
||||
import HomeComponent from '../views/Home'
|
||||
import NotFoundComponent from '../views/404'
|
||||
|
@ -573,16 +575,34 @@ const router = createRouter({
|
|||
],
|
||||
})
|
||||
|
||||
// bad example if using named routes:
|
||||
router.resolve({
|
||||
name: 'bad-not-found',
|
||||
params: { pathMatch: 'not/found' },
|
||||
}).href // '/not%2Ffound'
|
||||
router.beforeEach((to) => {
|
||||
return checkAuth(to)
|
||||
})
|
||||
|
||||
// good example:
|
||||
router.resolve({
|
||||
name: 'not-found',
|
||||
params: { pathMatch: ['not', 'found'] },
|
||||
}).href // '/not/found'
|
||||
function checkAuth(route: RouteLocation) {
|
||||
const authUser = store.getters['auth/authUser']
|
||||
const authLinkShare = store.getters['auth/authLinkShare']
|
||||
|
||||
if (authUser || authLinkShare) {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the user is already logged in and redirect them to the home page if not
|
||||
if (
|
||||
![
|
||||
'user.login',
|
||||
'user.password-reset.request',
|
||||
'user.password-reset.reset',
|
||||
'user.register',
|
||||
'link-share.auth',
|
||||
'openid.auth',
|
||||
].includes(route.name as string) &&
|
||||
localStorage.getItem('passwordResetToken') === null &&
|
||||
localStorage.getItem('emailConfirmToken') === null
|
||||
) {
|
||||
saveLastVisited(route.name as string, route.params)
|
||||
return {name: 'user.login'}
|
||||
}
|
||||
}
|
||||
|
||||
export default router
|
|
@ -81,7 +81,7 @@
|
|||
:disabled="!canWrite"
|
||||
item-key="id"
|
||||
:component-data="{
|
||||
class: { 'dragging-disabled': !canWrite },
|
||||
class: { 'dragging-disabled': !canWrite || isAlphabeticalSorting },
|
||||
}"
|
||||
>
|
||||
<template #item="{element: t}">
|
||||
|
@ -148,6 +148,7 @@ import {HAS_TASKS} from '@/store/mutation-types'
|
|||
import Nothing from '@/components/misc/nothing.vue'
|
||||
import Pagination from '@/components/misc/pagination.vue'
|
||||
import Popup from '@/components/misc/popup'
|
||||
import { ALPHABETICAL_SORT } from '@/components/list/partials/filters'
|
||||
|
||||
import draggable from 'vuedraggable'
|
||||
import {calculateItemPosition} from '../../../helpers/calculateItemPosition'
|
||||
|
@ -206,6 +207,9 @@ export default {
|
|||
saveListView(this.$route.params.listId, this.$route.name)
|
||||
},
|
||||
computed: {
|
||||
isAlphabeticalSorting() {
|
||||
return this.params.sort_by.find( sortBy => sortBy === ALPHABETICAL_SORT ) !== undefined
|
||||
},
|
||||
firstNewPosition() {
|
||||
if (this.tasks.length === 0) {
|
||||
return 0
|
||||
|
@ -254,12 +258,18 @@ export default {
|
|||
focusNewTaskInput() {
|
||||
this.$refs.newTaskInput.$refs.newTaskInput.focus()
|
||||
},
|
||||
updateTaskList(task) {
|
||||
const tasks = [
|
||||
task,
|
||||
...this.tasks,
|
||||
]
|
||||
this.tasks = tasks
|
||||
updateTaskList( task ) {
|
||||
if ( this.isAlphabeticalSorting ) {
|
||||
// reload tasks with current filter and sorting
|
||||
this.loadTasks(1, undefined, undefined, true)
|
||||
}
|
||||
else {
|
||||
this.tasks = [
|
||||
task,
|
||||
...this.tasks,
|
||||
]
|
||||
}
|
||||
|
||||
this.$store.commit(HAS_TASKS, true)
|
||||
},
|
||||
editTask(id) {
|
||||
|
|
Reference in New Issue