@adaptabletools/adaptable-cjs 22.0.0 → 22.0.1-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": "22.0.0",
3
+ "version": "22.0.1-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",
@@ -143,6 +143,7 @@ export interface IAdaptable {
143
143
  refreshCells(rowNode: IRowNode, columns: (string | any)[], forceUpdate: boolean, suppressFlash?: boolean): void;
144
144
  refreshAllCells(forceUpdate?: boolean): void;
145
145
  refreshColumns(columns: (string | Column)[], forceUpdate: boolean, suppressFlash?: boolean): void;
146
+ refreshGridHeader(): void;
146
147
  refreshSelectedCellsState(): SelectedCellInfo | undefined;
147
148
  refreshSelectedRowsState(): SelectedRowInfo | undefined;
148
149
  selectColumn(columnId: string, config?: {
@@ -537,6 +537,10 @@ export interface GridApi {
537
537
  * @param rowNodes AG Grid rows
538
538
  */
539
539
  refreshRowNodes(rowNodes?: IRowNode[]): void;
540
+ /**
541
+ * Forces a re-render of the Grid Header
542
+ */
543
+ refreshGridHeader(): void;
540
544
  /**
541
545
  * Forces a re-render of all Group Rows (including aggregations)
542
546
  */
@@ -138,6 +138,7 @@ export declare class GridApiImpl extends ApiBase implements GridApi {
138
138
  refreshRowNode(rowNode: IRowNode): void;
139
139
  refreshRowNodes(rowNodes?: IRowNode[]): void;
140
140
  refreshGroupRowNodes(): void;
141
+ refreshGridHeader(): void;
141
142
  isCellEditable(gridCell: GridCell): boolean;
142
143
  isCellEdited(gridCell: GridCell): boolean;
143
144
  isEveryCellEditable(gridCells: GridCell[]): boolean;
@@ -551,6 +551,9 @@ class GridApiImpl extends ApiBase_1.ApiBase {
551
551
  this.getAgGridApi().refreshClientSideRowModel('group');
552
552
  this._adaptable.updateRowGroupsAndColumnGroupsExpandedState();
553
553
  }
554
+ refreshGridHeader() {
555
+ this._adaptable.refreshGridHeader();
556
+ }
554
557
  isCellEditable(gridCell) {
555
558
  // If not Grid Cell or Column then return false - GridCell.column may be undefined for cells from synthetic columns created by AG Grid (ex. autoGroup columns)
556
559
  if (!gridCell || !gridCell.column || !gridCell.rowNode) {
@@ -8,4 +8,5 @@ export declare class RowFormApiImpl extends ApiBase implements RowFormApi {
8
8
  displayEditRowForm(primaryKey: any): void;
9
9
  displayCreateRowForm(): void;
10
10
  displayCloneRowForm(primaryKey?: any): void;
11
+ displayDeleteRowForm(primaryKey?: any): void;
11
12
  }
@@ -47,5 +47,18 @@ class RowFormApiImpl extends ApiBase_1.ApiBase {
47
47
  },
48
48
  }));
49
49
  }
50
+ displayDeleteRowForm(primaryKey) {
51
+ const rowNode = this.getGridApi().getRowNodeForPrimaryKey(primaryKey);
52
+ if (!rowNode) {
53
+ this.logWarn(`Can NOT delete row: rowNode not found for primaryKey ${primaryKey}`);
54
+ }
55
+ const eventInfo = {
56
+ type: 'rowDeleted',
57
+ rowNode: rowNode,
58
+ ...this.getAdaptableInternalApi().buildBaseContext(),
59
+ };
60
+ this.getEventApi().internalApi.fireRowFormSubmittedEvent(eventInfo);
61
+ this.getRowFormOptions().onRowFormSubmit?.(eventInfo);
62
+ }
50
63
  }
51
64
  exports.RowFormApiImpl = RowFormApiImpl;
@@ -112,27 +112,10 @@ class ActionColumnInternalApi extends ApiBase_1.ApiBase {
112
112
  break;
113
113
  case 'delete':
114
114
  button.onClick = (button, context) => {
115
- const eventInfo = {
116
- type: 'rowDeleted',
117
- rowNode: context.rowNode,
118
- ...this.getAdaptableInternalApi().buildBaseContext(),
119
- };
120
- this.getEventApi().internalApi.fireRowFormSubmittedEvent(eventInfo);
121
- this.getRowFormOptions().onRowFormSubmit?.(eventInfo);
115
+ this.getRowFormApi().displayDeleteRowForm(context.primaryKeyValue);
122
116
  };
123
117
  button.tooltip = button.tooltip ? button.tooltip : 'Delete Row';
124
- button.icon = button.icon ?? {
125
- name: 'delete',
126
- };
127
- break;
128
- case 'edit':
129
- button.onClick = (button, context) => {
130
- this.getRowFormApi().displayEditRowForm(context.primaryKeyValue);
131
- };
132
- button.tooltip = button.tooltip ? button.tooltip : 'Edit Row';
133
- button.icon = button.icon ?? {
134
- name: 'edit',
135
- };
118
+ button.icon = button.icon ?? { name: 'delete' };
136
119
  break;
137
120
  }
138
121
  }
@@ -45,7 +45,7 @@ class ExportInternalApi extends ApiBase_1.ApiBase {
45
45
  }
46
46
  break;
47
47
  case 'VisibleColumns':
48
- // hope that visibile column property is updated whenever the layout changes... (need to check!)
48
+ // hope that visible column property is updated whenever the layout changes... (need to check!)
49
49
  if (!cellDataChangedInfo.column.visible) {
50
50
  return false;
51
51
  }
@@ -16,4 +16,9 @@ export interface RowFormApi {
16
16
  * @param primaryKey - Primary Key of the duplicated row
17
17
  */
18
18
  displayCloneRowForm(primaryKey?: any): void;
19
+ /**
20
+ * Deletes row from grid (with event fired) - note: no visible Row Form is displayed
21
+ * @param primaryKey - Primary Key of the deleted row
22
+ */
23
+ displayDeleteRowForm(primaryKey?: any): void;
19
24
  }
@@ -18,6 +18,7 @@ export type WeightedAverageConfig = {
18
18
  export declare class CellSummaryModule extends AdaptableModuleBase implements ICellSummaryModule {
19
19
  cachedCellSummary: WeakMap<SelectedCellInfo<any>, CellSummmaryInfo>;
20
20
  constructor(api: AdaptableApi);
21
+ isModuleAvailable(): boolean;
21
22
  getViewAccessLevel(): AccessLevel;
22
23
  createColumnMenuItems(column: AdaptableColumn): import("../Utilities/MenuItem").MenuItemShowPopup<"separator" | "calculated-column-edit" | "cell-summary-show" | "chart-show" | "column-group" | "column-filter-group" | "column-filter-bar-hide" | "column-filter-bar-show" | "column-filter-clear" | "column-filter-suspend" | "column-filter-unsuspend" | "column-info-show" | "custom-sort-add" | "custom-sort-edit" | "dashboard-group" | "dashboard-collapse" | "dashboard-configure" | "dashboard-dock" | "dashboard-expand" | "dashboard-float" | "dashboard-hide" | "dashboard-show" | "data-import" | "flashing-cell-add" | "flashing-cell-delete" | "format-column-add" | "format-column-edit" | "free-text-column-edit" | "grid-group" | "grid-info-show" | "layout-column-caption-change" | "layout-column-hide" | "layout-edit" | "layout-column-select" | "layout-column-select-preserve" | "layout-column-select-reset" | "layout-grid-select" | "plus-minus-add" | "settings-panel-open" | "styling-group" | "styled-column-badge-add" | "styled-column-badge-edit" | "styled-column-gradient-add" | "styled-column-gradient-edit" | "styled-column-percent-bar-add" | "styled-column-percent-bar-edit" | "styled-column-sparkline-add" | "styled-column-sparkline-edit" | "system-status-show" | "_navbar">[];
23
24
  createContextMenuItems(menuContext: ContextMenuContext): import("../Utilities/MenuItem").MenuItemShowPopup<"calculated-column-edit" | "cell-summary-show" | "column-group" | "column-filter-group" | "column-filter-clear" | "column-filter-suspend" | "column-filter-unsuspend" | "column-info-show" | "dashboard-group" | "dashboard-collapse" | "dashboard-configure" | "dashboard-dock" | "dashboard-expand" | "dashboard-float" | "dashboard-hide" | "dashboard-show" | "data-import" | "grid-group" | "grid-info-show" | "layout-edit" | "settings-panel-open" | "system-status-show" | "menu-group" | "alert-clear" | "bulk-update-apply" | "column-filter-on-cell-value" | "comment-add" | "comment-remove" | "edit-group" | "export-group" | "export-all-data" | "export-all-data-excel-download" | "export-all-data-visualexcel-download" | "export-all-data-csv" | "export-all-data-csv-download" | "export-all-data-csv-clipboard" | "export-all-data-json" | "export-all-data-json-download" | "export-all-data-json-clipboard" | "export-current-layout" | "export-current-layout-excel-download" | "export-current-layout-visualexcel-download" | "export-current-layout-csv" | "export-current-layout-csv-download" | "export-current-layout-csv-clipboard" | "export-current-layout-json" | "export-current-layout-json-download" | "export-current-layout-json-clipboard" | "export-selected-data" | "export-selected-data-excel-download" | "export-selected-data-visualexcel-download" | "export-selected-data-csv" | "export-selected-data-csv-download" | "export-selected-data-csv-clipboard" | "export-selected-data-json" | "export-selected-data-json-download" | "export-selected-data-json-clipboard" | "fdc3-broadcast" | "fdc3-raise-intent" | "flashing-cell-clear" | "flashing-row-clear" | "layout-aggregated-view" | "layout-auto-size" | "layout-clear-selection" | "layout-select-all" | "note-add" | "note-remove" | "smart-edit-apply">[];
@@ -16,6 +16,9 @@ class CellSummaryModule extends AdaptableModuleBase_1.AdaptableModuleBase {
16
16
  constructor(api) {
17
17
  super(ModuleConstants.CellSummaryModuleId, ModuleConstants.CellSummaryFriendlyName, 'cells', 'CellSummaryPopup', 'See summary information on a group of numeric cells using multiple summary operations', api);
18
18
  }
19
+ isModuleAvailable() {
20
+ return super.isModuleAvailable() && this.api.gridApi.isGridRangeSelectable();
21
+ }
19
22
  getViewAccessLevel() {
20
23
  return 'Full';
21
24
  }
@@ -147,24 +147,26 @@ class LayoutModule extends AdaptableModuleBase_1.AdaptableModuleBase {
147
147
  this.api.columnApi.hideColumn(column.columnId);
148
148
  }));
149
149
  }
150
- const hasExistingSelection = this.api.gridApi.getSelectedCellInfo()?.gridCells?.length;
151
- if (hasExistingSelection) {
152
- returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-column-select-preserve', 'Select Column (Preserve Selection)', 'select-fwd', () => {
153
- this.api.columnApi.addColumnToSelection(column.columnId);
154
- }));
155
- returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-column-select-reset', 'Select Column (Reset Selection)', 'tab-unselected', () => {
156
- this.api.columnApi.selectColumn(column.columnId);
157
- }));
158
- }
159
- else {
160
- returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-column-select', 'Select Column', 'tab-unselected', () => {
161
- this.api.columnApi.selectColumn(column.columnId);
150
+ if (this.api.gridApi.isGridRangeSelectable()) {
151
+ const hasExistingSelection = this.api.gridApi.getSelectedCellInfo()?.gridCells?.length;
152
+ if (hasExistingSelection) {
153
+ returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-column-select-preserve', 'Select Column (Preserve Selection)', 'select-fwd', () => {
154
+ this.api.columnApi.addColumnToSelection(column.columnId);
155
+ }));
156
+ returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-column-select-reset', 'Select Column (Reset Selection)', 'tab-unselected', () => {
157
+ this.api.columnApi.selectColumn(column.columnId);
158
+ }));
159
+ }
160
+ else {
161
+ returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-column-select', 'Select Column', 'tab-unselected', () => {
162
+ this.api.columnApi.selectColumn(column.columnId);
163
+ }));
164
+ }
165
+ returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-grid-select', 'Select Grid', 'select-all', () => {
166
+ this.api.gridApi.selectAll();
162
167
  }));
163
168
  }
164
169
  }
165
- returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-grid-select', 'Select Grid', 'select-all', () => {
166
- this.api.gridApi.selectAll();
167
- }));
168
170
  return returnColumnMenuItems;
169
171
  }
170
172
  createContextMenuItems(menuContext) {
@@ -183,9 +185,11 @@ class LayoutModule extends AdaptableModuleBase_1.AdaptableModuleBase {
183
185
  this.api.gridApi.deselectAll();
184
186
  }));
185
187
  }
186
- returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-select-all', 'Select Grid', 'select-all', () => {
187
- this.api.gridApi.selectAll();
188
- }));
188
+ if (this.api.gridApi.isGridRangeSelectable()) {
189
+ returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-select-all', 'Select Grid', 'select-all', () => {
190
+ this.api.gridApi.selectAll();
191
+ }));
192
+ }
189
193
  returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-auto-size', 'Auto Size', 'arrow-expand', () => {
190
194
  this.api.columnApi.autosizeAllColumns();
191
195
  }));
@@ -12,6 +12,7 @@ export declare class PlusMinusModule extends AdaptableModuleBase implements IPlu
12
12
  private shouldHandleKeyDown;
13
13
  private adaptable;
14
14
  constructor(api: AdaptableApi);
15
+ isModuleAvailable(): boolean;
15
16
  getModuleAdaptableObjects(config?: LayoutExtendedConfig): AdaptableObject[];
16
17
  getExplicitlyReferencedColumnIds(plusMinusNudge: PlusMinusNudge): string[];
17
18
  getReferencedNamedQueryNames(plusMinusNudge: PlusMinusNudge): string[];
@@ -22,6 +22,9 @@ class PlusMinusModule extends AdaptableModuleBase_1.AdaptableModuleBase {
22
22
  this.shouldHandleKeyDown = false;
23
23
  this.adaptable = api.internalApi.getAdaptableInstance();
24
24
  }
25
+ isModuleAvailable() {
26
+ return super.isModuleAvailable() && this.api.gridApi.isGridRangeSelectable();
27
+ }
25
28
  getModuleAdaptableObjects(config) {
26
29
  return this.api.plusMinusApi.getAllPlusMinus(config);
27
30
  }
@@ -40,11 +43,14 @@ class PlusMinusModule extends AdaptableModuleBase_1.AdaptableModuleBase {
40
43
  return this.api.namedQueryApi.internalApi.getReferencedNamedQueryNames(plusMinusNudge.Rule?.BooleanExpression);
41
44
  }
42
45
  onAdaptableReady() {
43
- let plusMinusNudges = this.api.plusMinusApi.getAllPlusMinus();
44
- this.shouldHandleKeyDown = ArrayExtensions_1.ArrayExtensions.IsNotNullOrEmpty(plusMinusNudges);
46
+ const hasPlusMinusNudges = ArrayExtensions_1.ArrayExtensions.IsNotNullOrEmpty(this.api.plusMinusApi.getAllPlusMinus());
47
+ this.shouldHandleKeyDown = this.isModuleAvailable() && hasPlusMinusNudges;
45
48
  if (this.shouldHandleKeyDown) {
46
49
  this.setupKeyDownListener();
47
50
  }
51
+ else if (hasPlusMinusNudges && !this.api.gridApi.isGridRangeSelectable()) {
52
+ this.api.consoleWarn('Plus/Minus module is not available because AG Grid is not selectable');
53
+ }
48
54
  }
49
55
  setupKeyDownListener() {
50
56
  this.adaptable._on('KeyDown', (keyDownEvent) => {
@@ -8,8 +8,11 @@ interface OnlyAggResult {
8
8
  * AG Grid aggFunc that returns the column value only when all rows in the group
9
9
  * share the same value. Returns null when values differ (or when there are no values).
10
10
  *
11
- * Supports multiple group levels: leaf groups aggregate raw cell values while
12
- * parent groups merge the metadata objects returned by child groups.
11
+ * params.values already respects suppressAggFilteredOnly, containing either:
12
+ * - Raw cell values (string | number) for leaf children
13
+ * - OnlyAggResult objects for sub-group children (with pre-computed distinct values)
14
+ *
15
+ * Bails out early as soon as two distinct values are found.
13
16
  */
14
- export declare const only: (params: IAggFuncParams, columnId: string) => OnlyAggResult;
17
+ export declare const only: (params: IAggFuncParams) => OnlyAggResult;
15
18
  export {};
@@ -15,44 +15,30 @@ function createOnlyResult(distinctValues) {
15
15
  * AG Grid aggFunc that returns the column value only when all rows in the group
16
16
  * share the same value. Returns null when values differ (or when there are no values).
17
17
  *
18
- * Supports multiple group levels: leaf groups aggregate raw cell values while
19
- * parent groups merge the metadata objects returned by child groups.
18
+ * params.values already respects suppressAggFilteredOnly, containing either:
19
+ * - Raw cell values (string | number) for leaf children
20
+ * - OnlyAggResult objects for sub-group children (with pre-computed distinct values)
21
+ *
22
+ * Bails out early as soon as two distinct values are found.
20
23
  */
21
- const only = (params, columnId) => {
22
- const { api: gridApi, rowNode: groupRowNode, values } = params;
23
- // Leaf group: the lowest-level group whose children are actual data rows.
24
- // We read raw cell values and collect distinct ones, bailing out early
25
- // as soon as we see a second distinct value (the result would be null anyway).
26
- if (groupRowNode.leafGroup) {
27
- const filteredOnly = !gridApi.getGridOption('suppressAggFilteredOnly');
28
- const childNodes = (filteredOnly ? groupRowNode.childrenAfterFilter : groupRowNode.childrenAfterGroup) ?? [];
29
- const distinctValues = new Set();
30
- for (const rowNode of childNodes) {
31
- const rawValue = gridApi.getCellValue({ colKey: columnId, rowNode });
32
- if (typeof rawValue === 'number' || typeof rawValue === 'string') {
33
- distinctValues.add(rawValue);
34
- if (distinctValues.size > 1) {
35
- return createOnlyResult(distinctValues);
36
- }
37
- }
24
+ const only = (params) => {
25
+ const { values } = params;
26
+ const distinctValues = new Set();
27
+ for (let i = 0; i < values.length; i++) {
28
+ const value = values[i];
29
+ if (typeof value === 'number' || typeof value === 'string') {
30
+ distinctValues.add(value);
38
31
  }
39
- return createOnlyResult(distinctValues);
40
- }
41
- // Non-leaf group: children are other groups, not data rows.
42
- // AG Grid has already called this aggFunc on each child group, so
43
- // `params.values` contains the OnlyAggResult objects they returned.
44
- // We merge their distinctValues sets instead of re-traversing leaf rows.
45
- const mergedDistinctValues = new Set();
46
- for (const childResult of values) {
47
- if (childResult && typeof childResult === 'object' && 'distinctValues' in childResult) {
48
- for (const val of childResult.distinctValues) {
49
- mergedDistinctValues.add(val);
50
- if (mergedDistinctValues.size > 1) {
51
- return createOnlyResult(mergedDistinctValues);
52
- }
32
+ else if (value != null && typeof value === 'object' && 'distinctValues' in value) {
33
+ // sub-group: merge pre-computed distinct values (set has at most 2 elements)
34
+ for (const v of value.distinctValues) {
35
+ distinctValues.add(v);
53
36
  }
54
37
  }
38
+ if (distinctValues.size > 1) {
39
+ return createOnlyResult(distinctValues);
40
+ }
55
41
  }
56
- return createOnlyResult(mergedDistinctValues);
42
+ return createOnlyResult(distinctValues);
57
43
  };
58
44
  exports.only = only;
@@ -1,5 +1,16 @@
1
1
  import { IAggFuncParams } from 'ag-grid-enterprise';
2
2
  export declare const getNumericValue: (input: unknown) => number | null;
3
+ /**
4
+ * Computes a weighted average aggregation: Σ(value × weight) / Σ(weight)
5
+ *
6
+ * AG Grid calls agg functions bottom-up through the group hierarchy. For each group:
7
+ * - Leaf children contribute their raw value × weight
8
+ * - Sub-group children already have partial sums from a previous pass,
9
+ * so we combine those directly instead of re-traversing to leaves
10
+ *
11
+ * The returned object stores partial sums ([columnId] and [weightColumnId])
12
+ * so parent groups can combine sub-group results correctly.
13
+ */
3
14
  export declare const weightedAverage: (params: IAggFuncParams, columnId: string, weightColumnId: string) => {
4
15
  [x: string]: number | (() => string) | (() => number);
5
16
  toString: () => string;
@@ -11,56 +11,70 @@ const getNumericValue = (input) => {
11
11
  return isNaN(numericValue) ? null : numericValue;
12
12
  };
13
13
  exports.getNumericValue = getNumericValue;
14
- function getWeightedAverageLeafNodes(gridApi, groupRowNode, filteredOnly) {
15
- const nodeList = (filteredOnly ? groupRowNode.childrenAfterFilter : groupRowNode.childrenAfterGroup) ?? [];
16
- let leafNodes = [];
17
- nodeList.forEach((rowNode) => {
18
- if (rowNode.group === true) {
19
- // Recursively extract leaf nodes from group
20
- leafNodes = leafNodes.concat(getWeightedAverageLeafNodes(gridApi, rowNode, filteredOnly));
21
- }
22
- else {
23
- leafNodes.push(rowNode);
24
- }
25
- });
26
- return leafNodes;
27
- }
14
+ /**
15
+ * Computes a weighted average aggregation: Σ(value × weight) / Σ(weight)
16
+ *
17
+ * AG Grid calls agg functions bottom-up through the group hierarchy. For each group:
18
+ * - Leaf children contribute their raw value × weight
19
+ * - Sub-group children already have partial sums from a previous pass,
20
+ * so we combine those directly instead of re-traversing to leaves
21
+ *
22
+ * The returned object stores partial sums ([columnId] and [weightColumnId])
23
+ * so parent groups can combine sub-group results correctly.
24
+ */
28
25
  const weightedAverage = (params, columnId, weightColumnId) => {
29
- const { api: gridApi, rowNode: groupRowNode } = params;
30
- let weightedColumnValueSum = 0;
31
- let columnValueSum = 0;
32
- const filteredOnly = !gridApi.getGridOption('suppressAggFilteredOnly');
33
- const leafNodes = getWeightedAverageLeafNodes(gridApi, groupRowNode, filteredOnly);
34
- leafNodes.forEach((rowNode) => {
35
- // when editing values might be converted to strings
36
- const rawColumnValue = gridApi.getCellValue({ colKey: columnId, rowNode });
37
- const columnValue = (0, exports.getNumericValue)(rawColumnValue);
38
- const rawWeightedColumnValue = gridApi.getCellValue({ colKey: weightColumnId, rowNode });
39
- const weightedColumnValue = (0, exports.getNumericValue)(rawWeightedColumnValue);
40
- if (weightedColumnValue !== null) {
41
- weightedColumnValueSum += weightedColumnValue;
26
+ const { api: gridApi, rowNode: groupRowNode, values } = params;
27
+ // numerator: Σ(value × weight)
28
+ let weightedValueSum = 0;
29
+ // denominator: Σ(weight)
30
+ let totalWeight = 0;
31
+ // params.values already respects suppressAggFilteredOnly.
32
+ // We need the matching child nodes only for leaf rows (to look up weight column values).
33
+ const childNodes = getMatchingChildNodes(groupRowNode, values.length);
34
+ for (let i = 0; i < values.length; i++) {
35
+ const value = values[i];
36
+ if (value != null && typeof value === 'object') {
37
+ // sub-group: partial sums already computed by a previous aggregation pass
38
+ weightedValueSum += value[columnId] ?? 0;
39
+ totalWeight += value[weightColumnId] ?? 0;
42
40
  }
43
- if (columnValue !== null) {
44
- columnValueSum += columnValue * weightedColumnValue;
41
+ else {
42
+ // leaf row: compute value × weight from cell data
43
+ const childNode = childNodes[i];
44
+ if (!childNode) {
45
+ continue;
46
+ }
47
+ // values might be strings during editing
48
+ const columnValue = (0, exports.getNumericValue)(value);
49
+ const weightValue = (0, exports.getNumericValue)(gridApi.getCellValue({ colKey: weightColumnId, rowNode: childNode }));
50
+ if (weightValue !== null) {
51
+ totalWeight += weightValue;
52
+ }
53
+ if (columnValue !== null && weightValue !== null) {
54
+ weightedValueSum += columnValue * weightValue;
55
+ }
45
56
  }
46
- });
47
- let result = columnValueSum / weightedColumnValueSum;
48
- // 0 / 0 = NaN
49
- if (isNaN(result)) {
50
- result = 0;
51
57
  }
58
+ const result = totalWeight !== 0 ? weightedValueSum / totalWeight : 0;
52
59
  return {
53
- // the grid by default uses toString to render values for an object, so this
54
- // is a trick to get the default cellRenderer to display the avg value
55
- toString: () => {
56
- return String(result);
57
- },
58
- // used for sorting
59
- toNumber: function () {
60
- return result;
61
- },
62
- [columnId]: columnValueSum,
63
- [weightColumnId]: weightedColumnValueSum,
60
+ // toString/toNumber let AG Grid's default cell renderer display and sort the value
61
+ toString: () => String(result),
62
+ toNumber: () => result,
63
+ // partial sums stored so parent groups can combine sub-group results
64
+ [columnId]: weightedValueSum,
65
+ [weightColumnId]: totalWeight,
64
66
  };
65
67
  };
66
68
  exports.weightedAverage = weightedAverage;
69
+ /**
70
+ * Returns the child node list that corresponds to params.values.
71
+ * When suppressAggFilteredOnly is false, params.values comes from childrenAfterFilter.
72
+ * When true, it comes from childrenAfterGroup (all children).
73
+ * We match by length to pick the right list without checking the grid option directly.
74
+ */
75
+ function getMatchingChildNodes(groupRowNode, valueCount) {
76
+ if (groupRowNode.childrenAfterFilter?.length === valueCount) {
77
+ return groupRowNode.childrenAfterFilter;
78
+ }
79
+ return groupRowNode.childrenAfterGroup ?? [];
80
+ }
@@ -223,6 +223,7 @@ export declare class AdaptableAgGrid implements IAdaptable {
223
223
  redrawBody(): void;
224
224
  refreshHeader(): void;
225
225
  redrawRows(rowNodes?: IRowNode[]): void;
226
+ refreshGridHeader(): void;
226
227
  redrawRow(rowNode: IRowNode): void;
227
228
  refreshCell(rowNode: IRowNode, column: string | any, forceUpdate: boolean, suppressFlash?: boolean): void;
228
229
  refreshCells(rowNode: IRowNode, columns: (string | Column)[], forceUpdate: boolean, suppressFlash?: boolean): void;
@@ -1086,7 +1086,7 @@ class AdaptableAgGrid {
1086
1086
  this.agGridOptionsService.setGridOptionsProperty(gridOptions, 'aggFuncs', (original_aggFuncs) => {
1087
1087
  const aggregationFunctions = original_aggFuncs || {};
1088
1088
  aggregationFunctions[AggregationColumns_1.ONLY_AGG_FN_NAME] = (params) => {
1089
- return (0, only_1.only)(params, params.column.getColId());
1089
+ return (0, only_1.only)(params);
1090
1090
  };
1091
1091
  aggregationFunctions[AggregationColumns_1.WEIGHTED_AVERAGE_AGG_FN_NAME] = (params) => {
1092
1092
  const columnId = params.column.getColId();
@@ -2264,6 +2264,9 @@ class AdaptableAgGrid {
2264
2264
  this.logger.consoleError('AG Grid redrawRows failed to locate some row nodes.', rowNodes, ex);
2265
2265
  }
2266
2266
  }
2267
+ refreshGridHeader() {
2268
+ this.agGridAdapter.getAgGridApi().refreshHeader();
2269
+ }
2267
2270
  redrawRow(rowNode) {
2268
2271
  this.redrawRows([rowNode]);
2269
2272
  }
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: 1771927501120 || Date.now(),
6
- VERSION: "22.0.0" || '--current-version--',
5
+ PUBLISH_TIMESTAMP: 1772037269052 || Date.now(),
6
+ VERSION: "22.0.1-canary.0" || '--current-version--',
7
7
  };