diff --git a/WebAPP/AppResults/Controller/Pivot.js b/WebAPP/AppResults/Controller/Pivot.js index b582ffbaa..9da3e1b2c 100644 --- a/WebAPP/AppResults/Controller/Pivot.js +++ b/WebAPP/AppResults/Controller/Pivot.js @@ -9,6 +9,8 @@ import { DataModelResult } from "../../Classes/DataModelResult.Class.js"; import { DefaultObj } from "../../Classes/DefaultObj.Class.js"; export default class Pivot { + static unitLabelMaxChars = 40; + static onLoad() { Base.getSession() .then(response => { @@ -57,6 +59,69 @@ export default class Pivot { }); } + // Convert unique unit labels to plain text with Unicode superscripts and return a comma-separated string. + static getUnitLabel(units) { + const supMap = {'0':'⁰','1':'¹','2':'²','3':'³','4':'⁴','5':'⁵','6':'⁶','7':'⁷','8':'⁸','9':'⁹','-':'⁻'}; + const labels = [...units] + .filter(Boolean) + .map(u => String(u) + .replace(/(-?\d+)<\/sup>/g, (_, n) => + n.split('').map(d => supMap[d]).join('') + ) + .replace(/<[^>]+>/g, '') + ); + if (!labels.length) return ''; + return labels.join(', '); + } + + // Collect distinct raw units from rows that pass the active PivotPanel filters. + static getFilteredUnits(engine) { + const activeFilters = engine.fields.filter(field => field.filter.isActive); + const units = new Set(); + for (const item of engine.collectionView.items) { + const unit = item['Unit']; + if (!unit || units.has(unit)) continue; + if (activeFilters.every(field => field.filter.apply(item))) units.add(unit); + } + return units; + } + + // Update the unit display for Pie, horizontal, and vertical Pivot charts. + static setUnitDisplay(units, pivotChart) { + const flexChart = pivotChart.flexChart; + const chartType = pivotChart.chartType; + const label = Pivot.getUnitLabel(units); + const isPie = chartType === wijmo.olap.PivotChartType.Pie; + const activeChart = isPie ? pivotChart.flexPie : flexChart; + + flexChart.footer = ''; + if (pivotChart.flexPie) pivotChart.flexPie.footer = ''; + + if (!label) { + flexChart.axisX.title = ''; + flexChart.axisY.title = ''; + return; + } + + const isHorizontal = chartType === wijmo.olap.PivotChartType.Bar; + + // Pie charts have no value axis, so show their units in the chart footer. + if (isPie) { + flexChart.axisX.title = ''; + flexChart.axisY.title = ''; + activeChart.footer = 'Units: ' + label; + } else if (!isHorizontal && label.length > Pivot.unitLabelMaxChars) { + flexChart.axisX.title = ''; + flexChart.axisY.title = 'Multiple units'; + activeChart.footer = 'Y-axis units: ' + label; + } else { + const valueAxis = isHorizontal ? flexChart.axisX : flexChart.axisY; + const categoryAxis = isHorizontal ? flexChart.axisY : flexChart.axisX; + categoryAxis.title = ''; + valueAxis.title = label; + } + } + static refreshPage(casename) { Base.setSession(casename) .then(response => { @@ -333,6 +398,15 @@ export default class Pivot { // app.pivotChart.flexChart.palette = wijmo.chart.Palettes.midnight app.pivotChart.flexChart.palette = model.ColorSchemes.osyScheme; + // Recalculate the displayed units from the currently filtered Pivot data. + const updateUnitDisplay = () => { + const filteredUnits = Pivot.getFilteredUnits(app.engine); + Pivot.setUnitDisplay(filteredUnits, app.pivotChart); + }; + + // Refresh units after the PivotEngine finishes applying panel filters. + app.engine.updatedView.addHandler(updateUnitDisplay); + // app.pivotChart.flexChart.axisX.itemFormatter = function (engine, label) { // label.text = wijmo.toPlainText(label.text); // return label; @@ -362,6 +436,7 @@ export default class Pivot { app.pivotChart.rotated = 1; } app.pivotChart.chartType = s.selectedValue; + updateUnitDisplay(); } }); diff --git a/WebAPP/Classes/DataModelResult.Class.js b/WebAPP/Classes/DataModelResult.Class.js index 674d28fab..38b7ec15c 100644 --- a/WebAPP/Classes/DataModelResult.Class.js +++ b/WebAPP/Classes/DataModelResult.Class.js @@ -267,6 +267,7 @@ export class DataModelResult{ $.each(genData['osy-tech'], function (id, tObj) { unitData[group][obj.id][tObj.Tech] = {}; unitData[group][obj.id][tObj.Tech]['years'] = 'years'; + unitData[group][obj.id][tObj.Tech]['number'] = 'number'; unitData[group][obj.id][tObj.Tech]['percent'] = '%'; unitData[group][obj.id][tObj.Tech]['divide'] = '/'; unitData[group][obj.id][tObj.Tech]['multiply'] = '*'; @@ -579,6 +580,7 @@ export class DataModelResult{ if(obj.Tech in techData){ //let rule = paramById[group][param]['unitRule']; + // Some parameters define unitRule under indicator_type instead of directly let rule = paramById[group][param]?.unitRule ?? paramById[group][param]?.indicator_type?.unitRule; @@ -586,22 +588,24 @@ export class DataModelResult{ $.each(techData[obj.Tech].TG, function (id, tg) { let tmp = {}; tmp = JSON.parse(JSON.stringify(chunk)); - tmp['Tech'] = obj.Tech; + tmp['Tech'] = obj.Tech; tmp['TechGroup'] = techGroupNames[tg]; tmp['TechDesc'] = techData[obj.Tech]["Desc"]; tmp['TechGroupDesc'] = techGroupData[tg]["Desc"]; dataT = unitData[group][param][obj.Tech]; - tmp['Unit'] = jsonLogic.apply(rule, {...dataT}); + // Derive emission unit data for the current row only, avoiding stale shared state + const currentDataE = (obj.Emi && obj.Emi in emiData) ? unitData[group][param][obj.Emi] : {}; + tmp['Unit'] = jsonLogic.apply(rule, {...dataT, ...currentDataE}); pivotData.push(tmp); }) }else{ - chunk['Tech'] = obj.Tech; + chunk['Tech'] = obj.Tech; chunk['TechGroup'] = 'No group'; chunk['TechDesc'] = techData[obj.Tech]["Desc"]; chunk['TechGroupDesc'] = 'No group'; dataT = unitData[group][param][obj.Tech]; - - chunk['Unit'] = jsonLogic.apply(rule, {...dataT}); + const currentDataE = (obj.Emi && obj.Emi in emiData) ? unitData[group][param][obj.Emi] : {}; + chunk['Unit'] = jsonLogic.apply(rule, {...dataT, ...currentDataE}); pivotData.push(chunk); } @@ -1105,12 +1109,12 @@ export class DataModelResult{ pivotData.push(tmp); }) }else{ - chunk['Tech'] = obj.Tech; + chunk['Tech'] = obj.Tech; chunk['TechGroup'] = 'No group'; chunk['TechDesc'] = techData[obj.Tech]["Desc"]; chunk['TechGroupDesc'] = 'No group'; dataT = unitData[group][param][obj.Tech]; - + chunk['Unit'] = jsonLogic.apply(rule, {...dataT}); pivotData.push(chunk); } @@ -1145,4 +1149,4 @@ export class DataModelResult{ } -} \ No newline at end of file +} diff --git a/WebAPP/References/smartadmin/css/osy.css b/WebAPP/References/smartadmin/css/osy.css index af0ae9996..3bf3c4c00 100644 --- a/WebAPP/References/smartadmin/css/osy.css +++ b/WebAPP/References/smartadmin/css/osy.css @@ -1225,3 +1225,10 @@ jqx-menu-vertical-material .jqx-menu-item-top-selected-material, .jqx-grid-selec .py-9 { padding-top: 9px !important; padding-bottom: 9px !important; } .py-10 { padding-top: 10px !important; padding-bottom: 10px !important; } +/* Override Wijmo default italic Y-axis title for Pivot chart */ +#pivotChart .wj-axis-y .wj-title, +#pivotChart .wj-axis-y .wj-title tspan, +#pivotChart .wj-axis-x .wj-title, +#pivotChart .wj-axis-x .wj-title tspan { + font-style: normal !important; +}