mirror of
https://github.com/go-vikunja/vikunja.git
synced 2026-04-24 22:25:15 +00:00
fix(filters): persist url filter query across views (#1482)
This commit is contained in:
79
frontend/cypress/e2e/project/filter-persistence.spec.ts
Normal file
79
frontend/cypress/e2e/project/filter-persistence.spec.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import {createFakeUserAndLogin} from '../../support/authenticateUser'
|
||||
import {TaskFactory} from '../../factories/task'
|
||||
import {ProjectFactory} from '../../factories/project'
|
||||
import { createProjects } from './prepareProjects'
|
||||
|
||||
describe('Filter Persistence Across Views', () => {
|
||||
createFakeUserAndLogin()
|
||||
|
||||
const openAndSetFilters = () => {
|
||||
cy.get('.filter-container button')
|
||||
.contains('Filters')
|
||||
.click()
|
||||
cy.get('.filter-popup')
|
||||
.should('be.visible')
|
||||
cy.get('.filter-popup .filter-input')
|
||||
.type('done = true')
|
||||
cy.get('.filter-popup button')
|
||||
.contains('Show results')
|
||||
.click()
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
createProjects()
|
||||
TaskFactory.create(5, {
|
||||
id: '{increment}',
|
||||
project_id: 1,
|
||||
title: 'Test Task {increment}'
|
||||
})
|
||||
cy.visit('/projects/1/1')
|
||||
})
|
||||
|
||||
it('should persist filters in List view after page refresh', () => {
|
||||
openAndSetFilters()
|
||||
|
||||
cy.url().should('include', 'filter=')
|
||||
|
||||
cy.reload()
|
||||
|
||||
cy.url().should('include', 'filter=')
|
||||
})
|
||||
|
||||
it('should persist filters in Table view after page refresh', () => {
|
||||
cy.visit('/projects/1/3')
|
||||
|
||||
openAndSetFilters()
|
||||
|
||||
cy.url().should('include', 'filter=')
|
||||
|
||||
cy.reload()
|
||||
|
||||
cy.url().should('include', 'filter=')
|
||||
})
|
||||
|
||||
it('should persist filters in Kanban view after page refresh', () => {
|
||||
cy.visit('/projects/1/4')
|
||||
|
||||
openAndSetFilters()
|
||||
|
||||
cy.url().should('include', 'filter=')
|
||||
|
||||
cy.reload()
|
||||
|
||||
cy.url().should('include', 'filter=')
|
||||
})
|
||||
|
||||
it('should handle URL sharing with filters', () => {
|
||||
// Visit URL with pre-existing filter parameters
|
||||
cy.visit('/projects/1/4?filter=done%3Dtrue&s=Test')
|
||||
|
||||
// Verify URL parameters are preserved
|
||||
cy.url().should('include', 'filter=done%3Dtrue')
|
||||
cy.url().should('include', 's=Test')
|
||||
|
||||
// Switch views and verify parameters persist
|
||||
cy.visit('/projects/1/3?filter=done%3Dtrue&s=Test')
|
||||
cy.url().should('include', 'filter=done%3Dtrue')
|
||||
cy.url().should('include', 's=Test')
|
||||
})
|
||||
})
|
||||
@@ -12,6 +12,7 @@
|
||||
v-model="params"
|
||||
:view-id="viewId"
|
||||
:project-id="projectId"
|
||||
@update:modelValue="updateFilters"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -277,6 +278,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import {computed, nextTick, ref, watch, toRef} from 'vue'
|
||||
import {useRouteQuery} from '@vueuse/router'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import draggable from 'zhyswan-vuedraggable'
|
||||
import {klona} from 'klona/lite'
|
||||
@@ -374,6 +376,10 @@ const collapsedBuckets = ref<CollapsedBuckets>({})
|
||||
const taskUpdating = ref<{ [id: ITask['id']]: boolean }>({})
|
||||
const oneTaskUpdating = ref(false)
|
||||
|
||||
// URL-synchronized filter parameters
|
||||
const filter = useRouteQuery('filter')
|
||||
const s = useRouteQuery('s')
|
||||
|
||||
const params = ref<TaskFilterParams>({
|
||||
sort_by: [],
|
||||
order_by: [],
|
||||
@@ -382,6 +388,20 @@ const params = ref<TaskFilterParams>({
|
||||
s: '',
|
||||
})
|
||||
|
||||
watch([filter, s], ([filterValue, sValue]) => {
|
||||
params.value.filter = filterValue ?? ''
|
||||
params.value.s = sValue ?? ''
|
||||
}, { immediate: true })
|
||||
|
||||
function updateFilters(newParams: TaskFilterParams) {
|
||||
// Update all params
|
||||
params.value = { ...newParams }
|
||||
|
||||
// Sync only filter and s to URL
|
||||
filter.value = newParams.filter || undefined
|
||||
s.value = newParams.s || undefined
|
||||
}
|
||||
|
||||
const getTaskDraggableTaskComponentData = computed(() => (bucket: IBucket) => {
|
||||
return {
|
||||
ref: (el: HTMLElement) => setTaskContainerRef(bucket.id, el),
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
v-model="params"
|
||||
:view-id="viewId"
|
||||
:project-id="projectId"
|
||||
@update:modelValue="taskList.loadTasks()"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user