@adaptabletools/adaptable
Version:
Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
134 lines (133 loc) • 6.74 kB
JavaScript
import { CalculatedColumnModuleId } from '../Constants/ModuleConstants';
import { AggregatedScalarLiveValue } from './AggregatedScalarLiveValue';
export class CalculatedColumnExpressionService {
constructor(adaptableApi) {
this.adaptableApi = adaptableApi;
this.aggregatedScalarLiveValuesMap = new Map();
this.adaptableApi = adaptableApi;
}
listentoCellDataChange(cellDataChangedInfo) {
const refreshedCalculatedColumns = [];
this.aggregatedScalarLiveValuesMap.forEach((aggregatedScalarLiveValue, calculatedColumnId) => {
const calculatedColumn = this.adaptableApi.calculatedColumnApi.getCalculatedColumnById(calculatedColumnId);
const columnDependencies = this.adaptableApi.calculatedColumnApi.internalApi.getReferencedColumnIdsForCalculatedColumn(calculatedColumn);
if (columnDependencies.includes(cellDataChangedInfo.column.columnId)) {
aggregatedScalarLiveValue.refresh();
refreshedCalculatedColumns.push(calculatedColumn.ColumnId);
}
});
if (refreshedCalculatedColumns.length) {
this.adaptableApi.gridApi.refreshColumns(refreshedCalculatedColumns);
}
}
listentoRowDataChange(rowDataChangedInfo) {
const refreshedCalculatedColumns = [];
this.aggregatedScalarLiveValuesMap.forEach((aggregatedScalarLiveValue, calculatedColumnId) => {
const calculatedColumn = this.adaptableApi.calculatedColumnApi.getCalculatedColumnById(calculatedColumnId);
aggregatedScalarLiveValue.refresh();
refreshedCalculatedColumns.push(calculatedColumn.ColumnId);
});
if (refreshedCalculatedColumns.length) {
this.adaptableApi.gridApi.refreshColumns(refreshedCalculatedColumns);
}
}
destroy() {
this.aggregatedScalarLiveValuesMap.clear();
this.aggregatedScalarLiveValuesMap = null;
}
getCalculatedColumnDataType(calculatedColumnQuery) {
try {
if (calculatedColumnQuery.AggregatedScalarExpression) {
// currently AggregatedScalarExpression support only numerical values
// TODO AFL try to derive the type from the aggregatedColumn?
// we definitely don't want to aggregate everything only to get the data type
return 'number';
}
let firstRowNode = this.adaptableApi.gridApi.getFirstRowNode();
let firstRowValue = this.adaptableApi.internalApi
.getQueryLanguageService()
.evaluateScalarExpression(calculatedColumnQuery.ScalarExpression, CalculatedColumnModuleId, firstRowNode);
if (firstRowValue instanceof Date) {
return 'date';
}
if (typeof firstRowValue === 'boolean') {
return 'boolean';
}
if (typeof firstRowValue === 'string') {
return 'text';
}
if (typeof firstRowValue === 'number') {
return 'number';
}
if (Array.isArray(firstRowValue)) {
return 'numberArray';
}
}
catch (e) {
this.adaptableApi.logError(`Invalid CalculatedColumn expression ${this.adaptableApi.expressionApi.getAdaptableQueryExpression(calculatedColumnQuery)} :: ${e}`);
return 'number';
}
}
isCalculatedColumnQueryValid(calculatedColumnQuery) {
if (calculatedColumnQuery.ScalarExpression) {
try {
// TODO AFL add a cached validation for ScalarExpression, just like for all the other types
let firstRowNode = this.adaptableApi.gridApi.getFirstRowNode();
this.adaptableApi.internalApi
.getQueryLanguageService()
.evaluateScalarExpression(calculatedColumnQuery.ScalarExpression, CalculatedColumnModuleId, firstRowNode);
return true;
}
catch (e) {
// no logging as this method is used only in the UI
return false;
}
}
if (calculatedColumnQuery.AggregatedScalarExpression) {
const validationResult = this.adaptableApi.expressionApi.isValidAggregatedScalarExpression(calculatedColumnQuery.AggregatedScalarExpression, CalculatedColumnModuleId);
return validationResult;
}
// if query has neither a ScalarExpression nor an AggregatedScalarExpression => it can only be false
return false;
}
evaluateCalculatedColumnQuery(calculatedColumn, rowNode) {
try {
if (this.adaptableApi.gridApi.isGroupRowNode(rowNode)) {
return undefined;
}
// no validation here, this function has to be as performant as possible
if (calculatedColumn?.Query?.ScalarExpression) {
return this.adaptableApi.internalApi
.getQueryLanguageService()
.evaluateScalarExpression(calculatedColumn.Query.ScalarExpression, CalculatedColumnModuleId, rowNode);
}
if (calculatedColumn?.Query?.AggregatedScalarExpression) {
const aggregatedScalarLiveValue = this.aggregatedScalarLiveValuesMap.get(calculatedColumn.Uuid);
return aggregatedScalarLiveValue?.getAggregatedValueForRow(rowNode);
}
}
catch (error) {
this.adaptableApi.logError(`Invalid CalculatedColumn expression ${calculatedColumn?.Query?.ScalarExpression ??
calculatedColumn?.Query?.AggregatedScalarExpression} :: ${error}`);
return null;
}
}
createAggregatedScalarLiveValue(calculatedColumn) {
// if there is already an aggregated scalar, delete it (possible when editing)
this.destroyAggregatedScalarLiveValue(calculatedColumn);
if (calculatedColumn.Query?.AggregatedScalarExpression) {
try {
const aggregatedScalarLiveValue = new AggregatedScalarLiveValue({
aggregatedScalarExpression: calculatedColumn.Query?.AggregatedScalarExpression,
}, CalculatedColumnModuleId, this.adaptableApi);
this.aggregatedScalarLiveValuesMap.set(calculatedColumn.Uuid, aggregatedScalarLiveValue);
}
catch (e) {
this.adaptableApi.logError(`Creating CalculatedColumn ('${calculatedColumn.Query?.AggregatedScalarExpression}') failed!`, e.message);
}
}
}
destroyAggregatedScalarLiveValue(calculatedColumn) {
this.aggregatedScalarLiveValuesMap.delete(calculatedColumn.Uuid);
}
}