Compare commits
12 Commits
68aaea44d8
...
97f78984ec
Author | SHA1 | Date | |
---|---|---|---|
97f78984ec | |||
ae001c6ca7 | |||
f0b340a9c7 | |||
40538df392 | |||
fc17b16c60 | |||
6c59b4e2d2 | |||
e8a38ed482 | |||
f5604dcac6 | |||
049c644959 | |||
07b1e9a6b7 | |||
7aedf6ee1f | |||
bc9bfe3300 |
23
.github/workflows/lockdown.yml
vendored
Normal file
23
.github/workflows/lockdown.yml
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
name: 'Repo Lockdown'
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: opened
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/repo-lockdown@v3
|
||||
with:
|
||||
pr-comment: 'Hi! Thank you for your contribution.
|
||||
|
||||
This repo is only a mirror and unfortunately we can''t accept PRs made here. Please re-submit your changes to [our Gitea instance](https://kolaente.dev/vikunja/frontend/pulls).
|
||||
|
||||
Also check out the [contribution guidelines](https://vikunja.io/docs/development/#pull-requests).
|
||||
|
||||
Thank you for your understanding.'
|
30
package.json
30
package.json
|
@ -13,7 +13,7 @@
|
|||
},
|
||||
"homepage": "https://vikunja.io/",
|
||||
"funding": "https://opencollective.com/vikunja",
|
||||
"packageManager": "pnpm@8.8.0",
|
||||
"packageManager": "pnpm@8.9.0",
|
||||
"keywords": [
|
||||
"todo",
|
||||
"productivity",
|
||||
|
@ -49,14 +49,14 @@
|
|||
"@fortawesome/free-regular-svg-icons": "6.4.2",
|
||||
"@fortawesome/free-solid-svg-icons": "6.4.2",
|
||||
"@fortawesome/vue-fontawesome": "3.0.3",
|
||||
"@github/hotkey": "2.0.1",
|
||||
"@github/hotkey": "2.1.0",
|
||||
"@infectoone/vue-ganttastic": "2.2.0",
|
||||
"@intlify/unplugin-vue-i18n": "1.4.0",
|
||||
"@kyvg/vue3-notification": "3.0.2",
|
||||
"@sentry/tracing": "7.73.0",
|
||||
"@sentry/vue": "7.73.0",
|
||||
"@vueuse/core": "10.4.1",
|
||||
"@vueuse/router": "10.4.1",
|
||||
"@vueuse/core": "10.5.0",
|
||||
"@vueuse/router": "10.5.0",
|
||||
"axios": "1.5.1",
|
||||
"blurhash": "2.0.5",
|
||||
"bulma-css-variables": "0.9.33",
|
||||
|
@ -70,11 +70,11 @@
|
|||
"flatpickr": "4.6.13",
|
||||
"flexsearch": "0.7.31",
|
||||
"floating-vue": "2.0.0-beta.24",
|
||||
"highlight.js": "11.8.0",
|
||||
"highlight.js": "11.9.0",
|
||||
"is-touch-device": "1.0.1",
|
||||
"klona": "2.0.6",
|
||||
"lodash.debounce": "4.0.8",
|
||||
"marked": "9.1.0",
|
||||
"marked": "9.1.1",
|
||||
"pinia": "2.1.6",
|
||||
"register-service-worker": "1.7.2",
|
||||
"snake-case": "3.0.4",
|
||||
|
@ -103,11 +103,11 @@
|
|||
"@types/is-touch-device": "1.0.0",
|
||||
"@types/lodash.debounce": "4.0.7",
|
||||
"@types/marked": "5.0.2",
|
||||
"@types/node": "18.18.3",
|
||||
"@types/node": "18.18.4",
|
||||
"@types/postcss-preset-env": "7.7.0",
|
||||
"@types/sortablejs": "1.15.3",
|
||||
"@typescript-eslint/eslint-plugin": "6.7.4",
|
||||
"@typescript-eslint/parser": "6.7.4",
|
||||
"@typescript-eslint/eslint-plugin": "6.7.5",
|
||||
"@typescript-eslint/parser": "6.7.5",
|
||||
"@vitejs/plugin-legacy": "4.1.1",
|
||||
"@vitejs/plugin-vue": "4.4.0",
|
||||
"@vue/eslint-config-typescript": "11.0.3",
|
||||
|
@ -115,12 +115,12 @@
|
|||
"@vue/tsconfig": "0.4.0",
|
||||
"autoprefixer": "10.4.16",
|
||||
"browserslist": "4.22.1",
|
||||
"caniuse-lite": "1.0.30001543",
|
||||
"caniuse-lite": "1.0.30001547",
|
||||
"css-has-pseudo": "6.0.0",
|
||||
"csstype": "3.1.2",
|
||||
"cypress": "12.17.4",
|
||||
"esbuild": "0.19.4",
|
||||
"eslint": "8.50.0",
|
||||
"eslint": "8.51.0",
|
||||
"eslint-plugin-vue": "9.17.0",
|
||||
"happy-dom": "10.11.2",
|
||||
"histoire": "0.17.2",
|
||||
|
@ -128,19 +128,19 @@
|
|||
"postcss-easing-gradients": "3.0.1",
|
||||
"postcss-easings": "4.0.0",
|
||||
"postcss-focus-within": "8.0.0",
|
||||
"postcss-preset-env": "9.1.4",
|
||||
"postcss-preset-env": "9.2.0",
|
||||
"rollup": "3.29.4",
|
||||
"rollup-plugin-visualizer": "5.9.2",
|
||||
"sass": "1.68.0",
|
||||
"sass": "1.69.2",
|
||||
"start-server-and-test": "2.0.1",
|
||||
"typescript": "5.2.2",
|
||||
"vite": "4.4.10",
|
||||
"vite": "4.4.11",
|
||||
"vite-plugin-inject-preload": "1.3.3",
|
||||
"vite-plugin-pwa": "0.16.5",
|
||||
"vite-plugin-sentry": "1.3.0",
|
||||
"vite-svg-loader": "4.0.0",
|
||||
"vitest": "0.34.6",
|
||||
"vue-tsc": "1.8.15",
|
||||
"vue-tsc": "1.8.18",
|
||||
"wait-on": "7.0.1",
|
||||
"workbox-cli": "7.0.0"
|
||||
},
|
||||
|
|
720
pnpm-lock.yaml
720
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
|||
class="menu-show-button"
|
||||
@click="baseStore.toggleMenu()"
|
||||
@shortkey="() => baseStore.toggleMenu()"
|
||||
v-shortcut="'Control+e'"
|
||||
v-shortcut="'Mod+e'"
|
||||
:title="$t('keyboardShortcuts.toggleMenu')"
|
||||
:aria-label="menuActive ? $t('misc.hideMenu') : $t('misc.showMenu')"
|
||||
/>
|
||||
|
|
|
@ -5,13 +5,12 @@ import {onBeforeUnmount, onMounted} from 'vue'
|
|||
import {eventToHotkeyString} from '@github/hotkey'
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
const GLOBAL_HOTKEY = 'Control+k'
|
||||
|
||||
// See https://github.com/github/hotkey/discussions/85#discussioncomment-5214660
|
||||
function openQuickActionsViaHotkey(event) {
|
||||
const hotkeyString = eventToHotkeyString(event)
|
||||
if (!hotkeyString) return
|
||||
if (hotkeyString !== GLOBAL_HOTKEY) return
|
||||
if (hotkeyString !== 'Control+k' && hotkeyString !== 'Meta+k') return
|
||||
event.preventDefault()
|
||||
|
||||
openQuickActions()
|
||||
|
|
|
@ -152,6 +152,10 @@ export const KEYBOARD_SHORTCUTS : ShortcutGroup[] = [
|
|||
title: 'keyboardShortcuts.task.favorite',
|
||||
keys: ['s'],
|
||||
},
|
||||
{
|
||||
title: 'keyboardShortcuts.task.save',
|
||||
keys: [ctrl, 's'],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
|
@ -1,15 +1,11 @@
|
|||
import type {Directive} from 'vue'
|
||||
import {install, uninstall} from '@github/hotkey'
|
||||
import {isAppleDevice} from '@/helpers/isAppleDevice'
|
||||
|
||||
const directive = <Directive<HTMLElement,string>>{
|
||||
mounted(el, {value}) {
|
||||
if(value === '') {
|
||||
return
|
||||
}
|
||||
if (isAppleDevice() && value.includes('Control')) {
|
||||
value = value.replace('Control', 'Meta')
|
||||
}
|
||||
install(el, value)
|
||||
},
|
||||
beforeUnmount(el) {
|
||||
|
|
|
@ -176,6 +176,7 @@
|
|||
"title": "Delete your Vikunja Account",
|
||||
"text1": "The deletion of your account is permanent and cannot be undone. We will delete all your projects, tasks and everything associated with it.",
|
||||
"text2": "To proceed, please enter your password. You will receive an email with further instructions.",
|
||||
"text3": "To proceed, please press the button below. You will receive an email with further instructions.",
|
||||
"confirm": "Delete my account",
|
||||
"requestSuccess": "The request was successful. You'll receive an email with further instructions.",
|
||||
"passwordRequired": "Please enter your password.",
|
||||
|
@ -183,6 +184,7 @@
|
|||
"scheduled": "We will delete your Vikunja account at {date} ({dateSince}).",
|
||||
"scheduledCancel": "To cancel the deletion of your account, click here.",
|
||||
"scheduledCancelText": "To cancel the deletion of your account, please enter your password below:",
|
||||
"scheduledCancelButton": "To cancel the deletion of your account, please press the button below:",
|
||||
"scheduledCancelConfirm": "Cancel the deletion of my account",
|
||||
"scheduledCancelSuccess": "We will not delete your account."
|
||||
},
|
||||
|
@ -883,7 +885,8 @@
|
|||
"description": "Toggle editing of the task description",
|
||||
"delete": "Delete this task",
|
||||
"priority": "Change the priority of this task",
|
||||
"favorite": "Mark this task as favorite / unfavorite"
|
||||
"favorite": "Mark this task as favorite / unfavorite",
|
||||
"save": "Save the current task"
|
||||
},
|
||||
"project": {
|
||||
"title": "Project Views",
|
||||
|
|
|
@ -458,11 +458,12 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref, reactive, toRef, shallowReactive, computed, watch, nextTick} from 'vue'
|
||||
import {ref, reactive, toRef, shallowReactive, computed, watch, nextTick, onMounted, onBeforeUnmount} from 'vue'
|
||||
import {useRouter, type RouteLocation} from 'vue-router'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import {unrefElement} from '@vueuse/core'
|
||||
import {klona} from 'klona/lite'
|
||||
import {eventToHotkeyString} from '@github/hotkey'
|
||||
|
||||
import TaskService from '@/services/task'
|
||||
import TaskModel, {TASK_DEFAULT_COLOR} from '@/models/task'
|
||||
|
@ -533,6 +534,24 @@ const kanbanStore = useKanbanStore()
|
|||
const task = ref<ITask>(new TaskModel())
|
||||
useTitle(toRef(task.value, 'title'))
|
||||
|
||||
// See https://github.com/github/hotkey/discussions/85#discussioncomment-5214660
|
||||
function saveTaskViaHotkey(event) {
|
||||
const hotkeyString = eventToHotkeyString(event)
|
||||
if (!hotkeyString) return
|
||||
if (hotkeyString !== 'Control+s' && hotkeyString !== 'Meta+s') return
|
||||
event.preventDefault()
|
||||
|
||||
saveTask()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('keydown', saveTaskViaHotkey)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener('keydown', saveTaskViaHotkey)
|
||||
})
|
||||
|
||||
// We doubled the task color property here because verte does not have a real change property, leading
|
||||
// to the color property change being triggered when the # is removed from it, leading to an update,
|
||||
// which leads in turn to a change... This creates an infinite loop in which the task is updated, changed,
|
||||
|
|
|
@ -10,29 +10,34 @@
|
|||
})
|
||||
}}
|
||||
</p>
|
||||
<p>
|
||||
{{ $t('user.deletion.scheduledCancelText') }}
|
||||
</p>
|
||||
<div class="field">
|
||||
<label class="label" for="currentPasswordAccountDelete">
|
||||
{{ $t('user.settings.currentPassword') }}
|
||||
</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
:class="{'is-danger': errPasswordRequired}"
|
||||
id="currentPasswordAccountDelete"
|
||||
:placeholder="$t('user.settings.currentPasswordPlaceholder')"
|
||||
type="password"
|
||||
v-model="password"
|
||||
@keyup="() => errPasswordRequired = password === ''"
|
||||
ref="passwordInput"
|
||||
/>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errPasswordRequired">
|
||||
{{ $t('user.deletion.passwordRequired') }}
|
||||
<template v-if="isLocalUser">
|
||||
<p>
|
||||
{{ $t('user.deletion.scheduledCancelText') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label" for="currentPasswordAccountDelete">
|
||||
{{ $t('user.settings.currentPassword') }}
|
||||
</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
:class="{'is-danger': errPasswordRequired}"
|
||||
id="currentPasswordAccountDelete"
|
||||
:placeholder="$t('user.settings.currentPasswordPlaceholder')"
|
||||
type="password"
|
||||
v-model="password"
|
||||
@keyup="() => errPasswordRequired = password === ''"
|
||||
ref="passwordInput"
|
||||
/>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errPasswordRequired">
|
||||
{{ $t('user.deletion.passwordRequired') }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
<p v-else>
|
||||
{{ $t('user.deletion.scheduledCancelButton') }}
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<x-button
|
||||
|
@ -43,10 +48,10 @@
|
|||
</x-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<form @submit.prevent="deleteAccount()">
|
||||
<p>
|
||||
{{ $t('user.deletion.text1') }}
|
||||
</p>
|
||||
<p>
|
||||
{{ $t('user.deletion.text1') }}
|
||||
</p>
|
||||
<form @submit.prevent="deleteAccount()" v-if="isLocalUser">
|
||||
<p>
|
||||
{{ $t('user.deletion.text2') }}
|
||||
</p>
|
||||
|
@ -71,6 +76,9 @@
|
|||
</p>
|
||||
</div>
|
||||
</form>
|
||||
<p v-else>
|
||||
{{ $t('user.deletion.text3') }}
|
||||
</p>
|
||||
|
||||
<x-button
|
||||
:loading="accountDeleteService.loading"
|
||||
|
@ -83,7 +91,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default { name: 'user-settings-deletion' }
|
||||
export default {name: 'user-settings-deletion'}
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -111,9 +119,12 @@ const configStore = useConfigStore()
|
|||
const userDeletionEnabled = computed(() => configStore.userDeletionEnabled)
|
||||
const deletionScheduledAt = computed(() => parseDateOrNull(authStore.info?.deletionScheduledAt))
|
||||
|
||||
const isLocalUser = computed(() => authStore.info?.isLocalUser)
|
||||
|
||||
const passwordInput = ref()
|
||||
|
||||
async function deleteAccount() {
|
||||
if (password.value === '') {
|
||||
if (isLocalUser.value && password.value === '') {
|
||||
errPasswordRequired.value = true
|
||||
passwordInput.value.focus()
|
||||
return
|
||||
|
@ -125,7 +136,7 @@ async function deleteAccount() {
|
|||
}
|
||||
|
||||
async function cancelDeletion() {
|
||||
if (password.value === '') {
|
||||
if (isLocalUser.value && password.value === '') {
|
||||
errPasswordRequired.value = true
|
||||
passwordInput.value.focus()
|
||||
return
|
||||
|
|
Reference in New Issue
Block a user