@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptabletools/adaptable",
3
- "version": "22.0.0",
3
+ "version": "22.0.1-canary.1",
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?: {
@@ -34,6 +34,10 @@ export declare abstract class AdaptablePlugin {
34
34
  afterInitStore(adaptable: IAdaptable): void;
35
35
  afterInit(ab: IAdaptable): void;
36
36
  afterSetLayout(adaptable: IAdaptable, layout: Layout): void;
37
+ onBeforeStoreEvent(eventName: string, data: {
38
+ action: Redux.Action;
39
+ state: AdaptableState;
40
+ }, adaptableStore: IAdaptableStore): void;
37
41
  onStoreEvent(eventName: string, data: {
38
42
  action: Redux.Action;
39
43
  state: AdaptableState;
@@ -39,6 +39,7 @@ export class AdaptablePlugin {
39
39
  afterInit(ab) { }
40
40
  // hook executed after each layout update (Adaptable.setLayout())
41
41
  afterSetLayout(adaptable, layout) { }
42
+ onBeforeStoreEvent(eventName, data, adaptableStore) { }
42
43
  onStoreEvent(eventName, data, adaptableStore) { }
43
44
  onAdaptableReady(adaptable, adaptableOptions) { }
44
45
  interceptSetupColumnProperty;
@@ -1,4 +1,4 @@
1
- import { AdaptableReadyInfo, AdaptableStateChangedInfo, AdaptableStateReloadedInfo, AlertFiredInfo, CalculatedColumnChangedInfo, CellChangedInfo, CellSelectionChangedInfo, ChartChangedInfo, ColumnFilterAppliedInfo, CommentChangedInfo, CustomToolbarConfiguredInfo, DashboardChangedInfo, DataImportedInfo, DataSetSelectedInfo, Fdc3MessageInfo, FlashingCellDisplayedInfo, GridFilterAppliedInfo, GridSortedInfo, LayoutChangedInfo, LiveDataChangedInfo, RowChangedInfo, RowFormSubmittedInfo, RowSelectionChangedInfo, ScheduleTriggeredInfo, SystemStatusMessageDisplayedInfo, TeamSharingEntityChangedInfo, ThemeChangedInfo } from '../types';
1
+ import { AdaptableReadyInfo, AdaptableStateChangedInfo, AdaptableStateReloadedInfo, BeforeAdaptableStateChangeInfo, AlertFiredInfo, CalculatedColumnChangedInfo, CellChangedInfo, CellSelectionChangedInfo, ChartChangedInfo, ColumnFilterAppliedInfo, CommentChangedInfo, CustomToolbarConfiguredInfo, DashboardChangedInfo, DataImportedInfo, DataSetSelectedInfo, Fdc3MessageInfo, FlashingCellDisplayedInfo, GridFilterAppliedInfo, GridSortedInfo, LayoutChangedInfo, LiveDataChangedInfo, RowChangedInfo, RowFormSubmittedInfo, RowSelectionChangedInfo, ScheduleTriggeredInfo, SystemStatusMessageDisplayedInfo, TeamSharingEntityChangedInfo, ThemeChangedInfo } from '../types';
2
2
  /**
3
3
  * Responsible for publishing the many Events that AdapTable fires
4
4
  */
@@ -210,6 +210,17 @@ export interface EventApi {
210
210
  * Unsubscribe from DashboardChanged
211
211
  */
212
212
  off(eventName: 'DashboardChanged', callback: (dashboardChangedInfo: DashboardChangedInfo) => void): void;
213
+ /**
214
+ * Event fired **before** Adaptable State changes (before the action is processed)
215
+ * @param eventName BeforeAdaptableStateChange
216
+ * @param callback BeforeAdaptableStateChangeInfo
217
+ * @returns the unsubscribe function
218
+ */
219
+ on(eventName: 'BeforeAdaptableStateChange', callback: (beforeAdaptableStateChangeInfo: BeforeAdaptableStateChangeInfo) => void): () => void;
220
+ /**
221
+ * Unsubscribe from BeforeAdaptableStateChange
222
+ */
223
+ off(eventName: 'BeforeAdaptableStateChange', callback: (beforeAdaptableStateChangeInfo: BeforeAdaptableStateChangeInfo) => void): void;
213
224
  /**
214
225
  * Event fired whenever **Adaptable State changes**
215
226
  * @param eventName AdaptableStateChanged
@@ -336,9 +347,10 @@ export interface EventApi {
336
347
  * @param callbackFdc3MessageInfo
337
348
  */
338
349
  off(eventName: 'Fdc3Message', callback: (fdc3MessageInfo: Fdc3MessageInfo) => void): void;
350
+ emitSync(eventName: 'BeforeAdaptableStateChange', data?: any): any[];
339
351
  emitSync(eventName: 'DashboardChanged', data?: any): any[];
340
352
  emitSync(eventName: 'FlashingCellDisplayed', data?: any): any[];
341
353
  emitSync(eventName: 'AdaptableDestroy'): any[];
342
- emit(eventName: 'RowFormSubmitted' | 'AdaptableReady' | 'AlertFired' | 'AdaptableStateChanged' | 'AdaptableStateReloaded' | 'CellChanged' | 'ChartChanged' | 'CheckboxColumnClicked' | 'CustomToolbarConfigured' | 'DashboardChanged' | 'DataImported' | 'DataSetSelected' | 'ColumnFilterApplied' | 'Fdc3Message' | 'RowChanged' | 'GridSorted' | 'LayoutChanged' | 'CalculatedColumnChanged' | 'LiveDataChanged' | 'ScheduleTriggered' | 'SearchChanged' | 'CellSelectionChanged' | 'RowSelectionChanged' | 'SystemStatusMessageDisplayed' | 'TeamSharingEntityChanged' | 'ThemeChanged' | 'GridFilterApplied' | 'CommentChanged', data?: any): Promise<any>;
354
+ emit(eventName: 'RowFormSubmitted' | 'AdaptableReady' | 'AlertFired' | 'BeforeAdaptableStateChange' | 'AdaptableStateChanged' | 'AdaptableStateReloaded' | 'CellChanged' | 'ChartChanged' | 'CheckboxColumnClicked' | 'CustomToolbarConfigured' | 'DashboardChanged' | 'DataImported' | 'DataSetSelected' | 'ColumnFilterApplied' | 'Fdc3Message' | 'RowChanged' | 'GridSorted' | 'LayoutChanged' | 'CalculatedColumnChanged' | 'LiveDataChanged' | 'ScheduleTriggered' | 'SearchChanged' | 'CellSelectionChanged' | 'RowSelectionChanged' | 'SystemStatusMessageDisplayed' | 'TeamSharingEntityChanged' | 'ThemeChanged' | 'GridFilterApplied' | 'CommentChanged', data?: any): Promise<any>;
343
355
  destroy(): void;
344
356
  }
@@ -0,0 +1,20 @@
1
+ import * as Redux from 'redux';
2
+ import { AdaptableState } from '../../AdaptableState/AdaptableState';
3
+ import { BaseContext } from '../../types';
4
+ /**
5
+ * Object returned by the `BeforeAdaptableStateChange` event, fired before the action is processed by the reducer
6
+ */
7
+ export interface BeforeAdaptableStateChangeInfo extends BaseContext {
8
+ /**
9
+ * Name of the Action about to be performed
10
+ */
11
+ actionName: string;
12
+ /**
13
+ * The Redux Action that is about to be invoked
14
+ */
15
+ action: Redux.Action;
16
+ /**
17
+ * Current Adaptable State (before the Action is applied)
18
+ */
19
+ state: AdaptableState;
20
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -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;
@@ -547,6 +547,9 @@ export class GridApiImpl extends ApiBase {
547
547
  this.getAgGridApi().refreshClientSideRowModel('group');
548
548
  this._adaptable.updateRowGroupsAndColumnGroupsExpandedState();
549
549
  }
550
+ refreshGridHeader() {
551
+ this._adaptable.refreshGridHeader();
552
+ }
550
553
  isCellEditable(gridCell) {
551
554
  // 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)
552
555
  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
  }
@@ -44,4 +44,17 @@ export class RowFormApiImpl extends ApiBase {
44
44
  },
45
45
  }));
46
46
  }
47
+ displayDeleteRowForm(primaryKey) {
48
+ const rowNode = this.getGridApi().getRowNodeForPrimaryKey(primaryKey);
49
+ if (!rowNode) {
50
+ this.logWarn(`Can NOT delete row: rowNode not found for primaryKey ${primaryKey}`);
51
+ }
52
+ const eventInfo = {
53
+ type: 'rowDeleted',
54
+ rowNode: rowNode,
55
+ ...this.getAdaptableInternalApi().buildBaseContext(),
56
+ };
57
+ this.getEventApi().internalApi.fireRowFormSubmittedEvent(eventInfo);
58
+ this.getRowFormOptions().onRowFormSubmit?.(eventInfo);
59
+ }
47
60
  }
@@ -109,27 +109,10 @@ export class ActionColumnInternalApi extends ApiBase {
109
109
  break;
110
110
  case 'delete':
111
111
  button.onClick = (button, context) => {
112
- const eventInfo = {
113
- type: 'rowDeleted',
114
- rowNode: context.rowNode,
115
- ...this.getAdaptableInternalApi().buildBaseContext(),
116
- };
117
- this.getEventApi().internalApi.fireRowFormSubmittedEvent(eventInfo);
118
- this.getRowFormOptions().onRowFormSubmit?.(eventInfo);
112
+ this.getRowFormApi().displayDeleteRowForm(context.primaryKeyValue);
119
113
  };
120
114
  button.tooltip = button.tooltip ? button.tooltip : 'Delete Row';
121
- button.icon = button.icon ?? {
122
- name: 'delete',
123
- };
124
- break;
125
- case 'edit':
126
- button.onClick = (button, context) => {
127
- this.getRowFormApi().displayEditRowForm(context.primaryKeyValue);
128
- };
129
- button.tooltip = button.tooltip ? button.tooltip : 'Edit Row';
130
- button.icon = button.icon ?? {
131
- name: 'edit',
132
- };
115
+ button.icon = button.icon ?? { name: 'delete' };
133
116
  break;
134
117
  }
135
118
  }
@@ -17,6 +17,7 @@ export declare class EventInternalApi extends ApiBase {
17
17
  fireDataSetSelectedEvent(dataSet: DataSet): void;
18
18
  fireSystemStatusMessageDisplayedEvent(systemStatusMessageInfo: SystemStatusMessageInfo): void;
19
19
  fireDataImportedEvent(importData: any[], addedRows: IRowNode[], updatedRows: IRowNode[]): DataImportedInfo;
20
+ fireBeforeAdaptableStateChangeEvent(action: Redux.Action, state: AdaptableState): void;
20
21
  fireAdaptableStateChangedEvent(action: Redux.Action, oldState: AdaptableState, newState: AdaptableState): void;
21
22
  fireAdaptableStateReloadedEvent(oldState: AdaptablePersistentState, newState: AdaptablePersistentState): void;
22
23
  fireCalculatedColumnChangedEvent(trigger: string, calculatedColumn: CalculatedColumn): void;
@@ -129,6 +129,15 @@ export class EventInternalApi extends ApiBase {
129
129
  this.getEventApi().emit('DataImported', dataImportedInfo);
130
130
  return dataImportedInfo;
131
131
  }
132
+ fireBeforeAdaptableStateChangeEvent(action, state) {
133
+ const beforeAdaptableStateChangeInfo = {
134
+ actionName: action.type,
135
+ ...this.getAdaptableInternalApi().buildBaseContext(),
136
+ action: action,
137
+ state: state,
138
+ };
139
+ this.getEventApi().emitSync('BeforeAdaptableStateChange', beforeAdaptableStateChangeInfo);
140
+ }
132
141
  fireAdaptableStateChangedEvent(action, oldState, newState) {
133
142
  const adaptableStateChangedInfo = {
134
143
  actionName: action.type,
@@ -41,7 +41,7 @@ export class ExportInternalApi extends ApiBase {
41
41
  }
42
42
  break;
43
43
  case 'VisibleColumns':
44
- // hope that visibile column property is updated whenever the layout changes... (need to check!)
44
+ // hope that visible column property is updated whenever the layout changes... (need to check!)
45
45
  if (!cellDataChangedInfo.column.visible) {
46
46
  return false;
47
47
  }
@@ -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
  }
@@ -22,6 +22,7 @@ export declare class AdaptableStore implements IAdaptableStore {
22
22
  TheStore: Redux.Store<AdaptableState, Redux.Action>;
23
23
  Load: Promise<any>;
24
24
  private emitter;
25
+ private beforeEmitter;
25
26
  private storageEngine;
26
27
  private currentStorageState?;
27
28
  private previousStorageState?;
@@ -29,6 +30,7 @@ export declare class AdaptableStore implements IAdaptableStore {
29
30
  private loadStateOnStartup;
30
31
  on: (eventName: string, callback: EmitterCallback) => (() => void);
31
32
  onAny: (callback: EmitterAnyCallback) => (() => void);
33
+ onBeforeAny: (callback: EmitterAnyCallback) => (() => void);
32
34
  emit: (eventName: string, data: any) => Promise<any>;
33
35
  /**
34
36
  *
@@ -70,6 +70,7 @@ export class AdaptableStore {
70
70
  TheStore;
71
71
  Load;
72
72
  emitter;
73
+ beforeEmitter;
73
74
  storageEngine;
74
75
  currentStorageState;
75
76
  previousStorageState;
@@ -81,6 +82,9 @@ export class AdaptableStore {
81
82
  onAny = (callback) => {
82
83
  return this.emitter.onAny(callback);
83
84
  };
85
+ onBeforeAny = (callback) => {
86
+ return this.beforeEmitter.onAny(callback);
87
+ };
84
88
  emit = (eventName, data) => {
85
89
  return this.emitter.emit(eventName, data);
86
90
  };
@@ -149,6 +153,7 @@ export class AdaptableStore {
149
153
  };
150
154
  let storageEngine;
151
155
  this.emitter = new Emitter();
156
+ this.beforeEmitter = new Emitter();
152
157
  // If the user has remote storage set then we use Remote Engine, otherwise we use Local Enginge
153
158
  // not sure we can do this as we need to be backwardly compatible with existing users so need to stick with adaptable id (which should be unique)
154
159
  // const localStorageKey = 'adaptable-adaptable-state-' + adaptable.adaptableOptions.primaryKey;
@@ -204,6 +209,13 @@ export class AdaptableStore {
204
209
  }
205
210
  return finalState;
206
211
  };
212
+ const beforeEmitterMiddleware = (middlewareAPI) => (next) => (action) => {
213
+ this.beforeEmitter.emitSync(action.type, {
214
+ action,
215
+ state: middlewareAPI.getState(),
216
+ });
217
+ return next(action);
218
+ };
207
219
  const devToolsActionMarkerMiddleware = createDevToolsActionMarkerMiddleware(adaptable);
208
220
  const pluginsMiddleware = [];
209
221
  adaptable.forPlugins((plugin) => {
@@ -212,6 +224,7 @@ export class AdaptableStore {
212
224
  }
213
225
  });
214
226
  const middlewares = [
227
+ beforeEmitterMiddleware, // fires before anything else processes the action
215
228
  devToolsActionMarkerMiddleware,
216
229
  adaptableMiddleware(adaptable), // the main middleware that actually does stuff,
217
230
  ...pluginsMiddleware, // the plugins middleware
@@ -224,6 +237,8 @@ export class AdaptableStore {
224
237
  destroy() {
225
238
  this.emitter?.clearListeners();
226
239
  this.emitter = null;
240
+ this.beforeEmitter?.clearListeners();
241
+ this.beforeEmitter = null;
227
242
  }
228
243
  getCurrentStorageState() {
229
244
  return this.currentStorageState;
@@ -17,6 +17,7 @@ export interface IAdaptableStore {
17
17
  saveStateNow: (adaptable: IAdaptable) => Promise<any>;
18
18
  on: (eventName: string, callback: (data?: any) => any) => () => void;
19
19
  onAny: (callback: (eventName: string, data?: any) => any) => () => void;
20
+ onBeforeAny: (callback: (eventName: string, data?: any) => any) => () => void;
20
21
  emit: (eventName: string, data: any) => Promise<any>;
21
22
  destroy: () => void;
22
23
  }
@@ -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">[];
@@ -12,6 +12,9 @@ export class CellSummaryModule extends AdaptableModuleBase {
12
12
  constructor(api) {
13
13
  super(ModuleConstants.CellSummaryModuleId, ModuleConstants.CellSummaryFriendlyName, 'cells', 'CellSummaryPopup', 'See summary information on a group of numeric cells using multiple summary operations', api);
14
14
  }
15
+ isModuleAvailable() {
16
+ return super.isModuleAvailable() && this.api.gridApi.isGridRangeSelectable();
17
+ }
15
18
  getViewAccessLevel() {
16
19
  return 'Full';
17
20
  }
@@ -143,24 +143,26 @@ export class LayoutModule extends AdaptableModuleBase {
143
143
  this.api.columnApi.hideColumn(column.columnId);
144
144
  }));
145
145
  }
146
- const hasExistingSelection = this.api.gridApi.getSelectedCellInfo()?.gridCells?.length;
147
- if (hasExistingSelection) {
148
- returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-column-select-preserve', 'Select Column (Preserve Selection)', 'select-fwd', () => {
149
- this.api.columnApi.addColumnToSelection(column.columnId);
150
- }));
151
- returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-column-select-reset', 'Select Column (Reset Selection)', 'tab-unselected', () => {
152
- this.api.columnApi.selectColumn(column.columnId);
153
- }));
154
- }
155
- else {
156
- returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-column-select', 'Select Column', 'tab-unselected', () => {
157
- this.api.columnApi.selectColumn(column.columnId);
146
+ if (this.api.gridApi.isGridRangeSelectable()) {
147
+ const hasExistingSelection = this.api.gridApi.getSelectedCellInfo()?.gridCells?.length;
148
+ if (hasExistingSelection) {
149
+ returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-column-select-preserve', 'Select Column (Preserve Selection)', 'select-fwd', () => {
150
+ this.api.columnApi.addColumnToSelection(column.columnId);
151
+ }));
152
+ returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-column-select-reset', 'Select Column (Reset Selection)', 'tab-unselected', () => {
153
+ this.api.columnApi.selectColumn(column.columnId);
154
+ }));
155
+ }
156
+ else {
157
+ returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-column-select', 'Select Column', 'tab-unselected', () => {
158
+ this.api.columnApi.selectColumn(column.columnId);
159
+ }));
160
+ }
161
+ returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-grid-select', 'Select Grid', 'select-all', () => {
162
+ this.api.gridApi.selectAll();
158
163
  }));
159
164
  }
160
165
  }
161
- returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-grid-select', 'Select Grid', 'select-all', () => {
162
- this.api.gridApi.selectAll();
163
- }));
164
166
  return returnColumnMenuItems;
165
167
  }
166
168
  createContextMenuItems(menuContext) {
@@ -179,9 +181,11 @@ export class LayoutModule extends AdaptableModuleBase {
179
181
  this.api.gridApi.deselectAll();
180
182
  }));
181
183
  }
182
- returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-select-all', 'Select Grid', 'select-all', () => {
183
- this.api.gridApi.selectAll();
184
- }));
184
+ if (this.api.gridApi.isGridRangeSelectable()) {
185
+ returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-select-all', 'Select Grid', 'select-all', () => {
186
+ this.api.gridApi.selectAll();
187
+ }));
188
+ }
185
189
  returnColumnMenuItems.push(this.createMenuItemClickFunction('layout-auto-size', 'Auto Size', 'arrow-expand', () => {
186
190
  this.api.columnApi.autosizeAllColumns();
187
191
  }));
@@ -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[];
@@ -18,6 +18,9 @@ export class PlusMinusModule extends AdaptableModuleBase {
18
18
  this.shouldHandleKeyDown = false;
19
19
  this.adaptable = api.internalApi.getAdaptableInstance();
20
20
  }
21
+ isModuleAvailable() {
22
+ return super.isModuleAvailable() && this.api.gridApi.isGridRangeSelectable();
23
+ }
21
24
  getModuleAdaptableObjects(config) {
22
25
  return this.api.plusMinusApi.getAllPlusMinus(config);
23
26
  }
@@ -36,11 +39,14 @@ export class PlusMinusModule extends AdaptableModuleBase {
36
39
  return this.api.namedQueryApi.internalApi.getReferencedNamedQueryNames(plusMinusNudge.Rule?.BooleanExpression);
37
40
  }
38
41
  onAdaptableReady() {
39
- let plusMinusNudges = this.api.plusMinusApi.getAllPlusMinus();
40
- this.shouldHandleKeyDown = ArrayExtensions.IsNotNullOrEmpty(plusMinusNudges);
42
+ const hasPlusMinusNudges = ArrayExtensions.IsNotNullOrEmpty(this.api.plusMinusApi.getAllPlusMinus());
43
+ this.shouldHandleKeyDown = this.isModuleAvailable() && hasPlusMinusNudges;
41
44
  if (this.shouldHandleKeyDown) {
42
45
  this.setupKeyDownListener();
43
46
  }
47
+ else if (hasPlusMinusNudges && !this.api.gridApi.isGridRangeSelectable()) {
48
+ this.api.consoleWarn('Plus/Minus module is not available because AG Grid is not selectable');
49
+ }
44
50
  }
45
51
  setupKeyDownListener() {
46
52
  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 {};
@@ -12,43 +12,29 @@ function createOnlyResult(distinctValues) {
12
12
  * AG Grid aggFunc that returns the column value only when all rows in the group
13
13
  * share the same value. Returns null when values differ (or when there are no values).
14
14
  *
15
- * Supports multiple group levels: leaf groups aggregate raw cell values while
16
- * parent groups merge the metadata objects returned by child groups.
15
+ * params.values already respects suppressAggFilteredOnly, containing either:
16
+ * - Raw cell values (string | number) for leaf children
17
+ * - OnlyAggResult objects for sub-group children (with pre-computed distinct values)
18
+ *
19
+ * Bails out early as soon as two distinct values are found.
17
20
  */
18
- export const only = (params, columnId) => {
19
- const { api: gridApi, rowNode: groupRowNode, values } = params;
20
- // Leaf group: the lowest-level group whose children are actual data rows.
21
- // We read raw cell values and collect distinct ones, bailing out early
22
- // as soon as we see a second distinct value (the result would be null anyway).
23
- if (groupRowNode.leafGroup) {
24
- const filteredOnly = !gridApi.getGridOption('suppressAggFilteredOnly');
25
- const childNodes = (filteredOnly ? groupRowNode.childrenAfterFilter : groupRowNode.childrenAfterGroup) ?? [];
26
- const distinctValues = new Set();
27
- for (const rowNode of childNodes) {
28
- const rawValue = gridApi.getCellValue({ colKey: columnId, rowNode });
29
- if (typeof rawValue === 'number' || typeof rawValue === 'string') {
30
- distinctValues.add(rawValue);
31
- if (distinctValues.size > 1) {
32
- return createOnlyResult(distinctValues);
33
- }
34
- }
21
+ export const only = (params) => {
22
+ const { values } = params;
23
+ const distinctValues = new Set();
24
+ for (let i = 0; i < values.length; i++) {
25
+ const value = values[i];
26
+ if (typeof value === 'number' || typeof value === 'string') {
27
+ distinctValues.add(value);
35
28
  }
36
- return createOnlyResult(distinctValues);
37
- }
38
- // Non-leaf group: children are other groups, not data rows.
39
- // AG Grid has already called this aggFunc on each child group, so
40
- // `params.values` contains the OnlyAggResult objects they returned.
41
- // We merge their distinctValues sets instead of re-traversing leaf rows.
42
- const mergedDistinctValues = new Set();
43
- for (const childResult of values) {
44
- if (childResult && typeof childResult === 'object' && 'distinctValues' in childResult) {
45
- for (const val of childResult.distinctValues) {
46
- mergedDistinctValues.add(val);
47
- if (mergedDistinctValues.size > 1) {
48
- return createOnlyResult(mergedDistinctValues);
49
- }
29
+ else if (value != null && typeof value === 'object' && 'distinctValues' in value) {
30
+ // sub-group: merge pre-computed distinct values (set has at most 2 elements)
31
+ for (const v of value.distinctValues) {
32
+ distinctValues.add(v);
50
33
  }
51
34
  }
35
+ if (distinctValues.size > 1) {
36
+ return createOnlyResult(distinctValues);
37
+ }
52
38
  }
53
- return createOnlyResult(mergedDistinctValues);
39
+ return createOnlyResult(distinctValues);
54
40
  };
@@ -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;