@genesislcap/pbc-reporting-ui 15.16.0 → 15.16.1-alpha-8ba249e.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.
@@ -6904,6 +6904,24 @@
6904
6904
  "kind": "javascript-module",
6905
6905
  "path": "src/old/components/renderers/row-select.renderer.ts",
6906
6906
  "declarations": [
6907
+ {
6908
+ "kind": "function",
6909
+ "name": "isUserCheckboxToggle",
6910
+ "return": {
6911
+ "type": {
6912
+ "text": "boolean"
6913
+ }
6914
+ },
6915
+ "parameters": [
6916
+ {
6917
+ "name": "node",
6918
+ "type": {
6919
+ "text": "unknown"
6920
+ }
6921
+ }
6922
+ ],
6923
+ "description": "True while `RowSelectRenderer` is applying a user checkbox click. @public"
6924
+ },
6907
6925
  {
6908
6926
  "kind": "class",
6909
6927
  "description": "The AG Row Select Renderer element.",
@@ -7044,6 +7062,14 @@
7044
7062
  }
7045
7063
  ],
7046
7064
  "exports": [
7065
+ {
7066
+ "kind": "js",
7067
+ "name": "isUserCheckboxToggle",
7068
+ "declaration": {
7069
+ "name": "isUserCheckboxToggle",
7070
+ "module": "src/old/components/renderers/row-select.renderer.ts"
7071
+ }
7072
+ },
7047
7073
  {
7048
7074
  "kind": "js",
7049
7075
  "name": "RowSelectRenderer",
@@ -1 +1 @@
1
- {"version":3,"file":"col-filters-grid.helpers.d.ts","sourceRoot":"","sources":["../../../../../../src/new/main/edit-config/col-filters/col-filters-grid.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAQ3D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,gBAAgB,CAAC,aAAa,CAAC,GAAG,IAAI,CAqBvF"}
1
+ {"version":3,"file":"col-filters-grid.helpers.d.ts","sourceRoot":"","sources":["../../../../../../src/new/main/edit-config/col-filters/col-filters-grid.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAS3D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAazD;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,gBAAgB,CAAC,aAAa,CAAC,GAAG,IAAI,CAwBvF"}
@@ -1,6 +1,8 @@
1
1
  import { ICellRendererComp, ICellRendererParams } from '@ag-grid-community/core';
2
2
  import { BooleanRendererParams } from '@genesislcap/foundation-zero-grid-pro';
3
3
  import { FoundationElement } from '@genesislcap/web-core';
4
+ /** True while `RowSelectRenderer` is applying a user checkbox click. @public */
5
+ export declare function isUserCheckboxToggle(node: unknown): boolean;
4
6
  /**
5
7
  * The AG Row Select Renderer element.
6
8
  * @public
@@ -1 +1 @@
1
- {"version":3,"file":"row-select.renderer.d.ts","sourceRoot":"","sources":["../../../../../src/old/components/renderers/row-select.renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAuB,MAAM,uCAAuC,CAAC;AACnG,OAAO,EAAyB,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAEjF;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,iBAAkB,YAAW,iBAAiB;IAE5E,MAAM,EAAE,mBAAmB,GAAG,qBAAqB,CAAC;IAG3D,OAAO,EAAE,OAAO,CAAC;IAEV,UAAU,CAAC,IAAI,KAAA,GAAG,OAAO;IAWzB,IAAI,CAAC,MAAM,EAAE,mBAAmB;IAShC,kBAAkB;IAMlB,aAAa,CAAC,CAAC,KAAA;IAKf,MAAM,IAAI,WAAW;IAIrB,OAAO;IAOP,OAAO,CAAC,MAAM,EAAE,mBAAmB;IAK1C,QAAQ;IAIR,mBAAmB;CAGpB;AAED;;;GAGG;AACH,eAAO,MAAM,yBAAyB,iDAsCrC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,GAAI,qBAAsB,2EAYpE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B;;;;;;;;4BAIxC,CAAC"}
1
+ {"version":3,"file":"row-select.renderer.d.ts","sourceRoot":"","sources":["../../../../../src/old/components/renderers/row-select.renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAuB,MAAM,uCAAuC,CAAC;AACnG,OAAO,EAAyB,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAKjF,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAE3D;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,iBAAkB,YAAW,iBAAiB;IAE5E,MAAM,EAAE,mBAAmB,GAAG,qBAAqB,CAAC;IAG3D,OAAO,EAAE,OAAO,CAAC;IAEV,UAAU,CAAC,IAAI,KAAA,GAAG,OAAO;IAWzB,IAAI,CAAC,MAAM,EAAE,mBAAmB;IAShC,kBAAkB;IAMlB,aAAa,CAAC,CAAC,KAAA;IAYf,MAAM,IAAI,WAAW;IAIrB,OAAO;IAOP,OAAO,CAAC,MAAM,EAAE,mBAAmB;IAK1C,QAAQ;IAIR,mBAAmB;CAGpB;AAED;;;GAGG;AACH,eAAO,MAAM,yBAAyB,iDAsCrC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,GAAI,qBAAsB,2EAYpE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B;;;;;;;;4BAIxC,CAAC"}
@@ -1,5 +1,16 @@
1
+ import { isUserCheckboxToggle } from '../../../../old/components/renderers/row-select.renderer';
1
2
  import { actions, selectors } from '../../../store';
2
3
  import { GridColumnNames, datasourceNameFromDisplay, lookupColumnIsIncluded, shouldDisableColumn, } from '../shared';
4
+ /** AG Grid built-in UI sources. Row checkboxes use `isUserCheckboxToggle()` instead. */
5
+ const USER_SELECTION_SOURCES = new Set([
6
+ 'uiSelectAll',
7
+ 'uiSelectAllFiltered',
8
+ 'uiSelectAllCurrentPage',
9
+ 'checkboxSelected',
10
+ 'rowClicked',
11
+ 'spaceKey',
12
+ 'spacePressed', // v29 name for 'spaceKey'
13
+ ]);
3
14
  /**
4
15
  * Handler for row selection changes in the grid
5
16
  */
@@ -7,6 +18,9 @@ export function rowSelectionChangedHandler(event) {
7
18
  var _a, _b;
8
19
  if (!event.data)
9
20
  return;
21
+ // Ignore programmatic re-selection (`setSelected()` defaults to source `'api'`).
22
+ if (!USER_SELECTION_SOURCES.has(event.source) && !isUserCheckboxToggle(event.node))
23
+ return;
10
24
  // gate event listener to only trigger if the data is actually changed by the user
11
25
  // (return if setting the same value as in the store, e.g. when first loading
12
26
  // the grid data)
@@ -1,4 +1,5 @@
1
1
  import { assert, sinon, suite } from '@genesislcap/foundation-testing';
2
+ import { RowSelectRenderer, isUserCheckboxToggle, } from '../../../../old/components/renderers/row-select.renderer';
2
3
  import { actions, selectors } from '../../../store';
3
4
  import { GridColumnNames } from '../shared';
4
5
  import { rowSelectionChangedHandler } from './col-filters-grid.helpers';
@@ -23,6 +24,7 @@ RowSelectionChangedHandler('should return early if filtered state matches select
23
24
  };
24
25
  const mockEvent = {
25
26
  data: mockData,
27
+ source: 'uiSelectAll',
26
28
  node: {
27
29
  isSelected: sinon.stub().returns(false),
28
30
  },
@@ -53,6 +55,7 @@ RowSelectionChangedHandler('should return early if type is invalid', () => {
53
55
  };
54
56
  const mockEvent = {
55
57
  data: mockData,
58
+ source: 'uiSelectAll',
56
59
  node: {
57
60
  isSelected: sinon.stub().returns(false),
58
61
  },
@@ -83,6 +86,7 @@ RowSelectionChangedHandler('should update include and redraw when selection chan
83
86
  };
84
87
  const mockEvent = {
85
88
  data: mockData,
89
+ source: 'uiSelectAll',
86
90
  node: {
87
91
  isSelected: sinon.stub().returns(false),
88
92
  },
@@ -130,6 +134,7 @@ RowSelectionChangedHandler('should not set default format if output format is XL
130
134
  };
131
135
  const mockEvent = {
132
136
  data: mockData,
137
+ source: 'uiSelectAll',
133
138
  node: {
134
139
  isSelected: sinon.stub().returns(false),
135
140
  },
@@ -161,6 +166,7 @@ RowSelectionChangedHandler('should handle undefined selection state', () => {
161
166
  };
162
167
  const mockEvent = {
163
168
  data: mockData,
169
+ source: 'uiSelectAll',
164
170
  node: {
165
171
  isSelected: sinon.stub().returns(undefined),
166
172
  },
@@ -197,4 +203,63 @@ RowSelectionChangedHandler('should handle undefined selection state', () => {
197
203
  assert.equal(setColumnIncludedStub.getCall(0).args[0].setDefaultFormat, true);
198
204
  assert.equal(mockEvent.api.redrawRows.calledOnce, true);
199
205
  });
206
+ /** Event whose selection differs from the store, so only the user/API guard decides write-back. */
207
+ const makeChangingEvent = (source) => {
208
+ const mockData = {
209
+ [GridColumnNames.Datasource]: 'testAlias (Snapshot)',
210
+ [GridColumnNames.ColumnName]: 'testColumn',
211
+ [GridColumnNames.Type]: 'INT',
212
+ };
213
+ sinon.stub(selectors.datasourceConfig, 'getDatasource').returns({
214
+ KEY: 'testSource',
215
+ NAME: 'testAlias',
216
+ INPUT_TYPE: 'REQ_REP',
217
+ OUTPUT_TYPE: 'TABLE',
218
+ TRANSFORMER_CONFIGURATION: {
219
+ INCLUDE_COLUMNS: ['testColumn'],
220
+ },
221
+ GROUPING_STRATEGY: 'NONE',
222
+ GROUP_KEY: null,
223
+ });
224
+ sinon.stub(selectors.datasourceConfig, 'getAllConfigSet').returns({
225
+ REQ_REP_testSource_testAlias: {
226
+ KEY: 'testAlias',
227
+ NAME: 'testSource',
228
+ INPUT_TYPE: 'REQ_REP',
229
+ OUTPUT_TYPE: 'TABLE',
230
+ TRANSFORMER_CONFIGURATION: {},
231
+ GROUPING_STRATEGY: 'NONE',
232
+ GROUP_KEY: null,
233
+ },
234
+ });
235
+ return {
236
+ data: mockData,
237
+ source,
238
+ node: { isSelected: sinon.stub().returns(false) },
239
+ api: { redrawRows: sinon.stub() },
240
+ };
241
+ };
242
+ RowSelectionChangedHandler('should ignore programmatic api-sourced events (grid re-applying its own selection)', () => {
243
+ const setColumnIncludedStub = sinon.stub(actions.datasourceConfig, 'setColumnIncluded');
244
+ rowSelectionChangedHandler(makeChangingEvent('api'));
245
+ assert.equal(setColumnIncludedStub.called, false);
246
+ });
247
+ RowSelectionChangedHandler('should apply an api-sourced event while the user is toggling the row checkbox', () => {
248
+ const setColumnIncludedStub = sinon.stub(actions.datasourceConfig, 'setColumnIncluded');
249
+ const event = makeChangingEvent('api');
250
+ // Drive via the renderer prototype: custom elements cannot be constructed outside a registry.
251
+ event.node.setSelected = () => rowSelectionChangedHandler(event);
252
+ const renderer = { params: { node: event.node } };
253
+ RowSelectRenderer.prototype.changeHandler.call(renderer, { target: { checked: false } });
254
+ assert.equal(setColumnIncludedStub.calledOnce, true);
255
+ assert.equal(setColumnIncludedStub.getCall(0).args[0].column, 'testColumn');
256
+ assert.equal(isUserCheckboxToggle(event.node), false, 'the marker is cleared off the node once the toggle completes');
257
+ });
258
+ RowSelectionChangedHandler('should apply every row of a header select-all (not treat the batch as programmatic)', () => {
259
+ const setColumnIncludedStub = sinon.stub(actions.datasourceConfig, 'setColumnIncluded');
260
+ const event = makeChangingEvent('uiSelectAll');
261
+ rowSelectionChangedHandler(event);
262
+ rowSelectionChangedHandler(event);
263
+ assert.equal(setColumnIncludedStub.callCount, 2);
264
+ });
200
265
  RowSelectionChangedHandler.run();
@@ -1,6 +1,12 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { EDITED_COLUMN_FIELD } from '@genesislcap/foundation-zero-grid-pro';
3
3
  import { css, html, observable, FoundationElement } from '@genesislcap/web-core';
4
+ /** Set on the row node for the duration of a user checkbox click. @internal */
5
+ const USER_TOGGLE_MARKER = '__reportingUserCheckboxToggle';
6
+ /** True while `RowSelectRenderer` is applying a user checkbox click. @public */
7
+ export function isUserCheckboxToggle(node) {
8
+ return !!node && node[USER_TOGGLE_MARKER] === true;
9
+ }
4
10
  /**
5
11
  * The AG Row Select Renderer element.
6
12
  * @public
@@ -36,7 +42,15 @@ export class RowSelectRenderer extends FoundationElement {
36
42
  }
37
43
  changeHandler(e) {
38
44
  this.checked = e.target.checked;
39
- this.params.node.setSelected(this.checked);
45
+ const node = this.params.node;
46
+ const marked = node;
47
+ marked[USER_TOGGLE_MARKER] = true;
48
+ try {
49
+ node.setSelected(this.checked);
50
+ }
51
+ finally {
52
+ delete marked[USER_TOGGLE_MARKER];
53
+ }
40
54
  }
41
55
  getGui() {
42
56
  return this;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/pbc-reporting-ui",
3
3
  "description": "Genesis PBC Reporting UI",
4
- "version": "15.16.0",
4
+ "version": "15.16.1-alpha-8ba249e.0",
5
5
  "license": "SEE LICENSE IN license.txt",
6
6
  "main": "dist/esm/index.js",
7
7
  "types": "dist/dts/index.d.ts",
@@ -86,32 +86,32 @@
86
86
  "@ag-grid-community/core": "29.2.0"
87
87
  },
88
88
  "dependencies": {
89
- "@genesislcap/foundation-comms": "15.16.0",
90
- "@genesislcap/foundation-entity-management": "15.16.0",
91
- "@genesislcap/foundation-events": "15.16.0",
92
- "@genesislcap/foundation-forms": "15.16.0",
93
- "@genesislcap/foundation-logger": "15.16.0",
94
- "@genesislcap/foundation-notifications": "15.16.0",
95
- "@genesislcap/foundation-ui": "15.16.0",
96
- "@genesislcap/foundation-user": "15.16.0",
97
- "@genesislcap/foundation-utils": "15.16.0",
98
- "@genesislcap/foundation-zero": "15.16.0",
99
- "@genesislcap/foundation-zero-grid-pro": "15.16.0",
100
- "@genesislcap/grid-pro": "15.16.0",
101
- "@genesislcap/rapid-design-system": "15.16.0",
102
- "@genesislcap/rapid-grid-pro": "15.16.0",
103
- "@genesislcap/web-core": "15.16.0",
89
+ "@genesislcap/foundation-comms": "15.16.1-alpha-8ba249e.0",
90
+ "@genesislcap/foundation-entity-management": "15.16.1-alpha-8ba249e.0",
91
+ "@genesislcap/foundation-events": "15.16.1-alpha-8ba249e.0",
92
+ "@genesislcap/foundation-forms": "15.16.1-alpha-8ba249e.0",
93
+ "@genesislcap/foundation-logger": "15.16.1-alpha-8ba249e.0",
94
+ "@genesislcap/foundation-notifications": "15.16.1-alpha-8ba249e.0",
95
+ "@genesislcap/foundation-ui": "15.16.1-alpha-8ba249e.0",
96
+ "@genesislcap/foundation-user": "15.16.1-alpha-8ba249e.0",
97
+ "@genesislcap/foundation-utils": "15.16.1-alpha-8ba249e.0",
98
+ "@genesislcap/foundation-zero": "15.16.1-alpha-8ba249e.0",
99
+ "@genesislcap/foundation-zero-grid-pro": "15.16.1-alpha-8ba249e.0",
100
+ "@genesislcap/grid-pro": "15.16.1-alpha-8ba249e.0",
101
+ "@genesislcap/rapid-design-system": "15.16.1-alpha-8ba249e.0",
102
+ "@genesislcap/rapid-grid-pro": "15.16.1-alpha-8ba249e.0",
103
+ "@genesislcap/web-core": "15.16.1-alpha-8ba249e.0",
104
104
  "@reduxjs/toolkit": "^2.2.5",
105
105
  "@types/node": "^22.10.2",
106
106
  "change-case": "^5.4.3",
107
107
  "lodash": "^4.17.21"
108
108
  },
109
109
  "devDependencies": {
110
- "@genesislcap/eslint-config": "15.16.0",
111
- "@genesislcap/foundation-testing": "15.16.0",
112
- "@genesislcap/genx": "15.16.0",
113
- "@genesislcap/prettier-config": "15.16.0",
114
- "@genesislcap/stylelint-config": "15.16.0",
110
+ "@genesislcap/eslint-config": "15.16.1-alpha-8ba249e.0",
111
+ "@genesislcap/foundation-testing": "15.16.1-alpha-8ba249e.0",
112
+ "@genesislcap/genx": "15.16.1-alpha-8ba249e.0",
113
+ "@genesislcap/prettier-config": "15.16.1-alpha-8ba249e.0",
114
+ "@genesislcap/stylelint-config": "15.16.1-alpha-8ba249e.0",
115
115
  "@types/json-schema": "^7.0.11",
116
116
  "playwright-lighthouse": "^4.0.0",
117
117
  "rimraf": "^5.0.0"
@@ -120,5 +120,5 @@
120
120
  "access": "public"
121
121
  },
122
122
  "customElements": "dist/custom-elements.json",
123
- "gitHead": "2cacfdef54a332ee571ae784b5b7629cf66f050f"
123
+ "gitHead": "ae1f09ed0c413d087239cfd7299bcba065f177fa"
124
124
  }
@@ -1,5 +1,9 @@
1
1
  import { RowSelectedEvent } from '@ag-grid-community/core';
2
2
  import { assert, sinon, suite } from '@genesislcap/foundation-testing';
3
+ import {
4
+ RowSelectRenderer,
5
+ isUserCheckboxToggle,
6
+ } from '../../../../old/components/renderers/row-select.renderer';
3
7
  import { actions, selectors, TransformerConfig } from '../../../store';
4
8
  import { GridColumnNames } from '../shared';
5
9
  import { rowSelectionChangedHandler } from './col-filters-grid.helpers';
@@ -31,6 +35,7 @@ RowSelectionChangedHandler('should return early if filtered state matches select
31
35
 
32
36
  const mockEvent = {
33
37
  data: mockData,
38
+ source: 'uiSelectAll',
34
39
  node: {
35
40
  isSelected: sinon.stub().returns(false),
36
41
  },
@@ -66,6 +71,7 @@ RowSelectionChangedHandler('should return early if type is invalid', () => {
66
71
 
67
72
  const mockEvent = {
68
73
  data: mockData,
74
+ source: 'uiSelectAll',
69
75
  node: {
70
76
  isSelected: sinon.stub().returns(false),
71
77
  },
@@ -101,6 +107,7 @@ RowSelectionChangedHandler('should update include and redraw when selection chan
101
107
 
102
108
  const mockEvent = {
103
109
  data: mockData,
110
+ source: 'uiSelectAll',
104
111
  node: {
105
112
  isSelected: sinon.stub().returns(false),
106
113
  },
@@ -153,6 +160,7 @@ RowSelectionChangedHandler('should not set default format if output format is XL
153
160
 
154
161
  const mockEvent = {
155
162
  data: mockData,
163
+ source: 'uiSelectAll',
156
164
  node: {
157
165
  isSelected: sinon.stub().returns(false),
158
166
  },
@@ -189,6 +197,7 @@ RowSelectionChangedHandler('should handle undefined selection state', () => {
189
197
 
190
198
  const mockEvent = {
191
199
  data: mockData,
200
+ source: 'uiSelectAll',
192
201
  node: {
193
202
  isSelected: sinon.stub().returns(undefined),
194
203
  },
@@ -229,4 +238,88 @@ RowSelectionChangedHandler('should handle undefined selection state', () => {
229
238
  assert.equal((<any>mockEvent.api.redrawRows).calledOnce, true);
230
239
  });
231
240
 
241
+ /** Event whose selection differs from the store, so only the user/API guard decides write-back. */
242
+ const makeChangingEvent = (source?: string) => {
243
+ const mockData = {
244
+ [GridColumnNames.Datasource]: 'testAlias (Snapshot)',
245
+ [GridColumnNames.ColumnName]: 'testColumn',
246
+ [GridColumnNames.Type]: 'INT',
247
+ } as ColFilterData;
248
+
249
+ sinon.stub(selectors.datasourceConfig, 'getDatasource').returns({
250
+ KEY: 'testSource',
251
+ NAME: 'testAlias',
252
+ INPUT_TYPE: 'REQ_REP' as const,
253
+ OUTPUT_TYPE: 'TABLE' as const,
254
+ TRANSFORMER_CONFIGURATION: <TransformerConfig>{
255
+ INCLUDE_COLUMNS: ['testColumn'],
256
+ },
257
+ GROUPING_STRATEGY: 'NONE',
258
+ GROUP_KEY: null,
259
+ });
260
+ sinon.stub(selectors.datasourceConfig, 'getAllConfigSet').returns({
261
+ REQ_REP_testSource_testAlias: {
262
+ KEY: 'testAlias',
263
+ NAME: 'testSource',
264
+ INPUT_TYPE: 'REQ_REP',
265
+ OUTPUT_TYPE: 'TABLE',
266
+ TRANSFORMER_CONFIGURATION: {},
267
+ GROUPING_STRATEGY: 'NONE',
268
+ GROUP_KEY: null,
269
+ },
270
+ });
271
+
272
+ return {
273
+ data: mockData,
274
+ source,
275
+ node: { isSelected: sinon.stub().returns(false) },
276
+ api: { redrawRows: sinon.stub() },
277
+ } as unknown as RowSelectedEvent<ColFilterData>;
278
+ };
279
+
280
+ RowSelectionChangedHandler(
281
+ 'should ignore programmatic api-sourced events (grid re-applying its own selection)',
282
+ () => {
283
+ const setColumnIncludedStub = sinon.stub(actions.datasourceConfig, 'setColumnIncluded');
284
+
285
+ rowSelectionChangedHandler(makeChangingEvent('api'));
286
+
287
+ assert.equal(setColumnIncludedStub.called, false);
288
+ },
289
+ );
290
+
291
+ RowSelectionChangedHandler(
292
+ 'should apply an api-sourced event while the user is toggling the row checkbox',
293
+ () => {
294
+ const setColumnIncludedStub = sinon.stub(actions.datasourceConfig, 'setColumnIncluded');
295
+ const event = makeChangingEvent('api');
296
+
297
+ // Drive via the renderer prototype: custom elements cannot be constructed outside a registry.
298
+ (event.node as any).setSelected = () => rowSelectionChangedHandler(event);
299
+ const renderer = { params: { node: event.node } } as unknown as RowSelectRenderer;
300
+ RowSelectRenderer.prototype.changeHandler.call(renderer, { target: { checked: false } });
301
+
302
+ assert.equal(setColumnIncludedStub.calledOnce, true);
303
+ assert.equal(setColumnIncludedStub.getCall(0).args[0].column, 'testColumn');
304
+ assert.equal(
305
+ isUserCheckboxToggle(event.node),
306
+ false,
307
+ 'the marker is cleared off the node once the toggle completes',
308
+ );
309
+ },
310
+ );
311
+
312
+ RowSelectionChangedHandler(
313
+ 'should apply every row of a header select-all (not treat the batch as programmatic)',
314
+ () => {
315
+ const setColumnIncludedStub = sinon.stub(actions.datasourceConfig, 'setColumnIncluded');
316
+ const event = makeChangingEvent('uiSelectAll');
317
+
318
+ rowSelectionChangedHandler(event);
319
+ rowSelectionChangedHandler(event);
320
+
321
+ assert.equal(setColumnIncludedStub.callCount, 2);
322
+ },
323
+ );
324
+
232
325
  RowSelectionChangedHandler.run();
@@ -1,4 +1,5 @@
1
1
  import { RowSelectedEvent } from '@ag-grid-community/core';
2
+ import { isUserCheckboxToggle } from '../../../../old/components/renderers/row-select.renderer';
2
3
  import { actions, selectors } from '../../../store';
3
4
  import {
4
5
  GridColumnNames,
@@ -8,12 +9,26 @@ import {
8
9
  } from '../shared';
9
10
  import { ColFilterData } from './col-filters-grid.types';
10
11
 
12
+ /** AG Grid built-in UI sources. Row checkboxes use `isUserCheckboxToggle()` instead. */
13
+ const USER_SELECTION_SOURCES: ReadonlySet<string> = new Set([
14
+ 'uiSelectAll',
15
+ 'uiSelectAllFiltered',
16
+ 'uiSelectAllCurrentPage',
17
+ 'checkboxSelected',
18
+ 'rowClicked',
19
+ 'spaceKey',
20
+ 'spacePressed', // v29 name for 'spaceKey'
21
+ ]);
22
+
11
23
  /**
12
24
  * Handler for row selection changes in the grid
13
25
  */
14
26
  export function rowSelectionChangedHandler(event: RowSelectedEvent<ColFilterData>): void {
15
27
  if (!event.data) return;
16
28
 
29
+ // Ignore programmatic re-selection (`setSelected()` defaults to source `'api'`).
30
+ if (!USER_SELECTION_SOURCES.has(event.source) && !isUserCheckboxToggle(event.node)) return;
31
+
17
32
  // gate event listener to only trigger if the data is actually changed by the user
18
33
  // (return if setting the same value as in the store, e.g. when first loading
19
34
  // the grid data)
@@ -2,6 +2,14 @@ import { ICellRendererComp, ICellRendererParams } from '@ag-grid-community/core'
2
2
  import { BooleanRendererParams, EDITED_COLUMN_FIELD } from '@genesislcap/foundation-zero-grid-pro';
3
3
  import { css, html, observable, FoundationElement } from '@genesislcap/web-core';
4
4
 
5
+ /** Set on the row node for the duration of a user checkbox click. @internal */
6
+ const USER_TOGGLE_MARKER = '__reportingUserCheckboxToggle';
7
+
8
+ /** True while `RowSelectRenderer` is applying a user checkbox click. @public */
9
+ export function isUserCheckboxToggle(node: unknown): boolean {
10
+ return !!node && (node as Record<string, unknown>)[USER_TOGGLE_MARKER] === true;
11
+ }
12
+
5
13
  /**
6
14
  * The AG Row Select Renderer element.
7
15
  * @public
@@ -42,7 +50,14 @@ export class RowSelectRenderer extends FoundationElement implements ICellRendere
42
50
 
43
51
  public changeHandler(e) {
44
52
  this.checked = e.target.checked;
45
- this.params.node.setSelected(this.checked);
53
+ const node = this.params.node;
54
+ const marked = node as unknown as Record<string, boolean>;
55
+ marked[USER_TOGGLE_MARKER] = true;
56
+ try {
57
+ node.setSelected(this.checked);
58
+ } finally {
59
+ delete marked[USER_TOGGLE_MARKER];
60
+ }
46
61
  }
47
62
 
48
63
  public getGui(): HTMLElement {