Compare commits

..

23 Commits

Author SHA1 Message Date
d0efca194f Merge branch 'main' of https://kolaente.dev/davidangel/frontend 2023-07-14 23:36:11 -04:00
d19a5d9714 chore(deps): update dev-dependencies 2023-07-15 00:04:50 +00:00
90cad1c8dd chore(deps): update dev-dependencies 2023-07-14 01:09:00 +00:00
Frederick [Bot]
057017c8eb [skip ci] Updated translations via Crowdin 2023-07-14 00:08:42 +00:00
d7ce8dd320
fix(quick add magic): repeating intervals in words
Resolves vikunja/frontend#3676
2023-07-13 18:20:30 +02:00
25b110ce48
fix(quick add magic): annually and variants spelling
Related to vikunja/frontend#3676
2023-07-13 18:05:19 +02:00
33fe5e4f20 fix(deps): update sentry-javascript monorepo to v7.58.1 2023-07-13 12:04:38 +00:00
129ef769a3 fix(deps): update sentry-javascript monorepo to v7.58.0 2023-07-13 06:47:22 +00:00
9030a9f7c1 chore(deps): update dev-dependencies 2023-07-13 02:05:04 +00:00
Frederick [Bot]
3748a496d5 [skip ci] Updated translations via Crowdin 2023-07-13 00:08:55 +00:00
890e7e1f52 chore(deps): update dependency vite to v4.4.3 2023-07-12 00:05:46 +00:00
9e0f2b0249 chore(deps): update dev-dependencies 2023-07-11 11:04:54 +00:00
9a34c522b2 fix(deps): update dependency dompurify to v3.0.5 2023-07-11 10:24:42 +00:00
60dd698fad chore(deps): update dev-dependencies to v6 2023-07-11 10:05:43 +00:00
15ecafdf04
fix: don't try to load buckets for project id 0 2023-07-11 10:42:20 +02:00
8902c15f7e
fix: correctly resolve kanban board in the background when moving a task
Resolves F-951
2023-07-10 18:10:14 +02:00
d5358793de
chore: provide better error messages when refreshing user info fails 2023-07-10 12:20:40 +02:00
33798b8d88 chore(deps): update pnpm to v8.6.7 2023-07-10 06:43:02 +00:00
c686e8677b chore(deps): update dependency caniuse-lite to v1.0.30001514 2023-07-10 00:05:28 +00:00
5acc1696a9 fix(deps): update dependency @intlify/unplugin-vue-i18n to v0.12.2 2023-07-08 19:04:46 +00:00
c4976b6a22 chore(deps): update dependency vite to v4.4.2 2023-07-08 00:06:23 +00:00
d88ff594e1 fix(deps): update dependency marked to v5.1.1 2023-07-07 15:04:29 +00:00
70ea1f2301 Merge pull request 'main' (#1) from vikunja/frontend:main into main
Reviewed-on: #1
2023-01-26 04:07:51 +00:00
9 changed files with 775 additions and 570 deletions

View File

@ -13,7 +13,7 @@
}, },
"homepage": "https://vikunja.io/", "homepage": "https://vikunja.io/",
"funding": "https://opencollective.com/vikunja", "funding": "https://opencollective.com/vikunja",
"packageManager": "pnpm@8.6.6", "packageManager": "pnpm@8.6.7",
"keywords": [ "keywords": [
"todo", "todo",
"productivity", "productivity",
@ -51,10 +51,10 @@
"@fortawesome/vue-fontawesome": "3.0.3", "@fortawesome/vue-fontawesome": "3.0.3",
"@github/hotkey": "2.0.1", "@github/hotkey": "2.0.1",
"@infectoone/vue-ganttastic": "2.1.4", "@infectoone/vue-ganttastic": "2.1.4",
"@intlify/unplugin-vue-i18n": "0.12.1", "@intlify/unplugin-vue-i18n": "0.12.2",
"@kyvg/vue3-notification": "2.9.1", "@kyvg/vue3-notification": "2.9.1",
"@sentry/tracing": "7.57.0", "@sentry/tracing": "7.58.1",
"@sentry/vue": "7.57.0", "@sentry/vue": "7.58.1",
"@vueuse/core": "10.2.1", "@vueuse/core": "10.2.1",
"axios": "1.4.0", "axios": "1.4.0",
"blurhash": "2.0.5", "blurhash": "2.0.5",
@ -63,7 +63,7 @@
"codemirror": "5.65.13", "codemirror": "5.65.13",
"date-fns": "2.30.0", "date-fns": "2.30.0",
"dayjs": "1.11.9", "dayjs": "1.11.9",
"dompurify": "3.0.4", "dompurify": "3.0.5",
"easymde": "2.18.0", "easymde": "2.18.0",
"fast-deep-equal": "3.1.3", "fast-deep-equal": "3.1.3",
"flatpickr": "4.6.13", "flatpickr": "4.6.13",
@ -73,7 +73,7 @@
"is-touch-device": "1.0.1", "is-touch-device": "1.0.1",
"klona": "2.0.6", "klona": "2.0.6",
"lodash.debounce": "4.0.8", "lodash.debounce": "4.0.8",
"marked": "5.1.0", "marked": "5.1.1",
"pinia": "2.1.4", "pinia": "2.1.4",
"register-service-worker": "1.7.2", "register-service-worker": "1.7.2",
"snake-case": "3.0.4", "snake-case": "3.0.4",
@ -101,12 +101,12 @@
"@types/flexsearch": "0.7.3", "@types/flexsearch": "0.7.3",
"@types/is-touch-device": "1.0.0", "@types/is-touch-device": "1.0.0",
"@types/lodash.debounce": "4.0.7", "@types/lodash.debounce": "4.0.7",
"@types/marked": "5.0.0", "@types/marked": "5.0.1",
"@types/node": "18.16.19", "@types/node": "18.16.19",
"@types/postcss-preset-env": "7.7.0", "@types/postcss-preset-env": "7.7.0",
"@types/sortablejs": "1.15.1", "@types/sortablejs": "1.15.1",
"@typescript-eslint/eslint-plugin": "5.61.0", "@typescript-eslint/eslint-plugin": "6.0.0",
"@typescript-eslint/parser": "5.61.0", "@typescript-eslint/parser": "6.0.0",
"@vitejs/plugin-legacy": "4.1.0", "@vitejs/plugin-legacy": "4.1.0",
"@vitejs/plugin-vue": "4.2.3", "@vitejs/plugin-vue": "4.2.3",
"@vue/eslint-config-typescript": "11.0.3", "@vue/eslint-config-typescript": "11.0.3",
@ -114,16 +114,16 @@
"@vue/tsconfig": "0.4.0", "@vue/tsconfig": "0.4.0",
"autoprefixer": "10.4.14", "autoprefixer": "10.4.14",
"browserslist": "4.21.9", "browserslist": "4.21.9",
"caniuse-lite": "1.0.30001513", "caniuse-lite": "1.0.30001515",
"css-has-pseudo": "6.0.0", "css-has-pseudo": "6.0.0",
"csstype": "3.1.2", "csstype": "3.1.2",
"cypress": "12.17.0", "cypress": "12.17.1",
"esbuild": "0.18.11", "esbuild": "0.18.12",
"eslint": "8.44.0", "eslint": "8.45.0",
"eslint-plugin-vue": "9.15.1", "eslint-plugin-vue": "9.15.1",
"happy-dom": "10.0.3", "happy-dom": "10.3.2",
"histoire": "0.16.2", "histoire": "0.16.2",
"postcss": "8.4.25", "postcss": "8.4.26",
"postcss-easing-gradients": "3.0.1", "postcss-easing-gradients": "3.0.1",
"postcss-easings": "4.0.0", "postcss-easings": "4.0.0",
"postcss-focus-within": "8.0.0", "postcss-focus-within": "8.0.0",
@ -133,13 +133,13 @@
"sass": "1.63.6", "sass": "1.63.6",
"start-server-and-test": "2.0.0", "start-server-and-test": "2.0.0",
"typescript": "5.1.6", "typescript": "5.1.6",
"vite": "4.4.1", "vite": "4.4.4",
"vite-plugin-inject-preload": "1.3.1", "vite-plugin-inject-preload": "1.3.1",
"vite-plugin-pwa": "0.16.4", "vite-plugin-pwa": "0.16.4",
"vite-plugin-sentry": "1.3.0", "vite-plugin-sentry": "1.3.0",
"vite-svg-loader": "4.0.0", "vite-svg-loader": "4.0.0",
"vitest": "0.33.0", "vitest": "0.33.0",
"vue-tsc": "1.8.4", "vue-tsc": "1.8.5",
"wait-on": "7.0.1", "wait-on": "7.0.1",
"workbox-cli": "7.0.0" "workbox-cli": "7.0.0"
}, },

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,12 @@
import { computed, shallowRef, watchEffect, h, type VNode } from 'vue' import {computed, shallowRef, watchEffect, h, type VNode} from 'vue'
import { useRoute, useRouter } from 'vue-router' import {useRoute, useRouter} from 'vue-router'
import {useBaseStore} from '@/stores/base'
export function useRouteWithModal() { export function useRouteWithModal() {
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const backdropView = computed(() => route.fullPath && window.history.state.backdropView) const backdropView = computed(() => route.fullPath && window.history.state.backdropView)
const baseStore = useBaseStore()
const routeWithModal = computed(() => { const routeWithModal = computed(() => {
return backdropView.value return backdropView.value
@ -44,6 +46,18 @@ export function useRouteWithModal() {
function closeModal() { function closeModal() {
const historyState = computed(() => route.fullPath && window.history.state) const historyState = computed(() => route.fullPath && window.history.state)
// If the current project was changed because the user moved the currently opened task while coming from kanban,
// we need to reflect that change in the route when they close the task modal.
// The last route is only available as resolved string, therefore we need to use a regex for matching here
const kanbanRouteMatch = new RegExp('\\/projects\\/\\d+\\/kanban', 'g')
const kanbanRouter = {name: 'project.kanban', params: {projectId: baseStore.currentProject?.id}}
if (kanbanRouteMatch.test(historyState.value.back)
&& baseStore.currentProject
&& historyState.value.back !== router.resolve(kanbanRouter).fullPath) {
router.push(kanbanRouter)
return
}
if (historyState.value) { if (historyState.value) {
router.back() router.back()
} else { } else {

View File

@ -87,7 +87,7 @@
"defaultProject": "デフォルトのプロジェクト", "defaultProject": "デフォルトのプロジェクト",
"timezone": "タイムゾーン", "timezone": "タイムゾーン",
"overdueTasksRemindersTime": "期限切れタスクのリマインダー送信時間", "overdueTasksRemindersTime": "期限切れタスクのリマインダー送信時間",
"filterUsedOnOverview": "Saved filter used on the overview page" "filterUsedOnOverview": "概要ページに使用される絞り込み条件を保存しました"
}, },
"totp": { "totp": {
"title": "2要素認証", "title": "2要素認証",
@ -171,7 +171,7 @@
"title": "プロジェクト名", "title": "プロジェクト名",
"color": "色", "color": "色",
"projects": "プロジェクト", "projects": "プロジェクト",
"parent": "Parent Project", "parent": "親プロジェクト",
"search": "プロジェクトのキーワードを入力…", "search": "プロジェクトのキーワードを入力…",
"searchSelect": "クリックするかEnterキーを押してプロジェクトを選択", "searchSelect": "クリックするかEnterキーを押してプロジェクトを選択",
"shared": "共有プロジェクト", "shared": "共有プロジェクト",
@ -194,8 +194,8 @@
}, },
"background": { "background": {
"title": "プロジェクトの背景画像を設定", "title": "プロジェクトの背景画像を設定",
"remove": "背景画像削除", "remove": "背景画像削除",
"upload": "画像の選択", "upload": "画像を選択…",
"searchPlaceholder": "背景画像を検索…", "searchPlaceholder": "背景画像を検索…",
"poweredByUnsplash": "Powered by Unsplash", "poweredByUnsplash": "Powered by Unsplash",
"loadMore": "写真をもっと読み込む", "loadMore": "写真をもっと読み込む",
@ -254,9 +254,9 @@
"userTeam": { "userTeam": {
"typeUser": "ユーザー", "typeUser": "ユーザー",
"typeTeam": "チーム", "typeTeam": "チーム",
"shared": "Shared with these {type}", "shared": "アクセスできる{type}",
"you": "You", "you": "あなた",
"notShared": "Not shared with any {type} yet.", "notShared": "まだどの{type}とも共有していません。",
"removeHeader": "Remove a {type} from the {sharable}", "removeHeader": "Remove a {type} from the {sharable}",
"removeText": "Are you sure you want to remove this {sharable} from the {type}? This cannot be undone!", "removeText": "Are you sure you want to remove this {sharable} from the {type}? This cannot be undone!",
"removeSuccess": "The {sharable} was successfully removed from the {type}.", "removeSuccess": "The {sharable} was successfully removed from the {type}.",
@ -329,25 +329,25 @@
"title": "絞り込み", "title": "絞り込み",
"clear": "絞り込みの解除", "clear": "絞り込みの解除",
"attributes": { "attributes": {
"title": "Title", "title": "条件名",
"titlePlaceholder": "The saved filter title goes here…", "titlePlaceholder": "条件名を入力…",
"description": "説明", "description": "説明",
"descriptionPlaceholder": "The description goes here…", "descriptionPlaceholder": "説明を入力…",
"includeNulls": "Include Tasks which don't have a value set", "includeNulls": "値を設定していないタスクを含める",
"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": "完了したタスクを表示", "showDoneTasks": "完了したタスクを表示",
"sortAlphabetically": "アルファベット順に並べ替える", "sortAlphabetically": "アルファベット順に並べ替える",
"enablePriority": "優先度によるフィルターの有効化", "enablePriority": "優先度による絞り込みを有効化",
"enablePercentDone": "進捗状況によるフィルターの有効化", "enablePercentDone": "進捗状況による絞り込みを有効化",
"dueDateRange": "期日の範囲", "dueDateRange": "期日の範囲",
"startDateRange": "開始日の範囲", "startDateRange": "開始日の範囲",
"endDateRange": "開始日の範囲", "endDateRange": "開始日の範囲",
"reminderRange": "リマインダーの範囲" "reminderRange": "リマインダーの範囲"
}, },
"create": { "create": {
"title": "New Saved Filter", "title": "新しい絞り込み条件の作成",
"description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.", "description": "A saved filter is a virtual project which is computed from a set of filters each time it is accessed.",
"action": "Create new saved filter", "action": "新しい絞り込み条件を作成",
"titleRequired": "Please provide a title for the filter." "titleRequired": "Please provide a title for the filter."
}, },
"delete": { "delete": {
@ -492,17 +492,17 @@
"ranges": { "ranges": {
"today": "今日", "today": "今日",
"thisWeek": "今週", "thisWeek": "今週",
"restOfThisWeek": "現在日時から週末まで", "restOfThisWeek": "から週末まで",
"nextWeek": "来週", "nextWeek": "来週",
"next7Days": "7日間", "next7Days": "7日間",
"lastWeek": "先週", "lastWeek": "先週",
"thisMonth": "今月", "thisMonth": "今月",
"restOfThisMonth": "現在日時から月末まで", "restOfThisMonth": "から月末まで",
"nextMonth": "来月", "nextMonth": "来月",
"next30Days": "30日間", "next30Days": "30日間",
"lastMonth": "先月", "lastMonth": "先月",
"thisYear": "今年", "thisYear": "今年",
"restOfThisYear": "現在日時から年末まで" "restOfThisYear": "から年末まで"
} }
}, },
"datemathHelp": { "datemathHelp": {
@ -618,10 +618,10 @@
}, },
"subscription": { "subscription": {
"subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.", "subscribedTaskThroughParentProject": "You can't unsubscribe here because you are subscribed to this task through its project.",
"subscribedProject": "You are currently subscribed to this project and will receive notifications for changes.", "subscribedProject": "現在このプロジェクトを購読しており、変更通知が届きます。",
"notSubscribedProject": "You are not subscribed to this project and won't receive notifications for changes.", "notSubscribedProject": "このプロジェクトを購読していないため、変更通知は届きません。",
"subscribedTask": "You are currently subscribed to this task and will receive notifications for changes.", "subscribedTask": "現在このタスクを購読しており、変更通知が届きます。",
"notSubscribedTask": "You are not subscribed to this task and won't receive notifications for changes.", "notSubscribedTask": "このタスクを購読していないため、変更通知は届きません。",
"subscribe": "購読", "subscribe": "購読",
"unsubscribe": "購読解除", "unsubscribe": "購読解除",
"subscribeSuccessProject": "You are now subscribed to this project", "subscribeSuccessProject": "You are now subscribed to this project",
@ -826,34 +826,34 @@
"allPages": "これらのショートカットはすべてのページで機能します。", "allPages": "これらのショートカットはすべてのページで機能します。",
"currentPageOnly": "これらのショートカットはこのページで機能します。", "currentPageOnly": "これらのショートカットはこのページで機能します。",
"somePagesOnly": "これらのショートカットは一部のページでのみ機能します。", "somePagesOnly": "これらのショートカットは一部のページでのみ機能します。",
"toggleMenu": "Toggle The Menu", "toggleMenu": "メニューの表示/非表示",
"quickSearch": "Open the search/quick action bar", "quickSearch": "Open the search/quick action bar",
"then": "then", "then": " ",
"task": { "task": {
"title": "Task Page", "title": "タスク",
"done": "タスクの完了/取り消し", "done": "タスクの完了/取り消し",
"assign": "Assign this task to a user", "assign": "タスクに担当者を割り当てる",
"labels": "Add labels to this task", "labels": "タスクにラベルを追加",
"dueDate": "Change the due date of this task", "dueDate": "タスクの期日を設定",
"attachment": "このタスクに添付ファイルを追加", "attachment": "タスクに添付ファイルを追加",
"related": "Modify related tasks of this task", "related": "関連タスクを追加",
"color": "タスクの色変更", "color": "タスクの色変更",
"move": "Move this task to another project", "move": "タスクを別のプロジェクトに移動",
"reminder": "Manage reminders of this task", "reminder": "タスクのリマインダーを設定",
"description": "Toggle editing of the task description", "description": "タスクの説明を編集",
"delete": "タスク削除", "delete": "タスク削除",
"priority": "Change the priority of this task", "priority": "タスクの優先度を設定",
"favorite": "Mark this task as favorite / unfavorite" "favorite": "タスクをお気に入りに追加/削除"
}, },
"project": { "project": {
"title": "Project Views", "title": "プロジェクト",
"switchToListView": "リストで表示", "switchToListView": "リストで表示",
"switchToGanttView": "ガントチャートで表示", "switchToGanttView": "ガントチャートで表示",
"switchToKanbanView": "カンバンボードで表示", "switchToKanbanView": "カンバンボードで表示",
"switchToTableView": "テーブルで表示" "switchToTableView": "テーブルで表示"
}, },
"navigation": { "navigation": {
"title": "Navigation", "title": "ナビゲーション",
"overview": "概要に移動", "overview": "概要に移動",
"upcoming": "今後の予定に移動", "upcoming": "今後の予定に移動",
"labels": "ラベルに移動", "labels": "ラベルに移動",
@ -868,13 +868,13 @@
"menu": { "menu": {
"edit": "編集", "edit": "編集",
"archive": "アーカイブ", "archive": "アーカイブ",
"duplicate": "Duplicate", "duplicate": "複製",
"delete": "削除", "delete": "削除",
"unarchive": "アーカイブの取り消し", "unarchive": "アーカイブの取り消し",
"setBackground": "Set background", "setBackground": "背景画像の設定",
"share": "共有", "share": "共有",
"newProject": "新しいプロジェクトの作成", "newProject": "新しいプロジェクトの作成",
"createProject": "Create project" "createProject": "プロジェクトの作成"
}, },
"apiConfig": { "apiConfig": {
"url": "Vikunja URL", "url": "Vikunja URL",
@ -891,9 +891,9 @@
"contact": "contact us" "contact": "contact us"
}, },
"notification": { "notification": {
"title": "Notifications", "title": "通知",
"none": "You don't have any notifications. Have a nice day!", "none": "通知はありません。それではよい一日を!",
"explainer": "Notifications will appear here when actions projects or tasks you subscribed to happen." "explainer": "購読しているプロジェクトやタスクが変更されると通知されます。"
}, },
"quickActions": { "quickActions": {
"commands": "コマンド", "commands": "コマンド",
@ -906,7 +906,7 @@
"newTask": "新しいタスク名を入力…", "newTask": "新しいタスク名を入力…",
"newTeam": "新しいチーム名を入力…", "newTeam": "新しいチーム名を入力…",
"createTask": "現在のプロジェクト ({title}) にタスクを作成", "createTask": "現在のプロジェクト ({title}) にタスクを作成",
"createProject": "Create a project", "createProject": "プロジェクトを作成",
"cmds": { "cmds": {
"newTask": "新しいタスクの作成", "newTask": "新しいタスクの作成",
"newProject": "新しいプロジェクトの作成", "newProject": "新しいプロジェクトの作成",

View File

@ -13,8 +13,14 @@ export function getErrorText(r): string {
return message return message
} }
} }
let message = data?.message || r.message
if (typeof r.cause?.message !== 'undefined') {
message += ' ' + r.cause.message
}
return data?.message || r.message return message
} }
export interface Action { export interface Action {

View File

@ -719,15 +719,6 @@ describe('Parse Task Text', () => {
'every year': {type: 'years', amount: 1}, 'every year': {type: 'years', amount: 1},
'every 1 year': {type: 'years', amount: 1}, 'every 1 year': {type: 'years', amount: 1},
'every 4 years': {type: 'years', amount: 4}, 'every 4 years': {type: 'years', amount: 4},
'anually': {type: 'years', amount: 1},
'bianually': {type: 'months', amount: 6},
'semiannually': {type: 'months', amount: 6},
'biennially': {type: 'years', amount: 2},
'daily': {type: 'days', amount: 1},
'hourly': {type: 'hours', amount: 1},
'monthly': {type: 'months', amount: 1},
'weekly': {type: 'weeks', amount: 1},
'yearly': {type: 'years', amount: 1},
'every one hour': {type: 'hours', amount: 1}, // maybe unnesecary but better to include it for completeness sake 'every one hour': {type: 'hours', amount: 1}, // maybe unnesecary but better to include it for completeness sake
'every two hours': {type: 'hours', amount: 2}, 'every two hours': {type: 'hours', amount: 2},
'every three hours': {type: 'hours', amount: 3}, 'every three hours': {type: 'hours', amount: 3},
@ -738,6 +729,15 @@ describe('Parse Task Text', () => {
'every eight hours': {type: 'hours', amount: 8}, 'every eight hours': {type: 'hours', amount: 8},
'every nine hours': {type: 'hours', amount: 9}, 'every nine hours': {type: 'hours', amount: 9},
'every ten hours': {type: 'hours', amount: 10}, 'every ten hours': {type: 'hours', amount: 10},
'annually': {type: 'years', amount: 1},
'biannually': {type: 'months', amount: 6},
'semiannually': {type: 'months', amount: 6},
'biennially': {type: 'years', amount: 2},
'daily': {type: 'days', amount: 1},
'hourly': {type: 'hours', amount: 1},
'monthly': {type: 'months', amount: 1},
'weekly': {type: 'weeks', amount: 1},
'yearly': {type: 'years', amount: 1},
} as Record<string, IRepeatAfter> } as Record<string, IRepeatAfter>
for (const c in cases) { for (const c in cases) {
@ -749,5 +749,26 @@ describe('Parse Task Text', () => {
expect(result?.repeats?.amount).toBe(cases[c].amount) expect(result?.repeats?.amount).toBe(cases[c].amount)
}) })
} }
const wordCases = [
'annually',
'biannually',
'semiannually',
'biennially',
'daily',
'hourly',
'monthly',
'weekly',
'yearly',
]
wordCases.forEach(c => {
it(`should ignore recurring periods if they are part of a word ${c}`, () => {
const result = parseTaskText(`Lorem Ipsum word${c}notword`)
expect(result.text).toBe(`Lorem Ipsum word${c}notword`)
expect(result?.repeats).toBeNull()
})
})
}) })
}) })

View File

@ -165,7 +165,7 @@ const getPriority = (text: string, prefix: string): number | null => {
} }
const getRepeats = (text: string): repeatParsedResult => { const getRepeats = (text: string): repeatParsedResult => {
const regex = /((every|each) (([0-9]+|one|two|three|four|five|six|seven|eight|nine|ten) )?(hours?|days?|weeks?|months?|years?))|anually|bianually|semiannually|biennially|daily|hourly|monthly|weekly|yearly/ig const regex = /(^| )(((every|each) (([0-9]+|one|two|three|four|five|six|seven|eight|nine|ten) )?(hours?|days?|weeks?|months?|years?))|(annually|biannually|semiannually|biennially|daily|hourly|monthly|weekly|yearly))($| )/ig
const results = regex.exec(text) const results = regex.exec(text)
if (results === null) { if (results === null) {
return { return {
@ -175,7 +175,7 @@ const getRepeats = (text: string): repeatParsedResult => {
} }
let amount = 1 let amount = 1
switch (results[3] ? results[3].trim() : undefined) { switch (results[5] ? results[5].trim() : undefined) {
case 'one': case 'one':
amount = 1 amount = 1
break break
@ -207,22 +207,22 @@ const getRepeats = (text: string): repeatParsedResult => {
amount = 10 amount = 10
break break
default: default:
amount = results[3] ? parseInt(results[3]) : 1 amount = results[5] ? parseInt(results[5]) : 1
} }
let type: IRepeatType = REPEAT_TYPES.Hours let type: IRepeatType = REPEAT_TYPES.Hours
switch (results[0]) { switch (results[2]) {
case 'biennially': case 'biennially':
type = REPEAT_TYPES.Years type = REPEAT_TYPES.Years
amount = 2 amount = 2
break break
case 'bianually': case 'biannually':
case 'semiannually': case 'semiannually':
type = REPEAT_TYPES.Months type = REPEAT_TYPES.Months
amount = 6 amount = 6
break break
case 'yearly': case 'yearly':
case 'anually': case 'annually':
type = REPEAT_TYPES.Years type = REPEAT_TYPES.Years
break break
case 'daily': case 'daily':
@ -238,7 +238,7 @@ const getRepeats = (text: string): repeatParsedResult => {
type = REPEAT_TYPES.Weeks type = REPEAT_TYPES.Weeks
break break
default: default:
switch (results[5]) { switch (results[7]) {
case 'hour': case 'hour':
case 'hours': case 'hours':
type = REPEAT_TYPES.Hours type = REPEAT_TYPES.Hours

View File

@ -296,7 +296,16 @@ export const useAuthStore = defineStore('auth', () => {
logout() logout()
return return
} }
throw new Error('Error while refreshing user info:', {cause: e})
const cause = {e}
if (typeof e?.response?.data?.message !== 'undefined') {
cause.message = e.response.data.message
}
console.error('Error refreshing user info:', e)
throw new Error('Error while refreshing user info:', {cause})
} }
} }

View File

@ -1,7 +1,7 @@
<template> <template>
<ProjectWrapper <ProjectWrapper
class="project-kanban" class="project-kanban"
:project-id="projectId" :project-id="project.id"
viewName="kanban" viewName="kanban"
> >
<template #header> <template #header>
@ -224,7 +224,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {computed, nextTick, ref, watch, type PropType} from 'vue' import {computed, nextTick, ref, watch} from 'vue'
import {useI18n} from 'vue-i18n' import {useI18n} from 'vue-i18n'
import draggable from 'zhyswan-vuedraggable' import draggable from 'zhyswan-vuedraggable'
import {klona} from 'klona/lite' import {klona} from 'klona/lite'
@ -263,13 +263,6 @@ const DRAG_OPTIONS = {
const MIN_SCROLL_HEIGHT_PERCENT = 0.25 const MIN_SCROLL_HEIGHT_PERCENT = 0.25
const props = defineProps({
projectId: {
type: Number as PropType<IProject['id']>,
required: true,
},
})
const {t} = useI18n({useScope: 'global'}) const {t} = useI18n({useScope: 'global'})
const baseStore = useBaseStore() const baseStore = useBaseStore()
@ -340,11 +333,12 @@ const taskLoading = computed(() => taskStore.isLoading)
watch( watch(
() => ({ () => ({
projectId: props.projectId,
params: params.value, params: params.value,
project: project.value,
}), }),
({projectId, params}) => { ({params, project}) => {
if (projectId === undefined) { const projectId = project.id
if (projectId === undefined || Number(projectId) === 0) {
return return
} }
collapsedBuckets.value = getCollapsedBucketState(projectId) collapsedBuckets.value = getCollapsedBucketState(projectId)
@ -483,7 +477,7 @@ async function addTaskToBucket(bucketId: IBucket['id']) {
const task = await taskStore.createNewTask({ const task = await taskStore.createNewTask({
title: newTaskText.value, title: newTaskText.value,
bucketId, bucketId,
projectId: props.projectId, projectId: project.value.id,
}) })
newTaskText.value = '' newTaskText.value = ''
kanbanStore.addTaskToBucket(task) kanbanStore.addTaskToBucket(task)
@ -505,7 +499,7 @@ async function createNewBucket() {
await kanbanStore.createBucket(new BucketModel({ await kanbanStore.createBucket(new BucketModel({
title: newBucketTitle.value, title: newBucketTitle.value,
projectId: props.projectId, projectId: project.value.id,
})) }))
newBucketTitle.value = '' newBucketTitle.value = ''
showNewBucketInput.value = false showNewBucketInput.value = false
@ -525,7 +519,7 @@ async function deleteBucket() {
await kanbanStore.deleteBucket({ await kanbanStore.deleteBucket({
bucket: new BucketModel({ bucket: new BucketModel({
id: bucketToDelete.value, id: bucketToDelete.value,
projectId: props.projectId, projectId: project.value.id,
}), }),
params: params.value, params: params.value,
}) })
@ -612,7 +606,7 @@ async function toggleDoneBucket(bucket: IBucket) {
function collapseBucket(bucket: IBucket) { function collapseBucket(bucket: IBucket) {
collapsedBuckets.value[bucket.id] = true collapsedBuckets.value[bucket.id] = true
saveCollapsedBucketState(props.projectId, collapsedBuckets.value) saveCollapsedBucketState(project.value.id, collapsedBuckets.value)
} }
function unCollapseBucket(bucket: IBucket) { function unCollapseBucket(bucket: IBucket) {
@ -621,7 +615,7 @@ function unCollapseBucket(bucket: IBucket) {
} }
collapsedBuckets.value[bucket.id] = false collapsedBuckets.value[bucket.id] = false
saveCollapsedBucketState(props.projectId, collapsedBuckets.value) saveCollapsedBucketState(project.value.id, collapsedBuckets.value)
} }
</script> </script>