feat: rework loading state of stores
This commit is contained in:
parent
7f281fc5e9
commit
1d7f857070
13 changed files with 59 additions and 86 deletions
|
@ -6,14 +6,13 @@ import {objectToSnakeCase} from '@/helpers/case'
|
|||
import UserModel, { getAvatarUrl } from '@/models/user'
|
||||
import UserSettingsService from '@/services/userSettings'
|
||||
import {getToken, refreshToken, removeToken, saveToken} from '@/helpers/auth'
|
||||
import {setLoadingPinia} from '@/stores/helper'
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import {success} from '@/message'
|
||||
import {redirectToProvider} from '@/helpers/redirectToProvider'
|
||||
import {AUTH_TYPES, type IUser} from '@/modelTypes/IUser'
|
||||
import type {IUserSettings} from '@/modelTypes/IUserSettings'
|
||||
import router from '@/router'
|
||||
import {useConfigStore} from '@/stores/config'
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
import UserSettingsModel from '@/models/userSettings'
|
||||
|
||||
export interface AuthState {
|
||||
|
@ -104,8 +103,6 @@ export const useAuthStore = defineStore('auth', {
|
|||
// Logs a user in with a set of credentials.
|
||||
async login(credentials) {
|
||||
const HTTP = HTTPFactory()
|
||||
const baseStore = useBaseStore()
|
||||
baseStore.setLoading(true)
|
||||
this.setIsLoading(true)
|
||||
|
||||
// Delete an eventually preexisting old token
|
||||
|
@ -129,7 +126,6 @@ export const useAuthStore = defineStore('auth', {
|
|||
|
||||
throw e
|
||||
} finally {
|
||||
baseStore.setLoading(false)
|
||||
this.setIsLoading(false)
|
||||
}
|
||||
},
|
||||
|
@ -138,8 +134,6 @@ export const useAuthStore = defineStore('auth', {
|
|||
// Not sure if this is the right place to put the logic in, maybe a seperate js component would be better suited.
|
||||
async register(credentials) {
|
||||
const HTTP = HTTPFactory()
|
||||
const baseStore = useBaseStore()
|
||||
baseStore.setLoading(true)
|
||||
this.setIsLoading(true)
|
||||
try {
|
||||
await HTTP.post('register', credentials)
|
||||
|
@ -151,15 +145,12 @@ export const useAuthStore = defineStore('auth', {
|
|||
|
||||
throw e
|
||||
} finally {
|
||||
baseStore.setLoading(false)
|
||||
this.setIsLoading(false)
|
||||
}
|
||||
},
|
||||
|
||||
async openIdAuth({provider, code}) {
|
||||
const HTTP = HTTPFactory()
|
||||
const baseStore = useBaseStore()
|
||||
baseStore.setLoading(true)
|
||||
this.setIsLoading(true)
|
||||
|
||||
const data = {
|
||||
|
@ -176,7 +167,6 @@ export const useAuthStore = defineStore('auth', {
|
|||
// Tell others the user is autheticated
|
||||
this.checkAuth()
|
||||
} finally {
|
||||
baseStore.setLoading(false)
|
||||
this.setIsLoading(false)
|
||||
}
|
||||
},
|
||||
|
@ -294,8 +284,7 @@ export const useAuthStore = defineStore('auth', {
|
|||
}) {
|
||||
const userSettingsService = new UserSettingsService()
|
||||
|
||||
// FIXME
|
||||
const cancel = setLoadingPinia(this, this.setIsLoadingGeneralSettings)
|
||||
const cancel = setModuleLoading(this, this.setIsLoadingGeneralSettings)
|
||||
try {
|
||||
saveLanguage(settings.language)
|
||||
await userSettingsService.update(settings)
|
||||
|
|
|
@ -11,7 +11,6 @@ import type {IList} from '@/modelTypes/IList'
|
|||
|
||||
export interface RootStoreState {
|
||||
loading: boolean,
|
||||
loadingModule: null,
|
||||
|
||||
currentList: IList,
|
||||
background: string,
|
||||
|
@ -27,7 +26,6 @@ export interface RootStoreState {
|
|||
export const useBaseStore = defineStore('base', {
|
||||
state: () : RootStoreState => ({
|
||||
loading: false,
|
||||
loadingModule: null,
|
||||
|
||||
// This is used to highlight the current list in menu for all list related views
|
||||
currentList: new ListModel({
|
||||
|
@ -49,11 +47,6 @@ export const useBaseStore = defineStore('base', {
|
|||
this.loading = loading
|
||||
},
|
||||
|
||||
setLoadingModule(module) {
|
||||
this.loadingModule = module
|
||||
},
|
||||
|
||||
// FIXME: same action as mutation name
|
||||
setCurrentList(currentList: IList) {
|
||||
// Server updates don't return the right. Therefore, the right is reset after updating the list which is
|
||||
// confusing because all the buttons will disappear in that case. To prevent this, we're keeping the right
|
||||
|
@ -102,8 +95,7 @@ export const useBaseStore = defineStore('base', {
|
|||
this.logoVisible = visible
|
||||
},
|
||||
|
||||
// FIXME: update all actions handleSetCurrentList
|
||||
async handleSetCurrentList({list, forceUpdate = false}) {
|
||||
async handleSetCurrentList({list, forceUpdate = false} : {list: IList, forceUpdate: boolean}) {
|
||||
if (list === null) {
|
||||
this.setCurrentList({})
|
||||
this.setBackground('')
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
import type { StoreDefinition } from 'pinia'
|
||||
|
||||
export const setLoadingPinia = (store: StoreDefinition, loadFunc : ((isLoading: boolean) => void) | null = null) => {
|
||||
export interface LoadingState {
|
||||
isLoading: boolean
|
||||
}
|
||||
|
||||
const LOADING_TIMEOUT = 100
|
||||
|
||||
export const setModuleLoading = <LoadingStore extends StoreDefinition<string, LoadingState>>(store: LoadingStore, loadFunc : ((isLoading: boolean) => void) | null = null) => {
|
||||
const timeout = setTimeout(() => {
|
||||
if (loadFunc === null) {
|
||||
store.isLoading = true
|
||||
} else {
|
||||
loadFunc(true)
|
||||
}
|
||||
}, 100)
|
||||
}, LOADING_TIMEOUT)
|
||||
return () => {
|
||||
clearTimeout(timeout)
|
||||
if (loadFunc === null) {
|
||||
|
|
|
@ -8,7 +8,7 @@ import {success} from '@/message'
|
|||
import BucketService from '@/services/bucket'
|
||||
import TaskCollectionService from '@/services/taskCollection'
|
||||
|
||||
import {setLoadingPinia} from '@/stores/helper'
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
|
||||
import type { ITask } from '@/modelTypes/ITask'
|
||||
import type { IList } from '@/modelTypes/IList'
|
||||
|
@ -261,7 +261,7 @@ export const useKanbanStore = defineStore('kanban', {
|
|||
},
|
||||
|
||||
async loadBucketsForList({listId, params}: {listId: IList['id'], params}) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
|
||||
// Clear everything to prevent having old buckets in the list if loading the buckets from this list takes a few moments
|
||||
this.setBuckets([])
|
||||
|
@ -295,7 +295,7 @@ export const useKanbanStore = defineStore('kanban', {
|
|||
return
|
||||
}
|
||||
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
this.setBucketLoading({bucketId: bucketId, loading: true})
|
||||
|
||||
const params = JSON.parse(JSON.stringify(ps))
|
||||
|
@ -338,7 +338,7 @@ export const useKanbanStore = defineStore('kanban', {
|
|||
},
|
||||
|
||||
async createBucket(bucket: IBucket) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
|
||||
const bucketService = new BucketService()
|
||||
try {
|
||||
|
@ -351,7 +351,7 @@ export const useKanbanStore = defineStore('kanban', {
|
|||
},
|
||||
|
||||
async deleteBucket({bucket, params}: {bucket: IBucket, params}) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
|
||||
const bucketService = new BucketService()
|
||||
try {
|
||||
|
@ -366,7 +366,7 @@ export const useKanbanStore = defineStore('kanban', {
|
|||
},
|
||||
|
||||
async updateBucket(updatedBucketData: IBucket) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
|
||||
const bucketIndex = findIndexById(this.buckets, updatedBucketData.id)
|
||||
const oldBucket = cloneDeep(this.buckets[bucketIndex])
|
||||
|
|
|
@ -4,7 +4,7 @@ import LabelService from '@/services/label'
|
|||
import {success} from '@/message'
|
||||
import {i18n} from '@/i18n'
|
||||
import {createNewIndexer} from '@/indexes'
|
||||
import {setLoadingPinia} from '@/stores/helper'
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import type {ILabel} from '@/modelTypes/ILabel'
|
||||
|
||||
const {add, remove, update, search} = createNewIndexer('labels', ['title', 'description'])
|
||||
|
@ -85,7 +85,7 @@ export const useLabelStore = defineStore('label', {
|
|||
return
|
||||
}
|
||||
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
|
||||
try {
|
||||
const labels = await getAllLabels()
|
||||
|
@ -97,7 +97,7 @@ export const useLabelStore = defineStore('label', {
|
|||
},
|
||||
|
||||
async deleteLabel(label: ILabel) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
const labelService = new LabelService()
|
||||
|
||||
try {
|
||||
|
@ -111,7 +111,7 @@ export const useLabelStore = defineStore('label', {
|
|||
},
|
||||
|
||||
async updateLabel(label: ILabel) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
const labelService = new LabelService()
|
||||
|
||||
try {
|
||||
|
@ -125,7 +125,7 @@ export const useLabelStore = defineStore('label', {
|
|||
},
|
||||
|
||||
async createLabel(label: ILabel) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
const labelService = new LabelService()
|
||||
|
||||
try {
|
||||
|
|
|
@ -3,7 +3,7 @@ import {acceptHMRUpdate, defineStore} from 'pinia'
|
|||
import {useI18n} from 'vue-i18n'
|
||||
|
||||
import ListService from '@/services/list'
|
||||
import {setLoadingPinia} from '@/stores/helper'
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import {removeListFromHistory} from '@/modules/listHistory'
|
||||
import {createNewIndexer} from '@/indexes'
|
||||
import {useNamespaceStore} from './namespaces'
|
||||
|
@ -91,7 +91,7 @@ export const useListStore = defineStore('list', {
|
|||
},
|
||||
|
||||
async createList(list: IList) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
const listService = new ListService()
|
||||
|
||||
try {
|
||||
|
@ -107,7 +107,7 @@ export const useListStore = defineStore('list', {
|
|||
},
|
||||
|
||||
async updateList(list: IList) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
const listService = new ListService()
|
||||
|
||||
try {
|
||||
|
@ -143,7 +143,7 @@ export const useListStore = defineStore('list', {
|
|||
},
|
||||
|
||||
async deleteList(list: IList) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
const listService = new ListService()
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {defineStore, acceptHMRUpdate} from 'pinia'
|
||||
|
||||
import NamespaceService from '../services/namespace'
|
||||
import {setLoadingPinia} from '@/stores/helper'
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import {createNewIndexer} from '@/indexes'
|
||||
import type {INamespace} from '@/modelTypes/INamespace'
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
|
@ -139,7 +139,7 @@ export const useNamespaceStore = defineStore('namespace', {
|
|||
},
|
||||
|
||||
async loadNamespaces() {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
|
||||
const namespaceService = new NamespaceService()
|
||||
try {
|
||||
|
@ -174,7 +174,7 @@ export const useNamespaceStore = defineStore('namespace', {
|
|||
},
|
||||
|
||||
async deleteNamespace(namespace: INamespace) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
const namespaceService = new NamespaceService()
|
||||
|
||||
try {
|
||||
|
@ -187,7 +187,7 @@ export const useNamespaceStore = defineStore('namespace', {
|
|||
},
|
||||
|
||||
async createNamespace(namespace: INamespace) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
const namespaceService = new NamespaceService()
|
||||
|
||||
try {
|
||||
|
|
|
@ -23,8 +23,7 @@ import type {IUser} from '@/modelTypes/IUser'
|
|||
import type {IAttachment} from '@/modelTypes/IAttachment'
|
||||
import type {IList} from '@/modelTypes/IList'
|
||||
|
||||
import {setLoadingPinia} from '@/stores/helper'
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
import {setModuleLoading} from '@/stores/helper'
|
||||
import {useLabelStore} from '@/stores/labels'
|
||||
import {useListStore} from '@/stores/lists'
|
||||
import {useAttachmentStore} from '@/stores/attachments'
|
||||
|
@ -79,29 +78,41 @@ async function findAssignees(parsedTaskAssignees: string[]) {
|
|||
}
|
||||
|
||||
export interface TaskState {
|
||||
tasks: { [id: ITask['id']]: ITask }
|
||||
isLoading: boolean,
|
||||
}
|
||||
|
||||
export const useTaskStore = defineStore('task', {
|
||||
state: () : TaskState => ({
|
||||
tasks: {},
|
||||
isLoading: false,
|
||||
}),
|
||||
getters: {
|
||||
hasTasks(state) {
|
||||
return Object.keys(state.tasks).length > 0
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
setTasks(tasks: ITask[]) {
|
||||
tasks.forEach(task => {
|
||||
this.tasks[task.id] = task
|
||||
})
|
||||
},
|
||||
|
||||
async loadTasks(params) {
|
||||
const taskService = new TaskService()
|
||||
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
try {
|
||||
const tasks = await taskService.getAll({}, params)
|
||||
useBaseStore().setHasTasks(tasks.length > 0)
|
||||
return tasks
|
||||
this.tasks = await taskService.getAll({}, params)
|
||||
return this.tasks
|
||||
} finally {
|
||||
cancel()
|
||||
}
|
||||
},
|
||||
|
||||
async update(task: ITask) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
|
||||
const taskService = new TaskService()
|
||||
try {
|
||||
|
@ -358,7 +369,7 @@ export const useTaskStore = defineStore('task', {
|
|||
} :
|
||||
Partial<ITask>,
|
||||
) {
|
||||
const cancel = setLoadingPinia(this)
|
||||
const cancel = setModuleLoading(this)
|
||||
const parsedTask = parseTaskText(title, getQuickAddMagicMode())
|
||||
|
||||
const foundListId = await this.findListId({
|
||||
|
|
|
@ -79,17 +79,15 @@ import {getNamespaceTitle} from '@/helpers/getNamespaceTitle'
|
|||
import {useTitle} from '@/composables/useTitle'
|
||||
import {useStorage} from '@vueuse/core'
|
||||
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
import {useNamespaceStore} from '@/stores/namespaces'
|
||||
|
||||
const {t} = useI18n()
|
||||
const baseStore = useBaseStore()
|
||||
const namespaceStore = useNamespaceStore()
|
||||
|
||||
useTitle(() => t('namespace.title'))
|
||||
const showArchived = useStorage('showArchived', false)
|
||||
|
||||
const loading = computed(() => baseStore.loading) // FIXME: shouldn't this reference the namespace store?
|
||||
const loading = computed(() => namespaceStore.isLoading)
|
||||
const namespaces = computed(() => {
|
||||
return namespaceStore.namespaces.filter(n => showArchived.value ? true : !n.isArchived)
|
||||
// return namespaceStore.namespaces.filter(n => showArchived.value ? true : !n.isArchived).map(n => {
|
||||
|
|
|
@ -114,7 +114,6 @@ import {getLastVisited, clearLastVisited} from '../../helpers/saveLastVisited'
|
|||
import Password from '@/components/input/password.vue'
|
||||
import {setTitle} from '@/helpers/setTitle'
|
||||
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
import {useConfigStore} from '@/stores/config'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
|
||||
|
@ -172,13 +171,11 @@ export default defineComponent({
|
|||
hasOpenIdProviders() {
|
||||
return this.openidConnect.enabled && this.openidConnect.providers?.length > 0
|
||||
},
|
||||
...mapState(useBaseStore, {
|
||||
isLoading: state => state.loading,
|
||||
}),
|
||||
|
||||
...mapState(useAuthStore, {
|
||||
needsTotpPasscode: state => state.needsTotpPasscode,
|
||||
authenticated: state => state.authenticated,
|
||||
isLoading: state => state.isLoading,
|
||||
}),
|
||||
|
||||
...mapState(useConfigStore, {
|
||||
|
@ -195,16 +192,6 @@ export default defineComponent({
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
setLoading() {
|
||||
const timeout = setTimeout(() => {
|
||||
this.isLoading = true
|
||||
}, 100)
|
||||
return () => {
|
||||
clearTimeout(timeout)
|
||||
this.isLoading = false
|
||||
}
|
||||
},
|
||||
|
||||
async submit() {
|
||||
this.errorMessage = ''
|
||||
// Some browsers prevent Vue bindings from working with autofilled values.
|
||||
|
|
|
@ -22,7 +22,6 @@ import {getErrorText} from '@/message'
|
|||
import Message from '@/components/misc/message.vue'
|
||||
import {clearLastVisited, getLastVisited} from '@/helpers/saveLastVisited'
|
||||
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
|
||||
const {t} = useI18n({useScope: 'global'})
|
||||
|
@ -30,10 +29,9 @@ const {t} = useI18n({useScope: 'global'})
|
|||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const loading = computed(() => baseStore.loading)
|
||||
const loading = computed(() => authStore.isLoading)
|
||||
const errorMessage = ref('')
|
||||
|
||||
async function authenticateWithCode() {
|
||||
|
|
|
@ -77,10 +77,8 @@ import Message from '@/components/misc/message.vue'
|
|||
import {isEmail} from '@/helpers/isEmail'
|
||||
import Password from '@/components/input/password.vue'
|
||||
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
// FIXME: use the `beforeEnter` hook of vue-router
|
||||
|
@ -97,7 +95,7 @@ const credentials = reactive({
|
|||
password: '',
|
||||
})
|
||||
|
||||
const isLoading = computed(() => baseStore.loading)
|
||||
const isLoading = computed(() => authStore.isLoading)
|
||||
const errorMessage = ref('')
|
||||
const validatePasswordInitially = ref(false)
|
||||
|
||||
|
|
|
@ -147,13 +147,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {defineComponent} from 'vue'
|
||||
import { useListStore } from '@/stores/lists'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'user-settings-general',
|
||||
})
|
||||
export default {name: 'user-settings-general'}
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -168,14 +162,15 @@ import {availableLanguages} from '@/i18n'
|
|||
import {playSoundWhenDoneKey, playPopSound} from '@/helpers/playPop'
|
||||
import {getQuickAddMagicMode, setQuickAddMagicMode} from '@/helpers/quickAddMagicMode'
|
||||
import {createRandomID} from '@/helpers/randomId'
|
||||
import {objectIsEmpty} from '@/helpers/objectIsEmpty'
|
||||
import {success} from '@/message'
|
||||
import {AuthenticatedHTTPFactory} from '@/http-common'
|
||||
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
|
||||
import {useColorScheme} from '@/composables/useColorScheme'
|
||||
import {useTitle} from '@/composables/useTitle'
|
||||
import {objectIsEmpty} from '@/helpers/objectIsEmpty'
|
||||
|
||||
import {useListStore} from '@/stores/lists'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
|
||||
const {t} = useI18n({useScope: 'global'})
|
||||
useTitle(() => `${t('user.settings.general.title')} - ${t('user.settings.title')}`)
|
||||
|
@ -228,7 +223,6 @@ function getPlaySoundWhenDoneSetting() {
|
|||
const playSoundWhenDone = ref(getPlaySoundWhenDoneSetting())
|
||||
const quickAddMagicMode = ref(getQuickAddMagicMode())
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
const authStore = useAuthStore()
|
||||
const settings = ref({...authStore.settings})
|
||||
const id = ref(createRandomID())
|
||||
|
@ -257,7 +251,7 @@ const defaultList = computed({
|
|||
settings.value.defaultListId = l ? l.id : DEFAULT_LIST_ID
|
||||
},
|
||||
})
|
||||
const loading = computed(() => baseStore.loading && baseStore.loadingModule === 'general-settings')
|
||||
const loading = computed(() => authStore.isLoadingGeneralSettings)
|
||||
|
||||
watch(
|
||||
playSoundWhenDone,
|
||||
|
|
Loading…
Reference in a new issue