fix: order catalog
gitea/salix-front/pipeline/pr-dev This commit looks good Details

This commit is contained in:
William Buezas 2024-11-03 10:29:03 -03:00
parent c93f152060
commit d627c1f698
4 changed files with 231 additions and 156 deletions

View File

@ -120,7 +120,7 @@ watch(options, (newValue) => {
}); });
watch(modelValue, async (newValue) => { watch(modelValue, async (newValue) => {
if (!myOptions.value.some((option) => option[optionValue.value] == newValue)) if (!myOptions?.value?.some((option) => option[optionValue.value] == newValue))
await fetchFilter(newValue); await fetchFilter(newValue);
if ($props.noOne) myOptions.value.unshift(noOneOpt.value); if ($props.noOne) myOptions.value.unshift(noOneOpt.value);

View File

@ -189,7 +189,6 @@ const tags = computed(() => {
const filteredTags = tagsList.value.filter( const filteredTags = tagsList.value.filter(
(tag) => !($props.customTags || []).includes(tag.label) (tag) => !($props.customTags || []).includes(tag.label)
); );
console.log('formatTags: ', formatTags(filteredTags));
return formatTags(filteredTags); return formatTags(filteredTags);
}); });

View File

@ -0,0 +1,150 @@
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import axios from 'axios';
import VnSelect from 'components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue';
const props = defineProps({
tags: {
type: Array,
default: () => [],
},
});
const emit = defineEmits(['applyTags']);
const { t } = useI18n();
const tagValues = ref([{}]);
const tagOptions = ref([]);
const selectedTag = ref(null);
const applyTags = () => {
if (tagValues.value.some((tag) => !tag.value)) return;
const tagInfo = {
values: [...tagValues.value],
tagFk: selectedTag?.value?.id,
tagSelection: {
name: selectedTag?.value?.name,
},
};
emit('applyTags', tagInfo);
};
const removeTagGroupParam = (valIndex = null) => {
if (!valIndex) {
tagValues.value = [{}];
} else {
(tagValues.value || []).splice(valIndex, 1);
}
};
const getSelectedTagValues = async (tag) => {
try {
if (!tag?.id) return;
const filter = {
fields: ['value'],
order: 'value ASC',
limit: 30,
};
const url = `Tags/${tag?.id}/filterValue`;
const params = { filter: JSON.stringify(filter) };
const { data } = await axios.get(url, {
params,
});
tagOptions.value = data;
} catch (err) {
console.error('Error getting selected tag values');
}
};
</script>
<template>
<QForm @submit="applyTags(tagValues)" class="all-pointer-events">
<QCard class="q-pa-sm column q-pa-lg">
<VnSelect
:label="t('params.tag')"
v-model="selectedTag"
:options="props.tags || []"
option-value="id"
option-label="name"
dense
outlined
class="q-mb-md"
rounded
:emit-value="false"
use-input
@update:model-value="($event) => getSelectedTagValues($event)"
/>
<div
v-for="(value, index) in tagValues"
:key="value"
class="filter-value column align-left"
>
<div class="col row q-mb-md">
<VnSelect
v-if="!selectedTag?.isFree && tagOptions"
:label="t('components.itemsFilterPanel.value')"
v-model="value.value"
:options="tagOptions || []"
option-value="value"
option-label="value"
dense
outlined
rounded
emit-value
use-input
:disable="!value"
:is-clearable="false"
class="col"
/>
<VnInput
v-else
v-model="value.value"
:label="t('components.itemsFilterPanel.value')"
:disable="!value"
is-outlined
:is-clearable="false"
class="col"
/>
<QIcon
name="delete"
class="filter-icon col-2"
@click="removeTagGroupParam(index)"
/>
</div>
</div>
<QBtn
icon="add_circle"
shortcut="+"
flat
class="filter-icon q-mb-md"
size="md"
dense
@click="tagValues.push({})"
/>
<QBtn color="primary" type="submit">
{{ t('search') }}
</QBtn>
</QCard>
</QForm>
</template>
<style scoped lang="scss">
.filter-icon {
font-size: 24px;
color: $primary;
padding: 0 4px;
cursor: pointer;
}
</style>
<i18n>
en:
params:
tag: Tag
es:
params:
tag: Etiqueta
</i18n>

View File

@ -9,6 +9,7 @@ import VnSelect from 'components/common/VnSelect.vue';
import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue'; import VnFilterPanelChip from 'components/ui/VnFilterPanelChip.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import getParamWhere from 'src/filters/getParamWhere'; import getParamWhere from 'src/filters/getParamWhere';
import CatalogFilterValueDialog from 'src/pages/Order/Card/CatalogFilterValueDialog.vue';
const { t } = useI18n(); const { t } = useI18n();
@ -28,13 +29,13 @@ const props = defineProps({
}, },
}); });
const showValueFilterDialog = ref(false);
const categoryList = ref(null); const categoryList = ref(null);
const selectedCategoryFk = ref(null); const selectedCategoryFk = ref(null);
const typeList = ref([]); const typeList = ref([]);
const selectedTypeFk = ref(null); const selectedTypeFk = ref(null);
const selectedTag = ref(null); const generalSearchParam = ref(null);
const tagValues = ref([{}]);
const tagOptions = ref([]);
const vnFilterPanelRef = ref(); const vnFilterPanelRef = ref();
const orderByList = ref([ const orderByList = ref([
{ id: 'relevancy DESC, name', name: t('params.relevancy'), priority: 999 }, { id: 'relevancy DESC, name', name: t('params.relevancy'), priority: 999 },
@ -49,20 +50,17 @@ const orderWayList = ref([
const orderBySelected = ref('relevancy DESC, name'); const orderBySelected = ref('relevancy DESC, name');
const orderWaySelected = ref('ASC'); const orderWaySelected = ref('ASC');
const resetCategory = () => { const resetCategory = (params, search) => {
selectedCategoryFk.value = null; selectedCategoryFk.value = null;
typeList.value = null; typeList.value = null;
}; params.categoryFk = null;
params.typeFk = null;
const clearFilter = (key) => { search();
if (key === 'categoryFk') {
resetCategory();
}
}; };
const selectCategory = (params, category, search) => { const selectCategory = (params, category, search) => {
if (params.categoryFk === category?.id) { if (params.categoryFk === category?.id) {
resetCategory(); resetCategory(params, search);
params.categoryFk = null; params.categoryFk = null;
} else { } else {
selectedCategoryFk.value = category?.id; selectedCategoryFk.value = category?.id;
@ -102,37 +100,28 @@ function exprBuilder(param, value) {
} }
} }
const applyTags = (params, search) => { const applyTags = (tagInfo, params, search) => {
if (!tagValues.value?.length) { if (!tagInfo || !tagInfo.values.length) {
params.tagGroups = null; params.tagGroups = null;
search(); search();
toggleValueFilterDialog();
return; return;
} }
const tagGroups = { if (!params.tagGroups) params.tagGroups = [];
values: [...tagValues.value], params.tagGroups.push(tagInfo);
tagFk: selectedTag?.value?.id,
tagSelection: {
name: selectedTag?.value?.name,
},
};
params.tagGroups = tagGroups;
search(); search();
toggleValueFilterDialog();
}; };
const removeTagGroupParam = (params, search, valIndex = null) => { const removeTagGroupParam = (params, search, valIndex = null) => {
if (!params.tagGroups) return;
if (!valIndex) { if (!valIndex) {
params.tagGroups = null; params.tagGroups = null;
tagValues.value = [{}]; search();
} else { } else {
(tagValues.value || []).splice(valIndex, 1); params.tagGroups.splice(valIndex, 1);
params.tagGroups.values.splice(valIndex, 1); search();
} }
search();
}; };
const setCategoryList = (data) => { const setCategoryList = (data) => {
@ -160,37 +149,13 @@ function addOrder(value, field, params) {
vnFilterPanelRef.value.search(); vnFilterPanelRef.value.search();
} }
const getSelectedTagValues = async (tag) => { const toggleValueFilterDialog = () => {
try { showValueFilterDialog.value = !showValueFilterDialog.value;
if (!tag?.id) return;
const filter = {
fields: ['value'],
order: 'value ASC',
limit: 30,
};
const url = `Tags/${tag?.id}/filterValue`;
console.log('url', url);
const params = { filter: JSON.stringify(filter) };
const { data } = await axios.get(url, {
params,
});
tagOptions.value = data;
} catch (err) {
console.error('Error getting selected tag values');
}
}; };
onMounted(() => { onMounted(() => {
selectedCategoryFk.value = getParamWhere(route, 'categoryFk'); selectedCategoryFk.value = getParamWhere(route, 'categoryFk');
selectedTypeFk.value = getParamWhere(route, 'typeFk'); selectedTypeFk.value = getParamWhere(route, 'typeFk');
if (route.query.params && JSON.parse(route.query.params).tagGroups) {
const tagGroups = JSON.parse(route.query.params).tagGroups;
tagValues.value = [...tagGroups.values];
selectedTag.value = (props.tags || []).find(
(tag) => tag.name === tagGroups.tagSelection.name
);
}
}); });
</script> </script>
@ -202,15 +167,11 @@ onMounted(() => {
:hidden-tags="['orderFk', 'orderBy']" :hidden-tags="['orderFk', 'orderBy']"
:un-removable-params="['orderFk', 'orderBy']" :un-removable-params="['orderFk', 'orderBy']"
:expr-builder="exprBuilder" :expr-builder="exprBuilder"
:custom-tags="['tagGroups']" :custom-tags="['tagGroups', 'categoryFk']"
@remove="clearFilter"
:redirect="false" :redirect="false"
> >
<template #tags="{ tag, formatFn }"> <template #tags="{ tag, formatFn }">
<strong v-if="tag.label === 'categoryFk'"> <strong v-if="tag.label === 'typeFk'">
{{ t(selectedCategory?.name || '') }}
</strong>
<strong v-else-if="tag.label === 'typeFk'">
{{ t(selectedType?.name || '') }} {{ t(selectedType?.name || '') }}
</strong> </strong>
<div v-else class="q-gutter-x-xs"> <div v-else class="q-gutter-x-xs">
@ -219,24 +180,33 @@ onMounted(() => {
</div> </div>
</template> </template>
<template #customTags="{ tags: customTags, params, searchFn }"> <template #customTags="{ tags: customTags, params, searchFn }">
<template v-for="tag in customTags" :key="tag.label"> <template v-for="customTag in customTags" :key="customTag.label">
<template v-if="tag.label === 'tagGroups'"> <VnFilterPanelChip
<VnFilterPanelChip v-for="(tag, valIndex) in Array.isArray(customTag.value)
removable ? customTag.value
@remove="removeTagGroupParam(params, searchFn)" : 1"
> :key="valIndex"
<strong class="q-mr-xs"> removable
{{ tag.value?.tagSelection?.name }}: @remove="
</strong> customTag.label === 'categoryFk'
<span> ? resetCategory(params, searchFn)
{{ : removeTagGroupParam(params, searchFn, valIndex)
(tag.value?.values || []) "
.map((item) => `"${item.value}"`) >
.join(', ') <strong v-if="customTag.label === 'categoryFk'">
}} {{ t(selectedCategory?.name || '') }}
</span> </strong>
</VnFilterPanelChip> <strong v-if="tag?.tagSelection?.name" class="q-mr-xs">
</template> {{ tag.tagSelection.name }}:
</strong>
<span>
{{
(tag?.values || [])
.map((item) => `"${item.value}"`)
.join(', ')
}}
</span>
</VnFilterPanelChip>
</template> </template>
</template> </template>
<template #body="{ params, searchFn }"> <template #body="{ params, searchFn }">
@ -320,70 +290,43 @@ onMounted(() => {
</QItemSection> </QItemSection>
</QItem> </QItem>
<QSeparator /> <QSeparator />
<QItem class="q-mt-md">
<QItemSection> <QItem class="q-mt-lg">
<VnSelect
:label="t('params.tag')"
v-model="selectedTag"
:options="props.tags || []"
option-value="id"
option-label="name"
dense
outlined
rounded
:emit-value="false"
use-input
@update:model-value="($event) => getSelectedTagValues($event)"
/>
</QItemSection>
</QItem>
<QItem
v-for="(value, index) in tagValues"
:key="value"
class="q-mt-md filter-value"
>
<VnSelect
v-if="!selectedTag?.isFree && tagOptions"
:label="t('components.itemsFilterPanel.value')"
v-model="value.value"
:options="tagOptions || []"
option-value="value"
option-label="value"
dense
outlined
rounded
emit-value
use-input
:disable="!value"
:is-clearable="false"
@update:model-value="applyTags(params, searchFn)"
/>
<VnInput <VnInput
v-else
v-model="value.value"
:label="t('components.itemsFilterPanel.value')" :label="t('components.itemsFilterPanel.value')"
:disable="!value"
is-outlined is-outlined
:is-clearable="false" :is-clearable="false"
@keyup.enter="applyTags(params, searchFn)" v-model="generalSearchParam"
/> @keyup.enter="
<QIcon applyTags(
name="delete" { values: [{ value: generalSearchParam }] },
class="filter-icon" params,
@click="removeTagGroupParam(params, searchFn, index)" searchFn
/> )
</QItem> "
<QItem class="q-mt-lg"> >
<QBtn <template #prepend>
icon="add_circle" <QIcon name="search" />
shortcut="+" </template>
flat <template #append>
class="filter-icon" <QBtn
size="md" icon="add_circle"
@click="tagValues.push({})" shortcut="+"
/> flat
color="primary"
size="md"
@click="toggleValueFilterDialog()"
/>
</template>
</VnInput>
</QItem> </QItem>
<QSeparator /> <QSeparator />
<QDialog v-model="showValueFilterDialog">
<CatalogFilterValueDialog
:tags="tags"
@apply-tags="($event) => applyTags($event, params, searchFn)"
/>
</QDialog>
</template> </template>
</VnFilterPanel> </VnFilterPanel>
</template> </template>
@ -416,23 +359,6 @@ onMounted(() => {
cursor: pointer; cursor: pointer;
} }
} }
.filter-icon {
font-size: 24px;
color: $primary;
padding: 0 4px;
cursor: pointer;
}
.filter-input {
flex-shrink: 1;
min-width: 0;
}
.filter-value {
display: flex;
align-items: center;
}
</style> </style>
<i18n> <i18n>