@adaptabletools/adaptable 23.0.0-canary.3 → 23.0.0-canary.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/AdaptableOptions/DefaultAdaptableOptions.js +0 -4
- package/src/AdaptableOptions/FilterOptions.d.ts +0 -7
- package/src/AdaptableState/Common/AdaptableForm.d.ts +18 -1
- package/src/AdaptableState/Common/AdaptableForm.js +31 -0
- package/src/AdaptableState/Common/CellDataChangedInfo.d.ts +3 -2
- package/src/AdaptableState/Common/Enums.d.ts +0 -5
- package/src/AdaptableState/Common/Enums.js +0 -6
- package/src/Api/Implementation/LayoutHelpers.js +12 -0
- package/src/Strategy/CalculatedColumnModule.js +3 -1
- package/src/Utilities/Services/CalculatedColumnExpressionService.d.ts +1 -0
- package/src/Utilities/Services/CalculatedColumnExpressionService.js +7 -0
- package/src/Utilities/Services/CalculatedColumnSyntheticChange.d.ts +4 -0
- package/src/Utilities/Services/CalculatedColumnSyntheticChange.js +115 -0
- package/src/Utilities/Services/Interface/ICalculatedColumnExpressionService.d.ts +1 -0
- package/src/View/Charting/ChartingWizard/AgChargingWizard/SettingsSection.js +8 -16
- package/src/View/Components/ColumnFilter/ColumnFilterWindow.js +1 -1
- package/src/View/Components/Selectors/ColumnSelector.js +5 -0
- package/src/View/FlashingCell/Wizard/FlashingCellScopeWizardSection.js +3 -1
- package/src/View/Layout/LayoutViewPanel.js +23 -21
- package/src/View/renderWithAdaptableContext.js +2 -3
- package/src/agGrid/AdaptableAgGrid.d.ts +0 -1
- package/src/agGrid/AdaptableAgGrid.js +3 -18
- package/src/agGrid/AgGridColumnAdapter.js +1 -4
- package/src/components/AdaptableFormComponent/AdaptableFormComponent.js +11 -6
- package/src/components/Combobox/VirtualizedList.js +5 -5
- package/src/components/Combobox/comboboxUtils.d.ts +4 -1
- package/src/components/Combobox/comboboxUtils.js +2 -0
- package/src/components/Combobox/index.d.ts +1 -0
- package/src/components/Combobox/index.js +35 -15
- package/src/components/Tree/TreeDropdown/index.js +2 -6
- package/src/env.js +2 -2
- package/src/layout-manager/src/LayoutManagerModel.d.ts +5 -1
- package/src/metamodel/adaptable.metamodel.d.ts +0 -17
- package/src/metamodel/adaptable.metamodel.js +1 -1
- package/src/types.d.ts +0 -1
- package/tsconfig.esm.tsbuildinfo +1 -1
- package/src/AdaptableState/Common/FilterActionOnDataChange.d.ts +0 -17
- package/src/AdaptableState/Common/FilterActionOnDataChange.js +0 -4
- package/src/View/AdaptableComputedCSSVarsContext.d.ts +0 -12
- package/src/View/AdaptableComputedCSSVarsContext.js +0 -29
- package/src/components/Select/CSSNumericVariableWatch.d.ts +0 -11
- package/src/components/Select/CSSNumericVariableWatch.js +0 -45
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaptabletools/adaptable",
|
|
3
|
-
"version": "23.0.0-canary.
|
|
3
|
+
"version": "23.0.0-canary.4",
|
|
4
4
|
"description": "Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web-components",
|
|
@@ -165,10 +165,6 @@ const DefaultAdaptableOptions = {
|
|
|
165
165
|
},
|
|
166
166
|
},
|
|
167
167
|
filterOptions: {
|
|
168
|
-
filterActionOnDataChange: {
|
|
169
|
-
applyFilter: 'Always',
|
|
170
|
-
throttleDelay: 0,
|
|
171
|
-
},
|
|
172
168
|
clearFiltersOnStartUp: false,
|
|
173
169
|
enableFilterOnSpecialColumns: true,
|
|
174
170
|
useAdaptableFiltering: true,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { FilterActionOnDataChange } from '../AdaptableState/Common/FilterActionOnDataChange';
|
|
2
1
|
import { BaseContext } from '../../types';
|
|
3
2
|
import { AdaptableColumn } from '../AdaptableState/Common/AdaptableColumn';
|
|
4
3
|
import { SystemAlertPredicateId, SystemFilterPredicateId } from '../../types';
|
|
@@ -30,12 +29,6 @@ export interface FilterOptions<TData = any> {
|
|
|
30
29
|
* @returns
|
|
31
30
|
*/
|
|
32
31
|
customInFilterValues?: (context: CustomInFilterValuesContext<TData>) => Promise<InFilterValueResult> | InFilterValueResult;
|
|
33
|
-
/**
|
|
34
|
-
* When to re-filter grid after data changes: 'Always', 'Never' or 'Throttle' (with a delay value)
|
|
35
|
-
*
|
|
36
|
-
* @defaultValue 'Always'
|
|
37
|
-
*/
|
|
38
|
-
filterActionOnDataChange?: FilterActionOnDataChange;
|
|
39
32
|
/**
|
|
40
33
|
* Allow filtering on Calculated & FreeText columns
|
|
41
34
|
*
|
|
@@ -133,8 +133,19 @@ export interface AdaptableFormField {
|
|
|
133
133
|
/**
|
|
134
134
|
* Field Default Value - can be of type string, boolean, number, or for
|
|
135
135
|
* `select` fields with `multi: true` an array of those.
|
|
136
|
+
*
|
|
137
|
+
* For single `select` fields, this is also the value restored when the user
|
|
138
|
+
* clears the combobox (unless {@link clearToDefault} is `false`).
|
|
136
139
|
*/
|
|
137
140
|
defaultValue?: string | boolean | number | Array<string | number | boolean>;
|
|
141
|
+
/**
|
|
142
|
+
* For single `select` fields only. When the user clears the combobox,
|
|
143
|
+
* whether to restore {@link defaultValue} instead of leaving the field empty.
|
|
144
|
+
*
|
|
145
|
+
* Defaults to `true` when `defaultValue` is set, otherwise `false`.
|
|
146
|
+
* Set to `false` when an empty selection is a distinct state from the default.
|
|
147
|
+
*/
|
|
148
|
+
clearToDefault?: boolean;
|
|
138
149
|
/**
|
|
139
150
|
* Items to populate the `select` and `radio` fieldTypes.
|
|
140
151
|
*
|
|
@@ -166,7 +177,10 @@ export interface AdaptableFormField {
|
|
|
166
177
|
/**
|
|
167
178
|
* Placeholder text shown inside `text`, `textarea`, `number`, `date`,
|
|
168
179
|
* `time` and `datetime` inputs when empty. For `select` fields it is
|
|
169
|
-
* rendered as the empty-state label.
|
|
180
|
+
* rendered as the empty-state label when no value is selected.
|
|
181
|
+
*
|
|
182
|
+
* When omitted on a `select` field with a {@link defaultValue}, the label of
|
|
183
|
+
* the matching `options` entry is used as the empty-state label.
|
|
170
184
|
*/
|
|
171
185
|
placeholder?: string;
|
|
172
186
|
/**
|
|
@@ -310,6 +324,9 @@ export declare function isAdaptableFormFieldGroup(entry: AdaptableFormField | Ad
|
|
|
310
324
|
* computing defaults, validation or per-field lookups.
|
|
311
325
|
*/
|
|
312
326
|
export declare function flattenAdaptableFormFields<T extends BaseContext>(formDef?: AdaptableForm<T, any>): AdaptableFormField[];
|
|
327
|
+
export declare function shouldClearSelectToDefault(field: AdaptableFormField): boolean;
|
|
328
|
+
export declare function resolveSelectValueAfterClear(field: AdaptableFormField, newValue: unknown): unknown;
|
|
329
|
+
export declare function resolveSelectPlaceholder(field: AdaptableFormField, options: AdaptableFormFieldOption[]): string | undefined;
|
|
313
330
|
export declare function getDefaultAdaptableFormData<T extends BaseContext = BaseContext>(formDef?: AdaptableForm<T, any>): AdaptableFormData;
|
|
314
331
|
/**
|
|
315
332
|
* Resolves a field's `options` to the current array of options.
|
|
@@ -32,6 +32,37 @@ export function flattenAdaptableFormFields(formDef) {
|
|
|
32
32
|
}
|
|
33
33
|
return out;
|
|
34
34
|
}
|
|
35
|
+
export function shouldClearSelectToDefault(field) {
|
|
36
|
+
if (field.fieldType !== 'select' || field.multi) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
if (field.clearToDefault === false) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
if (field.clearToDefault === true) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
return (field.defaultValue !== undefined && field.defaultValue !== null && field.defaultValue !== '');
|
|
46
|
+
}
|
|
47
|
+
export function resolveSelectValueAfterClear(field, newValue) {
|
|
48
|
+
if (field.fieldType !== 'select' || field.multi) {
|
|
49
|
+
return newValue;
|
|
50
|
+
}
|
|
51
|
+
const isEmpty = newValue === null || newValue === undefined || newValue === '';
|
|
52
|
+
if (!isEmpty || !shouldClearSelectToDefault(field)) {
|
|
53
|
+
return newValue;
|
|
54
|
+
}
|
|
55
|
+
return field.defaultValue;
|
|
56
|
+
}
|
|
57
|
+
export function resolveSelectPlaceholder(field, options) {
|
|
58
|
+
if (field.placeholder) {
|
|
59
|
+
return field.placeholder;
|
|
60
|
+
}
|
|
61
|
+
if (field.defaultValue === undefined || field.defaultValue === null || field.defaultValue === '') {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
return options.find((option) => option.value === field.defaultValue)?.label;
|
|
65
|
+
}
|
|
35
66
|
export function getDefaultAdaptableFormData(formDef) {
|
|
36
67
|
return flattenAdaptableFormFields(formDef).reduce((data, field) => {
|
|
37
68
|
if (field.fieldType === 'select' && field.multi) {
|
|
@@ -33,9 +33,10 @@ export interface CellDataChangedInfo<TData = any> {
|
|
|
33
33
|
*/
|
|
34
34
|
rowData?: TData;
|
|
35
35
|
/**
|
|
36
|
-
* What triggered the change - user, background change
|
|
36
|
+
* What triggered the change - user, background change, a reverted change, or a
|
|
37
|
+
* derived update on a Calculated Column whose source value changed?
|
|
37
38
|
*/
|
|
38
|
-
trigger?: 'edit' | 'tick' | 'undo' | 'aggChange';
|
|
39
|
+
trigger?: 'edit' | 'tick' | 'undo' | 'aggChange' | 'calculatedColumnChange';
|
|
39
40
|
/**
|
|
40
41
|
* Whether the change was prevented by a validation rule
|
|
41
42
|
*/
|
|
@@ -49,11 +49,6 @@ export declare enum SummaryOperation {
|
|
|
49
49
|
Only = "Only",
|
|
50
50
|
Weighted_Average = "Weighted Avg"
|
|
51
51
|
}
|
|
52
|
-
export declare enum FilterOnDataChangeOptions {
|
|
53
|
-
Always = "Always",
|
|
54
|
-
Never = "Never",
|
|
55
|
-
Throttle = "Throttle"
|
|
56
|
-
}
|
|
57
52
|
export declare enum ChangeDirection {
|
|
58
53
|
Up = "Up",
|
|
59
54
|
Down = "Down",
|
|
@@ -61,12 +61,6 @@ export var SummaryOperation;
|
|
|
61
61
|
SummaryOperation["Only"] = "Only";
|
|
62
62
|
SummaryOperation["Weighted_Average"] = "Weighted Avg";
|
|
63
63
|
})(SummaryOperation || (SummaryOperation = {}));
|
|
64
|
-
export var FilterOnDataChangeOptions;
|
|
65
|
-
(function (FilterOnDataChangeOptions) {
|
|
66
|
-
FilterOnDataChangeOptions["Always"] = "Always";
|
|
67
|
-
FilterOnDataChangeOptions["Never"] = "Never";
|
|
68
|
-
FilterOnDataChangeOptions["Throttle"] = "Throttle";
|
|
69
|
-
})(FilterOnDataChangeOptions || (FilterOnDataChangeOptions = {}));
|
|
70
64
|
export var ChangeDirection;
|
|
71
65
|
(function (ChangeDirection) {
|
|
72
66
|
ChangeDirection["Up"] = "Up";
|
|
@@ -248,6 +248,9 @@ export const tableLayoutToTableLayoutModel = (tableLayout) => {
|
|
|
248
248
|
if (tableLayout.Metadata) {
|
|
249
249
|
result.Ignore_Metadata = tableLayout.Metadata;
|
|
250
250
|
}
|
|
251
|
+
if (tableLayout.OpenCharts) {
|
|
252
|
+
result.Ignore_OpenCharts = tableLayout.OpenCharts;
|
|
253
|
+
}
|
|
251
254
|
if (tableLayout.RowSummaries != null) {
|
|
252
255
|
result.Ignore_RowSummaries = tableLayout.RowSummaries;
|
|
253
256
|
}
|
|
@@ -327,6 +330,9 @@ export const pivotLayoutToPivotLayoutModel = (pivotLayout) => {
|
|
|
327
330
|
if (pivotLayout.Metadata) {
|
|
328
331
|
result.Ignore_Metadata = pivotLayout.Metadata;
|
|
329
332
|
}
|
|
333
|
+
if (pivotLayout.OpenCharts) {
|
|
334
|
+
result.Ignore_OpenCharts = pivotLayout.OpenCharts;
|
|
335
|
+
}
|
|
330
336
|
return result;
|
|
331
337
|
};
|
|
332
338
|
function toAggFunc(aggFunc) {
|
|
@@ -376,6 +382,9 @@ export const tableLayoutModelToTableLayout = (layoutModel) => {
|
|
|
376
382
|
if (layoutModel.Ignore_Metadata) {
|
|
377
383
|
tableLayout.Metadata = layoutModel.Ignore_Metadata;
|
|
378
384
|
}
|
|
385
|
+
if (layoutModel.Ignore_OpenCharts) {
|
|
386
|
+
tableLayout.OpenCharts = layoutModel.Ignore_OpenCharts;
|
|
387
|
+
}
|
|
379
388
|
// if (layoutModel.RowGroupDisplayType) {
|
|
380
389
|
tableLayout.RowGroupDisplayType = layoutModel.RowGroupDisplayType ?? 'single';
|
|
381
390
|
// }
|
|
@@ -481,6 +490,9 @@ export const pivotLayoutModelToPivotLayout = (layoutModel) => {
|
|
|
481
490
|
if (layoutModel.Ignore_Metadata) {
|
|
482
491
|
pivotLayout.Metadata = layoutModel.Ignore_Metadata;
|
|
483
492
|
}
|
|
493
|
+
if (layoutModel.Ignore_OpenCharts) {
|
|
494
|
+
pivotLayout.OpenCharts = layoutModel.Ignore_OpenCharts;
|
|
495
|
+
}
|
|
484
496
|
if (layoutModel.PivotGroupedColumns) {
|
|
485
497
|
pivotLayout.PivotGroupedColumns = layoutModel.PivotGroupedColumns;
|
|
486
498
|
}
|
|
@@ -32,7 +32,9 @@ export class CalculatedColumnModule extends AdaptableModuleBase {
|
|
|
32
32
|
this.api.internalApi
|
|
33
33
|
.getDataService()
|
|
34
34
|
.on('CellDataChanged', (cellDataChangedInfo) => {
|
|
35
|
-
if (cellDataChangedInfo.trigger !== 'aggChange' &&
|
|
35
|
+
if (cellDataChangedInfo.trigger !== 'aggChange' &&
|
|
36
|
+
cellDataChangedInfo.trigger !== 'calculatedColumnChange' &&
|
|
37
|
+
!cellDataChangedInfo.preventEdit) {
|
|
36
38
|
this.api.internalApi
|
|
37
39
|
.getCalculatedColumnExpressionService()
|
|
38
40
|
.listentoCellDataChange(cellDataChangedInfo);
|
|
@@ -8,6 +8,7 @@ export declare class CalculatedColumnExpressionService implements ICalculatedCol
|
|
|
8
8
|
private adaptableApi;
|
|
9
9
|
private aggregatedScalarLiveValuesMap;
|
|
10
10
|
constructor(adaptableApi: AdaptableApi);
|
|
11
|
+
buildSyntheticCellDataChangedInfosForCalcColumns(cellDataChangedInfo: CellDataChangedInfo): CellDataChangedInfo[];
|
|
11
12
|
listentoCellDataChange(cellDataChangedInfo: CellDataChangedInfo): void;
|
|
12
13
|
listentoRowDataChange(rowDataChangedInfo: RowDataChangedInfo): void;
|
|
13
14
|
destroy(): void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CalculatedColumnModuleId } from '../Constants/ModuleConstants';
|
|
2
2
|
import { AggregatedScalarLiveValue } from './AggregatedScalarLiveValue';
|
|
3
|
+
import { buildSyntheticCellDataChangedInfosForCalcColumns } from './CalculatedColumnSyntheticChange';
|
|
3
4
|
export class CalculatedColumnExpressionService {
|
|
4
5
|
adaptableApi;
|
|
5
6
|
aggregatedScalarLiveValuesMap = new Map();
|
|
@@ -7,7 +8,13 @@ export class CalculatedColumnExpressionService {
|
|
|
7
8
|
this.adaptableApi = adaptableApi;
|
|
8
9
|
this.adaptableApi = adaptableApi;
|
|
9
10
|
}
|
|
11
|
+
buildSyntheticCellDataChangedInfosForCalcColumns(cellDataChangedInfo) {
|
|
12
|
+
return buildSyntheticCellDataChangedInfosForCalcColumns(this.adaptableApi, cellDataChangedInfo);
|
|
13
|
+
}
|
|
10
14
|
listentoCellDataChange(cellDataChangedInfo) {
|
|
15
|
+
if (cellDataChangedInfo.trigger === 'calculatedColumnChange') {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
11
18
|
const refreshedCalculatedColumns = [];
|
|
12
19
|
this.aggregatedScalarLiveValuesMap.forEach((aggregatedScalarLiveValue, calculatedColumnId) => {
|
|
13
20
|
const calculatedColumn = this.adaptableApi.calculatedColumnApi.getCalculatedColumnById(calculatedColumnId);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { AdaptableApi } from '../../types';
|
|
2
|
+
import { CellDataChangedInfo } from '../../AdaptableState/Common/CellDataChangedInfo';
|
|
3
|
+
export declare function buildSyntheticCellDataChangedInfosForCalcColumns(adaptableApi: AdaptableApi, info: CellDataChangedInfo): CellDataChangedInfo[];
|
|
4
|
+
export declare function expandCellDataChangedInfosWithCalculatedColumns(adaptableApi: AdaptableApi, cellDataChangedInfos: CellDataChangedInfo[]): CellDataChangedInfo[];
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import * as parser from '../../parser/src';
|
|
2
|
+
import { CalculatedColumnModuleId } from '../Constants/ModuleConstants';
|
|
3
|
+
import Helper from '../Helpers/Helper';
|
|
4
|
+
function isScalarCalculatedColumn(calculatedColumn) {
|
|
5
|
+
return !!calculatedColumn.Query?.ScalarExpression;
|
|
6
|
+
}
|
|
7
|
+
function collectDependentScalarCalculatedColumns(adaptableApi, rootColumnId) {
|
|
8
|
+
const collected = [];
|
|
9
|
+
const seenCalcColumnIds = new Set();
|
|
10
|
+
const queue = [rootColumnId];
|
|
11
|
+
while (queue.length > 0) {
|
|
12
|
+
const columnId = queue.shift();
|
|
13
|
+
const adaptableColumn = adaptableApi.columnApi.getColumnWithColumnId(columnId);
|
|
14
|
+
if (!adaptableColumn) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
const dependentColumnIds = adaptableApi.calculatedColumnApi.internalApi.getCalculatedColumnsDependentOnColumn(adaptableColumn);
|
|
18
|
+
dependentColumnIds.forEach((dependentColumnId) => {
|
|
19
|
+
if (seenCalcColumnIds.has(dependentColumnId)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const calculatedColumn = adaptableApi.calculatedColumnApi.getCalculatedColumnForColumnId(dependentColumnId);
|
|
23
|
+
if (!calculatedColumn || !isScalarCalculatedColumn(calculatedColumn)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
seenCalcColumnIds.add(dependentColumnId);
|
|
27
|
+
collected.push(calculatedColumn);
|
|
28
|
+
queue.push(dependentColumnId);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return collected;
|
|
32
|
+
}
|
|
33
|
+
function buildShadowRowData(adaptableApi, info) {
|
|
34
|
+
const shadowData = Helper.cloneObject(info.rowNode?.data ?? info.rowData ?? {});
|
|
35
|
+
const fieldName = info.column.field ?? info.column.columnId;
|
|
36
|
+
adaptableApi.internalApi.setValueUsingField(shadowData, fieldName, info.oldValue);
|
|
37
|
+
return shadowData;
|
|
38
|
+
}
|
|
39
|
+
function evaluateScalarExpressionWithShadowData(adaptableApi, calculatedColumn, rowNode, shadowData) {
|
|
40
|
+
const internalApi = adaptableApi.internalApi;
|
|
41
|
+
const moduleFns = internalApi
|
|
42
|
+
.getQueryLanguageService()
|
|
43
|
+
.getModuleExpressionFunctionsMap(CalculatedColumnModuleId);
|
|
44
|
+
const baseFunctions = { ...moduleFns.booleanFunctions, ...moduleFns.scalarFunctions };
|
|
45
|
+
const resolveColumnValue = (columnId) => {
|
|
46
|
+
const childCalculatedColumn = adaptableApi.calculatedColumnApi.getCalculatedColumnForColumnId(columnId);
|
|
47
|
+
if (childCalculatedColumn?.Query?.ScalarExpression) {
|
|
48
|
+
return evaluateScalarExpressionWithShadowData(adaptableApi, childCalculatedColumn, rowNode, shadowData);
|
|
49
|
+
}
|
|
50
|
+
const adaptableColumn = adaptableApi.columnApi.getColumnWithColumnId(columnId);
|
|
51
|
+
return internalApi.getValueUsingField(shadowData, adaptableColumn?.field ?? columnId);
|
|
52
|
+
};
|
|
53
|
+
const customFunctions = {
|
|
54
|
+
...baseFunctions,
|
|
55
|
+
COL: {
|
|
56
|
+
...baseFunctions.COL,
|
|
57
|
+
handler: (args) => resolveColumnValue(args[0]),
|
|
58
|
+
},
|
|
59
|
+
FIELD: {
|
|
60
|
+
...baseFunctions.FIELD,
|
|
61
|
+
handler: (args) => internalApi.getValueUsingField(shadowData, args[0]),
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
return parser.evaluate(calculatedColumn.Query.ScalarExpression, {
|
|
65
|
+
node: { ...rowNode, data: shadowData },
|
|
66
|
+
functions: customFunctions,
|
|
67
|
+
...internalApi.buildBaseContext(),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
export function buildSyntheticCellDataChangedInfosForCalcColumns(adaptableApi, info) {
|
|
71
|
+
if (!info.rowNode ||
|
|
72
|
+
info.preventEdit ||
|
|
73
|
+
info.trigger === 'undo' ||
|
|
74
|
+
info.trigger === 'aggChange' ||
|
|
75
|
+
info.trigger === 'calculatedColumnChange') {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
const calculatedColumns = collectDependentScalarCalculatedColumns(adaptableApi, info.column.columnId);
|
|
79
|
+
if (!calculatedColumns.length) {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
const shadowData = buildShadowRowData(adaptableApi, info);
|
|
83
|
+
const expressionService = adaptableApi.internalApi.getCalculatedColumnExpressionService();
|
|
84
|
+
const syntheticEvents = [];
|
|
85
|
+
calculatedColumns.forEach((calculatedColumn) => {
|
|
86
|
+
const oldValue = evaluateScalarExpressionWithShadowData(adaptableApi, calculatedColumn, info.rowNode, shadowData);
|
|
87
|
+
const newValue = expressionService.evaluateCalculatedColumnQuery(calculatedColumn, info.rowNode);
|
|
88
|
+
if (oldValue == newValue) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const column = adaptableApi.columnApi.getColumnWithColumnId(calculatedColumn.ColumnId);
|
|
92
|
+
if (!column) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
syntheticEvents.push(adaptableApi.internalApi.buildCellDataChangedInfo({
|
|
96
|
+
oldValue,
|
|
97
|
+
newValue,
|
|
98
|
+
column,
|
|
99
|
+
primaryKeyValue: info.primaryKeyValue,
|
|
100
|
+
rowNode: info.rowNode,
|
|
101
|
+
trigger: 'calculatedColumnChange',
|
|
102
|
+
}));
|
|
103
|
+
});
|
|
104
|
+
return syntheticEvents;
|
|
105
|
+
}
|
|
106
|
+
export function expandCellDataChangedInfosWithCalculatedColumns(adaptableApi, cellDataChangedInfos) {
|
|
107
|
+
if (!cellDataChangedInfos.length) {
|
|
108
|
+
return cellDataChangedInfos;
|
|
109
|
+
}
|
|
110
|
+
const syntheticEvents = cellDataChangedInfos.flatMap((info) => buildSyntheticCellDataChangedInfosForCalcColumns(adaptableApi, info));
|
|
111
|
+
if (!syntheticEvents.length) {
|
|
112
|
+
return cellDataChangedInfos;
|
|
113
|
+
}
|
|
114
|
+
return [...cellDataChangedInfos, ...syntheticEvents];
|
|
115
|
+
}
|
|
@@ -11,4 +11,5 @@ export interface ICalculatedColumnExpressionService extends IAdaptableService {
|
|
|
11
11
|
destroyAggregatedScalarLiveValue(calculatedColumn: CalculatedColumn): void;
|
|
12
12
|
listentoCellDataChange(cellDataChangedInfo: CellDataChangedInfo): void;
|
|
13
13
|
listentoRowDataChange(rowDataChangedInfo: RowDataChangedInfo): void;
|
|
14
|
+
buildSyntheticCellDataChangedInfosForCalcColumns(cellDataChangedInfo: CellDataChangedInfo): CellDataChangedInfo[];
|
|
14
15
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { CheckBox } from '../../../../components/CheckBox';
|
|
4
|
-
import
|
|
4
|
+
import { SingleSelect } from '../../../../components/NewSelect';
|
|
5
5
|
import FormLayout, { FormRow } from '../../../../components/FormLayout';
|
|
6
6
|
import { validateChartName } from '../../../../Utilities/Helpers/chartingHelper';
|
|
7
7
|
import AdaptableInput from '../../../Components/AdaptableInput';
|
|
@@ -35,27 +35,19 @@ export const SettingsSection = (props) => {
|
|
|
35
35
|
});
|
|
36
36
|
}, [props.chartDefinition]);
|
|
37
37
|
const aggFuncs = ['sum', 'min', 'max', 'count', 'avg', 'first', 'last'];
|
|
38
|
-
const aggFuncsOptions = aggFuncs.map((aggFunc) => ({
|
|
39
|
-
label: aggFunc,
|
|
40
|
-
onClick: () => {
|
|
41
|
-
props.onChange({
|
|
42
|
-
...props.chartDefinition,
|
|
43
|
-
Model: {
|
|
44
|
-
...props.chartDefinition.Model,
|
|
45
|
-
aggFunc,
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
},
|
|
49
|
-
}));
|
|
50
38
|
const aggFunc = props.chartDefinition.Model.aggFunc;
|
|
51
|
-
const
|
|
39
|
+
const handleAggFuncChange = React.useCallback((value) => {
|
|
52
40
|
props.onChange({
|
|
53
41
|
...props.chartDefinition,
|
|
54
42
|
Model: {
|
|
55
43
|
...props.chartDefinition.Model,
|
|
56
|
-
aggFunc:
|
|
44
|
+
aggFunc: value,
|
|
57
45
|
},
|
|
58
46
|
});
|
|
59
47
|
}, [props.chartDefinition]);
|
|
60
|
-
|
|
48
|
+
const aggFuncsOptions = aggFuncs.map((option) => ({
|
|
49
|
+
label: option,
|
|
50
|
+
value: option,
|
|
51
|
+
}));
|
|
52
|
+
return (_jsxs(FormLayout, { children: [_jsx(FormRow, { label: "Name", children: _jsx(AdaptableInput, { onChange: handleNameChange, value: props.chartDefinition.Name }) }), _jsx(FormRow, { label: "Unlink Chart", children: _jsx(CheckBox, { onClick: handleUnLinkChange, checked: props.chartDefinition.Model.unlinkChart }) }), _jsx(FormRow, { label: "Suppress Chart Ranges", children: _jsx(CheckBox, { onClick: handleSuppressChartRanges, checked: props.chartDefinition.Model.suppressChartRanges }) }), props.chartDefinition.Model.modelType === 'range' && typeof aggFunc !== 'function' && (_jsx(FormRow, { label: "Agg Func", children: _jsx(SingleSelect, { placeholder: "Select", items: aggFuncsOptions, value: aggFunc || undefined, onValueChange: handleAggFuncChange }) }))] }));
|
|
61
53
|
};
|
|
@@ -28,5 +28,5 @@ export const ColumnFilterWindow = (props) => {
|
|
|
28
28
|
return (_jsxs(Flex, { children: [label, _jsx(Box, { className: "twa:flex-1" }), _jsx(AdaptableIconComponent, { icon: { name: 'filter' } })] }));
|
|
29
29
|
}
|
|
30
30
|
return label;
|
|
31
|
-
}, onChange: (column) => setColumnId(column), filterColumn: (column) => column.queryable,
|
|
31
|
+
}, onChange: (column) => setColumnId(column), filterColumn: (column) => column.queryable, value: columnId }) }) }) }), _jsx(AdaptableColumnFilter, { columnId: columnId, location: 'filterForm' })] }));
|
|
32
32
|
};
|
|
@@ -15,6 +15,7 @@ export const ColumnSelector = function (props) {
|
|
|
15
15
|
return {
|
|
16
16
|
label,
|
|
17
17
|
textLabel,
|
|
18
|
+
tooltip: textLabel,
|
|
18
19
|
value: column.columnId,
|
|
19
20
|
};
|
|
20
21
|
})
|
|
@@ -31,7 +32,11 @@ export const ColumnSelector = function (props) {
|
|
|
31
32
|
virtualized: true,
|
|
32
33
|
items: options,
|
|
33
34
|
showClear: false,
|
|
35
|
+
showItemTooltip: true,
|
|
34
36
|
onValueChange: (colId) => {
|
|
37
|
+
if (colId === null) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
35
40
|
props.onChange(colId);
|
|
36
41
|
},
|
|
37
42
|
value: props.value,
|
|
@@ -6,7 +6,9 @@ import { Flex } from '../../../components/Flex';
|
|
|
6
6
|
import { isScopeColumnIds } from '../../../AdaptableState/Common/ColumnScope';
|
|
7
7
|
export const FlashingAlertScopeWizardSection = (props) => {
|
|
8
8
|
const { data, api } = useOnePageAdaptableWizardContext();
|
|
9
|
-
const availableColumns = React.useMemo(() => api.columnApi
|
|
9
|
+
const availableColumns = React.useMemo(() => api.columnApi
|
|
10
|
+
.getUIAvailableColumns()
|
|
11
|
+
.filter((column) => !column.isActionColumn && !api.columnApi.isFdc3Column(column.columnId)), [api]);
|
|
10
12
|
return (_jsx(Flex, { flexDirection: "column", className: "twa:p-2 twa:h-full", children: _jsx(NewScopeComponent, { descriptions: {
|
|
11
13
|
rowScope: 'Changes anywhere in the row will trigger an Flashing Cell',
|
|
12
14
|
columnScope: 'Changes in selected columns will trigger an Flashing Cell',
|
|
@@ -33,29 +33,31 @@ const LayoutViewPanelComponent = (props) => {
|
|
|
33
33
|
const entityAccessLevel = AdaptableHelper.getAccessLevelForObject(layoutEntity, accessLevel);
|
|
34
34
|
const elementType = viewType === 'Toolbar' ? 'DashboardToolbar' : 'ToolPanel';
|
|
35
35
|
const layoutSelectStyle = elementType === 'ToolPanel' ? { minWidth: '100%' } : {};
|
|
36
|
+
const toLayoutSelectItems = (layouts) => layouts.map((layout) => ({
|
|
37
|
+
label: layout.Name,
|
|
38
|
+
value: layout.Name,
|
|
39
|
+
}));
|
|
36
40
|
const tableLayoutsArray = Layouts.filter((layout) => !isPivotLayout(layout));
|
|
37
41
|
const pivotLayoutsArray = Layouts.filter((layout) => isPivotLayout(layout));
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
].filter(Boolean);
|
|
58
|
-
return (_jsxs(Flex, { flexDirection: "row", className: `ab-${elementType}__Layout__wrap twa:gap-0.5`, flexWrap: viewType === 'ToolPanel' ? 'wrap' : 'nowrap', children: [_jsx(Flex, { style: layoutSelectStyle, className: "twa:flex-1", children: _jsx(SingleSelect, { groups: layoutGroups, showItemTooltip: true, disabled: isErrorLayout, className: `twa:w-full twa:min-w-30 ab-${elementType}__Layout__select`, ariaLabel: 'Select Layout', value: layoutEntity ? layoutEntity.Name : null, onValueChange: (layout) => onSelectLayout(layout) }) }), _jsxs(Flex, { flexDirection: "row", className: join(accessLevel === GeneralConstants.ACCESS_LEVEL_READ_ONLY
|
|
42
|
+
const showLayoutTypeHeadings = tableLayoutsArray.length > 0 && pivotLayoutsArray.length > 0;
|
|
43
|
+
const layoutSelectCommonProps = {
|
|
44
|
+
showItemTooltip: true,
|
|
45
|
+
disabled: isErrorLayout,
|
|
46
|
+
className: `twa:w-full twa:min-w-30 ab-${elementType}__Layout__select`,
|
|
47
|
+
ariaLabel: 'Select Layout',
|
|
48
|
+
value: layoutEntity ? layoutEntity.Name : null,
|
|
49
|
+
onValueChange: (layout) => onSelectLayout(layout),
|
|
50
|
+
};
|
|
51
|
+
return (_jsxs(Flex, { flexDirection: "row", className: `ab-${elementType}__Layout__wrap twa:gap-0.5`, flexWrap: viewType === 'ToolPanel' ? 'wrap' : 'nowrap', children: [_jsx(Flex, { style: layoutSelectStyle, className: "twa:flex-1", children: showLayoutTypeHeadings ? (_jsx(SingleSelect, { ...layoutSelectCommonProps, groups: [
|
|
52
|
+
{
|
|
53
|
+
label: 'Table Layouts',
|
|
54
|
+
items: toLayoutSelectItems(tableLayoutsArray),
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
label: 'Pivot Layouts',
|
|
58
|
+
items: toLayoutSelectItems(pivotLayoutsArray),
|
|
59
|
+
},
|
|
60
|
+
] })) : (_jsx(SingleSelect, { ...layoutSelectCommonProps, items: toLayoutSelectItems(Layouts) })) }), _jsxs(Flex, { flexDirection: "row", className: join(accessLevel === GeneralConstants.ACCESS_LEVEL_READ_ONLY
|
|
59
61
|
? GeneralConstants.READ_ONLY_STYLE
|
|
60
62
|
: '', `ab-${elementType}__Layout__wrap`), children: [_jsx(ButtonEdit, { disabled: isErrorLayout, onClick: () => api.layoutApi.showLayoutEditor(layoutEntity.Name), tooltip: LAYOUT_EDIT_TOOLTIP, className: `ab-${elementType}__Layout__edit`, accessLevel: entityAccessLevel }), _jsx(ButtonClone, { disabled: isErrorLayout, onClick: () => api.layoutApi.showLayoutEditor(layoutEntity.Name, isPivotLayout(layoutEntity) ? 'pivot' : 'table', 'Clone'), tooltip: LAYOUT_CLONE_TOOLTIP, className: `ab-${elementType}__Layout__clone`, tone: "neutral", variant: "text", children: null, accessLevel: cloneAccessLevel }), _jsx(NewDropdownButton, { variant: "text", tooltip: LAYOUT_NEW_TABLE_OR_PIVOT_TOOLTIP, "data-name": "new", items: [
|
|
61
63
|
{
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Provider } from 'react-redux';
|
|
3
3
|
import AdaptableContext from './AdaptableContext';
|
|
4
|
-
import {
|
|
5
|
-
import { TooltipProvider } from '../components/ui/tooltip';
|
|
4
|
+
import { TooltipProvider } from "../components/ui/tooltip";
|
|
6
5
|
export const renderWithAdaptableContext = (children, adaptable) => {
|
|
7
|
-
return (_jsx(TooltipProvider, { delay: 300, children: _jsx(Provider, { store: adaptable.adaptableStore.TheStore, children: _jsx(
|
|
6
|
+
return (_jsx(TooltipProvider, { delay: 300, children: _jsx(Provider, { store: adaptable.adaptableStore.TheStore, children: _jsx(AdaptableContext.Provider, { value: adaptable, children: children }) }) }));
|
|
8
7
|
};
|
|
@@ -97,7 +97,6 @@ export declare class AdaptableAgGrid implements IAdaptable {
|
|
|
97
97
|
private LicenseService;
|
|
98
98
|
private ChartingService;
|
|
99
99
|
private rowListeners;
|
|
100
|
-
private throttleFilterOnDataChange;
|
|
101
100
|
private debouncedSetSelectedRows;
|
|
102
101
|
private debouncedSetSelectedCells;
|
|
103
102
|
private agGridListenerKeydown;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import throttle from '../Utilities/utils/throttle';
|
|
2
1
|
import debounce from '../Utilities/utils/debounce';
|
|
3
2
|
import { createGrid, LocalEventService, } from 'ag-grid-enterprise';
|
|
4
3
|
import { AdaptableLogger } from './AdaptableLogger';
|
|
@@ -21,6 +20,7 @@ import { ThemeService } from '../Utilities/Services/ThemeService';
|
|
|
21
20
|
import { ValidationService } from '../Utilities/Services/ValidationService';
|
|
22
21
|
import { ModuleService } from '../Utilities/Services/ModuleService';
|
|
23
22
|
import { CalculatedColumnExpressionService } from '../Utilities/Services/CalculatedColumnExpressionService';
|
|
23
|
+
import { expandCellDataChangedInfosWithCalculatedColumns } from '../Utilities/Services/CalculatedColumnSyntheticChange';
|
|
24
24
|
import { QueryLanguageService } from '../Utilities/Services/QueryLanguageService';
|
|
25
25
|
import { AlertService } from '../Utilities/Services/AlertService';
|
|
26
26
|
import { TeamSharingService } from '../Utilities/Services/TeamSharingService';
|
|
@@ -83,7 +83,6 @@ import { computeParameterizedAggregation, getParameterizedAggregationDefinitions
|
|
|
83
83
|
import { getParameterizedAggForColumn } from '../Aggregation/parameterizedAggregationHelpers';
|
|
84
84
|
import { getParameterizedAggregationHeaderParenthesisValue } from '../Aggregation/parameterizedAggregationHeader';
|
|
85
85
|
import { RowFormService } from '../Utilities/Services/RowFormService';
|
|
86
|
-
import { FilterOnDataChangeOptions } from '../AdaptableState/Common/Enums';
|
|
87
86
|
import { ADAPTABLE_PUBLISH_TIMESTAMP } from '../EnvVars';
|
|
88
87
|
import { AdaptableUpgradeHelper } from '../migration/AdaptableUpgradeHelper';
|
|
89
88
|
import { ensureLoadingScreenPortalElement } from '../components/Modal';
|
|
@@ -204,7 +203,6 @@ export class AdaptableAgGrid {
|
|
|
204
203
|
LicenseService;
|
|
205
204
|
ChartingService;
|
|
206
205
|
rowListeners;
|
|
207
|
-
throttleFilterOnDataChange;
|
|
208
206
|
debouncedSetSelectedRows;
|
|
209
207
|
debouncedSetSelectedCells;
|
|
210
208
|
agGridListenerKeydown;
|
|
@@ -1699,12 +1697,6 @@ export class AdaptableAgGrid {
|
|
|
1699
1697
|
}), true);
|
|
1700
1698
|
gridContainerElement.addEventListener('mouseleave', (this.agGridListenerMouseLeave = (event) => this._emit('MouseLeave', event)));
|
|
1701
1699
|
}
|
|
1702
|
-
this.throttleFilterOnDataChange = throttle(
|
|
1703
|
-
// the extra function is to make sure we have a reference to ag-grid-api
|
|
1704
|
-
() => this.agGridAdapter.getAgGridApi()?.onFilterChanged(), this.adaptableOptions.filterOptions.filterActionOnDataChange.throttleDelay, {
|
|
1705
|
-
trailing: true,
|
|
1706
|
-
leading: false,
|
|
1707
|
-
});
|
|
1708
1700
|
/**
|
|
1709
1701
|
* Use Case: User has started inline editing but its disabled in Row Form Options
|
|
1710
1702
|
* Action: Stop editing
|
|
@@ -3813,7 +3805,6 @@ export class AdaptableAgGrid {
|
|
|
3813
3805
|
this.listenerCellSelectionChanged = null;
|
|
3814
3806
|
this.listenerGlobalSetRowSelection = null;
|
|
3815
3807
|
this.listenerSortChanged = null;
|
|
3816
|
-
this.throttleFilterOnDataChange = null;
|
|
3817
3808
|
const liveGridOptions = this.agGridAdapter.DANGER_getLiveGridOptions();
|
|
3818
3809
|
if (liveGridOptions) {
|
|
3819
3810
|
this.agGridOptionsService.revertGridOptionsPropertiesToUserValue(liveGridOptions, [
|
|
@@ -4133,6 +4124,7 @@ export class AdaptableAgGrid {
|
|
|
4133
4124
|
* There are a few things we need to do AFTER we edit a cell and it makes sense to put them in one place
|
|
4134
4125
|
*/
|
|
4135
4126
|
performPostEditChecks(rowNode, cellDataChangedInfos) {
|
|
4127
|
+
cellDataChangedInfos = expandCellDataChangedInfosWithCalculatedColumns(this.api, cellDataChangedInfos);
|
|
4136
4128
|
cellDataChangedInfos.forEach((cellDataChangedInfo) => {
|
|
4137
4129
|
// if a Cell Data Change is undone, log to the Console
|
|
4138
4130
|
if (cellDataChangedInfo.trigger === 'undo') {
|
|
@@ -4290,14 +4282,7 @@ export class AdaptableAgGrid {
|
|
|
4290
4282
|
}
|
|
4291
4283
|
}
|
|
4292
4284
|
filterOnDataChange() {
|
|
4293
|
-
|
|
4294
|
-
FilterOnDataChangeOptions.Always) {
|
|
4295
|
-
this.agGridAdapter.getAgGridApi()?.onFilterChanged();
|
|
4296
|
-
}
|
|
4297
|
-
else if (this.adaptableOptions.filterOptions.filterActionOnDataChange.applyFilter ==
|
|
4298
|
-
FilterOnDataChangeOptions.Throttle) {
|
|
4299
|
-
this.throttleFilterOnDataChange();
|
|
4300
|
-
}
|
|
4285
|
+
this.agGridAdapter.getAgGridApi()?.onFilterChanged();
|
|
4301
4286
|
}
|
|
4302
4287
|
refreshLayout() {
|
|
4303
4288
|
const columnDefs = this.agGridAdapter.getColumnDefinitionsInclSpecialColumns();
|
|
@@ -951,10 +951,7 @@ export class AgGridColumnAdapter {
|
|
|
951
951
|
// 1. evaluate EditOptions.isCellEditable if provided
|
|
952
952
|
if (this.adaptableApi.gridApi.internalApi.hasCellEditableAccordingToEditOptions()) {
|
|
953
953
|
const gridCell = this.adaptableApi.gridApi.getGridCellFromRowNode(params.node, params.column.getColId());
|
|
954
|
-
|
|
955
|
-
if (editOptionsEditability) {
|
|
956
|
-
return editOptionsEditability;
|
|
957
|
-
}
|
|
954
|
+
return this.adaptableApi.gridApi.internalApi.isCellEditableAccordingToEditOptions(gridCell, getOriginalColDefEditable());
|
|
958
955
|
}
|
|
959
956
|
// 2. otherwise, fallback to colDef.editable
|
|
960
957
|
return getOriginalColDefEditable();
|