@adaptabletools/adaptable
Version:
Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
116 lines (115 loc) • 5.87 kB
JavaScript
import { aggregate } from '../ExpressionFunctions/scalarAggregationHelper';
const doOnceFlags = {};
const logOnce = (message, loggingFn) => {
if (doOnceFlags[message]) {
return;
}
loggingFn(message);
doOnceFlags[message] = true;
};
export class AggregatedScalarLiveValue {
constructor(source, requestingModule, adaptableApi, getRowNodes) {
this.source = source;
this.requestingModule = requestingModule;
this.adaptableApi = adaptableApi;
this.getRowNodes = getRowNodes;
if (source.aggregatedScalarExpression) {
this.aggregatedScalarExpression = source.aggregatedScalarExpression;
}
this.expressionEvaluation = source.aggregatedScalarExpression
? this.adaptableApi.internalApi
.getQueryLanguageService()
.evaluateAggregatedScalarExpression(source.aggregatedScalarExpression, requestingModule, getRowNodes).value
: source.aggregatedScalarExpressionEvaluation;
// currently we support only one reducer
this.aggregationReducerName = Object.keys(this.expressionEvaluation.aggregationParams.reducers)[0];
this.aggregationResult = this.computeAggregatedValue(this.expressionEvaluation);
}
refresh() {
if (this.aggregatedScalarExpression) {
this.expressionEvaluation = this.adaptableApi.internalApi
.getQueryLanguageService()
.evaluateAggregatedScalarExpression(this.aggregatedScalarExpression, this.requestingModule, this.getRowNodes).value;
}
// currently we support only one reducer
this.aggregationReducerName = Object.keys(this.expressionEvaluation.aggregationParams.reducers)[0];
this.aggregationResult = this.computeAggregatedValue(this.expressionEvaluation);
}
getAggregatedValueForRow(rowNode) {
const aggregationValue = this.getAggregationValue(rowNode);
if (aggregationValue == undefined) {
logOnce(`${this.aggregatedScalarExpression} :: aggregation value is NOT available!`, (message) => {
this.adaptableApi.logWarn(message);
});
return;
}
if (this.expressionEvaluation.rowValueGetter) {
return this.expressionEvaluation.rowValueGetter(rowNode, aggregationValue);
}
return aggregationValue;
}
getAllAggregationValues() {
if (this.expressionEvaluation.aggregationParams.groupBy?.length) {
const aggregations = this.aggregationResult.deepMap.topDownValues();
return aggregations.map((aggregation) => aggregation.reducerResults[this.aggregationReducerName]);
}
return [this.getGlobalAggregatedValue()];
}
getAggregationValue(rowNode) {
if (this.expressionEvaluation.aggregationParams.groupBy?.length) {
const groupColumns = this.expressionEvaluation.aggregationParams.groupBy.map((groupByParam) => groupByParam.field);
const groupKeys = groupColumns.map((groupColumnName) => this.getRowNodeValueForColumnId(rowNode, groupColumnName));
return this.aggregationResult.deepMap.get(groupKeys)?.reducerResults[this.aggregationReducerName];
}
return this.getGlobalAggregatedValue();
}
getGlobalAggregatedValue() {
return this.aggregationResult.reducerResults[this.aggregationReducerName];
}
getRowNodeValueForColumnId(rowNode, columnId) {
const rawValue = this.adaptableApi.gridApi.getRawValueFromRowNode(rowNode, columnId);
// we need to convert the Date object to a number, otherwise the grouping will not work (each Date instance is unique)
return rawValue instanceof Date ? rawValue.getTime() : rawValue;
}
computeAggregatedValue(expressionEvaluation) {
const gridRowNodes = expressionEvaluation.getRowNodes
? expressionEvaluation.getRowNodes()
: this.adaptableApi.gridApi.getAllRowNodes({
filterFn: expressionEvaluation.rowFilterFn,
});
// we iterate over the RowNode list (we need this to handle complex column values (nested values, valueGetters etc)
// so we will map the fieldNames to RowNode.data
const mapReducerValueGetter = (columnId) => {
return (rowNode) => this.getRowNodeValueForColumnId(rowNode, columnId);
};
Object.values(expressionEvaluation.aggregationParams.reducers).forEach((aggregationReducer) => {
aggregationReducer.getter = mapReducerValueGetter(aggregationReducer.field);
// nullify the field to force the fallback on the getter fn
aggregationReducer.field = null;
});
const mapGroupByToKey = (columnId) => {
return (_unusableProperty, rowNode) => this.getRowNodeValueForColumnId(rowNode, columnId);
};
expressionEvaluation.aggregationParams.groupBy?.forEach((groupByDef) => {
groupByDef.toKey = mapGroupByToKey(groupByDef.field);
});
let aggregatedRowNodes = gridRowNodes;
if (expressionEvaluation.sortByColumn) {
const sortByColumn = expressionEvaluation.sortByColumn;
// currently, we support only ascending sorting
aggregatedRowNodes.sort((first, second) => {
const firstValue = this.getRowNodeValueForColumnId(first, sortByColumn);
const secondValue = this.getRowNodeValueForColumnId(second, sortByColumn);
if (firstValue < secondValue) {
return -1;
}
if (firstValue > secondValue) {
return 1;
}
return 0;
});
}
const result = aggregate(expressionEvaluation.aggregationParams, aggregatedRowNodes);
return result;
}
}