fix(quick add magic): don't create a new label multiple times if it is used in multiple tasks

Resolves https://github.com/go-vikunja/frontend/issues/94
This commit is contained in:
kolaente 2022-12-04 20:19:43 +01:00
parent 33494cab6b
commit 463d22b07c
Signed by untrusted user: konrad
GPG Key ID: F40E70337AB24C9B
3 changed files with 42 additions and 16 deletions

View File

@ -53,6 +53,7 @@ import {RELATION_KIND} from '@/types/IRelationKind'
import {useAuthStore} from '@/stores/auth'
import {useTaskStore} from '@/stores/tasks'
import {useAutoHeightTextarea} from '@/composables/useAutoHeightTextarea'
import {getLabelsFromPrefix} from '@/modules/parseTaskText'
const props = defineProps({
defaultPosition: {
@ -82,6 +83,7 @@ function resetEmptyTitleError(e) {
}
const loading = computed(() => taskStore.isLoading)
async function addTask() {
if (newTaskTitle.value === '') {
errorMessage.value = t('list.create.addTitleRequired')
@ -98,11 +100,18 @@ async function addTask() {
// by quick add magic.
const createdTasks: { [key: ITask['title']]: ITask } = {}
const tasksToCreate = parseSubtasksViaIndention(newTaskTitle.value)
// We ensure all labels exist prior to passing them down to the create task method
// In the store it will only ever see one task at a time so there's no way to reliably
// check if a new label was created before (because everything happens async).
const allLabels = tasksToCreate.map(({title}) => getLabelsFromPrefix(title) ?? [])
await taskStore.ensureLabelsExist(allLabels.flat())
const newTasks = tasksToCreate.map(async ({title, list}) => {
if (title === '') {
return
}
// If the task has a list specified, make sure to use it
let listId = null
if (list !== null) {

View File

@ -72,7 +72,7 @@ export const parseTaskText = (text: string, prefixesMode: PrefixMode = PrefixMod
return result
}
result.labels = getItemsFromPrefix(text, prefixes.label)
result.labels = getLabelsFromPrefix(text, prefixes.label) ?? []
result.text = cleanupItemText(result.text, result.labels, prefixes.label)
result.list = getListFromPrefix(result.text, prefixes.list)
@ -142,6 +142,17 @@ export const getListFromPrefix = (text: string, listPrefix: string | null = null
return lists.length > 0 ? lists[0] : null
}
export const getLabelsFromPrefix = (text: string, listPrefix: string | null = null): string[] | null => {
if (listPrefix === null) {
const prefixes = PREFIXES[getQuickAddMagicMode()]
if (prefixes === undefined) {
return null
}
listPrefix = prefixes.label
}
return getItemsFromPrefix(text, listPrefix)
}
const getPriority = (text: string, prefix: string): number | null => {
const ps = getItemsFromPrefix(text, prefix)
if (ps.length === 0) {

View File

@ -1,5 +1,5 @@
import {computed, ref} from 'vue'
import {defineStore, acceptHMRUpdate} from 'pinia'
import {acceptHMRUpdate, defineStore} from 'pinia'
import router from '@/router'
import {formatISO} from 'date-fns'
@ -14,8 +14,8 @@ import {parseTaskText} from '@/modules/parseTaskText'
import TaskAssigneeModel from '@/models/taskAssignee'
import LabelTaskModel from '@/models/labelTask'
import TaskModel from '@/models/task'
import LabelTask from '@/models/labelTask'
import TaskModel from '@/models/task'
import LabelModel from '@/models/label'
import type {ILabel} from '@/modelTypes/ILabel'
@ -306,6 +306,20 @@ export const useTaskStore = defineStore('task', () => {
return response
}
async function ensureLabelsExist(labels: string[]): Promise<LabelModel[]> {
const all = [...new Set(labels)]
const mustCreateLabel = all.map(async labelTitle => {
let label = validateLabel(Object.values(labelStore.labels), labelTitle)
if (typeof label === 'undefined') {
// label not found, create it
const labelModel = new LabelModel({title: labelTitle})
label = await labelStore.createLabel(labelModel)
}
return label
})
return Promise.all(mustCreateLabel)
}
// Do everything that is involved in finding, creating and adding the label to the task
async function addLabelsToTask(
@ -316,16 +330,8 @@ export const useTaskStore = defineStore('task', () => {
return task
}
const labelAddsToWaitFor = parsedLabels.map(async labelTitle => {
let label = validateLabel(Object.values(labelStore.labels), labelTitle)
if (typeof label === 'undefined') {
// label not found, create it
const labelModel = new LabelModel({title: labelTitle})
label = await labelStore.createLabel(labelModel)
}
return addLabelToTask(task, label)
})
const labels = await ensureLabelsExist(parsedLabels)
const labelAddsToWaitFor = labels.map(async l => addLabelToTask(task, l))
// This waits until all labels are created and added to the task
await Promise.all(labelAddsToWaitFor)
@ -402,11 +408,10 @@ export const useTaskStore = defineStore('task', () => {
const taskService = new TaskService()
try {
const createdTask = await taskService.create(task)
const result = await addLabelsToTask({
return await addLabelsToTask({
task: createdTask,
parsedLabels: parsedTask.labels,
})
return result
} finally {
cancel()
}
@ -438,6 +443,7 @@ export const useTaskStore = defineStore('task', () => {
createNewTask,
setCoverImage,
findListId,
ensureLabelsExist,
}
})