feat: port tasks store to pinia
This commit is contained in:
parent
1fdda07f65
commit
34ffd1d572
20 changed files with 157 additions and 128 deletions
|
@ -73,6 +73,7 @@ import {PREFIXES} from '@/modules/parseTaskText'
|
||||||
import {useListStore} from '@/stores/lists'
|
import {useListStore} from '@/stores/lists'
|
||||||
import {useNamespaceStore} from '@/stores/namespaces'
|
import {useNamespaceStore} from '@/stores/namespaces'
|
||||||
import {useLabelStore} from '@/stores/labels'
|
import {useLabelStore} from '@/stores/labels'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
const TYPE_LIST = 'list'
|
const TYPE_LIST = 'list'
|
||||||
const TYPE_TASK = 'task'
|
const TYPE_TASK = 'task'
|
||||||
|
@ -412,7 +413,8 @@ export default defineComponent({
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const task = await this.$store.dispatch('tasks/createNewTask', {
|
const taskStore = useTaskStore()
|
||||||
|
const task = await taskStore.createNewTask({
|
||||||
title: this.query,
|
title: this.query,
|
||||||
listId: this.currentList.id,
|
listId: this.currentList.id,
|
||||||
})
|
})
|
||||||
|
|
|
@ -43,12 +43,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, watch, unref, computed} from 'vue'
|
import {ref, watch, unref, computed} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
import {useStore} from '@/store'
|
|
||||||
import {tryOnMounted, debouncedWatch, useWindowSize, type MaybeRef} from '@vueuse/core'
|
import {tryOnMounted, debouncedWatch, useWindowSize, type MaybeRef} from '@vueuse/core'
|
||||||
|
|
||||||
import QuickAddMagic from '@/components/tasks/partials/quick-add-magic.vue'
|
import QuickAddMagic from '@/components/tasks/partials/quick-add-magic.vue'
|
||||||
import {LOADING, LOADING_MODULE} from '@/store/mutation-types'
|
|
||||||
import {useAuthStore} from '@/stores/auth'
|
import {useAuthStore} from '@/stores/auth'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
function cleanupTitle(title: string) {
|
function cleanupTitle(title: string) {
|
||||||
return title.replace(/^((\* |\+ |- )(\[ \] )?)/g, '')
|
return title.replace(/^((\* |\+ |- )(\[ \] )?)/g, '')
|
||||||
|
@ -135,8 +134,8 @@ const newTaskTitle = ref('')
|
||||||
const newTaskInput = useAutoHeightTextarea(newTaskTitle)
|
const newTaskInput = useAutoHeightTextarea(newTaskTitle)
|
||||||
|
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
const store = useStore()
|
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
|
const taskStore = useTaskStore()
|
||||||
|
|
||||||
const errorMessage = ref('')
|
const errorMessage = ref('')
|
||||||
|
|
||||||
|
@ -149,7 +148,7 @@ function resetEmptyTitleError(e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const loading = computed(() => store.state[LOADING] && store.state[LOADING_MODULE] === 'tasks')
|
const loading = computed(() => taskStore.isLoading)
|
||||||
async function addTask() {
|
async function addTask() {
|
||||||
if (newTaskTitle.value === '') {
|
if (newTaskTitle.value === '') {
|
||||||
errorMessage.value = t('list.create.addTitleRequired')
|
errorMessage.value = t('list.create.addTitleRequired')
|
||||||
|
@ -168,7 +167,7 @@ async function addTask() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const task = await store.dispatch('tasks/createNewTask', {
|
const task = await taskStore.createNewTask({
|
||||||
title,
|
title,
|
||||||
listId: authStore.settings.defaultListId,
|
listId: authStore.settings.defaultListId,
|
||||||
position: props.defaultPosition,
|
position: props.defaultPosition,
|
||||||
|
|
|
@ -32,11 +32,12 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref,computed, watch, type PropType} from 'vue'
|
import {ref,computed, watch, type PropType} from 'vue'
|
||||||
import {useStore} from '@/store'
|
|
||||||
|
|
||||||
import Editor from '@/components/input/AsyncEditor'
|
import Editor from '@/components/input/AsyncEditor'
|
||||||
|
|
||||||
import type {ITask} from '@/modelTypes/ITask'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
import TaskModel from '@/models/task'
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -55,14 +56,14 @@ const props = defineProps({
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
const task = ref<ITask>({description: ''})
|
const task = ref<ITask>(new TaskModel())
|
||||||
const saved = ref(false)
|
const saved = ref(false)
|
||||||
|
|
||||||
// Since loading is global state, this variable ensures we're only showing the saving icon when saving the description.
|
// Since loading is global state, this variable ensures we're only showing the saving icon when saving the description.
|
||||||
const saving = ref(false)
|
const saving = ref(false)
|
||||||
|
|
||||||
const store = useStore()
|
const taskStore = useTaskStore()
|
||||||
const loading = computed(() => store.state.loading)
|
const loading = computed(() => taskStore.isLoading)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
|
@ -77,7 +78,7 @@ async function save() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// FIXME: don't update state from internal.
|
// FIXME: don't update state from internal.
|
||||||
task.value = await store.dispatch('tasks/update', task.value)
|
task.value = await taskStore.update(task.value)
|
||||||
emit('update:modelValue', task.value)
|
emit('update:modelValue', task.value)
|
||||||
|
|
||||||
saved.value = true
|
saved.value = true
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, shallowReactive, watch, type PropType} from 'vue'
|
import {ref, shallowReactive, watch, type PropType} from 'vue'
|
||||||
import {useStore} from '@/store'
|
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import User from '@/components/misc/user.vue'
|
import User from '@/components/misc/user.vue'
|
||||||
|
@ -39,6 +38,8 @@ import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import {includesById} from '@/helpers/utils'
|
import {includesById} from '@/helpers/utils'
|
||||||
import ListUserService from '@/services/listUsers'
|
import ListUserService from '@/services/listUsers'
|
||||||
import {success} from '@/message'
|
import {success} from '@/message'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
import type {IUser} from '@/modelTypes/IUser'
|
import type {IUser} from '@/modelTypes/IUser'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -60,7 +61,7 @@ const props = defineProps({
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
const store = useStore()
|
const taskStore = useTaskStore()
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
|
|
||||||
const listUserService = shallowReactive(new ListUserService())
|
const listUserService = shallowReactive(new ListUserService())
|
||||||
|
@ -79,13 +80,13 @@ watch(
|
||||||
)
|
)
|
||||||
|
|
||||||
async function addAssignee(user: IUser) {
|
async function addAssignee(user: IUser) {
|
||||||
await store.dispatch('tasks/addAssignee', {user: user, taskId: props.taskId})
|
await taskStore.addAssignee({user: user, taskId: props.taskId})
|
||||||
emit('update:modelValue', assignees.value)
|
emit('update:modelValue', assignees.value)
|
||||||
success({message: t('task.assignee.assignSuccess')})
|
success({message: t('task.assignee.assignSuccess')})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function removeAssignee(user: IUser) {
|
async function removeAssignee(user: IUser) {
|
||||||
await store.dispatch('tasks/removeAssignee', {user: user, taskId: props.taskId})
|
await taskStore.removeAssignee({user: user, taskId: props.taskId})
|
||||||
|
|
||||||
// Remove the assignee from the list
|
// Remove the assignee from the list
|
||||||
for (const a in assignees.value) {
|
for (const a in assignees.value) {
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {type PropType, ref, computed, shallowReactive, watch} from 'vue'
|
import {type PropType, ref, computed, shallowReactive, watch} from 'vue'
|
||||||
import {useStore} from '@/store'
|
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
|
|
||||||
import LabelModel from '@/models/label'
|
import LabelModel from '@/models/label'
|
||||||
|
@ -51,6 +50,7 @@ import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
import Multiselect from '@/components/input/multiselect.vue'
|
import Multiselect from '@/components/input/multiselect.vue'
|
||||||
import type {ILabel} from '@/modelTypes/ILabel'
|
import type {ILabel} from '@/modelTypes/ILabel'
|
||||||
import {useLabelStore} from '@/stores/labels'
|
import {useLabelStore} from '@/stores/labels'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
|
@ -69,7 +69,6 @@ const props = defineProps({
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
const store = useStore()
|
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
|
|
||||||
const labelTaskService = shallowReactive(new LabelTaskService())
|
const labelTaskService = shallowReactive(new LabelTaskService())
|
||||||
|
@ -87,6 +86,7 @@ watch(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const taskStore = useTaskStore()
|
||||||
const labelStore = useLabelStore()
|
const labelStore = useLabelStore()
|
||||||
|
|
||||||
const foundLabels = computed(() => labelStore.filterLabelsByQuery(labels.value, query.value))
|
const foundLabels = computed(() => labelStore.filterLabelsByQuery(labels.value, query.value))
|
||||||
|
@ -97,17 +97,13 @@ function findLabel(newQuery: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addLabel(label: ILabel, showNotification = true) {
|
async function addLabel(label: ILabel, showNotification = true) {
|
||||||
const bubble = () => {
|
|
||||||
emit('update:modelValue', labels.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.taskId === 0) {
|
if (props.taskId === 0) {
|
||||||
bubble()
|
emit('update:modelValue', labels.value)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await store.dispatch('tasks/addLabel', {label, taskId: props.taskId})
|
await taskStore.addLabel({label, taskId: props.taskId})
|
||||||
bubble()
|
emit('update:modelValue', labels.value)
|
||||||
if (showNotification) {
|
if (showNotification) {
|
||||||
success({message: t('task.label.addSuccess')})
|
success({message: t('task.label.addSuccess')})
|
||||||
}
|
}
|
||||||
|
@ -115,7 +111,7 @@ async function addLabel(label: ILabel, showNotification = true) {
|
||||||
|
|
||||||
async function removeLabel(label: ILabel) {
|
async function removeLabel(label: ILabel) {
|
||||||
if (props.taskId !== 0) {
|
if (props.taskId !== 0) {
|
||||||
await store.dispatch('tasks/removeLabel', {label, taskId: props.taskId})
|
await taskStore.removeLabel({label, taskId: props.taskId})
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const l in labels.value) {
|
for (const l in labels.value) {
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, computed, type PropType} from 'vue'
|
import {ref, computed, type PropType} from 'vue'
|
||||||
import {useStore} from '@/store'
|
|
||||||
import {useRouter} from 'vue-router'
|
import {useRouter} from 'vue-router'
|
||||||
|
|
||||||
import BaseButton from '@/components/base/BaseButton.vue'
|
import BaseButton from '@/components/base/BaseButton.vue'
|
||||||
|
@ -48,6 +47,7 @@ import {useCopyToClipboard} from '@/composables/useCopyToClipboard'
|
||||||
|
|
||||||
import type {ITask} from '@/modelTypes/ITask'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
import ColorBubble from '@/components/misc/colorBubble.vue'
|
import ColorBubble from '@/components/misc/colorBubble.vue'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
task: {
|
task: {
|
||||||
|
@ -72,8 +72,8 @@ async function copyUrl() {
|
||||||
await copy(absoluteURL)
|
await copy(absoluteURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
const store = useStore()
|
const taskStore = useTaskStore()
|
||||||
const loading = computed(() => store.state.loading)
|
const loading = computed(() => taskStore.isLoading)
|
||||||
|
|
||||||
const textIdentifier = computed(() => props.task?.getTextIdentifier() || '')
|
const textIdentifier = computed(() => props.task?.getTextIdentifier() || '')
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ async function save(title: string) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
saving.value = true
|
saving.value = true
|
||||||
const newTask = await store.dispatch('tasks/update', {
|
const newTask = await taskStore.update({
|
||||||
...props.task,
|
...props.task,
|
||||||
title,
|
title,
|
||||||
})
|
})
|
||||||
|
|
|
@ -78,6 +78,7 @@ import type {ITask} from '@/modelTypes/ITask'
|
||||||
|
|
||||||
import {formatDateLong, formatISO, formatDateSince} from '@/helpers/time/formatDate'
|
import {formatDateLong, formatISO, formatDateSince} from '@/helpers/time/formatDate'
|
||||||
import {colorIsDark} from '@/helpers/color/colorIsDark'
|
import {colorIsDark} from '@/helpers/color/colorIsDark'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'kanban-card',
|
name: 'kanban-card',
|
||||||
|
@ -121,7 +122,7 @@ export default defineComponent({
|
||||||
this.loadingInternal = true
|
this.loadingInternal = true
|
||||||
try {
|
try {
|
||||||
const done = !task.done
|
const done = !task.done
|
||||||
await this.$store.dispatch('tasks/update', {
|
await useTaskStore().update({
|
||||||
...task,
|
...task,
|
||||||
done,
|
done,
|
||||||
})
|
})
|
||||||
|
|
|
@ -149,7 +149,6 @@
|
||||||
import {ref, reactive, shallowReactive, watch, computed, type PropType} from 'vue'
|
import {ref, reactive, shallowReactive, watch, computed, type PropType} from 'vue'
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
import {useRoute} from 'vue-router'
|
import {useRoute} from 'vue-router'
|
||||||
import {useStore} from '@/store'
|
|
||||||
|
|
||||||
import TaskService from '@/services/task'
|
import TaskService from '@/services/task'
|
||||||
import TaskModel from '@/models/task'
|
import TaskModel from '@/models/task'
|
||||||
|
@ -167,6 +166,7 @@ import Fancycheckbox from '@/components/input/fancycheckbox.vue'
|
||||||
import {useNamespaceStore} from '@/stores/namespaces'
|
import {useNamespaceStore} from '@/stores/namespaces'
|
||||||
|
|
||||||
import {error, success} from '@/message'
|
import {error, success} from '@/message'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
taskId: {
|
taskId: {
|
||||||
|
@ -190,7 +190,7 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const store = useStore()
|
const taskStore = useTaskStore()
|
||||||
const namespaceStore = useNamespaceStore()
|
const namespaceStore = useNamespaceStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
|
@ -344,7 +344,7 @@ async function createAndRelateTask(title: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleTaskDone(task: ITask) {
|
async function toggleTaskDone(task: ITask) {
|
||||||
await store.dispatch('tasks/update', task)
|
await taskStore.update(task)
|
||||||
|
|
||||||
// Find the task in the list and update it so that it is correctly strike through
|
// Find the task in the list and update it so that it is correctly strike through
|
||||||
Object.entries(relatedTasks.value).some(([kind, tasks]) => {
|
Object.entries(relatedTasks.value).some(([kind, tasks]) => {
|
||||||
|
|
|
@ -119,6 +119,7 @@ import {formatDateSince, formatISO, formatDateLong} from '@/helpers/time/formatD
|
||||||
import ColorBubble from '@/components/misc/colorBubble.vue'
|
import ColorBubble from '@/components/misc/colorBubble.vue'
|
||||||
import {useListStore} from '@/stores/lists'
|
import {useListStore} from '@/stores/lists'
|
||||||
import {useNamespaceStore} from '@/stores/namespaces'
|
import {useNamespaceStore} from '@/stores/namespaces'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'singleTaskInList',
|
name: 'singleTaskInList',
|
||||||
|
@ -208,7 +209,7 @@ export default defineComponent({
|
||||||
|
|
||||||
async markAsDone(checked: boolean) {
|
async markAsDone(checked: boolean) {
|
||||||
const updateFunc = async () => {
|
const updateFunc = async () => {
|
||||||
const task = await this.$store.dispatch('tasks/update', this.task)
|
const task = await useTaskStore().update(this.task)
|
||||||
this.task = task
|
this.task = task
|
||||||
this.$emit('task-updated', task)
|
this.$emit('task-updated', task)
|
||||||
this.$message.success({
|
this.$message.success({
|
||||||
|
|
|
@ -2,7 +2,7 @@ import AttachmentModel from '@/models/attachment'
|
||||||
import type {IAttachment} from '@/modelTypes/IAttachment'
|
import type {IAttachment} from '@/modelTypes/IAttachment'
|
||||||
|
|
||||||
import AttachmentService from '@/services/attachment'
|
import AttachmentService from '@/services/attachment'
|
||||||
import { store } from '@/store'
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
export function uploadFile(taskId: number, file: File, onSuccess: (url: string) => void) {
|
export function uploadFile(taskId: number, file: File, onSuccess: (url: string) => void) {
|
||||||
const attachmentService = new AttachmentService()
|
const attachmentService = new AttachmentService()
|
||||||
|
@ -22,7 +22,7 @@ export async function uploadFiles(
|
||||||
console.debug(`Uploaded attachments for task ${taskId}, response was`, response)
|
console.debug(`Uploaded attachments for task ${taskId}, response was`, response)
|
||||||
|
|
||||||
response.success?.map((attachment: IAttachment) => {
|
response.success?.map((attachment: IAttachment) => {
|
||||||
store.dispatch('tasks/addTaskAttachment', {
|
useTaskStore().addTaskAttachment({
|
||||||
taskId,
|
taskId,
|
||||||
attachment,
|
attachment,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import {createApp} from 'vue'
|
import {createApp} from 'vue'
|
||||||
|
|
||||||
import App from './App.vue'
|
import pinia from './pinia'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import { createPinia } from 'pinia'
|
import App from './App.vue'
|
||||||
|
|
||||||
import {error, success} from './message'
|
import {error, success} from './message'
|
||||||
|
|
||||||
|
@ -105,7 +105,6 @@ if (window.SENTRY_ENABLED) {
|
||||||
import('./sentry').then(sentry => sentry.default(app, router))
|
import('./sentry').then(sentry => sentry.default(app, router))
|
||||||
}
|
}
|
||||||
|
|
||||||
const pinia = createPinia()
|
|
||||||
app.use(pinia)
|
app.use(pinia)
|
||||||
|
|
||||||
app.use(store, key) // pass the injection key
|
app.use(store, key) // pass the injection key
|
||||||
|
|
5
src/pinia.ts
Normal file
5
src/pinia.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import {createPinia} from 'pinia'
|
||||||
|
|
||||||
|
const pinia = createPinia()
|
||||||
|
|
||||||
|
export default pinia
|
|
@ -21,6 +21,7 @@ import ListService from '../services/list'
|
||||||
import {checkAndSetApiUrl} from '@/helpers/checkAndSetApiUrl'
|
import {checkAndSetApiUrl} from '@/helpers/checkAndSetApiUrl'
|
||||||
|
|
||||||
import type { RootStoreState, StoreState } from './types'
|
import type { RootStoreState, StoreState } from './types'
|
||||||
|
import pinia from '@/pinia'
|
||||||
import {useAuthStore} from '@/stores/auth'
|
import {useAuthStore} from '@/stores/auth'
|
||||||
|
|
||||||
export const key: InjectionKey<Store<StoreState>> = Symbol()
|
export const key: InjectionKey<Store<StoreState>> = Symbol()
|
||||||
|
@ -130,7 +131,7 @@ export const store = createStore<RootStoreState>({
|
||||||
},
|
},
|
||||||
async loadApp() {
|
async loadApp() {
|
||||||
await checkAndSetApiUrl(window.API_URL)
|
await checkAndSetApiUrl(window.API_URL)
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore(pinia)
|
||||||
await authStore.checkAuth()
|
await authStore.checkAuth()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -94,7 +94,9 @@ export interface NamespaceState {
|
||||||
isLoading: boolean,
|
isLoading: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TaskState {}
|
export interface TaskState {
|
||||||
|
isLoading: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export type StoreState = RootStoreState & {
|
export type StoreState = RootStoreState & {
|
||||||
|
|
|
@ -124,7 +124,7 @@ export const useLabelStore = defineStore('label', {
|
||||||
const labelService = new LabelService()
|
const labelService = new LabelService()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const newLabel = await labelService.create(label)
|
const newLabel = await labelService.create(label) as ILabel
|
||||||
this.setLabel(newLabel)
|
this.setLabel(newLabel)
|
||||||
return newLabel
|
return newLabel
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Module } from 'vuex'
|
import {defineStore, acceptHMRUpdate} from 'pinia'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
import {formatISO} from 'date-fns'
|
import {formatISO} from 'date-fns'
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import LabelTaskService from '@/services/labelTask'
|
||||||
import UserService from '@/services/user'
|
import UserService from '@/services/user'
|
||||||
|
|
||||||
import {HAS_TASKS} from '../store/mutation-types'
|
import {HAS_TASKS} from '../store/mutation-types'
|
||||||
import {setLoading} from '../store/helper'
|
import {setLoadingPinia} from '../store/helper'
|
||||||
import {getQuickAddMagicMode} from '@/helpers/quickAddMagicMode'
|
import {getQuickAddMagicMode} from '@/helpers/quickAddMagicMode'
|
||||||
import {parseTaskText} from '@/modules/parseTaskText'
|
import {parseTaskText} from '@/modules/parseTaskText'
|
||||||
|
|
||||||
|
@ -24,11 +24,12 @@ import type { IUser } from '@/modelTypes/IUser'
|
||||||
import type {IAttachment} from '@/modelTypes/IAttachment'
|
import type {IAttachment} from '@/modelTypes/IAttachment'
|
||||||
import type {IList} from '@/modelTypes/IList'
|
import type {IList} from '@/modelTypes/IList'
|
||||||
|
|
||||||
import type { RootStoreState, TaskState } from '@/store/types'
|
import type {TaskState} from '@/store/types'
|
||||||
import {useLabelStore} from '@/stores/labels'
|
import {useLabelStore} from '@/stores/labels'
|
||||||
import {useListStore} from '@/stores/lists'
|
import {useListStore} from '@/stores/lists'
|
||||||
import {useAttachmentStore} from '@/stores/attachments'
|
import {useAttachmentStore} from '@/stores/attachments'
|
||||||
import {playPop} from '@/helpers/playPop'
|
import {playPop} from '@/helpers/playPop'
|
||||||
|
import {store} from '@/store'
|
||||||
|
|
||||||
// IDEA: maybe use a small fuzzy search here to prevent errors
|
// IDEA: maybe use a small fuzzy search here to prevent errors
|
||||||
function findPropertyByValue(object, key, value) {
|
function findPropertyByValue(object, key, value) {
|
||||||
|
@ -43,7 +44,7 @@ function validateUsername(users: IUser[], username: IUser['username']) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the label exists
|
// Check if the label exists
|
||||||
function validateLabel(labels: ILabel[], label: ILabel) {
|
function validateLabel(labels: ILabel[], label: string) {
|
||||||
return findPropertyByValue(labels, 'title', label)
|
return findPropertyByValue(labels, 'title', label)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ async function addLabelToTask(task: ITask, label: ILabel) {
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findAssignees(parsedTaskAssignees) {
|
async function findAssignees(parsedTaskAssignees: string[]) {
|
||||||
if (parsedTaskAssignees.length <= 0) {
|
if (parsedTaskAssignees.length <= 0) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
@ -74,30 +75,31 @@ async function findAssignees(parsedTaskAssignees) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const tasksStore : Module<TaskState, RootStoreState>= {
|
export const useTaskStore = defineStore('task', {
|
||||||
namespaced: true,
|
state: () : TaskState => ({
|
||||||
state: () => ({}),
|
isLoading: false,
|
||||||
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
async loadTasks(ctx, params) {
|
async loadTasks(params) {
|
||||||
const taskService = new TaskService()
|
const taskService = new TaskService()
|
||||||
|
|
||||||
const cancel = setLoading(ctx, 'tasks')
|
const cancel = setLoadingPinia(this)
|
||||||
try {
|
try {
|
||||||
const tasks = await taskService.getAll({}, params)
|
const tasks = await taskService.getAll({}, params)
|
||||||
ctx.commit(HAS_TASKS, tasks.length > 0, {root: true})
|
store.commit(HAS_TASKS, tasks.length > 0)
|
||||||
return tasks
|
return tasks
|
||||||
} finally {
|
} finally {
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async update(ctx, task: ITask) {
|
async update(task: ITask) {
|
||||||
const cancel = setLoading(ctx, 'tasks')
|
const cancel = setLoadingPinia(this)
|
||||||
|
|
||||||
const taskService = new TaskService()
|
const taskService = new TaskService()
|
||||||
try {
|
try {
|
||||||
const updatedTask = await taskService.update(task)
|
const updatedTask = await taskService.update(task)
|
||||||
ctx.commit('kanban/setTaskInBucket', updatedTask, {root: true})
|
store.commit('kanban/setTaskInBucket', updatedTask)
|
||||||
if (task.done) {
|
if (task.done) {
|
||||||
playPop()
|
playPop()
|
||||||
}
|
}
|
||||||
|
@ -107,23 +109,23 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async delete(ctx, task: ITask) {
|
async delete(task: ITask) {
|
||||||
const taskService = new TaskService()
|
const taskService = new TaskService()
|
||||||
const response = await taskService.delete(task)
|
const response = await taskService.delete(task)
|
||||||
ctx.commit('kanban/removeTaskInBucket', task, {root: true})
|
store.commit('kanban/removeTaskInBucket', task)
|
||||||
return response
|
return response
|
||||||
},
|
},
|
||||||
|
|
||||||
// Adds a task attachment in store.
|
// Adds a task attachment in store.
|
||||||
// This is an action to be able to commit other mutations
|
// This is an action to be able to commit other mutations
|
||||||
addTaskAttachment(ctx, {
|
addTaskAttachment({
|
||||||
taskId,
|
taskId,
|
||||||
attachment,
|
attachment,
|
||||||
}: {
|
}: {
|
||||||
taskId: ITask['id']
|
taskId: ITask['id']
|
||||||
attachment: IAttachment
|
attachment: IAttachment
|
||||||
}) {
|
}) {
|
||||||
const t = ctx.rootGetters['kanban/getTaskById'](taskId)
|
const t = store.getters['kanban/getTaskById'](taskId)
|
||||||
if (t.task !== null) {
|
if (t.task !== null) {
|
||||||
const attachments = [
|
const attachments = [
|
||||||
...t.task.attachments,
|
...t.task.attachments,
|
||||||
|
@ -137,24 +139,25 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
||||||
attachments,
|
attachments,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
ctx.commit('kanban/setTaskInBucketByIndex', newTask, {root: true})
|
store.commit('kanban/setTaskInBucketByIndex', newTask)
|
||||||
}
|
}
|
||||||
const attachmentStore = useAttachmentStore()
|
const attachmentStore = useAttachmentStore()
|
||||||
attachmentStore.add(attachment)
|
attachmentStore.add(attachment)
|
||||||
},
|
},
|
||||||
|
|
||||||
async addAssignee(ctx, {
|
async addAssignee({
|
||||||
user,
|
user,
|
||||||
taskId,
|
taskId,
|
||||||
}: {
|
}: {
|
||||||
user: IUser,
|
user: IUser,
|
||||||
taskId: ITask['id']
|
taskId: ITask['id']
|
||||||
}) {
|
}) {
|
||||||
const taskAssignee = new TaskAssigneeModel({userId: user.id, taskId: taskId})
|
|
||||||
|
|
||||||
const taskAssigneeService = new TaskAssigneeService()
|
const taskAssigneeService = new TaskAssigneeService()
|
||||||
const r = await taskAssigneeService.create(taskAssignee)
|
const r = await taskAssigneeService.create(new TaskAssigneeModel({
|
||||||
const t = ctx.rootGetters['kanban/getTaskById'](taskId)
|
userId: user.id,
|
||||||
|
taskId: taskId,
|
||||||
|
}))
|
||||||
|
const t = store.getters['kanban/getTaskById'](taskId)
|
||||||
if (t.task === null) {
|
if (t.task === null) {
|
||||||
// Don't try further adding a label if the task is not in kanban
|
// 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.
|
// Usually this means the kanban board hasn't been accessed until now.
|
||||||
|
@ -163,33 +166,32 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
const assignees = [
|
store.commit('kanban/setTaskInBucketByIndex', {
|
||||||
...t.task.assignees,
|
|
||||||
user,
|
|
||||||
]
|
|
||||||
|
|
||||||
ctx.commit('kanban/setTaskInBucketByIndex', {
|
|
||||||
...t,
|
...t,
|
||||||
task: {
|
task: {
|
||||||
...t.task,
|
...t.task,
|
||||||
assignees,
|
assignees: [
|
||||||
|
...t.task.assignees,
|
||||||
|
user,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}, {root: true})
|
})
|
||||||
return r
|
return r
|
||||||
},
|
},
|
||||||
|
|
||||||
async removeAssignee(ctx, {
|
async removeAssignee({
|
||||||
user,
|
user,
|
||||||
taskId,
|
taskId,
|
||||||
}: {
|
}: {
|
||||||
user: IUser,
|
user: IUser,
|
||||||
taskId: ITask['id']
|
taskId: ITask['id']
|
||||||
}) {
|
}) {
|
||||||
const taskAssignee = new TaskAssigneeModel({userId: user.id, taskId: taskId})
|
|
||||||
|
|
||||||
const taskAssigneeService = new TaskAssigneeService()
|
const taskAssigneeService = new TaskAssigneeService()
|
||||||
const response = await taskAssigneeService.delete(taskAssignee)
|
const response = await taskAssigneeService.delete(new TaskAssigneeModel({
|
||||||
const t = ctx.rootGetters['kanban/getTaskById'](taskId)
|
userId: user.id,
|
||||||
|
taskId: taskId,
|
||||||
|
}))
|
||||||
|
const t = store.getters['kanban/getTaskById'](taskId)
|
||||||
if (t.task === null) {
|
if (t.task === null) {
|
||||||
// Don't try further adding a label if the task is not in kanban
|
// 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.
|
// Usually this means the kanban board hasn't been accessed until now.
|
||||||
|
@ -200,29 +202,30 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
||||||
|
|
||||||
const assignees = t.task.assignees.filter(({ id }) => id !== user.id)
|
const assignees = t.task.assignees.filter(({ id }) => id !== user.id)
|
||||||
|
|
||||||
ctx.commit('kanban/setTaskInBucketByIndex', {
|
store.commit('kanban/setTaskInBucketByIndex', {
|
||||||
...t,
|
...t,
|
||||||
task: {
|
task: {
|
||||||
...t.task,
|
...t.task,
|
||||||
assignees,
|
assignees,
|
||||||
},
|
},
|
||||||
}, {root: true})
|
})
|
||||||
return response
|
return response
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async addLabel(ctx, {
|
async addLabel({
|
||||||
label,
|
label,
|
||||||
taskId,
|
taskId,
|
||||||
} : {
|
} : {
|
||||||
label: ILabel,
|
label: ILabel,
|
||||||
taskId: ITask['id']
|
taskId: ITask['id']
|
||||||
}) {
|
}) {
|
||||||
const labelTask = new LabelTaskModel({taskId, labelId: label.id})
|
|
||||||
|
|
||||||
const labelTaskService = new LabelTaskService()
|
const labelTaskService = new LabelTaskService()
|
||||||
const r = await labelTaskService.create(labelTask)
|
const r = await labelTaskService.create(new LabelTaskModel({
|
||||||
const t = ctx.rootGetters['kanban/getTaskById'](taskId)
|
taskId,
|
||||||
|
labelId: label.id,
|
||||||
|
}))
|
||||||
|
const t = store.getters['kanban/getTaskById'](taskId)
|
||||||
if (t.task === null) {
|
if (t.task === null) {
|
||||||
// Don't try further adding a label if the task is not in kanban
|
// 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.
|
// Usually this means the kanban board hasn't been accessed until now.
|
||||||
|
@ -231,28 +234,30 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
const labels = [
|
store.commit('kanban/setTaskInBucketByIndex', {
|
||||||
...t.task.labels,
|
|
||||||
label,
|
|
||||||
]
|
|
||||||
|
|
||||||
ctx.commit('kanban/setTaskInBucketByIndex', {
|
|
||||||
...t,
|
...t,
|
||||||
task: {
|
task: {
|
||||||
...t.task,
|
...t.task,
|
||||||
labels,
|
labels: [
|
||||||
|
...t.task.labels,
|
||||||
|
label,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}, {root: true})
|
})
|
||||||
|
|
||||||
return r
|
return r
|
||||||
},
|
},
|
||||||
|
|
||||||
async removeLabel(ctx, {label, taskId}) {
|
async removeLabel(
|
||||||
const labelTask = new LabelTaskModel({taskId, labelId: label.id})
|
{label, taskId}:
|
||||||
|
{label: ILabel, taskId: ITask['id']},
|
||||||
|
) {
|
||||||
const labelTaskService = new LabelTaskService()
|
const labelTaskService = new LabelTaskService()
|
||||||
const response = await labelTaskService.delete(labelTask)
|
const response = await labelTaskService.delete(new LabelTaskModel({
|
||||||
const t = ctx.rootGetters['kanban/getTaskById'](taskId)
|
taskId, labelId:
|
||||||
|
label.id,
|
||||||
|
}))
|
||||||
|
const t = store.getters['kanban/getTaskById'](taskId)
|
||||||
if (t.task === null) {
|
if (t.task === null) {
|
||||||
// Don't try further adding a label if the task is not in kanban
|
// 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.
|
// Usually this means the kanban board hasn't been accessed until now.
|
||||||
|
@ -264,19 +269,22 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
||||||
// Remove the label from the list
|
// Remove the label from the list
|
||||||
const labels = t.task.labels.filter(({ id }) => id !== label.id)
|
const labels = t.task.labels.filter(({ id }) => id !== label.id)
|
||||||
|
|
||||||
ctx.commit('kanban/setTaskInBucketByIndex', {
|
store.commit('kanban/setTaskInBucketByIndex', {
|
||||||
...t,
|
...t,
|
||||||
task: {
|
task: {
|
||||||
...t.task,
|
...t.task,
|
||||||
labels,
|
labels,
|
||||||
},
|
},
|
||||||
}, {root: true})
|
})
|
||||||
|
|
||||||
return response
|
return response
|
||||||
},
|
},
|
||||||
|
|
||||||
// Do everything that is involved in finding, creating and adding the label to the task
|
// Do everything that is involved in finding, creating and adding the label to the task
|
||||||
async addLabelsToTask(_, { task, parsedLabels }) {
|
async addLabelsToTask(
|
||||||
|
{ task, parsedLabels }:
|
||||||
|
{ task: ITask, parsedLabels: string[] },
|
||||||
|
) {
|
||||||
if (parsedLabels.length <= 0) {
|
if (parsedLabels.length <= 0) {
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
|
@ -299,10 +307,9 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
||||||
return task
|
return task
|
||||||
},
|
},
|
||||||
|
|
||||||
findListId(_, { list: listName, listId }: {
|
findListId(
|
||||||
list: string,
|
{ list: listName, listId }:
|
||||||
listId: IList['id']
|
{ list: string, listId: IList['id'] }) {
|
||||||
}) {
|
|
||||||
let foundListId = null
|
let foundListId = null
|
||||||
|
|
||||||
// Uses the following ways to get the list id of the new task:
|
// Uses the following ways to get the list id of the new task:
|
||||||
|
@ -320,7 +327,7 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
||||||
|
|
||||||
// 3. Otherwise use the id from the route parameter
|
// 3. Otherwise use the id from the route parameter
|
||||||
if (typeof router.currentRoute.value.params.listId !== 'undefined') {
|
if (typeof router.currentRoute.value.params.listId !== 'undefined') {
|
||||||
foundListId = parseInt(router.currentRoute.value.params.listId)
|
foundListId = Number(router.currentRoute.value.params.listId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. If none of the above worked, reject the promise with an error.
|
// 4. If none of the above worked, reject the promise with an error.
|
||||||
|
@ -331,7 +338,7 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
||||||
return foundListId
|
return foundListId
|
||||||
},
|
},
|
||||||
|
|
||||||
async createNewTask(ctx, {
|
async createNewTask({
|
||||||
title,
|
title,
|
||||||
bucketId,
|
bucketId,
|
||||||
listId,
|
listId,
|
||||||
|
@ -339,10 +346,10 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
||||||
} :
|
} :
|
||||||
Partial<ITask>,
|
Partial<ITask>,
|
||||||
) {
|
) {
|
||||||
const cancel = setLoading(ctx, 'tasks')
|
const cancel = setLoadingPinia(this)
|
||||||
const parsedTask = parseTaskText(title, getQuickAddMagicMode())
|
const parsedTask = parseTaskText(title, getQuickAddMagicMode())
|
||||||
|
|
||||||
const foundListId = await ctx.dispatch('findListId', {
|
const foundListId = await this.findListId({
|
||||||
list: parsedTask.list,
|
list: parsedTask.list,
|
||||||
listId: listId || 0,
|
listId: listId || 0,
|
||||||
})
|
})
|
||||||
|
@ -369,7 +376,7 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
||||||
|
|
||||||
const taskService = new TaskService()
|
const taskService = new TaskService()
|
||||||
const createdTask = await taskService.create(task)
|
const createdTask = await taskService.create(task)
|
||||||
const result = await ctx.dispatch('addLabelsToTask', {
|
const result = await this.addLabelsToTask({
|
||||||
task: createdTask,
|
task: createdTask,
|
||||||
parsedLabels: parsedTask.labels,
|
parsedLabels: parsedTask.labels,
|
||||||
})
|
})
|
||||||
|
@ -377,6 +384,9 @@ const tasksStore : Module<TaskState, RootStoreState>= {
|
||||||
return result
|
return result
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
|
|
||||||
export default tasksStore
|
// support hot reloading
|
||||||
|
if (import.meta.hot) {
|
||||||
|
import.meta.hot.accept(acceptHMRUpdate(useTaskStore, import.meta.hot))
|
||||||
|
}
|
|
@ -240,6 +240,7 @@ import {calculateItemPosition} from '../../helpers/calculateItemPosition'
|
||||||
import KanbanCard from '@/components/tasks/partials/kanban-card.vue'
|
import KanbanCard from '@/components/tasks/partials/kanban-card.vue'
|
||||||
import DropdownItem from '@/components/misc/dropdown-item.vue'
|
import DropdownItem from '@/components/misc/dropdown-item.vue'
|
||||||
import {isSavedFilter} from '@/helpers/savedFilter'
|
import {isSavedFilter} from '@/helpers/savedFilter'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
const DRAG_OPTIONS = {
|
const DRAG_OPTIONS = {
|
||||||
// sortable options
|
// sortable options
|
||||||
|
@ -433,7 +434,8 @@ export default defineComponent({
|
||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch('tasks/update', newTask)
|
const taskStore = useTaskStore()
|
||||||
|
await taskStore.update(newTask)
|
||||||
|
|
||||||
// Make sure the first and second task don't both get position 0 assigned
|
// Make sure the first and second task don't both get position 0 assigned
|
||||||
if(newTaskIndex === 0 && taskAfter !== null && taskAfter.kanbanPosition === 0) {
|
if(newTaskIndex === 0 && taskAfter !== null && taskAfter.kanbanPosition === 0) {
|
||||||
|
@ -445,7 +447,7 @@ export default defineComponent({
|
||||||
taskAfterAfter !== null ? taskAfterAfter.kanbanPosition : null,
|
taskAfterAfter !== null ? taskAfterAfter.kanbanPosition : null,
|
||||||
)
|
)
|
||||||
|
|
||||||
await this.$store.dispatch('tasks/update', newTaskAfter)
|
await taskStore.update(newTaskAfter)
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
this.taskUpdating[task.id] = false
|
this.taskUpdating[task.id] = false
|
||||||
|
@ -464,7 +466,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
this.newTaskError[bucketId] = false
|
this.newTaskError[bucketId] = false
|
||||||
|
|
||||||
const task = await this.$store.dispatch('tasks/createNewTask', {
|
const task = await useTaskStore().createNewTask({
|
||||||
title: this.newTaskText,
|
title: this.newTaskText,
|
||||||
bucketId,
|
bucketId,
|
||||||
listId: this.listId,
|
listId: this.listId,
|
||||||
|
|
|
@ -139,7 +139,7 @@ export default { name: 'List' }
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, computed, toRef, nextTick, onMounted} from 'vue'
|
import {ref, computed, toRef, nextTick, onMounted, type PropType} from 'vue'
|
||||||
import draggable from 'zhyswan-vuedraggable'
|
import draggable from 'zhyswan-vuedraggable'
|
||||||
import {useRoute, useRouter} from 'vue-router'
|
import {useRoute, useRouter} from 'vue-router'
|
||||||
|
|
||||||
|
@ -161,6 +161,9 @@ import {RIGHTS as Rights} from '@/constants/rights'
|
||||||
import {calculateItemPosition} from '@/helpers/calculateItemPosition'
|
import {calculateItemPosition} from '@/helpers/calculateItemPosition'
|
||||||
import type {ITask} from '@/modelTypes/ITask'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
import {isSavedFilter} from '@/helpers/savedFilter'
|
import {isSavedFilter} from '@/helpers/savedFilter'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
|
import type {IList} from '@/modelTypes/IList'
|
||||||
|
|
||||||
function sortTasks(tasks: ITask[]) {
|
function sortTasks(tasks: ITask[]) {
|
||||||
if (tasks === null || Array.isArray(tasks) && tasks.length === 0) {
|
if (tasks === null || Array.isArray(tasks) && tasks.length === 0) {
|
||||||
|
@ -182,7 +185,7 @@ function sortTasks(tasks: ITask[]) {
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
listId: {
|
listId: {
|
||||||
type: Number,
|
type: Number as PropType<IList['id']>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -224,6 +227,7 @@ const firstNewPosition = computed(() => {
|
||||||
return calculateItemPosition(null, tasks.value[0].position)
|
return calculateItemPosition(null, tasks.value[0].position)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const taskStore = useTaskStore()
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const list = computed(() => store.state.currentList)
|
const list = computed(() => store.state.currentList)
|
||||||
|
|
||||||
|
@ -238,6 +242,7 @@ onMounted(async () => {
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
function searchTasks() {
|
function searchTasks() {
|
||||||
// Only search if the search term changed
|
// Only search if the search term changed
|
||||||
if (route.query as unknown as string === searchTerm.value) {
|
if (route.query as unknown as string === searchTerm.value) {
|
||||||
|
@ -309,7 +314,7 @@ async function saveTaskPosition(e) {
|
||||||
position: calculateItemPosition(taskBefore !== null ? taskBefore.position : null, taskAfter !== null ? taskAfter.position : null),
|
position: calculateItemPosition(taskBefore !== null ? taskBefore.position : null, taskAfter !== null ? taskAfter.position : null),
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedTask = await this.$store.dispatch('tasks/update', newTask)
|
const updatedTask = await taskStore.update(newTask)
|
||||||
tasks.value[e.newIndex] = updatedTask
|
tasks.value[e.newIndex] = updatedTask
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -60,9 +60,11 @@ import {LOADING, LOADING_MODULE} from '@/store/mutation-types'
|
||||||
import LlamaCool from '@/assets/llama-cool.svg?component'
|
import LlamaCool from '@/assets/llama-cool.svg?component'
|
||||||
import type {ITask} from '@/modelTypes/ITask'
|
import type {ITask} from '@/modelTypes/ITask'
|
||||||
import {useAuthStore} from '@/stores/auth'
|
import {useAuthStore} from '@/stores/auth'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
|
const taskStore = useTaskStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
|
@ -180,7 +182,7 @@ async function loadPendingTasks(from: string, to: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.value = await store.dispatch('tasks/loadTasks', params)
|
tasks.value = await taskStore.loadTasks(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this modification should happen in the store
|
// FIXME: this modification should happen in the store
|
||||||
|
|
|
@ -464,6 +464,7 @@ import type {IList} from '@/modelTypes/IList'
|
||||||
import {colorIsDark} from '@/helpers/color/colorIsDark'
|
import {colorIsDark} from '@/helpers/color/colorIsDark'
|
||||||
import {useNamespaceStore} from '@/stores/namespaces'
|
import {useNamespaceStore} from '@/stores/namespaces'
|
||||||
import {useAttachmentStore} from '@/stores/attachments'
|
import {useAttachmentStore} from '@/stores/attachments'
|
||||||
|
import {useTaskStore} from '@/stores/tasks'
|
||||||
|
|
||||||
function scrollIntoView(el) {
|
function scrollIntoView(el) {
|
||||||
if (!el) {
|
if (!el) {
|
||||||
|
@ -696,7 +697,8 @@ export default defineComponent({
|
||||||
task.endDate = task.dueDate
|
task.endDate = task.dueDate
|
||||||
}
|
}
|
||||||
|
|
||||||
this.task = await this.$store.dispatch('tasks/update', task)
|
|
||||||
|
this.task = await useTaskStore().update(task)
|
||||||
|
|
||||||
if (!showNotification) {
|
if (!showNotification) {
|
||||||
return
|
return
|
||||||
|
@ -728,7 +730,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
async deleteTask() {
|
async deleteTask() {
|
||||||
await this.$store.dispatch('tasks/delete', this.task)
|
await useTaskStore().delete(this.task)
|
||||||
this.$message.success({message: this.$t('task.detail.deleteSuccess')})
|
this.$message.success({message: this.$t('task.detail.deleteSuccess')})
|
||||||
this.$router.push({name: 'list.index', params: {listId: this.task.listId}})
|
this.$router.push({name: 'list.index', params: {listId: this.task.listId}})
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue