frontend/src/composables/useTaskList.ts

136 lines
3.0 KiB
TypeScript
Raw Normal View History

import {ref, shallowReactive, watch, computed} from 'vue'
2021-12-10 14:29:28 +00:00
import {useRoute} from 'vue-router'
2021-10-25 20:17:23 +00:00
import TaskCollectionService from '@/services/taskCollection'
import type {ITask} from '@/modelTypes/ITask'
import {error} from '@/message'
2021-10-25 20:17:23 +00:00
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
}
2021-10-25 20:17:23 +00:00
// FIXME: merge with DEFAULT_PARAMS in filters.vue
export const getDefaultParams = () => ({
sort_by: ['position', 'id'],
order_by: ['asc', 'desc'],
filter_by: ['done'],
filter_value: ['false'],
filter_comparator: ['equals'],
filter_concat: 'and',
})
const SORT_BY_DEFAULT: SortBy = {
2021-12-10 14:29:28 +00:00
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) {
2021-12-10 14:29:28 +00:00
let hasIdFilter = false
const sortKeys = Object.keys(sortBy)
2021-12-10 14:29:28 +00:00
for (const s of sortKeys) {
if (s === 'id') {
sortKeys.splice(s, 1)
hasIdFilter = true
break
}
}
if (hasIdFilter) {
sortKeys.push('id')
2021-10-25 20:17:23 +00:00
}
2021-12-10 14:29:28 +00:00
params.sort_by = sortKeys
params.order_by = sortKeys.map(s => sortBy[s])
2021-10-25 20:17:23 +00:00
2021-12-10 14:29:28 +00:00
return params
}
2021-10-25 20:17:23 +00:00
/**
* This mixin provides a base set of methods and properties to get tasks.
*/
export function useTaskList(projectId, sortByDefault: SortBy = SORT_BY_DEFAULT) {
const params = ref({...getDefaultParams()})
const search = ref('')
const page = ref(1)
const sortBy = ref({ ...sortByDefault })
2021-12-10 14:29:28 +00:00
const getAllTasksParams = computed(() => {
let loadParams = {...params.value}
if (search.value !== '') {
loadParams.s = search.value
2021-10-25 20:17:23 +00:00
}
loadParams = formatSortOrder(sortBy.value, loadParams)
2021-12-10 14:29:28 +00:00
return [
{projectId: projectId.value},
2021-12-10 14:29:28 +00:00
loadParams,
page.value || 1,
]
})
const taskCollectionService = shallowReactive(new TaskCollectionService())
const loading = computed(() => taskCollectionService.loading)
const totalPages = computed(() => taskCollectionService.totalPages)
2021-11-01 17:19:59 +00:00
const tasks = ref<ITask[]>([])
2021-12-10 14:29:28 +00:00
async function loadTasks() {
tasks.value = []
try {
tasks.value = await taskCollectionService.getAll(...getAllTasksParams.value)
} catch (e) {
error(e)
}
2021-11-01 17:19:59 +00:00
return tasks.value
2021-10-25 20:17:23 +00:00
}
2021-12-10 14:29:28 +00:00
const route = useRoute()
watch(() => route.query, (query) => {
const { page: pageQueryValue, search: searchQuery } = query
if (searchQuery !== undefined) {
search.value = searchQuery as string
}
if (pageQueryValue !== undefined) {
page.value = Number(pageQueryValue)
}
2021-12-10 14:29:28 +00:00
}, { immediate: true })
// Only listen for query path changes
watch(() => JSON.stringify(getAllTasksParams.value), (newParams, oldParams) => {
if (oldParams === newParams) {
return
2021-10-25 20:17:23 +00:00
}
2021-12-10 14:29:28 +00:00
loadTasks()
}, { immediate: true })
2021-10-25 20:17:23 +00:00
return {
tasks,
loading,
totalPages,
2021-12-10 14:29:28 +00:00
currentPage: page,
2021-10-25 20:17:23 +00:00
loadTasks,
2021-12-10 14:29:28 +00:00
searchTerm: search,
2021-10-25 20:17:23 +00:00
params,
sortByParam: sortBy,
2021-10-25 20:17:23 +00:00
}
}