From 1ebdb8c92fe56ba4f073d3a82da05033ab18a70c Mon Sep 17 00:00:00 2001 From: Gasper Grom Date: Sun, 28 May 2023 10:44:14 +0200 Subject: [PATCH 1/4] Number base filter --- .../components/filterTypes/NumberFilter.vue | 58 ++++++++++++++++--- .../partials/FilterInlineSelect.vue | 12 ++-- .../number.filter.renderer.ts | 24 ++++++-- .../config/constants/number.constants.ts | 41 +++++++++++++ .../number.label.renderer.ts | 14 ++++- .../config/queryUrlParser/number.parser.ts | 5 +- .../modules/filters/types/FilterOperator.ts | 5 ++ .../types/filterTypes/NumberFilterConfig.ts | 4 +- 8 files changed, 140 insertions(+), 23 deletions(-) create mode 100644 frontend/src/shared/modules/filters/config/constants/number.constants.ts create mode 100644 frontend/src/shared/modules/filters/types/FilterOperator.ts diff --git a/frontend/src/shared/modules/filters/components/filterTypes/NumberFilter.vue b/frontend/src/shared/modules/filters/components/filterTypes/NumberFilter.vue index f298cf86be..43c60a0143 100644 --- a/frontend/src/shared/modules/filters/components/filterTypes/NumberFilter.vue +++ b/frontend/src/shared/modules/filters/components/filterTypes/NumberFilter.vue @@ -1,9 +1,34 @@ @@ -16,8 +41,15 @@ import { NumberFilterValue, } from '@/shared/modules/filters/types/filterTypes/NumberFilterConfig'; import useVuelidate from '@vuelidate/core'; -import { required } from '@vuelidate/validators'; +import { minValue, numeric, required } from '@vuelidate/validators'; import CrFilterIncludeSwitch from '@/shared/modules/filters/components/partials/FilterIncludeSwitch.vue'; +import { + FilterNumberOperator, + numberFilterOperators, +} from '@/shared/modules/filters/config/constants/number.constants'; +import CrFilterInput from '@/shared/modules/filters/components/partials/string/FilterInput.vue'; +import CrFilterInlineSelect from '@/shared/modules/filters/components/partials/FilterInlineSelect.vue'; +import AppFormItem from '@/shared/form/form-item.vue'; const props = defineProps<{ modelValue: NumberFilterValue, @@ -33,20 +65,30 @@ const form = computed({ const defaultForm: NumberFilterValue = { value: '', - operator: 'eq', + valueTo: '', + operator: FilterNumberOperator.EQ, include: true, }; -const rules: any = { +const rules: any = computed(() => ({ value: { required, + numeric, + minValue: minValue(0), }, + ...(form.value.operator === FilterNumberOperator.BETWEEN ? { + valueTo: { + required, + numeric, + minValue: minValue((form.value.value) || 0), + }, + } : {}), operator: { required, }, -}; +})); -useVuelidate(rules, form); +const $v = useVuelidate(rules, form); onMounted(() => { if (!form.value || Object.keys(form.value).length === 0) { diff --git a/frontend/src/shared/modules/filters/components/partials/FilterInlineSelect.vue b/frontend/src/shared/modules/filters/components/partials/FilterInlineSelect.vue index 897fee7860..464e9e3d57 100644 --- a/frontend/src/shared/modules/filters/components/partials/FilterInlineSelect.vue +++ b/frontend/src/shared/modules/filters/components/partials/FilterInlineSelect.vue @@ -27,11 +27,11 @@ :class="{ 'is-selected': props.modelValue === option.value, }" + class="flex justify-between" @click="model = option.value" > -
- {{ option.label }} -
+ {{ option.label }} + {{ option.subLabel }} @@ -40,14 +40,12 @@ + + diff --git a/frontend/src/shared/form/form-item.vue b/frontend/src/shared/form/form-item.vue index 07c4db2502..c631a6cb79 100644 --- a/frontend/src/shared/form/form-item.vue +++ b/frontend/src/shared/form/form-item.vue @@ -23,9 +23,10 @@
- {{ errorMessage(errors[0]) }} + {{ errorMessage(errors[0]) }}
@@ -66,6 +67,16 @@ const props = defineProps({ type: Boolean, default: true, }, + errorIcon: { + required: false, + type: String, + default: '', + }, + errorClass: { + required: false, + type: String, + default: '', + }, }); const errors = computed(() => props.validation?.$errors || []); diff --git a/frontend/src/shared/modules/filters/components/filterTypes/NumberFilter.vue b/frontend/src/shared/modules/filters/components/filterTypes/NumberFilter.vue index 43c60a0143..2eef13e54c 100644 --- a/frontend/src/shared/modules/filters/components/filterTypes/NumberFilter.vue +++ b/frontend/src/shared/modules/filters/components/filterTypes/NumberFilter.vue @@ -11,24 +11,51 @@ />
- +
- +
+ @@ -50,6 +77,7 @@ import { import CrFilterInput from '@/shared/modules/filters/components/partials/string/FilterInput.vue'; import CrFilterInlineSelect from '@/shared/modules/filters/components/partials/FilterInlineSelect.vue'; import AppFormItem from '@/shared/form/form-item.vue'; +import AppFormErrors from '@/shared/form/form-errors.vue'; const props = defineProps<{ modelValue: NumberFilterValue, diff --git a/frontend/src/shared/modules/filters/components/partials/FilterInlineSelect.vue b/frontend/src/shared/modules/filters/components/partials/FilterInlineSelect.vue index 464e9e3d57..79056cb812 100644 --- a/frontend/src/shared/modules/filters/components/partials/FilterInlineSelect.vue +++ b/frontend/src/shared/modules/filters/components/partials/FilterInlineSelect.vue @@ -6,7 +6,7 @@ :teleported="false" @visible-change="dropdownExpanded = $event" > -
+
{{ prefix }} diff --git a/frontend/src/shared/modules/filters/components/partials/string/FilterInput.vue b/frontend/src/shared/modules/filters/components/partials/string/FilterInput.vue index 101eea29e4..2aef48f6da 100644 --- a/frontend/src/shared/modules/filters/components/partials/string/FilterInput.vue +++ b/frontend/src/shared/modules/filters/components/partials/string/FilterInput.vue @@ -1,7 +1,7 @@ @@ -32,13 +32,12 @@ export default { }; - From af370b8704cb614012647752ee0cbdee27a8572b Mon Sep 17 00:00:00 2001 From: Gasper Grom Date: Tue, 30 May 2023 08:12:37 +0200 Subject: [PATCH 4/4] Fix relation bug and query empty values --- .../modules/filters/components/Filter.vue | 22 ++++++++++++------- .../components/filterTypes/NumberFilter.vue | 11 +++++++++- .../filters/services/filter-api.service.ts | 2 +- .../filters/services/filter-query.service.ts | 10 +++++++-- .../types/filterTypes/NumberFilterConfig.ts | 2 +- 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/frontend/src/shared/modules/filters/components/Filter.vue b/frontend/src/shared/modules/filters/components/Filter.vue index ddf3d7cdf5..7cf5a8a61d 100644 --- a/frontend/src/shared/modules/filters/components/Filter.vue +++ b/frontend/src/shared/modules/filters/components/Filter.vue @@ -74,10 +74,7 @@ const filters = computed({ return props.modelValue; }, set(value: Filter) { - const { - settings, search, relation, order, pagination, ...filterValues - } = value; - filterList.value = Object.keys(filterValues); + alignFilterList(value); emit('update:modelValue', value); }, }); @@ -88,11 +85,23 @@ const configuration = computed(() => ({ })); const filterList = ref([]); +const cachedRelation = ref<'and' | 'or'>('and'); const switchOperator = () => { filters.value.relation = filters.value.relation === 'and' ? 'or' : 'and'; }; +const alignFilterList = (value: Filter) => { + const { + settings, search, relation, order, pagination, ...filterValues + } = value; + if (JSON.stringify(relation) !== JSON.stringify(cachedRelation.value)) { + cachedRelation.value = relation; + return; + } + filterList.value = Object.keys(filterValues); +}; + const removeFilter = (key) => { open.value = ''; filterList.value = filterList.value.filter((el) => el !== key); @@ -109,10 +118,7 @@ const fetch = (value: Filter) => { watch(() => filters.value, (value: Filter) => { fetch(value); - const { - settings, search, relation, order, pagination, ...filterValues - } = value; - filterList.value = Object.keys(filterValues); + alignFilterList(value); const query = setQuery(value); router.push({ query }); }, { deep: true }); diff --git a/frontend/src/shared/modules/filters/components/filterTypes/NumberFilter.vue b/frontend/src/shared/modules/filters/components/filterTypes/NumberFilter.vue index 2eef13e54c..735cb9f32e 100644 --- a/frontend/src/shared/modules/filters/components/filterTypes/NumberFilter.vue +++ b/frontend/src/shared/modules/filters/components/filterTypes/NumberFilter.vue @@ -61,7 +61,7 @@