Merge branch 'main' into feature/ganttastic
# Conflicts: # pnpm-lock.yaml
This commit is contained in:
commit
a1e280e47b
15 changed files with 364 additions and 312 deletions
|
|
@ -6,13 +6,13 @@
|
|||
{{ $t('input.datemathHelp.intro') }}
|
||||
</p>
|
||||
<p>
|
||||
<i18n-t keypath="input.datemathHelp.expression">
|
||||
<i18n-t keypath="input.datemathHelp.expression" scope="global">
|
||||
<code>now</code>
|
||||
<code>||</code>
|
||||
</i18n-t>
|
||||
</p>
|
||||
<p>
|
||||
<i18n-t keypath="input.datemathHelp.similar">
|
||||
<i18n-t keypath="input.datemathHelp.similar" scope="global">
|
||||
<BaseButton
|
||||
href="https://grafana.com/docs/grafana/latest/dashboards/time-range-controls/"
|
||||
target="_blank">
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
<tr>
|
||||
<td><code>{{ exampleDate }}||+1M/d</code></td>
|
||||
<td>
|
||||
<i18n-t keypath="input.datemathHelp.examples.datePlusMonth">
|
||||
<i18n-t keypath="input.datemathHelp.examples.datePlusMonth" scope="global">
|
||||
<code>{{ exampleDate }}</code>
|
||||
</i18n-t>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="api-url-info" v-else>
|
||||
<i18n-t keypath="apiConfig.use">
|
||||
<i18n-t keypath="apiConfig.use" scope="global">
|
||||
<span class="url" v-tooltip="apiUrl"> {{ apiDomain }} </span>
|
||||
</i18n-t>
|
||||
<br/>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<message variant="danger">
|
||||
<i18n-t keypath="loadingError.failed">
|
||||
<i18n-t keypath="loadingError.failed" scope="global">
|
||||
<ButtonLink @click="reload">{{ $t('loadingError.tryAgain') }}</ButtonLink>
|
||||
<ButtonLink href="https://vikunja.io/contact/">{{ $t('loadingError.contact') }}</ButtonLink>
|
||||
</i18n-t>
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@
|
|||
</p>
|
||||
|
||||
<p class="mb-2">
|
||||
<i18n-t keypath="list.share.links.sharedBy">
|
||||
<i18n-t keypath="list.share.links.sharedBy" scope="global">
|
||||
<strong>{{ s.sharedBy.getDisplayName() }}</strong>
|
||||
</i18n-t>
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
<div class="filename">{{ a.file.name }}</div>
|
||||
<div class="info">
|
||||
<p class="attachment-info-meta">
|
||||
<i18n-t keypath="task.attachment.createdBy">
|
||||
<i18n-t keypath="task.attachment.createdBy" scope="global">
|
||||
<span v-tooltip="formatDateLong(a.created)">
|
||||
{{ formatDateSince(a.created) }}
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<p class="created">
|
||||
<time :datetime="formatISO(task.created)" v-tooltip="formatDateLong(task.created)">
|
||||
<i18n-t keypath="task.detail.created">
|
||||
<i18n-t keypath="task.detail.created" scope="global">
|
||||
<span>{{ formatDateSince(task.created) }}</span>
|
||||
{{ task.createdBy.getDisplayName() }}
|
||||
</i18n-t>
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
<br/>
|
||||
<!-- Computed properties to show the actual date every time it gets updated -->
|
||||
<time :datetime="formatISO(task.updated)" v-tooltip="updatedFormatted">
|
||||
<i18n-t keypath="task.detail.updated">
|
||||
<i18n-t keypath="task.detail.updated" scope="global">
|
||||
<span>{{ updatedSince }}</span>
|
||||
</i18n-t>
|
||||
</time>
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
<template v-if="task.done">
|
||||
<br/>
|
||||
<time :datetime="formatISO(task.doneAt)" v-tooltip="doneFormatted">
|
||||
<i18n-t keypath="task.detail.doneAt">
|
||||
<i18n-t keypath="task.detail.doneAt" scope="global">
|
||||
<span>{{ doneSince }}</span>
|
||||
</i18n-t>
|
||||
</time>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import AbstractService from './abstractService'
|
||||
import {downloadBlob} from '../helpers/downloadBlob'
|
||||
|
||||
const DOWNLOAD_NAME = 'vikunja-export.zip'
|
||||
|
||||
export default class DataExportService extends AbstractService {
|
||||
request(password: string) {
|
||||
return this.post('/user/export/request', {password})
|
||||
|
|
@ -10,7 +12,7 @@ export default class DataExportService extends AbstractService {
|
|||
const clear = this.setLoading()
|
||||
try {
|
||||
const url = await this.getBlobUrl('/user/export/download', 'POST', {password})
|
||||
downloadBlob(url, 'vikunja-export.zip')
|
||||
downloadBlob(url, DOWNLOAD_NAME)
|
||||
} finally {
|
||||
clear()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,52 +34,43 @@
|
|||
</create-edit>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {defineComponent} from 'vue'
|
||||
import {mapState} from 'pinia'
|
||||
<script setup lang="ts">
|
||||
import {computed, ref} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import {useRouter} from 'vue-router'
|
||||
|
||||
import LabelModel from '../../models/label'
|
||||
import CreateEdit from '@/components/misc/create-edit.vue'
|
||||
import ColorPicker from '../../components/input/colorPicker.vue'
|
||||
import { setTitle } from '@/helpers/setTitle'
|
||||
import { useLabelStore } from '@/stores/labels'
|
||||
import ColorPicker from '@/components/input/colorPicker.vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NewLabel',
|
||||
data() {
|
||||
return {
|
||||
label: new LabelModel(),
|
||||
showError: false,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
CreateEdit,
|
||||
ColorPicker,
|
||||
},
|
||||
mounted() {
|
||||
setTitle(this.$t('label.create.title'))
|
||||
},
|
||||
computed: {
|
||||
...mapState(useLabelStore, {
|
||||
loading: state => state.isLoading,
|
||||
}),
|
||||
},
|
||||
methods: {
|
||||
async newLabel() {
|
||||
if (this.label.title === '') {
|
||||
this.showError = true
|
||||
return
|
||||
}
|
||||
this.showError = false
|
||||
import LabelModel from '@/models/label'
|
||||
import {useLabelStore} from '@/stores/labels'
|
||||
import {useTitle} from '@/composables/useTitle'
|
||||
import {success} from '@/message'
|
||||
|
||||
const labelStore = useLabelStore()
|
||||
const label = labelStore.createLabel(this.label)
|
||||
this.$router.push({
|
||||
name: 'labels.index',
|
||||
params: {id: label.id},
|
||||
})
|
||||
this.$message.success({message: this.$t('label.create.success')})
|
||||
},
|
||||
},
|
||||
})
|
||||
const router = useRouter()
|
||||
|
||||
const {t} = useI18n({useScope: 'global'})
|
||||
useTitle(() => t('label.create.title'))
|
||||
|
||||
const labelStore = useLabelStore()
|
||||
const label = ref(new LabelModel())
|
||||
|
||||
const showError = ref(false)
|
||||
const loading = computed(() => labelStore.isLoading)
|
||||
|
||||
async function newLabel() {
|
||||
if (label.value.title === '') {
|
||||
showError.value = true
|
||||
return
|
||||
}
|
||||
showError.value = false
|
||||
|
||||
const labelStore = useLabelStore()
|
||||
const newLabel = labelStore.createLabel(label.value)
|
||||
router.push({
|
||||
name: 'labels.index',
|
||||
params: {id: newLabel.id},
|
||||
})
|
||||
success({message: t('label.create.success')})
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -10,9 +10,12 @@
|
|||
class="control is-expanded"
|
||||
:class="{ 'is-loading': namespaceService.loading }"
|
||||
>
|
||||
<!-- The user should be able to close the modal by pressing escape - that already works with the default modal.
|
||||
But with the input modal here since it autofocuses the input that input field catches the focus instead.
|
||||
Hence we place the listener on the input field directly. -->
|
||||
<input
|
||||
@keyup.enter="newNamespace()"
|
||||
@keyup.esc="back()"
|
||||
@keyup.esc="$router.back()"
|
||||
class="input"
|
||||
:placeholder="$t('namespace.attributes.titlePlaceholder')"
|
||||
type="text"
|
||||
|
|
@ -40,48 +43,42 @@
|
|||
</create-edit>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {defineComponent} from 'vue'
|
||||
<script setup lang="ts">
|
||||
import {ref, shallowReactive} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import {useRouter} from 'vue-router'
|
||||
|
||||
import Message from '@/components/misc/message.vue'
|
||||
import NamespaceModel from '../../models/namespace'
|
||||
import NamespaceService from '../../services/namespace'
|
||||
import CreateEdit from '@/components/misc/create-edit.vue'
|
||||
import ColorPicker from '../../components/input/colorPicker.vue'
|
||||
import { setTitle } from '@/helpers/setTitle'
|
||||
import ColorPicker from '@/components/input/colorPicker.vue'
|
||||
|
||||
import NamespaceModel from '@/models/namespace'
|
||||
import NamespaceService from '@/services/namespace'
|
||||
import {useNamespaceStore} from '@/stores/namespaces'
|
||||
import type {INamespace} from '@/modelTypes/INamespace'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NewNamespace',
|
||||
data() {
|
||||
return {
|
||||
showError: false,
|
||||
namespace: new NamespaceModel(),
|
||||
namespaceService: new NamespaceService(),
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Message,
|
||||
ColorPicker,
|
||||
CreateEdit,
|
||||
},
|
||||
mounted() {
|
||||
setTitle(this.$t('namespace.create.title'))
|
||||
},
|
||||
methods: {
|
||||
async newNamespace() {
|
||||
if (this.namespace.title === '') {
|
||||
this.showError = true
|
||||
return
|
||||
}
|
||||
this.showError = false
|
||||
import {useTitle} from '@/composables/useTitle'
|
||||
import {success} from '@/message'
|
||||
|
||||
const namespace = await this.namespaceService.create(this.namespace)
|
||||
const namespaceStore = useNamespaceStore()
|
||||
namespaceStore.addNamespace(namespace)
|
||||
this.$message.success({message: this.$t('namespace.create.success')})
|
||||
this.$router.back()
|
||||
},
|
||||
},
|
||||
})
|
||||
const showError = ref(false)
|
||||
const namespace = ref<INamespace>(new NamespaceModel())
|
||||
const namespaceService = shallowReactive(new NamespaceService())
|
||||
|
||||
const {t} = useI18n({useScope: 'global'})
|
||||
const router = useRouter()
|
||||
|
||||
useTitle(() => t('namespace.create.title'))
|
||||
|
||||
async function newNamespace() {
|
||||
if (namespace.value.title === '') {
|
||||
showError.value = true
|
||||
return
|
||||
}
|
||||
showError.value = false
|
||||
|
||||
const newNamespace = await namespaceService.create(namespace.value)
|
||||
useNamespaceStore().addNamespace(newNamespace)
|
||||
success({message: t('namespace.create.success')})
|
||||
router.back()
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
{{ isLocalUser ? $t('user.settings.caldav.tokensHowTo') : $t('user.settings.caldav.mustUseToken') }}
|
||||
<template v-if="!isLocalUser">
|
||||
<br/>
|
||||
<i18n-t keypath="user.settings.caldav.usernameIs">
|
||||
<i18n-t keypath="user.settings.caldav.usernameIs" scope="global">
|
||||
<strong>{{ username }}</strong>
|
||||
</i18n-t>
|
||||
</template>
|
||||
|
|
|
|||
Reference in a new issue