feat: port label store to pinia | pinia 1/9 (#2391)
Co-authored-by: Dominik Pschenitschni <mail@celement.de> Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/2391 Reviewed-by: konrad <k@knt.li> Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de> Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
This commit is contained in:
parent
e91b5fde02
commit
d67e5e386d
17 changed files with 276 additions and 235 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import type { ActionContext } from 'vuex'
|
||||
import type { StoreDefinition } from 'pinia'
|
||||
import {LOADING, LOADING_MODULE} from './mutation-types'
|
||||
import type { RootStoreState } from './types'
|
||||
|
||||
|
|
@ -31,4 +32,22 @@ export function setLoading<State>(
|
|||
loadFunc(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const setLoadingPinia = (store: StoreDefinition, loadFunc : ((isLoading: boolean) => void) | null = null) => {
|
||||
const timeout = setTimeout(() => {
|
||||
if (loadFunc === null) {
|
||||
store.isLoading = true
|
||||
} else {
|
||||
loadFunc(true)
|
||||
}
|
||||
}, 100)
|
||||
return () => {
|
||||
clearTimeout(timeout)
|
||||
if (loadFunc === null) {
|
||||
store.isLoading = false
|
||||
} else {
|
||||
loadFunc(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,6 @@ import kanban from './modules/kanban'
|
|||
import tasks from './modules/tasks'
|
||||
import lists from './modules/lists'
|
||||
import attachments from './modules/attachments'
|
||||
import labels from './modules/labels'
|
||||
|
||||
import ListModel from '@/models/list'
|
||||
|
||||
|
|
@ -46,7 +45,6 @@ export const store = createStore<RootStoreState>({
|
|||
tasks,
|
||||
lists,
|
||||
attachments,
|
||||
labels,
|
||||
},
|
||||
state: () => ({
|
||||
loading: false,
|
||||
|
|
|
|||
|
|
@ -1,121 +0,0 @@
|
|||
import type { Module } from 'vuex'
|
||||
|
||||
import {i18n} from '@/i18n'
|
||||
import {success} from '@/message'
|
||||
import LabelService from '@/services/label'
|
||||
import {setLoading} from '@/store/helper'
|
||||
import type { LabelState, RootStoreState } from '@/store/types'
|
||||
import {getLabelsByIds, filterLabelsByQuery} from '@/helpers/labels'
|
||||
import {createNewIndexer} from '@/indexes'
|
||||
import type { ILabel } from '@/modelTypes/ILabel'
|
||||
|
||||
const {add, remove, update} = createNewIndexer('labels', ['title', 'description'])
|
||||
|
||||
async function getAllLabels(page = 1): Promise<ILabel[]> {
|
||||
const labelService = new LabelService()
|
||||
const labels = await labelService.getAll({}, {}, page) as ILabel[]
|
||||
if (page < labelService.totalPages) {
|
||||
const nextLabels = await getAllLabels(page + 1)
|
||||
return labels.concat(nextLabels)
|
||||
} else {
|
||||
return labels
|
||||
}
|
||||
}
|
||||
|
||||
const LabelStore : Module<LabelState, RootStoreState> = {
|
||||
namespaced: true,
|
||||
state: () => ({
|
||||
labels: {},
|
||||
loaded: false,
|
||||
}),
|
||||
mutations: {
|
||||
setLabels(state, labels: ILabel[]) {
|
||||
labels.forEach(l => {
|
||||
state.labels[l.id] = l
|
||||
add(l)
|
||||
})
|
||||
},
|
||||
setLabel(state, label: ILabel) {
|
||||
state.labels[label.id] = label
|
||||
update(label)
|
||||
},
|
||||
removeLabelById(state, label: ILabel) {
|
||||
remove(label)
|
||||
delete state.labels[label.id]
|
||||
},
|
||||
setLoaded(state, loaded: boolean) {
|
||||
state.loaded = loaded
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
getLabelsByIds(state) {
|
||||
return (ids: ILabel['id'][]) => getLabelsByIds(state, ids)
|
||||
},
|
||||
filterLabelsByQuery(state) {
|
||||
return (labelsToHide: ILabel[], query: string) => filterLabelsByQuery(state, labelsToHide, query)
|
||||
},
|
||||
getLabelsByExactTitles(state) {
|
||||
return labelTitles => Object
|
||||
.values(state.labels)
|
||||
.filter(({title}) => labelTitles.some(l => l.toLowerCase() === title.toLowerCase()))
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async loadAllLabels(ctx, {forceLoad} = {}) {
|
||||
if (ctx.state.loaded && !forceLoad) {
|
||||
return
|
||||
}
|
||||
|
||||
const cancel = setLoading(ctx, 'labels')
|
||||
|
||||
try {
|
||||
const labels = await getAllLabels()
|
||||
ctx.commit('setLabels', labels)
|
||||
ctx.commit('setLoaded', true)
|
||||
return labels
|
||||
} finally {
|
||||
cancel()
|
||||
}
|
||||
},
|
||||
async deleteLabel(ctx, label: ILabel) {
|
||||
const cancel = setLoading(ctx, 'labels')
|
||||
const labelService = new LabelService()
|
||||
|
||||
try {
|
||||
const result = await labelService.delete(label)
|
||||
ctx.commit('removeLabelById', label)
|
||||
success({message: i18n.global.t('label.deleteSuccess')})
|
||||
return result
|
||||
} finally {
|
||||
cancel()
|
||||
}
|
||||
},
|
||||
async updateLabel(ctx, label: ILabel) {
|
||||
const cancel = setLoading(ctx, 'labels')
|
||||
const labelService = new LabelService()
|
||||
|
||||
try {
|
||||
const newLabel = await labelService.update(label)
|
||||
ctx.commit('setLabel', newLabel)
|
||||
success({message: i18n.global.t('label.edit.success')})
|
||||
return newLabel
|
||||
} finally {
|
||||
cancel()
|
||||
}
|
||||
},
|
||||
async createLabel(ctx, label: ILabel) {
|
||||
const cancel = setLoading(ctx, 'labels')
|
||||
const labelService = new LabelService()
|
||||
|
||||
try {
|
||||
const newLabel = await labelService.create(label)
|
||||
ctx.commit('setLabel', newLabel)
|
||||
return newLabel
|
||||
} finally {
|
||||
cancel()
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default LabelStore
|
||||
|
|
@ -25,6 +25,7 @@ import type { IAttachment } from '@/modelTypes/IAttachment'
|
|||
import type { IList } from '@/modelTypes/IList'
|
||||
|
||||
import type { RootStoreState, TaskState } from '@/store/types'
|
||||
import { useLabelStore } from '@/stores/labels'
|
||||
|
||||
// IDEA: maybe use a small fuzzy search here to prevent errors
|
||||
function findPropertyByValue(object, key, value) {
|
||||
|
|
@ -268,22 +269,19 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
|||
},
|
||||
|
||||
// Do everything that is involved in finding, creating and adding the label to the task
|
||||
async addLabelsToTask({rootState, dispatch}, {
|
||||
task,
|
||||
parsedLabels,
|
||||
}) {
|
||||
async addLabelsToTask(_, { task, parsedLabels }) {
|
||||
if (parsedLabels.length <= 0) {
|
||||
return task
|
||||
}
|
||||
|
||||
const {labels} = rootState.labels
|
||||
const labelStore = useLabelStore()
|
||||
|
||||
const labelAddsToWaitFor = parsedLabels.map(async labelTitle => {
|
||||
let label = validateLabel(labels, labelTitle)
|
||||
let label = validateLabel(labelStore.labels, labelTitle)
|
||||
if (typeof label === 'undefined') {
|
||||
// label not found, create it
|
||||
const labelModel = new LabelModel({title: labelTitle})
|
||||
label = await dispatch('labels/createLabel', labelModel, {root: true})
|
||||
label = await labelStore.createLabel(labelModel)
|
||||
}
|
||||
|
||||
return addLabelToTask(task, label)
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ export interface LabelState {
|
|||
labels: {
|
||||
[id: ILabel['id']]: ILabel
|
||||
},
|
||||
loaded: boolean,
|
||||
isLoading: boolean,
|
||||
}
|
||||
|
||||
export interface ListState {
|
||||
|
|
|
|||
Reference in a new issue