@adaptabletools/adaptable-cjs 21.0.12 → 21.1.0-canary.1

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.
Files changed (66) hide show
  1. package/base.css +1811 -2336
  2. package/base.css.map +1 -1
  3. package/index.css +1768 -1413
  4. package/index.css.map +1 -1
  5. package/package.json +3 -3
  6. package/src/AdaptableInterfaces/IAdaptable.d.ts +2 -1
  7. package/src/AdaptableOptions/FilterOptions.d.ts +7 -0
  8. package/src/AdaptableOptions/PredicateOptions.d.ts +4 -3
  9. package/src/AdaptableState/Common/AdaptableColumn.d.ts +1 -1
  10. package/src/AdaptableState/Common/AdaptablePredicate.d.ts +12 -0
  11. package/src/AdaptableState/Common/AdaptablePredicate.js +132 -18
  12. package/src/AdaptableState/Selection/GridCell.d.ts +10 -0
  13. package/src/Api/Implementation/ExportApiImpl.js +1 -7
  14. package/src/Api/Implementation/PredicateApiImpl.d.ts +3 -1
  15. package/src/Api/Implementation/PredicateApiImpl.js +27 -3
  16. package/src/Api/Internal/AdaptableInternalApi.d.ts +2 -1
  17. package/src/Api/Internal/AdaptableInternalApi.js +6 -0
  18. package/src/Api/Internal/PredicateInternalApi.d.ts +3 -1
  19. package/src/Api/Internal/PredicateInternalApi.js +14 -0
  20. package/src/Api/PredicateApi.d.ts +1 -1
  21. package/src/Redux/Store/AdaptableStore.js +111 -3
  22. package/src/Utilities/Helpers/Helper.js +26 -2
  23. package/src/Utilities/Hooks/index.d.ts +4 -0
  24. package/src/Utilities/Hooks/index.js +9 -0
  25. package/src/Utilities/Hooks/useAdaptableColumn.d.ts +2 -0
  26. package/src/Utilities/Hooks/useAdaptableColumn.js +10 -0
  27. package/src/Utilities/Hooks/useAdaptableOptions.d.ts +2 -0
  28. package/src/Utilities/Hooks/useAdaptableOptions.js +9 -0
  29. package/src/Utilities/Hooks/useAdaptableState.d.ts +3 -0
  30. package/src/Utilities/Hooks/useAdaptableState.js +43 -0
  31. package/src/Utilities/Services/ModuleService.js +1 -1
  32. package/src/Utilities/adaptableQlUtils.js +3 -0
  33. package/src/View/AdaptableComputedCSSVarsContext.d.ts +12 -0
  34. package/src/View/AdaptableComputedCSSVarsContext.js +32 -0
  35. package/src/View/Components/AdaptableInput/AdaptableDateInlineInput.d.ts +1 -1
  36. package/src/View/Components/ColumnFilter/FloatingFilter.js +5 -1
  37. package/src/View/Components/ColumnFilter/components/FloatingFilterInputList.js +1 -1
  38. package/src/View/Components/ColumnFilter/components/FloatingFilterValues.js +34 -9
  39. package/src/View/Components/FilterForm/ListBoxFilterForm.d.ts +1 -0
  40. package/src/View/Components/FilterForm/ListBoxFilterForm.js +93 -16
  41. package/src/View/Layout/Wizard/sections/ColumnsSection.js +1 -1
  42. package/src/View/renderWithAdaptableContext.js +3 -1
  43. package/src/agGrid/AdaptableAgGrid.d.ts +3 -1
  44. package/src/agGrid/AdaptableAgGrid.js +360 -23
  45. package/src/agGrid/AdaptableFilterHandler.d.ts +3 -1
  46. package/src/agGrid/AdaptableFilterHandler.js +16 -12
  47. package/src/agGrid/AgGridAdapter.js +9 -5
  48. package/src/agGrid/AgGridColumnAdapter.js +14 -12
  49. package/src/components/OverlayTrigger/index.js +1 -1
  50. package/src/components/Select/Select.js +21 -21
  51. package/src/components/Tree/TreeDropdown/index.d.ts +27 -0
  52. package/src/components/Tree/TreeDropdown/index.js +256 -0
  53. package/src/components/Tree/TreeList/index.d.ts +25 -0
  54. package/src/components/Tree/TreeList/index.js +40 -0
  55. package/src/devTools/DevToolsTracks.d.ts +31 -0
  56. package/src/devTools/DevToolsTracks.js +34 -0
  57. package/src/devTools/PerfMarker.d.ts +12 -0
  58. package/src/devTools/PerfMarker.js +2 -0
  59. package/src/devTools/index.d.ts +102 -0
  60. package/src/devTools/index.js +165 -0
  61. package/src/env.js +2 -2
  62. package/src/layout-manager/src/index.d.ts +2 -0
  63. package/src/layout-manager/src/index.js +24 -0
  64. package/src/metamodel/adaptable.metamodel.d.ts +6 -0
  65. package/src/metamodel/adaptable.metamodel.js +1 -1
  66. package/tsconfig.cjs.tsbuildinfo +1 -1
@@ -103,6 +103,9 @@ const AgGridThemeAdapter_1 = require("./AgGridThemeAdapter");
103
103
  const VersionUpgrade20_1 = require("../migration/VersionUpgrade20");
104
104
  const adaptableOverrideCheck_1 = require("../Utilities/adaptableOverrideCheck");
105
105
  const AgGridModulesAdapter_1 = require("./AgGridModulesAdapter");
106
+ const devTools_1 = require("../devTools");
107
+ const infinite_react_1 = require("@infinite-table/infinite-react");
108
+ const FormatHelper_1 = require("../Utilities/Helpers/FormatHelper");
106
109
  const LocalEventService_Prototype = ag_grid_enterprise_1.LocalEventService.prototype;
107
110
  const LocalEventService_dispatchEvent = LocalEventService_Prototype.dispatchEvent;
108
111
  LocalEventService_Prototype.dispatchEvent = function (event) {
@@ -281,6 +284,8 @@ class AdaptableAgGrid {
281
284
  this._rawAdaptableOptions.adaptableId = `adaptable_id_${Date.now()}`;
282
285
  }
283
286
  this.logger = this.logger ?? new AdaptableLogger_1.AdaptableLogger(this._rawAdaptableOptions.adaptableId);
287
+ const adaptableId = this._rawAdaptableOptions.adaptableId;
288
+ const initMarker = (0, devTools_1.getMarker)(adaptableId).track.Init.label.Init.start();
284
289
  const perfInitAdaptableAgGrid = this.logger.beginPerf(`Adaptable._initAdaptableAgGrid()`);
285
290
  AdaptableAgGrid.collectInstance(this, this._rawAdaptableOptions.adaptableId);
286
291
  this.variant = config.variant;
@@ -318,6 +323,7 @@ class AdaptableAgGrid {
318
323
  this.forPlugins((plugin) => plugin.afterInitServices(this));
319
324
  this.adaptableModules = this.initModules();
320
325
  this.forPlugins((plugin) => plugin.afterInitModules(this, this.adaptableModules));
326
+ const loadStoreMarker = (0, devTools_1.getMarker)(adaptableId).track.Init.label.LoadStore.start();
321
327
  const perfLoadStore = this.logger.beginPerf(`loadStore()`);
322
328
  this.adaptableStore = this.initAdaptableStore();
323
329
  this.forPlugins((plugin) => plugin.afterInitStore(this));
@@ -344,6 +350,7 @@ class AdaptableAgGrid {
344
350
  },
345
351
  });
346
352
  perfLoadStore.end();
353
+ loadStoreMarker.end();
347
354
  // just in case Adaptable was destroyed while loading the store (which is an async operation)
348
355
  if (this.isDestroyed) {
349
356
  this.midwayDestroy();
@@ -390,6 +397,7 @@ class AdaptableAgGrid {
390
397
  this.lifecycleState = 'initAgGrid';
391
398
  this.agGridAdapter.initialGridOptions = gridOptions;
392
399
  const perfInitAgGrid = this.logger.beginPerf(`initAgGrid()`);
400
+ const initAgGridMarker = (0, devTools_1.getMarker)(adaptableId).track.Init.label.InitAGGrid.start();
393
401
  this.validateColumnDefTypes(gridOptions.columnDefs);
394
402
  const agGridApi = await this.initializeAgGrid(gridOptions, config.modules, config.renderAgGridFrameworkComponent);
395
403
  if (agGridApi === false) {
@@ -423,6 +431,7 @@ class AdaptableAgGrid {
423
431
  this.logger.info(`Hide Loading Screen`);
424
432
  this.unmountLoadingScreen?.();
425
433
  perfInitAgGrid.end();
434
+ initAgGridMarker.end();
426
435
  // we need to intercept several AG Grid Api methods and trigger Adaptable state changes
427
436
  this.agGridAdapter.setAgGridApi(agGridApi);
428
437
  this.agGridAdapter.monkeyPatchingGridOptionsUpdates();
@@ -498,6 +507,7 @@ class AdaptableAgGrid {
498
507
  });
499
508
  });
500
509
  perfInitAdaptableAgGrid.end();
510
+ initMarker.end();
501
511
  return Promise.resolve(this.api);
502
512
  }
503
513
  midwayDestroy() {
@@ -554,6 +564,36 @@ You need to define at least one Layout!`);
554
564
  // eg: might not include the generated row group columns in the column order
555
565
  // but the normalization does this for us
556
566
  state.Layout.Layouts = state.Layout.Layouts.map((layout) => (0, LayoutHelpers_1.normalizeLayout)(layout, normalizeOptions));
567
+ //now let's normalize the In/NotIn predicate for the group column
568
+ // the inputs in this predicate should be an array of arrays
569
+ // but for ease of use (and also for similarity with the In predicate for
570
+ // other columns) we allow the inputs to be an array of strings
571
+ // and change them to an array of arrays
572
+ state.Layout.Layouts = state.Layout.Layouts.map((layout) => {
573
+ if (Array.isArray(layout.ColumnFilters)) {
574
+ layout.ColumnFilters = layout.ColumnFilters.map((columnFilter) => {
575
+ if (columnFilter.ColumnId === GeneralConstants_1.AG_GRID_GROUPED_COLUMN) {
576
+ if (Array.isArray(columnFilter.Predicates)) {
577
+ columnFilter.Predicates = columnFilter.Predicates.map((predicate) => {
578
+ if (predicate.PredicateId === 'In' || predicate.PredicateId === 'NotIn') {
579
+ if (Array.isArray(predicate.Inputs)) {
580
+ predicate.Inputs = predicate.Inputs.map((input) => {
581
+ if (!Array.isArray(input)) {
582
+ return [input];
583
+ }
584
+ return input;
585
+ });
586
+ }
587
+ }
588
+ return predicate;
589
+ });
590
+ }
591
+ }
592
+ return columnFilter;
593
+ });
594
+ }
595
+ return layout;
596
+ });
557
597
  }
558
598
  return state;
559
599
  }
@@ -1292,6 +1332,7 @@ You need to define at least one Layout!`);
1292
1332
  }
1293
1333
  initAdaptableStore() {
1294
1334
  const perfNewAdaptableStore = this.logger.beginPerf(`initAdaptableStore()`);
1335
+ const initAdaptableStoreMarker = (0, devTools_1.getMarker)(this.adaptableOptions.adaptableId).track.Init.label.InitStore.start();
1295
1336
  const adaptableStore = new AdaptableStore_1.AdaptableStore(this);
1296
1337
  adaptableStore.onAny((eventName, data) => {
1297
1338
  if (this.isReady) {
@@ -1300,6 +1341,7 @@ You need to define at least one Layout!`);
1300
1341
  this.forPlugins((plugin) => plugin.onStoreEvent(eventName, data, this.adaptableStore));
1301
1342
  });
1302
1343
  perfNewAdaptableStore.end();
1344
+ initAdaptableStoreMarker.end();
1303
1345
  return adaptableStore;
1304
1346
  }
1305
1347
  mapAdaptableStateToAgGridState(adaptableState, agGridColDefs, options) {
@@ -1718,12 +1760,12 @@ You need to define at least one Layout!`);
1718
1760
  /**
1719
1761
  * Use (lazy evaluated) getters to avoid unnecessary calculations and memoization to avoid recalculating the same values
1720
1762
  */
1721
- createGridCell(rowNode, columnId) {
1763
+ createGridCell(rowNode, columnId, defaults) {
1722
1764
  let _column;
1723
1765
  let _primaryKeyValue;
1724
- let _rawValue;
1725
- let _displayValue;
1726
- let _normalisedValue;
1766
+ let _rawValue = defaults ? defaults.rawValue : undefined;
1767
+ let _displayValue = defaults ? defaults.displayValue : undefined;
1768
+ let _normalisedValue = defaults ? defaults.normalisedValue : undefined;
1727
1769
  let _isRowGroupCell;
1728
1770
  const _isPivotCell = this.api.columnApi.isPivotResultColumn(columnId);
1729
1771
  const self = this;
@@ -2320,7 +2362,41 @@ You need to define at least one Layout!`);
2320
2362
  if (currentGridCells) {
2321
2363
  return currentGridCells;
2322
2364
  }
2323
- return (currentGridCells = this.getDistinctGridCellsForColumn(column));
2365
+ return (currentGridCells =
2366
+ column.columnId === GeneralConstants_1.AG_GRID_GROUPED_COLUMN
2367
+ ? this.getDistinctGridCellsForGroupedColumn()
2368
+ : column.dataType === 'date'
2369
+ ? this.getDistinctGridCellsForDateColumn(column)
2370
+ : this.getDistinctGridCellsForColumn(column));
2371
+ };
2372
+ // No distinct values so lets return unique grid cells
2373
+ const mapFn = (gridCell, level) => {
2374
+ if (level || Array.isArray(gridCell.children)) {
2375
+ const cell = gridCell;
2376
+ const inFilterValue = {
2377
+ value: gridCell.rawValue,
2378
+ label: gridCell.displayValue,
2379
+ level: level ?? 0,
2380
+ tooltip: false,
2381
+ get visible() {
2382
+ return gridCell.visible;
2383
+ },
2384
+ count: gridCell.count ?? 0,
2385
+ leafChildrenCount: cell.leafChildrenCount ?? 0,
2386
+ get visibleCount() {
2387
+ return gridCell.visibleCount ?? 0;
2388
+ },
2389
+ isSelected: gridCell.rowNode.displayed,
2390
+ children: cell.children
2391
+ ? cell.children.map((v) => mapFn(v, level ? level + 1 : 1))
2392
+ : undefined,
2393
+ };
2394
+ return inFilterValue;
2395
+ }
2396
+ return {
2397
+ value: gridCell.rawValue,
2398
+ label: gridCell.displayValue,
2399
+ };
2324
2400
  };
2325
2401
  // If there are custom distinct value, return them; otherwise return the Grids Cells just retrieved
2326
2402
  const customInFilterValues = this.adaptableOptions.filterOptions.customInFilterValues;
@@ -2341,13 +2417,21 @@ You need to define at least one Layout!`);
2341
2417
  label: gridCell.displayValue,
2342
2418
  value: gridCell.rawValue,
2343
2419
  isSelected: gridCell.rowNode.displayed,
2344
- count: gridCell.count,
2420
+ count: gridCell.count ?? 0,
2345
2421
  tooltip: false,
2422
+ level: 0,
2423
+ leafChildrenCount: gridCell.leafChildrenCount ?? 0,
2424
+ get children() {
2425
+ if (!gridCell.children) {
2426
+ return undefined;
2427
+ }
2428
+ return gridCell.children.map((gridCell) => mapFn(gridCell, 1));
2429
+ },
2346
2430
  get visible() {
2347
2431
  return gridCell.visible;
2348
2432
  },
2349
2433
  get visibleCount() {
2350
- return gridCell.visibleCount;
2434
+ return gridCell.visibleCount ?? 0;
2351
2435
  },
2352
2436
  };
2353
2437
  });
@@ -2359,13 +2443,21 @@ You need to define at least one Layout!`);
2359
2443
  label: gridCell.displayValue,
2360
2444
  value: gridCell.rawValue,
2361
2445
  isSelected: gridCell.rowNode.displayed,
2362
- count: gridCell.count,
2446
+ count: gridCell.count ?? 0,
2363
2447
  tooltip: false,
2448
+ level: 0,
2449
+ leafChildrenCount: gridCell.leafChildrenCount ?? 0,
2450
+ get children() {
2451
+ if (!gridCell.children) {
2452
+ return undefined;
2453
+ }
2454
+ return gridCell.children.map((gridCell) => mapFn(gridCell, 1));
2455
+ },
2364
2456
  get visible() {
2365
2457
  return gridCell.visible;
2366
2458
  },
2367
2459
  get visibleCount() {
2368
- return gridCell.visibleCount;
2460
+ return gridCell.visibleCount ?? 0;
2369
2461
  },
2370
2462
  };
2371
2463
  });
@@ -2381,6 +2473,14 @@ You need to define at least one Layout!`);
2381
2473
  isSelected: gridCell.rowNode.displayed,
2382
2474
  count: gridCell.count,
2383
2475
  tooltip: false,
2476
+ level: 0,
2477
+ get children() {
2478
+ if (!gridCell.children) {
2479
+ return undefined;
2480
+ }
2481
+ return gridCell.children.map((gridCell) => mapFn(gridCell, 1));
2482
+ },
2483
+ leafChildrenCount: gridCell.leafChildrenCount ?? 0,
2384
2484
  get visible() {
2385
2485
  return gridCell.visible;
2386
2486
  },
@@ -2401,14 +2501,7 @@ You need to define at least one Layout!`);
2401
2501
  }
2402
2502
  return customInFilterValuesResult;
2403
2503
  }
2404
- // No distinct values so lets return unique grid cells
2405
- const values = getCurrentGridCells().map((gridCell) => {
2406
- const inFilterValue = {
2407
- value: gridCell.rawValue,
2408
- label: gridCell.displayValue,
2409
- };
2410
- return inFilterValue;
2411
- });
2504
+ const values = getCurrentGridCells().map((gridCell) => mapFn(gridCell));
2412
2505
  return { values };
2413
2506
  }
2414
2507
  async getDistinctEditValuesForColumn(options) {
@@ -2458,6 +2551,218 @@ You need to define at least one Layout!`);
2458
2551
  return result;
2459
2552
  });
2460
2553
  }
2554
+ getDistinctGridCellsForGroupedColumn(rowNodes) {
2555
+ const groupedColumns = this.api.columnApi.getRowGroupedColumns();
2556
+ const treeMode = this.api.gridApi.isTreeDataGrid();
2557
+ // if we're not in tree mode, return if there are no grouped columns
2558
+ // but in tree mode, we have to continue, even if there are no grouped columns
2559
+ if (!groupedColumns.length && !treeMode) {
2560
+ return [];
2561
+ }
2562
+ let prevLevel = -1;
2563
+ const currentGroupKey = [];
2564
+ const currentParentGridCells = [];
2565
+ const topLevelGridCells = [];
2566
+ const includeLeafNodes = treeMode || !!this.agGridAdapter.getAgGridApi().getColumnDef(GeneralConstants_1.AG_GRID_GROUPED_COLUMN)?.field;
2567
+ const rowNodeCallback = (rowNode) => {
2568
+ if (!rowNode.group && !includeLeafNodes) {
2569
+ return;
2570
+ }
2571
+ const level = rowNode.level;
2572
+ const key = rowNode.key;
2573
+ if (level <= prevLevel) {
2574
+ currentGroupKey.length = level;
2575
+ currentParentGridCells.length = level;
2576
+ }
2577
+ prevLevel = level;
2578
+ // for non-tree mode
2579
+ // or for tree mode, if the rowNode has data - so it's not a filler group
2580
+ if (!treeMode || (treeMode && rowNode.data)) {
2581
+ currentGroupKey.push(key);
2582
+ }
2583
+ const parentGridCell = currentParentGridCells[currentParentGridCells.length - 1];
2584
+ const gridCell = this.addDistinctColumnValue(rowNode, GeneralConstants_1.AG_GRID_GROUPED_COLUMN, false);
2585
+ // for tree-mode filler nodes, we might end up without a gridCell
2586
+ // so we need to make sure it's defined
2587
+ if (gridCell) {
2588
+ gridCell.leafChildrenCount = rowNode.allLeafChildren?.length ?? 0;
2589
+ currentParentGridCells.push(gridCell);
2590
+ if (parentGridCell) {
2591
+ parentGridCell.children = parentGridCell.children || [];
2592
+ parentGridCell.children.push(gridCell);
2593
+ }
2594
+ if (level === 0 && gridCell) {
2595
+ topLevelGridCells.push(gridCell);
2596
+ }
2597
+ }
2598
+ };
2599
+ if (rowNodes) {
2600
+ rowNodes.forEach(rowNodeCallback);
2601
+ }
2602
+ else {
2603
+ this.agGridAdapter.getAgGridApi().forEachNode(rowNodeCallback);
2604
+ }
2605
+ const column = this.api.columnApi.getColumnWithColumnId(GeneralConstants_1.AG_GRID_GROUPED_COLUMN);
2606
+ return this.getUniqueGridCells(column, topLevelGridCells);
2607
+ }
2608
+ getDistinctGridCellsForDateColumn(column, rowNodes) {
2609
+ const topLevelGridCells = [];
2610
+ const treeDeepMap = new infinite_react_1.DeepMap();
2611
+ const isPivotResultColumn = column.isGeneratedPivotResultColumn;
2612
+ const includeTime = this.api.predicateApi.internalApi.shouldEvaluateInPredicateUsingTime(column.columnId);
2613
+ const colId = column.columnId;
2614
+ const rowNodeCallback = (rowNode) => {
2615
+ if (!rowNode) {
2616
+ return;
2617
+ }
2618
+ const initialCell = this.addDistinctColumnValue(rowNode, column.columnId, isPivotResultColumn);
2619
+ if (initialCell) {
2620
+ const value = initialCell.rawValue;
2621
+ // we want to filter out empty values
2622
+ if (value === '' || value === null || value === undefined) {
2623
+ return;
2624
+ }
2625
+ const dateInstance = (0, DateHelper_1.parseDateValue)(value);
2626
+ if (!(dateInstance instanceof Date)) {
2627
+ return;
2628
+ }
2629
+ const year = dateInstance.getFullYear();
2630
+ const month = dateInstance.getMonth() + 1;
2631
+ const day = dateInstance.getDate();
2632
+ const yearRawValue = `${year}`;
2633
+ const monthRawValue = `${year}-${`${month}`.padStart(2, '0')}`;
2634
+ const dayRawValue = `${monthRawValue}-${`${day}`.padStart(2, '0')}`;
2635
+ const yearCells = treeDeepMap.get([year]) || [];
2636
+ const yearCell = this.createGridCell(rowNode, colId, {
2637
+ rawValue: yearRawValue,
2638
+ displayValue: yearRawValue,
2639
+ normalisedValue: yearRawValue,
2640
+ });
2641
+ yearCells.push(yearCell);
2642
+ treeDeepMap.set([year], yearCells);
2643
+ const monthCells = treeDeepMap.get([year, month]) || [];
2644
+ const monthCell = this.createGridCell(rowNode, colId, {
2645
+ rawValue: monthRawValue,
2646
+ displayValue: (0, FormatHelper_1.DateFormatter)(`${monthRawValue}-01`, { Pattern: 'LLLL' }),
2647
+ normalisedValue: monthRawValue,
2648
+ });
2649
+ monthCells.push(monthCell);
2650
+ treeDeepMap.set([year, month], monthCells);
2651
+ const dayCells = treeDeepMap.get([year, month, day]) || [];
2652
+ const dayCell = this.createGridCell(rowNode, colId, {
2653
+ rawValue: dayRawValue,
2654
+ displayValue: `${day}`.padStart(2, '0'),
2655
+ normalisedValue: dayRawValue,
2656
+ });
2657
+ dayCells.push(dayCell);
2658
+ treeDeepMap.set([year, month, day], dayCells);
2659
+ if (includeTime) {
2660
+ const timeCells = treeDeepMap.get([year, month, day, dateInstance.getTime()]) || [];
2661
+ // if the value is a string, let's use it as the final raw value
2662
+ const timeRawValue = typeof value === 'string' ? value : `${dateInstance.toISOString()}`;
2663
+ let timeDisplayValue = typeof value === 'string'
2664
+ ? value
2665
+ : [dateInstance.getHours(), dateInstance.getMinutes(), dateInstance.getSeconds()]
2666
+ .map((v) => `${v}`.padStart(2, '0'))
2667
+ .join(':')
2668
+ .concat(dateInstance.getMilliseconds()
2669
+ ? `.${dateInstance.getMilliseconds().toString().padStart(3, '0')}`
2670
+ : '');
2671
+ const timeCell = this.createGridCell(rowNode, colId, {
2672
+ rawValue: timeRawValue,
2673
+ displayValue: timeDisplayValue,
2674
+ normalisedValue: timeRawValue,
2675
+ });
2676
+ timeCells.push(timeCell);
2677
+ treeDeepMap.set([year, month, day, dateInstance.getTime()], timeCells);
2678
+ }
2679
+ }
2680
+ };
2681
+ if (rowNodes) {
2682
+ rowNodes.forEach(rowNodeCallback);
2683
+ }
2684
+ else {
2685
+ this.agGridAdapter.getAgGridApi().forEachNode(rowNodeCallback);
2686
+ }
2687
+ const years = treeDeepMap.getKeysStartingWith([], {
2688
+ excludeSelf: true,
2689
+ depthLimit: 1,
2690
+ });
2691
+ for (const keys of years) {
2692
+ const [year] = keys;
2693
+ const yearCells = treeDeepMap.get([year]) || [];
2694
+ // should only be one item in the uniqueYearCells array
2695
+ const uniqueYearCell = this.getUniqueGridCells(column, yearCells)[0];
2696
+ if (!uniqueYearCell) {
2697
+ continue;
2698
+ }
2699
+ uniqueYearCell.children = [];
2700
+ topLevelGridCells.push(uniqueYearCell);
2701
+ const keysForYear = treeDeepMap.getKeysStartingWith([year], {
2702
+ depthLimit: 1,
2703
+ excludeSelf: true,
2704
+ });
2705
+ for (const keys of keysForYear) {
2706
+ const [_, month] = keys;
2707
+ const monthCells = treeDeepMap.get([year, month]) || [];
2708
+ const uniqueMonthCell = this.getUniqueGridCells(column, monthCells)[0];
2709
+ if (!uniqueMonthCell) {
2710
+ continue;
2711
+ }
2712
+ uniqueMonthCell.children = [];
2713
+ uniqueYearCell.children.push(uniqueMonthCell);
2714
+ // those are all the days for which there are values in this year/month
2715
+ const keysForMonth = treeDeepMap.getKeysStartingWith([year, month], {
2716
+ depthLimit: 1,
2717
+ excludeSelf: true,
2718
+ });
2719
+ for (const keys of keysForMonth) {
2720
+ const [_, __, day] = keys;
2721
+ const dayCells = treeDeepMap.get([year, month, day]) || [];
2722
+ const uniqueDayCell = this.getUniqueGridCells(column, dayCells)[0];
2723
+ if (!uniqueDayCell) {
2724
+ continue;
2725
+ }
2726
+ uniqueMonthCell.children.push(uniqueDayCell);
2727
+ if (includeTime) {
2728
+ uniqueDayCell.children = [];
2729
+ const keysForDay = treeDeepMap.getKeysStartingWith([year, month, day], {
2730
+ depthLimit: 1,
2731
+ excludeSelf: true,
2732
+ });
2733
+ for (const keys of keysForDay) {
2734
+ const [_, __, ___, time] = keys;
2735
+ const timeCells = treeDeepMap.get([year, month, day, time]) || [];
2736
+ const uniqueTimeCell = this.getUniqueGridCells(column, timeCells)[0];
2737
+ if (!uniqueTimeCell) {
2738
+ continue;
2739
+ }
2740
+ uniqueDayCell.children.push(uniqueTimeCell);
2741
+ }
2742
+ uniqueDayCell.leafChildrenCount =
2743
+ treeDeepMap.getKeysForLeafNodesStartingWith([year, month, day]).length;
2744
+ uniqueDayCell.children.sort((dayCell1, dayCell2) => {
2745
+ return dayCell1.rawValue.localeCompare(dayCell2.rawValue);
2746
+ });
2747
+ }
2748
+ }
2749
+ uniqueMonthCell.leafChildrenCount =
2750
+ treeDeepMap.getKeysForLeafNodesStartingWith([year, month]).length;
2751
+ uniqueMonthCell.children.sort((monthCell1, monthCell2) => {
2752
+ return monthCell1.rawValue.localeCompare(monthCell2.rawValue);
2753
+ });
2754
+ }
2755
+ uniqueYearCell.leafChildrenCount =
2756
+ treeDeepMap.getKeysForLeafNodesStartingWith([year]).length;
2757
+ uniqueYearCell.children.sort((monthCell1, monthCell2) => {
2758
+ return monthCell1.rawValue.localeCompare(monthCell2.rawValue);
2759
+ });
2760
+ }
2761
+ topLevelGridCells.sort((yearCell1, yearCell2) => {
2762
+ return yearCell1.rawValue.localeCompare(yearCell2.rawValue);
2763
+ });
2764
+ return topLevelGridCells;
2765
+ }
2461
2766
  getDistinctGridCellsForColumn(column, rowNodes) {
2462
2767
  let gridCells = [];
2463
2768
  const isPivotResultColumn = column.isGeneratedPivotResultColumn;
@@ -2494,10 +2799,17 @@ You need to define at least one Layout!`);
2494
2799
  // see https://www.ag-grid.com/javascript-data-grid/tree-data-paths/#filler-groups
2495
2800
  return;
2496
2801
  }
2802
+ // if (columnId !== AG_GRID_GROUPED_COLUMN) {
2803
+ // return;
2804
+ // }
2805
+ return this.getGridCellFromRowNode(rowNode, columnId);
2497
2806
  }
2498
2807
  else {
2499
2808
  // for normal Table Columns we do NOT return the values of the aggregates
2500
- return;
2809
+ if (columnId !== GeneralConstants_1.AG_GRID_GROUPED_COLUMN) {
2810
+ return;
2811
+ }
2812
+ return this.getGridCellFromRowNode(rowNode, columnId);
2501
2813
  }
2502
2814
  }
2503
2815
  if (isPivotResultColumn) {
@@ -2511,14 +2823,12 @@ You need to define at least one Layout!`);
2511
2823
  }
2512
2824
  }
2513
2825
  const returnValue = this.getGridCellFromRowNode(rowNode, columnId);
2514
- if (Helper_1.Helper.objectExists(returnValue)) {
2515
- return returnValue;
2516
- }
2826
+ return returnValue;
2517
2827
  }
2518
2828
  getUniqueGridCells(column, gridCells) {
2519
2829
  let gridCellsToUse = gridCells;
2520
2830
  const cache = new Map();
2521
- const lowercase = this.api.predicateApi.useCaseSensitivity();
2831
+ const lowercase = this.api.predicateApi.useCaseSensitivity(column.columnId);
2522
2832
  const getter = (dataItem) => {
2523
2833
  let value = dataItem.rawValue;
2524
2834
  if (value instanceof Date) {
@@ -3264,6 +3574,7 @@ You need to define at least one Layout!`);
3264
3574
  const prevLayout = this._prevLayout;
3265
3575
  this._prevLayout = layout;
3266
3576
  const perfSetLayout = this.logger.beginPerf(`setLayout(${layout.Name})`);
3577
+ const setLayoutMarker = (0, devTools_1.getMarker)(this.adaptableOptions.adaptableId).track.Runtime.label.SetLayout.start();
3267
3578
  const isPivot = (0, LayoutHelpers_1.isPivotLayout)(layout);
3268
3579
  // update the header name for all columns
3269
3580
  this.agGridAdapter
@@ -3315,6 +3626,22 @@ You need to define at least one Layout!`);
3315
3626
  }
3316
3627
  });
3317
3628
  perfSetLayout.end();
3629
+ setLayoutMarker.end({
3630
+ details: [
3631
+ {
3632
+ name: 'Layout name',
3633
+ value: layout.Name,
3634
+ },
3635
+ {
3636
+ name: 'Type',
3637
+ value: isPivot ? 'Pivot' : 'Table',
3638
+ },
3639
+ {
3640
+ name: isPivot ? 'Pivot Columns' : 'Table Columns',
3641
+ value: isPivot ? layout.PivotColumns.join(', ') : layout.TableColumns.join(', '),
3642
+ },
3643
+ ],
3644
+ });
3318
3645
  }
3319
3646
  getActiveAdaptableAggFuncForCol(columnId) {
3320
3647
  if (!columnId) {
@@ -3623,7 +3950,7 @@ You need to define at least one Layout!`);
3623
3950
  return hasPivotTotals(one) || hasPivotTotals(other);
3624
3951
  }
3625
3952
  onLayoutChange(layout) {
3626
- this.refreshAdaptableAfterLayoutChange(layout);
3953
+ layout = this.refreshAdaptableAfterLayoutChange(layout);
3627
3954
  this.api.layoutApi.createOrUpdateLayout(layout);
3628
3955
  }
3629
3956
  refreshAdaptableAfterLayoutChange(layout) {
@@ -3631,6 +3958,15 @@ You need to define at least one Layout!`);
3631
3958
  const prevLayoutForRefresh = this.__prevLayoutForRefresh || this.api.layoutApi.getCurrentLayout();
3632
3959
  // see #on-regroup-expect-group-column-to-be-recomputed-and-setup-properly
3633
3960
  const rowGroupsChanged = this.isRowGroupDifferentInLayout(prevLayoutForRefresh, layout);
3961
+ // when grouping changes, if we have a filter on the grouped column, we need to remove it
3962
+ // as it is no longer valid
3963
+ if (rowGroupsChanged && layout.ColumnFilters) {
3964
+ const newFilters = layout.ColumnFilters.filter((filter) => filter.ColumnId !== GeneralConstants_1.AG_GRID_GROUPED_COLUMN);
3965
+ if (newFilters.length != layout.ColumnFilters.length) {
3966
+ layout = { ...layout };
3967
+ layout.ColumnFilters = newFilters;
3968
+ }
3969
+ }
3634
3970
  const hasPivotTotalsInLayout = this.hasPivotTotalsInLayout(prevLayoutForRefresh, layout);
3635
3971
  const pivotColsChanged = JSON.stringify(layout.PivotColumns) !== JSON.stringify(prevLayoutForRefresh.PivotColumns);
3636
3972
  if (rowGroupsChanged || pivotColsChanged || hasPivotTotalsInLayout) {
@@ -3640,6 +3976,7 @@ You need to define at least one Layout!`);
3640
3976
  this.deriveAdaptableColumnStateFromAgGrid();
3641
3977
  }
3642
3978
  this.__prevLayoutForRefresh = layout;
3979
+ return layout;
3643
3980
  }
3644
3981
  validateColumnDefTypes(columnDefs) {
3645
3982
  // in Adaptable version 20 we switched from colDef.type to colDef.cellDataType
@@ -2,12 +2,14 @@ import { DoesFilterPassParams, FilterHandler, FilterHandlerParams } from 'ag-gri
2
2
  import { AdaptableApi } from '../Api/AdaptableApi';
3
3
  import { ColumnSetupInfo } from '../AdaptableState/Common/ColumnSetupInfo';
4
4
  import { InFilterValueResult } from '../AdaptableOptions/FilterOptions';
5
+ import { ColumnFilter } from '../types';
5
6
  export declare class AdaptableFilterHandler implements FilterHandler {
6
7
  private adaptableApi;
7
8
  readonly colId: string;
8
9
  private filterDisplayValuesResult;
9
10
  private previousFilterDisplayValuesResult;
10
11
  constructor(adaptableApi: AdaptableApi, columnSetup: ColumnSetupInfo);
12
+ getCurrentColumnFilters(): ColumnFilter[];
11
13
  doesFilterPass(params: DoesFilterPassParams): boolean;
12
14
  getCachedFilterDisplayValues(): InFilterValueResult | undefined;
13
15
  getLastCachedFilterDisplayValues(): InFilterValueResult | undefined;
@@ -21,6 +23,6 @@ export declare class AdaptableFilterHandler implements FilterHandler {
21
23
  onAnyFilterChanged(): void;
22
24
  resetFilterDisplayValues(): void;
23
25
  refreshFilterDisplayValues(): Promise<InFilterValueResult>;
24
- refresh(params: FilterHandlerParams<any, any, any, any>): void;
26
+ refresh(_params: FilterHandlerParams<any, any, any, any>): void;
25
27
  destroy(): void;
26
28
  }
@@ -6,6 +6,17 @@ class AdaptableFilterHandler {
6
6
  this.adaptableApi = adaptableApi;
7
7
  this.colId = columnSetup.colId;
8
8
  }
9
+ getCurrentColumnFilters() {
10
+ const columnFilters = this.adaptableApi.filterApi.columnFilterApi
11
+ .getActiveColumnFilters()
12
+ .filter((columnFilter) => this.adaptableApi.filterApi.columnFilterApi.isColumnFilterActive(columnFilter))
13
+ .filter((columnFilter) => columnFilter.ColumnId === this.colId)
14
+ .filter((columnFilter) => {
15
+ const shouldEvaluateFilterOnClient = this.adaptableApi.expressionApi.internalApi.shouldEvaluatePredicatesInAdaptableQL('ColumnFilter', columnFilter, columnFilter.Predicates);
16
+ return shouldEvaluateFilterOnClient;
17
+ });
18
+ return columnFilters;
19
+ }
9
20
  doesFilterPass(params) {
10
21
  try {
11
22
  const rowNode = params.node;
@@ -14,15 +25,11 @@ class AdaptableFilterHandler {
14
25
  if (!isRowFilterable) {
15
26
  return true;
16
27
  }
17
- const columnFilters = this.adaptableApi.filterApi.columnFilterApi
18
- .getActiveColumnFilters()
19
- .filter((columnFilter) => this.adaptableApi.filterApi.columnFilterApi.isColumnFilterActive(columnFilter))
20
- .filter((columnFilter) => columnFilter.ColumnId === this.colId)
21
- .filter((columnFilter) => {
22
- const shouldEvaluateFilterOnClient = this.adaptableApi.expressionApi.internalApi.shouldEvaluatePredicatesInAdaptableQL('ColumnFilter', columnFilter, columnFilter.Predicates);
23
- return shouldEvaluateFilterOnClient;
28
+ const columnFilters = this.getCurrentColumnFilters();
29
+ const anyFilterFailed = columnFilters.some((columnFilter) => {
30
+ const result = !this.adaptableApi.filterApi.columnFilterApi.internalApi.evaluateColumnFilter(columnFilter, rowNode);
31
+ return result;
24
32
  });
25
- const anyFilterFailed = columnFilters.some((columnFilter) => !this.adaptableApi.filterApi.columnFilterApi.internalApi.evaluateColumnFilter(columnFilter, rowNode));
26
33
  return anyFilterFailed ? false : true;
27
34
  }
28
35
  catch (ex) {
@@ -80,10 +87,7 @@ class AdaptableFilterHandler {
80
87
  this.resetFilterDisplayValues();
81
88
  return this.getFromCacheOrFetchFilterDisplayValues({ currentSearchValue: '' });
82
89
  }
83
- refresh(params) {
84
- // No specific refresh logic needed for this handler
85
- // The filter display values will be reset on new rows loaded or any filter changed
86
- }
90
+ refresh(_params) { }
87
91
  destroy() {
88
92
  this.filterDisplayValuesResult = undefined;
89
93
  this.previousFilterDisplayValuesResult = undefined;