kolaente
6e5b31f1e0
Some checks failed
continuous-integration/drone/push Build is failing
Previously, when using the filter query as a search input, it would load the search as requested but the filter query parameter in the url would be empty, which meant the search would not be loaded correctly when reloading (or otherwise newly accessing) the page. We're now persisting the filter and search in the task loading logic, to make sure they are always populated correctly.
159 lines
3.5 KiB
Vue
159 lines
3.5 KiB
Vue
<template>
|
|
<card
|
|
class="filters has-overflow"
|
|
:title="hasTitle ? $t('filters.title') : ''"
|
|
role="search"
|
|
>
|
|
<FilterInput
|
|
v-model="filterQuery"
|
|
:project-id="projectId"
|
|
@blur="change()"
|
|
/>
|
|
|
|
<div class="field is-flex is-flex-direction-column">
|
|
<Fancycheckbox
|
|
v-model="params.filter_include_nulls"
|
|
@blur="change()"
|
|
>
|
|
{{ $t('filters.attributes.includeNulls') }}
|
|
</Fancycheckbox>
|
|
</div>
|
|
|
|
<FilterInputDocs />
|
|
|
|
<template
|
|
v-if="hasFooter"
|
|
#footer
|
|
>
|
|
<x-button
|
|
variant="secondary"
|
|
class="mr-2"
|
|
:disabled="filterQuery === ''"
|
|
@click.prevent.stop="clearFiltersAndEmit"
|
|
>
|
|
{{ $t('filters.clear') }}
|
|
</x-button>
|
|
<x-button
|
|
variant="primary"
|
|
@click.prevent.stop="changeAndEmitButton"
|
|
>
|
|
{{ $t('filters.showResults') }}
|
|
</x-button>
|
|
</template>
|
|
</card>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
export const ALPHABETICAL_SORT = 'title'
|
|
</script>
|
|
|
|
<script setup lang="ts">
|
|
import {computed, ref, watch} from 'vue'
|
|
import Fancycheckbox from '@/components/input/fancycheckbox.vue'
|
|
import FilterInput from '@/components/project/partials/FilterInput.vue'
|
|
import {useRoute} from 'vue-router'
|
|
import type {TaskFilterParams} from '@/services/taskCollection'
|
|
import {useLabelStore} from '@/stores/labels'
|
|
import {useProjectStore} from '@/stores/projects'
|
|
import {FILTER_OPERATORS, transformFilterStringForApi, transformFilterStringFromApi} from '@/helpers/filters'
|
|
import FilterInputDocs from '@/components/project/partials/FilterInputDocs.vue'
|
|
|
|
const {
|
|
hasTitle = false,
|
|
hasFooter = true,
|
|
modelValue,
|
|
} = defineProps<{
|
|
hasTitle?: boolean,
|
|
hasFooter?: boolean,
|
|
modelValue: TaskFilterParams,
|
|
}>()
|
|
|
|
const emit = defineEmits(['update:modelValue', 'showResultsButtonClicked'])
|
|
|
|
const route = useRoute()
|
|
const projectId = computed(() => {
|
|
if (route.name?.startsWith('project.')) {
|
|
return Number(route.params.projectId)
|
|
}
|
|
|
|
return undefined
|
|
})
|
|
|
|
const params = ref<TaskFilterParams>({
|
|
sort_by: [],
|
|
order_by: [],
|
|
filter: '',
|
|
filter_include_nulls: false,
|
|
s: '',
|
|
})
|
|
|
|
const filterQuery = ref('')
|
|
watch(
|
|
() => [params.value.filter, params.value.s],
|
|
() => {
|
|
const filter = params.value.filter || ''
|
|
const s = params.value.s || ''
|
|
filterQuery.value = filter || s
|
|
},
|
|
)
|
|
|
|
// Using watchDebounced to prevent the filter re-triggering itself.
|
|
watch(
|
|
() => modelValue,
|
|
(value: TaskFilterParams) => {
|
|
const val = {...value}
|
|
val.filter = transformFilterStringFromApi(
|
|
val?.filter || '',
|
|
labelId => labelStore.getLabelById(labelId)?.title,
|
|
projectId => projectStore.projects[projectId]?.title || null,
|
|
)
|
|
params.value = val
|
|
},
|
|
{immediate: true},
|
|
)
|
|
|
|
const labelStore = useLabelStore()
|
|
const projectStore = useProjectStore()
|
|
|
|
function change() {
|
|
const filter = transformFilterStringForApi(
|
|
filterQuery.value,
|
|
labelTitle => labelStore.filterLabelsByQuery([], labelTitle)[0]?.id || null,
|
|
projectTitle => {
|
|
const found = projectStore.findProjectByExactname(projectTitle)
|
|
return found?.id || null
|
|
},
|
|
)
|
|
|
|
let s = ''
|
|
|
|
// When the filter does not contain any filter tokens, assume a simple search and redirect the input
|
|
const hasFilterQueries = FILTER_OPERATORS.find(o => filter.includes(o)) || false
|
|
if (!hasFilterQueries) {
|
|
s = filter
|
|
}
|
|
|
|
const newParams = {
|
|
...params.value,
|
|
filter: s === '' ? filter : '',
|
|
s,
|
|
}
|
|
|
|
if (JSON.stringify(modelValue) === JSON.stringify(newParams)) {
|
|
return
|
|
}
|
|
|
|
emit('update:modelValue', newParams)
|
|
}
|
|
|
|
function changeAndEmitButton() {
|
|
change()
|
|
emit('showResultsButtonClicked')
|
|
}
|
|
|
|
function clearFiltersAndEmit() {
|
|
filterQuery.value = ''
|
|
changeAndEmitButton()
|
|
}
|
|
</script>
|