diff --git a/src/components/VnTable/VnFilter.vue b/src/components/VnTable/VnFilter.vue index 86802ee92..d859d12aa 100644 --- a/src/components/VnTable/VnFilter.vue +++ b/src/components/VnTable/VnFilter.vue @@ -32,7 +32,10 @@ const $props = defineProps({ defineExpose({ addFilter, props: $props }); const model = defineModel(undefined, { required: true }); -const arrayData = useArrayData($props.dataKey, { searchUrl: $props.searchUrl }); +const arrayData = useArrayData( + $props.dataKey, + $props.searchUrl ? { searchUrl: $props.searchUrl } : null +); const columnFilter = computed(() => $props.column?.columnFilter); const updateEvent = { 'update:modelValue': addFilter }; diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue index 941477084..324c49cde 100644 --- a/src/components/VnTable/VnTable.vue +++ b/src/components/VnTable/VnTable.vue @@ -1,20 +1,21 @@ - - - - tableFilterRef - .find((f) => f.props?.column.name == key) - ?.addFilter() - " - > - - - - - - - - - - {{ t(`${chipLocale}.${tag.label}`) }}: - {{ formatFn(tag.value) }} - - - - - + :data-key="$attrs['data-key']" + :columns="columns" + /> +import { ref } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useStateStore } from 'stores/useStateStore'; + +import VnFilterPanel from 'components/ui/VnFilterPanel.vue'; +import VnFilter from 'components/VnTable/VnFilter.vue'; +import VnTableOrder from 'src/components/VnTable/VnOrder.vue'; + +defineProps({ + columns: { + type: Array, + required: true, + }, + chipLocale: { + type: String, + default: null, + }, + searchUrl: { + type: [String, Boolean], + default: 'table', + }, +}); +const { t } = useI18n(); +const stateStore = useStateStore(); + +const tableFilterRef = ref([]); + +function columnName(col) { + const column = { ...col, ...col.columnFilter }; + let name = column.name; + if (column.alias) name = column.alias + '.' + name; + return name; +} + + + + + + + + + + + + + + + {{ t(`${chipLocale}.${tag.label}`) }}: + {{ formatFn(tag.value) }} + + + + + + diff --git a/src/components/common/VnCard.vue b/src/components/common/VnCard.vue index 88d374c74..16a077a79 100644 --- a/src/components/common/VnCard.vue +++ b/src/components/common/VnCard.vue @@ -4,10 +4,7 @@ import { useRoute, useRouter, onBeforeRouteUpdate } from 'vue-router'; import { useArrayData } from 'src/composables/useArrayData'; import { useStateStore } from 'stores/useStateStore'; import useCardSize from 'src/composables/useCardSize'; -import VnSubToolbar from '../ui/VnSubToolbar.vue'; -import VnSearchbar from 'components/ui/VnSearchbar.vue'; import LeftMenu from 'components/LeftMenu.vue'; -import RightMenu from 'components/common/RightMenu.vue'; const props = defineProps({ dataKey: { type: String, required: true }, baseUrl: { type: String, default: undefined }, @@ -29,10 +26,7 @@ const url = computed(() => { } return props.customUrl; }); -const searchRightDataKey = computed(() => { - if (!props.searchDataKey) return route.name; - return props.searchDataKey; -}); + const arrayData = useArrayData(props.dataKey, { url: url.value, filter: props.filter, @@ -59,9 +53,6 @@ if (props.baseUrl) { } - - - diff --git a/src/components/common/VnCardMain.vue b/src/components/common/VnCardMain.vue index 6e0231537..3ebfcfb8b 100644 --- a/src/components/common/VnCardMain.vue +++ b/src/components/common/VnCardMain.vue @@ -12,9 +12,11 @@ defineProps({ + {{ stateStore.isHeaderMounted() }} + diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue index 7319dc866..b59df8990 100644 --- a/src/components/ui/VnFilterPanel.vue +++ b/src/components/ui/VnFilterPanel.vue @@ -1,10 +1,10 @@ @@ -296,7 +250,12 @@ function sanitizer(params) { - + { onBeforeUnmount(() => { arrayData.resetPagination(); + arrayData.reset(['currentFilter', 'userParams', 'userFilter']); }); watch( @@ -197,7 +198,14 @@ async function onLoad(index, done) { done(isDone); } -defineExpose({ fetch, update, addFilter, paginate }); +defineExpose({ + fetch, + update, + addFilter, + paginate, + userParams: arrayData.store.userParams, + currentFilter: arrayData.store.currentFilter, +}); diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js index c36eb9990..c0c744852 100644 --- a/src/composables/useArrayData.js +++ b/src/composables/useArrayData.js @@ -25,11 +25,14 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) { const searchUrl = store.searchUrl; if (query[searchUrl]) { const params = JSON.parse(query[searchUrl]); - const filter = params?.filter && JSON.parse(params?.filter ?? '{}'); + const filter = + params?.filter && typeof params?.filter == 'object' + ? params?.filter + : JSON.parse(params?.filter ?? '{}'); delete params.filter; store.userParams = { ...store.userParams, ...params }; - store.userFilter = { ...filter, ...store.userFilter }; + store.filter = { ...filter, ...store.userFilter }; if (filter?.order) store.order = filter.order; } }); @@ -74,7 +77,6 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) { const filter = { limit: store.limit, }; - let userParams = { ...store.userParams }; Object.assign(filter, store.userFilter); diff --git a/src/composables/useFilterParams.js b/src/composables/useFilterParams.js new file mode 100644 index 000000000..2878e4b76 --- /dev/null +++ b/src/composables/useFilterParams.js @@ -0,0 +1,65 @@ +import { useArrayData } from 'src/composables/useArrayData'; +import { onBeforeMount, ref, watch } from 'vue'; + +export function useFilterParams(key) { + if (!key) throw new Error('ArrayData: A key is required to use this composable'); + const params = ref({}); + const orders = ref({}); + const arrayData = ref({}); + + onBeforeMount(() => { + arrayData.value = useArrayData(key); + }); + + watch( + () => arrayData.value.store?.currentFilter, + (val, oldValue) => (val || oldValue) && setUserParams(val), + { immediate: true, deep: true } + ); + + function parseOrder(urlOrders) { + const orderObject = {}; + if (urlOrders) { + if (typeof urlOrders == 'string') urlOrders = [urlOrders]; + for (const [index, orders] of urlOrders.entries()) { + const [name, direction] = orders.split(' '); + orderObject[name] = { direction, index: index + 1 }; + } + } + orders.value = orderObject; + } + + function setUserParams(watchedParams) { + if (!watchedParams || Object.keys(watchedParams).length == 0) return; + + if (typeof watchedParams == 'string') watchedParams = JSON.parse(watchedParams); + if (typeof watchedParams?.filter == 'string') + watchedParams.filter = JSON.parse(watchedParams.filter); + + watchedParams = { ...watchedParams, ...watchedParams.filter?.where }; + parseOrder(watchedParams.filter?.order); + + delete watchedParams.filter; + params.value = sanitizer(watchedParams); + } + + function sanitizer(params) { + for (const [key, value] of Object.entries(params)) { + 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]; + if (typeof param == 'string') params[key] = param.replaceAll('%', ''); + } + } + return params; + } + + return { + params, + orders, + }; +} diff --git a/src/pages/Account/AccountList.vue b/src/pages/Account/AccountList.vue index 4b8e8fb28..a0e2a3842 100644 --- a/src/pages/Account/AccountList.vue +++ b/src/pages/Account/AccountList.vue @@ -1,11 +1,13 @@ @@ -109,28 +121,24 @@ const exprBuilder = (param, value) => { + + + diff --git a/src/utils/getUserParams.js b/src/utils/getUserParams.js new file mode 100644 index 000000000..e69de29bb