@adaptabletools/adaptable-cjs 20.0.4 → 20.0.5-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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptabletools/adaptable-cjs",
3
- "version": "20.0.4",
3
+ "version": "20.0.5-canary.0",
4
4
  "description": "Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements",
5
5
  "keywords": [
6
6
  "web-components",
@@ -12,7 +12,14 @@ export type TableAggregationColumns = {
12
12
  /**
13
13
  * Defines an Aggregated Column in a Pivot Layout
14
14
  */
15
- export type PivotAggregationColumns = TableAggregationColumns;
15
+ export type PivotAggregationColumns = {
16
+ ColumnId: string;
17
+ AggFunc: AggregationColumnValue;
18
+ TotalColumn?: boolean | 'before' | 'after' | {
19
+ PivotColumnId: string;
20
+ ShowTotal?: boolean | 'before' | 'after';
21
+ }[];
22
+ }[];
16
23
  export declare const WEIGHTED_AVERAGE_AGG_FN_NAME = "weightedAvg";
17
24
  /**
18
25
  * Defines a Weighted Average Agg
@@ -148,6 +148,18 @@ export interface PivotLayout extends LayoutBase {
148
148
  * Row Grouped Columns Columns - must NOT be provided
149
149
  */
150
150
  RowGroupedColumns?: never;
151
+ /**
152
+ * Display Grand Total Row at the top or bottom of the Pivot Table
153
+ */
154
+ GrandTotalRow?: 'top' | 'bottom' | boolean;
155
+ /**
156
+ * Display automatically calculated Totals of all Pivot Columns, in the position specified
157
+ */
158
+ GrandTotalColumn?: 'before' | 'after' | boolean;
159
+ /**
160
+ * Display automatically calculated Totals within EACH Pivot Column Group, in the position specified
161
+ */
162
+ PivotGroupTotalColumn?: 'before' | 'after' | boolean;
151
163
  }
152
164
  /**
153
165
  * Manages how (and which) Row Group values are stored
@@ -11,6 +11,7 @@ export declare function generateAutoTreeSingleColumn(): AdaptableColumn;
11
11
  export declare function generateAutoRowGroupColumnForColumn(column: AdaptableColumn): AdaptableColumn;
12
12
  export declare function getFriendlyNameForPivotResultColumn(columnId: string): string;
13
13
  export declare function isPivotResultColumn(columnId: string): boolean;
14
+ export declare function isPivotGrandTotalColumn(columnId: string): boolean;
14
15
  export declare class ColumnApiImpl extends ApiBase implements ColumnApi {
15
16
  internalApi: ColumnInternalApi;
16
17
  constructor(_adaptable: IAdaptable);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ColumnApiImpl = exports.isPivotResultColumn = exports.getFriendlyNameForPivotResultColumn = exports.generateAutoRowGroupColumnForColumn = exports.generateAutoTreeSingleColumn = exports.generateAutoRowGroupSingleColumn = exports.isAutoRowGroupColumn = void 0;
3
+ exports.ColumnApiImpl = exports.isPivotGrandTotalColumn = exports.isPivotResultColumn = exports.getFriendlyNameForPivotResultColumn = exports.generateAutoRowGroupColumnForColumn = exports.generateAutoTreeSingleColumn = exports.generateAutoRowGroupSingleColumn = exports.isAutoRowGroupColumn = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const ApiBase_1 = require("./ApiBase");
6
6
  const GeneralConstants = tslib_1.__importStar(require("../../Utilities/Constants/GeneralConstants"));
@@ -71,6 +71,13 @@ function generateAutoRowGroupColumnForColumn(column) {
71
71
  }
72
72
  exports.generateAutoRowGroupColumnForColumn = generateAutoRowGroupColumnForColumn;
73
73
  function getFriendlyNameForPivotResultColumn(columnId) {
74
+ if (isPivotGrandTotalColumn(columnId)) {
75
+ return `[Grand Total] ${columnId
76
+ .split('_')
77
+ .slice(2)
78
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
79
+ .join(' ')}`;
80
+ }
74
81
  return `[Pivot] ${columnId
75
82
  .split('_')
76
83
  .slice(1)
@@ -83,6 +90,10 @@ function isPivotResultColumn(columnId) {
83
90
  return columnId?.startsWith(GeneralConstants.AG_GRID_PIVOT_COLUMN);
84
91
  }
85
92
  exports.isPivotResultColumn = isPivotResultColumn;
93
+ function isPivotGrandTotalColumn(columnId) {
94
+ return columnId?.startsWith(GeneralConstants.AG_GRID_PIVOT_GRAND_TOTAL_COLUMN);
95
+ }
96
+ exports.isPivotGrandTotalColumn = isPivotGrandTotalColumn;
86
97
  class ColumnApiImpl extends ApiBase_1.ApiBase {
87
98
  constructor(_adaptable) {
88
99
  super(_adaptable);
@@ -146,7 +157,7 @@ class ColumnApiImpl extends ApiBase_1.ApiBase {
146
157
  return isAutoRowGroupColumn(columnId);
147
158
  }
148
159
  isPivotResultColumn(columnId) {
149
- return isPivotResultColumn(columnId);
160
+ return isPivotResultColumn(columnId) || isPivotGrandTotalColumn(columnId);
150
161
  }
151
162
  isAutoRowGroupColumnForSingle(columnId) {
152
163
  return columnId === normalizeLayoutModel_1.GROUP_COLUMN_ID__SINGLE;
@@ -209,12 +209,16 @@ const pivotLayoutToPivotLayoutModel = (pivotLayout) => {
209
209
  ColumnPinning: pivotLayout.ColumnPinning,
210
210
  PivotColumns: pivotLayout.PivotColumns,
211
211
  PivotExpandLevel: pivotLayout.PivotExpandLevel,
212
- PivotAggregationColumns: (pivotLayout.PivotAggregationColumns || []).map(({ ColumnId, AggFunc }) => {
212
+ PivotAggregationColumns: (pivotLayout.PivotAggregationColumns || []).map(({ ColumnId, AggFunc, TotalColumn }) => {
213
213
  return {
214
214
  ColumnId,
215
215
  AggFunc: toAggFunc(AggFunc),
216
+ TotalColumn,
216
217
  };
217
218
  }),
219
+ GrandTotalRow: pivotLayout.GrandTotalRow,
220
+ GrandTotalColumn: pivotLayout.GrandTotalColumn,
221
+ PivotGroupTotalColumn: pivotLayout.PivotGroupTotalColumn,
218
222
  RowGroupValues: pivotLayout.RowGroupValues
219
223
  ? pivotLayout.RowGroupValues.RowGroupDefaultBehavior === 'always-collapsed' ||
220
224
  pivotLayout.RowGroupValues.RowGroupDefaultBehavior === 'always-expanded'
@@ -340,10 +344,29 @@ const pivotLayoutModelToPivotLayout = (layoutModel, defaults) => {
340
344
  else {
341
345
  delete pivotLayout.RowGroupValues;
342
346
  }
347
+ if (layoutModel.GrandTotalRow) {
348
+ pivotLayout.GrandTotalRow = layoutModel.GrandTotalRow;
349
+ }
350
+ else {
351
+ delete pivotLayout.GrandTotalRow;
352
+ }
353
+ if (layoutModel.GrandTotalColumn) {
354
+ pivotLayout.GrandTotalColumn = layoutModel.GrandTotalColumn;
355
+ }
356
+ else {
357
+ delete pivotLayout.GrandTotalColumn;
358
+ }
359
+ if (layoutModel.PivotGroupTotalColumn) {
360
+ pivotLayout.PivotGroupTotalColumn = layoutModel.PivotGroupTotalColumn;
361
+ }
362
+ else {
363
+ delete pivotLayout.PivotGroupTotalColumn;
364
+ }
343
365
  if (layoutModel.PivotAggregationColumns) {
344
- pivotLayout.PivotAggregationColumns = (layoutModel.PivotAggregationColumns || []).map(({ ColumnId, AggFunc }) => ({
366
+ pivotLayout.PivotAggregationColumns = (layoutModel.PivotAggregationColumns || []).map(({ ColumnId, AggFunc, TotalColumn }) => ({
345
367
  ColumnId,
346
368
  AggFunc: toAggregationColumnValue(AggFunc),
369
+ TotalColumn,
347
370
  }));
348
371
  }
349
372
  else {
@@ -24,6 +24,7 @@ export declare const GROUP_PATH_SEPARATOR: string;
24
24
  export declare const AG_GRID_GROUPED_COLUMN: string;
25
25
  export declare const AG_GRID_SELECTION_COLUMN: string;
26
26
  export declare const AG_GRID_PIVOT_COLUMN: string;
27
+ export declare const AG_GRID_PIVOT_GRAND_TOTAL_COLUMN: string;
27
28
  export declare const AG_GRID_CHART_WINDOW = "AG Grid Window";
28
29
  export declare const ADAPTABLE_FDC3_ACTION_COLUMN_FRIENDLY_NAME = "(FDC3ActionColumn)";
29
30
  export declare const DEFAULT_DATE_FORMAT_PATTERN = "dd-MM-yyyy";
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LAYOUT_NEW_PIVOT_TOOLTIP = exports.LAYOUT_NEW_TABLE_TOOLTIP = exports.THEME_STYLE = exports.SYSTEM_EXPORT_DESTINATIONS = exports.CLIPBOARD_EXPORT_DESTINATION = exports.DOWNLOAD_EXPORT_DESTINATION = exports.SELECT_REPORT_FORMAT_STRING = exports.SELECT_REPORT_STRING = exports.SYSTEM_REPORT_FORMATS = exports.JSON_FORMAT_REPORT = exports.CSV_FORMAT_REPORT = exports.VISUAL_EXCEL_FORMAT_REPORT = exports.EXCEL_FORMAT_REPORT = exports.SYSTEM_REPORT_NAMES = exports.SELECTED_DATA_REPORT = exports.CURRENT_LAYOUT_REPORT = exports.ALL_DATA_REPORT = exports.SERVER_VALIDATION_MESSAGE_TYPE = exports.SERVER_VALIDATION_HEADER = exports.DEFAULT_LIVE_REPORT_THROTTLE_TIME = exports.MENU_SEPARATOR = exports.QUICK_SEARCH_DEBOUNCE_TIME = exports.DEFAULT_DOUBLE_DISPLAY_VALUE = exports.DEFAULT_INTEGER_DISPLAY_VALUE = exports.DEFAULT_STRING_DISPLAY_VALUE = exports.DEFAULT_DATE_FORMAT_PATTERN_WITH_TIME = exports.DEFAULT_DATE_FORMAT_PATTERN = exports.ADAPTABLE_FDC3_ACTION_COLUMN_FRIENDLY_NAME = exports.AG_GRID_CHART_WINDOW = exports.AG_GRID_PIVOT_COLUMN = exports.AG_GRID_SELECTION_COLUMN = exports.AG_GRID_GROUPED_COLUMN = exports.GROUP_PATH_SEPARATOR = exports.QUARTER_SECOND = exports.HALF_SECOND = exports.EMPTY_ARRAY = exports.EMPTY_STRING = exports.READ_ONLY_STYLE = exports.AGGRID_TOOLPANEL_COLUMNS = exports.AGGRID_TOOLPANEL_FILTERS = exports.ADAPTABLE_TOOLPANEL_COMPONENT = exports.ADAPTABLE_TOOLPANEL_ID = exports.ADAPTABLE_ID = exports.ADAPTABLE = exports.ERROR_LAYOUT = exports.OS_THEME = exports.DARK_THEME = exports.LIGHT_THEME = exports.MISSING_COLUMN = exports.AUTOGENERATED_PK_COLUMN = void 0;
4
- exports.OBSERVABLE_EXPRESSION_ROW_REMOVED = exports.OBSERVABLE_EXPRESSION_ROW_ADDED = exports.STANDALONE_MODULE_POPUPS = exports.LAYOUT_DELETE_TOOLTIP = exports.LAYOUT_CLONE_TOOLTIP = exports.LAYOUT_EDIT_TOOLTIP = exports.LAYOUT_SAVE_TOOLTIP = exports.LAYOUT_NEW_TABLE_OR_PIVOT_TOOLTIP = void 0;
3
+ exports.LAYOUT_NEW_TABLE_TOOLTIP = exports.THEME_STYLE = exports.SYSTEM_EXPORT_DESTINATIONS = exports.CLIPBOARD_EXPORT_DESTINATION = exports.DOWNLOAD_EXPORT_DESTINATION = exports.SELECT_REPORT_FORMAT_STRING = exports.SELECT_REPORT_STRING = exports.SYSTEM_REPORT_FORMATS = exports.JSON_FORMAT_REPORT = exports.CSV_FORMAT_REPORT = exports.VISUAL_EXCEL_FORMAT_REPORT = exports.EXCEL_FORMAT_REPORT = exports.SYSTEM_REPORT_NAMES = exports.SELECTED_DATA_REPORT = exports.CURRENT_LAYOUT_REPORT = exports.ALL_DATA_REPORT = exports.SERVER_VALIDATION_MESSAGE_TYPE = exports.SERVER_VALIDATION_HEADER = exports.DEFAULT_LIVE_REPORT_THROTTLE_TIME = exports.MENU_SEPARATOR = exports.QUICK_SEARCH_DEBOUNCE_TIME = exports.DEFAULT_DOUBLE_DISPLAY_VALUE = exports.DEFAULT_INTEGER_DISPLAY_VALUE = exports.DEFAULT_STRING_DISPLAY_VALUE = exports.DEFAULT_DATE_FORMAT_PATTERN_WITH_TIME = exports.DEFAULT_DATE_FORMAT_PATTERN = exports.ADAPTABLE_FDC3_ACTION_COLUMN_FRIENDLY_NAME = exports.AG_GRID_CHART_WINDOW = exports.AG_GRID_PIVOT_GRAND_TOTAL_COLUMN = exports.AG_GRID_PIVOT_COLUMN = exports.AG_GRID_SELECTION_COLUMN = exports.AG_GRID_GROUPED_COLUMN = exports.GROUP_PATH_SEPARATOR = exports.QUARTER_SECOND = exports.HALF_SECOND = exports.EMPTY_ARRAY = exports.EMPTY_STRING = exports.READ_ONLY_STYLE = exports.AGGRID_TOOLPANEL_COLUMNS = exports.AGGRID_TOOLPANEL_FILTERS = exports.ADAPTABLE_TOOLPANEL_COMPONENT = exports.ADAPTABLE_TOOLPANEL_ID = exports.ADAPTABLE_ID = exports.ADAPTABLE = exports.ERROR_LAYOUT = exports.OS_THEME = exports.DARK_THEME = exports.LIGHT_THEME = exports.MISSING_COLUMN = exports.AUTOGENERATED_PK_COLUMN = void 0;
4
+ exports.OBSERVABLE_EXPRESSION_ROW_REMOVED = exports.OBSERVABLE_EXPRESSION_ROW_ADDED = exports.STANDALONE_MODULE_POPUPS = exports.LAYOUT_DELETE_TOOLTIP = exports.LAYOUT_CLONE_TOOLTIP = exports.LAYOUT_EDIT_TOOLTIP = exports.LAYOUT_SAVE_TOOLTIP = exports.LAYOUT_NEW_TABLE_OR_PIVOT_TOOLTIP = exports.LAYOUT_NEW_PIVOT_TOOLTIP = void 0;
5
5
  exports.AUTOGENERATED_PK_COLUMN = '__ADAPTABLE_PK__';
6
6
  exports.MISSING_COLUMN = ' [MISSING]';
7
7
  exports.LIGHT_THEME = 'light';
@@ -27,6 +27,7 @@ exports.GROUP_PATH_SEPARATOR = '/';
27
27
  exports.AG_GRID_GROUPED_COLUMN = 'ag-Grid-AutoColumn';
28
28
  exports.AG_GRID_SELECTION_COLUMN = 'ag-Grid-SelectionColumn';
29
29
  exports.AG_GRID_PIVOT_COLUMN = 'pivot_';
30
+ exports.AG_GRID_PIVOT_GRAND_TOTAL_COLUMN = 'PivotRowTotal_pivot_';
30
31
  exports.AG_GRID_CHART_WINDOW = 'AG Grid Window';
31
32
  exports.ADAPTABLE_FDC3_ACTION_COLUMN_FRIENDLY_NAME = '(FDC3ActionColumn)';
32
33
  // FIXME AFL - load this from DateInputOptions
package/src/env.js CHANGED
@@ -2,6 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = {
4
4
  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" || '',
5
- PUBLISH_TIMESTAMP: 1744726373908 || Date.now(),
6
- VERSION: "20.0.4" || '--current-version--',
5
+ PUBLISH_TIMESTAMP: 1744819299231 || Date.now(),
6
+ VERSION: "20.0.5-canary.0" || '--current-version--',
7
7
  };
@@ -62,26 +62,17 @@ export type ColumnAggregationModel = {
62
62
  aggFunc: string | true;
63
63
  weightedColumnId?: string;
64
64
  };
65
- export type AggregationColumnsModel = {
65
+ export type AggregationColumnsModelItem = {
66
66
  ColumnId: string;
67
67
  AggFunc: ColumnAggregationModel;
68
- }[];
69
- type RowSummaryPosition = 'Top' | 'Bottom';
70
- export interface RowSummaryModel {
71
- /**
72
- * Where Row Summary appears - 'Top' or 'Bottom'
73
- */
74
- Position?: RowSummaryPosition;
75
- /**
76
- * Map of Columns with Summary Expressions
77
- */
78
- ColumnsMap: Record<string, string>;
79
- /**
80
- * Evaluates only currently filtered rows in the summary
81
- * @defaultValue true
82
- */
83
- IncludeOnlyFilteredRows?: boolean;
84
- }
68
+ };
69
+ export type AggregationColumnsModel = AggregationColumnsModelItem[];
70
+ export type PivotAggregationColumnsModel = (AggregationColumnsModelItem & {
71
+ TotalColumn?: boolean | 'before' | 'after' | {
72
+ PivotColumnId: string;
73
+ ShowTotal?: boolean | 'before' | 'after';
74
+ }[];
75
+ })[];
85
76
  export interface TableLayoutModel extends BaseLayoutModel {
86
77
  TableColumns: string[];
87
78
  /**
@@ -96,6 +87,7 @@ export interface TableLayoutModel extends BaseLayoutModel {
96
87
  * @defaultValue 'single'
97
88
  */
98
89
  RowGroupDisplayType?: 'single' | 'multi';
90
+ PivotAggregationColumns?: never;
99
91
  PivotColumns?: never;
100
92
  PivotGroupedColumns?: never;
101
93
  PivotExpandLevel?: never;
@@ -110,13 +102,24 @@ export interface PivotLayoutModel extends BaseLayoutModel {
110
102
  /**
111
103
  * Columns showing aggregated values in Group Rows; 1st value in record is Column name, 2nd is either aggfunc (e.g. sum, avg etc.) or 'true' (to use default aggfunc)
112
104
  */
113
- PivotAggregationColumns?: AggregationColumnsModel;
105
+ PivotAggregationColumns?: PivotAggregationColumnsModel;
114
106
  TableAggregationColumns?: never;
115
107
  /**
116
108
  * Columns which are row-grouped when the Layout is applied
117
109
  */
118
110
  PivotGroupedColumns?: string[];
119
111
  RowGroupedColumns?: never;
112
+ /**
113
+ * Display Grand Total Row at the top or bottom of the Pivot Table
114
+ */
115
+ GrandTotalRow?: 'top' | 'bottom' | boolean;
116
+ /**
117
+ * Display Total of all Pivot Columns before or after the Pivot Columns
118
+ */
119
+ GrandTotalColumn?: 'before' | 'after' | boolean;
120
+ /**
121
+ * Display automatically calculated Totals within EACH Pivot Column Group, in the position specified
122
+ */
123
+ PivotGroupTotalColumn?: 'before' | 'after' | boolean;
120
124
  }
121
125
  export type LayoutModel = TableLayoutModel | PivotLayoutModel;
122
- export {};
@@ -1,4 +1,4 @@
1
- import { ColumnState, GridApi, GridOptions, GridState } from 'ag-grid-enterprise';
1
+ import { ColDef, ColumnState, GridApi, GridOptions, GridState } from 'ag-grid-enterprise';
2
2
  import { PivotLayoutModel, TableLayoutModel } from './LayoutManagerModel';
3
3
  import { LMEmitter } from './LMEmitter';
4
4
  export type LayoutManagerOptions = {
@@ -69,7 +69,24 @@ export declare class LayoutManager<DATA_TYPE = any> extends LMEmitter {
69
69
  private computeColumnOrderAndVisibility;
70
70
  autoSizeColumns(columnIds?: string[]): false | string[];
71
71
  private applyPivotLayout;
72
+ applyPivotTotals(layout: PivotLayoutModel): void;
72
73
  applyPivotExpandLevel(layout: PivotLayoutModel): void;
73
74
  private withSuppressColumnAnimation;
75
+ private setupPivotTotals;
76
+ private isPivotRowTotalColDef;
77
+ private patchGrandTotalColumn;
78
+ private isPivotGroupTotalColumn;
79
+ private patchPivotGroupTotalColumn;
80
+ private patchPivotTotalColumn;
81
+ destructurePivotColumnId(colDef: ColDef, currentModel: {
82
+ pivotColIds: string[];
83
+ aggColIds: string[];
84
+ }): '!unknown!' | {
85
+ pivotColumnIds: string[];
86
+ pivotKeys: string[];
87
+ pivotColumnId: string;
88
+ aggregationColumnId?: string;
89
+ };
90
+ private getPivotTotalColumnConfig;
74
91
  }
75
92
  export {};
@@ -120,8 +120,12 @@ class LayoutManager extends LMEmitter_1.LMEmitter {
120
120
  }).bind(this);
121
121
  }
122
122
  this.setOptions(options);
123
+ // this ensures the grand total columns are positioned correctly (before/after) even when changed at runtime
124
+ // see https://www.ag-grid.com/react-data-grid/pivoting-column-groups/#changing-data-filters-and-configurations
125
+ this.gridApi.setGridOption('enableStrictPivotColumnOrder', true);
123
126
  this.setupEvents();
124
127
  this.indexColumns();
128
+ this.setupPivotTotals();
125
129
  globalThis.layoutManager = this;
126
130
  }
127
131
  destroy() {
@@ -255,6 +259,18 @@ class LayoutManager extends LMEmitter_1.LMEmitter {
255
259
  PivotAggregationColumns: layout.TableAggregationColumns,
256
260
  PivotExpandLevel: prevLayout?.PivotExpandLevel ?? -1,
257
261
  };
262
+ const grandTotalRow = this.gridApi.getGridOption('grandTotalRow');
263
+ if (grandTotalRow) {
264
+ pivotLayout.GrandTotalRow = grandTotalRow;
265
+ }
266
+ const grandTotalColumn = this.gridApi.getGridOption('pivotRowTotals');
267
+ if (grandTotalColumn) {
268
+ pivotLayout.GrandTotalColumn = grandTotalColumn;
269
+ }
270
+ const pivotGroupTotalColumn = this.gridApi.getGridOption('pivotColumnGroupTotals');
271
+ if (pivotGroupTotalColumn) {
272
+ pivotLayout.PivotGroupTotalColumn = pivotGroupTotalColumn;
273
+ }
258
274
  return (0, simplifyLayoutModel_1.simplifyPivotLayoutModel)(pivotLayout);
259
275
  }
260
276
  getTableLayoutModelFromGrid() {
@@ -275,7 +291,7 @@ class LayoutManager extends LMEmitter_1.LMEmitter {
275
291
  let ColumnPinning = {};
276
292
  const gridState = this.gridApi.getState();
277
293
  const prevLayout = this.currentLayout;
278
- const prevAggColumns = prevLayout?.TableAggregationColumns;
294
+ const prevAggColumns = prevLayout?.TableAggregationColumns ?? prevLayout?.PivotAggregationColumns;
279
295
  const prevAggColumnsMap = prevAggColumns?.reduce((acc, agg) => {
280
296
  acc[agg.ColumnId] = agg;
281
297
  return acc;
@@ -986,6 +1002,7 @@ class LayoutManager extends LMEmitter_1.LMEmitter {
986
1002
  return columnIds;
987
1003
  }
988
1004
  applyPivotLayout(layout, options) {
1005
+ this.applyPivotTotals(layout);
989
1006
  const columnState = this.computeColumnStateForPivotLayout(layout);
990
1007
  // by simply calling this.gridApi.applyColumnState(columnState)
991
1008
  // the order of aggregations is not preserved/guaranteed by ag-grid
@@ -1013,6 +1030,50 @@ class LayoutManager extends LMEmitter_1.LMEmitter {
1013
1030
  this.applyRowGroupValues(layout.RowGroupValues);
1014
1031
  }
1015
1032
  }
1033
+ applyPivotTotals(layout) {
1034
+ /**
1035
+ * GrandTotalRow
1036
+ */
1037
+ if (layout.GrandTotalRow) {
1038
+ const grandTotalRow = layout.GrandTotalRow === true || layout.GrandTotalRow === 'top'
1039
+ ? 'top'
1040
+ : layout.GrandTotalRow === 'bottom'
1041
+ ? 'bottom'
1042
+ : null;
1043
+ this.gridApi.setGridOption('grandTotalRow', grandTotalRow);
1044
+ }
1045
+ else {
1046
+ this.gridApi.setGridOption('grandTotalRow', null);
1047
+ }
1048
+ /**
1049
+ * GrandTotalColumn
1050
+ */
1051
+ if (layout.GrandTotalColumn) {
1052
+ const grandTotalColumn = layout.GrandTotalColumn === true || layout.GrandTotalColumn === 'before'
1053
+ ? 'before'
1054
+ : layout.GrandTotalColumn === 'after'
1055
+ ? 'after'
1056
+ : null;
1057
+ this.gridApi.setGridOption('pivotRowTotals', grandTotalColumn);
1058
+ }
1059
+ else {
1060
+ this.gridApi.setGridOption('pivotRowTotals', null);
1061
+ }
1062
+ /**
1063
+ * PivotGroupTotalColumn
1064
+ */
1065
+ if (layout.PivotGroupTotalColumn) {
1066
+ const pivotGroupTotalColumn = layout.PivotGroupTotalColumn === true || layout.PivotGroupTotalColumn === 'before'
1067
+ ? 'before'
1068
+ : layout.PivotGroupTotalColumn === 'after'
1069
+ ? 'after'
1070
+ : null;
1071
+ this.gridApi.setGridOption('pivotColumnGroupTotals', pivotGroupTotalColumn);
1072
+ }
1073
+ else {
1074
+ this.gridApi.setGridOption('pivotColumnGroupTotals', null);
1075
+ }
1076
+ }
1016
1077
  applyPivotExpandLevel(layout) {
1017
1078
  const PivotExpandLevel = layout.PivotExpandLevel ?? -1;
1018
1079
  const allDisplayedColumnGroups = this.gridApi.getAllDisplayedColumnGroups();
@@ -1048,5 +1109,230 @@ class LayoutManager extends LMEmitter_1.LMEmitter {
1048
1109
  }
1049
1110
  return res;
1050
1111
  }
1112
+ setupPivotTotals() {
1113
+ const _original_processPivotResultColDef = this.gridApi.getGridOption('processPivotResultColDef');
1114
+ this.gridApi.setGridOption('processPivotResultColDef', (resulColDef) => {
1115
+ _original_processPivotResultColDef?.(resulColDef);
1116
+ if (!(0, isPivotLayoutModel_1.isPivotLayoutModel)(this.currentLayout)) {
1117
+ return;
1118
+ }
1119
+ // column that contain the aggregated total for each value column per row
1120
+ this.patchGrandTotalColumn(resulColDef);
1121
+ this.patchPivotGroupTotalColumn(resulColDef);
1122
+ });
1123
+ const _original_processPivotResultColGroupDef = this.gridApi.getGridOption('processPivotResultColGroupDef');
1124
+ this.gridApi.setGridOption('processPivotResultColGroupDef', (colGroupDef) => {
1125
+ _original_processPivotResultColGroupDef?.(colGroupDef);
1126
+ if (!(0, isPivotLayoutModel_1.isPivotLayoutModel)(this.currentLayout)) {
1127
+ return;
1128
+ }
1129
+ this.patchPivotTotalColumn(colGroupDef);
1130
+ });
1131
+ }
1132
+ isPivotRowTotalColDef(colDef) {
1133
+ return colDef.colId?.startsWith('PivotRowTotal_');
1134
+ }
1135
+ patchGrandTotalColumn(resultColDef) {
1136
+ if (!(0, isPivotLayoutModel_1.isPivotLayoutModel)(this.currentLayout) || !this.currentLayout.GrandTotalColumn) {
1137
+ return;
1138
+ }
1139
+ if (this.isPivotRowTotalColDef(resultColDef)) {
1140
+ resultColDef.headerName = `Grand Total ${resultColDef.headerName}`;
1141
+ }
1142
+ }
1143
+ isPivotGroupTotalColumn(colDef) {
1144
+ // pivot group total are spanning cross all aggregations
1145
+ // therefore the last part of the colId is empty (hence the "dangling" underscore)
1146
+ return colDef.colId?.startsWith('pivot_') && colDef.colId?.endsWith('_');
1147
+ }
1148
+ patchPivotGroupTotalColumn(resultColDef) {
1149
+ if (!(0, isPivotLayoutModel_1.isPivotLayoutModel)(this.currentLayout) || !this.currentLayout.PivotGroupTotalColumn) {
1150
+ return;
1151
+ }
1152
+ if (this.isPivotGroupTotalColumn(resultColDef)) {
1153
+ // resultColDef
1154
+ const colInfo = this.destructurePivotColumnId(resultColDef, {
1155
+ pivotColIds: this.currentLayout.PivotColumns,
1156
+ aggColIds: this.currentLayout.PivotAggregationColumns.map((col) => col.ColumnId),
1157
+ });
1158
+ if (colInfo !== '!unknown!') {
1159
+ const currentPivotKey = colInfo.pivotKeys[colInfo.pivotKeys.length - 1];
1160
+ resultColDef.headerName = `${currentPivotKey} Total`;
1161
+ }
1162
+ }
1163
+ }
1164
+ patchPivotTotalColumn(colGroupDef) {
1165
+ const hasPivotTotalCols = (pivotLayout) => {
1166
+ return pivotLayout.PivotAggregationColumns?.some((aggCol) => !!aggCol.TotalColumn);
1167
+ };
1168
+ const isPivotTotalColDef = (colDef) => {
1169
+ return !!colDef.pivotTotalColumnIds?.length;
1170
+ };
1171
+ if (!(0, isPivotLayoutModel_1.isPivotLayoutModel)(this.currentLayout) || !hasPivotTotalCols(this.currentLayout)) {
1172
+ return;
1173
+ }
1174
+ const pivotRowTotalColDefsBefore = [];
1175
+ const pivotRowTotalColDefsAfter = [];
1176
+ const pivotTotalColDefsBefore = [];
1177
+ const pivotTotalColDefsAfter = [];
1178
+ const normalColDefs = [];
1179
+ colGroupDef.children.forEach((colDef) => {
1180
+ if (this.isPivotRowTotalColDef(colDef)) {
1181
+ if (this.gridApi.getGridOption('pivotRowTotals') === 'after') {
1182
+ pivotRowTotalColDefsAfter.push(colDef);
1183
+ }
1184
+ else {
1185
+ pivotRowTotalColDefsBefore.push(colDef);
1186
+ }
1187
+ return;
1188
+ }
1189
+ if (isPivotTotalColDef(colDef)) {
1190
+ if (!colDef.colId.startsWith('pivot_')) {
1191
+ this.warn(`Pivot total column ${colDef.colId} is not prefixed with 'pivot_', skipping...`);
1192
+ return;
1193
+ }
1194
+ // we do this for all total cols, but we will hide the ones that are not visible
1195
+ colDef.columnGroupShow = undefined;
1196
+ colDef.headerName = `Total ${colDef.headerName}`;
1197
+ const totalColConfig = this.getPivotTotalColumnConfig(colDef, this.currentLayout);
1198
+ if (!totalColConfig.visible) {
1199
+ colDef.hide = true;
1200
+ }
1201
+ else {
1202
+ if (totalColConfig.position === 'after') {
1203
+ pivotTotalColDefsAfter.push(colDef);
1204
+ }
1205
+ else {
1206
+ pivotTotalColDefsBefore.push(colDef);
1207
+ }
1208
+ }
1209
+ }
1210
+ else {
1211
+ normalColDefs.push(colDef);
1212
+ }
1213
+ });
1214
+ colGroupDef.children = [
1215
+ ...pivotRowTotalColDefsBefore,
1216
+ ...pivotTotalColDefsBefore,
1217
+ ...normalColDefs,
1218
+ ...pivotTotalColDefsAfter,
1219
+ ...pivotRowTotalColDefsAfter,
1220
+ ];
1221
+ }
1222
+ // supports only pivotTotalColumns (aggregation total) and pivotGroupTotal
1223
+ // AG Grid builds the ID as: `pivot_${pivotCols.join('-')}_${pivotKeys.join('-')}_${measureColumnId}`
1224
+ // see https://github.com/ag-grid/ag-grid/blob/e0cfe533b55b75cdc148cdfb1a4e977731dc0712/packages/ag-grid-enterprise/src/pivot/pivotColDefService.ts#L454C16-L454C88
1225
+ destructurePivotColumnId(colDef, currentModel) {
1226
+ const { colId } = colDef;
1227
+ // Basic validation
1228
+ if (!colId?.startsWith('pivot_')) {
1229
+ this.warn(`Column id must start with 'pivot_': ${colId}`);
1230
+ return '!unknown!';
1231
+ }
1232
+ const hasSpecialChars = (arr) => arr.some((str) => str.includes('-') || str.includes('_'));
1233
+ // AG Grid uses _ and - as delimiters
1234
+ // if we have these special characters in the column IDs, we need to parse them differently
1235
+ const colIdsOrKeysContainSpecialChars = hasSpecialChars(currentModel.pivotColIds) ||
1236
+ hasSpecialChars(currentModel.aggColIds) ||
1237
+ hasSpecialChars(colDef.pivotKeys || []);
1238
+ // Fast path - no special characters
1239
+ if (!colIdsOrKeysContainSpecialChars) {
1240
+ // Split by underscore to get 4 parts
1241
+ const parts = colId.split('_');
1242
+ if (parts.length !== 4) {
1243
+ this.warn(`Unsupported format of pivot total column id: ${colId}`);
1244
+ return '!unknown!';
1245
+ }
1246
+ const [_pivotPrefix, pivotColsTxt, pivotKeysTxt, aggregationColumnId] = parts;
1247
+ const pivotColumnIds = pivotColsTxt.split('-');
1248
+ const pivotKeys = pivotKeysTxt.split('-');
1249
+ const pivotColumnId = pivotColumnIds[pivotKeys.length - 1];
1250
+ return {
1251
+ pivotColumnIds,
1252
+ pivotKeys,
1253
+ pivotColumnId,
1254
+ aggregationColumnId: aggregationColumnId !== '' ? aggregationColumnId : undefined,
1255
+ };
1256
+ }
1257
+ // the complex path, where we have to handle the special characters
1258
+ // Remove 'pivot_' prefix
1259
+ const withoutPrefix = colId.slice(6);
1260
+ // Check if it's a pivot group total
1261
+ const isPivotGroupTotal = withoutPrefix.endsWith('_');
1262
+ // Get pivot keys from colDef (more reliable than string parsing)
1263
+ const pivotKeys = colDef.pivotKeys || [];
1264
+ if (isPivotGroupTotal) {
1265
+ // Remove trailing underscore for pivot group totals
1266
+ const content = withoutPrefix.slice(0, -1);
1267
+ // The remaining content should be the pivot columns
1268
+ const pivotColumnIds = currentModel.pivotColIds.filter((id) => content.includes(id));
1269
+ if (!pivotColumnIds.length) {
1270
+ this.warn(`Could not identify pivot columns in: ${content}`);
1271
+ return '!unknown!';
1272
+ }
1273
+ return {
1274
+ pivotColumnIds,
1275
+ pivotKeys,
1276
+ pivotColumnId: pivotColumnIds[pivotKeys.length],
1277
+ };
1278
+ }
1279
+ // For regular pivot columns, work backwards to find aggregation column
1280
+ const parts = withoutPrefix.split('_');
1281
+ const lastPart = parts[parts.length - 1];
1282
+ // Find the longest matching aggregation column id from the end
1283
+ const aggregationColumnId = currentModel.aggColIds.find((aggId) => lastPart.endsWith(aggId));
1284
+ if (!aggregationColumnId) {
1285
+ this.warn(`Could not identify aggregation column in: ${lastPart}`);
1286
+ return '!unknown!';
1287
+ }
1288
+ // Remove aggregation part and get pivot columns
1289
+ const withoutAgg = withoutPrefix.slice(0, -(aggregationColumnId.length + 1));
1290
+ const pivotColumnIds = currentModel.pivotColIds.filter((id) => withoutAgg.includes(id));
1291
+ if (!pivotColumnIds.length) {
1292
+ this.warn(`Could not identify pivot columns in: ${withoutAgg}`);
1293
+ return '!unknown!';
1294
+ }
1295
+ return {
1296
+ pivotColumnIds,
1297
+ pivotKeys,
1298
+ pivotColumnId: pivotColumnIds[pivotKeys.length - 1],
1299
+ aggregationColumnId,
1300
+ };
1301
+ }
1302
+ getPivotTotalColumnConfig(colDef, currentPivotLayout) {
1303
+ const defaultHiddenConfig = {
1304
+ visible: false,
1305
+ };
1306
+ const colIdInfo = this.destructurePivotColumnId(colDef, {
1307
+ pivotColIds: this.currentLayout.PivotColumns,
1308
+ aggColIds: this.currentLayout.PivotAggregationColumns.map((col) => col.ColumnId),
1309
+ });
1310
+ if (colIdInfo === '!unknown!') {
1311
+ return defaultHiddenConfig;
1312
+ }
1313
+ const { pivotColumnId, aggregationColumnId } = colIdInfo;
1314
+ const layoutAggCol = currentPivotLayout.PivotAggregationColumns?.find((col) => col.ColumnId === aggregationColumnId);
1315
+ if (!layoutAggCol) {
1316
+ this.warn(`Pivot Totals: could NOT find aggregation(value) column with id ${aggregationColumnId}`);
1317
+ return defaultHiddenConfig;
1318
+ }
1319
+ const layoutPivotTotalColumn = layoutAggCol.TotalColumn;
1320
+ if (!layoutPivotTotalColumn) {
1321
+ return defaultHiddenConfig;
1322
+ }
1323
+ if (Array.isArray(layoutPivotTotalColumn)) {
1324
+ const pivotSpecificConfig = layoutPivotTotalColumn.find((config) => config.PivotColumnId === pivotColumnId);
1325
+ return {
1326
+ visible: pivotSpecificConfig && pivotSpecificConfig.ShowTotal !== false,
1327
+ position: pivotSpecificConfig?.ShowTotal === 'after' ? 'after' : 'before',
1328
+ };
1329
+ }
1330
+ else {
1331
+ return {
1332
+ visible: !!layoutPivotTotalColumn,
1333
+ position: layoutPivotTotalColumn === 'after' ? 'after' : 'before',
1334
+ };
1335
+ }
1336
+ }
1051
1337
  }
1052
1338
  exports.LayoutManager = LayoutManager;
@@ -144,6 +144,9 @@ function normalizePivotLayoutModel(layout) {
144
144
  // make it an own property
145
145
  layout.SuppressAggFuncInHeader = undefined;
146
146
  }
147
+ if (!layout.GrandTotalRow) {
148
+ layout.GrandTotalRow = false;
149
+ }
147
150
  return layout;
148
151
  }
149
152
  exports.normalizePivotLayoutModel = normalizePivotLayoutModel;