@adaptabletools/adaptable 20.1.8 → 20.2.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.
Files changed (63) hide show
  1. package/base.css +27 -0
  2. package/base.css.map +1 -1
  3. package/index.css +22 -0
  4. package/index.css.map +1 -1
  5. package/package.json +2 -2
  6. package/src/AdaptableInterfaces/IAdaptable.d.ts +1 -0
  7. package/src/AdaptableOptions/DefaultAdaptableOptions.js +2 -1
  8. package/src/AdaptableOptions/ExportOptions.d.ts +91 -8
  9. package/src/AdaptableOptions/QuickSearchOptions.d.ts +1 -6
  10. package/src/AdaptableState/FormatColumnState.d.ts +8 -0
  11. package/src/AdaptableState/LayoutState.d.ts +15 -2
  12. package/src/AdaptableState/QuickSearchState.d.ts +8 -0
  13. package/src/Api/ColumnApi.d.ts +5 -0
  14. package/src/Api/ExportApi.d.ts +23 -7
  15. package/src/Api/Implementation/ColumnApiImpl.d.ts +2 -2
  16. package/src/Api/Implementation/ColumnApiImpl.js +15 -30
  17. package/src/Api/Implementation/ExportApiImpl.d.ts +11 -4
  18. package/src/Api/Implementation/ExportApiImpl.js +51 -9
  19. package/src/Api/Implementation/LayoutHelpers.js +44 -0
  20. package/src/Api/Implementation/QuickSearchApiImpl.d.ts +4 -0
  21. package/src/Api/Implementation/QuickSearchApiImpl.js +12 -0
  22. package/src/Api/Internal/AlertInternalApi.js +1 -1
  23. package/src/Api/Internal/ExportInternalApi.d.ts +3 -8
  24. package/src/Api/Internal/ExportInternalApi.js +1 -74
  25. package/src/Api/Internal/ExpressionInternalApi.d.ts +1 -1
  26. package/src/Api/Internal/ExpressionInternalApi.js +1 -32
  27. package/src/Api/Internal/FormatColumnInternalApi.d.ts +2 -1
  28. package/src/Api/Internal/FormatColumnInternalApi.js +62 -0
  29. package/src/Api/QuickSearchApi.d.ts +16 -0
  30. package/src/Redux/Store/AdaptableStore.js +3 -2
  31. package/src/Utilities/Constants/GeneralConstants.js +2 -1
  32. package/src/View/Components/Forms/AdaptableFormControlTextClear.d.ts +1 -0
  33. package/src/View/Components/Forms/AdaptableFormControlTextClear.js +1 -0
  34. package/src/View/Dashboard/Dashboard.js +2 -4
  35. package/src/View/Layout/Wizard/sections/AggregationsSection.js +2 -2
  36. package/src/View/Layout/Wizard/sections/PivotAggregationsSection.js +2 -2
  37. package/src/View/Layout/Wizard/sections/PivotRowGroupingSection.js +6 -1
  38. package/src/View/Layout/Wizard/sections/RowGroupingSection.d.ts +4 -0
  39. package/src/View/Layout/Wizard/sections/RowGroupingSection.js +22 -19
  40. package/src/View/QuickSearch/QuickSearchInput.js +6 -1
  41. package/src/View/QuickSearch/QuickSearchPopup.js +2 -3
  42. package/src/agGrid/AdaptableAgGrid.d.ts +2 -0
  43. package/src/agGrid/AdaptableAgGrid.js +121 -38
  44. package/src/agGrid/AgGridAdapter.d.ts +4 -1
  45. package/src/agGrid/AgGridAdapter.js +90 -13
  46. package/src/agGrid/AgGridColumnAdapter.d.ts +4 -0
  47. package/src/agGrid/AgGridColumnAdapter.js +142 -35
  48. package/src/agGrid/AgGridExportAdapter.d.ts +6 -1
  49. package/src/agGrid/AgGridExportAdapter.js +103 -14
  50. package/src/agGrid/FloatingFilterWrapper.js +30 -4
  51. package/src/env.js +2 -2
  52. package/src/layout-manager/src/LayoutManagerModel.d.ts +16 -2
  53. package/src/layout-manager/src/index.d.ts +1 -1
  54. package/src/layout-manager/src/index.js +135 -20
  55. package/src/layout-manager/src/normalizeLayoutModel.d.ts +2 -4
  56. package/src/layout-manager/src/normalizeLayoutModel.js +12 -16
  57. package/src/layout-manager/src/simplifyLayoutModel.js +15 -3
  58. package/src/metamodel/adaptable.metamodel.d.ts +71 -0
  59. package/src/metamodel/adaptable.metamodel.js +1 -1
  60. package/src/types.d.ts +1 -1
  61. package/tsconfig.esm.tsbuildinfo +1 -1
  62. package/src/Utilities/buildSortedColumnStateForLayout.d.ts +0 -7
  63. package/src/Utilities/buildSortedColumnStateForLayout.js +0 -131
@@ -134,6 +134,7 @@ export class AgGridColumnAdapter {
134
134
  this.setupColumnEditable(colSetupInfo);
135
135
  this.setupColumnValueSetter(colSetupInfo);
136
136
  this.setupColumnComparator(colSetupInfo);
137
+ this.setupColumnGetFindText(colSetupInfo);
137
138
  this.setupColumnCellEditor(colSetupInfo);
138
139
  this.setupColumnHeader(colSetupInfo);
139
140
  this.setupColumnQuickFilterText(colSetupInfo);
@@ -152,6 +153,8 @@ export class AgGridColumnAdapter {
152
153
  this.setColDefProperty(col, 'cellClass', (userCellClass) => {
153
154
  const formatColumns = this.adaptableApi.formatColumnApi.internalApi.getFormatColumnWithStyleClassNameForColumn(abColumn);
154
155
  const quickSearchStyleClassName = this.adaptableApi.quickSearchApi.getQuickSearchStyle().ClassName;
156
+ const quickSearchTextMatchStyle = this.getQuickSearchTextMatchStyle();
157
+ const quickSearchCurrentTextMatchStyle = this.getQuickSearchCurrentTextMatchStyle();
155
158
  const hasQuickSearchStyleClassName = StringExtensions.IsNotNullOrEmpty(quickSearchStyleClassName);
156
159
  const cellClass = (params) => {
157
160
  const gridCell = this.adaptableApi.gridApi.getGridCellFromRowNode(params.node, abColumn.columnId);
@@ -164,7 +167,7 @@ export class AgGridColumnAdapter {
164
167
  const cellClassKey = AgGridExportAdapter.getExcelClassNameForCell(colId, gridCell.primaryKeyValue, userDefinedCellClass);
165
168
  return this.adaptableInstance.agGridExportAdapter.getExcelStyleIdForCellClassKey(cellClassKey);
166
169
  }
167
- const isQuickSearchActive = hasQuickSearchStyleClassName && this.isQuickSearchActive(gridCell, params);
170
+ const isQuickSearchActive = this.isQuickSearchActive(gridCell);
168
171
  const editableClassName = this.getEditableCellClass(gridCell, params);
169
172
  const readonlyClassName = this.getReadonlyCellClass(gridCell, params);
170
173
  const editedClassName = this.getEditedCellClass(gridCell, params);
@@ -179,7 +182,10 @@ export class AgGridColumnAdapter {
179
182
  !hasStyledColumn && formatColumns.length
180
183
  ? this.getFormatColumnCellClass(formatColumns, abColumn, params)
181
184
  : null,
182
- isQuickSearchActive ? quickSearchStyleClassName : null,
185
+ isQuickSearchActive && hasQuickSearchStyleClassName ? quickSearchStyleClassName : null,
186
+ isQuickSearchActive && (quickSearchTextMatchStyle || quickSearchCurrentTextMatchStyle)
187
+ ? 'ab-QuickSearchFind'
188
+ : null,
183
189
  editableClassName,
184
190
  readonlyClassName,
185
191
  editedClassName,
@@ -197,19 +203,39 @@ export class AgGridColumnAdapter {
197
203
  return cellClass;
198
204
  });
199
205
  }
200
- setupColumnCellStyle({ col, colId, abColumn }) {
206
+ setupColumnCellStyle({ col }) {
201
207
  this.setColDefProperty(col, 'cellStyle', (userCellStyle) => {
202
208
  const quickSearchStyle = this.getQuickSearchCellStyle();
203
- const hasQuickSearchStyle = quickSearchStyle != undefined;
209
+ const quickSearchTextMatchStyle = this.getQuickSearchTextMatchStyle();
210
+ const quickSearchCurrentTextMatchStyle = this.getQuickSearchCurrentTextMatchStyle();
211
+ const textMatchStyle = quickSearchTextMatchStyle
212
+ ? Object.entries(quickSearchTextMatchStyle).reduce((acc, [key, value]) => {
213
+ // @ts-ignore
214
+ acc[`--ab-dynamic-${key}`] = value;
215
+ return acc;
216
+ }, {})
217
+ : undefined;
218
+ const currentTextMatchStyle = quickSearchCurrentTextMatchStyle
219
+ ? Object.entries(quickSearchCurrentTextMatchStyle).reduce((acc, [key, value]) => {
220
+ // @ts-ignore
221
+ acc[`--ab-dynamic-${key}`] = value;
222
+ return acc;
223
+ }, {})
224
+ : undefined;
225
+ const hasQuickSearchStyle = quickSearchStyle != undefined || quickSearchCurrentTextMatchStyle != undefined;
204
226
  const cellStyle = (params) => {
205
227
  const columnId = params.column.getColId();
206
228
  const gridCell = this.adaptableApi.gridApi.getGridCellFromRowNode(params.node, columnId);
207
229
  if (!gridCell || !gridCell.column) {
208
230
  return {};
209
231
  }
210
- const isQuickSearchActive = hasQuickSearchStyle && this.isQuickSearchActive(gridCell, params);
232
+ const isQuickSearchActive = hasQuickSearchStyle && this.isQuickSearchActive(gridCell);
233
+ const isCurrentMatch = this.adaptableApi.agGridApi.findGetActiveMatch()?.node === params.node;
234
+ const textStyleToApply = isCurrentMatch
235
+ ? { ...textMatchStyle, ...currentTextMatchStyle }
236
+ : textMatchStyle;
211
237
  let baseStyles = {};
212
- // this is required because otherwise, when AG Grid filters, it refershed the pivotResultColDef and the base styles get lost
238
+ // this is required because otherwise, when AG Grid filters, it refreshed the pivotResultColDef and the base styles get lost
213
239
  // if pivot result col: inherit styles from base column
214
240
  if (this.adaptableApi.columnApi.isPivotResultColumn(columnId)) {
215
241
  const baseColumn = params.column.getColDef()?.pivotValueColumn;
@@ -233,6 +259,7 @@ export class AgGridColumnAdapter {
233
259
  ...this.getEditedCellStyle(gridCell, params),
234
260
  ...this.getFormatColumnAndStyledColumnCellStyle(gridCell, params),
235
261
  ...(isQuickSearchActive ? quickSearchStyle : {}),
262
+ ...(isQuickSearchActive && textStyleToApply ? textStyleToApply : {}),
236
263
  ...this.getAlertCellStyle(gridCell, params),
237
264
  ...this.getFlashingCellStyle(gridCell, params),
238
265
  ...this.getCellHighlightStyle(gridCell, params),
@@ -398,18 +425,45 @@ export class AgGridColumnAdapter {
398
425
  });
399
426
  }
400
427
  setupColumnFilter({ col, colDef }) {
428
+ if (!this.adaptableOptions.filterOptions.useAdaptableFiltering) {
429
+ return;
430
+ }
431
+ // setup Auto Group Column Filter
432
+ if (this.adaptableApi.columnApi.isAutoRowGroupColumn(col.getColId())) {
433
+ if (this.adaptableApi.gridApi.isTreeDataGrid()) {
434
+ this.setColDefProperty(col, 'filter', (original_filter) => {
435
+ const autoGroupColumnDef = this.agGridApi.getGridOption('autoGroupColumnDef');
436
+ if (autoGroupColumnDef.filter != undefined) {
437
+ // we plan to provide a TreeListColumnFilter
438
+ // until then, it's the user's responsibility to explicitly set the filter in the provided `autoGroupColumnDef`
439
+ return original_filter;
440
+ }
441
+ else {
442
+ // if no filter is explicitly set, we do NOT provide a filter
443
+ return false;
444
+ }
445
+ });
446
+ }
447
+ else {
448
+ this.setColDefProperty(col, 'filter', () => {
449
+ return 'agGroupColumnFilter';
450
+ });
451
+ }
452
+ return;
453
+ }
454
+ // setup "normal" column filter
401
455
  this.setColDefProperty(col, 'filter', () => {
402
456
  if (!colDef.filter) {
403
457
  return;
404
458
  }
405
- if (!this.adaptableOptions.filterOptions.useAdaptableFiltering) {
406
- return;
407
- }
408
459
  this.agGridApi.destroyFilter(col);
409
460
  return FilterWrapperFactory(this.adaptableInstance);
410
461
  });
411
462
  }
412
463
  setupColumnFloatingFilterTemporarily(initialGridOptions) {
464
+ if (!this.adaptableOptions.filterOptions.useAdaptableFiltering) {
465
+ return;
466
+ }
413
467
  initialGridOptions.columnDefs
414
468
  ?.filter((colDef) => !this.isColGroupDef(colDef))
415
469
  .map((colDef) => {
@@ -423,6 +477,21 @@ export class AgGridColumnAdapter {
423
477
  const isFloatingFilterDisabled = !colDef.floatingFilter ||
424
478
  !this.adaptableOptions.filterOptions.useAdaptableFiltering ||
425
479
  !this.adaptableOptions.filterOptions.columnFilterOptions.showQuickFilter;
480
+ if (this.adaptableApi.columnApi.isAutoRowGroupColumn(col.getColId())) {
481
+ this.setColDefProperty(col, 'floatingFilter', (original_floatingFilter) => {
482
+ // the floating filter for the group column is "inherited" from the base column
483
+ // via the colDef.filter = 'agGroupColumnFilter'
484
+ // see #group_inherit_column_filter
485
+ // https://www.ag-grid.com/javascript-data-grid/grouping-single-group-column/#inherit-row-grouped-columns-filters
486
+ // https://www.ag-grid.com/javascript-data-grid/grouping-multiple-group-columns/#filtering
487
+ return original_floatingFilter;
488
+ });
489
+ this.setColDefProperty(col, 'suppressFloatingFilterButton', () => {
490
+ // hide button for multi column groups
491
+ return this.adaptableApi.columnApi.isAutoRowGroupColumnForMulti(col.getColId());
492
+ });
493
+ return;
494
+ }
426
495
  this.setColDefProperty(col, 'floatingFilterComponent', () => {
427
496
  if (isFloatingFilterDisabled) {
428
497
  return;
@@ -607,42 +676,66 @@ export class AgGridColumnAdapter {
607
676
  this.setColDefProperty(col, 'comparator', comparatorGetter('comparator'));
608
677
  this.setColDefProperty(col, 'pivotComparator', comparatorGetter('pivotComparator'));
609
678
  }
610
- isQuickSearchActive(gridCell, params) {
611
- const quickSearchValue = this.adaptableApi.quickSearchApi.getQuickSearchValue();
612
- if (StringExtensions.IsNullOrEmpty(quickSearchValue)) {
613
- return false;
614
- }
615
- if (!gridCell.rowNode) {
679
+ setupColumnGetFindText({ col, abColumn }) {
680
+ this.setColDefProperty(col, 'getFindText', (userGetFindText) => {
681
+ return (params) => {
682
+ const gridCell = this.adaptableApi.gridApi.getGridCellFromRowNode(params.node, abColumn.columnId);
683
+ if (!this.isCellSearchable(gridCell)) {
684
+ return null;
685
+ }
686
+ const getCellSearchText = this.adaptableOptions.quickSearchOptions.getCellSearchText;
687
+ if (getCellSearchText) {
688
+ const quickSearchValue = this.adaptableApi.quickSearchApi.getQuickSearchValue();
689
+ const quickSearchContext = {
690
+ ...this.adaptableApi.internalApi.buildBaseContext(),
691
+ gridCell,
692
+ quickSearchValue,
693
+ };
694
+ return getCellSearchText(quickSearchContext);
695
+ }
696
+ return userGetFindText?.(params) ?? gridCell.displayValue;
697
+ };
698
+ });
699
+ }
700
+ isCellSearchable(gridCell) {
701
+ const isCellSearchableFn = this.adaptableOptions.quickSearchOptions.isCellSearchable;
702
+ if (!gridCell.column) {
616
703
  return false;
617
704
  }
618
- let quickSearchContext;
619
- const isCellSearchable = this.adaptableOptions.quickSearchOptions.isCellSearchable;
620
- if (isCellSearchable) {
621
- quickSearchContext = {
705
+ if (isCellSearchableFn) {
706
+ const quickSearchValue = this.adaptableApi.quickSearchApi.getQuickSearchValue();
707
+ const quickSearchContext = {
622
708
  ...this.adaptableApi.internalApi.buildBaseContext(),
623
709
  gridCell,
624
710
  quickSearchValue,
625
711
  };
626
- if (!isCellSearchable(quickSearchContext)) {
712
+ if (!isCellSearchableFn(quickSearchContext)) {
627
713
  return false;
628
714
  }
629
715
  }
630
- const runCustomQuickSearch = this.adaptableOptions.quickSearchOptions.runCustomQuickSearch;
631
- if (runCustomQuickSearch) {
632
- if (!quickSearchContext) {
633
- quickSearchContext = {
634
- ...this.adaptableApi.internalApi.buildBaseContext(),
635
- gridCell,
636
- quickSearchValue,
637
- };
638
- }
639
- return runCustomQuickSearch(quickSearchContext);
716
+ return true;
717
+ }
718
+ isQuickSearchActive(gridCell) {
719
+ const quickSearchValue = this.adaptableApi.quickSearchApi.getQuickSearchValue();
720
+ if (!quickSearchValue) {
721
+ return false;
722
+ }
723
+ if (!this.isCellSearchable(gridCell)) {
724
+ return false;
725
+ }
726
+ let column = this.agGridApi.getColumn(gridCell.column.columnId);
727
+ if (!column && this.adaptableApi.layoutApi.isCurrentLayoutPivot()) {
728
+ column = this.agGridApi
729
+ .getAllGridColumns()
730
+ .find((col) => col.getColId() === gridCell.column.columnId);
731
+ }
732
+ if (!column) {
733
+ return false;
640
734
  }
641
- const isCaseSensitive = this.adaptableOptions.quickSearchOptions.isQuickSearchCaseSensitive;
642
- const cellDisplayValue = String(gridCell.displayValue);
643
- const displayValue = isCaseSensitive ? cellDisplayValue : cellDisplayValue.toLocaleLowerCase();
644
- const searchText = isCaseSensitive ? quickSearchValue : quickSearchValue.toLocaleLowerCase();
645
- return displayValue.indexOf(searchText) !== -1;
735
+ return (this.agGridApi.findGetNumMatches({
736
+ column,
737
+ node: gridCell.rowNode,
738
+ }) > 0);
646
739
  }
647
740
  getEditableCellClass(gridCell, params) {
648
741
  const editableCellStyle = this.adaptableApi.userInterfaceApi.getEditableCellStyle();
@@ -741,6 +834,20 @@ export class AgGridColumnAdapter {
741
834
  }
742
835
  return convertAdaptableStyleToCSS(quickSearchStyle);
743
836
  }
837
+ getQuickSearchTextMatchStyle() {
838
+ const quickSearchTextMatchStyle = this.adaptableApi.quickSearchApi.getQuickSearchTextMatchStyle();
839
+ if (!quickSearchTextMatchStyle) {
840
+ return undefined;
841
+ }
842
+ return convertAdaptableStyleToCSS(quickSearchTextMatchStyle);
843
+ }
844
+ getQuickSearchCurrentTextMatchStyle() {
845
+ const quickSearchCurrentTextMatchStyle = this.adaptableApi.quickSearchApi.getQuickSearchCurrentTextMatchStyle();
846
+ if (!quickSearchCurrentTextMatchStyle) {
847
+ return undefined;
848
+ }
849
+ return convertAdaptableStyleToCSS(quickSearchCurrentTextMatchStyle);
850
+ }
744
851
  getReadOnlyCellStyle(gridCell, params) {
745
852
  const editableCellStyle = this.adaptableApi.userInterfaceApi.getReadOnlyCellStyle();
746
853
  if (!editableCellStyle) {
@@ -1,13 +1,14 @@
1
1
  import { AdaptableAgGrid } from './AdaptableAgGrid';
2
2
  import { Report, ReportFormatType } from '../AdaptableState/ExportState';
3
3
  import { CsvExportParams, ExcelExportParams, ExcelStyle } from 'ag-grid-enterprise';
4
- import { ExportDestinationType, ExportResultData } from '../AdaptableOptions/ExportOptions';
4
+ import { CustomExportParams, ExportDestinationType, ExportResultData } from '../AdaptableOptions/ExportOptions';
5
5
  import { Layout } from '../AdaptableState/LayoutState';
6
6
  export interface ExportConfig {
7
7
  report: Report;
8
8
  format: ReportFormatType;
9
9
  destination: ExportDestinationType;
10
10
  showProgressIndicator: boolean;
11
+ customExportParams?: (defaultExportParams: CustomExportParams) => CustomExportParams;
11
12
  }
12
13
  interface ExportProcessContext extends ExportConfig {
13
14
  exportedColumnIds: string[];
@@ -71,5 +72,9 @@ export declare class AgGridExportAdapter {
71
72
  private getCsvSeparator;
72
73
  private computeSkipColumnHeaders;
73
74
  private computeGetCustomContentBelowRow;
75
+ private getCellExportValueFromRawValue;
76
+ private getCustomExportDateFormat;
77
+ private getCellExportValueFromRawValueByType;
78
+ private getCellExportFormatType;
74
79
  }
75
80
  export {};
@@ -1,7 +1,7 @@
1
1
  import { ExportModuleId } from '../Utilities/Constants/ModuleConstants';
2
2
  import { waitForTimeout } from '../Utilities/waitForTimeout';
3
3
  import { convertCSSAbsoluteFontSizeToPt, getVariableColor, sanitizeStyle, } from '../Utilities/Helpers/StyleHelper';
4
- import { DateFormatter } from '../Utilities/Helpers/FormatHelper';
4
+ import FormatHelper, { DateFormatter } from '../Utilities/Helpers/FormatHelper';
5
5
  import tinycolor from 'tinycolor2';
6
6
  import StringExtensions from '../Utilities/Extensions/StringExtensions';
7
7
  import { createUuid } from '../AdaptableState/Uuid';
@@ -72,7 +72,7 @@ export class AgGridExportAdapter {
72
72
  if (exportContext.isVisualExcelReport) {
73
73
  // FIXME AFL patch styles only for exported columns!
74
74
  // or even better, only cells
75
- this.patchExcelStyles();
75
+ this.patchExcelStyles(exportContext);
76
76
  excelStylesWerePatched = true;
77
77
  }
78
78
  // 1. easiest case, we download the file using AG Grid
@@ -128,7 +128,11 @@ export class AgGridExportAdapter {
128
128
  */
129
129
  buildExportProcessData(config) {
130
130
  const exportContext = this.buildExportProcessContext(config);
131
- const exportParams = this.buildExportParams(exportContext);
131
+ let exportParams = this.buildExportParams(exportContext);
132
+ if (typeof config?.customExportParams === 'function') {
133
+ this.logger.info(`Custom export params for ${config.report.Name} in ${config.format} format`);
134
+ exportParams = config.customExportParams(exportParams);
135
+ }
132
136
  exportContext.exportedColumnIds = exportParams.columnKeys;
133
137
  return {
134
138
  exportContext,
@@ -139,7 +143,10 @@ export class AgGridExportAdapter {
139
143
  const baseExportParams = this.buildBaseExportParams(exportContext);
140
144
  if (exportContext.format === 'Excel' || exportContext.format === 'VisualExcel') {
141
145
  const excelExportParams = baseExportParams;
142
- excelExportParams.sheetName = 'Sheet 1';
146
+ const sheetName = typeof this.exportOptions.excelSheetName === 'function'
147
+ ? this.exportOptions.excelSheetName(this.adaptableApi.exportApi.internalApi.buildBaseExportContext(exportContext.report.Name, exportContext.format, exportContext.destination))
148
+ : this.exportOptions.excelSheetName;
149
+ excelExportParams.sheetName = sheetName;
143
150
  return excelExportParams;
144
151
  }
145
152
  // for everything else we use the CSV export
@@ -398,7 +405,7 @@ export class AgGridExportAdapter {
398
405
  return isoFormattedDate;
399
406
  }
400
407
  }
401
- return this.adaptableApi.exportApi.internalApi.getCellExportValueFromRowNode(rowNode, columnId, exportContext.isVisualExcelReport);
408
+ return this.getCellExportValueFromRawValue(rowNode, this.adaptableApi.gridApi.getRawValueFromRowNode(rowNode, columnId), columnId, exportContext);
402
409
  }
403
410
  processRowGroupForExcelExport(rowNode, exportContext) {
404
411
  if (this.isTreeDataGrid()) {
@@ -423,10 +430,10 @@ export class AgGridExportAdapter {
423
430
  rawValue = dateRawValue;
424
431
  }
425
432
  }
426
- return this.adaptableApi.exportApi.internalApi.getCellExportValueFromRawValue(rowNode, rawValue, columnId, exportContext.isVisualExcelReport);
433
+ return this.getCellExportValueFromRawValue(rowNode, rawValue, columnId, exportContext);
427
434
  }
428
- patchExcelStyles() {
429
- const exportExcelStyles = this.buildExcelStyles();
435
+ patchExcelStyles(exportContext) {
436
+ const exportExcelStyles = this.buildExcelStyles(exportContext);
430
437
  // set DANGER_excelStyles without changing the array reference
431
438
  this.DANGER_excelStyles.splice(0, this.DANGER_excelStyles.length, ...exportExcelStyles);
432
439
  }
@@ -436,7 +443,7 @@ export class AgGridExportAdapter {
436
443
  this.cellClassKey2excelStyleIdMap = {};
437
444
  this.excelStylesWithFormattedDate = {};
438
445
  }
439
- buildExcelStyles() {
446
+ buildExcelStyles(exportContext) {
440
447
  // we make sure that we start with a clean slate
441
448
  // theoretically this should have happened at the end of the export process, but just in case
442
449
  this.resetExcelStyles();
@@ -488,7 +495,7 @@ export class AgGridExportAdapter {
488
495
  this.logger.warn(`Export Styling: Column with id ${columnId} not found in Adaptable`);
489
496
  return;
490
497
  }
491
- const isDateCellExportedAsFormattedValue = this.isDateCellExportedAsFormattedValue(adaptableColumn);
498
+ const isDateCellExportedAsFormattedValue = this.isDateCellExportedAsFormattedValue(adaptableColumn, exportContext);
492
499
  let cellClassParams;
493
500
  const getLazyCellClassParams = () => {
494
501
  if (!cellClassParams) {
@@ -555,6 +562,12 @@ export class AgGridExportAdapter {
555
562
  mostRelevantFormatColumn?.DisplayFormat?.Options?.Pattern;
556
563
  }
557
564
  if (dateFormatPattern) {
565
+ const customDateFormatPattern = typeof dateFormatPattern === 'function'
566
+ ? dateFormatPattern({
567
+ ...this.adaptableApi.exportApi.internalApi.buildBaseExportContext(exportContext.report.Name, exportContext.format, exportContext.destination),
568
+ column: adaptableColumn,
569
+ })
570
+ : dateFormatPattern;
558
571
  const normalisedValue = this._adaptableInstance.getNormalisedValueFromRawValue(rawValue, abColumn);
559
572
  if (normalisedValue) {
560
573
  // we have to pass the date in the ISO format to Excel
@@ -565,7 +578,7 @@ export class AgGridExportAdapter {
565
578
  });
566
579
  if (isoFormattedValue) {
567
580
  finalCellExcelStyle.dataType = 'DateTime';
568
- finalCellExcelStyle.numberFormat = { format: dateFormatPattern };
581
+ finalCellExcelStyle.numberFormat = { format: customDateFormatPattern };
569
582
  // create a new cell key to ensure any user provided className does not interfere
570
583
  const cellKey = AgGridExportAdapter.getExcelClassNameForCell(column.getColId(), this.adaptableApi.gridApi.getPrimaryKeyValueForRowNode(node));
571
584
  // we need to register so that later the cellProcessor will put the isoFormattedValue through (thus giving the formatting responsability to Excel)
@@ -591,11 +604,10 @@ export class AgGridExportAdapter {
591
604
  registerExcelStyleWithFormattedDate(cellClassId, isoFormattedValue) {
592
605
  this.excelStylesWithFormattedDate[cellClassId] = isoFormattedValue;
593
606
  }
594
- isDateCellExportedAsFormattedValue(abColumn) {
607
+ isDateCellExportedAsFormattedValue(abColumn, exportContext) {
595
608
  return (!!this.exportOptions.exportDateFormat ||
596
609
  // FIXME AFL move this method here
597
- this.adaptableApi.exportApi.internalApi.getCellExportFormatType(abColumn, 'date') ===
598
- 'formattedValue');
610
+ this.getCellExportFormatType(abColumn, 'date', exportContext) === 'formattedValue');
599
611
  }
600
612
  convertCSSToExcelStyle(style) {
601
613
  const getHexColor = (color) => {
@@ -785,4 +797,81 @@ export class AgGridExportAdapter {
785
797
  return detailRows;
786
798
  };
787
799
  }
800
+ getCellExportValueFromRawValue(rowNode, cellRawValue, columnId, exportContext) {
801
+ if (StringExtensions.IsNullOrEmpty(cellRawValue)) {
802
+ return cellRawValue;
803
+ }
804
+ const column = this.adaptableApi.columnApi.getColumnWithColumnId(columnId);
805
+ const columnDataType = column.dataType;
806
+ // 1. if it is a VisualExcel report format, we always ONLY send the formatted value and ignore all other properties
807
+ if (exportContext.isVisualExcelReport) {
808
+ return this.getCellExportValueFromRawValueByType(rowNode, cellRawValue, columnId, 'formattedValue');
809
+ }
810
+ const isDateColumn = columnDataType === 'date' || columnDataType === 'dateString';
811
+ // 2. if this is a date column and there is a custom export date format provided, that will next take precedence
812
+ if (isDateColumn) {
813
+ const customExportDateFormat = this.getCustomExportDateFormat(column, exportContext);
814
+ if (!!customExportDateFormat) {
815
+ return FormatHelper.DateFormatter(cellRawValue, {
816
+ Pattern: customExportDateFormat,
817
+ });
818
+ }
819
+ }
820
+ // 3. in all other cases check the general export format types
821
+ const cellExportFormat = this.getCellExportFormatType(column, columnDataType, exportContext);
822
+ return this.getCellExportValueFromRawValueByType(rowNode, cellRawValue, columnId, cellExportFormat);
823
+ }
824
+ getCustomExportDateFormat(column, exportContext) {
825
+ const exportDateFormatOption = this.adaptableApi.optionsApi.getExportOptions().exportDateFormat;
826
+ return typeof exportDateFormatOption === 'function'
827
+ ? exportDateFormatOption({
828
+ ...this.adaptableApi.exportApi.internalApi.buildBaseExportContext(exportContext.report.Name, exportContext.format, exportContext.destination),
829
+ column,
830
+ })
831
+ : exportDateFormatOption;
832
+ }
833
+ getCellExportValueFromRawValueByType(rowNode, cellRawValue, columnId,
834
+ // default to rawValue if, for some reason, the configs provide invalid values
835
+ type = 'rawValue') {
836
+ return type === 'rawValue'
837
+ ? cellRawValue
838
+ : // type === formattedValue
839
+ this.adaptableApi.gridApi.getDisplayValueFromRawValue(rowNode, columnId, cellRawValue);
840
+ }
841
+ getCellExportFormatType(column, columnDataType, exportContext) {
842
+ const exportDataFormat = this.exportOptions.exportDataFormat;
843
+ // First check if a function was provided and return the result
844
+ if (exportDataFormat != null && typeof exportDataFormat === 'function') {
845
+ const context = {
846
+ ...this.adaptableApi.exportApi.internalApi.buildBaseExportContext(exportContext.report.Name, exportContext.format, exportContext.destination),
847
+ column: column,
848
+ };
849
+ return exportDataFormat(context);
850
+ }
851
+ // Next Check if a "hard-coded" value has been provided and return that
852
+ if (exportDataFormat === 'rawValue') {
853
+ return 'rawValue';
854
+ }
855
+ if (exportDataFormat === 'formattedValue') {
856
+ return 'formattedValue';
857
+ }
858
+ // Finally test if a DataType object has been provided and return the relevant property
859
+ const dataFormatDataType = exportDataFormat;
860
+ if (dataFormatDataType) {
861
+ // format is customized based on column data type
862
+ switch (columnDataType) {
863
+ case 'text':
864
+ return dataFormatDataType.text;
865
+ case 'number':
866
+ return dataFormatDataType.number;
867
+ case 'date':
868
+ case 'dateString':
869
+ return dataFormatDataType.date;
870
+ default:
871
+ // default to rawValue for all other column types
872
+ return 'rawValue';
873
+ }
874
+ }
875
+ return 'rawValue';
876
+ }
788
877
  }
@@ -29,11 +29,37 @@ export const FloatingFilterWrapperFactory = (adaptable) => {
29
29
  function getNotifyModel(colId, onModelChange) {
30
30
  return getAgGridFilterNotifyModelFn(adaptableApi, colId, onModelChange);
31
31
  }
32
+ function findParentWithClass(element, className, stopClasses, applyToAll) {
33
+ let current = element.parentElement;
34
+ while (current) {
35
+ // Stop traversing if we hit any of the stop classes
36
+ if (stopClasses.some((stopClass) => current.classList.contains(stopClass))) {
37
+ return null;
38
+ }
39
+ if (current.classList.contains(className)) {
40
+ return current;
41
+ }
42
+ applyToAll?.(current);
43
+ current = current.parentElement;
44
+ }
45
+ return null;
46
+ }
32
47
  function patchParentElement(filterContainer) {
33
- if (filterContainer) {
34
- // todo: consider theme
35
- filterContainer.parentElement.style.overflow = 'visible';
36
- filterContainer.parentElement.parentElement.style.padding = 'var(--ab-space-1)';
48
+ if (!filterContainer) {
49
+ return;
50
+ }
51
+ const stopClasses = ['ag-header-row', 'ag-header-row-column-filter'];
52
+ // Find and update floating filter body
53
+ const filterBody = findParentWithClass(filterContainer, 'ag-floating-filter-full-body', stopClasses, (currentElem) => {
54
+ currentElem.style.height = '100%';
55
+ });
56
+ if (filterBody) {
57
+ filterBody.style.overflow = 'visible';
58
+ }
59
+ // Find and update header cell
60
+ const headerCell = findParentWithClass(filterContainer, 'ag-header-cell', stopClasses);
61
+ if (headerCell?.classList.contains('ag-floating-filter')) {
62
+ headerCell.style.padding = 'var(--ab-space-1)';
37
63
  }
38
64
  }
39
65
  if (adaptable.isAgGridInitialising) {
package/src/env.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export default {
2
2
  NEXT_PUBLIC_INFINITE_TABLE_LICENSE_KEY: "StartDate=2021-06-29|EndDate=2030-01-01|Owner=Adaptable|Type=distribution|TS=1624971462479|C=137829811,1004007071,2756196225,1839832928,3994409405,636616862" || '',
3
- PUBLISH_TIMESTAMP: 1748626733832 || Date.now(),
4
- VERSION: "20.1.8" || '--current-version--',
3
+ PUBLISH_TIMESTAMP: 1748873595292 || Date.now(),
4
+ VERSION: "20.2.0-canary.0" || '--current-version--',
5
5
  };
@@ -73,6 +73,20 @@ export interface BaseLayoutModel {
73
73
  RowGroupDisplay: 'collapsed';
74
74
  Values: any[][];
75
75
  };
76
+ /**
77
+ * Behaviour for Expanding / Collapsing Column Groups
78
+ */
79
+ ColumnGroupValues?: {
80
+ ColumnGroupDisplay: 'always-expanded';
81
+ } | {
82
+ ColumnGroupDisplay: 'expanded';
83
+ Values: any[];
84
+ } | {
85
+ ColumnGroupDisplay: 'always-collapsed';
86
+ } | {
87
+ ColumnGroupDisplay: 'collapsed';
88
+ Values: any[];
89
+ };
76
90
  /**
77
91
  * Hides aggFunc name in the column header: e.g. 'sum(Bank Balance)' will just be 'Bank Balance'
78
92
  */
@@ -85,9 +99,9 @@ export interface BaseLayoutModel {
85
99
  [columnId: string]: 'left' | 'right';
86
100
  };
87
101
  /**
88
- * Display Grand Total Row at the top or bottom of the Pivot Table
102
+ * Display Grand Total Row of the Pivot Table
89
103
  */
90
- GrandTotalRow?: 'top' | 'bottom' | boolean;
104
+ GrandTotalRow?: 'top' | 'bottom' | 'pinnedTop' | 'pinnedBottom' | boolean;
91
105
  }
92
106
  export type ColumnAggregationModel = {
93
107
  aggFunc: string | true;
@@ -76,7 +76,7 @@ export declare class LayoutManager<DATA_TYPE = any> extends LMEmitter {
76
76
  autoSizeColumns(columnIds?: string[]): false | string[];
77
77
  private applyPivotLayout;
78
78
  applyPivotTotals(layout: PivotLayoutModel): void;
79
- applyPivotExpandLevel(layout: PivotLayoutModel): void;
79
+ applyColumnGroupCollapseExpandState(layout: PivotLayoutModel | TableLayoutModel): void;
80
80
  private withSuppressColumnAnimation;
81
81
  private patchColDefType;
82
82
  private setupPivotTotals;