From 68d233684f51ce325c3babd9fa222b9bd48699bc Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 3 Jun 2024 22:20:57 +0200 Subject: [PATCH] fix(views): edit views with filters This change fixes a bug where filter values of views would be transformed in the wrong order, not transformed at all or at the wrong time. Transforming the filters now happens transparently in the background without anything funky happening visible to the user. --- .../project/partials/FilterInput.vue | 10 +- .../components/project/views/viewEditForm.vue | 117 +++++++++++------- frontend/src/views/project/settings/views.vue | 20 +-- 3 files changed, 83 insertions(+), 64 deletions(-) diff --git a/frontend/src/components/project/partials/FilterInput.vue b/frontend/src/components/project/partials/FilterInput.vue index a0b43b626..37b9df25a 100644 --- a/frontend/src/components/project/partials/FilterInput.vue +++ b/frontend/src/components/project/partials/FilterInput.vue @@ -35,6 +35,11 @@ const { const emit = defineEmits(['update:modelValue', 'blur']) +const userService = new UserService() +const projectUserService = new ProjectUserService() +const labelStore = useLabelStore() +const projectStore = useProjectStore() + const filterQuery = ref('') const { textarea: filterInput, @@ -60,9 +65,6 @@ watch( }, ) -const userService = new UserService() -const projectUserService = new ProjectUserService() - function escapeHtml(unsafe: string): string { return unsafe .replace(/&/g, '&') @@ -196,8 +198,6 @@ const autocompleteMatchText = ref('') const autocompleteResultType = ref<'labels' | 'assignees' | 'projects' | null>(null) // eslint-disable-next-line @typescript-eslint/no-explicit-any const autocompleteResults = ref([]) -const labelStore = useLabelStore() -const projectStore = useProjectStore() function handleFieldInput() { const cursorPosition = filterInput.value.selectionStart diff --git a/frontend/src/components/project/views/viewEditForm.vue b/frontend/src/components/project/views/viewEditForm.vue index 169244205..1c3754c44 100644 --- a/frontend/src/components/project/views/viewEditForm.vue +++ b/frontend/src/components/project/views/viewEditForm.vue @@ -2,77 +2,86 @@ import type {IProjectView} from '@/modelTypes/IProjectView' import XButton from '@/components/input/button.vue' import FilterInput from '@/components/project/partials/FilterInput.vue' -import {ref, watch} from 'vue' +import {ref, onBeforeMount} from 'vue' import {transformFilterStringForApi, transformFilterStringFromApi} from '@/helpers/filters' import {useLabelStore} from '@/stores/labels' import {useProjectStore} from '@/stores/projects' const { modelValue, + loading = false, + showSaveButtons = false, } = defineProps<{ modelValue: IProjectView, + loading?: bool, + showSaveButtons?: bool, }>() -const emit = defineEmits(['update:modelValue']) +const emit = defineEmits(['update:modelValue', 'cancel']) const view = ref() const labelStore = useLabelStore() const projectStore = useProjectStore() -watch( - () => modelValue, - newValue => { - - const transform = filterString => transformFilterStringFromApi( - filterString, - labelId => labelStore.getLabelById(labelId)?.title, - projectId => projectStore.projects[projectId]?.title || null, - ) - - const transformed = { - ...newValue, - filter: transform(newValue.filter), - bucketConfiguration: newValue.bucketConfiguration.map(bc => ({ - title: bc.title, - filter: transform(bc.filter), - })), - } +onBeforeMount(() => { + const transform = filterString => transformFilterStringFromApi( + filterString, + labelId => labelStore.getLabelById(labelId)?.title, + projectId => projectStore.projects[projectId]?.title || null, + ) - if (JSON.stringify(view.value) !== JSON.stringify(transformed)) { - view.value = transformed - } - }, - {immediate: true, deep: true}, -) + const transformed = { + ...modelValue, + filter: transform(modelValue.filter), + bucketConfiguration: modelValue.bucketConfiguration.map(bc => ({ + title: bc.title, + filter: transform(bc.filter), + })), + } -watch( - () => view.value, - newView => { - emit('update:modelValue', { - ...newView, - filter: transformFilterStringForApi( - newView.filter, - labelTitle => labelStore.filterLabelsByQuery([], labelTitle)[0]?.id || null, - projectTitle => { - const found = projectStore.findProjectByExactname(projectTitle) - return found?.id || null - }, - ), - }) - }, - {deep: true}, -) + if (JSON.stringify(view.value) !== JSON.stringify(transformed)) { + view.value = transformed + } +}) + +function save() { + const transformFilter = filterQuery => transformFilterStringForApi( + filterQuery, + labelTitle => labelStore.filterLabelsByQuery([], labelTitle)[0]?.id || null, + projectTitle => { + const found = projectStore.findProjectByExactname(projectTitle) + return found?.id || null + }, + ) + + emit('update:modelValue', { + ...view.value, + filter: transformFilter(view.value?.filter), + bucketConfiguration: view.value?.bucketConfiguration.map(bc => ({ + title: bc.title, + filter: transformFilter(bc.filter), + })), + }) +} const titleValid = ref(true) function validateTitle() { titleValid.value = view.value?.title !== '' } + +function handleBubbleSave() { + if (showSaveButtons) { + return + } + + save() +} diff --git a/frontend/src/views/project/settings/views.vue b/frontend/src/views/project/settings/views.vue index 7fc55c28c..fd885bf6e 100644 --- a/frontend/src/views/project/settings/views.vue +++ b/frontend/src/views/project/settings/views.vue @@ -111,6 +111,7 @@ async function saveView() { > {{ $t('project.views.create') }} @@ -144,22 +145,11 @@ async function saveView() { -
- - {{ $t('misc.cancel') }} - - - {{ $t('misc.save') }} - -