From 94c02e2e1cb2afbb2a6d1e9ea10f67d2f2fee8e6 Mon Sep 17 00:00:00 2001 From: ssemenkoff Date: Wed, 13 May 2026 08:55:08 +0200 Subject: [PATCH] Added single measure header for charts and pivot table --- .../lib/datasource/xmla/src/classes/index.ts | 6 ++-- .../xmla/src/utils/MdxRequestConstructor.ts | 21 ++++++++++--- .../xmla/src/utils/MdxRequestHelper.ts | 29 +++++++++-------- .../xmla/src/QueryDesigner/QueryDesigner.vue | 31 ++++++++++++------- .../vue/widget/table/pivot/model/model.ecore | 1 + .../table/pivot/src/PivotTableWidget.vue | 2 +- .../pivot/src/PivotTableWidgetSettings.vue | 5 +-- .../widget/table/pivot/src/gen/PivotTable.ts | 1 + 8 files changed, 60 insertions(+), 36 deletions(-) diff --git a/packages/lib/datasource/xmla/src/classes/index.ts b/packages/lib/datasource/xmla/src/classes/index.ts index ebda237e5..461d5738d 100644 --- a/packages/lib/datasource/xmla/src/classes/index.ts +++ b/packages/lib/datasource/xmla/src/classes/index.ts @@ -187,7 +187,7 @@ export class XmlaStore extends BaseDatasource { if (this.useMdx) { request = this.mdx } else { - request = await this.getMdxRequest() + request = await this.getMdxRequest(requestConfig) } console.log('MDX Request in store:', request) @@ -221,7 +221,7 @@ export class XmlaStore extends BaseDatasource { return response } - async getMdxRequest() { + async getMdxRequest(requestConfig: any = {}) { await this.loadMetadata() const properties = this.metadata.getProperties() const levels = this.metadata.getLevels() @@ -235,7 +235,7 @@ export class XmlaStore extends BaseDatasource { this.requestParams.rows, this.requestParams.columns, this.requestParams.measures, - {}, + requestConfig, properties, this.requestParams.filters, levels, diff --git a/packages/lib/datasource/xmla/src/utils/MdxRequestConstructor.ts b/packages/lib/datasource/xmla/src/utils/MdxRequestConstructor.ts index 170db6356..b1e988e75 100644 --- a/packages/lib/datasource/xmla/src/utils/MdxRequestConstructor.ts +++ b/packages/lib/datasource/xmla/src/utils/MdxRequestConstructor.ts @@ -30,6 +30,11 @@ export async function getMdxRequest( filters: any[], levels: any[], ) { + if (measures.length === 1 && pivotTableSettings?.showSingleMeasureHeader === false) { + rows = rows.filter(e => e.type !== 'Values') + columns = columns.filter(e => e.type !== 'Values') + } + const filtersRequest = getFiltersRequest(filters) if (!rows.length || !columns.length) { @@ -50,7 +55,8 @@ export async function getMdxRequest( } else { let withSection = 'WITH' let selectSection = 'SELECT' - const fromSection = getFromPart(measures, cubename, filtersRequest.where) + const hasValues = rows.some((e: any) => e.type === 'Values') || columns.some((e: any) => e.type === 'Values') + const fromSection = getFromPart(measures, cubename, filtersRequest.where, hasValues) if (!pivotTableSettings.showEmpty) selectSection += ' NON EMPTY' @@ -377,8 +383,10 @@ async function getSingleHierarchyRequest( filtersRequest: any, levels: any[], ) { + const forceValues = (rows.length === 0 && columns.length === 0 && measures.length > 0 && pivotTableSettings?.showSingleMeasureHeader !== false) + const hasValues = rows.some((e: any) => e.type === 'Values') || columns.some((e: any) => e.type === 'Values') || forceValues const selectPart = getSelectWithOptions(pivotTableSettings) - const fromPart = getFromPart(measures, cubename, filtersRequest.where) + const fromPart = getFromPart(measures, cubename, filtersRequest.where, hasValues) if (rows.length) { const request = await getRowsRequest( @@ -433,8 +441,11 @@ async function getSingleHierarchyRequest( ${fromPart} ` } else if (measures.length) { + const selectRequest = measures.map((e: any) => e.originalItem.MEASURE_UNIQUE_NAME).join(',') return ` - SELECT ${fromPart} + ${selectPart} + {${selectRequest}} ON 0 + ${fromPart} ` } return '' @@ -446,9 +457,9 @@ function getSelectWithOptions(pivotTableSettings: any) { return result } -function getFromPart(measures: any[], cubename: string, filtersWhere: any) { +function getFromPart(measures: any[], cubename: string, filtersWhere: any, hasValues: boolean = false) { let measuresPart = '' - if (measures.length === 1) { + if (measures.length === 1 && !hasValues) { measuresPart = `${measures[0].originalItem.MEASURE_UNIQUE_NAME}` } diff --git a/packages/lib/datasource/xmla/src/utils/MdxRequestHelper.ts b/packages/lib/datasource/xmla/src/utils/MdxRequestHelper.ts index 5f5c6d395..63a8212db 100644 --- a/packages/lib/datasource/xmla/src/utils/MdxRequestHelper.ts +++ b/packages/lib/datasource/xmla/src/utils/MdxRequestHelper.ts @@ -105,7 +105,7 @@ const parseMdxRequest = (mdxResponce: any, params: QueryParams) => { console.log('Params in helper', params) - columns[0].forEach((col: any) => { + columns[0]?.forEach((col: any) => { // const colPropsShown = pivotTableStore.state.membersWithProps.includes( // col.HIERARCHY_UNIQUE_NAME, // ); @@ -118,7 +118,7 @@ const parseMdxRequest = (mdxResponce: any, params: QueryParams) => { columnProperties.push(...colProps); }); - rows[0].forEach((row: any) => { + rows[0]?.forEach((row: any) => { // const rowPropsShown = pivotTableStore.state.membersWithProps.includes( // row.HIERARCHY_UNIQUE_NAME, // ); @@ -299,31 +299,34 @@ const parseRequestToTable = (mdxResponce: any, mainAxis = 0) => { rowProperties: {}, } as any + const getCaption = (member: any) => { + return optionalArrayToArray(member).map(m => m.Caption).join(' - ') + } + if (mainAxis === 0) { axis1.forEach((item, index) => { - const newItem = item.Member.Caption - table.headers.push(newItem) + table.headers.push(getCaption(item.Member)) }) axis0.forEach((item, i) => { - console.log(i) - table.rows[i] = [item.Member.Caption] - table.rowProperties[item.Member.Caption] = item.Member; + const caption = getCaption(item.Member) + table.rows[i] = [caption] + table.rowProperties[caption] = item.Member; axis1.forEach((subItem, j) => { - table.rows[i].push(cellsArray[j * axis0.length + i].Value) + table.rows[i].push(cellsArray[j * axis0.length + i]?.Value) }) }) } else if (mainAxis === 1) { axis0.forEach((item, index) => { - const newItem = item.Member.Caption - table.headers.push(newItem) + table.headers.push(getCaption(item.Member)) }) axis1.forEach((item, i) => { - table.items[i] = [item.Member.Caption] - table.rowProperties[item.Member.Caption] = item.Member; + const caption = getCaption(item.Member) + table.items[i] = [caption] + table.rowProperties[caption] = item.Member; axis0.forEach((subItem, j) => { - table.items[i].push(cellsArray[i * axis0.length + j].Value) + table.items[i].push(cellsArray[i * axis0.length + j]?.Value) }) }) } diff --git a/packages/ui/vue/common/xmla/src/QueryDesigner/QueryDesigner.vue b/packages/ui/vue/common/xmla/src/QueryDesigner/QueryDesigner.vue index 221520463..7d5813b21 100644 --- a/packages/ui/vue/common/xmla/src/QueryDesigner/QueryDesigner.vue +++ b/packages/ui/vue/common/xmla/src/QueryDesigner/QueryDesigner.vue @@ -150,21 +150,28 @@ const changeMeasures = (e: any) => { } } - if (queryConfig.value.measures.length > 1) { - queryConfig.value.columns.push({ - type: "Values", - id: "Values", - children: [], - caption: "Values", - originalItem: { - HIERARCHY_UNIQUE_NAME: "Values", - } as any, - filters: null as any, - }); + if (queryConfig.value.measures.length > 0) { + const hasValues = queryConfig.value.columns.some((e: any) => e.type === 'Values') || + queryConfig.value.rows.some((e: any) => e.type === 'Values'); + if (!hasValues) { + queryConfig.value.columns.push({ + type: "Values", + id: "Values", + children: [], + caption: "Values", + originalItem: { + HIERARCHY_UNIQUE_NAME: "Values", + } as any, + filters: null as any, + }); + } } else { queryConfig.value.columns = queryConfig.value.columns.filter( (e) => (e as any).type !== 'Values', ); + queryConfig.value.rows = queryConfig.value.rows.filter( + (e) => (e as any).type !== 'Values', + ); } }; @@ -178,7 +185,7 @@ const remove = ( const index = areaContent.findIndex((e) => e.id === item.id); if (area === "measures") { - if (areaContent.length === 2) { + if (areaContent.length === 1) { queryConfig.value["rows"] = queryConfig.value[ "rows" ].filter((e) => (e as any).type !== "Values"); diff --git a/packages/ui/vue/widget/table/pivot/model/model.ecore b/packages/ui/vue/widget/table/pivot/model/model.ecore index 7d253abb2..5e6b2f0d9 100644 --- a/packages/ui/vue/widget/table/pivot/model/model.ecore +++ b/packages/ui/vue/widget/table/pivot/model/model.ecore @@ -88,6 +88,7 @@ + diff --git a/packages/ui/vue/widget/table/pivot/src/PivotTableWidget.vue b/packages/ui/vue/widget/table/pivot/src/PivotTableWidget.vue index 46a6ab0bf..b95c66c9d 100644 --- a/packages/ui/vue/widget/table/pivot/src/PivotTableWidget.vue +++ b/packages/ui/vue/widget/table/pivot/src/PivotTableWidget.vue @@ -220,6 +220,7 @@ const stylingProps = computed(() => ({ const dataProps = computed(() => ({ showRowsProperties: config.value?.showRowsProperties || defaultConfig.showRowsProperties, showColumnsProperties: config.value?.showColumnsProperties || defaultConfig.showColumnsProperties, + showSingleMeasureHeader: config.value?.showSingleMeasureHeader ?? defaultConfig.showSingleMeasureHeader, })) const data = ref(null as any); @@ -230,7 +231,6 @@ watch(datasourceId, (newVal, oldVal) => { }) watch(() => dataProps.value, () => { - console.log(dataProps.value); update(); }); diff --git a/packages/ui/vue/widget/table/pivot/src/PivotTableWidgetSettings.vue b/packages/ui/vue/widget/table/pivot/src/PivotTableWidgetSettings.vue index 585fa866d..534b404f6 100644 --- a/packages/ui/vue/widget/table/pivot/src/PivotTableWidgetSettings.vue +++ b/packages/ui/vue/widget/table/pivot/src/PivotTableWidgetSettings.vue @@ -119,8 +119,9 @@ const needsResultColors = (type?: string) => {