fix/OrderCatalog #893
|
@ -119,7 +119,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);
|
||||||
|
|
|
@ -57,7 +57,6 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
defineExpose({ search, sanitizer });
|
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([
|
||||||
'update:modelValue',
|
'update:modelValue',
|
||||||
'refresh',
|
'refresh',
|
||||||
|
@ -170,9 +169,29 @@ const tagsList = computed(() => {
|
||||||
return tagList;
|
return tagList;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const formatTags = (tags) => {
|
||||||
jsegarra marked this conversation as resolved
|
|||||||
|
const formattedTags = [];
|
||||||
|
tags.forEach((tag) => {
|
||||||
|
if (tag.label === 'and') {
|
||||||
|
tag.value.forEach((item) => {
|
||||||
|
for (const key in item) {
|
||||||
|
formattedTags.push({ label: key, value: item[key] });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
formattedTags.push(tag);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return formattedTags;
|
||||||
|
};
|
||||||
|
|
||||||
const tags = computed(() => {
|
const tags = computed(() => {
|
||||||
return tagsList.value.filter((tag) => !($props.customTags || []).includes(tag.label));
|
const filteredTags = tagsList.value.filter(
|
||||||
|
(tag) => !($props.customTags || []).includes(tag.label)
|
||||||
|
);
|
||||||
|
return formatTags(filteredTags);
|
||||||
});
|
});
|
||||||
|
|
||||||
const customTags = computed(() =>
|
const customTags = computed(() =>
|
||||||
tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label))
|
tagsList.value.filter((tag) => ($props.customTags || []).includes(tag.label))
|
||||||
);
|
);
|
||||||
|
@ -193,13 +212,20 @@ function formatValue(value) {
|
||||||
|
|
||||||
function sanitizer(params) {
|
function sanitizer(params) {
|
||||||
for (const [key, value] of Object.entries(params)) {
|
for (const [key, value] of Object.entries(params)) {
|
||||||
if (value && typeof value === 'object') {
|
if (key === 'and' && Array.isArray(value)) {
|
||||||
|
value.forEach((item) => {
|
||||||
|
Object.assign(params, item);
|
||||||
|
});
|
||||||
|
delete params[key];
|
||||||
|
} else if (value && typeof value === 'object') {
|
||||||
const param = Object.values(value)[0];
|
const param = Object.values(value)[0];
|
||||||
if (typeof param == 'string') params[key] = param.replaceAll('%', '');
|
if (typeof param == 'string') params[key] = param.replaceAll('%', '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defineExpose({ search, sanitizer, userParams });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -10,11 +10,19 @@ function parseJSON(str, fallback) {
|
||||||
export default function (route, param) {
|
export default function (route, param) {
|
||||||
// catch route query params
|
// catch route query params
|
||||||
const params = parseJSON(route?.query?.params, {});
|
const params = parseJSON(route?.query?.params, {});
|
||||||
|
|
||||||
// extract and parse filter from params
|
// extract and parse filter from params
|
||||||
const { filter: filterStr = '{}' } = params;
|
const { filter: filterStr = '{}' } = params;
|
||||||
|
|
||||||
const where = parseJSON(filterStr, {})?.where;
|
const where = parseJSON(filterStr, {})?.where;
|
||||||
if (where && where[param] !== undefined) {
|
|
||||||
|
if (where && !param) {
|
||||||
|
return where;
|
||||||
|
} else if (where && where.and) {
|
||||||
|
const foundParam = where.and.find((p) => p[param]);
|
||||||
|
if (foundParam) {
|
||||||
|
return foundParam[param];
|
||||||
|
}
|
||||||
|
} else if (where && where[param]) {
|
||||||
return where[param];
|
return where[param];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
<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">
|
||||||
|
<QBtn
|
||||||
|
round
|
||||||
|
color="primary"
|
||||||
|
style="position: absolute; z-index: 1; right: 0; top: 0"
|
||||||
jsegarra marked this conversation as resolved
Outdated
jsegarra
commented
porque pones un valor por defecto si ya tiene el default? porque pones un valor por defecto si ya tiene el default?
wbuezas
commented
Buena observación, había quedado de antes que componentice esta parte. Commit: Buena observación, había quedado de antes que componentice esta parte.
Commit: https://gitea.verdnatura.es/verdnatura/salix-front/commit/498a52a3e5a78c4e8c8f7c58a3cc4b655ca33cac
|
|||||||
|
icon="search"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
</QBtn>
|
||||||
|
|
||||||
|
<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)"
|
||||||
|
/>
|
||||||
|
<QBtn
|
||||||
|
icon="add_circle"
|
||||||
|
shortcut="+"
|
||||||
|
flat
|
||||||
|
class="filter-icon q-mb-md"
|
||||||
|
size="md"
|
||||||
|
dense
|
||||||
|
:disabled="!selectedTag || !tagValues[0].value"
|
||||||
|
@click="tagValues.unshift({})"
|
||||||
|
/>
|
||||||
|
<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 || !selectedTag"
|
||||||
|
: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"
|
||||||
|
/>
|
||||||
|
<QBtn
|
||||||
|
icon="delete"
|
||||||
|
size="md"
|
||||||
|
outlined
|
||||||
|
dense
|
||||||
|
rounded
|
||||||
|
flat
|
||||||
|
class="filter-icon col-2"
|
||||||
|
:disabled="!value.value"
|
||||||
|
@click="removeTagGroupParam(index)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</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>
|
|
@ -1,30 +1,57 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { onMounted, onUnmounted, ref } from 'vue';
|
import { onBeforeMount, onMounted, onUnmounted, ref, computed, watch } from 'vue';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import VnPaginate from 'components/ui/VnPaginate.vue';
|
import VnPaginate from 'components/ui/VnPaginate.vue';
|
||||||
import CatalogItem from 'components/ui/CatalogItem.vue';
|
import CatalogItem from 'components/ui/CatalogItem.vue';
|
||||||
import OrderCatalogFilter from 'pages/Order/Card/OrderCatalogFilter.vue';
|
import OrderCatalogFilter from 'pages/Order/Card/OrderCatalogFilter.vue';
|
||||||
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
|
||||||
|
import getParamWhere from 'src/filters/getParamWhere';
|
||||||
|
import { useArrayData } from 'composables/useArrayData';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const arrayData = useArrayData('OrderCatalogList');
|
||||||
|
const store = arrayData.store;
|
||||||
|
const showFilter = ref(null);
|
||||||
const tags = ref([]);
|
const tags = ref([]);
|
||||||
|
|
||||||
|
let catalogParams = {
|
||||||
|
orderFk: route.params.id,
|
||||||
|
orderBy: JSON.stringify({ field: 'relevancy DESC, name', way: 'ASC', isTag: false }),
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
const whereParams = getParamWhere(route);
|
||||||
|
if (whereParams) {
|
||||||
|
const formattedWhereParams = {};
|
||||||
|
if (whereParams.and) {
|
||||||
|
whereParams.and.forEach((item) => {
|
||||||
|
Object.assign(formattedWhereParams, item);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Object.assign(formattedWhereParams, whereParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
catalogParams = {
|
||||||
|
...catalogParams,
|
||||||
|
...formattedWhereParams,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
showFilter.value = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
stateStore.rightDrawer = true;
|
stateStore.rightDrawer = true;
|
||||||
checkOrderConfirmation();
|
checkOrderConfirmation();
|
||||||
});
|
});
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
|
||||||
|
|
||||||
const catalogParams = {
|
onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
orderFk: route.params.id,
|
|
||||||
orderBy: JSON.stringify({ field: 'relevancy DESC, name', way: 'ASC', isTag: false }),
|
|
||||||
};
|
|
||||||
|
|
||||||
async function checkOrderConfirmation() {
|
async function checkOrderConfirmation() {
|
||||||
const response = await axios.get(`Orders/${route.params.id}`);
|
const response = await axios.get(`Orders/${route.params.id}`);
|
||||||
|
@ -34,6 +61,7 @@ async function checkOrderConfirmation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractTags(items) {
|
function extractTags(items) {
|
||||||
|
if (!items || !items.length) return;
|
||||||
const resultTags = [];
|
const resultTags = [];
|
||||||
(items || []).forEach((item) => {
|
(items || []).forEach((item) => {
|
||||||
(item.tags || []).forEach((tag) => {
|
(item.tags || []).forEach((tag) => {
|
||||||
|
@ -61,6 +89,15 @@ function extractValueTags(items) {
|
||||||
);
|
);
|
||||||
tagValue.value = resultValueTags;
|
tagValue.value = resultValueTags;
|
||||||
}
|
}
|
||||||
|
const autoLoad = computed(() => !!catalogParams.categoryFk);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => store.data,
|
||||||
|
(val) => {
|
||||||
|
extractTags(val);
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -74,11 +111,12 @@ function extractValueTags(items) {
|
||||||
:info="t('You can search items by name or id')"
|
:info="t('You can search items by name or id')"
|
||||||
/>
|
/>
|
||||||
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
|
||||||
<QScrollArea class="fit text-grey-8">
|
<QScrollArea v-if="showFilter" class="fit text-grey-8">
|
||||||
<OrderCatalogFilter
|
<OrderCatalogFilter
|
||||||
data-key="OrderCatalogList"
|
data-key="OrderCatalogList"
|
||||||
:tag-value="tagValue"
|
:tag-value="tagValue"
|
||||||
:tags="tags"
|
:tags="tags"
|
||||||
|
:initial-catalog-params="catalogParams"
|
||||||
/>
|
/>
|
||||||
</QScrollArea>
|
</QScrollArea>
|
||||||
</QDrawer>
|
</QDrawer>
|
||||||
|
@ -89,8 +127,9 @@ function extractValueTags(items) {
|
||||||
url="Orders/CatalogFilter"
|
url="Orders/CatalogFilter"
|
||||||
:limit="50"
|
:limit="50"
|
||||||
:user-params="catalogParams"
|
:user-params="catalogParams"
|
||||||
@on-fetch="extractTags"
|
@on-fetch="showFilter = true"
|
||||||
:update-router="false"
|
:update-router="false"
|
||||||
|
:auto-load="autoLoad"
|
||||||
>
|
>
|
||||||
<template #body="{ rows }">
|
<template #body="{ rows }">
|
||||||
<div class="catalog-list">
|
<div class="catalog-list">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref, onMounted } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
@ -9,10 +9,9 @@ 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';
|
||||||
|
import { useArrayData } from 'composables/useArrayData';
|
||||||
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
dataKey: {
|
dataKey: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -27,13 +26,18 @@ const props = defineProps({
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
const arrayData = useArrayData(props.dataKey);
|
||||||
|
|
||||||
const categoryList = ref(null);
|
const categoryList = ref(null);
|
||||||
const selectedCategoryFk = ref(getParamWhere(route, 'categoryFk'));
|
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 },
|
||||||
|
@ -48,32 +52,24 @@ const orderWayList = ref([
|
||||||
const orderBySelected = ref('relevancy DESC, name');
|
const orderBySelected = ref('relevancy DESC, name');
|
||||||
const orderWaySelected = ref('ASC');
|
const orderWaySelected = ref('ASC');
|
||||||
|
|
||||||
const createValue = (val, done) => {
|
const resetCategory = (params, search) => {
|
||||||
if (val.length > 2) {
|
|
||||||
if (!tagOptions.value.includes(val)) {
|
|
||||||
done(tagOptions.value, 'add-unique');
|
|
||||||
}
|
|
||||||
tagValues.value.push({ value: val });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const resetCategory = () => {
|
|
||||||
selectedCategoryFk.value = null;
|
selectedCategoryFk.value = null;
|
||||||
typeList.value = null;
|
typeList.value = null;
|
||||||
};
|
params.categoryFk = null;
|
||||||
|
params.typeFk = null;
|
||||||
const clearFilter = (key) => {
|
arrayData.store.userFilter = null;
|
||||||
if (key === 'categoryFk') {
|
removeTagGroupParam(params, search);
|
||||||
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;
|
||||||
params.categoryFk = category?.id;
|
params.categoryFk = category?.id;
|
||||||
|
params.typeFk = null;
|
||||||
|
selectedTypeFk.value = null;
|
||||||
loadTypes(category?.id);
|
loadTypes(category?.id);
|
||||||
}
|
}
|
||||||
search();
|
search();
|
||||||
|
@ -86,19 +82,12 @@ const loadTypes = async (categoryFk = selectedCategoryFk.value) => {
|
||||||
typeList.value = data;
|
typeList.value = data;
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectedCategory = computed(() =>
|
const selectedCategory = computed(() => {
|
||||||
(categoryList.value || []).find(
|
return (categoryList.value || []).find(
|
||||||
(category) => category?.id === selectedCategoryFk.value
|
(category) => category?.id === selectedCategoryFk.value
|
||||||
)
|
);
|
||||||
);
|
});
|
||||||
function filterFn(val, update) {
|
|
||||||
update(() => {
|
|
||||||
const needle = val.toLowerCase();
|
|
||||||
tagOptions.value = props.tagValue.filter(
|
|
||||||
(v) => v.toLowerCase().indexOf(needle) > -1
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const selectedType = computed(() => {
|
const selectedType = computed(() => {
|
||||||
return (typeList.value || []).find((type) => type?.id === selectedTypeFk.value);
|
return (typeList.value || []).find((type) => type?.id === selectedTypeFk.value);
|
||||||
});
|
});
|
||||||
|
@ -114,37 +103,26 @@ function exprBuilder(param, value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const applyTagFilter = (params, search) => {
|
const applyTags = (tagInfo, params, search) => {
|
||||||
if (!tagValues.value?.length) {
|
if (!tagInfo || !tagInfo.values.length) {
|
||||||
params.tagGroups = null;
|
params.tagGroups = null;
|
||||||
search();
|
search();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!params.tagGroups) {
|
|
||||||
params.tagGroups = [];
|
if (!params.tagGroups) params.tagGroups = [];
|
||||||
}
|
params.tagGroups.push(tagInfo);
|
||||||
params.tagGroups.push(
|
|
||||||
JSON.stringify({
|
|
||||||
values: tagValues.value.filter((obj) => Object.keys(obj).length > 0),
|
|
||||||
tagSelection: {
|
|
||||||
...selectedTag.value,
|
|
||||||
orgShowField: selectedTag?.value?.name,
|
|
||||||
},
|
|
||||||
tagFk: selectedTag?.value?.tagFk,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
search();
|
search();
|
||||||
selectedTag.value = null;
|
|
||||||
tagValues.value = [{}];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeTagChip = (selection, params, search) => {
|
const removeTagGroupParam = (params, search, valIndex = null) => {
|
||||||
if (params.tagGroups) {
|
if (!valIndex) {
|
||||||
params.tagGroups = (params.tagGroups || []).filter(
|
params.tagGroups = null;
|
||||||
(value) => value !== selection
|
search();
|
||||||
);
|
} else {
|
||||||
|
params.tagGroups.splice(valIndex, 1);
|
||||||
|
search();
|
||||||
}
|
}
|
||||||
search();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const setCategoryList = (data) => {
|
const setCategoryList = (data) => {
|
||||||
|
@ -171,6 +149,11 @@ function addOrder(value, field, params) {
|
||||||
params.orderBy = JSON.stringify(orderBy);
|
params.orderBy = JSON.stringify(orderBy);
|
||||||
vnFilterPanelRef.value.search();
|
vnFilterPanelRef.value.search();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
selectedCategoryFk.value = getParamWhere(route, 'categoryFk');
|
||||||
|
selectedTypeFk.value = getParamWhere(route, 'typeFk');
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -181,15 +164,11 @@ function addOrder(value, field, params) {
|
||||||
: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">
|
||||||
|
@ -198,22 +177,33 @@ function addOrder(value, field, params) {
|
||||||
</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)
|
||||||
v-for="chip in tag.value"
|
? customTag.value
|
||||||
:key="chip"
|
: 1"
|
||||||
removable
|
:key="valIndex"
|
||||||
@remove="removeTagChip(chip, params, searchFn)"
|
removable
|
||||||
>
|
@remove="
|
||||||
<strong> {{ JSON.parse(chip).tagSelection?.name }}: </strong>
|
customTag.label === 'categoryFk'
|
||||||
<span>{{
|
? resetCategory(params, searchFn)
|
||||||
(JSON.parse(chip).values || [])
|
: removeTagGroupParam(params, searchFn, valIndex)
|
||||||
.map((item) => item.value)
|
"
|
||||||
.join(' | ')
|
>
|
||||||
}}</span>
|
<strong v-if="customTag.label === 'categoryFk'">
|
||||||
</VnFilterPanelChip>
|
{{ t(selectedCategory?.name || '') }}
|
||||||
</template>
|
</strong>
|
||||||
|
<strong v-if="tag?.tagSelection?.name" class="q-mr-xs">
|
||||||
jsegarra marked this conversation as resolved
jsegarra
commented
ufff 2 veces la misma comprobacion... ufff 2 veces la misma comprobacion...
|
|||||||
|
{{ 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 }">
|
||||||
|
@ -297,91 +287,46 @@ function addOrder(value, field, params) {
|
||||||
</QItemSection>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QSeparator />
|
<QSeparator />
|
||||||
<QItem class="q-mt-md">
|
|
||||||
<QItemSection>
|
|
||||||
<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
|
|
||||||
/>
|
|
||||||
</QItemSection>
|
|
||||||
</QItem>
|
|
||||||
<QItem
|
|
||||||
v-for="(value, index) in tagValues"
|
|
||||||
:key="value"
|
|
||||||
class="q-mt-md filter-value"
|
|
||||||
>
|
|
||||||
<FetchData
|
|
||||||
v-if="selectedTag"
|
|
||||||
:url="`Tags/${selectedTag}/filterValue`"
|
|
||||||
limit="30"
|
|
||||||
auto-load
|
|
||||||
@on-fetch="(data) => (tagOptions = data)"
|
|
||||||
/>
|
|
||||||
<VnSelect
|
|
||||||
v-if="!selectedTag"
|
|
||||||
:label="t('params.value')"
|
|
||||||
v-model="value.value"
|
|
||||||
:options="tagOptions || []"
|
|
||||||
option-value="value"
|
|
||||||
option-label="value"
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
rounded
|
|
||||||
emit-value
|
|
||||||
use-input
|
|
||||||
class="filter-input"
|
|
||||||
@new-value="createValue"
|
|
||||||
@filter="filterFn"
|
|
||||||
@update:model-value="applyTagFilter(params, searchFn)"
|
|
||||||
/>
|
|
||||||
<VnSelect
|
|
||||||
v-else-if="selectedTag === 1"
|
|
||||||
:label="t('params.value')"
|
|
||||||
v-model="value.value"
|
|
||||||
:options="tagOptions || []"
|
|
||||||
option-value="value"
|
|
||||||
option-label="value"
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
rounded
|
|
||||||
emit-value
|
|
||||||
use-input
|
|
||||||
class="filter-input"
|
|
||||||
@new-value="createValue"
|
|
||||||
@update:model-value="applyTagFilter(params, searchFn)"
|
|
||||||
/>
|
|
||||||
<VnInput
|
|
||||||
v-else
|
|
||||||
:label="t('params.value')"
|
|
||||||
v-model="value.value"
|
|
||||||
dense
|
|
||||||
outlined
|
|
||||||
rounded
|
|
||||||
class="filter-input"
|
|
||||||
@keyup.enter="applyTagFilter(params, searchFn)"
|
|
||||||
/>
|
|
||||||
<QIcon
|
|
||||||
name="delete"
|
|
||||||
class="filter-icon"
|
|
||||||
@click="(tagValues || []).splice(index, 1)"
|
|
||||||
/>
|
|
||||||
</QItem>
|
|
||||||
<QItem class="q-mt-lg">
|
<QItem class="q-mt-lg">
|
||||||
<QBtn
|
<VnSelect
|
||||||
icon="add_circle"
|
:label="t('components.itemsFilterPanel.value')"
|
||||||
shortcut="+"
|
:options="props.tagValue"
|
||||||
flat
|
dense
|
||||||
class="filter-icon"
|
outlined
|
||||||
@click="tagValues.push({})"
|
rounded
|
||||||
/>
|
:is-clearable="false"
|
||||||
|
v-model="generalSearchParam"
|
||||||
|
@update:model-value="
|
||||||
|
applyTags(
|
||||||
|
{ values: [{ value: generalSearchParam }] },
|
||||||
|
params,
|
||||||
|
searchFn
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<QIcon name="search" />
|
||||||
|
</template>
|
||||||
|
<template #after>
|
||||||
|
<QBtn
|
||||||
|
icon="add_circle"
|
||||||
|
shortcut="+"
|
||||||
|
flat
|
||||||
|
color="primary"
|
||||||
|
size="md"
|
||||||
|
/>
|
||||||
|
<QPopupProxy>
|
||||||
|
<CatalogFilterValueDialog
|
||||||
|
style="display: inline-block"
|
||||||
|
:tags="tags"
|
||||||
|
@apply-tags="
|
||||||
|
($event) => applyTags($event, params, searchFn)
|
||||||
jsegarra marked this conversation as resolved
Outdated
jsegarra
commented
Prueba con QPopupProxy mejor que dialogo porque así se abre en la misma región y no hay que mover tanto el ratón y vista. Prueba con QPopupProxy mejor que dialogo porque así se abre en la misma región y no hay que mover tanto el ratón y vista.
También nos facilita copiar y pegar valores
wbuezas
commented
Coincido, Commit: Coincido, `QPopupProxy` aplicado.
Commit: https://gitea.verdnatura.es/verdnatura/salix-front/commit/52a2250acc721f80a9a5e5d85dd4b9bad99ea1df
|
|||||||
|
"
|
||||||
|
/>
|
||||||
|
</QPopupProxy>
|
||||||
|
</template>
|
||||||
|
</VnSelect>
|
||||||
</QItem>
|
</QItem>
|
||||||
<QSeparator />
|
<QSeparator />
|
||||||
</template>
|
</template>
|
||||||
|
@ -416,23 +361,6 @@ function addOrder(value, field, params) {
|
||||||
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>
|
||||||
|
|
Loading…
Reference in New Issue
La IA me ha propiesto esta solucion
const formatTags = (tags) => { return tags.flatMap((tag) => tag.label === 'and' ? tag.value.flatMap(item => Object.entries(item).map(([key, value]) => ({ label: key, value })) ) : [tag] ); };
Con reduce es mas complejo
Decidí no aplicar la sugerencia ya que considero que complejiza y hace el codigo más dificil de leer / mantener.