From 480cad0d6f3c4fb3243e4927233752e6c71dea7e Mon Sep 17 00:00:00 2001 From: M_Kececi Date: Sun, 5 Jul 2026 01:02:04 +0300 Subject: [PATCH] Fix product performance grouped JSON build --- .../pages/ProductPerformanceProfitability.vue | 115 +++++++++--------- 1 file changed, 60 insertions(+), 55 deletions(-) diff --git a/ui/src/pages/ProductPerformanceProfitability.vue b/ui/src/pages/ProductPerformanceProfitability.vue index 9e43bb7..4385ee7 100644 --- a/ui/src/pages/ProductPerformanceProfitability.vue +++ b/ui/src/pages/ProductPerformanceProfitability.vue @@ -37,12 +37,14 @@ />
{ }) function maxAutoExpandThroughLevelForTab (tabKey = activeTab.value) { - return Number.isFinite(maxAutoExpandLevelByTab[tabKey]) ? maxAutoExpandLevelByTab[tabKey] : 1 + return Number.isFinite(maxAutoExpandLevelByTab[tabKey]) ? maxAutoExpandLevelByTab[tabKey] : 8 } function maxBackendExpandedKeysForTab (tabKey = activeTab.value) { @@ -2648,6 +2655,11 @@ const autoExpandThroughLevel = computed(() => { return Math.min(requestedLevel, lastGroupLevel, maxAutoExpandThroughLevelForTab()) }) +const fullExpandThroughLevel = computed(() => { + const lastGroupLevel = Math.max(0, activeGroupLevels.value.length - 2) + return Math.min(lastGroupLevel, maxAutoExpandThroughLevelForTab()) +}) + const tableFilterSourceMap = computed(() => ({ products: { rows: filterSourceRowsForTab('products', rows.value), columns: productColumns.value }, product_detail: { rows: filterSourceRowsForTab('product_detail', detailProductRows.value), columns: productDetailColumns.value }, @@ -2693,24 +2705,25 @@ const activeGroupSourceRows = computed(() => { const columnFilterOptionMap = computed(() => { const out = {} - for (const [tableKey, source] of Object.entries(tableFilterSourceMap.value)) { - out[tableKey] = {} - for (const col of source.columns) { - if (!isColumnFilterable(col.name)) continue - const seen = new Map() - for (const row of source.rows) { - const value = columnFilterValue(row, col) - if (!value) continue - if (!seen.has(value)) { - seen.set(value, { - label: columnFilterLabel(row, col), - value - }) - } + const tableKey = isProductKpiTab.value ? activeProductTableKey.value : activeTab.value + const source = tableFilterSourceMap.value[tableKey] + if (!source) return out + out[tableKey] = {} + for (const col of source.columns) { + if (!isColumnFilterable(col.name)) continue + const seen = new Map() + for (const row of source.rows) { + const value = columnFilterValue(row, col) + if (!value) continue + if (!seen.has(value)) { + seen.set(value, { + label: columnFilterLabel(row, col), + value + }) } - out[tableKey][col.name] = Array.from(seen.values()) - .sort((a, b) => String(a.label).localeCompare(String(b.label), 'tr', { numeric: true })) } + out[tableKey][col.name] = Array.from(seen.values()) + .sort((a, b) => String(a.label).localeCompare(String(b.label), 'tr', { numeric: true })) } return out }) @@ -2733,6 +2746,18 @@ const displayIdleTableRows = computed(() => backendRowsForTab('idle', idleTableR const displayOrderProductCustomerTableRows = computed(() => backendRowsForTab('order_product_customers', orderProductCustomerTableRows.value)) const displayOrderMarketDetailTableRows = computed(() => backendRowsForTab('order_market_details', orderMarketDetailTableRows.value)) const displayActiveSalesBreakdownTableRows = computed(() => backendRowsForTab(activeTab.value, activeSalesBreakdownTableRows.value)) +const activeDisplayedTableRows = computed(() => { + if (isProductKpiTab.value) return displayProductKpiTableRows.value + if (activeTab.value === 'idle') return displayIdleTableRows.value + if (activeTab.value === 'order_product_customers') return displayOrderProductCustomerTableRows.value + if (activeTab.value === 'order_market_details') return displayOrderMarketDetailTableRows.value + if (salesBreakdownTabKeys.includes(activeTab.value)) return displayActiveSalesBreakdownTableRows.value + if (activeTab.value === 'general') return filteredGeneralRows.value + if (activeTab.value === 'markets') return filteredMarketRows.value + if (activeTab.value === 'countries') return filteredCountryRows.value + if (activeTab.value === 'customers') return filteredCustomerRows.value + return [] +}) const detailMainGroupOptions = computed(() => { const grouped = new Map() @@ -2785,7 +2810,7 @@ const productAutoExpandKeys = computed(() => { }) const allProductGroupsExpanded = computed(() => { - return selectedExpandThroughLevel.value >= autoExpandThroughLevel.value + return selectedExpandThroughLevel.value >= fullExpandThroughLevel.value }) function appendGroupRows (out, sourceRows, level, parentKeys, levels = groupLevels) { @@ -3485,6 +3510,15 @@ function toggleGroup (key) { applyActiveExpansionThroughLevel(isGroupExpanded(key) ? level - 1 : level) } +async function toggleAllProductGroups () { + if (allProductGroupsExpanded.value) await collapseAllProductGroups() + else { + detailLevelMenuOpen.value = false + applyActiveExpansionThroughLevel(fullExpandThroughLevel.value) + await nextTick() + } +} + async function collapseAllProductGroups () { if (bulkExpandLoading.value) return detailLevelMenuOpen.value = false @@ -3664,26 +3698,8 @@ function selectAllColumnFilterOptions (tableKey, name) { } function runWithFilterBusy (apply) { - filterBusy.value = true - const done = () => { - filterBusy.value = false - syncExpansionAfterFilterChange() - } - const execute = () => { - apply() - if (typeof window === 'undefined') { - setTimeout(done, 0) - return - } - window.requestAnimationFrame(() => { - window.requestAnimationFrame(done) - }) - } - if (typeof window === 'undefined') { - execute() - return - } - window.requestAnimationFrame(execute) + apply() + syncExpansionAfterFilterChange() } function syncExpansionAfterFilterChange () { @@ -4819,17 +4835,7 @@ watch(activeTab, () => { setupTopScrollbarSync() }) -watch([ - displayProductKpiTableRows, - displayIdleTableRows, - displayOrderProductCustomerTableRows, - displayOrderMarketDetailTableRows, - displayActiveSalesBreakdownTableRows, - filteredGeneralRows, - filteredMarketRows, - filteredCountryRows, - filteredCustomerRows -], () => { +watch(activeDisplayedTableRows, () => { setupTopScrollbarSync() }, { flush: 'post' }) @@ -4846,10 +4852,9 @@ watch(selectedDetailMainGroup, () => { } }) -watch(productTableRows, tableRows => { +watch(activeDisplayedTableRows, tableRows => { if (!isProductKpiTab.value) return - const sourceRows = activeTab.value === 'product_detail' ? displayDetailProductTableRows.value : tableRows - const imageRows = sourceRows + const imageRows = tableRows .filter(row => !row.__group || groupShowsImage(row)) .slice(0, 240) void primeProductImages(imageRows)