From 3b8f0381f67fd3ff89557dac2d473ef49e3f75ea Mon Sep 17 00:00:00 2001 From: amansinghbais Date: Tue, 30 Jul 2024 12:40:18 +0530 Subject: [PATCH 1/9] Improved: product filters fetching, searching and infinite scrolling logic (#360) --- src/components/AddProductFiltersModal.vue | 75 ++++++++++++----------- src/store/modules/util/UtilState.ts | 1 + src/store/modules/util/actions.ts | 31 ++++++++++ src/store/modules/util/getters.ts | 3 + src/store/modules/util/index.ts | 3 +- src/store/modules/util/mutation-types.ts | 3 +- src/store/modules/util/mutations.ts | 3 + 7 files changed, 80 insertions(+), 39 deletions(-) diff --git a/src/components/AddProductFiltersModal.vue b/src/components/AddProductFiltersModal.vue index e3ed9475..aafbb381 100644 --- a/src/components/AddProductFiltersModal.vue +++ b/src/components/AddProductFiltersModal.vue @@ -22,8 +22,14 @@ - - +
+ + + {{ translate("Fetching filters") }} + +
+ + {{ option.label }} {{ option.label }} @@ -70,28 +76,36 @@ import { IonNote, IonRow, IonSearchbar, + IonSpinner, IonTitle, IonToolbar, modalController } from "@ionic/vue"; import { closeOutline, saveOutline } from 'ionicons/icons'; import { useStore } from "vuex"; -import { UtilService } from "@/services/UtilService"; import { translate } from '@hotwax/dxp-components'; -import { hasError } from "@/utils"; const queryString = ref(''); -const facetOptions = ref([]) as any; const isScrollable = ref(true); const selectedValues = ref([]) as any; +const isLoading = ref(false); +const filteredOptions = ref([]) as any; + +const pageSize = process.env.VUE_APP_VIEW_SIZE; +const currentPage = ref(0); const props = defineProps(["label", "facetToSelect", "searchfield", "type"]); const store = useStore(); const appliedFilters = computed(() => store.getters["util/getAppliedFilters"]); +const facetOptions = computed(() => store.getters["util/getFacetOptions"]); -onMounted(() => { +onMounted(async() => { + isLoading.value = true; + await store.dispatch("util/fetchProductFilters", { facetToSelect: props.facetToSelect, searchfield: props.searchfield }) + getFilters(); selectedValues.value = JSON.parse(JSON.stringify(appliedFilters.value[props.type][props.searchfield])) + isLoading.value = false; }) function closeModal() { @@ -99,47 +113,34 @@ function closeModal() { } function search() { + isScrollable.value = true; + currentPage.value = 0; + filteredOptions.value = [] + getFilters(); } -async function getFilters(vSize?: any, vIndex?: any) { - const viewSize = vSize ? vSize : process.env.VUE_APP_VIEW_SIZE; - const viewIndex = vIndex ? vIndex : 0; - - const payload = { - facetToSelect: props.facetToSelect, - docType: 'PRODUCT', - coreName: 'enterpriseSearch', - searchfield: props.searchfield, - jsonQuery: '{"query":"*:*","filter":["docType:PRODUCT"]}', - noConditionFind: 'N', - limit: viewSize, - q: queryString.value, - term: queryString.value, - offset: viewSize * viewIndex, +async function loadMoreFilters(event: any){ + getFilters().then(() => { + event.target.complete(); + }) +} + +async function getFilters() { + let options = facetOptions.value + if(queryString.value) { + options = facetOptions.value.filter((option: any) => option.label.toLowerCase().includes(queryString.value.toLowerCase())) } - const resp = await UtilService.fetchFacets(payload); - if(!hasError(resp)) { - const results = resp.data.facetResponse.response - facetOptions.value = viewIndex === 0 ? results : [...facetOptions.value , ...results]; - isScrollable.value = (facetOptions.value.length % process.env.VUE_APP_VIEW_SIZE) === 0; + const nextPageItems = options.slice(currentPage.value * pageSize, (currentPage.value + 1) * pageSize); + filteredOptions.value = filteredOptions.value.concat(nextPageItems); + currentPage.value += 1; - } else { - facetOptions.value = []; + if(filteredOptions.value.length >= facetOptions.value.length) { isScrollable.value = false; } } -async function loadMoreFilters(event: any){ - getFilters( - undefined, - Math.ceil(facetOptions.value.length / process.env.VUE_APP_VIEW_SIZE).toString() - ).then(() => { - event.target.complete(); - }) -} - function updateSelectedValues(value: string) { selectedValues.value.includes(value) ? selectedValues.value.splice(selectedValues.value.indexOf(value), 1) : selectedValues.value.push(value); } diff --git a/src/store/modules/util/UtilState.ts b/src/store/modules/util/UtilState.ts index 1716b899..daf1014a 100644 --- a/src/store/modules/util/UtilState.ts +++ b/src/store/modules/util/UtilState.ts @@ -6,4 +6,5 @@ export default interface UtilState { selectedSegment: any; pickupGroups: any; pickupGroupFacilities: any; + facetOptions: any; } \ No newline at end of file diff --git a/src/store/modules/util/actions.ts b/src/store/modules/util/actions.ts index 069746ea..18615df0 100644 --- a/src/store/modules/util/actions.ts +++ b/src/store/modules/util/actions.ts @@ -178,6 +178,37 @@ const actions: ActionTree = { return pickupGroupFacilities; }, + async fetchProductFilters({ commit }, params) { + let filters = [], total = 0; + + const payload = { + facetToSelect: params.facetToSelect, + docType: 'PRODUCT', + coreName: 'enterpriseSearch', + searchfield: params.searchfield, + jsonQuery: '{"query":"*:*","filter":["docType:PRODUCT"]}', + noConditionFind: 'N', + limit: -1, + q: "", + term: "", + offset: 0, + } + + try { + const resp = await UtilService.fetchFacets(payload); + if(!hasError(resp)) { + filters = resp.data.facetResponse.response + total = filters.length + } else { + throw resp.data; + } + } catch(error: any) { + logger.error(error); + } + + commit(types.UTIL_FACET_OPTIONS_UPDATED, filters); + }, + async updatePickupGroupFacilities({ commit }, payload) { commit(types.UTIL_PICKUP_GROUP_FACILITIES , payload); }, diff --git a/src/store/modules/util/getters.ts b/src/store/modules/util/getters.ts index 9ec8c000..a2801d6e 100644 --- a/src/store/modules/util/getters.ts +++ b/src/store/modules/util/getters.ts @@ -27,6 +27,9 @@ const getters: GetterTree = { getPickupGroupFacilities(state) { return state.pickupGroupFacilities }, + getFacetOptions(state) { + return state.facetOptions + } } export default getters; \ No newline at end of file diff --git a/src/store/modules/util/index.ts b/src/store/modules/util/index.ts index c88207ec..fa03150d 100644 --- a/src/store/modules/util/index.ts +++ b/src/store/modules/util/index.ts @@ -26,7 +26,8 @@ const utilModule: Module = { }, selectedSegment: "", pickupGroups: [], - pickupGroupFacilities: {} + pickupGroupFacilities: {}, + facetOptions: [] }, getters, actions, diff --git a/src/store/modules/util/mutation-types.ts b/src/store/modules/util/mutation-types.ts index a4a05217..b00c5ff1 100644 --- a/src/store/modules/util/mutation-types.ts +++ b/src/store/modules/util/mutation-types.ts @@ -7,4 +7,5 @@ export const UTIL_FACILITY_GROUPS_UPDATED = SN_UTIL + '/FACILITY_GROUPS_UPDATED' export const UTIL_FACILITY_LIST_UPDATED = SN_UTIL + '/FACILITY_LIST_UPDATED' export const UTIL_SELECTED_SEGMENT_UPDATED = SN_UTIL + '/SELECTED_SEGMENT_UPDATED' export const UTIL_PICKUP_GROUPS_UPDATED = SN_UTIL + '/PICKUP_GROUPS_UPDATED' -export const UTIL_PICKUP_GROUP_FACILITIES = SN_UTIL + '/PICKUP_GROUP_FACILITIES_UPDATED' \ No newline at end of file +export const UTIL_PICKUP_GROUP_FACILITIES = SN_UTIL + '/PICKUP_GROUP_FACILITIES_UPDATED' +export const UTIL_FACET_OPTIONS_UPDATED = SN_UTIL + '/FACET_OPTIONS_UPDATED' \ No newline at end of file diff --git a/src/store/modules/util/mutations.ts b/src/store/modules/util/mutations.ts index 1e645f4b..a8cecf2d 100644 --- a/src/store/modules/util/mutations.ts +++ b/src/store/modules/util/mutations.ts @@ -50,5 +50,8 @@ const mutations: MutationTree = { [types.UTIL_PICKUP_GROUP_FACILITIES](state, payload) { state.pickupGroupFacilities = payload }, + [types.UTIL_FACET_OPTIONS_UPDATED](state, payload) { + state.facetOptions = payload + }, } export default mutations; \ No newline at end of file From 6bffb0cbf7d5dc1389c63a933e71ed2866a5d543 Mon Sep 17 00:00:00 2001 From: amansinghbais Date: Tue, 30 Jul 2024 15:01:24 +0530 Subject: [PATCH 2/9] Fixed: scrolling issue in the product filters modal (#360) --- src/components/AddProductFiltersModal.vue | 25 ++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/components/AddProductFiltersModal.vue b/src/components/AddProductFiltersModal.vue index aafbb381..e1cd76fa 100644 --- a/src/components/AddProductFiltersModal.vue +++ b/src/components/AddProductFiltersModal.vue @@ -14,7 +14,7 @@ - + @@ -50,7 +50,7 @@ - + @@ -86,14 +86,17 @@ import { useStore } from "vuex"; import { translate } from '@hotwax/dxp-components'; const queryString = ref(''); -const isScrollable = ref(true); const selectedValues = ref([]) as any; -const isLoading = ref(false); const filteredOptions = ref([]) as any; - const pageSize = process.env.VUE_APP_VIEW_SIZE; const currentPage = ref(0); +const isScrollable = ref(true); +const isLoading = ref(false); +const isScrollingEnabled = ref(false); +const contentRef = ref({}) as any; +const infiniteScrollRef = ref({}) as any; + const props = defineProps(["label", "facetToSelect", "searchfield", "type"]); const store = useStore(); @@ -157,6 +160,18 @@ async function saveFilters() { await store.dispatch('util/updateAppliedFilters', selectedFilters) modalController.dismiss() } + +function enableScrolling() { + const parentElement = contentRef.value.$el + const scrollEl = parentElement.shadowRoot.querySelector("main[part='scroll']") + let scrollHeight = scrollEl.scrollHeight, infiniteHeight = infiniteScrollRef.value.$el.offsetHeight, scrollTop = scrollEl.scrollTop, threshold = 100, height = scrollEl.offsetHeight + const distanceFromInfinite = scrollHeight - infiniteHeight - scrollTop - threshold - height + if(distanceFromInfinite < 0) { + isScrollingEnabled.value = false; + } else { + isScrollingEnabled.value = true; + } +}