@adaptabletools/adaptable 23.0.21 → 23.1.0-canary.0
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 +3 -2
- package/src/AdaptableInterfaces/IAdaptable.d.ts +1 -0
- package/src/AdaptableOptions/ColumnMenuOptions.d.ts +1 -1
- package/src/AdaptableOptions/ContextMenuOptions.d.ts +1 -1
- package/src/AdaptableOptions/FilterOptions.d.ts +34 -0
- package/src/Api/GridApi.d.ts +5 -1
- package/src/Api/Implementation/GridApiImpl.d.ts +1 -0
- package/src/Api/Implementation/GridApiImpl.js +22 -1
- package/src/Redux/Store/AdaptableStore.js +6 -1
- package/src/Utilities/Helpers/DisplayFormatHelper.js +16 -4
- package/src/Utilities/Helpers/StyledColumns/SparklineStyleHelper.d.ts +2 -0
- package/src/Utilities/Helpers/StyledColumns/SparklineStyleHelper.js +13 -10
- package/src/Utilities/Hooks/useAdaptableOptions.d.ts +1 -1
- package/src/Utilities/Services/AnnotationsService.js +8 -8
- package/src/View/Components/ColumnFilter/components/FloatingFilterValues.d.ts +3 -0
- package/src/View/Components/ColumnFilter/components/FloatingFilterValues.js +16 -1
- package/src/View/Components/FilterForm/ListBoxFilterForm.js +1 -1
- package/src/View/Components/PredicateEditor/PredicateEditor.js +11 -1
- package/src/View/FormatColumn/Wizard/FormatColumnFormatWizardSection.js +6 -2
- package/src/View/StyledColumn/Wizard/StyledColumnSparklineSettingsSection.js +18 -8
- package/src/View/Wizard/OnePageAdaptableWizard.d.ts +2 -2
- package/src/View/Wizard/OnePageWizards.d.ts +1 -1
- package/src/agGrid/AdaptableAgGrid.d.ts +30 -6
- package/src/agGrid/AdaptableAgGrid.js +60 -78
- package/src/agGrid/AgGridAdapter.d.ts +32 -1
- package/src/agGrid/AgGridAdapter.js +88 -0
- package/src/agGrid/AgGridColumnAdapter.d.ts +44 -0
- package/src/agGrid/AgGridColumnAdapter.js +153 -37
- package/src/agGrid/AgGridMenuAdapter.d.ts +8 -2
- package/src/agGrid/AgGridMenuAdapter.js +17 -4
- package/src/agGrid/AgGridModulesAdapter.js +6 -1
- package/src/agGrid/AgGridThemeAdapter.d.ts +17 -0
- package/src/agGrid/AgGridThemeAdapter.js +37 -6
- package/src/components/Combobox/index.d.ts +11 -0
- package/src/components/Combobox/index.js +5 -3
- package/src/components/Radio/index.d.ts +2 -2
- package/src/components/Tree/TreeDropdown/index.d.ts +11 -0
- package/src/components/Tree/TreeDropdown/index.js +6 -3
- package/src/env.js +2 -2
- package/src/layout-manager/src/index.d.ts +9 -0
- package/src/layout-manager/src/index.js +38 -17
- package/src/types.d.ts +1 -1
- package/tsconfig.esm.tsbuildinfo +1 -1
|
@@ -5,7 +5,7 @@ import { AdaptableApi, DestroyConfig } from '../Api/AdaptableApi';
|
|
|
5
5
|
import { AdaptableVariant, IAdaptable, NormalizeAdaptableStateOptions } from '../AdaptableInterfaces/IAdaptable';
|
|
6
6
|
import { EmitterCallback } from '../Utilities/Emitter';
|
|
7
7
|
import { AdaptablePlugin } from '../AdaptableOptions/AdaptablePlugin';
|
|
8
|
-
import { AgGridAdapter } from './AgGridAdapter';
|
|
8
|
+
import { AgGridAdapter, RowNodeEvent } from './AgGridAdapter';
|
|
9
9
|
import { IDataService } from '../Utilities/Services/Interface/IDataService';
|
|
10
10
|
import { AdaptableState } from '../AdaptableState/AdaptableState';
|
|
11
11
|
import { IAdaptableStore } from '../Redux/Store/Interface/IAdaptableStore';
|
|
@@ -54,7 +54,6 @@ interface AdaptableInitInternalConfig<TData = any> {
|
|
|
54
54
|
}
|
|
55
55
|
export declare class AdaptableAgGrid implements IAdaptable {
|
|
56
56
|
logger: AdaptableLogger;
|
|
57
|
-
private _id;
|
|
58
57
|
lifecycleState: AdaptableLifecycleState;
|
|
59
58
|
variant: AdaptableVariant;
|
|
60
59
|
private emitter;
|
|
@@ -94,7 +93,7 @@ export declare class AdaptableAgGrid implements IAdaptable {
|
|
|
94
93
|
ThemeService: IThemeService;
|
|
95
94
|
private LicenseService;
|
|
96
95
|
private ChartingService;
|
|
97
|
-
private
|
|
96
|
+
private isListeningToAgGridRowNodeEvents;
|
|
98
97
|
private debouncedSetSelectedRows;
|
|
99
98
|
private debouncedSetSelectedCells;
|
|
100
99
|
private agGridListenerKeydown;
|
|
@@ -131,9 +130,6 @@ export declare class AdaptableAgGrid implements IAdaptable {
|
|
|
131
130
|
constructor(config?: {
|
|
132
131
|
getAgGridColumnApiModuleReference?: () => Module;
|
|
133
132
|
});
|
|
134
|
-
static forEachAdaptable(fn: (adaptable: AdaptableAgGrid) => void): void;
|
|
135
|
-
private static collectInstance;
|
|
136
|
-
private static dismissInstance;
|
|
137
133
|
get isAgGridInitialising(): boolean;
|
|
138
134
|
get isReady(): boolean;
|
|
139
135
|
get isAvailable(): boolean;
|
|
@@ -187,6 +183,22 @@ export declare class AdaptableAgGrid implements IAdaptable {
|
|
|
187
183
|
* Either initializes the AG Grid instance or delegates it to the framework wrappers (React/Anglar)
|
|
188
184
|
*/
|
|
189
185
|
private initializeAgGrid;
|
|
186
|
+
/**
|
|
187
|
+
* Derives the host element of the grid (the element the framework wrapper / `createGrid()` renders
|
|
188
|
+
* the grid into) when `ContainerOptions.agGridContainer` is not provided.
|
|
189
|
+
*
|
|
190
|
+
* AG Grid 36+ wraps the grid in three grid-owned `div.ag-styled-root` elements which mirror the
|
|
191
|
+
* theme classes (`ag-theme-params-N ...`, or the host's `ag-theme-<name>` in legacy mode);
|
|
192
|
+
* `AgGridAdapter.getAgGridRootElement()` is the innermost one. These wrappers must be skipped:
|
|
193
|
+
* they are re-classed by AG Grid on every theme change, so anything AdapTable adds/removes on them
|
|
194
|
+
* (legacy theme switching) would be lost.
|
|
195
|
+
*
|
|
196
|
+
* Resolution order:
|
|
197
|
+
* 1. the closest non-`.ag-styled-root` ancestor of the grid root (the host element)
|
|
198
|
+
* 2. legacy theme mode only: if the host element has no `ag-theme-*` class, the closest ancestor
|
|
199
|
+
* which has one (AG Grid itself accepts the theme class anywhere up the tree)
|
|
200
|
+
*/
|
|
201
|
+
private deriveAgGridContainerElement;
|
|
190
202
|
useRowNodeLookUp(): boolean;
|
|
191
203
|
private buildInitContainerContext;
|
|
192
204
|
getAgGridContainerElement(): HTMLElement | null;
|
|
@@ -198,6 +210,13 @@ export declare class AdaptableAgGrid implements IAdaptable {
|
|
|
198
210
|
private initAdaptableStore;
|
|
199
211
|
private mapAdaptableStateToAgGridState;
|
|
200
212
|
private addGridEventListeners;
|
|
213
|
+
/**
|
|
214
|
+
* see #local_event_service_monkey_patch (AgGridAdapter.ts)
|
|
215
|
+
*
|
|
216
|
+
* Entry point for the AG Grid RowNode `dataChanged` / `cellChanged` events, which AG Grid does not expose publicly.
|
|
217
|
+
* These drive Adaptable's data change detection (CellChanged events, Alerts, Flashing Cells, etc.)
|
|
218
|
+
*/
|
|
219
|
+
onAgGridRowNodeEvent(event: RowNodeEvent): void;
|
|
201
220
|
private shouldAutoSizeLayout;
|
|
202
221
|
private autoSizeLayoutIfNeeded;
|
|
203
222
|
forPlugins(callback: (plugin: AdaptablePlugin) => any): void;
|
|
@@ -232,6 +251,11 @@ export declare class AdaptableAgGrid implements IAdaptable {
|
|
|
232
251
|
private __forceUpdateColumnModel;
|
|
233
252
|
updateColumnModelAndRefreshGrid(): void;
|
|
234
253
|
_updateColumnModelAndRefreshGridNow(): void;
|
|
254
|
+
/**
|
|
255
|
+
* Re-applies the current sort, eg. after a Custom Sort was added/edited/removed at runtime.
|
|
256
|
+
* The column comparators are already up to date (see #stable_col_def_callbacks), AG Grid just has to sort again.
|
|
257
|
+
*/
|
|
258
|
+
refreshSortIfColumnsSorted(): void;
|
|
235
259
|
redrawBody(): void;
|
|
236
260
|
refreshHeader(): void;
|
|
237
261
|
redrawRows(rowNodes?: IRowNode[]): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { debounce } from '../Utilities/Helpers/TimingHelper';
|
|
2
|
-
import { createGrid,
|
|
2
|
+
import { createGrid, } from 'ag-grid-enterprise';
|
|
3
3
|
import { AdaptableLogger } from './AdaptableLogger';
|
|
4
4
|
import { PrimaryKeyDocsLink } from '../Utilities/Constants/DocumentationLinkConstants';
|
|
5
5
|
import StringExtensions from '../Utilities/Extensions/StringExtensions';
|
|
@@ -110,48 +110,9 @@ import { AgGridFilterAdapterFactory } from './AgGridFilterAdapter';
|
|
|
110
110
|
import { AdaptableFilterHandler } from './AdaptableFilterHandler';
|
|
111
111
|
import { AgGridFloatingFilterAdapterFactory } from './AgGridFloatingFilterAdapter';
|
|
112
112
|
import { listenForDevTools } from '../setupDevTools';
|
|
113
|
-
const LocalEventService_Prototype = LocalEventService.prototype;
|
|
114
|
-
const LocalEventService_dispatchEvent = LocalEventService_Prototype.dispatchEvent;
|
|
115
|
-
LocalEventService_Prototype.dispatchEvent = function (event) {
|
|
116
|
-
const agGridApi = event.api;
|
|
117
|
-
if (agGridApi?.isDestroyed()) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
LocalEventService_dispatchEvent.apply(this, arguments);
|
|
121
|
-
if (event.type === 'cellChanged' || event.type === 'dataChanged') {
|
|
122
|
-
const eventRowNode = event.node;
|
|
123
|
-
if (!eventRowNode) {
|
|
124
|
-
AdaptableLogger.consoleErrorBase(`No RowNode found in passed event, this should never happen!`, event);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
const extractGridApiFromRowNode = (rowNode) => {
|
|
128
|
-
const rowNodeApi = rowNode?.beans?.gridApi;
|
|
129
|
-
if (!rowNodeApi) {
|
|
130
|
-
AdaptableLogger.consoleErrorBase(`No GridAPI found in passed RowNode, this should never happen!`, rowNode);
|
|
131
|
-
}
|
|
132
|
-
return rowNodeApi;
|
|
133
|
-
};
|
|
134
|
-
if (eventRowNode) {
|
|
135
|
-
AdaptableAgGrid.forEachAdaptable((adaptable) => {
|
|
136
|
-
if (extractGridApiFromRowNode(eventRowNode) !== adaptable.agGridAdapter?.getAgGridApi(true)) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
if (adaptable.isDestroyed) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
const fn = adaptable.rowListeners ? adaptable.rowListeners[event.type] : null;
|
|
143
|
-
if (fn) {
|
|
144
|
-
fn(event);
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
const adaptableInstances = {};
|
|
151
113
|
const publishTimestamp = Number(ADAPTABLE_PUBLISH_TIMESTAMP);
|
|
152
114
|
export class AdaptableAgGrid {
|
|
153
115
|
logger;
|
|
154
|
-
_id;
|
|
155
116
|
lifecycleState;
|
|
156
117
|
variant;
|
|
157
118
|
emitter;
|
|
@@ -188,7 +149,7 @@ export class AdaptableAgGrid {
|
|
|
188
149
|
ThemeService;
|
|
189
150
|
LicenseService;
|
|
190
151
|
ChartingService;
|
|
191
|
-
|
|
152
|
+
isListeningToAgGridRowNodeEvents = false;
|
|
192
153
|
debouncedSetSelectedRows;
|
|
193
154
|
debouncedSetSelectedCells;
|
|
194
155
|
agGridListenerKeydown;
|
|
@@ -226,18 +187,6 @@ export class AdaptableAgGrid {
|
|
|
226
187
|
this.agGridModulesAdapter = new AgGridModulesAdapter(this);
|
|
227
188
|
this.DataService = new DataService(this);
|
|
228
189
|
}
|
|
229
|
-
static forEachAdaptable(fn) {
|
|
230
|
-
Object.keys(adaptableInstances).forEach((key) => {
|
|
231
|
-
fn(adaptableInstances[key]);
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
static collectInstance(adaptable, adaptableId) {
|
|
235
|
-
adaptable._id = adaptableId;
|
|
236
|
-
adaptableInstances[adaptable._id] = adaptable;
|
|
237
|
-
}
|
|
238
|
-
static dismissInstance(adaptable) {
|
|
239
|
-
delete adaptableInstances[adaptable._id];
|
|
240
|
-
}
|
|
241
190
|
get isAgGridInitialising() {
|
|
242
191
|
return this.lifecycleState === 'initAgGrid';
|
|
243
192
|
}
|
|
@@ -330,7 +279,6 @@ export class AdaptableAgGrid {
|
|
|
330
279
|
const adaptableId = this._rawAdaptableOptions.adaptableId;
|
|
331
280
|
const initMarker = getMarker(adaptableId).track.Init.label.Init.start();
|
|
332
281
|
const perfInitAdaptableAgGrid = this.logger.beginPerf(`Adaptable._initAdaptableAgGrid()`);
|
|
333
|
-
AdaptableAgGrid.collectInstance(this, this._rawAdaptableOptions.adaptableId);
|
|
334
282
|
this.variant = config.variant;
|
|
335
283
|
this.initWithLazyData =
|
|
336
284
|
config.gridOptions.rowData == undefined || config.gridOptions.rowData.length === 0;
|
|
@@ -669,6 +617,7 @@ export class AdaptableAgGrid {
|
|
|
669
617
|
agGridApi.onFilterChanged();
|
|
670
618
|
filteringApplied = true;
|
|
671
619
|
}
|
|
620
|
+
agGridApi.refreshCells();
|
|
672
621
|
this._emit('AdapTableFiltersApplied');
|
|
673
622
|
return filteringApplied;
|
|
674
623
|
}
|
|
@@ -1055,6 +1004,14 @@ export class AdaptableAgGrid {
|
|
|
1055
1004
|
return result;
|
|
1056
1005
|
};
|
|
1057
1006
|
});
|
|
1007
|
+
this.agGridOptionsService.setGridOptionsProperty(gridOptions, 'getColumnMenuItems', (original_getColumnMenuItems) => {
|
|
1008
|
+
return (params) => {
|
|
1009
|
+
if (params.source === 'columnMenu') {
|
|
1010
|
+
return this.agGridMenuAdapter.buildColumnMenu(params, original_getColumnMenuItems);
|
|
1011
|
+
}
|
|
1012
|
+
return this.agGridMenuAdapter.buildColumnsToolPanelMenu(params);
|
|
1013
|
+
};
|
|
1014
|
+
});
|
|
1058
1015
|
this.agGridOptionsService.setGridOptionsProperty(gridOptions, 'getMainMenuItems', (original_getMainMenuItems) => {
|
|
1059
1016
|
return (params) => {
|
|
1060
1017
|
return this.agGridMenuAdapter.buildColumnMenu(params, original_getMainMenuItems);
|
|
@@ -1300,8 +1257,7 @@ export class AdaptableAgGrid {
|
|
|
1300
1257
|
this.logger.info('Initializing with lazy data (no initial rowData).');
|
|
1301
1258
|
}
|
|
1302
1259
|
if (!this.getAgGridContainerElement()) {
|
|
1303
|
-
const
|
|
1304
|
-
const gridContainer = gridRoot?.closest('[class*="ag-theme"]');
|
|
1260
|
+
const gridContainer = this.deriveAgGridContainerElement(agGridApi.getGridOption('theme') === 'legacy');
|
|
1305
1261
|
if (!gridContainer) {
|
|
1306
1262
|
this.logger.consoleError('Failed to derive AG Grid container from the framework wrapper. Please provide a valid container element via ContainerOptions.agGridContainer.');
|
|
1307
1263
|
}
|
|
@@ -1321,6 +1277,27 @@ export class AdaptableAgGrid {
|
|
|
1321
1277
|
const agGridApi = createGrid(agGridContainer, gridOptions, gridParams);
|
|
1322
1278
|
return agGridApi;
|
|
1323
1279
|
}
|
|
1280
|
+
deriveAgGridContainerElement(isLegacyTheme) {
|
|
1281
|
+
const gridRoot = this.agGridAdapter.getAgGridRootElement();
|
|
1282
|
+
if (!gridRoot) {
|
|
1283
|
+
return undefined;
|
|
1284
|
+
}
|
|
1285
|
+
let hostElement = gridRoot;
|
|
1286
|
+
while (hostElement && hostElement.classList?.contains('ag-styled-root')) {
|
|
1287
|
+
hostElement = hostElement.parentElement;
|
|
1288
|
+
}
|
|
1289
|
+
if (!hostElement) {
|
|
1290
|
+
return undefined;
|
|
1291
|
+
}
|
|
1292
|
+
const hasAgThemeClass = (element) => Array.from(element.classList ?? []).some((cls) => cls.indexOf('ag-theme-') === 0);
|
|
1293
|
+
if (isLegacyTheme && !hasAgThemeClass(hostElement)) {
|
|
1294
|
+
const themedAncestor = hostElement.parentElement?.closest('[class*="ag-theme-"]');
|
|
1295
|
+
if (themedAncestor && hasAgThemeClass(themedAncestor)) {
|
|
1296
|
+
return themedAncestor;
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
return hostElement;
|
|
1300
|
+
}
|
|
1324
1301
|
useRowNodeLookUp() {
|
|
1325
1302
|
return this.agGridAdapter.getAgGridApi().getGridOption('getRowId') != undefined;
|
|
1326
1303
|
}
|
|
@@ -1519,25 +1496,23 @@ export class AdaptableAgGrid {
|
|
|
1519
1496
|
};
|
|
1520
1497
|
this.agGridAdapter.getAgGridApi().addGlobalListener(this.listenerGlobalChartingChanges);
|
|
1521
1498
|
}
|
|
1522
|
-
this.
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
}
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
},
|
|
1540
|
-
};
|
|
1499
|
+
this.isListeningToAgGridRowNodeEvents = true;
|
|
1500
|
+
}
|
|
1501
|
+
onAgGridRowNodeEvent(event) {
|
|
1502
|
+
if (!this.isListeningToAgGridRowNodeEvents) {
|
|
1503
|
+
return;
|
|
1504
|
+
}
|
|
1505
|
+
if (event.type === 'dataChanged') {
|
|
1506
|
+
const { node, oldData, newData } = event;
|
|
1507
|
+
this.onRowDataChanged({ rowNode: node, oldData, newData });
|
|
1508
|
+
return;
|
|
1509
|
+
}
|
|
1510
|
+
if (event.type === 'cellChanged') {
|
|
1511
|
+
const { node, column, oldValue, newValue } = event;
|
|
1512
|
+
if (column) {
|
|
1513
|
+
this.onCellDataChanged({ rowNode: node, oldValue, newValue, colId: column.getColId() });
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1541
1516
|
}
|
|
1542
1517
|
shouldAutoSizeLayout() {
|
|
1543
1518
|
const { layoutApi } = this.api;
|
|
@@ -1926,11 +1901,18 @@ export class AdaptableAgGrid {
|
|
|
1926
1901
|
}
|
|
1927
1902
|
}
|
|
1928
1903
|
_updateColumnModelAndRefreshGridNow() {
|
|
1929
|
-
|
|
1904
|
+
const startTime = performance.now();
|
|
1930
1905
|
this.deriveAdaptableColumnStateFromAgGrid();
|
|
1931
1906
|
this.agGridColumnAdapter.setupColumns();
|
|
1932
1907
|
this.redrawBody();
|
|
1933
1908
|
this.refreshHeader();
|
|
1909
|
+
this.logger.info(`Updated column model and refreshed grid in ${Math.round(performance.now() - startTime)}ms.`);
|
|
1910
|
+
}
|
|
1911
|
+
refreshSortIfColumnsSorted() {
|
|
1912
|
+
const columnSorts = this.api.layoutApi.getCurrentLayout()?.ColumnSorts;
|
|
1913
|
+
if (columnSorts?.length) {
|
|
1914
|
+
this.layoutManager.refreshSort();
|
|
1915
|
+
}
|
|
1934
1916
|
}
|
|
1935
1917
|
redrawBody() {
|
|
1936
1918
|
this.redrawRows();
|
|
@@ -3415,6 +3397,7 @@ export class AdaptableAgGrid {
|
|
|
3415
3397
|
'doesExternalFilterPass',
|
|
3416
3398
|
'excelStyles',
|
|
3417
3399
|
'getContextMenuItems',
|
|
3400
|
+
'getColumnMenuItems',
|
|
3418
3401
|
'getMainMenuItems',
|
|
3419
3402
|
'getRowClass',
|
|
3420
3403
|
'getRowId',
|
|
@@ -3458,13 +3441,12 @@ export class AdaptableAgGrid {
|
|
|
3458
3441
|
this.agGridThemeAdapter = null;
|
|
3459
3442
|
this.agGridModulesAdapter?.destroy();
|
|
3460
3443
|
this.agGridModulesAdapter = null;
|
|
3461
|
-
this.
|
|
3444
|
+
this.isListeningToAgGridRowNodeEvents = false;
|
|
3462
3445
|
this.emitter.destroy();
|
|
3463
3446
|
this.emitter = null;
|
|
3464
3447
|
this.adaptableOptions = null;
|
|
3465
3448
|
this.columnMinMaxValuesCache = null;
|
|
3466
3449
|
this.lifecycleState = 'preDestroyed';
|
|
3467
|
-
AdaptableAgGrid.dismissInstance(this);
|
|
3468
3450
|
if (config?.unmount) {
|
|
3469
3451
|
const abContainerElement = this.getAdaptableContainerElement();
|
|
3470
3452
|
if (abContainerElement != null) {
|
|
@@ -1,9 +1,34 @@
|
|
|
1
|
-
import { ColDef, ColGroupDef, Column, GridApi, GridOptions, IRowNode, ManagedGridOptionKey, ManagedGridOptions, Module } from 'ag-grid-enterprise';
|
|
1
|
+
import { AgEvent, ColDef, ColGroupDef, Column, GridApi, GridOptions, IRowNode, ManagedGridOptionKey, ManagedGridOptions, Module } from 'ag-grid-enterprise';
|
|
2
2
|
import type { AgChartInstance, AgSparklineOptions } from 'ag-charts-types';
|
|
3
3
|
import { AdaptableAgGrid } from './AdaptableAgGrid';
|
|
4
4
|
import { AdaptableColumn, AdaptableColumnGroup } from '../AdaptableState/Common/AdaptableColumn';
|
|
5
5
|
import { SelectedCellInfo } from '../AdaptableState/Selection/SelectedCellInfo';
|
|
6
6
|
import { SelectedRowInfo } from '../AdaptableState/Selection/SelectedRowInfo';
|
|
7
|
+
/**
|
|
8
|
+
* #local_event_service_monkey_patch
|
|
9
|
+
*
|
|
10
|
+
* AG Grid does not expose the RowNode `cellChanged` and `dataChanged` events (they are dispatched only on the
|
|
11
|
+
* RowNode's own, lazily created, `LocalEventService`), so we override `LocalEventService.prototype.dispatchEvent`
|
|
12
|
+
* and hook our own data change detection into it.
|
|
13
|
+
*
|
|
14
|
+
* Since AG Grid v36, `LocalEventService` lives in the `ag-stack` package (not in `ag-grid-community`).
|
|
15
|
+
* Unlike a duplicated `ag-grid-community`, a duplicated `ag-stack` copy in a consumer bundle
|
|
16
|
+
* (different install location, CJS vs ESM, version skew) is SILENT - AG Grid keeps working,
|
|
17
|
+
* but a prototype patched via `import { LocalEventService } from 'ag-stack'` would never be hit
|
|
18
|
+
* by the grid, because the grid instantiates the class from ITS copy of the module.
|
|
19
|
+
*
|
|
20
|
+
* Because of this we don't patch the statically imported class; instead we patch the prototype
|
|
21
|
+
* of the `LocalEventService` instance actually used by the running grid (`beans.eventSvc.globalSvc`)
|
|
22
|
+
* - one patch per distinct prototype, regardless of how many copies of `ag-stack` are loaded.
|
|
23
|
+
*
|
|
24
|
+
* The patched prototype is shared by ALL grids (and all their RowNodes), so the patch identifies the
|
|
25
|
+
* originating grid via `rowNode.beans` and routes the event to that grid's AgGridAdapter
|
|
26
|
+
* (see DANGER_AG_GRID_ADAPTERS_MAP & AgGridAdapter.handleRowNodeEvent).
|
|
27
|
+
*/
|
|
28
|
+
export type RowNodeEventType = 'dataChanged' | 'cellChanged';
|
|
29
|
+
export interface RowNodeEvent extends AgEvent<RowNodeEventType> {
|
|
30
|
+
node: IRowNode;
|
|
31
|
+
}
|
|
7
32
|
export type AgGridThemeMode = 'legacy' | 'themingApi';
|
|
8
33
|
export declare class AgGridAdapter {
|
|
9
34
|
private _adaptableInstance;
|
|
@@ -26,6 +51,11 @@ export declare class AgGridAdapter {
|
|
|
26
51
|
private getActivePivotColumnFilters;
|
|
27
52
|
private get agGridOptionsService();
|
|
28
53
|
setAgGridId(agGridId: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* see #local_event_service_monkey_patch
|
|
56
|
+
* Called (for the grid managed by this adapter) whenever AG Grid dispatches a RowNode `cellChanged` / `dataChanged` event
|
|
57
|
+
*/
|
|
58
|
+
handleRowNodeEvent(event: RowNodeEvent): void;
|
|
29
59
|
setAgGridApi(gridApi: GridApi): void;
|
|
30
60
|
getAgGridApi(skipLogging?: boolean): GridApi | undefined;
|
|
31
61
|
monkeyPatchingGridOptionsUpdates(): void;
|
|
@@ -34,6 +64,7 @@ export declare class AgGridAdapter {
|
|
|
34
64
|
private DANGER_getPrivateAgGridBeans;
|
|
35
65
|
DANGER_getCreateSparkline(): ((options: AgSparklineOptions) => AgChartInstance<AgSparklineOptions>) | undefined;
|
|
36
66
|
DANGER_getLiveGridOptions(): GridOptions<any>;
|
|
67
|
+
DANGER_invalidateSortCache(): void;
|
|
37
68
|
getAgGridRootElement(): HTMLElement;
|
|
38
69
|
/**
|
|
39
70
|
* When AG Grid is rendered the first time, the AG GridApi is not yet set in the Adaptable context (as it's set only AFTER the grid is fully initialised)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ColumnApiModule, } from 'ag-grid-enterprise';
|
|
2
|
+
import { AdaptableLogger } from './AdaptableLogger';
|
|
2
3
|
import { ACTION_COLUMN_TYPE, CALCULATED_COLUMN_TYPE, FDC3_COLUMN_TYPE, FREE_TEXT_COLUMN_TYPE, } from '../AdaptableState/Common/AdaptableColumn';
|
|
3
4
|
import { ACCESS_LEVEL_HIDDEN, ADAPTABLE_FDC3_ACTION_COLUMN_FRIENDLY_NAME, } from '../Utilities/Constants/GeneralConstants';
|
|
4
5
|
import { createUuid } from '../AdaptableState/Uuid';
|
|
@@ -10,7 +11,84 @@ import { isPivotColumnTotal } from '../layout-manager/src/isPivotColumnTotal';
|
|
|
10
11
|
import { isPivotAggTotalColumn } from '../layout-manager/src/isPivotAggTotalColumn';
|
|
11
12
|
import { ONLY_AGG_FN_NAME, WEIGHTED_AVERAGE_AGG_FN_NAME, } from '../AdaptableState/Common/AggregationColumns';
|
|
12
13
|
const DANGER_AG_GRID_BEANS_MAP = {};
|
|
14
|
+
const DANGER_AG_GRID_ADAPTERS_MAP = {};
|
|
13
15
|
const getColumnApiModule = () => ColumnApiModule;
|
|
16
|
+
const PATCHED_LOCAL_EVENT_SERVICE_PROTOTYPES = new WeakSet();
|
|
17
|
+
const patchLocalEventServiceDispatchEvent = (beans) => {
|
|
18
|
+
const localEventServiceInstance = beans?.eventSvc?.globalSvc;
|
|
19
|
+
const LocalEventService_Prototype = localEventServiceInstance
|
|
20
|
+
? Object.getPrototypeOf(localEventServiceInstance)
|
|
21
|
+
: null;
|
|
22
|
+
if (!LocalEventService_Prototype ||
|
|
23
|
+
typeof LocalEventService_Prototype.dispatchEvent !== 'function') {
|
|
24
|
+
AdaptableLogger.consoleErrorBase(`CRITICAL: could not get hold of AG Grid LocalEventService, data change detection will NOT work!`, beans);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (PATCHED_LOCAL_EVENT_SERVICE_PROTOTYPES.has(LocalEventService_Prototype)) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
PATCHED_LOCAL_EVENT_SERVICE_PROTOTYPES.add(LocalEventService_Prototype);
|
|
31
|
+
const LocalEventService_dispatchEvent = LocalEventService_Prototype.dispatchEvent;
|
|
32
|
+
LocalEventService_Prototype.dispatchEvent = function (event) {
|
|
33
|
+
LocalEventService_dispatchEvent.apply(this, arguments);
|
|
34
|
+
if (event.type !== 'cellChanged' && event.type !== 'dataChanged') {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const rowNodeEvent = event;
|
|
38
|
+
const rowNode = rowNodeEvent.node;
|
|
39
|
+
if (!rowNode) {
|
|
40
|
+
AdaptableLogger.consoleErrorBase(`No RowNode found in passed event, this should never happen!`, event);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const gridId = rowNode.beans?.context?.getId();
|
|
44
|
+
if (!gridId) {
|
|
45
|
+
AdaptableLogger.consoleErrorBase(`No gridId found in passed RowNode, this should never happen!`, rowNode);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
DANGER_AG_GRID_ADAPTERS_MAP[gridId]?.handleRowNodeEvent(rowNodeEvent);
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
const patchVisibleColsPartition = (beans) => {
|
|
52
|
+
const visibleCols = beans?.visibleCols;
|
|
53
|
+
if (!visibleCols || typeof visibleCols.partitionVisibleCols !== 'function') {
|
|
54
|
+
console.error(`CRITICAL: could not get hold of AG Grid VisibleColsService.partitionVisibleCols, the selection column may NOT be displayed when it is the last column!`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const original_partitionVisibleCols = visibleCols.partitionVisibleCols;
|
|
58
|
+
visibleCols.partitionVisibleCols = function () {
|
|
59
|
+
const result = original_partitionVisibleCols.apply(this, arguments);
|
|
60
|
+
const leftCols = result?.leftCols ?? [];
|
|
61
|
+
const rightCols = result?.rightCols ?? [];
|
|
62
|
+
const centerCols = result?.centerCols ?? [];
|
|
63
|
+
if (leftCols.length + rightCols.length + centerCols.length === 0) {
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
const colModel = beans.colModel;
|
|
67
|
+
const selectionCol = colModel?.colsList?.find((col) => col?.colKind === 'selection');
|
|
68
|
+
if (!selectionCol || !selectionCol.visible) {
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
if (leftCols.includes(selectionCol) ||
|
|
72
|
+
rightCols.includes(selectionCol) ||
|
|
73
|
+
centerCols.includes(selectionCol)) {
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
const showAutoGroupAndValuesOnly = colModel.pivotMode && !colModel.showingPivotResult;
|
|
77
|
+
if (showAutoGroupAndValuesOnly && !(beans.selectionColSvc?.isEnabled?.() ?? false)) {
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
if (selectionCol.pinned === 'right') {
|
|
81
|
+
rightCols.push(selectionCol);
|
|
82
|
+
}
|
|
83
|
+
else if (selectionCol.pinned) {
|
|
84
|
+
leftCols.push(selectionCol);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
centerCols.push(selectionCol);
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
};
|
|
91
|
+
};
|
|
14
92
|
export class AgGridAdapter {
|
|
15
93
|
_adaptableInstance;
|
|
16
94
|
DANGER_USE_GETTER_gridApi;
|
|
@@ -38,11 +116,14 @@ export class AgGridAdapter {
|
|
|
38
116
|
console.error('CRITICAL: No gridId found in beans, this should never happen!');
|
|
39
117
|
}
|
|
40
118
|
DANGER_AG_GRID_BEANS_MAP[gridId] = beans;
|
|
119
|
+
patchLocalEventServiceDispatchEvent(beans);
|
|
120
|
+
patchVisibleColsPartition(beans);
|
|
41
121
|
};
|
|
42
122
|
}
|
|
43
123
|
}
|
|
44
124
|
destroy() {
|
|
45
125
|
delete DANGER_AG_GRID_BEANS_MAP[this._agGridId];
|
|
126
|
+
delete DANGER_AG_GRID_ADAPTERS_MAP[this._agGridId];
|
|
46
127
|
this.initialGridOptions = null;
|
|
47
128
|
this.DANGER_gridApi_from_args = null;
|
|
48
129
|
this.DANGER_USE_GETTER_gridApi = null;
|
|
@@ -86,6 +167,10 @@ export class AgGridAdapter {
|
|
|
86
167
|
}
|
|
87
168
|
setAgGridId(agGridId) {
|
|
88
169
|
this._agGridId = agGridId;
|
|
170
|
+
DANGER_AG_GRID_ADAPTERS_MAP[agGridId] = this;
|
|
171
|
+
}
|
|
172
|
+
handleRowNodeEvent(event) {
|
|
173
|
+
this._adaptableInstance?.onAgGridRowNodeEvent(event);
|
|
89
174
|
}
|
|
90
175
|
setAgGridApi(gridApi) {
|
|
91
176
|
this.DANGER_USE_GETTER_gridApi = gridApi;
|
|
@@ -223,6 +308,9 @@ export class AgGridAdapter {
|
|
|
223
308
|
DANGER_getLiveGridOptions() {
|
|
224
309
|
return this.DANGER_getPrivateAgGridBeans()?.gridOptions;
|
|
225
310
|
}
|
|
311
|
+
DANGER_invalidateSortCache() {
|
|
312
|
+
this.DANGER_getPrivateAgGridBeans()?.sortSvc?.invalidate();
|
|
313
|
+
}
|
|
226
314
|
getAgGridRootElement() {
|
|
227
315
|
return this.DANGER_getPrivateAgGridBeans()?.eGridDiv;
|
|
228
316
|
}
|
|
@@ -7,12 +7,53 @@ export declare function getEditorForColumnDataType(columnDataType: AdaptableColu
|
|
|
7
7
|
export declare class AgGridColumnAdapter {
|
|
8
8
|
private adaptableInstance;
|
|
9
9
|
private colDefPropertyCache;
|
|
10
|
+
private workingColDefs;
|
|
11
|
+
private sortCacheInvalidationNeeded;
|
|
12
|
+
private stableCallbacks;
|
|
13
|
+
private stableCallbackImplementations;
|
|
14
|
+
private stableCallbackOwners;
|
|
15
|
+
private adaptableColumnFilterDef;
|
|
16
|
+
private adaptableFloatingFilterComponent;
|
|
10
17
|
constructor(adaptableInstance: AdaptableAgGrid);
|
|
11
18
|
private getVariant;
|
|
12
19
|
destroy(): void;
|
|
13
20
|
private get adaptableApi();
|
|
14
21
|
private get adaptableOptions();
|
|
15
22
|
private get agGridApi();
|
|
23
|
+
/**
|
|
24
|
+
* The colDef that `setupColumnXxx` methods should read from & write to:
|
|
25
|
+
* the working copy while the column is being set up (see #col_def_commit), the live colDef otherwise.
|
|
26
|
+
*/
|
|
27
|
+
private getColDefForSetup;
|
|
28
|
+
/**
|
|
29
|
+
* see #col_def_commit
|
|
30
|
+
* Creates the working copy of the colDef, which is committed via `commitColDefChanges`
|
|
31
|
+
*/
|
|
32
|
+
private beginColDefChanges;
|
|
33
|
+
/**
|
|
34
|
+
* see #col_def_commit
|
|
35
|
+
* Hands the working copy over to AG Grid, which re-initialises everything it caches from the colDef
|
|
36
|
+
* and refreshes the rendered cells of the column - but only if the colDef actually changed.
|
|
37
|
+
*/
|
|
38
|
+
private commitColDefChanges;
|
|
39
|
+
/**
|
|
40
|
+
* see #stable_col_def_callbacks
|
|
41
|
+
* Returns the (stable) function AG Grid should see for this column & property,
|
|
42
|
+
* delegating to the given (latest) implementation.
|
|
43
|
+
*/
|
|
44
|
+
private toStableCallback;
|
|
45
|
+
/**
|
|
46
|
+
* #pivot_result_col_def_copies_source
|
|
47
|
+
*
|
|
48
|
+
* AG Grid generates a pivot result colDef by copying the WHOLE colDef of its value (source) column
|
|
49
|
+
* (`PivotColDefService.createColDef` -> `Object.assign(colDef, valueColumn.colDef)`), and regenerates it
|
|
50
|
+
* whenever the source colDef is committed (see #col_def_commit). The copy therefore contains the
|
|
51
|
+
* callbacks Adaptable set up for the SOURCE column, which must not be mistaken for values provided by the user.
|
|
52
|
+
*
|
|
53
|
+
* When such a callback is found where a user value is expected, the user value of the source column
|
|
54
|
+
* is used instead - which is exactly what the pivot result column would have inherited from the user.
|
|
55
|
+
*/
|
|
56
|
+
private resolveUserProvidedValue;
|
|
16
57
|
setColDefProperty<T extends keyof ColDef>(col: Column, propertyName: T, propertyGetter: (userPropertyValue: ColDef[T]) => ColDef[T] | undefined): void;
|
|
17
58
|
getUserColDefProperty<T extends keyof ColDef>(columnId: string, propertyName: T): ColDef[T] | undefined;
|
|
18
59
|
shouldSkipColumn(colId: string): boolean;
|
|
@@ -22,6 +63,7 @@ export declare class AgGridColumnAdapter {
|
|
|
22
63
|
* @param specificColumnIds - optional list of column Ids to setup. If not provided, all columns are setup
|
|
23
64
|
*/
|
|
24
65
|
setupColumns(specificColumnIds?: string[]): void;
|
|
66
|
+
private setupColumn;
|
|
25
67
|
private setupColumnValueGetter;
|
|
26
68
|
private setupColumnCellClass;
|
|
27
69
|
private setupColumnHeaderClass;
|
|
@@ -45,6 +87,8 @@ export declare class AgGridColumnAdapter {
|
|
|
45
87
|
private setupColumnCellDataType;
|
|
46
88
|
setupColumnHeader({ col }: ColumnSetupInfo): void;
|
|
47
89
|
private setupColumnFilter;
|
|
90
|
+
private getAdaptableColumnFilterDef;
|
|
91
|
+
private getAdaptableFloatingFilterComponent;
|
|
48
92
|
private setupColumnFloatingFilter;
|
|
49
93
|
private setupColumnValueFormatter;
|
|
50
94
|
private setupColumnEditable;
|