@adaptabletools/adaptable 22.0.0 → 22.0.1-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/package.json +1 -1
  2. package/src/AdaptableInterfaces/IAdaptable.d.ts +1 -0
  3. package/src/AdaptableOptions/AdaptablePlugin.d.ts +4 -0
  4. package/src/AdaptableOptions/AdaptablePlugin.js +1 -0
  5. package/src/Api/EventApi.d.ts +14 -2
  6. package/src/Api/Events/BeforeAdaptableStateChange.d.ts +20 -0
  7. package/src/Api/Events/BeforeAdaptableStateChange.js +1 -0
  8. package/src/Api/GridApi.d.ts +4 -0
  9. package/src/Api/Implementation/GridApiImpl.d.ts +1 -0
  10. package/src/Api/Implementation/GridApiImpl.js +3 -0
  11. package/src/Api/Implementation/RowFormApiImpl.d.ts +1 -0
  12. package/src/Api/Implementation/RowFormApiImpl.js +13 -0
  13. package/src/Api/Internal/ActionColumnInternalApi.js +2 -19
  14. package/src/Api/Internal/EventInternalApi.d.ts +1 -0
  15. package/src/Api/Internal/EventInternalApi.js +9 -0
  16. package/src/Api/Internal/ExportInternalApi.js +1 -1
  17. package/src/Api/RowFormApi.d.ts +5 -0
  18. package/src/Redux/Store/AdaptableStore.d.ts +2 -0
  19. package/src/Redux/Store/AdaptableStore.js +15 -0
  20. package/src/Redux/Store/Interface/IAdaptableStore.d.ts +1 -0
  21. package/src/Strategy/CellSummaryModule.d.ts +1 -0
  22. package/src/Strategy/CellSummaryModule.js +3 -0
  23. package/src/Strategy/LayoutModule.js +22 -18
  24. package/src/Strategy/PlusMinusModule.d.ts +1 -0
  25. package/src/Strategy/PlusMinusModule.js +8 -2
  26. package/src/Utilities/only.d.ts +6 -3
  27. package/src/Utilities/only.js +20 -34
  28. package/src/Utilities/weightedAverage.d.ts +11 -0
  29. package/src/Utilities/weightedAverage.js +59 -45
  30. package/src/agGrid/AdaptableAgGrid.d.ts +1 -0
  31. package/src/agGrid/AdaptableAgGrid.js +11 -1
  32. package/src/env.js +2 -2
  33. package/src/types.d.ts +1 -0
  34. package/tsconfig.esm.tsbuildinfo +1 -1
@@ -6,55 +6,69 @@ export const getNumericValue = (input) => {
6
6
  const numericValue = toNumber(input);
7
7
  return isNaN(numericValue) ? null : numericValue;
8
8
  };
9
- function getWeightedAverageLeafNodes(gridApi, groupRowNode, filteredOnly) {
10
- const nodeList = (filteredOnly ? groupRowNode.childrenAfterFilter : groupRowNode.childrenAfterGroup) ?? [];
11
- let leafNodes = [];
12
- nodeList.forEach((rowNode) => {
13
- if (rowNode.group === true) {
14
- // Recursively extract leaf nodes from group
15
- leafNodes = leafNodes.concat(getWeightedAverageLeafNodes(gridApi, rowNode, filteredOnly));
16
- }
17
- else {
18
- leafNodes.push(rowNode);
19
- }
20
- });
21
- return leafNodes;
22
- }
9
+ /**
10
+ * Computes a weighted average aggregation: Σ(value × weight) / Σ(weight)
11
+ *
12
+ * AG Grid calls agg functions bottom-up through the group hierarchy. For each group:
13
+ * - Leaf children contribute their raw value × weight
14
+ * - Sub-group children already have partial sums from a previous pass,
15
+ * so we combine those directly instead of re-traversing to leaves
16
+ *
17
+ * The returned object stores partial sums ([columnId] and [weightColumnId])
18
+ * so parent groups can combine sub-group results correctly.
19
+ */
23
20
  export const weightedAverage = (params, columnId, weightColumnId) => {
24
- const { api: gridApi, rowNode: groupRowNode } = params;
25
- let weightedColumnValueSum = 0;
26
- let columnValueSum = 0;
27
- const filteredOnly = !gridApi.getGridOption('suppressAggFilteredOnly');
28
- const leafNodes = getWeightedAverageLeafNodes(gridApi, groupRowNode, filteredOnly);
29
- leafNodes.forEach((rowNode) => {
30
- // when editing values might be converted to strings
31
- const rawColumnValue = gridApi.getCellValue({ colKey: columnId, rowNode });
32
- const columnValue = getNumericValue(rawColumnValue);
33
- const rawWeightedColumnValue = gridApi.getCellValue({ colKey: weightColumnId, rowNode });
34
- const weightedColumnValue = getNumericValue(rawWeightedColumnValue);
35
- if (weightedColumnValue !== null) {
36
- weightedColumnValueSum += weightedColumnValue;
21
+ const { api: gridApi, rowNode: groupRowNode, values } = params;
22
+ // numerator: Σ(value × weight)
23
+ let weightedValueSum = 0;
24
+ // denominator: Σ(weight)
25
+ let totalWeight = 0;
26
+ // params.values already respects suppressAggFilteredOnly.
27
+ // We need the matching child nodes only for leaf rows (to look up weight column values).
28
+ const childNodes = getMatchingChildNodes(groupRowNode, values.length);
29
+ for (let i = 0; i < values.length; i++) {
30
+ const value = values[i];
31
+ if (value != null && typeof value === 'object') {
32
+ // sub-group: partial sums already computed by a previous aggregation pass
33
+ weightedValueSum += value[columnId] ?? 0;
34
+ totalWeight += value[weightColumnId] ?? 0;
37
35
  }
38
- if (columnValue !== null) {
39
- columnValueSum += columnValue * weightedColumnValue;
36
+ else {
37
+ // leaf row: compute value × weight from cell data
38
+ const childNode = childNodes[i];
39
+ if (!childNode) {
40
+ continue;
41
+ }
42
+ // values might be strings during editing
43
+ const columnValue = getNumericValue(value);
44
+ const weightValue = getNumericValue(gridApi.getCellValue({ colKey: weightColumnId, rowNode: childNode }));
45
+ if (weightValue !== null) {
46
+ totalWeight += weightValue;
47
+ }
48
+ if (columnValue !== null && weightValue !== null) {
49
+ weightedValueSum += columnValue * weightValue;
50
+ }
40
51
  }
41
- });
42
- let result = columnValueSum / weightedColumnValueSum;
43
- // 0 / 0 = NaN
44
- if (isNaN(result)) {
45
- result = 0;
46
52
  }
53
+ const result = totalWeight !== 0 ? weightedValueSum / totalWeight : 0;
47
54
  return {
48
- // the grid by default uses toString to render values for an object, so this
49
- // is a trick to get the default cellRenderer to display the avg value
50
- toString: () => {
51
- return String(result);
52
- },
53
- // used for sorting
54
- toNumber: function () {
55
- return result;
56
- },
57
- [columnId]: columnValueSum,
58
- [weightColumnId]: weightedColumnValueSum,
55
+ // toString/toNumber let AG Grid's default cell renderer display and sort the value
56
+ toString: () => String(result),
57
+ toNumber: () => result,
58
+ // partial sums stored so parent groups can combine sub-group results
59
+ [columnId]: weightedValueSum,
60
+ [weightColumnId]: totalWeight,
59
61
  };
60
62
  };
63
+ /**
64
+ * Returns the child node list that corresponds to params.values.
65
+ * When suppressAggFilteredOnly is false, params.values comes from childrenAfterFilter.
66
+ * When true, it comes from childrenAfterGroup (all children).
67
+ * We match by length to pick the right list without checking the grid option directly.
68
+ */
69
+ function getMatchingChildNodes(groupRowNode, valueCount) {
70
+ if (groupRowNode.childrenAfterFilter?.length === valueCount) {
71
+ return groupRowNode.childrenAfterFilter;
72
+ }
73
+ return groupRowNode.childrenAfterGroup ?? [];
74
+ }
@@ -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;
@@ -957,6 +957,7 @@ export class AdaptableAgGrid {
957
957
  if (rowGroupDisplayType === 'single') {
958
958
  return true;
959
959
  }
960
+ // this is required because of AG Grid bug, see https://github.com/AdaptableTools/adaptable/issues/3212
960
961
  if (rowGroupDisplayType === 'multi') {
961
962
  const groupedColumnFilterConfig = this.api.layoutApi.internalApi.areAllGroupedColumnsFilterable();
962
963
  if (groupedColumnFilterConfig.floatingFilter) {
@@ -1082,7 +1083,7 @@ export class AdaptableAgGrid {
1082
1083
  this.agGridOptionsService.setGridOptionsProperty(gridOptions, 'aggFuncs', (original_aggFuncs) => {
1083
1084
  const aggregationFunctions = original_aggFuncs || {};
1084
1085
  aggregationFunctions[ONLY_AGG_FN_NAME] = (params) => {
1085
- return only(params, params.column.getColId());
1086
+ return only(params);
1086
1087
  };
1087
1088
  aggregationFunctions[WEIGHTED_AVERAGE_AGG_FN_NAME] = (params) => {
1088
1089
  const columnId = params.column.getColId();
@@ -1612,6 +1613,12 @@ export class AdaptableAgGrid {
1612
1613
  const perfNewAdaptableStore = this.logger.beginPerf(`initAdaptableStore()`);
1613
1614
  const initAdaptableStoreMarker = getMarker(this.adaptableOptions.adaptableId).track.Init.label.InitStore.start();
1614
1615
  const adaptableStore = new AdaptableStore(this);
1616
+ adaptableStore.onBeforeAny((eventName, data) => {
1617
+ if (this.isReady) {
1618
+ this.api.eventApi.internalApi.fireBeforeAdaptableStateChangeEvent(data.action, data.state);
1619
+ }
1620
+ this.forPlugins((plugin) => plugin.onBeforeStoreEvent?.(eventName, data, this.adaptableStore));
1621
+ });
1615
1622
  adaptableStore.onAny((eventName, data) => {
1616
1623
  if (this.isReady) {
1617
1624
  this.api.eventApi.internalApi.fireAdaptableStateChangedEvent(data.action, data.state, data.newState);
@@ -2260,6 +2267,9 @@ export class AdaptableAgGrid {
2260
2267
  this.logger.consoleError('AG Grid redrawRows failed to locate some row nodes.', rowNodes, ex);
2261
2268
  }
2262
2269
  }
2270
+ refreshGridHeader() {
2271
+ this.agGridAdapter.getAgGridApi().refreshHeader();
2272
+ }
2263
2273
  redrawRow(rowNode) {
2264
2274
  this.redrawRows([rowNode]);
2265
2275
  }
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: 1771927464818 || Date.now(),
4
- VERSION: "22.0.0" || '--current-version--',
3
+ PUBLISH_TIMESTAMP: 1772179361165 || Date.now(),
4
+ VERSION: "22.0.1-canary.1" || '--current-version--',
5
5
  };
package/src/types.d.ts CHANGED
@@ -139,6 +139,7 @@ export type { ThemeChangedInfo } from './Api/Events/ThemeChanged';
139
139
  export type { DashboardChangedInfo } from './Api/Events/DashboardChanged';
140
140
  export type { ScheduleTriggeredInfo } from './Api/Events/ScheduleTriggered';
141
141
  export type { AdaptableStateChangedInfo } from './Api/Events/AdaptableStateChanged';
142
+ export type { BeforeAdaptableStateChangeInfo } from './Api/Events/BeforeAdaptableStateChange';
142
143
  export type { CommentChangedInfo } from './Api/Events/CommentChanged';
143
144
  export type { Fdc3MessageInfo, Fdc3MessageSentInfo, Fdc3MessageReceivedInfo, } from './Api/Events/Fdc3MessageInfo';
144
145
  export type { AdaptableState, AdaptablePersistentState, AdaptableTransientState, } from './AdaptableState/AdaptableState';