UNPKG

@adaptabletools/adaptable

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

183 lines (182 loc) 8.88 kB
import * as ModuleConstants from '../Utilities/Constants/ModuleConstants'; import { ArrayExtensions } from '../Utilities/Extensions/ArrayExtensions'; import ObjectFactory from '../Utilities/ObjectFactory'; import { AggregatedScalarLiveValue } from '../Utilities/Services/AggregatedScalarLiveValue'; import { CellSummaryStatusPanel } from '../View/CellSummary/CellSummaryStatusPanel'; import { AdaptableModuleBase } from './AdaptableModuleBase'; /** * Module that provides Cell Summaries on numeric columns */ export class CellSummaryModule extends AdaptableModuleBase { constructor(api) { super(ModuleConstants.CellSummaryModuleId, ModuleConstants.CellSummaryFriendlyName, 'cells', 'CellSummaryPopup', 'See summary information on a group of numeric cells using multiple summary operations', api); this.cachedCellSummary = new WeakMap(); } getViewAccessLevel() { return 'Full'; } createColumnMenuItems(column) { if (!this.isModuleAvailable()) { return; } if (column.dataType !== 'number') { return; } return [ this.createMainMenuItemShowPopup({ Name: 'cell-summary-show', Label: 'See Cell Summary', ComponentName: this.moduleInfo.Popup, Icon: this.moduleInfo.Glyph, PopupParams: { source: 'ColumnMenu', column, }, }), ]; } createContextMenuItems(menuContext) { if (!this.isModuleAvailable()) { return; } if (menuContext.adaptableColumn && menuContext.isSelectedCell && menuContext.adaptableColumn.dataType === 'number') { return [ this.createMainMenuItemShowPopup({ Name: 'cell-summary-show', Label: 'See Cell Summary', ComponentName: this.moduleInfo.Popup, Icon: this.moduleInfo.Glyph, PopupParams: { source: 'ContextMenu', }, }), ]; } } createCellSummaryInfo(selectedCellInfo) { if (this.cachedCellSummary.has(selectedCellInfo)) { return this.cachedCellSummary.get(selectedCellInfo); } let selectedCellSummary = ObjectFactory.CreateEmptyCellSummmary(); if (selectedCellInfo && ArrayExtensions.hasOneItem(selectedCellInfo.columns)) { let selectedColumn = selectedCellInfo.columns[0]; if (selectedColumn && selectedColumn.dataType === 'number') { const numberFormatOptions = this.getNumberFormatOptions(selectedColumn); const rowNodes = selectedCellInfo.gridCells.map((gc) => gc.rowNode); const handleExpression = (functionName) => { const aggScalarValue = new AggregatedScalarLiveValue({ aggregatedScalarExpression: `${functionName}([${selectedColumn.columnId}])`, }, ModuleConstants.CellSummaryModuleId, this.api, () => rowNodes); return this.formatValue(numberFormatOptions, selectedColumn, aggScalarValue.getGlobalAggregatedValue(), rowNodes[0]); }; const sumValue = handleExpression('SUM'); const avgValue = handleExpression('AVG'); const modeValue = handleExpression('MODE'); const medianValue = handleExpression('MEDIAN'); const distinctValue = handleExpression('DISTINCT'); const maxValue = handleExpression('MAX'); const minValue = handleExpression('MIN'); const countValue = selectedCellInfo.gridCells.length; const stdDeviation = handleExpression('STD_DEVIATION'); selectedCellSummary = { Sum: sumValue, Average: avgValue, Median: medianValue, Mode: modeValue, Distinct: distinctValue, Max: maxValue, Min: minValue, Count: countValue, Std_Deviation: stdDeviation, Only: distinctValue == 1 ? JSON.stringify(selectedCellInfo.gridCells[0].rawValue) : undefined, }; const weightedAverageConfig = this.getWeightedAverageConfig(selectedColumn.columnId); if (weightedAverageConfig) { const weightedAverage = this.getWeightedAverageCellSummary(weightedAverageConfig, selectedColumn.columnId, rowNodes); if (weightedAverage !== null) { selectedCellSummary.Weighted_Average = this.formatValue(numberFormatOptions, selectedColumn, weightedAverage, rowNodes[0]); } } const customCellSummaryOperations = this.api.cellSummaryApi.getCustomCellSummaryOperations(); customCellSummaryOperations?.forEach((operation) => { if (operation.operationFunction) { const cellSummaryOperationContext = { selectedCellInfo, selectedColumn, ...this.api.internalApi.buildBaseContext(), }; selectedCellSummary[operation.operationName] = operation.operationFunction(cellSummaryOperationContext); } }); this.cachedCellSummary.set(selectedCellInfo, selectedCellSummary); } } return selectedCellSummary; } getNumberFormatOptions(column) { let columnToFormat = column; let adaptableFormat; // first get any Display Formats applied for the column and if provided, then return those // note: this will automatically include any custom formats adaptableFormat = this.api.formatColumnApi.getDisplayFormatForColumn(columnToFormat); if (adaptableFormat) { return adaptableFormat.Options; } // temporary hack until we get the parent for pivot columns - just in case we dont have time... if (columnToFormat.isGeneratedPivotResultColumn) { const parts = columnToFormat.columnId.split('_'); const colid = parts[parts.length - 1]; columnToFormat = this.api.columnApi.getColumnWithColumnId(colid); // check if this pivot result column has been give its own Format and if so return it adaptableFormat = this.api.formatColumnApi.getDisplayFormatForColumn(columnToFormat); if (adaptableFormat) { return adaptableFormat.Options; } } // otherwise get the numeric format in Cell Summary Options (either function or value) const numericDisplayFormat = this.api.optionsApi.getCellSummaryOptions().numericDisplayFormat; if (typeof numericDisplayFormat === 'function') { const context = { column: columnToFormat, ...this.api.internalApi.buildBaseContext(), }; return numericDisplayFormat(context); } else { return numericDisplayFormat; } } formatValue(formatterOptions, column, valueToFormat, node) { return isNaN(valueToFormat) ? valueToFormat : this.api.formatColumnApi.internalApi.getNumberFormattedValue(valueToFormat, node, column, formatterOptions); } getWeightedAverageConfig(columnId) { const weightedAverageConfig = (this.api.layoutApi.getCurrentLayout().TableAggregationColumns || []).find(({ ColumnId, AggFunc }) => typeof AggFunc === 'object' && AggFunc.type === 'weightedAverage' && ColumnId === columnId); return weightedAverageConfig; } getWeightedAverageCellSummary(weightedAverageConfig, columnId, rowNodes) { const weightedColumnId = weightedAverageConfig.AggFunc .weightedColumnId; const expression = `AVG([${columnId}], WEIGHT([${weightedColumnId}]))`; const aggScalarValue = new AggregatedScalarLiveValue({ aggregatedScalarExpression: expression, }, ModuleConstants.CellSummaryModuleId, this.api, () => rowNodes); return aggScalarValue.getGlobalAggregatedValue(); } getViewProperties() { return { getStatusBarPanelProps() { /** * This uses a custom view because it has special logic to * trigger summary operations when the component is rendered. */ return { view: CellSummaryStatusPanel, }; }, }; } }