mirror of
https://github.com/go-vikunja/vikunja.git
synced 2026-04-24 22:25:15 +00:00
fix: guard saved filter requests (#1462)
This commit is contained in:
@@ -276,7 +276,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {computed, nextTick, ref, watch} from 'vue'
|
||||
import {computed, nextTick, ref, watch, toRef} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import draggable from 'zhyswan-vuedraggable'
|
||||
import {klona} from 'klona/lite'
|
||||
@@ -323,6 +323,8 @@ const props = defineProps<{
|
||||
viewId: IProjectView['id'],
|
||||
}>()
|
||||
|
||||
const projectId = toRef(props, 'projectId')
|
||||
|
||||
const DRAG_OPTIONS = {
|
||||
// sortable options
|
||||
animation: 150,
|
||||
@@ -344,7 +346,7 @@ const taskPositionService = ref(new TaskPositionService())
|
||||
const taskBucketService = ref(new TaskBucketService())
|
||||
|
||||
// Saved filter composable for accessing filter data
|
||||
const {filter: savedFilter} = useSavedFilter(() => props.projectId)
|
||||
const savedFilter = useSavedFilter(() => projectId.value < 0 ? projectId.value : undefined).filter
|
||||
|
||||
const taskContainerRefs = ref<{ [id: IBucket['id']]: HTMLElement }>({})
|
||||
const bucketLimitInputRef = ref<HTMLInputElement | null>(null)
|
||||
@@ -401,10 +403,10 @@ const bucketDraggableComponentData = computed(() => ({
|
||||
{'dragging-disabled': !canWrite.value},
|
||||
],
|
||||
}))
|
||||
const project = computed(() => props.projectId ? projectStore.projects[props.projectId] : null)
|
||||
const project = computed(() => projectId.value ? projectStore.projects[projectId.value] : null)
|
||||
const view = computed(() => project.value?.views.find(v => v.id === props.viewId) as IProjectView || null)
|
||||
const canWrite = computed(() => baseStore.currentProject?.maxPermission > Permissions.READ && view.value.bucketConfigurationMode === 'manual')
|
||||
const canCreateTasks = computed(() => canWrite.value && props.projectId > 0)
|
||||
const canCreateTasks = computed(() => canWrite.value && projectId.value > 0)
|
||||
const buckets = computed(() => kanbanStore.buckets)
|
||||
const loading = computed(() => kanbanStore.isLoading)
|
||||
|
||||
@@ -413,7 +415,7 @@ const taskLoading = computed(() => taskStore.isLoading || taskPositionService.va
|
||||
watch(
|
||||
() => ({
|
||||
params: params.value,
|
||||
projectId: props.projectId,
|
||||
projectId: projectId.value,
|
||||
viewId: props.viewId,
|
||||
}),
|
||||
({params, projectId, viewId}) => {
|
||||
@@ -445,7 +447,7 @@ function handleTaskContainerScroll(id: IBucket['id'], el: HTMLElement) {
|
||||
}
|
||||
|
||||
kanbanStore.loadNextTasksForBucket(
|
||||
props.projectId,
|
||||
projectId.value,
|
||||
props.viewId,
|
||||
params.value,
|
||||
id,
|
||||
@@ -657,7 +659,7 @@ async function saveBucketTitle(bucketId: IBucket['id'], bucketTitle: string) {
|
||||
await kanbanStore.updateBucket({
|
||||
id: bucketId,
|
||||
title: bucketTitle,
|
||||
projectId: props.projectId,
|
||||
projectId: projectId.value,
|
||||
})
|
||||
success({message: i18n.global.t('project.kanban.bucketTitleSavedSuccess')})
|
||||
bucketTitleEditable.value = false
|
||||
@@ -674,13 +676,13 @@ function handleRecurringTaskCompletion() {
|
||||
return
|
||||
}
|
||||
|
||||
const filterContainsDateFields = savedFilter.value.filters?.filter?.includes('due_date') ||
|
||||
savedFilter.value.filters?.filter?.includes('start_date') ||
|
||||
savedFilter.value.filters?.filter?.includes('end_date')
|
||||
const filterContainsDateFields = savedFilter.value?.filters?.filter?.includes('due_date') ||
|
||||
savedFilter.value?.filters?.filter?.includes('start_date') ||
|
||||
savedFilter.value?.filters?.filter?.includes('end_date')
|
||||
|
||||
if (filterContainsDateFields) {
|
||||
// Reload the kanban board to refresh tasks that now match/don't match the filter
|
||||
kanbanStore.loadBucketsForProject(props.projectId, props.viewId, params.value)
|
||||
kanbanStore.loadBucketsForProject(projectId.value, props.viewId, params.value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,7 +697,7 @@ function updateBucketPosition(e: { newIndex: number }) {
|
||||
|
||||
kanbanStore.updateBucket({
|
||||
id: bucket.id,
|
||||
projectId: props.projectId,
|
||||
projectId: projectId.value,
|
||||
position: calculateItemPosition(
|
||||
bucketBefore !== null ? bucketBefore.position : null,
|
||||
bucketAfter !== null ? bucketAfter.position : null,
|
||||
@@ -710,7 +712,7 @@ async function saveBucketLimit(bucketId: IBucket['id'], limit: number) {
|
||||
|
||||
await kanbanStore.updateBucket({
|
||||
...kanbanStore.getBucketById(bucketId),
|
||||
projectId: props.projectId,
|
||||
projectId: projectId.value,
|
||||
limit,
|
||||
})
|
||||
success({message: t('project.kanban.bucketLimitSavedSuccess')})
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref, computed, nextTick, onMounted, onBeforeUnmount, watch} from 'vue'
|
||||
import {ref, computed, nextTick, onMounted, onBeforeUnmount, watch, toRef} from 'vue'
|
||||
import draggable from 'zhyswan-vuedraggable'
|
||||
|
||||
import ProjectWrapper from '@/components/project/ProjectWrapper.vue'
|
||||
@@ -113,7 +113,6 @@ import {PERMISSIONS as Permissions} from '@/constants/permissions'
|
||||
import {calculateItemPosition} from '@/helpers/calculateItemPosition'
|
||||
import type {ITask} from '@/modelTypes/ITask'
|
||||
import {isSavedFilter, useSavedFilter} from '@/services/savedFilter'
|
||||
import {TASK_REPEAT_MODES} from '@/types/IRepeatMode'
|
||||
|
||||
import {useBaseStore} from '@/stores/base'
|
||||
|
||||
@@ -123,11 +122,13 @@ import TaskPositionService from '@/services/taskPosition'
|
||||
import TaskPositionModel from '@/models/taskPosition'
|
||||
|
||||
const props = defineProps<{
|
||||
isLoadingProject: boolean,
|
||||
projectId: IProject['id'],
|
||||
viewId: IProjectView['id'],
|
||||
isLoadingProject: boolean,
|
||||
projectId: IProject['id'],
|
||||
viewId: IProjectView['id'],
|
||||
}>()
|
||||
|
||||
const projectId = toRef(props, 'projectId')
|
||||
|
||||
defineOptions({name: 'List'})
|
||||
|
||||
const ctaVisible = ref(false)
|
||||
@@ -143,10 +144,10 @@ const {
|
||||
params,
|
||||
sortByParam,
|
||||
} = useTaskList(
|
||||
() => props.projectId,
|
||||
() => projectId.value,
|
||||
() => props.viewId,
|
||||
{position: 'asc'},
|
||||
() => props.projectId === -1
|
||||
() => projectId.value === -1
|
||||
? null
|
||||
: 'subtasks',
|
||||
)
|
||||
@@ -154,14 +155,14 @@ const {
|
||||
const taskPositionService = ref(new TaskPositionService())
|
||||
|
||||
// Saved filter composable for accessing filter data
|
||||
const {filter: savedFilter} = useSavedFilter(() => props.projectId)
|
||||
const _savedFilter = useSavedFilter(() => projectId.value < 0 ? projectId.value : undefined).filter
|
||||
|
||||
const tasks = ref<ITask[]>([])
|
||||
watch(
|
||||
allTasks,
|
||||
() => {
|
||||
tasks.value = [...allTasks.value]
|
||||
if (props.projectId < 0) {
|
||||
if (projectId.value < 0) {
|
||||
return
|
||||
}
|
||||
tasks.value = tasks.value.filter(t => {
|
||||
@@ -219,31 +220,9 @@ function updateTaskList(task: ITask) {
|
||||
}
|
||||
|
||||
function updateTasks(updatedTask: ITask) {
|
||||
if (props.projectId < 0) {
|
||||
const originalTask = allTasks.value.find(t => t.id === updatedTask.id)
|
||||
const isRecurringTask = originalTask && (originalTask.repeatAfter.amount > 0 || originalTask.repeatMode === TASK_REPEAT_MODES.REPEAT_MODE_MONTH)
|
||||
|
||||
const filterContainsDateFields = project.value && isSavedFilter(project.value) &&
|
||||
project.value.title &&
|
||||
(savedFilter.value.filters?.filter?.includes('due_date') ||
|
||||
savedFilter.value.filters?.filter?.includes('start_date') ||
|
||||
savedFilter.value.filters?.filter?.includes('end_date'))
|
||||
|
||||
|
||||
if (isRecurringTask && filterContainsDateFields) {
|
||||
// In the case of a filter, we'll reload the filter in the background to avoid tasks which do
|
||||
// not match the filter show up here
|
||||
loadTasks(false)
|
||||
return
|
||||
}
|
||||
|
||||
// For other updates in saved filters, just update the task in place
|
||||
for (const t in allTasks.value) {
|
||||
if (allTasks.value[t].id === updatedTask.id) {
|
||||
allTasks.value[t] = updatedTask
|
||||
break
|
||||
}
|
||||
}
|
||||
if (projectId.value < 0) {
|
||||
// Reload tasks to keep saved filter results in sync
|
||||
loadTasks(false)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user