feat: use ref for filters
This commit is contained in:
parent
acb3ddc73f
commit
51dc123d89
@ -1,4 +1,4 @@
|
|||||||
import {reactive, watch, type Ref} from 'vue'
|
import {computed, ref, watch, type Ref} from 'vue'
|
||||||
import {useRouter, type RouteLocationNormalized, type RouteLocationRaw} from 'vue-router'
|
import {useRouter, type RouteLocationNormalized, type RouteLocationRaw} from 'vue-router'
|
||||||
import cloneDeep from 'lodash.clonedeep'
|
import cloneDeep from 'lodash.clonedeep'
|
||||||
|
|
||||||
@ -11,26 +11,26 @@ export function useRouteFilter<F extends Filter = Filter>(
|
|||||||
) {
|
) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const filters: F = reactive(routeToFilter(route.value))
|
const filters = ref<F>(routeToFilter(route.value))
|
||||||
|
|
||||||
|
const routeFromFiltersFullPath = computed(() => router.resolve(filterToRoute(filters.value)).fullPath)
|
||||||
|
|
||||||
watch(() => cloneDeep(route.value), (route, oldRoute) => {
|
watch(() => cloneDeep(route.value), (route, oldRoute) => {
|
||||||
if (route.name !== oldRoute.name) {
|
if (
|
||||||
return
|
route.name !== oldRoute.name ||
|
||||||
}
|
routeFromFiltersFullPath.value === route.fullPath
|
||||||
const filterFullPath = router.resolve(filterToRoute(filters)).fullPath
|
) {
|
||||||
if (filterFullPath === route.fullPath) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.assign(filters, routeToFilter(route))
|
filters.value = routeToFilter(route)
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
filters,
|
filters,
|
||||||
async () => {
|
async () => {
|
||||||
const newRouteFullPath = router.resolve(filterToRoute(filters)).fullPath
|
if (routeFromFiltersFullPath.value !== route.value.fullPath) {
|
||||||
if (newRouteFullPath !== route.value.fullPath) {
|
await router.push(routeFromFiltersFullPath.value)
|
||||||
await router.push(newRouteFullPath)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// only apply new route after all filters have changed in component cycle
|
// only apply new route after all filters have changed in component cycle
|
||||||
|
@ -87,7 +87,7 @@ const defaultTaskEndDate: DateISO = new Date(today.getFullYear(), today.getMonth
|
|||||||
async function addGanttTask(title: ITask['title']) {
|
async function addGanttTask(title: ITask['title']) {
|
||||||
return await addTask({
|
return await addTask({
|
||||||
title,
|
title,
|
||||||
listId: filters.listId,
|
listId: filters.value.listId,
|
||||||
startDate: defaultTaskStartDate,
|
startDate: defaultTaskStartDate,
|
||||||
endDate: defaultTaskEndDate,
|
endDate: defaultTaskEndDate,
|
||||||
})
|
})
|
||||||
@ -96,8 +96,8 @@ async function addGanttTask(title: ITask['title']) {
|
|||||||
const flatPickerEl = ref<typeof Foo | null>(null)
|
const flatPickerEl = ref<typeof Foo | null>(null)
|
||||||
const flatPickerDateRange = computed<Date[]>({
|
const flatPickerDateRange = computed<Date[]>({
|
||||||
get: () => ([
|
get: () => ([
|
||||||
new Date(filters.dateFrom),
|
new Date(filters.value.dateFrom),
|
||||||
new Date(filters.dateTo),
|
new Date(filters.value.dateTo),
|
||||||
]),
|
]),
|
||||||
set(newVal) {
|
set(newVal) {
|
||||||
const [dateFrom, dateTo] = newVal.map((date) => date?.toISOString())
|
const [dateFrom, dateTo] = newVal.map((date) => date?.toISOString())
|
||||||
@ -105,11 +105,11 @@ const flatPickerDateRange = computed<Date[]>({
|
|||||||
// only set after whole range has been selected
|
// only set after whole range has been selected
|
||||||
if (!dateTo) return
|
if (!dateTo) return
|
||||||
|
|
||||||
Object.assign(filters, {dateFrom, dateTo})
|
Object.assign(filters.value, {dateFrom, dateTo})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const initialDateRange = [filters.dateFrom, filters.dateTo]
|
const initialDateRange = [filters.value.dateFrom, filters.value.dateTo]
|
||||||
|
|
||||||
const {t} = useI18n({useScope: 'global'})
|
const {t} = useI18n({useScope: 'global'})
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
|
@ -36,7 +36,8 @@ function getDefaultDateTo() {
|
|||||||
return new Date(now.getFullYear(), now.getMonth(), now.getDate() + DEFAULT_DATETO_DAY_OFFSET).toISOString()
|
return new Date(now.getFullYear(), now.getMonth(), now.getDate() + DEFAULT_DATETO_DAY_OFFSET).toISOString()
|
||||||
}
|
}
|
||||||
|
|
||||||
function routeToFilter(route: RouteLocationNormalized): GanttFilter {
|
// FIXME: use zod for this
|
||||||
|
function ganttRouteToFilter(route: RouteLocationNormalized): GanttFilter {
|
||||||
return {
|
return {
|
||||||
listId: Number(route.params.listId as string),
|
listId: Number(route.params.listId as string),
|
||||||
dateFrom: parseDateProp(route.query.dateFrom as DateKebab) || getDefaultDateFrom(),
|
dateFrom: parseDateProp(route.query.dateFrom as DateKebab) || getDefaultDateFrom(),
|
||||||
@ -45,7 +46,8 @@ function routeToFilter(route: RouteLocationNormalized): GanttFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterToRoute(filters: GanttFilter): RouteLocationRaw {
|
// FIXME: use zod for this
|
||||||
|
function ganttFilterToRoute(filters: GanttFilter): RouteLocationRaw {
|
||||||
let query: Record<string, string> = {}
|
let query: Record<string, string> = {}
|
||||||
if (
|
if (
|
||||||
filters.dateFrom !== getDefaultDateFrom() ||
|
filters.dateFrom !== getDefaultDateFrom() ||
|
||||||
@ -80,8 +82,8 @@ function ganttFiltersToApiParams(filters: GanttFilter): GetAllTasksParams {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useGanttFilter(route: Ref<RouteLocationNormalized>) {
|
export function useGanttFilter(route: Ref<RouteLocationNormalized>): ReturnType<typeof useRouteFilter> & ReturnType<typeof useGanttTaskList> {
|
||||||
const {filters} = useRouteFilter<GanttFilter>(route, routeToFilter, filterToRoute)
|
const {filters} = useRouteFilter<GanttFilter>(route, ganttRouteToFilter, ganttFilterToRoute)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
tasks,
|
tasks,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {computed, ref, shallowReactive, watchEffect} from 'vue'
|
import {computed, ref, shallowReactive, watch, type Ref} from 'vue'
|
||||||
import cloneDeep from 'lodash.clonedeep'
|
import cloneDeep from 'lodash.clonedeep'
|
||||||
|
|
||||||
import type {Filter} from '@/composables/useRouteFilter'
|
import type {Filter} from '@/composables/useRouteFilter'
|
||||||
@ -12,7 +12,7 @@ import {error, success} from '@/message'
|
|||||||
|
|
||||||
// FIXME: unify with general `useTaskList`
|
// FIXME: unify with general `useTaskList`
|
||||||
export function useGanttTaskList<F extends Filter>(
|
export function useGanttTaskList<F extends Filter>(
|
||||||
filters: F,
|
filters: Ref<F>,
|
||||||
filterToApiParams: (filters: F) => GetAllTasksParams,
|
filterToApiParams: (filters: F) => GetAllTasksParams,
|
||||||
options: {
|
options: {
|
||||||
loadAll?: boolean,
|
loadAll?: boolean,
|
||||||
@ -27,7 +27,7 @@ export function useGanttTaskList<F extends Filter>(
|
|||||||
const tasks = ref<Map<ITask['id'], ITask>>(new Map())
|
const tasks = ref<Map<ITask['id'], ITask>>(new Map())
|
||||||
|
|
||||||
async function fetchTasks(params: GetAllTasksParams, page = 1): Promise<ITask[]> {
|
async function fetchTasks(params: GetAllTasksParams, page = 1): Promise<ITask[]> {
|
||||||
const tasks = await taskCollectionService.getAll({listId: filters.listId}, params, page) as ITask[]
|
const tasks = await taskCollectionService.getAll({listId: filters.value.listId}, params, page) as ITask[]
|
||||||
if (options.loadAll && page < taskCollectionService.totalPages) {
|
if (options.loadAll && page < taskCollectionService.totalPages) {
|
||||||
const nextTasks = await fetchTasks(params, page + 1)
|
const nextTasks = await fetchTasks(params, page + 1)
|
||||||
return tasks.concat(nextTasks)
|
return tasks.concat(nextTasks)
|
||||||
@ -35,15 +35,26 @@ export function useGanttTaskList<F extends Filter>(
|
|||||||
return tasks
|
return tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadTasks(filters: F) {
|
/**
|
||||||
const params: GetAllTasksParams = filterToApiParams(filters)
|
* Load and assign new tasks
|
||||||
|
* Normally there is no need to trigger this manually
|
||||||
|
*/
|
||||||
|
async function loadTasks() {
|
||||||
|
const params: GetAllTasksParams = filterToApiParams(filters.value)
|
||||||
|
|
||||||
const loadedTasks = await fetchTasks(params)
|
const loadedTasks = await fetchTasks(params)
|
||||||
tasks.value = new Map()
|
tasks.value = new Map()
|
||||||
loadedTasks.forEach(t => tasks.value.set(t.id, t))
|
loadedTasks.forEach(t => tasks.value.set(t.id, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
watchEffect(() => loadTasks(filters))
|
/**
|
||||||
|
* Load tasks when filters change
|
||||||
|
*/
|
||||||
|
watch(
|
||||||
|
filters,
|
||||||
|
() => loadTasks(),
|
||||||
|
{immediate: true, deep: true},
|
||||||
|
)
|
||||||
|
|
||||||
async function addTask(task: Partial<ITask>) {
|
async function addTask(task: Partial<ITask>) {
|
||||||
const newTask = await taskService.create(new TaskModel({...task}))
|
const newTask = await taskService.create(new TaskModel({...task}))
|
||||||
@ -83,6 +94,8 @@ export function useGanttTaskList<F extends Filter>(
|
|||||||
tasks,
|
tasks,
|
||||||
|
|
||||||
isLoading,
|
isLoading,
|
||||||
|
loadTasks,
|
||||||
|
|
||||||
addTask,
|
addTask,
|
||||||
updateTask,
|
updateTask,
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user