
This fixes a UI issue where if a user had a filter set and marked the task done, it would not disappear, even though the filter does not match the done task anymore.
173 lines
4.0 KiB
TypeScript
173 lines
4.0 KiB
TypeScript
import {ref, shallowReactive, watch, computed, type ComputedGetter} from 'vue'
|
|
import {useRoute, useRouter} from 'vue-router'
|
|
import {useRouteQuery} from '@vueuse/router'
|
|
|
|
import TaskCollectionService, {getDefaultTaskFilterParams, type TaskFilterParams} from '@/services/taskCollection'
|
|
import type {ITask} from '@/modelTypes/ITask'
|
|
import {error} from '@/message'
|
|
import type {IProject} from '@/modelTypes/IProject'
|
|
import {useAuthStore} from '@/stores/auth'
|
|
import type {IProjectView} from '@/modelTypes/IProjectView'
|
|
|
|
export type Order = 'asc' | 'desc' | 'none'
|
|
|
|
export interface SortBy {
|
|
id?: Order
|
|
index?: Order
|
|
done?: Order
|
|
title?: Order
|
|
priority?: Order
|
|
due_date?: Order
|
|
start_date?: Order
|
|
end_date?: Order
|
|
percent_done?: Order
|
|
created?: Order
|
|
updated?: Order
|
|
done_at?: Order,
|
|
}
|
|
|
|
const SORT_BY_DEFAULT: SortBy = {
|
|
id: 'desc',
|
|
}
|
|
|
|
// This makes sure an id sort order is always sorted last.
|
|
// When tasks would be sorted first by id and then by whatever else was specified, the id sort takes
|
|
// precedence over everything else, making any other sort columns pretty useless.
|
|
function formatSortOrder(sortBy, params) {
|
|
let hasIdFilter = false
|
|
const sortKeys = Object.keys(sortBy)
|
|
for (const s of sortKeys) {
|
|
if (s === 'id') {
|
|
sortKeys.splice(s, 1)
|
|
hasIdFilter = true
|
|
break
|
|
}
|
|
}
|
|
if (hasIdFilter) {
|
|
sortKeys.push('id')
|
|
}
|
|
params.sort_by = sortKeys
|
|
params.order_by = sortKeys.map(s => sortBy[s])
|
|
|
|
return params
|
|
}
|
|
|
|
/**
|
|
* This mixin provides a base set of methods and properties to get tasks.
|
|
*/
|
|
export function useTaskList(
|
|
projectIdGetter: ComputedGetter<IProject['id']>,
|
|
projectViewIdGetter: ComputedGetter<IProjectView['id']>,
|
|
sortByDefault: SortBy = SORT_BY_DEFAULT,
|
|
) {
|
|
|
|
const projectId = computed(() => projectIdGetter())
|
|
const projectViewId = computed(() => projectViewIdGetter())
|
|
|
|
const params = ref<TaskFilterParams>({...getDefaultTaskFilterParams()})
|
|
|
|
const page = useRouteQuery('page', '1', { transform: Number })
|
|
|
|
const sortBy = ref({ ...sortByDefault })
|
|
|
|
const allParams = computed(() => {
|
|
const loadParams = {...params.value}
|
|
|
|
return formatSortOrder(sortBy.value, loadParams)
|
|
})
|
|
|
|
watch(
|
|
() => allParams.value,
|
|
() => {
|
|
// When parameters change, the page should always be the first
|
|
page.value = 1
|
|
},
|
|
)
|
|
|
|
const authStore = useAuthStore()
|
|
|
|
const getAllTasksParams = computed(() => {
|
|
return [
|
|
{
|
|
projectId: projectId.value,
|
|
viewId: projectViewId.value,
|
|
},
|
|
{
|
|
...allParams.value,
|
|
filter_timezone: authStore.settings.timezone,
|
|
},
|
|
page.value,
|
|
]
|
|
})
|
|
|
|
const taskCollectionService = shallowReactive(new TaskCollectionService())
|
|
const loading = computed(() => taskCollectionService.loading)
|
|
const totalPages = computed(() => taskCollectionService.totalPages)
|
|
|
|
const tasks = ref<ITask[]>([])
|
|
async function loadTasks(resetBeforeLoad: boolean = true) {
|
|
if(resetBeforeLoad) {
|
|
tasks.value = []
|
|
}
|
|
try {
|
|
tasks.value = await taskCollectionService.getAll(...getAllTasksParams.value)
|
|
} catch (e) {
|
|
error(e)
|
|
}
|
|
return tasks.value
|
|
}
|
|
|
|
const route = useRoute()
|
|
watch(() => route.query, (query) => {
|
|
const {
|
|
page: pageQueryValue,
|
|
s,
|
|
filter,
|
|
} = query
|
|
if (s !== undefined) {
|
|
params.value.s = s as string
|
|
}
|
|
if (pageQueryValue !== undefined) {
|
|
page.value = Number(pageQueryValue)
|
|
}
|
|
if (filter !== undefined) {
|
|
params.value.filter = filter
|
|
}
|
|
}, { immediate: true })
|
|
|
|
const router = useRouter()
|
|
watch(
|
|
() => [page.value, params.value.filter, params.value.s],
|
|
() => {
|
|
router.replace({
|
|
name: route.name,
|
|
params: route.params,
|
|
query: {
|
|
page: page.value,
|
|
filter: params.value.filter || undefined,
|
|
s: params.value.s || undefined,
|
|
},
|
|
})
|
|
},
|
|
{ deep: true },
|
|
)
|
|
|
|
// Only listen for query path changes
|
|
watch(() => JSON.stringify(getAllTasksParams.value), (newParams, oldParams) => {
|
|
if (oldParams === newParams) {
|
|
return
|
|
}
|
|
|
|
loadTasks()
|
|
}, { immediate: true })
|
|
|
|
return {
|
|
tasks,
|
|
loading,
|
|
totalPages,
|
|
currentPage: page,
|
|
loadTasks,
|
|
params,
|
|
sortByParam: sortBy,
|
|
}
|
|
} |