forked from vikunja/frontend
Compare commits
48 Commits
feature/ca
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
ede8bc5015 | ||
924359f739 | |||
|
b84fe4c88b | ||
|
d57c9af332 | ||
|
eac07d3169 | ||
|
72d6701404 | ||
cb395f3f69 | |||
45e1ae66d6 | |||
e2c81d840f | |||
69654b823e | |||
f72fc79861 | |||
80664b6182 | |||
8b90b8f6a8 | |||
78ad9becf3 | |||
864928b378 | |||
c2b7d03dc5 | |||
4ee651cb2e | |||
5716a78127 | |||
d4d40a05ac | |||
f557e310c3 | |||
a3cab286cd | |||
8f726e17ef | |||
6aa0651013 | |||
eece690c6c | |||
3bd302081a | |||
017c025aaa | |||
232d2f7c88 | |||
9b0e8a06fa | |||
da8144c0c7 | |||
c5e5b96853 | |||
|
cf849da104 | ||
|
10bcdc8804 | ||
6c7fd4ef5b | |||
ba1ff6af81 | |||
6895b5ab94 | |||
|
d1d51ac998 | ||
|
1e0607cb86 | ||
83d6f30d2d | |||
bb56158112 | |||
f39d4d09cf | |||
6aa914ad9c | |||
f7f4bbbf3f | |||
01961f48e9 | |||
2de0337638 | |||
25c230cf63 | |||
|
f7bbd95fef | ||
|
2a4bf25d20 | ||
cb381e2ce9 |
|
@ -132,7 +132,7 @@ describe('List View Kanban', () => {
|
|||
cy.getSettled('.kanban .bucket .tasks .task')
|
||||
.contains(tasks[0].title)
|
||||
.first()
|
||||
.drag('.kanban .bucket:nth-child(2) .tasks .dropper')
|
||||
.drag('.kanban .bucket:nth-child(2) .tasks')
|
||||
|
||||
cy.get('.kanban .bucket:nth-child(2) .tasks')
|
||||
.should('contain', tasks[0].title)
|
||||
|
|
|
@ -6,7 +6,7 @@ describe('Log out', () => {
|
|||
|
||||
cy.get('.navbar .user .username')
|
||||
.click()
|
||||
cy.get('.navbar .user .dropdown-menu a.dropdown-item')
|
||||
cy.get('.navbar .user .dropdown-menu .dropdown-item')
|
||||
.contains('Logout')
|
||||
.click()
|
||||
|
||||
|
|
38
package.json
38
package.json
|
@ -20,12 +20,12 @@
|
|||
"dependencies": {
|
||||
"@github/hotkey": "2.0.0",
|
||||
"@kyvg/vue3-notification": "2.3.4",
|
||||
"@sentry/tracing": "6.17.4",
|
||||
"@sentry/vue": "6.17.4",
|
||||
"@sentry/tracing": "6.17.7",
|
||||
"@sentry/vue": "6.17.7",
|
||||
"@types/is-touch-device": "1.0.0",
|
||||
"@vue/compat": "3.2.29",
|
||||
"@vueuse/core": "7.5.5",
|
||||
"@vueuse/router": "7.5.5",
|
||||
"@vue/compat": "3.2.30",
|
||||
"@vueuse/core": "7.6.0",
|
||||
"@vueuse/router": "7.6.1",
|
||||
"bulma-css-variables": "0.9.33",
|
||||
"camel-case": "4.1.2",
|
||||
"codemirror": "5.65.1",
|
||||
|
@ -44,7 +44,7 @@
|
|||
"snake-case": "3.0.4",
|
||||
"ufo": "0.7.10",
|
||||
"v-tooltip": "4.0.0-beta.17",
|
||||
"vue": "3.2.29",
|
||||
"vue": "3.2.30",
|
||||
"vue-advanced-cropper": "2.8.0",
|
||||
"vue-drag-resize": "2.0.3",
|
||||
"vue-flatpickr-component": "9.0.5",
|
||||
|
@ -56,31 +56,31 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@4tw/cypress-drag-drop": "2.1.0",
|
||||
"@faker-js/faker": "6.0.0-alpha.5",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.36",
|
||||
"@faker-js/faker": "6.0.0-alpha.6",
|
||||
"@fortawesome/fontawesome-svg-core": "1.3.0",
|
||||
"@fortawesome/free-regular-svg-icons": "5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "5.15.4",
|
||||
"@fortawesome/vue-fontawesome": "3.0.0-5",
|
||||
"@types/flexsearch": "0.7.2",
|
||||
"@typescript-eslint/eslint-plugin": "5.10.2",
|
||||
"@typescript-eslint/parser": "5.10.2",
|
||||
"@vitejs/plugin-legacy": "1.6.4",
|
||||
"@vitejs/plugin-vue": "2.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.11.0",
|
||||
"@typescript-eslint/parser": "5.11.0",
|
||||
"@vitejs/plugin-legacy": "1.7.1",
|
||||
"@vitejs/plugin-vue": "2.2.0",
|
||||
"@vue/eslint-config-typescript": "10.0.0",
|
||||
"autoprefixer": "10.4.2",
|
||||
"axios": "0.25.0",
|
||||
"browserslist": "4.19.1",
|
||||
"caniuse-lite": "1.0.30001307",
|
||||
"caniuse-lite": "1.0.30001311",
|
||||
"cypress": "9.4.1",
|
||||
"esbuild": "0.14.18",
|
||||
"eslint": "8.8.0",
|
||||
"esbuild": "0.14.21",
|
||||
"eslint": "8.9.0",
|
||||
"eslint-plugin-vue": "8.4.1",
|
||||
"express": "4.17.2",
|
||||
"happy-dom": "2.31.1",
|
||||
"netlify-cli": "8.15.0",
|
||||
"netlify-cli": "8.16.1",
|
||||
"postcss": "8.4.6",
|
||||
"postcss-preset-env": "7.3.1",
|
||||
"rollup": "2.67.0",
|
||||
"rollup": "2.67.2",
|
||||
"rollup-plugin-visualizer": "5.5.4",
|
||||
"sass": "1.49.7",
|
||||
"slugify": "1.6.5",
|
||||
|
@ -88,9 +88,9 @@
|
|||
"vite": "2.7.13",
|
||||
"vite-plugin-pwa": "0.11.13",
|
||||
"vite-svg-loader": "3.1.2",
|
||||
"vitest": "0.2.7",
|
||||
"vitest": "0.3.2",
|
||||
"vue-tsc": "0.31.2",
|
||||
"wait-on": "6.0.0",
|
||||
"wait-on": "6.0.1",
|
||||
"workbox-cli": "6.4.2"
|
||||
},
|
||||
"eslintConfig": {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<ready>
|
||||
<template v-if="authUser">
|
||||
<top-navigation/>
|
||||
<TheNavigation/>
|
||||
<content-auth/>
|
||||
</template>
|
||||
<content-link-share v-else-if="authLinkShare"/>
|
||||
|
@ -27,7 +27,7 @@ import {success} from '@/message'
|
|||
|
||||
import Notification from '@/components/misc/notification.vue'
|
||||
import KeyboardShortcuts from './components/misc/keyboard-shortcuts/index.vue'
|
||||
import TopNavigation from './components/home/topNavigation.vue'
|
||||
import TheNavigation from '@/components/home/TheNavigation.vue'
|
||||
import ContentAuth from './components/home/contentAuth.vue'
|
||||
import ContentLinkShare from './components/home/contentLinkShare.vue'
|
||||
import NoAuthWrapper from '@/components/misc/no-auth-wrapper.vue'
|
||||
|
|
|
@ -69,10 +69,10 @@ watchEffect(() => {
|
|||
}
|
||||
|
||||
// if there is a href we assume the user wants an external link via a link element
|
||||
// we also set the attribute rel to "noopener" but make it possible to overwrite this by the user.
|
||||
// we also set a predefined value for the attribute rel, but make it possible to overwrite this by the user.
|
||||
if ('href' in attrs) {
|
||||
nodeName = 'a'
|
||||
bindings = {rel: 'noopener'}
|
||||
bindings = {rel: 'noreferrer noopener nofollow'}
|
||||
}
|
||||
|
||||
componentNodeName.value = nodeName
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useNow } from '@vueuse/core'
|
||||
|
||||
import LogoFull from '@/assets/logo-full.svg?component'
|
||||
import LogoFullPride from '@/assets/logo-full-pride.svg?component'
|
||||
|
||||
const Logo = computed(() => new Date().getMonth() === 5 ? LogoFullPride : LogoFull)
|
||||
const now = useNow()
|
||||
const Logo = computed(() => now.value.getMonth() === 5 ? LogoFullPride : LogoFull)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<template>
|
||||
<button
|
||||
type="button"
|
||||
@click="$store.commit('toggleMenu')"
|
||||
<BaseButton
|
||||
class="menu-show-button"
|
||||
@click="$store.commit('toggleMenu')"
|
||||
@shortkey="() => $store.commit('toggleMenu')"
|
||||
v-shortcut="'Control+e'"
|
||||
:title="$t('keyboardShortcuts.toggleMenu')"
|
||||
|
@ -10,11 +9,14 @@
|
|||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
import {computed} from 'vue'
|
||||
import {store} from '@/store'
|
||||
import {useStore} from 'vuex'
|
||||
|
||||
const menuActive = computed(() => store.menuActive)
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
|
||||
const store = useStore()
|
||||
const menuActive = computed(() => store.state.menuActive)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -22,11 +24,6 @@ $lineWidth: 2rem;
|
|||
$size: $lineWidth + 1rem;
|
||||
|
||||
.menu-show-button {
|
||||
// FIXME: create general button component
|
||||
appearance: none;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
|
||||
min-height: $size;
|
||||
width: $size;
|
||||
|
||||
|
|
|
@ -32,12 +32,13 @@
|
|||
</a>
|
||||
<notifications/>
|
||||
<div class="user">
|
||||
<img :src="userAvatar" alt="" class="avatar" width="40" height="40"/>
|
||||
<dropdown class="is-right" ref="usernameDropdown">
|
||||
<template #trigger>
|
||||
<x-button
|
||||
variant="secondary"
|
||||
:shadow="false">
|
||||
:shadow="false"
|
||||
>
|
||||
<img :src="userAvatar" alt="" class="avatar" width="40" height="40"/>
|
||||
<span class="username">{{ userInfo.name !== '' ? userInfo.name : userInfo.username }}</span>
|
||||
<span class="icon is-small">
|
||||
<icon icon="chevron-down"/>
|
||||
|
@ -45,92 +46,96 @@
|
|||
</x-button>
|
||||
</template>
|
||||
|
||||
<router-link :to="{name: 'user.settings'}" class="dropdown-item">
|
||||
<BaseButton
|
||||
:to="{name: 'user.settings'}"
|
||||
class="dropdown-item"
|
||||
>
|
||||
{{ $t('user.settings.title') }}
|
||||
</router-link>
|
||||
<a
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
v-if="imprintUrl"
|
||||
:href="imprintUrl"
|
||||
class="dropdown-item"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener nofollow"
|
||||
v-if="imprintUrl">
|
||||
>
|
||||
{{ $t('navigation.imprint') }}
|
||||
</a>
|
||||
<a
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
v-if="privacyPolicyUrl"
|
||||
:href="privacyPolicyUrl"
|
||||
class="dropdown-item"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener nofollow"
|
||||
v-if="privacyPolicyUrl">
|
||||
>
|
||||
{{ $t('navigation.privacy') }}
|
||||
</a>
|
||||
<a @click="$store.commit('keyboardShortcutsActive', true)" class="dropdown-item">
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
@click="$store.commit('keyboardShortcutsActive', true)"
|
||||
class="dropdown-item"
|
||||
>
|
||||
{{ $t('keyboardShortcuts.title') }}
|
||||
</a>
|
||||
<router-link :to="{name: 'about'}" class="dropdown-item">
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
:to="{name: 'about'}"
|
||||
class="dropdown-item"
|
||||
>
|
||||
{{ $t('about.title') }}
|
||||
</router-link>
|
||||
<a @click="logout()" class="dropdown-item">
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
@click="logout()"
|
||||
class="dropdown-item"
|
||||
>
|
||||
{{ $t('user.auth.logout') }}
|
||||
</a>
|
||||
</BaseButton>
|
||||
</dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
import {CURRENT_LIST, QUICK_ACTIONS_ACTIVE} from '@/store/mutation-types'
|
||||
<script setup langs="ts">
|
||||
import {ref, computed, onMounted, nextTick} from 'vue'
|
||||
import {useStore} from 'vuex'
|
||||
import {useRouter} from 'vue-router'
|
||||
|
||||
import {QUICK_ACTIONS_ACTIVE} from '@/store/mutation-types'
|
||||
import Rights from '@/models/constants/rights.json'
|
||||
|
||||
import Update from '@/components/home/update.vue'
|
||||
import ListSettingsDropdown from '@/components/list/list-settings-dropdown.vue'
|
||||
import Dropdown from '@/components/misc/dropdown.vue'
|
||||
import Notifications from '@/components/notifications/notifications.vue'
|
||||
import Logo from '@/components/home/Logo.vue'
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
import MenuButton from '@/components/home/MenuButton.vue'
|
||||
|
||||
export default {
|
||||
name: 'topNavigation',
|
||||
components: {
|
||||
Notifications,
|
||||
Dropdown,
|
||||
ListSettingsDropdown,
|
||||
Update,
|
||||
Logo,
|
||||
MenuButton,
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
userInfo: state => state.auth.info,
|
||||
userAvatar: state => state.auth.avatarUrl,
|
||||
userAuthenticated: state => state.auth.authenticated,
|
||||
currentList: CURRENT_LIST,
|
||||
background: 'background',
|
||||
imprintUrl: state => state.config.legal.imprintUrl,
|
||||
privacyPolicyUrl: state => state.config.legal.privacyPolicyUrl,
|
||||
canWriteCurrentList: state => state.currentList.maxRight > Rights.READ,
|
||||
}),
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
if (typeof this.$refs.usernameDropdown === 'undefined' || typeof this.$refs.listTitle === 'undefined') {
|
||||
return
|
||||
}
|
||||
const store = useStore()
|
||||
|
||||
const usernameWidth = this.$refs.usernameDropdown.$el.clientWidth
|
||||
this.$refs.listTitle.style.setProperty('--nav-username-width', `${usernameWidth}px`)
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
logout() {
|
||||
this.$store.dispatch('auth/logout')
|
||||
this.$router.push({name: 'user.login'})
|
||||
},
|
||||
openQuickActions() {
|
||||
this.$store.commit(QUICK_ACTIONS_ACTIVE, true)
|
||||
},
|
||||
},
|
||||
const userInfo = computed(() => store.state.auth.info)
|
||||
const userAvatar = computed(() => store.state.auth.avatarUrl)
|
||||
const currentList = computed(() => store.state.currentList)
|
||||
const background = computed(() => store.state.background)
|
||||
const imprintUrl = computed(() => store.state.config.legal.imprintUrl)
|
||||
const privacyPolicyUrl = computed(() => store.state.config.legal.privacyPolicyUrl)
|
||||
const canWriteCurrentList = computed(() => store.state.currentList.maxRight > Rights.READ)
|
||||
|
||||
const usernameDropdown = ref()
|
||||
const listTitle = ref()
|
||||
onMounted(async () => {
|
||||
await nextTick()
|
||||
if (typeof usernameDropdown.value === 'undefined' || typeof listTitle.value === 'undefined') {
|
||||
return
|
||||
}
|
||||
|
||||
const usernameWidth = usernameDropdown.value.$el.clientWidth
|
||||
listTitle.value.style.setProperty('--nav-username-width', `${usernameWidth}px`)
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
function logout() {
|
||||
store.dispatch('auth/logout')
|
||||
router.push({name: 'user.login'})
|
||||
}
|
||||
|
||||
function openQuickActions() {
|
||||
store.commit(QUICK_ACTIONS_ACTIVE, true)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -246,6 +251,7 @@ $hamburger-menu-icon-width: 28px;
|
|||
border-radius: 100%;
|
||||
vertical-align: middle;
|
||||
height: 40px;
|
||||
margin-right: var(--button-padding-horizontal);
|
||||
}
|
||||
|
||||
:deep(.dropdown-trigger .button) {
|
|
@ -66,7 +66,7 @@ const showIconOnly = computed(() => props.icon !== '' && typeof slots.default ==
|
|||
text-transform: uppercase;
|
||||
font-size: 0.85rem;
|
||||
font-weight: bold;
|
||||
height: $button-height;
|
||||
min-height: $button-height;
|
||||
box-shadow: var(--shadow-sm);
|
||||
display: inline-flex;
|
||||
|
||||
|
|
|
@ -39,79 +39,66 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Message from '@/components/misc/message'
|
||||
<script setup lang="ts">
|
||||
import {ref, computed, watch} from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import {parseURL} from 'ufo'
|
||||
|
||||
import {checkAndSetApiUrl} from '@/helpers/checkAndSetApiUrl'
|
||||
import {success} from '@/message'
|
||||
|
||||
export default {
|
||||
name: 'apiConfig',
|
||||
components: {
|
||||
Message,
|
||||
import Message from '@/components/misc/message.vue'
|
||||
|
||||
const props = defineProps({
|
||||
configureOpen: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
configureApi: false,
|
||||
apiUrl: window.API_URL,
|
||||
errorMsg: '',
|
||||
successMsg: '',
|
||||
})
|
||||
const emit = defineEmits(['foundApi'])
|
||||
|
||||
const apiUrl = ref(window.API_URL)
|
||||
const configureApi = ref(apiUrl.value === '')
|
||||
|
||||
const apiDomain = computed(() => parseURL(apiUrl.value).host || parseURL(window.location.href).host)
|
||||
|
||||
|
||||
watch(() => props.configureOpen, (value) => {
|
||||
configureApi.value = value
|
||||
}, { immediate: true })
|
||||
|
||||
|
||||
const {t} = useI18n()
|
||||
|
||||
const errorMsg = ref('')
|
||||
const successMsg = ref('')
|
||||
async function setApiUrl() {
|
||||
if (apiUrl.value === '') {
|
||||
// Don't try to check and set an empty url
|
||||
errorMsg.value = t('apiConfig.urlRequired')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const url = await checkAndSetApiUrl(apiUrl.value)
|
||||
|
||||
if (url === '') {
|
||||
// If the config setter function could not figure out a url
|
||||
throw new Error('URL cannot be empty.')
|
||||
}
|
||||
},
|
||||
emits: ['foundApi'],
|
||||
created() {
|
||||
if (this.apiUrl === '') {
|
||||
this.configureApi = true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
apiDomain() {
|
||||
return parseURL(this.apiUrl).host || parseURL(window.location.href).host
|
||||
},
|
||||
},
|
||||
props: {
|
||||
configureOpen: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
configureOpen: {
|
||||
handler(value) {
|
||||
this.configureApi = value
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async setApiUrl() {
|
||||
if (this.apiUrl === '') {
|
||||
// Don't try to check and set an empty url
|
||||
this.errorMsg = this.$t('apiConfig.urlRequired')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const url = await checkAndSetApiUrl(this.apiUrl)
|
||||
|
||||
if (url === '') {
|
||||
// If the config setter function could not figure out a url
|
||||
throw new Error('URL cannot be empty.')
|
||||
}
|
||||
|
||||
// Set it + save it to local storage to save us the hoops
|
||||
this.errorMsg = ''
|
||||
this.$message.success({message: this.$t('apiConfig.success', {domain: this.apiDomain})})
|
||||
this.configureApi = false
|
||||
this.apiUrl = url
|
||||
this.$emit('foundApi', this.apiUrl)
|
||||
} catch (e) {
|
||||
// Still not found, url is still invalid
|
||||
this.successMsg = ''
|
||||
this.errorMsg = this.$t('apiConfig.error', {domain: this.apiDomain})
|
||||
}
|
||||
},
|
||||
},
|
||||
// Set it + save it to local storage to save us the hoops
|
||||
errorMsg.value = ''
|
||||
apiUrl.value = url
|
||||
success({message: t('apiConfig.success', {domain: apiDomain.value})})
|
||||
configureApi.value = false
|
||||
emit('foundApi', apiUrl.value)
|
||||
} catch (e) {
|
||||
// Still not found, url is still invalid
|
||||
successMsg.value = ''
|
||||
errorMsg.value = t('apiConfig.error', {domain: apiDomain.value})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
}"
|
||||
>
|
||||
<BaseButton
|
||||
@click="emit('close')"
|
||||
@click="$emit('close')"
|
||||
class="close"
|
||||
>
|
||||
<icon icon="times"/>
|
||||
|
|
|
@ -138,7 +138,6 @@ $task-background: var(--white);
|
|||
border: 3px solid transparent;
|
||||
|
||||
font-size: .9rem;
|
||||
margin: .5rem;
|
||||
padding: .4rem;
|
||||
border-radius: $radius;
|
||||
background: $task-background;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { createI18n } from 'vue-i18n'
|
||||
import {createI18n} from 'vue-i18n'
|
||||
import langEN from './lang/en.json'
|
||||
|
||||
export const i18n = createI18n({
|
||||
|
@ -19,6 +19,9 @@ export const availableLanguages = {
|
|||
'vi-VN': 'Tiếng Việt',
|
||||
'it-IT': 'Italiano',
|
||||
'cs-CZ': 'Čeština',
|
||||
'pl-PL': 'Polski',
|
||||
'nl-NL': 'Nederlands',
|
||||
'pt-PT': 'Português',
|
||||
}
|
||||
|
||||
const loadedLanguages = ['en'] // our default language that is preloaded
|
||||
|
@ -30,10 +33,10 @@ const setI18nLanguage = lang => {
|
|||
}
|
||||
|
||||
export const loadLanguageAsync = lang => {
|
||||
if(!lang) {
|
||||
return
|
||||
if (!lang) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
// If the same language
|
||||
i18n.global.locale === lang ||
|
||||
|
|
|
@ -31,10 +31,9 @@
|
|||
"username": "Uživatelské jméno",
|
||||
"usernameEmail": "Uživatelské jméno nebo e-mail",
|
||||
"usernamePlaceholder": "např. Jarmil",
|
||||
"email": "E-mailová adresa",
|
||||
"email": "Email address",
|
||||
"emailPlaceholder": "např. jarmil{'@'}vikunja.io",
|
||||
"password": "Heslo",
|
||||
"passwordRepeat": "Zopakovat heslo",
|
||||
"passwordPlaceholder": "např. • • • • • • • •",
|
||||
"forgotPassword": "Zapomenuté heslo?",
|
||||
"resetPassword": "Obnovit heslo",
|
||||
|
@ -45,12 +44,20 @@
|
|||
"totpTitle": "Kód dvoufaktorového ověření",
|
||||
"totpPlaceholder": "např. 123456",
|
||||
"login": "Přihlásit se",
|
||||
"register": "Registrovat",
|
||||
"createAccount": "Create account",
|
||||
"loginWith": "Přihlásit se pomocí {provider}",
|
||||
"authenticating": "Ověřování…",
|
||||
"openIdStateError": "Stav neodpovídá, odmítám pokračovat!",
|
||||
"openIdGeneralError": "Došlo k chybě při ověřování proti třetí straně.",
|
||||
"logout": "Odhlásit se"
|
||||
"logout": "Odhlásit se",
|
||||
"emailInvalid": "Please enter a valid email address.",
|
||||
"usernameRequired": "Please provide a username.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
"alreadyHaveAnAccount": "Already have an account?",
|
||||
"remember": "Stay logged in"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Nastavení",
|
||||
|
@ -61,7 +68,7 @@
|
|||
"currentPasswordPlaceholder": "Vaše současné heslo",
|
||||
"passwordsDontMatch": "Nové heslo se neshoduje s potvrzením hesla.",
|
||||
"passwordUpdateSuccess": "Heslo bylo úspěšně změněno.",
|
||||
"updateEmailTitle": "Aktualizovat Vaši e-mailovou adresu",
|
||||
"updateEmailTitle": "Update Your Email Address",
|
||||
"updateEmailNew": "Nová e-mailová adresa",
|
||||
"updateEmailSuccess": "Vaše e-mailová adresa byla úspěšně aktualizována. Poslali jsme vám odkaz pro její potvrzení.",
|
||||
"general": {
|
||||
|
@ -78,7 +85,8 @@
|
|||
"weekStartSunday": "Neděle",
|
||||
"weekStartMonday": "Pondělí",
|
||||
"language": "Jazyk",
|
||||
"defaultList": "Výchozí seznam"
|
||||
"defaultList": "Výchozí seznam",
|
||||
"timezone": "Time Zone"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Dvoufaktorové ověření",
|
||||
|
@ -327,6 +335,7 @@
|
|||
"archiveText": "Nebudete moci upravovat tento jmenný prostor ani vytvářet nové seznamy, dokud jej neodarchivujete. Všechny seznamy v tomto prostoru budou také archivovány.",
|
||||
"unarchiveText": "Budete moci vytvářet nové úkoly nebo je upravovat.",
|
||||
"success": "Prostor byl úspěšně archivován.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "Pokud je prostor archivován, nelze vytvořit nové seznamy nebo je upravit."
|
||||
},
|
||||
"delete": {
|
||||
|
|
|
@ -31,10 +31,9 @@
|
|||
"username": "Anmeldename",
|
||||
"usernameEmail": "Anmeldename oder E-Mail-Adresse",
|
||||
"usernamePlaceholder": "z.B. frederick",
|
||||
"email": "Email address",
|
||||
"email": "E-Mail-Adresse",
|
||||
"emailPlaceholder": "z.B. frederic{'@'}vikunja.io",
|
||||
"password": "Passwort",
|
||||
"passwordRepeat": "Gib dein Passwort erneut ein",
|
||||
"passwordPlaceholder": "z.B. •••••••••••",
|
||||
"forgotPassword": "Passwort vergessen?",
|
||||
"resetPassword": "Setze dein Passwort zurück",
|
||||
|
@ -45,12 +44,20 @@
|
|||
"totpTitle": "Zwei-Faktor-Authentifizierungscode",
|
||||
"totpPlaceholder": "z.B. 123456",
|
||||
"login": "Anmelden",
|
||||
"register": "Registrieren",
|
||||
"createAccount": "Account erstellen",
|
||||
"loginWith": "Mit {provider} anmelden",
|
||||
"authenticating": "Authentifizierung…",
|
||||
"openIdStateError": "Zustand stimmt nicht überein, fahre nicht fort!",
|
||||
"openIdGeneralError": "Es ist ein Fehler bei der externen Authentisierung aufgetreten.",
|
||||
"logout": "Abmelden"
|
||||
"logout": "Abmelden",
|
||||
"emailInvalid": "Bitte gib eine gültige E-Mail-Adresse ein.",
|
||||
"usernameRequired": "Bitte gib einen Anmeldenamen ein.",
|
||||
"passwordRequired": "Bitte gib ein Passwort ein.",
|
||||
"showPassword": "Passwort anzeigen",
|
||||
"hidePassword": "Passwort verbergen",
|
||||
"noAccountYet": "Noch kein Account?",
|
||||
"alreadyHaveAnAccount": "Hast du bereits einen Account?",
|
||||
"remember": "Stay logged in"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Einstellungen",
|
||||
|
@ -78,7 +85,8 @@
|
|||
"weekStartSunday": "Sonntag",
|
||||
"weekStartMonday": "Montag",
|
||||
"language": "Sprache",
|
||||
"defaultList": "Standard-Liste"
|
||||
"defaultList": "Standard-Liste",
|
||||
"timezone": "Time Zone"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Zwei-Faktor-Authentifizierung",
|
||||
|
@ -327,6 +335,7 @@
|
|||
"archiveText": "Du kannst diesen Namespace nicht mehr bearbeiten oder neue Listen erstellen, bis du die Archivierung rückgängig machst. Das gilt auch für alle Listen in diesem Namespace.",
|
||||
"unarchiveText": "Du kannst neue Aufgaben erstellen oder diese bearbeiten.",
|
||||
"success": "Der Namespace wurde erfolgreich archiviert.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "In einem archivierten Namespace können Listen weder angelegt noch editiert werden."
|
||||
},
|
||||
"delete": {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"username": "Benutzernamä",
|
||||
"usernameEmail": "Benutzernamä oder E-Mail Adrässe",
|
||||
"usernamePlaceholder": "z.B. Hansruedi",
|
||||
"email": "Email address",
|
||||
"email": "E-Mail-Adresse",
|
||||
"emailPlaceholder": "z.B. frederic{'@'}vikunja.io",
|
||||
"password": "Passwort",
|
||||
"passwordPlaceholder": "z.B. •••••••••••",
|
||||
|
@ -44,19 +44,20 @@
|
|||
"totpTitle": "Zweifaktor Authentifizierigs Ziffere",
|
||||
"totpPlaceholder": "z.B. 123456",
|
||||
"login": "Iihlogge",
|
||||
"createAccount": "Create account",
|
||||
"createAccount": "Account erstellen",
|
||||
"loginWith": "Iihlogge mit {provider}",
|
||||
"authenticating": "Authentifiziere…",
|
||||
"openIdStateError": "Status stimmt nid überiih, ich verweigerä wiiter zmache!",
|
||||
"openIdGeneralError": "Es ist ein Fehler bei der externen Authentisierung aufgetreten.",
|
||||
"logout": "Uuslogge",
|
||||
"emailInvalid": "Please enter a valid email address.",
|
||||
"usernameRequired": "Please provide a username.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
"alreadyHaveAnAccount": "Already have an account?"
|
||||
"emailInvalid": "Bitte gib eine gültige E-Mail-Adresse ein.",
|
||||
"usernameRequired": "Bitte gib einen Anmeldenamen ein.",
|
||||
"passwordRequired": "Bitte gib ein Passwort ein.",
|
||||
"showPassword": "Passwort anzeigen",
|
||||
"hidePassword": "Passwort verbergen",
|
||||
"noAccountYet": "Noch kein Account?",
|
||||
"alreadyHaveAnAccount": "Hast du bereits einen Account?",
|
||||
"remember": "Stay logged in"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Iihstellige",
|
||||
|
@ -67,7 +68,7 @@
|
|||
"currentPasswordPlaceholder": "Diis jetzige Passwort",
|
||||
"passwordsDontMatch": "Dis neue Passwort und siini Bestätigung stimmed nid überiih.",
|
||||
"passwordUpdateSuccess": "Dis Passwort isch erfolgriich aktualisiert wordä.",
|
||||
"updateEmailTitle": "Update Your Email Address",
|
||||
"updateEmailTitle": "Aktualisiere deine E-Mail-Adresse",
|
||||
"updateEmailNew": "Neui E-Mail Adrässä",
|
||||
"updateEmailSuccess": "Dini E-Mail Adrässä isch erfolgriich gänderet worde. Mir hend dir en Link gschickt, um si zu bestätigä.",
|
||||
"general": {
|
||||
|
@ -84,7 +85,8 @@
|
|||
"weekStartSunday": "Sunntig",
|
||||
"weekStartMonday": "Määntig",
|
||||
"language": "Sproch",
|
||||
"defaultList": "Standard Liste"
|
||||
"defaultList": "Standard Liste",
|
||||
"timezone": "Time Zone"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Zweifaktor Authentifizierig",
|
||||
|
@ -101,9 +103,9 @@
|
|||
"disableSuccess": "Zweifaktor Authentifizierig isch erfolgriich uusgschalte wore."
|
||||
},
|
||||
"caldav": {
|
||||
"title": "Caldav",
|
||||
"howTo": "Du chasch Vikunja zu Caldav Applikatione verbinde, um dini Uufgabe vo verschidene Gräät zgseh. Gib die Url i dim Client iih:",
|
||||
"more": "Meh Informatione über Caldav in Vikunja"
|
||||
"title": "CalDAV",
|
||||
"howTo": "Du chasch Vikunja zu CalDAV Applikatione verbinde, um dini Uufgabe vo verschidene Gräät zgseh. Gib die Url i dim Client iih:",
|
||||
"more": "Meh Informatione über CalDAV in Vikunja"
|
||||
},
|
||||
"avatar": {
|
||||
"title": "Herr Der Elemente",
|
||||
|
@ -333,6 +335,7 @@
|
|||
"archiveText": "Du hesch kei möglichkeit meh de Namensruum z'bearbeite oder neui Listene drin z'erstelle, bis du si wider ent-archiviert hesch. Das archiviert au grad alli Liste im Namensruum.",
|
||||
"unarchiveText": "Du chasch neui Liste erstelle oder bearbeite.",
|
||||
"success": "De Namensruum isch erfolgriich archiviert worde.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "Wenn en Namensruum archiviert isch, chasch du kei neui Liste erstelle oder die bearbeite."
|
||||
},
|
||||
"delete": {
|
||||
|
|
|
@ -335,6 +335,7 @@
|
|||
"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.",
|
||||
"success": "The namespace was successfully archived.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "If a namespace is archived, you cannot create new lists or edit it."
|
||||
},
|
||||
"delete": {
|
||||
|
|
|
@ -56,7 +56,8 @@
|
|||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
"alreadyHaveAnAccount": "Already have an account?"
|
||||
"alreadyHaveAnAccount": "Already have an account?",
|
||||
"remember": "Stay logged in"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
|
@ -84,7 +85,8 @@
|
|||
"weekStartSunday": "Sunday",
|
||||
"weekStartMonday": "Monday",
|
||||
"language": "Language",
|
||||
"defaultList": "Default List"
|
||||
"defaultList": "Default List",
|
||||
"timezone": "Time Zone"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Two Factor Authentication",
|
||||
|
@ -333,6 +335,7 @@
|
|||
"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.",
|
||||
"success": "The namespace was successfully archived.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "If a namespace is archived, you cannot create new lists or edit it."
|
||||
},
|
||||
"delete": {
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
"email": "Email address",
|
||||
"emailPlaceholder": "p. ex. frederic{'@'}vikunja.io",
|
||||
"password": "Mot de passe",
|
||||
"passwordRepeat": "Retape ton mot de passe",
|
||||
"passwordPlaceholder": "p. ex. •••••••••••",
|
||||
"forgotPassword": "Forgot your password?",
|
||||
"resetPassword": "Réinitialiser ton mot de passe",
|
||||
|
@ -45,12 +44,20 @@
|
|||
"totpTitle": "Code d’authentification à deux facteurs",
|
||||
"totpPlaceholder": "p. ex. 123456",
|
||||
"login": "Se connecter",
|
||||
"register": "S’inscrire",
|
||||
"createAccount": "Create account",
|
||||
"loginWith": "Se connecter avec {provider}",
|
||||
"authenticating": "Authentification…",
|
||||
"openIdStateError": "L’état ne correspond pas, impossible de continuer !",
|
||||
"openIdGeneralError": "Une erreur s'est produite lors de l'authentification contre un tiers.",
|
||||
"logout": "Se déconnecter"
|
||||
"logout": "Se déconnecter",
|
||||
"emailInvalid": "Please enter a valid email address.",
|
||||
"usernameRequired": "Please provide a username.",
|
||||
"passwordRequired": "Please provide a password.",
|
||||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
"alreadyHaveAnAccount": "Already have an account?",
|
||||
"remember": "Stay logged in"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Paramètres",
|
||||
|
@ -61,7 +68,7 @@
|
|||
"currentPasswordPlaceholder": "Ton mot de passe actuel",
|
||||
"passwordsDontMatch": "Le nouveau mot de passe et sa confirmation ne correspondent pas.",
|
||||
"passwordUpdateSuccess": "Mot de passe mis à jour.",
|
||||
"updateEmailTitle": "Mets à jour ton adresse électronique",
|
||||
"updateEmailTitle": "Update Your Email Address",
|
||||
"updateEmailNew": "Nouvelle adresse courriel",
|
||||
"updateEmailSuccess": "Mise à jour de l’adresse électronique. Clique sur le lien dans le courriel qui t’a été envoyé pour le confirmer.",
|
||||
"general": {
|
||||
|
@ -78,7 +85,8 @@
|
|||
"weekStartSunday": "dimanche",
|
||||
"weekStartMonday": "lundi",
|
||||
"language": "Langue",
|
||||
"defaultList": "Liste par défaut"
|
||||
"defaultList": "Liste par défaut",
|
||||
"timezone": "Time Zone"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Authentification à deux facteurs",
|
||||
|
@ -327,6 +335,7 @@
|
|||
"archiveText": "Tu ne pourras pas modifier cet espace de noms ou créer de nouvelles listes tant que tu ne l’auras pas désarchivé. Ceci archivera également toutes les listes de cet espace de noms.",
|
||||
"unarchiveText": "Tu pourras créer de nouvelles listes ou les modifier.",
|
||||
"success": "Espace de noms archivé.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "L’archivage d’un espace de noms signifie qu’on ne peut pas créer de nouvelles listes dans cet espace, ni le modifier."
|
||||
},
|
||||
"delete": {
|
||||
|
|
|
@ -31,10 +31,9 @@
|
|||
"username": "Nome utente",
|
||||
"usernameEmail": "Nome utente o indirizzo e-mail",
|
||||
"usernamePlaceholder": "es. frederick",
|
||||
"email": "Email address",
|
||||
"email": "Indirizzo e-mail",
|
||||
"emailPlaceholder": "per es. frederic{'@'}vikunja.io",
|
||||
"password": "Password",
|
||||
"passwordRepeat": "Digita di nuovo la tua password",
|
||||
"passwordPlaceholder": "es. ••••••••••••",
|
||||
"forgotPassword": "Password dimenticata?",
|
||||
"resetPassword": "Reimposta la tua password",
|
||||
|
@ -45,12 +44,20 @@
|
|||
"totpTitle": "Codice di autenticazione a due fattori",
|
||||
"totpPlaceholder": "es. 123456",
|
||||
"login": "Accedi",
|
||||
"register": "Registrati",
|
||||
"createAccount": "Crea account",
|
||||
"loginWith": "Accedi con {provider}",
|
||||
"authenticating": "Autenticazione…",
|
||||
"openIdStateError": "Stato non corrispondente, impossibile continuare!",
|
||||
"openIdGeneralError": "Si è verificato un errore durante l'autenticazione con terze parti.",
|
||||
"logout": "Esci"
|
||||
"logout": "Esci",
|
||||
"emailInvalid": "Inserisci un indirizzo e-mail valido.",
|
||||
"usernameRequired": "Inserisci un nome utente.",
|
||||
"passwordRequired": "Inserisci una password.",
|
||||
"showPassword": "Mostra la password",
|
||||
"hidePassword": "Nascondi la password",
|
||||
"noAccountYet": "Non hai un account?",
|
||||
"alreadyHaveAnAccount": "Hai già un account?",
|
||||
"remember": "Resta connesso"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Impostazioni",
|
||||
|
@ -61,7 +68,7 @@
|
|||
"currentPasswordPlaceholder": "La tua password attuale",
|
||||
"passwordsDontMatch": "La nuova password e la conferma non coincidono.",
|
||||
"passwordUpdateSuccess": "Password aggiornata con successo.",
|
||||
"updateEmailTitle": "Inserisci il tuo indirizzo e-mail",
|
||||
"updateEmailTitle": "Aggiorna l'indirizzo e-mail",
|
||||
"updateEmailNew": "Nuovo indirizzo e-mail",
|
||||
"updateEmailSuccess": "Il tuo indirizzo e-mail è stato aggiornato correttamente. Ti abbiamo inviato un collegamento per confermarlo.",
|
||||
"general": {
|
||||
|
@ -78,7 +85,8 @@
|
|||
"weekStartSunday": "Domenica",
|
||||
"weekStartMonday": "Lunedì",
|
||||
"language": "Lingua",
|
||||
"defaultList": "Lista predefinita"
|
||||
"defaultList": "Lista predefinita",
|
||||
"timezone": "Fuso Orario"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Autenticazione a due fattori",
|
||||
|
@ -95,9 +103,9 @@
|
|||
"disableSuccess": "L'autenticazione a due fattori è stata disattivata."
|
||||
},
|
||||
"caldav": {
|
||||
"title": "CalDav",
|
||||
"title": "CalDAV",
|
||||
"howTo": "Puoi connettere Vikunja ai client caldav per visualizzare e gestire tutte le attività da diversi client. Inserisci questo URL nel tuo client:",
|
||||
"more": "Ulteriori informazioni su caldav in Vikunja"
|
||||
"more": "Ulteriori informazioni su CalDAV in Vikunja"
|
||||
},
|
||||
"avatar": {
|
||||
"title": "Avatar",
|
||||
|
@ -327,6 +335,7 @@
|
|||
"archiveText": "Non sarà possibile modificare questo namespace o creare nuove liste fino a quando non verrà disarchiviato. Questo archivierà anche tutte le liste in questo namespace.",
|
||||
"unarchiveText": "Potrai creare nuove liste o modificarle.",
|
||||
"success": "Namespace creato.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "Se un namespace è archiviato, non è possibile creare nuove liste o modificarlo."
|
||||
},
|
||||
"delete": {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -56,7 +56,8 @@
|
|||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
"alreadyHaveAnAccount": "Already have an account?"
|
||||
"alreadyHaveAnAccount": "Already have an account?",
|
||||
"remember": "Stay logged in"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
|
@ -84,7 +85,8 @@
|
|||
"weekStartSunday": "Sunday",
|
||||
"weekStartMonday": "Monday",
|
||||
"language": "Language",
|
||||
"defaultList": "Default List"
|
||||
"defaultList": "Default List",
|
||||
"timezone": "Time Zone"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Two Factor Authentication",
|
||||
|
@ -333,6 +335,7 @@
|
|||
"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.",
|
||||
"success": "The namespace was successfully archived.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "If a namespace is archived, you cannot create new lists or edit it."
|
||||
},
|
||||
"delete": {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -56,7 +56,8 @@
|
|||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
"alreadyHaveAnAccount": "Already have an account?"
|
||||
"alreadyHaveAnAccount": "Already have an account?",
|
||||
"remember": "Stay logged in"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
|
@ -84,7 +85,8 @@
|
|||
"weekStartSunday": "Sunday",
|
||||
"weekStartMonday": "Monday",
|
||||
"language": "Language",
|
||||
"defaultList": "Default List"
|
||||
"defaultList": "Default List",
|
||||
"timezone": "Time Zone"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Two Factor Authentication",
|
||||
|
@ -333,6 +335,7 @@
|
|||
"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.",
|
||||
"success": "The namespace was successfully archived.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "If a namespace is archived, you cannot create new lists or edit it."
|
||||
},
|
||||
"delete": {
|
||||
|
|
|
@ -56,7 +56,8 @@
|
|||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
"alreadyHaveAnAccount": "Already have an account?"
|
||||
"alreadyHaveAnAccount": "Already have an account?",
|
||||
"remember": "Stay logged in"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Настройки",
|
||||
|
@ -84,7 +85,8 @@
|
|||
"weekStartSunday": "Воскресенье",
|
||||
"weekStartMonday": "Понедельник",
|
||||
"language": "Язык",
|
||||
"defaultList": "Список по умолчанию"
|
||||
"defaultList": "Список по умолчанию",
|
||||
"timezone": "Time Zone"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Двухфакторная аутентификация",
|
||||
|
@ -103,7 +105,7 @@
|
|||
"caldav": {
|
||||
"title": "CalDAV",
|
||||
"howTo": "Ты можешь подключить Vikunja к клиентам CalDAV, чтобы просматривать и управлять всеми задачами из разных клиентов. Введи этот URL в свой клиент:",
|
||||
"more": "Подробнее о caldav в Vikunja"
|
||||
"more": "Подробнее о CalDAV в Vikunja"
|
||||
},
|
||||
"avatar": {
|
||||
"title": "Аватар",
|
||||
|
@ -333,6 +335,7 @@
|
|||
"archiveText": "Ты не сможешь изменять это пространство имён, пока не вернёшь его из архива. Это также касается всех списков в этом пространстве имён.",
|
||||
"unarchiveText": "Ты сможешь создавать новые списки или изменять их.",
|
||||
"success": "Пространство имён архивировано.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "Архивирование пространства имён означает, что ты не сможешь создавать в нём новые списки или изменять их."
|
||||
},
|
||||
"delete": {
|
||||
|
|
|
@ -56,7 +56,8 @@
|
|||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
"alreadyHaveAnAccount": "Already have an account?"
|
||||
"alreadyHaveAnAccount": "Already have an account?",
|
||||
"remember": "Stay logged in"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
|
@ -84,7 +85,8 @@
|
|||
"weekStartSunday": "Sunday",
|
||||
"weekStartMonday": "Monday",
|
||||
"language": "Language",
|
||||
"defaultList": "Default List"
|
||||
"defaultList": "Default List",
|
||||
"timezone": "Time Zone"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Two Factor Authentication",
|
||||
|
@ -333,6 +335,7 @@
|
|||
"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.",
|
||||
"success": "The namespace was successfully archived.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "If a namespace is archived, you cannot create new lists or edit it."
|
||||
},
|
||||
"delete": {
|
||||
|
|
|
@ -56,7 +56,8 @@
|
|||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
"alreadyHaveAnAccount": "Already have an account?"
|
||||
"alreadyHaveAnAccount": "Already have an account?",
|
||||
"remember": "Stay logged in"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
|
@ -84,7 +85,8 @@
|
|||
"weekStartSunday": "Sunday",
|
||||
"weekStartMonday": "Monday",
|
||||
"language": "Language",
|
||||
"defaultList": "Default List"
|
||||
"defaultList": "Default List",
|
||||
"timezone": "Time Zone"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Two Factor Authentication",
|
||||
|
@ -333,6 +335,7 @@
|
|||
"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.",
|
||||
"success": "The namespace was successfully archived.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "If a namespace is archived, you cannot create new lists or edit it."
|
||||
},
|
||||
"delete": {
|
||||
|
|
|
@ -56,7 +56,8 @@
|
|||
"showPassword": "Show the password",
|
||||
"hidePassword": "Hide the password",
|
||||
"noAccountYet": "Don't have an account yet?",
|
||||
"alreadyHaveAnAccount": "Already have an account?"
|
||||
"alreadyHaveAnAccount": "Already have an account?",
|
||||
"remember": "Stay logged in"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Cài đặt",
|
||||
|
@ -84,7 +85,8 @@
|
|||
"weekStartSunday": "Chủ nhật",
|
||||
"weekStartMonday": "Thứ hai",
|
||||
"language": "Ngôn ngữ",
|
||||
"defaultList": "Danh sách mặc định"
|
||||
"defaultList": "Danh sách mặc định",
|
||||
"timezone": "Time Zone"
|
||||
},
|
||||
"totp": {
|
||||
"title": "Xác thực hai lớp",
|
||||
|
@ -101,7 +103,7 @@
|
|||
"disableSuccess": "Xác thực hai lớp đã bị vô hiệu hóa thành công."
|
||||
},
|
||||
"caldav": {
|
||||
"title": "Giao thức Caldav",
|
||||
"title": "Giao thức CalDAV",
|
||||
"howTo": "Bạn có thể kết nối Vikunja tới các máy khách CalDAV để xem và quản lý tất cả các công việc từ nhiều máy khách khác nhau. Nhập URL này vào ứng dụng khách của bạn:",
|
||||
"more": "Tìm hiểu thêm về CalDAV"
|
||||
},
|
||||
|
@ -333,6 +335,7 @@
|
|||
"archiveText": "Bạn sẽ không thể chỉnh sửa góc làm việc này hoặc tạo danh sách mới cho đến khi bạn bỏ lưu trữ nó. Điều này cũng sẽ lưu trữ tất cả các danh sách trong góc làm việc này.",
|
||||
"unarchiveText": "Bạn có thể tạo danh sách mới hoặc chỉnh sửa nó.",
|
||||
"success": "Góc làm việc đã lưu trữ thành công.",
|
||||
"unarchiveSuccess": "The namespace was successfully un-archived.",
|
||||
"description": "Nếu một góc làm việc được lưu trữ, bạn không thể tạo thêm danh sách hoặc chỉnh sửa nó."
|
||||
},
|
||||
"delete": {
|
||||
|
|
|
@ -44,35 +44,15 @@ export default {
|
|||
},
|
||||
mutations: {
|
||||
[CONFIG](state, config) {
|
||||
state.version = config.version
|
||||
state.frontendUrl = config.frontend_url
|
||||
state.motd = config.motd
|
||||
state.linkSharingEnabled = config.link_sharing_enabled
|
||||
state.maxFileSize = config.max_file_size
|
||||
state.registrationEnabled = config.registration_enabled
|
||||
state.availableMigrators = config.available_migrators
|
||||
state.taskAttachmentsEnabled = config.task_attachments_enabled
|
||||
state.totpEnabled = config.totp_enabled
|
||||
state.enabledBackgroundProviders = config.enabled_background_providers
|
||||
state.legal.imprintUrl = config.legal.imprint_url
|
||||
state.legal.privacyPolicyUrl = config.legal.privacy_policy_url
|
||||
state.caldavEnabled = config.caldav_enabled
|
||||
state.userDeletionEnabled = config.user_deletion_enabled
|
||||
state.taskCommentsEnabled = config.task_comments_enabled
|
||||
const auth = objectToCamelCase(config.auth)
|
||||
state.auth.local.enabled = auth.local.enabled
|
||||
state.auth.openidConnect.enabled = auth.openidConnect.enabled
|
||||
state.auth.openidConnect.redirectUrl = auth.openidConnect.redirectUrl
|
||||
state.auth.openidConnect.providers = auth.openidConnect.providers
|
||||
Object.assign(state, config)
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async update(ctx) {
|
||||
const HTTP = HTTPFactory()
|
||||
|
||||
const {data: info} = await HTTP.get('info')
|
||||
ctx.commit(CONFIG, info)
|
||||
return info
|
||||
const {data: config} = await HTTP.get('info')
|
||||
ctx.commit(CONFIG, objectToCamelCase(config))
|
||||
return config
|
||||
},
|
||||
},
|
||||
}
|
|
@ -2,12 +2,12 @@
|
|||
<ListWrapper class="list-kanban" :list-id="listId" viewName="kanban">
|
||||
<template #header>
|
||||
<div class="filter-container" v-if="isSavedFilter">
|
||||
<div class="items">
|
||||
<filter-popup
|
||||
v-model="params"
|
||||
@update:modelValue="loadBuckets"
|
||||
/>
|
||||
</div>
|
||||
<div class="items">
|
||||
<filter-popup
|
||||
v-model="params"
|
||||
@update:modelValue="loadBuckets"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -123,61 +123,59 @@
|
|||
</a>
|
||||
</dropdown>
|
||||
</div>
|
||||
<div
|
||||
:ref="(el) => setTaskContainerRef(bucket.id, el)"
|
||||
@scroll="($event) => handleTaskContainerScroll(bucket.id, bucket.listId, $event.target)"
|
||||
class="tasks"
|
||||
|
||||
<draggable
|
||||
v-bind="dragOptions"
|
||||
:modelValue="bucket.tasks"
|
||||
@update:modelValue="(tasks) => updateTasks(bucket.id, tasks)"
|
||||
@start="() => dragstart(bucket)"
|
||||
@end="updateTaskPosition"
|
||||
:group="{name: 'tasks', put: shouldAcceptDrop(bucket) && !dragBucket}"
|
||||
:disabled="!canWrite"
|
||||
:data-bucket-index="bucketIndex"
|
||||
tag="transition-group"
|
||||
:item-key="(task) => `bucket${bucket.id}-task${task.id}`"
|
||||
:component-data="getTaskDraggableTaskComponentData(bucket)"
|
||||
>
|
||||
<draggable
|
||||
v-bind="dragOptions"
|
||||
:modelValue="bucket.tasks"
|
||||
@update:modelValue="(tasks) => updateTasks(bucket.id, tasks)"
|
||||
@start="() => dragstart(bucket)"
|
||||
@end="updateTaskPosition"
|
||||
:group="{name: 'tasks', put: shouldAcceptDrop(bucket) && !dragBucket}"
|
||||
:disabled="!canWrite"
|
||||
:data-bucket-index="bucketIndex"
|
||||
tag="transition-group"
|
||||
:item-key="(task) => `bucket${bucket.id}-task${task.id}`"
|
||||
:component-data="taskDraggableTaskComponentData"
|
||||
>
|
||||
<template #item="{element: task}">
|
||||
<kanban-card :task="task"/>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
<div class="bucket-footer" v-if="canWrite">
|
||||
<div class="field" v-if="showNewTaskInput[bucket.id]">
|
||||
<div class="control" :class="{'is-loading': loading}">
|
||||
<input
|
||||
class="input"
|
||||
:disabled="loading || null"
|
||||
@focusout="toggleShowNewTaskInput(bucket.id)"
|
||||
@keyup.enter="addTaskToBucket(bucket.id)"
|
||||
@keyup.esc="toggleShowNewTaskInput(bucket.id)"
|
||||
:placeholder="$t('list.kanban.addTaskPlaceholder')"
|
||||
type="text"
|
||||
v-focus.always
|
||||
v-model="newTaskText"
|
||||
/>
|
||||
<template #footer>
|
||||
<div class="bucket-footer" v-if="canWrite">
|
||||
<div class="field" v-if="showNewTaskInput[bucket.id]">
|
||||
<div class="control" :class="{'is-loading': loading}">
|
||||
<input
|
||||
class="input"
|
||||
:disabled="loading || undefined"
|
||||
@focusout="toggleShowNewTaskInput(bucket.id)"
|
||||
@keyup.enter="addTaskToBucket(bucket.id)"
|
||||
@keyup.esc="toggleShowNewTaskInput(bucket.id)"
|
||||
:placeholder="$t('list.kanban.addTaskPlaceholder')"
|
||||
type="text"
|
||||
v-focus.always
|
||||
v-model="newTaskText"
|
||||
/>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="newTaskError[bucket.id] && newTaskText === ''">
|
||||
{{ $t('list.create.addTitleRequired') }}
|
||||
</p>
|
||||
</div>
|
||||
<x-button
|
||||
@click="toggleShowNewTaskInput(bucket.id)"
|
||||
class="is-fullwidth has-text-centered"
|
||||
:shadow="false"
|
||||
v-else
|
||||
icon="plus"
|
||||
variant="secondary"
|
||||
>
|
||||
{{ bucket.tasks.length === 0 ? $t('list.kanban.addTask') : $t('list.kanban.addAnotherTask') }}
|
||||
</x-button>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="newTaskError[bucket.id] && newTaskText === ''">
|
||||
{{ $t('list.create.addTitleRequired') }}
|
||||
</p>
|
||||
</div>
|
||||
<x-button
|
||||
@click="toggleShowNewTaskInput(bucket.id)"
|
||||
class="is-transparent is-fullwidth has-text-centered"
|
||||
:shadow="false"
|
||||
v-if="!showNewTaskInput[bucket.id]"
|
||||
icon="plus"
|
||||
variant="secondary"
|
||||
>
|
||||
{{
|
||||
bucket.tasks.length === 0 ? $t('list.kanban.addTask') : $t('list.kanban.addAnotherTask')
|
||||
}}
|
||||
</x-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #item="{element: task}">
|
||||
<div class="task-item">
|
||||
<kanban-card class="kanban-card" :task="task"/>
|
||||
</div>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
</template>
|
||||
</draggable>
|
||||
|
@ -197,10 +195,10 @@
|
|||
v-model="newBucketTitle"
|
||||
/>
|
||||
<x-button
|
||||
v-else
|
||||
@click="() => showNewBucketInput = true"
|
||||
:shadow="false"
|
||||
class="is-transparent is-fullwidth has-text-centered"
|
||||
v-else
|
||||
variant="secondary"
|
||||
icon="plus"
|
||||
>
|
||||
|
@ -313,6 +311,20 @@ export default {
|
|||
},
|
||||
},
|
||||
computed: {
|
||||
getTaskDraggableTaskComponentData() {
|
||||
return (bucket) => ({
|
||||
ref: (el) => this.setTaskContainerRef(bucket.id, el),
|
||||
onScroll: (event) => this.handleTaskContainerScroll(bucket.id, bucket.listId, event.target),
|
||||
type: 'transition',
|
||||
tag: 'div',
|
||||
name: !this.drag ? 'move-card' : null,
|
||||
class: [
|
||||
'tasks',
|
||||
{'dragging-disabled': !this.canWrite},
|
||||
],
|
||||
})
|
||||
},
|
||||
|
||||
isSavedFilter() {
|
||||
return this.list.isSavedFilter && !this.list.isSavedFilter()
|
||||
},
|
||||
|
@ -333,17 +345,6 @@ export default {
|
|||
],
|
||||
}
|
||||
},
|
||||
taskDraggableTaskComponentData() {
|
||||
return {
|
||||
type: 'transition',
|
||||
tag: 'div',
|
||||
name: !this.drag ? 'move-card' : null,
|
||||
class: [
|
||||
'dropper',
|
||||
{'dragging-disabled': !this.canWrite},
|
||||
],
|
||||
}
|
||||
},
|
||||
buckets() {
|
||||
return this.$store.state.kanban.buckets
|
||||
},
|
||||
|
@ -406,10 +407,25 @@ export default {
|
|||
// of the drop target works all the time.
|
||||
const bucketIndex = parseInt(e.to.dataset.bucketIndex)
|
||||
|
||||
|
||||
const newBucket = this.buckets[bucketIndex]
|
||||
const task = newBucket.tasks[e.newIndex]
|
||||
const taskBefore = newBucket.tasks[e.newIndex - 1] ?? null
|
||||
const taskAfter = newBucket.tasks[e.newIndex + 1] ?? null
|
||||
|
||||
// HACK:
|
||||
// this is a hacky workaround for a known problem of vue.draggable.next when using the footer slot
|
||||
// the problem: https://github.com/SortableJS/vue.draggable.next/issues/108
|
||||
// This hack doesn't remove the problem that the ghost item is still displayed below the footer
|
||||
// It just makes releasing the item possible.
|
||||
|
||||
// The newIndex of the event doesn't count in the elements of the footer slot.
|
||||
// This is why in case the length of the tasks is identical with the newIndex
|
||||
// we have to remove 1 to get the correct index.
|
||||
const newTaskIndex = newBucket.tasks.length === e.newIndex
|
||||
? e.newIndex - 1
|
||||
: e.newIndex
|
||||
|
||||
const task = newBucket.tasks[newTaskIndex]
|
||||
const taskBefore = newBucket.tasks[newTaskIndex - 1] ?? null
|
||||
const taskAfter = newBucket.tasks[newTaskIndex + 1] ?? null
|
||||
|
||||
const newTask = cloneDeep(task) // cloning the task to avoid vuex store mutations
|
||||
newTask.bucketId = newBucket.id,
|
||||
|
@ -525,7 +541,10 @@ export default {
|
|||
|
||||
const updatedData = {
|
||||
id: bucket.id,
|
||||
position: calculateItemPosition(bucketBefore !== null ? bucketBefore.position : null, bucketAfter !== null ? bucketAfter.position : null),
|
||||
position: calculateItemPosition(
|
||||
bucketBefore !== null ? bucketBefore.position : null,
|
||||
bucketAfter !== null ? bucketAfter.position : null,
|
||||
),
|
||||
}
|
||||
|
||||
this.$store.dispatch('kanban/updateBucket', updatedData)
|
||||
|
@ -546,9 +565,14 @@ export default {
|
|||
},
|
||||
|
||||
shouldAcceptDrop(bucket) {
|
||||
return bucket.id === this.sourceBucket || // When dragging from a bucket who has its limit reached, dragging should still be possible
|
||||
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
|
||||
return (
|
||||
// When dragging from a bucket who has its limit reached, dragging should still be possible
|
||||
bucket.id === this.sourceBucket ||
|
||||
// If there is no limit set, dragging & dropping should always work
|
||||
bucket.limit === 0 ||
|
||||
// Disallow dropping to buckets which have their limit reached
|
||||
bucket.tasks.length < bucket.limit
|
||||
)
|
||||
},
|
||||
|
||||
dragstart(bucket) {
|
||||
|
@ -597,7 +621,6 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
|||
}
|
||||
|
||||
.kanban {
|
||||
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
height: calc(#{$crazy-height-calculation});
|
||||
|
@ -610,21 +633,28 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
|||
|
||||
&-bucket-container {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.ghost {
|
||||
background: transparent !important;
|
||||
border: 3px dashed var(--grey-300) !important;
|
||||
box-shadow: none !important;
|
||||
position: relative;
|
||||
|
||||
* {
|
||||
opacity: 0;
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: 0.25rem;
|
||||
right: 0.5rem;
|
||||
bottom: 0.25rem;
|
||||
left: 0.5rem;
|
||||
border: 3px dashed var(--grey-300);
|
||||
border-radius: $radius;
|
||||
}
|
||||
}
|
||||
|
||||
.bucket {
|
||||
background-color: var(--grey-100);
|
||||
border-radius: $radius;
|
||||
position: relative;
|
||||
|
||||
|
@ -632,24 +662,24 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
|||
max-height: 100%;
|
||||
min-height: 20px;
|
||||
width: $bucket-width;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.tasks {
|
||||
max-height: calc(#{$crazy-height-calculation-tasks});
|
||||
overflow: auto;
|
||||
|
||||
@media screen and (max-width: $tablet) {
|
||||
max-height: calc(#{$crazy-height-calculation-tasks} - #{$filter-container-height});
|
||||
}
|
||||
|
||||
.dropper {
|
||||
&, > div {
|
||||
min-height: 40px;
|
||||
}
|
||||
}
|
||||
overflow: hidden auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.move-card-move {
|
||||
transition: transform $transition-duration;
|
||||
.task-item {
|
||||
background-color: var(--grey-100);
|
||||
padding: .25rem .5rem;
|
||||
|
||||
&:first-of-type {
|
||||
padding-top: .5rem;
|
||||
}
|
||||
&:last-of-type {
|
||||
padding-bottom: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.no-move {
|
||||
|
@ -682,10 +712,11 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
|||
}
|
||||
|
||||
&.is-collapsed {
|
||||
transform: rotate(90deg) translateX(math.div($bucket-width, 2) - math.div($bucket-header-height, 2));
|
||||
align-self: flex-start;
|
||||
transform: rotate(90deg) translateY(-100%);
|
||||
transform-origin: top left;
|
||||
// Using negative margins instead of translateY here to make all other buckets fill the empty space
|
||||
margin-left: (math.div($bucket-width, 2) - math.div($bucket-header-height, 2)) * -1;
|
||||
margin-right: calc(#{(math.div($bucket-width, 2) - math.div($bucket-header-height, 2)) * -1} + #{$bucket-right-margin});
|
||||
margin-right: calc((#{$bucket-width} - #{$bucket-header-height} - #{$bucket-right-margin}) * -1);
|
||||
cursor: pointer;
|
||||
|
||||
.tasks, .bucket-footer {
|
||||
|
@ -695,6 +726,8 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
|||
}
|
||||
|
||||
.bucket-header {
|
||||
background-color: var(--grey-100);
|
||||
height: min-content;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
@ -724,7 +757,13 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
|||
}
|
||||
|
||||
.bucket-footer {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
height: min-content;
|
||||
padding: .5rem;
|
||||
background-color: var(--grey-100);
|
||||
border-bottom-left-radius: $radius;
|
||||
border-bottom-right-radius: $radius;
|
||||
|
||||
.button {
|
||||
background-color: transparent;
|
||||
|
@ -737,8 +776,13 @@ $filter-container-height: '1rem - #{$switch-view-height}';
|
|||
}
|
||||
|
||||
.task-dragging {
|
||||
transform: rotateZ(3deg);
|
||||
transition: transform 0.18s ease;
|
||||
transform: rotateZ(3deg)
|
||||
}
|
||||
|
||||
.move-card-move {
|
||||
transform: rotateZ(3deg);
|
||||
transition: transform $transition-duration;
|
||||
}
|
||||
|
||||
.move-card-leave-from,
|
||||
|
|
|
@ -37,12 +37,13 @@ export default {
|
|||
methods: {
|
||||
async archiveNamespace() {
|
||||
try {
|
||||
const isArchived = !this.namespace.isArchived
|
||||
const namespace = await this.namespaceService.update({
|
||||
...this.namespace,
|
||||
isArchived: !this.namespace.isArchived,
|
||||
isArchived,
|
||||
})
|
||||
this.$store.commit('namespaces/setNamespaceById', namespace)
|
||||
this.$message.success({message: this.$t('namespace.archive.success')})
|
||||
this.$message.success({message: this.$t(isArchived ? 'namespace.archive.success' : 'namespace.archive.unarchiveSuccess')})
|
||||
} finally {
|
||||
this.$router.back()
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
"resolveJsonModule": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"strictNullChecks": true,
|
||||
"isolatedModules": true,
|
||||
"types": [
|
||||
"vite/client"
|
||||
|
|
Loading…
Reference in New Issue
Block a user