feat: port config store to pinia
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Dominik Pschenitschni 2022-09-21 02:21:22 +02:00
parent 9e8c429864
commit a737fc5bc2
Signed by: dpschen
GPG Key ID: B257AC0149F43A77
21 changed files with 93 additions and 68 deletions

View File

@ -108,15 +108,17 @@ import BaseButton from '@/components/base/BaseButton.vue'
import MenuButton from '@/components/home/MenuButton.vue' import MenuButton from '@/components/home/MenuButton.vue'
import {getListTitle} from '@/helpers/getListTitle' import {getListTitle} from '@/helpers/getListTitle'
import {useConfigStore} from '@/stores/config'
const store = useStore() const store = useStore()
const configStore = useConfigStore()
const userInfo = computed(() => store.state.auth.info) const userInfo = computed(() => store.state.auth.info)
const userAvatar = computed(() => store.state.auth.avatarUrl) const userAvatar = computed(() => store.state.auth.avatarUrl)
const currentList = computed(() => store.state.currentList) const currentList = computed(() => store.state.currentList)
const background = computed(() => store.state.background) const background = computed(() => store.state.background)
const imprintUrl = computed(() => store.state.config.legal.imprintUrl) const imprintUrl = computed(() => configStore.legal.imprintUrl)
const privacyPolicyUrl = computed(() => store.state.config.legal.privacyPolicyUrl) const privacyPolicyUrl = computed(() => configStore.legal.privacyPolicyUrl)
const canWriteCurrentList = computed(() => store.state.currentList.maxRight > Rights.READ) const canWriteCurrentList = computed(() => store.state.currentList.maxRight > Rights.READ)
const menuActive = computed(() => store.state.menuActive) const menuActive = computed(() => store.state.menuActive)

View File

@ -77,7 +77,6 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref, computed, watchEffect, type PropType} from 'vue' import {ref, computed, watchEffect, type PropType} from 'vue'
import {useStore} from '@/store'
import {getSavedFilterIdFromListId} from '@/helpers/savedFilter' import {getSavedFilterIdFromListId} from '@/helpers/savedFilter'
import Dropdown from '@/components/misc/dropdown.vue' import Dropdown from '@/components/misc/dropdown.vue'
@ -85,6 +84,7 @@ import DropdownItem from '@/components/misc/dropdown-item.vue'
import TaskSubscription from '@/components/misc/subscription.vue' import TaskSubscription from '@/components/misc/subscription.vue'
import type {IList} from '@/modelTypes/IList' import type {IList} from '@/modelTypes/IList'
import type {ISubscription} from '@/modelTypes/ISubscription' import type {ISubscription} from '@/modelTypes/ISubscription'
import {useConfigStore} from '@/stores/config'
const props = defineProps({ const props = defineProps({
list: { list: {
@ -98,7 +98,7 @@ watchEffect(() => {
subscription.value = props.list.subscription ?? null subscription.value = props.list.subscription ?? null
}) })
const store = useStore() const configStore = useConfigStore()
const backgroundsEnabled = computed(() => store.state.config.enabledBackgroundProviders?.length > 0) const backgroundsEnabled = computed(() => configStore.enabledBackgroundProviders?.length > 0)
const isSavedFilter = computed(() => getSavedFilterIdFromListId(props.list.id) > 0) const isSavedFilter = computed(() => getSavedFilterIdFromListId(props.list.id) > 0)
</script> </script>

View File

@ -8,14 +8,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import {computed} from 'vue' import {computed} from 'vue'
import {useStore} from '@/store'
import BaseButton from '@/components/base/BaseButton.vue' import BaseButton from '@/components/base/BaseButton.vue'
import {useConfigStore} from '@/stores/config'
const store = useStore() const configStore = useConfigStore()
const imprintUrl = computed(() => store.state.config.legal.imprintUrl) const imprintUrl = computed(() => configStore.legal.imprintUrl)
const privacyPolicyUrl = computed(() => store.state.config.legal.privacyPolicyUrl) const privacyPolicyUrl = computed(() => configStore.legal.privacyPolicyUrl)
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -26,22 +26,23 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import {computed} from 'vue'
import {useRoute} from 'vue-router'
import {useI18n} from 'vue-i18n'
import Logo from '@/components/home/Logo.vue' import Logo from '@/components/home/Logo.vue'
import Message from '@/components/misc/message.vue' import Message from '@/components/misc/message.vue'
import Legal from '@/components/misc/legal.vue' import Legal from '@/components/misc/legal.vue'
import ApiConfig from '@/components/misc/api-config.vue' import ApiConfig from '@/components/misc/api-config.vue'
import {useStore} from '@/store'
import {computed} from 'vue'
import {useRoute} from 'vue-router'
import {useI18n} from 'vue-i18n'
import {useTitle} from '@/composables/useTitle' import {useTitle} from '@/composables/useTitle'
import {useConfigStore} from '@/stores/config'
const configStore = useConfigStore()
const motd = computed(() => configStore.motd)
const route = useRoute() const route = useRoute()
const store = useStore()
const {t} = useI18n({useScope: 'global'}) const {t} = useI18n({useScope: 'global'})
const motd = computed(() => store.state.config.motd)
const title = computed(() => t(route.meta?.title as string || '')) const title = computed(() => t(route.meta?.title as string || ''))
useTitle(() => title.value) useTitle(() => title.value)
</script> </script>

View File

@ -189,7 +189,6 @@
<script setup lang="ts"> <script setup lang="ts">
import {ref, watch, computed, shallowReactive} from 'vue' import {ref, watch, computed, shallowReactive} from 'vue'
import {useStore} from '@/store'
import {useI18n} from 'vue-i18n' import {useI18n} from 'vue-i18n'
import {RIGHTS} from '@/constants/rights' import {RIGHTS} from '@/constants/rights'
@ -204,6 +203,7 @@ import {useCopyToClipboard} from '@/composables/useCopyToClipboard'
import {success} from '@/message' import {success} from '@/message'
import type {ListView} from '@/types/ListView' import type {ListView} from '@/types/ListView'
import {LIST_VIEWS} from '@/types/ListView' import {LIST_VIEWS} from '@/types/ListView'
import {useConfigStore} from '@/stores/config'
const props = defineProps({ const props = defineProps({
listId: { listId: {
@ -241,8 +241,8 @@ watch(
{immediate: true}, {immediate: true},
) )
const store = useStore() const configStore = useConfigStore()
const frontendUrl = computed(() => store.state.config.frontendUrl) const frontendUrl = computed(() => configStore.frontendUrl)
async function load(listId: IList['id']) { async function load(listId: IList['id']) {
// If listId == 0 the list on the calling component wasn't already loaded, so we just bail out here // If listId == 0 the list on the calling component wasn't already loaded, so we just bail out here

View File

@ -167,6 +167,7 @@ import type {ITask} from '@/modelTypes/ITask'
import {uploadFile} from '@/helpers/attachments' import {uploadFile} from '@/helpers/attachments'
import {success} from '@/message' import {success} from '@/message'
import {formatDateLong, formatDateSince} from '@/helpers/time/formatDate' import {formatDateLong, formatDateSince} from '@/helpers/time/formatDate'
import {useConfigStore} from '@/stores/config'
const props = defineProps({ const props = defineProps({
taskId: { taskId: {
@ -180,6 +181,7 @@ const props = defineProps({
const {t} = useI18n({useScope: 'global'}) const {t} = useI18n({useScope: 'global'})
const store = useStore() const store = useStore()
const configStore = useConfigStore()
const comments = ref<ITaskComment[]>([]) const comments = ref<ITaskComment[]>([])
@ -196,7 +198,7 @@ const saving = ref<ITask['id'] | null>(null)
const userAvatar = computed(() => store.state.auth.info.getAvatarUrl(48)) const userAvatar = computed(() => store.state.auth.info.getAvatarUrl(48))
const currentUserId = computed(() => store.state.auth.info.id) const currentUserId = computed(() => store.state.auth.info.id)
const enabled = computed(() => store.state.config.taskCommentsEnabled) const enabled = computed(() => configStore.taskCommentsEnabled)
const actions = computed(() => { const actions = computed(() => {
if (!props.canWrite) { if (!props.canWrite) {
return {} return {}

View File

@ -1,10 +1,9 @@
import {store} from '@/store' import {useConfigStore} from '@/stores/config'
const API_DEFAULT_PORT = '3456' const API_DEFAULT_PORT = '3456'
export const ERROR_NO_API_URL = 'noApiUrlProvided' export const ERROR_NO_API_URL = 'noApiUrlProvided'
const updateConfig = () => store.dispatch('config/update')
export const checkAndSetApiUrl = (url: string): Promise<string> => { export const checkAndSetApiUrl = (url: string): Promise<string> => {
if(url.startsWith('/')) { if(url.startsWith('/')) {
@ -25,6 +24,9 @@ export const checkAndSetApiUrl = (url: string): Promise<string> => {
const oldUrl = window.API_URL const oldUrl = window.API_URL
window.API_URL = urlToCheck.toString() window.API_URL = urlToCheck.toString()
const configStore = useConfigStore()
const updateConfig = () => configStore.update()
// Check if the api is reachable at the provided url // Check if the api is reachable at the provided url
return updateConfig() return updateConfig()
.catch(e => { .catch(e => {

View File

@ -7,7 +7,7 @@ export default class TotpModel extends AbstractModel<ITotp> implements ITotp {
enabled = false enabled = false
url = '' url = ''
constructor(data: Partial<ITotp>) { constructor(data: Partial<ITotp> = {}) {
super() super()
this.assignData(data) this.assignData(data)
} }

View File

@ -13,7 +13,6 @@ import {
MENU_ACTIVE, MENU_ACTIVE,
QUICK_ACTIONS_ACTIVE, QUICK_ACTIONS_ACTIVE,
} from './mutation-types' } from './mutation-types'
import config from './modules/config'
import auth from './modules/auth' import auth from './modules/auth'
import kanban from './modules/kanban' import kanban from './modules/kanban'
import tasks from './modules/tasks' import tasks from './modules/tasks'
@ -35,7 +34,6 @@ export function useStore () {
export const store = createStore<RootStoreState>({ export const store = createStore<RootStoreState>({
strict: import.meta.env.DEV, strict: import.meta.env.DEV,
modules: { modules: {
config,
auth, auth,
kanban, kanban,
tasks, tasks,

View File

@ -14,6 +14,7 @@ import type { RootStoreState, AuthState, Info} from '@/store/types'
import {AUTH_TYPES} from '@/store/types' import {AUTH_TYPES} from '@/store/types'
import type { IUserSettings } from '@/modelTypes/IUserSettings' import type { IUserSettings } from '@/modelTypes/IUserSettings'
import router from '@/router' import router from '@/router'
import {useConfigStore} from '@/stores/config'
function defaultSettings(settings: Partial<IUserSettings>) { function defaultSettings(settings: Partial<IUserSettings>) {
if (typeof settings.weekStart === 'undefined' || settings.weekStart === '') { if (typeof settings.weekStart === 'undefined' || settings.weekStart === '') {
@ -198,8 +199,8 @@ const authStore : Module<AuthState, RootStoreState> = {
} }
}, },
redirectToProviderIfNothingElseIsEnabled({rootState}) { redirectToProviderIfNothingElseIsEnabled() {
const {auth} = rootState.config const {auth} = useConfigStore()
if ( if (
auth.local.enabled === false && auth.local.enabled === false &&
auth.openidConnect.enabled && auth.openidConnect.enabled &&

View File

@ -1,14 +1,13 @@
import type { Module } from 'vuex' import {defineStore, acceptHMRUpdate} from 'pinia'
import {parseURL} from 'ufo' import {parseURL} from 'ufo'
import {CONFIG} from '../mutation-types' import {CONFIG} from '../store/mutation-types'
import {HTTPFactory} from '@/http-common' import {HTTPFactory} from '@/http-common'
import {objectToCamelCase} from '@/helpers/case' import {objectToCamelCase} from '@/helpers/case'
import type { RootStoreState, ConfigState } from '@/store/types' import type {ConfigState} from '@/store/types'
const configStore : Module<ConfigState, RootStoreState> = { export const useConfigStore = defineStore('config', {
namespaced: true, state: (): ConfigState => ({
state: () => ({
// These are the api defaults. // These are the api defaults.
version: '', version: '',
frontendUrl: '', frontendUrl: '',
@ -45,19 +44,20 @@ const configStore : Module<ConfigState, RootStoreState> = {
return protocol + '//' + host return protocol + '//' + host
}, },
}, },
mutations: {
[CONFIG](state, config: ConfigState) {
Object.assign(state, config)
},
},
actions: { actions: {
async update(ctx) { [CONFIG](config: ConfigState) {
Object.assign(this, config)
},
async update() {
const HTTP = HTTPFactory() const HTTP = HTTPFactory()
const {data: config} = await HTTP.get('info') const {data: config} = await HTTP.get('info')
ctx.commit(CONFIG, objectToCamelCase(config)) this[CONFIG](objectToCamelCase(config))
return config return config
}, },
}, },
} })
export default configStore // support hot reloading
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useConfigStore, import.meta.hot))
}

View File

@ -34,8 +34,9 @@
<script setup lang="ts"> <script setup lang="ts">
import {computed} from 'vue' import {computed} from 'vue'
import { store } from '@/store'
import {VERSION as frontendVersion} from '@/version.json' import {VERSION as frontendVersion} from '@/version.json'
import {useConfigStore} from '@/stores/config'
const apiVersion = computed(() => store.state.config.version) const configStore = useConfigStore()
const apiVersion = computed(() => configStore.version)
</script> </script>

View File

@ -72,11 +72,13 @@ import {parseDateOrNull} from '@/helpers/parseDateOrNull'
import {formatDateShort, formatDateSince} from '@/helpers/time/formatDate' import {formatDateShort, formatDateSince} from '@/helpers/time/formatDate'
import {useDateTimeSalutation} from '@/composables/useDateTimeSalutation' import {useDateTimeSalutation} from '@/composables/useDateTimeSalutation'
import {useListStore} from '@/stores/lists' import {useListStore} from '@/stores/lists'
import {useConfigStore} from '@/stores/config'
import {useNamespaceStore} from '@/stores/namespaces' import {useNamespaceStore} from '@/stores/namespaces'
const welcome = useDateTimeSalutation() const welcome = useDateTimeSalutation()
const store = useStore() const store = useStore()
const configStore = useConfigStore()
const namespaceStore = useNamespaceStore() const namespaceStore = useNamespaceStore()
const listStore = useListStore() const listStore = useListStore()
const listHistory = computed(() => { const listHistory = computed(() => {
@ -90,7 +92,7 @@ const listHistory = computed(() => {
.filter(l => l !== null) .filter(l => l !== null)
}) })
const migratorsEnabled = computed(() => store.state.config.availableMigrators?.length > 0) const migratorsEnabled = computed(() => configStore.availableMigrators?.length > 0)
const userInfo = computed(() => store.state.auth.info) const userInfo = computed(() => store.state.auth.info)
const hasTasks = computed(() => store.state.hasTasks) const hasTasks = computed(() => store.state.hasTasks)
const defaultListId = computed(() => store.state.auth.settings.defaultListId) const defaultListId = computed(() => store.state.auth.settings.defaultListId)

View File

@ -106,6 +106,7 @@ import debounce from 'lodash.debounce'
import BaseButton from '@/components/base/BaseButton.vue' import BaseButton from '@/components/base/BaseButton.vue'
import {useListStore} from '@/stores/lists' import {useListStore} from '@/stores/lists'
import {useNamespaceStore} from '@/stores/namespaces' import {useNamespaceStore} from '@/stores/namespaces'
import {useConfigStore} from '@/stores/config'
import BackgroundUnsplashService from '@/services/backgroundUnsplash' import BackgroundUnsplashService from '@/services/backgroundUnsplash'
import BackgroundUploadService from '@/services/backgroundUpload' import BackgroundUploadService from '@/services/backgroundUpload'
@ -144,9 +145,10 @@ const backgroundUploadService = ref(new BackgroundUploadService())
const listService = ref(new ListService()) const listService = ref(new ListService())
const listStore = useListStore() const listStore = useListStore()
const namespaceStore = useNamespaceStore() const namespaceStore = useNamespaceStore()
const configStore = useConfigStore()
const unsplashBackgroundEnabled = computed(() => store.state.config.enabledBackgroundProviders.includes('unsplash')) const unsplashBackgroundEnabled = computed(() => configStore.enabledBackgroundProviders.includes('unsplash'))
const uploadBackgroundEnabled = computed(() => store.state.config.enabledBackgroundProviders.includes('upload')) const uploadBackgroundEnabled = computed(() => configStore.enabledBackgroundProviders.includes('upload'))
const currentList = computed(() => store.state.currentList) const currentList = computed(() => store.state.currentList)
const hasBackground = computed(() => store.state.background !== null) const hasBackground = computed(() => store.state.background !== null)

View File

@ -40,6 +40,7 @@ import {CURRENT_LIST} from '@/store/mutation-types'
import CreateEdit from '@/components/misc/create-edit.vue' import CreateEdit from '@/components/misc/create-edit.vue'
import LinkSharing from '@/components/sharing/linkSharing.vue' import LinkSharing from '@/components/sharing/linkSharing.vue'
import userTeam from '@/components/sharing/userTeam.vue' import userTeam from '@/components/sharing/userTeam.vue'
import {useConfigStore} from '@/stores/config'
const {t} = useI18n({useScope: 'global'}) const {t} = useI18n({useScope: 'global'})
@ -51,7 +52,9 @@ const title = computed(() => list.value?.title
useTitle(title) useTitle(title)
const store = useStore() const store = useStore()
const linkSharingEnabled = computed(() => store.state.config.linkSharingEnabled) const configStore = useConfigStore()
const linkSharingEnabled = computed(() => configStore.linkSharingEnabled)
const userIsAdmin = computed(() => 'owner' in list.value && list.value.owner.id === store.state.auth.info.id) const userIsAdmin = computed(() => 'owner' in list.value && list.value.owner.id === store.state.auth.info.id)
async function loadList(listId: number) { async function loadList(listId: number) {

View File

@ -23,17 +23,17 @@
<script setup lang="ts"> <script setup lang="ts">
import {computed} from 'vue' import {computed} from 'vue'
import {useI18n} from 'vue-i18n' import {useI18n} from 'vue-i18n'
import {useStore} from '@/store'
import {MIGRATORS} from './migrators' import {MIGRATORS} from './migrators'
import {useTitle} from '@/composables/useTitle' import {useTitle} from '@/composables/useTitle'
import {useConfigStore} from '@/stores/config'
const {t} = useI18n({useScope: 'global'}) const {t} = useI18n({useScope: 'global'})
const store = useStore()
useTitle(() => t('migrate.title')) useTitle(() => t('migrate.title'))
const availableMigrators = computed(() => store.state.config.availableMigrators const configStore = useConfigStore()
const availableMigrators = computed(() => configStore.availableMigrators
.map((id) => MIGRATORS[id]) .map((id) => MIGRATORS[id])
.filter((item) => Boolean(item)), .filter((item) => Boolean(item)),
) )

View File

@ -104,7 +104,8 @@
<script lang="ts"> <script lang="ts">
import {defineComponent} from 'vue' import {defineComponent} from 'vue'
import {useDebounceFn} from '@vueuse/core' import {useDebounceFn} from '@vueuse/core'
import {mapState} from 'vuex' import {mapState as mapStateVuex} from 'vuex'
import {mapState} from 'pinia'
import {HTTPFactory} from '@/http-common' import {HTTPFactory} from '@/http-common'
import {LOADING} from '@/store/mutation-types' import {LOADING} from '@/store/mutation-types'
@ -114,6 +115,7 @@ import {redirectToProvider} from '../../helpers/redirectToProvider'
import {getLastVisited, clearLastVisited} from '../../helpers/saveLastVisited' import {getLastVisited, clearLastVisited} from '../../helpers/saveLastVisited'
import Password from '@/components/input/password.vue' import Password from '@/components/input/password.vue'
import { setTitle } from '@/helpers/setTitle' import { setTitle } from '@/helpers/setTitle'
import {useConfigStore} from '@/stores/config'
export default defineComponent({ export default defineComponent({
components: { components: {
@ -169,13 +171,16 @@ export default defineComponent({
hasOpenIdProviders() { hasOpenIdProviders() {
return this.openidConnect.enabled && this.openidConnect.providers?.length > 0 return this.openidConnect.enabled && this.openidConnect.providers?.length > 0
}, },
...mapState({ ...mapStateVuex({
registrationEnabled: state => state.config.registrationEnabled,
loading: LOADING, loading: LOADING,
needsTotpPasscode: state => state.auth.needsTotpPasscode, needsTotpPasscode: state => state.auth.needsTotpPasscode,
authenticated: state => state.auth.authenticated, authenticated: state => state.auth.authenticated,
localAuthEnabled: state => state.config.auth.local.enabled, }),
openidConnect: state => state.config.auth.openidConnect,
...mapState(useConfigStore, {
registrationEnabled: state => state.registrationEnabled,
localAuthEnabled: state => state.auth.local.enabled,
openidConnect: state => state.auth.openidConnect,
}), }),
validateField() { validateField() {

View File

@ -22,13 +22,15 @@ import {computed} from 'vue'
import { store } from '@/store' import { store } from '@/store'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useTitle } from '@/composables/useTitle' import { useTitle } from '@/composables/useTitle'
import { useConfigStore } from '@/stores/config'
const { t } = useI18n({useScope: 'global'}) const { t } = useI18n({useScope: 'global'})
useTitle(() => t('user.settings.title')) useTitle(() => t('user.settings.title'))
const totpEnabled = computed(() => store.state.config.totpEnabled) const configStore = useConfigStore()
const caldavEnabled = computed(() => store.state.config.caldavEnabled) const totpEnabled = computed(() => configStore.totpEnabled)
const migratorsEnabled = computed(() => store.getters['config/migratorsEnabled']) const caldavEnabled = computed(() => configStore.caldavEnabled)
const migratorsEnabled = computed(() => configStore.migratorsEnabled)
const isLocalUser = computed(() => store.state.auth.info?.isLocalUser) const isLocalUser = computed(() => store.state.auth.info?.isLocalUser)
const navigationItems = computed(() => { const navigationItems = computed(() => {

View File

@ -79,6 +79,7 @@ import Message from '@/components/misc/message.vue'
import CaldavTokenService from '@/services/caldavToken' import CaldavTokenService from '@/services/caldavToken'
import { formatDateShort } from '@/helpers/time/formatDate' import { formatDateShort } from '@/helpers/time/formatDate'
import type {ICaldavToken} from '@/modelTypes/ICaldavToken' import type {ICaldavToken} from '@/modelTypes/ICaldavToken'
import {useConfigStore} from '@/stores/config'
const copy = useCopyToClipboard() const copy = useCopyToClipboard()
@ -105,8 +106,9 @@ async function deleteToken(token: ICaldavToken) {
} }
const store = useStore() const store = useStore()
const configStore = useConfigStore()
const username = computed(() => store.state.auth.info?.username) const username = computed(() => store.state.auth.info?.username)
const caldavUrl = computed(() => `${store.getters['config/apiBase']}/dav/principals/${username.value}/`) const caldavUrl = computed(() => `${configStore.apiBase}/dav/principals/${username.value}/`)
const caldavEnabled = computed(() => store.state.config.caldavEnabled) const caldavEnabled = computed(() => configStore.caldavEnabled)
const isLocalUser = computed(() => store.state.auth.info?.isLocalUser) const isLocalUser = computed(() => store.state.auth.info?.isLocalUser)
</script> </script>

View File

@ -96,6 +96,7 @@ import {parseDateOrNull} from '@/helpers/parseDateOrNull'
import {formatDateShort, formatDateSince} from '@/helpers/time/formatDate' import {formatDateShort, formatDateSince} from '@/helpers/time/formatDate'
import {useTitle} from '@/composables/useTitle' import {useTitle} from '@/composables/useTitle'
import {success} from '@/message' import {success} from '@/message'
import {useConfigStore} from '@/stores/config'
const {t} = useI18n({useScope: 'global'}) const {t} = useI18n({useScope: 'global'})
useTitle(() => `${t('user.deletion.title')} - ${t('user.settings.title')}`) useTitle(() => `${t('user.deletion.title')} - ${t('user.settings.title')}`)
@ -105,7 +106,9 @@ const password = ref('')
const errPasswordRequired = ref(false) const errPasswordRequired = ref(false)
const store = useStore() const store = useStore()
const userDeletionEnabled = computed(() => store.state.config.userDeletionEnabled) const configStore = useConfigStore()
const userDeletionEnabled = computed(() => configStore.userDeletionEnabled)
const deletionScheduledAt = computed(() => parseDateOrNull(store.state.auth.info?.deletionScheduledAt)) const deletionScheduledAt = computed(() => parseDateOrNull(store.state.auth.info?.deletionScheduledAt))
const passwordInput = ref() const passwordInput = ref()

View File

@ -70,7 +70,6 @@ export default { name: 'user-settings-totp' }
<script lang="ts" setup> <script lang="ts" setup>
import {computed, ref, shallowReactive} from 'vue' import {computed, ref, shallowReactive} from 'vue'
import {useStore} from '@/store'
import {useI18n} from 'vue-i18n' import {useI18n} from 'vue-i18n'
import TotpService from '@/services/totp' import TotpService from '@/services/totp'
@ -78,7 +77,8 @@ import TotpModel from '@/models/totp'
import {success} from '@/message' import {success} from '@/message'
import { useTitle } from '@/composables/useTitle' import {useTitle} from '@/composables/useTitle'
import {useConfigStore} from '@/stores/config'
const {t} = useI18n({useScope: 'global'}) const {t} = useI18n({useScope: 'global'})
useTitle(() => `${t('user.settings.totp.title')} - ${t('user.settings.title')}`) useTitle(() => `${t('user.settings.totp.title')} - ${t('user.settings.title')}`)
@ -92,8 +92,8 @@ const totpConfirmPasscode = ref('')
const totpDisableForm = ref(false) const totpDisableForm = ref(false)
const totpDisablePassword = ref('') const totpDisablePassword = ref('')
const store = useStore() const configStore = useConfigStore()
const totpEnabled = computed(() => store.state.config.totpEnabled) const totpEnabled = computed(() => configStore.totpEnabled)
totpStatus() totpStatus()