fix(tasks): don't allow adding the same assignee multiple times
See https://community.vikunja.io/t/task-can-be-assigned-twice-or-more-to-the-same-user/883
This commit is contained in:
parent
d4c179c862
commit
bc1e366750
2 changed files with 64 additions and 45 deletions
|
@ -28,7 +28,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, shallowReactive, watch, type PropType} from 'vue'
|
import {ref, shallowReactive, watch, nextTick, type PropType} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import User from '@/components/misc/user.vue'
|
import User from '@/components/misc/user.vue'
|
||||||
|
@ -43,22 +43,22 @@ import {useTaskStore} from '@/stores/tasks'
|
||||||
import type {IUser} from '@/modelTypes/IUser'
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
taskId: {
|
taskId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
listId: {
|
listId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Array as PropType<IUser[]>,
|
type: Array as PropType<IUser[]>,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
const taskStore = useTaskStore()
|
const taskStore = useTaskStore()
|
||||||
|
@ -67,6 +67,7 @@ const {t} = useI18n({useScope: 'global'})
|
||||||
const listUserService = shallowReactive(new ListUserService())
|
const listUserService = shallowReactive(new ListUserService())
|
||||||
const foundUsers = ref([])
|
const foundUsers = ref([])
|
||||||
const assignees = ref<IUser[]>([])
|
const assignees = ref<IUser[]>([])
|
||||||
|
let isAdding = false
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
|
@ -80,9 +81,19 @@ watch(
|
||||||
)
|
)
|
||||||
|
|
||||||
async function addAssignee(user: IUser) {
|
async function addAssignee(user: IUser) {
|
||||||
await taskStore.addAssignee({user: user, taskId: props.taskId})
|
if (isAdding) {
|
||||||
emit('update:modelValue', assignees.value)
|
return
|
||||||
success({message: t('task.assignee.assignSuccess')})
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
nextTick(() => isAdding = true)
|
||||||
|
|
||||||
|
await taskStore.addAssignee({user: user, taskId: props.taskId})
|
||||||
|
emit('update:modelValue', assignees.value)
|
||||||
|
success({message: t('task.assignee.assignSuccess')})
|
||||||
|
} finally {
|
||||||
|
nextTick(() => isAdding = false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function removeAssignee(user: IUser) {
|
async function removeAssignee(user: IUser) {
|
||||||
|
@ -119,6 +130,7 @@ function clearAllFoundUsers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const multiselect = ref()
|
const multiselect = ref()
|
||||||
|
|
||||||
function focus() {
|
function focus() {
|
||||||
multiselect.value.focus()
|
multiselect.value.focus()
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,32 +171,39 @@ export const useTaskStore = defineStore('task', {
|
||||||
user: IUser,
|
user: IUser,
|
||||||
taskId: ITask['id']
|
taskId: ITask['id']
|
||||||
}) {
|
}) {
|
||||||
const kanbanStore = useKanbanStore()
|
const cancel = setModuleLoading(this)
|
||||||
const taskAssigneeService = new TaskAssigneeService()
|
|
||||||
const r = await taskAssigneeService.create(new TaskAssigneeModel({
|
|
||||||
userId: user.id,
|
|
||||||
taskId: taskId,
|
|
||||||
}))
|
|
||||||
const t = kanbanStore.getTaskById(taskId)
|
|
||||||
if (t.task === null) {
|
|
||||||
// Don't try further adding a label if the task is not in kanban
|
|
||||||
// Usually this means the kanban board hasn't been accessed until now.
|
|
||||||
// Vuex seems to have its difficulties with that, so we just log the error and fail silently.
|
|
||||||
console.debug('Could not add assignee to task in kanban, task not found', t)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
kanbanStore.setTaskInBucketByIndex({
|
try {
|
||||||
...t,
|
const kanbanStore = useKanbanStore()
|
||||||
task: {
|
const taskAssigneeService = new TaskAssigneeService()
|
||||||
...t.task,
|
const r = await taskAssigneeService.create(new TaskAssigneeModel({
|
||||||
assignees: [
|
userId: user.id,
|
||||||
...t.task.assignees,
|
taskId: taskId,
|
||||||
user,
|
}))
|
||||||
],
|
const t = kanbanStore.getTaskById(taskId)
|
||||||
},
|
if (t.task === null) {
|
||||||
})
|
// Don't try further adding a label if the task is not in kanban
|
||||||
return r
|
// Usually this means the kanban board hasn't been accessed until now.
|
||||||
|
// Vuex seems to have its difficulties with that, so we just log the error and fail silently.
|
||||||
|
console.debug('Could not add assignee to task in kanban, task not found', t)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
kanbanStore.setTaskInBucketByIndex({
|
||||||
|
...t,
|
||||||
|
task: {
|
||||||
|
...t.task,
|
||||||
|
assignees: [
|
||||||
|
...t.task.assignees,
|
||||||
|
user,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return r
|
||||||
|
} finally {
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async removeAssignee({
|
async removeAssignee({
|
||||||
|
|
Loading…
Reference in a new issue