@adaptabletools/adaptable 20.0.4-canary.3 → 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",
3
- "version": "20.0.4-canary.3",
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",
@@ -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);
@@ -63,6 +63,13 @@ export function generateAutoRowGroupColumnForColumn(column) {
63
63
  };
64
64
  }
65
65
  export function getFriendlyNameForPivotResultColumn(columnId) {
66
+ if (isPivotGrandTotalColumn(columnId)) {
67
+ return `[Grand Total] ${columnId
68
+ .split('_')
69
+ .slice(2)
70
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
71
+ .join(' ')}`;
72
+ }
66
73
  return `[Pivot] ${columnId
67
74
  .split('_')
68
75
  .slice(1)
@@ -73,6 +80,9 @@ export function isPivotResultColumn(columnId) {
73
80
  // put this here as there might be other indicators we are not aware of?
74
81
  return columnId?.startsWith(GeneralConstants.AG_GRID_PIVOT_COLUMN);
75
82
  }
83
+ export function isPivotGrandTotalColumn(columnId) {
84
+ return columnId?.startsWith(GeneralConstants.AG_GRID_PIVOT_GRAND_TOTAL_COLUMN);
85
+ }
76
86
  export class ColumnApiImpl extends ApiBase {
77
87
  constructor(_adaptable) {
78
88
  super(_adaptable);
@@ -136,7 +146,7 @@ export class ColumnApiImpl extends ApiBase {
136
146
  return isAutoRowGroupColumn(columnId);
137
147
  }
138
148
  isPivotResultColumn(columnId) {
139
- return isPivotResultColumn(columnId);
149
+ return isPivotResultColumn(columnId) || isPivotGrandTotalColumn(columnId);
140
150
  }
141
151
  isAutoRowGroupColumnForSingle(columnId) {
142
152
  return columnId === GROUP_COLUMN_ID__SINGLE;
@@ -43,5 +43,5 @@ export declare class ColumnFilterInternalApi extends ApiBase {
43
43
  areColumnFiltersDifferent(oldFilters: ColumnFilter[], newFilters: ColumnFilter[]): boolean;
44
44
  getPredicateDefShortcuts(predicateDef: AdaptablePredicateDef): string[];
45
45
  showQuickFilterDropdown(columnId: string): boolean;
46
- openColumnFilterPopup(columnId: string): void;
46
+ openColumnFilterPopup(columnId: string, popupProps?: any): void;
47
47
  }
@@ -187,7 +187,7 @@ export class ColumnFilterInternalApi extends ApiBase {
187
187
  }
188
188
  return true;
189
189
  }
190
- openColumnFilterPopup(columnId) {
190
+ openColumnFilterPopup(columnId, popupProps) {
191
191
  this.getAdaptableInternalApi().showPopupWindow({
192
192
  id: COLUMN_FILTER_WINDOW,
193
193
  title: ModuleConstants.ColumnFilterFriendlyName,
@@ -199,6 +199,7 @@ export class ColumnFilterInternalApi extends ApiBase {
199
199
  width: 380,
200
200
  height: 450,
201
201
  },
202
+ ...popupProps,
202
203
  },
203
204
  });
204
205
  }
@@ -60,6 +60,12 @@ export class CalculatedColumnModule extends AdaptableModuleBase {
60
60
  return (this.api.namedQueryApi.internalApi.getReferencedNamedQueryNames(this.api.expressionApi.getAdaptableQueryExpression(calculatedColumn.Query)) ?? []);
61
61
  }
62
62
  createColumnMenuItems(column) {
63
+ if (!column) {
64
+ return;
65
+ }
66
+ if (!this.isModuleAvailable()) {
67
+ return;
68
+ }
63
69
  if (this.isModuleEditable() && column.isCalculatedColumn) {
64
70
  const popupParam = {
65
71
  column: column,
@@ -72,6 +78,9 @@ export class CalculatedColumnModule extends AdaptableModuleBase {
72
78
  }
73
79
  }
74
80
  createContextMenuItems(menuContext) {
81
+ if (!menuContext.adaptableColumn) {
82
+ return;
83
+ }
75
84
  if (!this.isModuleAvailable()) {
76
85
  return;
77
86
  }
@@ -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";
@@ -23,6 +23,7 @@ export const GROUP_PATH_SEPARATOR = '/';
23
23
  export const AG_GRID_GROUPED_COLUMN = 'ag-Grid-AutoColumn';
24
24
  export const AG_GRID_SELECTION_COLUMN = 'ag-Grid-SelectionColumn';
25
25
  export const AG_GRID_PIVOT_COLUMN = 'pivot_';
26
+ export const AG_GRID_PIVOT_GRAND_TOTAL_COLUMN = 'PivotRowTotal_pivot_';
26
27
  export const AG_GRID_CHART_WINDOW = 'AG Grid Window';
27
28
  export const ADAPTABLE_FDC3_ACTION_COLUMN_FRIENDLY_NAME = '(FDC3ActionColumn)';
28
29
  // FIXME AFL - load this from DateInputOptions
@@ -34,5 +34,5 @@ export const AdaptableFloatingFilter = (props) => {
34
34
  ]);
35
35
  props.onChange?.();
36
36
  }
37
- }, onClear: onClear, columnId: props.Column.columnId, predicate: qlPredicate, predicateDefs: qlPredicateDefs, disabled: columnFilter?.IsSuspended, onPredicateChange: onPredicateChange }));
37
+ }, onClear: onClear, columnId: props.Column.columnId, predicate: qlPredicate, predicateDefs: qlPredicateDefs, disabled: columnFilter?.IsSuspended, onPredicateChange: onPredicateChange, onChange: props.onChange }));
38
38
  };
@@ -12,6 +12,7 @@ export const ColumnFilterWindow = (props) => {
12
12
  React.useEffect(() => {
13
13
  setColumnId(initialColumnId);
14
14
  }, [props.popupProps.value]);
15
+ const onChange = props.popupProps.onChange;
15
16
  return (React.createElement(Flex, { flex: 1, minHeight: 0, height: "100%", flexDirection: "column", p: 2, className: "ab-ColumnFilterWindow" },
16
17
  React.createElement(Box, { mb: 2 },
17
18
  React.createElement(FormLayout, null,
@@ -28,5 +29,5 @@ export const ColumnFilterWindow = (props) => {
28
29
  }
29
30
  return label;
30
31
  }, onChange: (column) => setColumnId(column), filterColumn: (column) => column.queryable, isMulti: false, value: columnId })))),
31
- React.createElement(AdaptableColumnFilter, { columnId: columnId })));
32
+ React.createElement(AdaptableColumnFilter, { columnId: columnId, onChange: onChange })));
32
33
  };
@@ -8,5 +8,6 @@ export interface FloatingFilterProps {
8
8
  onPredicateChange: (predicate: QlPredicate) => void;
9
9
  onKeydown?: (event: React.KeyboardEventHandler<HTMLDivElement>) => void;
10
10
  onClear?: () => void;
11
+ onChange?: () => void;
11
12
  }
12
13
  export declare const FloatingFilter: React.FunctionComponent<FloatingFilterProps>;
@@ -77,7 +77,9 @@ export const FloatingFilter = (props) => {
77
77
  });
78
78
  } }))),
79
79
  isInlineEditable && (React.createElement(SimpleButton, { px: 0, onClick: () => {
80
- adaptable.api.filterApi.columnFilterApi.internalApi.openColumnFilterPopup(props.columnId);
80
+ adaptable.api.filterApi.columnFilterApi.internalApi.openColumnFilterPopup(props.columnId, {
81
+ onChange: props.onChange,
82
+ });
81
83
  }, "data-name": "expand-filter", icon: "expand", variant: "text" })),
82
84
  (isMultiple ||
83
85
  !isPredicateEmpty(props.predicate.args[0], singleFilterPredicateDef)) && (React.createElement(SimpleButton, { "data-name": "clear-filter", p: 0, variant: "text", onClick: handleClear, icon: "close" }))));
@@ -24,7 +24,7 @@ export const ColumnValuesSelect = (props) => {
24
24
  }
25
25
  return true;
26
26
  });
27
- const component = (React.createElement(Select, { isMulti: true, showHeaderSelectionCheckbox: true, searchable: true, closeMenuOnSelect: false, size: "small", menuStyle: {
27
+ const component = (React.createElement(Select, { isMulti: true, showHeaderSelectionCheckbox: true, searchable: true, closeMenuOnSelect: false, menuStyle: {
28
28
  minWidth: `var(--ab-cmp-select-column-menu-${column.columnId}__min-width, var(--ab-cmp-select-column-menu__min-width, 260px))`,
29
29
  }, ...props.selectProps, options: options, value: value, isLoading: props.isLoading, onChange: props.onChange }));
30
30
  return (React.createElement("div", { className: join(baseClassName, props.isLoading && `${baseClassName}--loading`, !value.length && `${baseClassName}--empty`), onKeyDownCapture: (e) => {
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: 1744658441173 || Date.now(),
4
- VERSION: "20.0.4-canary.3" || '--current-version--',
3
+ PUBLISH_TIMESTAMP: 1744819271502 || Date.now(),
4
+ VERSION: "20.0.5-canary.0" || '--current-version--',
5
5
  };
@@ -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 = {
@@ -78,7 +78,15 @@ export declare class LayoutManager<DATA_TYPE = any> extends LMEmitter {
78
78
  private isPivotGroupTotalColumn;
79
79
  private patchPivotGroupTotalColumn;
80
80
  private patchPivotTotalColumn;
81
- private destructurePivotColumnId;
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
+ };
82
90
  private getPivotTotalColumnConfig;
83
91
  }
84
92
  export {};
@@ -1113,6 +1113,7 @@ export class LayoutManager extends LMEmitter {
1113
1113
  if (!isPivotLayoutModel(this.currentLayout)) {
1114
1114
  return;
1115
1115
  }
1116
+ // column that contain the aggregated total for each value column per row
1116
1117
  this.patchGrandTotalColumn(resulColDef);
1117
1118
  this.patchPivotGroupTotalColumn(resulColDef);
1118
1119
  });
@@ -1147,7 +1148,10 @@ export class LayoutManager extends LMEmitter {
1147
1148
  }
1148
1149
  if (this.isPivotGroupTotalColumn(resultColDef)) {
1149
1150
  // resultColDef
1150
- const colInfo = this.destructurePivotColumnId(resultColDef.colId);
1151
+ const colInfo = this.destructurePivotColumnId(resultColDef, {
1152
+ pivotColIds: this.currentLayout.PivotColumns,
1153
+ aggColIds: this.currentLayout.PivotAggregationColumns.map((col) => col.ColumnId),
1154
+ });
1151
1155
  if (colInfo !== '!unknown!') {
1152
1156
  const currentPivotKey = colInfo.pivotKeys[colInfo.pivotKeys.length - 1];
1153
1157
  resultColDef.headerName = `${currentPivotKey} Total`;
@@ -1212,26 +1216,83 @@ export class LayoutManager extends LMEmitter {
1212
1216
  ...pivotRowTotalColDefsAfter,
1213
1217
  ];
1214
1218
  }
1215
- destructurePivotColumnId(colId = '') {
1216
- // Split by underscore to get 4 parts
1217
- const parts = colId.split('_');
1218
- if (parts.length !== 4) {
1219
- this.warn(`Unsupported format of pivot total column id: ${colId}`);
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}`);
1220
1290
  return '!unknown!';
1221
1291
  }
1222
- // e.g.
1223
- // pivot_country-sport-year_United States-Basketball_gold
1224
- // pivotColumnIds: ['country', 'sport', 'year']
1225
- // pivotKeys: ['United States', 'Basketball']
1226
- // aggregationColumnId: 'gold'
1227
- const [_pivotPrefix, pivotColsTxt, pivotKeysTxt, aggregationColumnId] = parts;
1228
- const pivotColumnIds = pivotColsTxt.split('-');
1229
- const pivotKeys = pivotKeysTxt.split('-');
1230
- const pivotColumnId = pivotColumnIds[pivotKeys.length - 1];
1231
1292
  return {
1232
1293
  pivotColumnIds,
1233
1294
  pivotKeys,
1234
- pivotColumnId,
1295
+ pivotColumnId: pivotColumnIds[pivotKeys.length - 1],
1235
1296
  aggregationColumnId,
1236
1297
  };
1237
1298
  }
@@ -1239,7 +1300,10 @@ export class LayoutManager extends LMEmitter {
1239
1300
  const defaultHiddenConfig = {
1240
1301
  visible: false,
1241
1302
  };
1242
- const colIdInfo = this.destructurePivotColumnId(colDef.colId);
1303
+ const colIdInfo = this.destructurePivotColumnId(colDef, {
1304
+ pivotColIds: this.currentLayout.PivotColumns,
1305
+ aggColIds: this.currentLayout.PivotAggregationColumns.map((col) => col.ColumnId),
1306
+ });
1243
1307
  if (colIdInfo === '!unknown!') {
1244
1308
  return defaultHiddenConfig;
1245
1309
  }
@@ -15,7 +15,7 @@ export function simplifyTableLayoutModel(layout) {
15
15
  delete layout.RowGroupedColumns;
16
16
  }
17
17
  if (!layout.RowGroupedColumns && layout.RowGroupValues) {
18
- delete layout.RowGroupValues;
18
+ // delete layout.RowGroupValues;
19
19
  }
20
20
  if (layout.SuppressAggFuncInHeader === undefined) {
21
21
  delete layout.SuppressAggFuncInHeader;