@adaptabletools/adaptable 20.0.5-canary.0 → 20.0.6

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.
@@ -62,17 +62,26 @@ export type ColumnAggregationModel = {
62
62
  aggFunc: string | true;
63
63
  weightedColumnId?: string;
64
64
  };
65
- export type AggregationColumnsModelItem = {
65
+ export type AggregationColumnsModel = {
66
66
  ColumnId: string;
67
67
  AggFunc: ColumnAggregationModel;
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
- })[];
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
+ }
76
85
  export interface TableLayoutModel extends BaseLayoutModel {
77
86
  TableColumns: string[];
78
87
  /**
@@ -87,7 +96,6 @@ export interface TableLayoutModel extends BaseLayoutModel {
87
96
  * @defaultValue 'single'
88
97
  */
89
98
  RowGroupDisplayType?: 'single' | 'multi';
90
- PivotAggregationColumns?: never;
91
99
  PivotColumns?: never;
92
100
  PivotGroupedColumns?: never;
93
101
  PivotExpandLevel?: never;
@@ -102,24 +110,13 @@ export interface PivotLayoutModel extends BaseLayoutModel {
102
110
  /**
103
111
  * 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)
104
112
  */
105
- PivotAggregationColumns?: PivotAggregationColumnsModel;
113
+ PivotAggregationColumns?: AggregationColumnsModel;
106
114
  TableAggregationColumns?: never;
107
115
  /**
108
116
  * Columns which are row-grouped when the Layout is applied
109
117
  */
110
118
  PivotGroupedColumns?: string[];
111
119
  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;
124
120
  }
125
121
  export type LayoutModel = TableLayoutModel | PivotLayoutModel;
122
+ export {};
@@ -1,4 +1,4 @@
1
- import { ColDef, ColumnState, GridApi, GridOptions, GridState } from 'ag-grid-enterprise';
1
+ import { 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,24 +69,7 @@ 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;
73
72
  applyPivotExpandLevel(layout: PivotLayoutModel): void;
74
73
  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;
91
74
  }
92
75
  export {};
@@ -3,7 +3,7 @@ import { isPivotLayoutModel } from './isPivotLayoutModel';
3
3
  import { LMEmitter } from './LMEmitter';
4
4
  import { GROUP_COLUMN_ID__MULTI_PREFIX, GROUP_COLUMN_ID__SINGLE, normalizeLayoutModel, normalizePivotLayoutModel, normalizeTableLayoutModel, } from './normalizeLayoutModel';
5
5
  import { isLayoutEqual } from './isLayoutEqual';
6
- import { simplifyLayoutModel, simplifyPivotLayoutModel, simplifyTableLayoutModel, } from './simplifyLayoutModel';
6
+ import { simplifyTableLayoutModel, simplifyPivotLayoutModel, simplifyLayoutModel, } from './simplifyLayoutModel';
7
7
  import { sortColumnIdsByOrder } from './sortColumnIdsByOrder';
8
8
  function flattenColDefs(colDefs) {
9
9
  const res = [];
@@ -117,12 +117,8 @@ export class LayoutManager extends LMEmitter {
117
117
  }).bind(this);
118
118
  }
119
119
  this.setOptions(options);
120
- // this ensures the grand total columns are positioned correctly (before/after) even when changed at runtime
121
- // see https://www.ag-grid.com/react-data-grid/pivoting-column-groups/#changing-data-filters-and-configurations
122
- this.gridApi.setGridOption('enableStrictPivotColumnOrder', true);
123
120
  this.setupEvents();
124
121
  this.indexColumns();
125
- this.setupPivotTotals();
126
122
  globalThis.layoutManager = this;
127
123
  }
128
124
  destroy() {
@@ -256,18 +252,6 @@ export class LayoutManager extends LMEmitter {
256
252
  PivotAggregationColumns: layout.TableAggregationColumns,
257
253
  PivotExpandLevel: prevLayout?.PivotExpandLevel ?? -1,
258
254
  };
259
- const grandTotalRow = this.gridApi.getGridOption('grandTotalRow');
260
- if (grandTotalRow) {
261
- pivotLayout.GrandTotalRow = grandTotalRow;
262
- }
263
- const grandTotalColumn = this.gridApi.getGridOption('pivotRowTotals');
264
- if (grandTotalColumn) {
265
- pivotLayout.GrandTotalColumn = grandTotalColumn;
266
- }
267
- const pivotGroupTotalColumn = this.gridApi.getGridOption('pivotColumnGroupTotals');
268
- if (pivotGroupTotalColumn) {
269
- pivotLayout.PivotGroupTotalColumn = pivotGroupTotalColumn;
270
- }
271
255
  return simplifyPivotLayoutModel(pivotLayout);
272
256
  }
273
257
  getTableLayoutModelFromGrid() {
@@ -288,7 +272,7 @@ export class LayoutManager extends LMEmitter {
288
272
  let ColumnPinning = {};
289
273
  const gridState = this.gridApi.getState();
290
274
  const prevLayout = this.currentLayout;
291
- const prevAggColumns = prevLayout?.TableAggregationColumns ?? prevLayout?.PivotAggregationColumns;
275
+ const prevAggColumns = prevLayout?.TableAggregationColumns;
292
276
  const prevAggColumnsMap = prevAggColumns?.reduce((acc, agg) => {
293
277
  acc[agg.ColumnId] = agg;
294
278
  return acc;
@@ -999,7 +983,6 @@ export class LayoutManager extends LMEmitter {
999
983
  return columnIds;
1000
984
  }
1001
985
  applyPivotLayout(layout, options) {
1002
- this.applyPivotTotals(layout);
1003
986
  const columnState = this.computeColumnStateForPivotLayout(layout);
1004
987
  // by simply calling this.gridApi.applyColumnState(columnState)
1005
988
  // the order of aggregations is not preserved/guaranteed by ag-grid
@@ -1027,50 +1010,6 @@ export class LayoutManager extends LMEmitter {
1027
1010
  this.applyRowGroupValues(layout.RowGroupValues);
1028
1011
  }
1029
1012
  }
1030
- applyPivotTotals(layout) {
1031
- /**
1032
- * GrandTotalRow
1033
- */
1034
- if (layout.GrandTotalRow) {
1035
- const grandTotalRow = layout.GrandTotalRow === true || layout.GrandTotalRow === 'top'
1036
- ? 'top'
1037
- : layout.GrandTotalRow === 'bottom'
1038
- ? 'bottom'
1039
- : null;
1040
- this.gridApi.setGridOption('grandTotalRow', grandTotalRow);
1041
- }
1042
- else {
1043
- this.gridApi.setGridOption('grandTotalRow', null);
1044
- }
1045
- /**
1046
- * GrandTotalColumn
1047
- */
1048
- if (layout.GrandTotalColumn) {
1049
- const grandTotalColumn = layout.GrandTotalColumn === true || layout.GrandTotalColumn === 'before'
1050
- ? 'before'
1051
- : layout.GrandTotalColumn === 'after'
1052
- ? 'after'
1053
- : null;
1054
- this.gridApi.setGridOption('pivotRowTotals', grandTotalColumn);
1055
- }
1056
- else {
1057
- this.gridApi.setGridOption('pivotRowTotals', null);
1058
- }
1059
- /**
1060
- * PivotGroupTotalColumn
1061
- */
1062
- if (layout.PivotGroupTotalColumn) {
1063
- const pivotGroupTotalColumn = layout.PivotGroupTotalColumn === true || layout.PivotGroupTotalColumn === 'before'
1064
- ? 'before'
1065
- : layout.PivotGroupTotalColumn === 'after'
1066
- ? 'after'
1067
- : null;
1068
- this.gridApi.setGridOption('pivotColumnGroupTotals', pivotGroupTotalColumn);
1069
- }
1070
- else {
1071
- this.gridApi.setGridOption('pivotColumnGroupTotals', null);
1072
- }
1073
- }
1074
1013
  applyPivotExpandLevel(layout) {
1075
1014
  const PivotExpandLevel = layout.PivotExpandLevel ?? -1;
1076
1015
  const allDisplayedColumnGroups = this.gridApi.getAllDisplayedColumnGroups();
@@ -1106,229 +1045,4 @@ export class LayoutManager extends LMEmitter {
1106
1045
  }
1107
1046
  return res;
1108
1047
  }
1109
- setupPivotTotals() {
1110
- const _original_processPivotResultColDef = this.gridApi.getGridOption('processPivotResultColDef');
1111
- this.gridApi.setGridOption('processPivotResultColDef', (resulColDef) => {
1112
- _original_processPivotResultColDef?.(resulColDef);
1113
- if (!isPivotLayoutModel(this.currentLayout)) {
1114
- return;
1115
- }
1116
- // column that contain the aggregated total for each value column per row
1117
- this.patchGrandTotalColumn(resulColDef);
1118
- this.patchPivotGroupTotalColumn(resulColDef);
1119
- });
1120
- const _original_processPivotResultColGroupDef = this.gridApi.getGridOption('processPivotResultColGroupDef');
1121
- this.gridApi.setGridOption('processPivotResultColGroupDef', (colGroupDef) => {
1122
- _original_processPivotResultColGroupDef?.(colGroupDef);
1123
- if (!isPivotLayoutModel(this.currentLayout)) {
1124
- return;
1125
- }
1126
- this.patchPivotTotalColumn(colGroupDef);
1127
- });
1128
- }
1129
- isPivotRowTotalColDef(colDef) {
1130
- return colDef.colId?.startsWith('PivotRowTotal_');
1131
- }
1132
- patchGrandTotalColumn(resultColDef) {
1133
- if (!isPivotLayoutModel(this.currentLayout) || !this.currentLayout.GrandTotalColumn) {
1134
- return;
1135
- }
1136
- if (this.isPivotRowTotalColDef(resultColDef)) {
1137
- resultColDef.headerName = `Grand Total ${resultColDef.headerName}`;
1138
- }
1139
- }
1140
- isPivotGroupTotalColumn(colDef) {
1141
- // pivot group total are spanning cross all aggregations
1142
- // therefore the last part of the colId is empty (hence the "dangling" underscore)
1143
- return colDef.colId?.startsWith('pivot_') && colDef.colId?.endsWith('_');
1144
- }
1145
- patchPivotGroupTotalColumn(resultColDef) {
1146
- if (!isPivotLayoutModel(this.currentLayout) || !this.currentLayout.PivotGroupTotalColumn) {
1147
- return;
1148
- }
1149
- if (this.isPivotGroupTotalColumn(resultColDef)) {
1150
- // resultColDef
1151
- const colInfo = this.destructurePivotColumnId(resultColDef, {
1152
- pivotColIds: this.currentLayout.PivotColumns,
1153
- aggColIds: this.currentLayout.PivotAggregationColumns.map((col) => col.ColumnId),
1154
- });
1155
- if (colInfo !== '!unknown!') {
1156
- const currentPivotKey = colInfo.pivotKeys[colInfo.pivotKeys.length - 1];
1157
- resultColDef.headerName = `${currentPivotKey} Total`;
1158
- }
1159
- }
1160
- }
1161
- patchPivotTotalColumn(colGroupDef) {
1162
- const hasPivotTotalCols = (pivotLayout) => {
1163
- return pivotLayout.PivotAggregationColumns?.some((aggCol) => !!aggCol.TotalColumn);
1164
- };
1165
- const isPivotTotalColDef = (colDef) => {
1166
- return !!colDef.pivotTotalColumnIds?.length;
1167
- };
1168
- if (!isPivotLayoutModel(this.currentLayout) || !hasPivotTotalCols(this.currentLayout)) {
1169
- return;
1170
- }
1171
- const pivotRowTotalColDefsBefore = [];
1172
- const pivotRowTotalColDefsAfter = [];
1173
- const pivotTotalColDefsBefore = [];
1174
- const pivotTotalColDefsAfter = [];
1175
- const normalColDefs = [];
1176
- colGroupDef.children.forEach((colDef) => {
1177
- if (this.isPivotRowTotalColDef(colDef)) {
1178
- if (this.gridApi.getGridOption('pivotRowTotals') === 'after') {
1179
- pivotRowTotalColDefsAfter.push(colDef);
1180
- }
1181
- else {
1182
- pivotRowTotalColDefsBefore.push(colDef);
1183
- }
1184
- return;
1185
- }
1186
- if (isPivotTotalColDef(colDef)) {
1187
- if (!colDef.colId.startsWith('pivot_')) {
1188
- this.warn(`Pivot total column ${colDef.colId} is not prefixed with 'pivot_', skipping...`);
1189
- return;
1190
- }
1191
- // we do this for all total cols, but we will hide the ones that are not visible
1192
- colDef.columnGroupShow = undefined;
1193
- colDef.headerName = `Total ${colDef.headerName}`;
1194
- const totalColConfig = this.getPivotTotalColumnConfig(colDef, this.currentLayout);
1195
- if (!totalColConfig.visible) {
1196
- colDef.hide = true;
1197
- }
1198
- else {
1199
- if (totalColConfig.position === 'after') {
1200
- pivotTotalColDefsAfter.push(colDef);
1201
- }
1202
- else {
1203
- pivotTotalColDefsBefore.push(colDef);
1204
- }
1205
- }
1206
- }
1207
- else {
1208
- normalColDefs.push(colDef);
1209
- }
1210
- });
1211
- colGroupDef.children = [
1212
- ...pivotRowTotalColDefsBefore,
1213
- ...pivotTotalColDefsBefore,
1214
- ...normalColDefs,
1215
- ...pivotTotalColDefsAfter,
1216
- ...pivotRowTotalColDefsAfter,
1217
- ];
1218
- }
1219
- // supports only pivotTotalColumns (aggregation total) and pivotGroupTotal
1220
- // AG Grid builds the ID as: `pivot_${pivotCols.join('-')}_${pivotKeys.join('-')}_${measureColumnId}`
1221
- // see https://github.com/ag-grid/ag-grid/blob/e0cfe533b55b75cdc148cdfb1a4e977731dc0712/packages/ag-grid-enterprise/src/pivot/pivotColDefService.ts#L454C16-L454C88
1222
- destructurePivotColumnId(colDef, currentModel) {
1223
- const { colId } = colDef;
1224
- // Basic validation
1225
- if (!colId?.startsWith('pivot_')) {
1226
- this.warn(`Column id must start with 'pivot_': ${colId}`);
1227
- return '!unknown!';
1228
- }
1229
- const hasSpecialChars = (arr) => arr.some((str) => str.includes('-') || str.includes('_'));
1230
- // AG Grid uses _ and - as delimiters
1231
- // if we have these special characters in the column IDs, we need to parse them differently
1232
- const colIdsOrKeysContainSpecialChars = hasSpecialChars(currentModel.pivotColIds) ||
1233
- hasSpecialChars(currentModel.aggColIds) ||
1234
- hasSpecialChars(colDef.pivotKeys || []);
1235
- // Fast path - no special characters
1236
- if (!colIdsOrKeysContainSpecialChars) {
1237
- // Split by underscore to get 4 parts
1238
- const parts = colId.split('_');
1239
- if (parts.length !== 4) {
1240
- this.warn(`Unsupported format of pivot total column id: ${colId}`);
1241
- return '!unknown!';
1242
- }
1243
- const [_pivotPrefix, pivotColsTxt, pivotKeysTxt, aggregationColumnId] = parts;
1244
- const pivotColumnIds = pivotColsTxt.split('-');
1245
- const pivotKeys = pivotKeysTxt.split('-');
1246
- const pivotColumnId = pivotColumnIds[pivotKeys.length - 1];
1247
- return {
1248
- pivotColumnIds,
1249
- pivotKeys,
1250
- pivotColumnId,
1251
- aggregationColumnId: aggregationColumnId !== '' ? aggregationColumnId : undefined,
1252
- };
1253
- }
1254
- // the complex path, where we have to handle the special characters
1255
- // Remove 'pivot_' prefix
1256
- const withoutPrefix = colId.slice(6);
1257
- // Check if it's a pivot group total
1258
- const isPivotGroupTotal = withoutPrefix.endsWith('_');
1259
- // Get pivot keys from colDef (more reliable than string parsing)
1260
- const pivotKeys = colDef.pivotKeys || [];
1261
- if (isPivotGroupTotal) {
1262
- // Remove trailing underscore for pivot group totals
1263
- const content = withoutPrefix.slice(0, -1);
1264
- // The remaining content should be the pivot columns
1265
- const pivotColumnIds = currentModel.pivotColIds.filter((id) => content.includes(id));
1266
- if (!pivotColumnIds.length) {
1267
- this.warn(`Could not identify pivot columns in: ${content}`);
1268
- return '!unknown!';
1269
- }
1270
- return {
1271
- pivotColumnIds,
1272
- pivotKeys,
1273
- pivotColumnId: pivotColumnIds[pivotKeys.length],
1274
- };
1275
- }
1276
- // For regular pivot columns, work backwards to find aggregation column
1277
- const parts = withoutPrefix.split('_');
1278
- const lastPart = parts[parts.length - 1];
1279
- // Find the longest matching aggregation column id from the end
1280
- const aggregationColumnId = currentModel.aggColIds.find((aggId) => lastPart.endsWith(aggId));
1281
- if (!aggregationColumnId) {
1282
- this.warn(`Could not identify aggregation column in: ${lastPart}`);
1283
- return '!unknown!';
1284
- }
1285
- // Remove aggregation part and get pivot columns
1286
- const withoutAgg = withoutPrefix.slice(0, -(aggregationColumnId.length + 1));
1287
- const pivotColumnIds = currentModel.pivotColIds.filter((id) => withoutAgg.includes(id));
1288
- if (!pivotColumnIds.length) {
1289
- this.warn(`Could not identify pivot columns in: ${withoutAgg}`);
1290
- return '!unknown!';
1291
- }
1292
- return {
1293
- pivotColumnIds,
1294
- pivotKeys,
1295
- pivotColumnId: pivotColumnIds[pivotKeys.length - 1],
1296
- aggregationColumnId,
1297
- };
1298
- }
1299
- getPivotTotalColumnConfig(colDef, currentPivotLayout) {
1300
- const defaultHiddenConfig = {
1301
- visible: false,
1302
- };
1303
- const colIdInfo = this.destructurePivotColumnId(colDef, {
1304
- pivotColIds: this.currentLayout.PivotColumns,
1305
- aggColIds: this.currentLayout.PivotAggregationColumns.map((col) => col.ColumnId),
1306
- });
1307
- if (colIdInfo === '!unknown!') {
1308
- return defaultHiddenConfig;
1309
- }
1310
- const { pivotColumnId, aggregationColumnId } = colIdInfo;
1311
- const layoutAggCol = currentPivotLayout.PivotAggregationColumns?.find((col) => col.ColumnId === aggregationColumnId);
1312
- if (!layoutAggCol) {
1313
- this.warn(`Pivot Totals: could NOT find aggregation(value) column with id ${aggregationColumnId}`);
1314
- return defaultHiddenConfig;
1315
- }
1316
- const layoutPivotTotalColumn = layoutAggCol.TotalColumn;
1317
- if (!layoutPivotTotalColumn) {
1318
- return defaultHiddenConfig;
1319
- }
1320
- if (Array.isArray(layoutPivotTotalColumn)) {
1321
- const pivotSpecificConfig = layoutPivotTotalColumn.find((config) => config.PivotColumnId === pivotColumnId);
1322
- return {
1323
- visible: pivotSpecificConfig && pivotSpecificConfig.ShowTotal !== false,
1324
- position: pivotSpecificConfig?.ShowTotal === 'after' ? 'after' : 'before',
1325
- };
1326
- }
1327
- else {
1328
- return {
1329
- visible: !!layoutPivotTotalColumn,
1330
- position: layoutPivotTotalColumn === 'after' ? 'after' : 'before',
1331
- };
1332
- }
1333
- }
1334
1048
  }
@@ -139,9 +139,6 @@ export function normalizePivotLayoutModel(layout) {
139
139
  // make it an own property
140
140
  layout.SuppressAggFuncInHeader = undefined;
141
141
  }
142
- if (!layout.GrandTotalRow) {
143
- layout.GrandTotalRow = false;
144
- }
145
142
  return layout;
146
143
  }
147
144
  export function normalizeLayoutModel(layout, options) {