@adaptabletools/adaptable
Version:
Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
271 lines (270 loc) • 12.1 kB
JavaScript
import { ApiBase } from '../Implementation/ApiBase';
import StringExtensions from '../../Utilities/Extensions/StringExtensions';
import FormatHelper from '../../Utilities/Helpers/FormatHelper';
import ObjectFactory from '../../Utilities/ObjectFactory';
import * as ModuleConstants from '../../Utilities/Constants/ModuleConstants';
import { errorOnce } from '../../agGrid/AdaptableLogger';
export class FormatColumnInternalApi extends ApiBase {
/**
* Retrieves all Format Columns in Adaptable State with the `Style` property set
* @returns format columns
*/
getAllFormatColumnWithStyle() {
return this.getFormatColumnApi()
.getFormatColumns()
.filter((fc) => fc.Style);
}
/**
* Retrieves all Format Columns in Adaptable State with the `Style` or the `CellAlignment` property set
* @returns format columns
*/
getAllFormatColumnWithStyleAndCellAlignment() {
return this.getFormatColumnApi()
.getFormatColumns()
.filter((fc) => fc.Style || fc.CellAlignment);
}
/**
* Retrieves all Format Columns in Adaptable State with `DisplayFormat` property set
* @returns format columns
*/
getAllFormatColumnWithDisplayFormat() {
return this.getFormatColumnApi()
.getFormatColumns()
.filter((fc) => fc.DisplayFormat);
}
/**
* Retrieves all Format Columns in Adaptable State with `CellAlignment` property set
* @returns format columns
*/
getAllFormatColumnWithCellAlignment() {
return this.getFormatColumnApi()
.getFormatColumns()
.filter((fc) => fc.CellAlignment);
}
/**
* Get all FormatColumns which are defined for this column and have a custom AdaptableStyle
* @param column
* @param config
* @returns list of FormatColumn
*/
getFormatColumnsWithStyleForColumn(column, config) {
const formatColumns = this.getAllFormatColumnWithStyleAndCellAlignment().filter((formatColumn) => config?.includeSuspended || !formatColumn.IsSuspended);
return this.getFormatColumnWithColumnInScope(formatColumns, column);
}
/**
* Gets Format Column if any for given Column which includes Style element with ClassName
* @param column The Column for which to retrieve the Format Column
* @returns format columns
*/
getFormatColumnWithStyleClassNameForColumn(column, config) {
return this.getFormatColumnsWithStyleForColumn(column, config).filter((formatColumn) => StringExtensions.IsNotNullOrEmpty(formatColumn?.Style?.ClassName));
}
getFormatColumnWithColumnInScope(formatColumns, column) {
return this.getFormatColumnInColumnScope(formatColumns).filter((scopedFormatColumn) => this.getColumnScopeApi().isColumnInScope(column, scopedFormatColumn.Scope));
}
// TODO is this really needed, I don't think it achieves anything
getFormatColumnInColumnScope(formatColumns) {
// we need to maintain the format columns order, therefore we will extract all 3 scope types in a single iteration
return formatColumns.filter((fc) => {
return (
// this.getFormatColumnsWithColumnScope(formatColumns)
(this.getColumnScopeApi().scopeHasColumns(fc.Scope) ||
// this.getFormatColumnsWithDataTypeScope(formatColumns)
this.getColumnScopeApi().scopeHasDataType(fc.Scope) ||
// this.getFormatColumnsWithAllScope(formatColumns)
this.getColumnScopeApi().scopeIsAll(fc.Scope) || this.getColumnScopeApi().scopeHasColumnType(fc.Scope))
);
});
}
/**
* Get all FormatColumns which are defined for this column and have a custom DisplayFormat
* @param column
* @param config
* @returns list of FormatColumn
*/
getFormatColumnsWithDisplayFormatForColumn(column, config) {
const formatColumns = this.getAllFormatColumnWithDisplayFormat().filter((formatColumn) => config?.includeSuspended || !formatColumn.IsSuspended);
return this.getFormatColumnWithColumnInScope(formatColumns, column);
}
/**
* Format value according to format options.
*
* @param customDisplayFormatterContext context that includes value to format
* @param options formatter options
*/
getNumberFormattedValue(value, node, column, options) {
const preparedValue = this.applyCustomFormatters(value, node, column, options);
return FormatHelper.NumberFormatter(preparedValue, options, node, column, this.getAdaptableApi());
}
/**
* Format value according to format options.
*
* @param value context that includes value to format
* @param options formatter options
*/
getStringFormattedValue(value, node, column, options) {
const preparedValue = this.applyCustomFormatters(value, node, column, options);
return FormatHelper.StringFormatter(preparedValue, options, node, column, this.getAdaptableApi());
}
/**
* Format value according to format options.
*
* @param customDisplayFormatterContext context that includes value to format
* @param options formatter options
*/
getDateFormattedValue(value, node, abColumn, options) {
const preparedValue = this.applyCustomFormatters(value, node, abColumn, options);
const dateFormatterOptions = options;
// only use DateFormatter if we have a pattern
return dateFormatterOptions.Pattern
? FormatHelper.DateFormatter(preparedValue, options)
: preparedValue;
}
applyCustomFormatters(value, node, abColumn, options) {
const columnCustomFormatters = options?.CustomDisplayFormats ?? [];
if (!columnCustomFormatters?.length) {
return value;
}
const customFormattersFromOptions = this.getFormatColumnOptions()?.customDisplayFormatters ?? [];
// formatters are applied in the order they are defined in the options
const customFormatters = customFormattersFromOptions.filter((customFormatterOption) => columnCustomFormatters.includes(customFormatterOption.id));
const customDisplayFormatterContext = ObjectFactory.CreateCustomDisplayFormatterContext(value, node, abColumn, this.getAdaptableApi());
return customFormatters.reduce((context, formatter) => {
if (formatter && formatter.handler) {
return formatter.handler(context);
}
return context.cellValue;
}, customDisplayFormatterContext);
}
/**
* Returns all Predicates appropriate for the given Scope
* @param scope Scope to check
*/
getFormatColumnDefsForScope(scope) {
return this.getAdaptableApi()
.predicateApi.internalApi.getFormatColumnPredicateDefs(scope)
.filter((predicateDef) => this.getColumnScopeApi().isScopeInScope(scope, predicateDef.columnScope));
}
/**
* Checks if format column is relevant for a given cell (intersection of given AdaptableColumn and RowNode)
*
* @param formatColumn
* @param column
* @param params
*/
formatColumnShouldRender(formatColumn, column, rowNode, cellValue) {
// suspended is important to be first
if (formatColumn.IsSuspended) {
return false;
}
const isSummaryNode = this.getGridApi().isSummaryNode(rowNode);
const isGroupedRowNode = this.getGridApi().isGroupRowNode(rowNode);
// For Summary Rows cannot be excluded
if (isSummaryNode) {
if (formatColumn.RowScope?.ExcludeSummaryRows) {
return false;
}
}
else if (isGroupedRowNode) {
if (formatColumn.RowScope?.ExcludeGroupRows) {
return false;
}
}
else {
if (formatColumn.RowScope?.ExcludeDataRows) {
return false;
}
}
if (!formatColumn.Rule) {
return true;
}
// first run the predicate
if (formatColumn.Rule.Predicates && formatColumn.Rule?.Predicates?.length) {
const predicateDefHandlerContext = {
value: cellValue,
oldValue: null,
displayValue: cellValue,
node: rowNode,
column: column,
...this.getAdaptableInternalApi().buildBaseContext(),
};
return this.evaluatePredicate(formatColumn, predicateDefHandlerContext);
} // then run the Expression
else if (formatColumn.Rule.BooleanExpression) {
return this.evaluateExpression(formatColumn, rowNode);
}
// nothing has passed then return false
return false;
}
evaluatePredicate(formatColumn, predicateDefHandlerContext) {
return this.getPredicateApi().handleColumnPredicates(formatColumn.Rule?.Predicates, predicateDefHandlerContext, false);
}
evaluateExpression(formatColumn, node) {
const isValidExpression = this.getExpressionApi().isValidBooleanExpression(formatColumn.Rule.BooleanExpression, ModuleConstants.FormatColumnModuleId, `Invalid format column rule '${formatColumn.Rule.BooleanExpression}'`);
try {
return (isValidExpression &&
this.getAdaptableApi()
.internalApi.getQueryLanguageService()
.evaluateBooleanExpression(formatColumn.Rule.BooleanExpression, ModuleConstants.FormatColumnModuleId, node));
}
catch (error) {
errorOnce(error.message);
return false;
}
}
/**
* Extract from the given FormatColumns only the ones which are relevant for a given cell (intersection of given AdaptableColumn and RowNode)
*
* @param formatColumns
* @param column
* @param params
*/
getFormatColumnsRelevantForColumn(formatColumns, column, params) {
return formatColumns.filter((formatColumn) => this.formatColumnShouldRender(formatColumn, column, params.node, params.value));
}
/**
* Extract from the given FormatColumns the one which is the most relevant for a given cell (intersection of given AdaptableColumn and RowNode)
*
* @param formatColumns
* @param column
* @param params
*/
getMostRelevantFormatColumnForColumn(formatColumns, column, params) {
return formatColumns.find((formatColumn) => this.formatColumnShouldRender(formatColumn, column, params.node, params.value));
}
/**
* Retrieves all Format Columns which have an Expression
* @returns Format Columns with Expression
*/
getFormatColumnsWithExpression() {
return this.getFormatColumnApi()
.getFormatColumns()
.filter((fc) => !!fc.Rule?.BooleanExpression);
}
getFormatColumnsDependentOnColumns(columnSet) {
return this.getFormatColumnApi()
.getFormatColumns()
.filter((fc) => fc.Rule?.Predicates?.some((p) => columnSet.has(p.ColumnId)));
}
/**
* Retrieves the columns that need rerendering based on format column predicates.
*/
getFormatColumnColumnsDependentOnColumnChange(column) {
const impactedColumnIds = new Set();
impactedColumnIds.add(column.columnId);
this.getCalculatedColumnApi()
.internalApi.getCalculatedColumnsDependentOnColumn(column)
.forEach((calculatedColumnId) => {
impactedColumnIds.add(calculatedColumnId);
});
const columnsThatNeedRefresh = new Set();
this.getFormatColumnsDependentOnColumns(impactedColumnIds).forEach((formatColumn) => {
this.getAdaptableApi()
.columnScopeApi.getColumnsInScope(formatColumn.Scope)
.forEach((col) => {
columnsThatNeedRefresh.add(col.columnId);
});
});
return [...columnsThatNeedRefresh];
}
}