feat: save and restore the user language on the server (#1181)
Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/1181 Reviewed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de> Co-authored-by: konrad <k@knt.li> Co-committed-by: konrad <k@knt.li>
This commit is contained in:
parent
0befa58908
commit
4a7d2d8414
2 changed files with 67 additions and 39 deletions
|
@ -1,7 +1,12 @@
|
||||||
import {HTTPFactory} from '@/http-common'
|
import {HTTPFactory} from '@/http-common'
|
||||||
|
import {getCurrentLanguage, saveLanguage} from '@/i18n'
|
||||||
import {LOADING} from '../mutation-types'
|
import {LOADING} from '../mutation-types'
|
||||||
import UserModel from '../../models/user'
|
import UserModel from '@/models/user'
|
||||||
|
import UserSettingsService from '@/services/userSettings'
|
||||||
import {getToken, refreshToken, removeToken, saveToken} from '@/helpers/auth'
|
import {getToken, refreshToken, removeToken, saveToken} from '@/helpers/auth'
|
||||||
|
import {setLoading} from '@/store/helper'
|
||||||
|
import {i18n} from '@/i18n'
|
||||||
|
import {success} from '@/message'
|
||||||
|
|
||||||
const AUTH_TYPES = {
|
const AUTH_TYPES = {
|
||||||
'UNKNOWN': 0,
|
'UNKNOWN': 0,
|
||||||
|
@ -101,7 +106,7 @@ export default {
|
||||||
|
|
||||||
// Tell others the user is autheticated
|
// Tell others the user is autheticated
|
||||||
ctx.dispatch('checkAuth')
|
ctx.dispatch('checkAuth')
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
if (
|
if (
|
||||||
e.response &&
|
e.response &&
|
||||||
e.response.data.code === 1017 &&
|
e.response.data.code === 1017 &&
|
||||||
|
@ -124,7 +129,7 @@ export default {
|
||||||
try {
|
try {
|
||||||
await HTTP.post('register', credentials)
|
await HTTP.post('register', credentials)
|
||||||
return ctx.dispatch('login', credentials)
|
return ctx.dispatch('login', credentials)
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
if (e.response?.data?.message) {
|
if (e.response?.data?.message) {
|
||||||
throw e.response.data
|
throw e.response.data
|
||||||
}
|
}
|
||||||
|
@ -200,7 +205,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async refreshUserInfo(ctx) {
|
async refreshUserInfo({state, commit, dispatch}) {
|
||||||
const jwt = getToken()
|
const jwt = getToken()
|
||||||
if (!jwt) {
|
if (!jwt) {
|
||||||
return
|
return
|
||||||
|
@ -208,22 +213,53 @@ export default {
|
||||||
|
|
||||||
const HTTP = HTTPFactory()
|
const HTTP = HTTPFactory()
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const response = await HTTP.get('user', {
|
const response = await HTTP.get('user', {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${jwt}`,
|
Authorization: `Bearer ${jwt}`,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const info = new UserModel(response.data)
|
const info = new UserModel(response.data)
|
||||||
info.type = ctx.state.info.type
|
info.type = state.info.type
|
||||||
info.email = ctx.state.info.email
|
info.email = state.info.email
|
||||||
info.exp = ctx.state.info.exp
|
info.exp = state.info.exp
|
||||||
|
|
||||||
|
commit('info', info)
|
||||||
|
commit('lastUserRefresh')
|
||||||
|
|
||||||
|
if (typeof info.settings.language !== 'undefined') {
|
||||||
|
// save current language
|
||||||
|
await dispatch('saveUserSettings', {
|
||||||
|
settings: {
|
||||||
|
...state.settings,
|
||||||
|
language: getCurrentLanguage(),
|
||||||
|
},
|
||||||
|
showMessage: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
ctx.commit('info', info)
|
|
||||||
ctx.commit('lastUserRefresh')
|
|
||||||
return info
|
return info
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
throw new Error('Error while refreshing user info:', { cause: e })
|
throw new Error('Error while refreshing user info:', {cause: e})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async saveUserSettings(ctx, payload) {
|
||||||
|
const {settings} = payload
|
||||||
|
const showMessage = payload.showMessage ?? true
|
||||||
|
const userSettingsService = new UserSettingsService()
|
||||||
|
|
||||||
|
const cancel = setLoading(ctx, 'general-settings')
|
||||||
|
try {
|
||||||
|
saveLanguage(settings.language)
|
||||||
|
await userSettingsService.update(settings)
|
||||||
|
ctx.commit('setUserSettings', {...settings})
|
||||||
|
if (showMessage) {
|
||||||
|
success({message: i18n.global.t('user.settings.general.savedSuccess')})
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('Error while saving user settings:', {cause: e})
|
||||||
|
} finally {
|
||||||
|
cancel()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -240,7 +276,7 @@ export default {
|
||||||
try {
|
try {
|
||||||
await refreshToken(!ctx.state.isLinkShareAuth)
|
await refreshToken(!ctx.state.isLinkShareAuth)
|
||||||
ctx.dispatch('checkAuth')
|
ctx.dispatch('checkAuth')
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
// Don't logout on network errors as the user would then get logged out if they don't have
|
// Don't logout on network errors as the user would then get logged out if they don't have
|
||||||
// internet for a short period of time - such as when the laptop is still reconnecting
|
// internet for a short period of time - such as when the laptop is still reconnecting
|
||||||
if (e?.request?.status) {
|
if (e?.request?.status) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<card :title="$t('user.settings.general.title')" class="general-settings" :loading="userSettingsService.loading">
|
<card :title="$t('user.settings.general.title')" class="general-settings" :loading="loading">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label" :for="`newName${id}`">{{ $t('user.settings.general.name') }}</label>
|
<label class="label" :for="`newName${id}`">{{ $t('user.settings.general.name') }}</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
|
@ -67,8 +67,8 @@
|
||||||
{{ $t('user.settings.general.language') }}
|
{{ $t('user.settings.general.language') }}
|
||||||
</span>
|
</span>
|
||||||
<div class="select ml-2">
|
<div class="select ml-2">
|
||||||
<select v-model="language">
|
<select v-model="settings.language">
|
||||||
<option :value="lang.code" v-for="lang in availableLanguages" :key="lang.code">{{
|
<option :value="lang.code" v-for="lang in availableLanguageOptions" :key="lang.code">{{
|
||||||
lang.title
|
lang.title
|
||||||
}}
|
}}
|
||||||
</option>
|
</option>
|
||||||
|
@ -107,7 +107,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<x-button
|
<x-button
|
||||||
:loading="userSettingsService.loading"
|
:loading="loading"
|
||||||
@click="updateSettings()"
|
@click="updateSettings()"
|
||||||
class="is-fullwidth mt-4"
|
class="is-fullwidth mt-4"
|
||||||
>
|
>
|
||||||
|
@ -120,14 +120,12 @@
|
||||||
import {computed, watch} from 'vue'
|
import {computed, watch} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import {playSoundWhenDoneKey} from '@/helpers/playPop'
|
import {playSoundWhenDoneKey, playPop} from '@/helpers/playPop'
|
||||||
import {availableLanguages, saveLanguage, getCurrentLanguage} from '@/i18n'
|
import {availableLanguages} from '@/i18n'
|
||||||
import {getQuickAddMagicMode, setQuickAddMagicMode} from '@/helpers/quickAddMagicMode'
|
import {getQuickAddMagicMode, setQuickAddMagicMode} from '@/helpers/quickAddMagicMode'
|
||||||
import UserSettingsService from '@/services/userSettings'
|
|
||||||
import {PrefixMode} from '@/modules/parseTaskText'
|
import {PrefixMode} from '@/modules/parseTaskText'
|
||||||
import ListSearch from '@/components/tasks/partials/listSearch'
|
import ListSearch from '@/components/tasks/partials/listSearch'
|
||||||
import {createRandomID} from '@/helpers/randomId'
|
import {createRandomID} from '@/helpers/randomId'
|
||||||
import {playPop} from '@/helpers/playPop'
|
|
||||||
import {useColorScheme} from '@/composables/useColorScheme'
|
import {useColorScheme} from '@/composables/useColorScheme'
|
||||||
import {success} from '@/message'
|
import {success} from '@/message'
|
||||||
|
|
||||||
|
@ -165,23 +163,19 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
playSoundWhenDone: getPlaySoundWhenDoneSetting(),
|
playSoundWhenDone: getPlaySoundWhenDoneSetting(),
|
||||||
language: getCurrentLanguage(),
|
|
||||||
quickAddMagicMode: getQuickAddMagicMode(),
|
quickAddMagicMode: getQuickAddMagicMode(),
|
||||||
quickAddMagicPrefixes: PrefixMode,
|
quickAddMagicPrefixes: PrefixMode,
|
||||||
userSettingsService: new UserSettingsService(),
|
|
||||||
settings: {...this.$store.state.auth.settings},
|
settings: {...this.$store.state.auth.settings},
|
||||||
id: createRandomID(),
|
id: createRandomID(),
|
||||||
|
availableLanguageOptions: Object.entries(availableLanguages)
|
||||||
|
.map(l => ({code: l[0], title: l[1]}))
|
||||||
|
.sort((a, b) => a.title.localeCompare(b.title)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
ListSearch,
|
ListSearch,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
availableLanguages() {
|
|
||||||
return Object.entries(availableLanguages)
|
|
||||||
.map(l => ({code: l[0], title: l[1]}))
|
|
||||||
.sort((a, b) => a.title.localeCompare(b.title))
|
|
||||||
},
|
|
||||||
defaultList: {
|
defaultList: {
|
||||||
get() {
|
get() {
|
||||||
return this.$store.getters['lists/getListById'](this.settings.defaultListId)
|
return this.$store.getters['lists/getListById'](this.settings.defaultListId)
|
||||||
|
@ -190,6 +184,9 @@ export default {
|
||||||
this.settings.defaultListId = l ? l.id : DEFAULT_LIST_ID
|
this.settings.defaultListId = l ? l.id : DEFAULT_LIST_ID
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
loading() {
|
||||||
|
return this.$store.state.loading && this.$store.state.loadingModule === 'general-settings'
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
|
@ -211,16 +208,11 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
async updateSettings() {
|
async updateSettings() {
|
||||||
localStorage.setItem(playSoundWhenDoneKey, this.playSoundWhenDone)
|
localStorage.setItem(playSoundWhenDoneKey, this.playSoundWhenDone)
|
||||||
saveLanguage(this.language)
|
|
||||||
setQuickAddMagicMode(this.quickAddMagicMode)
|
setQuickAddMagicMode(this.quickAddMagicMode)
|
||||||
|
|
||||||
const settings = {
|
await this.$store.dispatch('auth/saveUserSettings', {
|
||||||
...this.settings,
|
settings: {...this.settings},
|
||||||
}
|
})
|
||||||
|
|
||||||
await this.userSettingsService.update(settings)
|
|
||||||
this.$store.commit('auth/setUserSettings', settings)
|
|
||||||
this.$message.success({message: this.$t('user.settings.general.savedSuccess')})
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue