@genesislcap/grid-pro 14.323.0 → 14.324.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.
Files changed (51) hide show
  1. package/README.md +1 -1
  2. package/dist/custom-elements.json +941 -349
  3. package/dist/dts/datasource/base.datasource.d.ts +64 -5
  4. package/dist/dts/datasource/base.datasource.d.ts.map +1 -1
  5. package/dist/dts/datasource/base.types.d.ts +5 -2
  6. package/dist/dts/datasource/base.types.d.ts.map +1 -1
  7. package/dist/dts/datasource/datasource.types.d.ts +8 -0
  8. package/dist/dts/datasource/datasource.types.d.ts.map +1 -1
  9. package/dist/dts/datasource/server-side.datasource.d.ts +9 -1
  10. package/dist/dts/datasource/server-side.datasource.d.ts.map +1 -1
  11. package/dist/dts/datasource/server-side.resource-base.d.ts +26 -2
  12. package/dist/dts/datasource/server-side.resource-base.d.ts.map +1 -1
  13. package/dist/dts/datasource/server-side.resource-dataserver.d.ts +5 -0
  14. package/dist/dts/datasource/server-side.resource-dataserver.d.ts.map +1 -1
  15. package/dist/dts/datasource/server-side.resource-reqrep.d.ts +9 -0
  16. package/dist/dts/datasource/server-side.resource-reqrep.d.ts.map +1 -1
  17. package/dist/dts/grid-pro-genesis-datasource/grid-pro-genesis-datasource.d.ts +2 -0
  18. package/dist/dts/grid-pro-genesis-datasource/grid-pro-genesis-datasource.d.ts.map +1 -1
  19. package/dist/dts/status-bar-components/pagination.status-bar.d.ts.map +1 -1
  20. package/dist/esm/datasource/base.datasource.js +61 -19
  21. package/dist/esm/datasource/server-side.datasource.js +32 -44
  22. package/dist/esm/datasource/server-side.resource-base.js +36 -38
  23. package/dist/esm/datasource/server-side.resource-dataserver.js +47 -1
  24. package/dist/esm/datasource/server-side.resource-reqrep.js +174 -39
  25. package/dist/esm/grid-pro-genesis-datasource/grid-pro-genesis-datasource.js +40 -2
  26. package/dist/esm/status-bar-components/pagination.status-bar.js +29 -4
  27. package/dist/grid-pro.api.json +82 -21
  28. package/dist/grid-pro.d.ts +83 -6
  29. package/docs/api/grid-pro.genesisgriddatasourceelement.criteria.md +2 -0
  30. package/docs/api/grid-pro.genesisgriddatasourceelement.disablepolling.md +7 -0
  31. package/docs/api/grid-pro.genesisgriddatasourceelement.fields.md +7 -0
  32. package/docs/api/grid-pro.genesisgriddatasourceelement.issnapshot.md +7 -0
  33. package/docs/api/grid-pro.genesisgriddatasourceelement.maxrows.md +7 -0
  34. package/docs/api/grid-pro.genesisgriddatasourceelement.maxview.md +7 -0
  35. package/docs/api/grid-pro.genesisgriddatasourceelement.md +47 -0
  36. package/docs/api/grid-pro.genesisgriddatasourceelement.movingview.md +7 -0
  37. package/docs/api/grid-pro.genesisgriddatasourceelement.offset.md +18 -0
  38. package/docs/api/grid-pro.genesisgriddatasourceelement.orderby.md +7 -0
  39. package/docs/api/grid-pro.genesisgriddatasourceelement.pollinginterval.md +7 -0
  40. package/docs/api/grid-pro.genesisgriddatasourceelement.polltriggerevents.md +7 -0
  41. package/docs/api/grid-pro.genesisgriddatasourceelement.request.md +7 -0
  42. package/docs/api/grid-pro.genesisgriddatasourceelement.resourcename.md +7 -0
  43. package/docs/api/grid-pro.genesisgriddatasourceelement.reverse.md +7 -0
  44. package/docs/api/grid-pro.genesisgriddatasourceelement.viewnumber.md +2 -0
  45. package/docs/api/grid-pro.gridproserversidedatasource.md +3 -5
  46. package/docs/api/grid-pro.gridproserversidedatasource.pagingmode.md +21 -0
  47. package/docs/api/grid-pro.md +11 -0
  48. package/docs/api/grid-pro.pagingmode.md +18 -0
  49. package/docs/api-report.md.api.md +5 -16
  50. package/package.json +13 -13
  51. package/docs/api/grid-pro.gridproserversidedatasource.params.md +0 -14
@@ -1,6 +1,6 @@
1
1
  import { __awaiter, __decorate } from "tslib";
2
2
  import { Events, } from '@ag-grid-community/core';
3
- import { dataServerResultFilter, MessageType, normaliseCriteria, toFieldMetadata, } from '@genesislcap/foundation-comms';
3
+ import { dataServerResultFilter, MessageType, normaliseCriteria, ResourceType, toFieldMetadata, } from '@genesislcap/foundation-comms';
4
4
  import { LifecycleMixin, insertDocumentCSSRule } from '@genesislcap/foundation-utils';
5
5
  import { attr, customElement, DOM, observable } from '@microsoft/fast-element';
6
6
  import { gridProGenesisDatasourceEventNames } from '../grid-pro-genesis-datasource';
@@ -11,7 +11,6 @@ import { DataserverServerSideDatasource } from './server-side.resource-dataserve
11
11
  import { ReqRepServerSideDatasource } from './server-side.resource-reqrep';
12
12
  const criteriaDelimiter = ';';
13
13
  const withoutColumnDefs = null;
14
- const timeoutInMs = 500;
15
14
  /**
16
15
  * Custom CSS for server-side datasource sort indicators
17
16
  * Makes sort indicators always visible with custom styling
@@ -203,7 +202,7 @@ let GridProServerSideDatasource = class GridProServerSideDatasource extends Life
203
202
  if (!params.data) {
204
203
  return null;
205
204
  }
206
- return params.data[this.rowId];
205
+ return String(params.data[this.rowId]);
207
206
  }, getRowStyle(params) {
208
207
  var _a, _b;
209
208
  if ((_b = (_a = params.data) === null || _a === void 0 ? void 0 : _a.ROW_REF) === null || _b === void 0 ? void 0 : _b.includes('_deleted')) {
@@ -237,7 +236,7 @@ let GridProServerSideDatasource = class GridProServerSideDatasource extends Life
237
236
  reloadResourceDataFunc: this.reloadResourceData.bind(this),
238
237
  errorHandlerFunc: this.handleErrors.bind(this),
239
238
  resourceName: this.resourceName,
240
- resourceParams: this.params,
239
+ resourceParams: this.datasource.dataserverOnlyParams,
241
240
  resourceIndexes: this.indexes,
242
241
  resourceColDefs: this.datasource.originalFieldDef,
243
242
  maxRows: +this.maxRows,
@@ -245,6 +244,8 @@ let GridProServerSideDatasource = class GridProServerSideDatasource extends Life
245
244
  rowId: this.rowId,
246
245
  pagination: this.pagination,
247
246
  zeroBasedViewNumber: this.zeroBasedViewNumber,
247
+ pagingMode: this.pagingMode,
248
+ criteriaOnlyRequest: this.datasource.criteriaOnlyRequest,
248
249
  });
249
250
  }
250
251
  else {
@@ -253,7 +254,7 @@ let GridProServerSideDatasource = class GridProServerSideDatasource extends Life
253
254
  reloadResourceDataFunc: this.reloadResourceData.bind(this),
254
255
  errorHandlerFunc: this.handleErrors.bind(this),
255
256
  resourceName: this.resourceName,
256
- resourceParams: this.params,
257
+ resourceParams: this.datasource.requestOnlyParams,
257
258
  resourceIndexes: this.indexes,
258
259
  resourceColDefs: this.datasource.originalFieldDef,
259
260
  maxRows: +this.maxRows,
@@ -323,27 +324,6 @@ let GridProServerSideDatasource = class GridProServerSideDatasource extends Life
323
324
  });
324
325
  return resourceIndexesMap;
325
326
  }
326
- get params() {
327
- const params = {
328
- CRITERIA_MATCH: this.criteria,
329
- FIELDS: this.fields,
330
- MAX_ROWS: this.maxRows,
331
- MAX_VIEW: this.maxView,
332
- MOVING_VIEW: this.movingView,
333
- REVERSE: this.reverse,
334
- };
335
- const keys = Array.from(this.indexes.keys());
336
- if (this.orderBy) {
337
- if (keys.findIndex((key) => key === this.orderBy) > -1) {
338
- params.ORDER_BY = this.orderBy;
339
- }
340
- else {
341
- const validIndexes = keys.map((key) => key);
342
- logger.warn('Specified [orderBy] index is not valid and will not be used. See https://learn.genesis.global/docs/database/data-types/index-entities/ - Available indexes:', validIndexes);
343
- }
344
- }
345
- return params;
346
- }
347
327
  get rowModel() {
348
328
  return this.agGrid.gridApi.getModel();
349
329
  }
@@ -357,7 +337,7 @@ let GridProServerSideDatasource = class GridProServerSideDatasource extends Life
357
337
  return __awaiter(this, arguments, void 0, function* (existingParams = null) {
358
338
  if (this.liveUpdates) {
359
339
  const streamOnMessage = (message) => __awaiter(this, void 0, void 0, function* () {
360
- var _a, _b;
340
+ var _a, _b, _c, _d, _e, _f, _g, _h;
361
341
  const messageType = message.MESSAGE_TYPE;
362
342
  if (messageType === MessageType.QUERY_UPDATE && message.ROW) {
363
343
  if (!this.ssrmDatasource) {
@@ -369,21 +349,19 @@ let GridProServerSideDatasource = class GridProServerSideDatasource extends Life
369
349
  this.handleStreamUpdates(nextMessage.updates);
370
350
  this.handleStreamDeletes(nextMessage.deletes);
371
351
  if (message.SEQUENCE_ID > 1) {
372
- this.ssrmDatasource.clientRowsCount += (_a = nextMessage.inserts.length) !== null && _a !== void 0 ? _a : 0;
373
- this.ssrmDatasource.serverRowsCount += (_b = nextMessage.inserts.length) !== null && _b !== void 0 ? _b : 0;
374
- }
375
- // this.handleStreamDeletes(nextMessage.deletes);
376
- // this.ssrmDatasource.client_ROWS_COUNT -= nextMessage.deletes.length ?? 0;
377
- // this.ssrmDatasource.server_ROWS_COUNT -= nextMessage.deletes.length ?? 0;
378
- if (this.pagination) {
352
+ // Calculate net row count change (inserts - deletes)
353
+ const netRowChange = ((_b = (_a = nextMessage.inserts) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) - ((_d = (_c = nextMessage.deletes) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0);
354
+ this.ssrmDatasource.serverRowsCount += netRowChange;
355
+ const loadedDeletes = (_f = (_e = nextMessage.deletes) === null || _e === void 0 ? void 0 : _e.filter((deleteData) => {
356
+ const rowId = deleteData[this.rowId];
357
+ const rowNode = this.agGrid.gridApi.getRowNode(rowId);
358
+ return rowNode != null;
359
+ })) !== null && _f !== void 0 ? _f : [];
360
+ // Calculate net row count change for client (inserts - loaded deletes)
361
+ const clientNetRowChange = ((_h = (_g = nextMessage.inserts) === null || _g === void 0 ? void 0 : _g.length) !== null && _h !== void 0 ? _h : 0) - loadedDeletes.length;
362
+ this.ssrmDatasource.clientRowsCount += clientNetRowChange;
379
363
  this.applyAllAgTransactions();
380
364
  }
381
- else {
382
- // TODO: Double-check this bit / DOM.queueUpdate do not work here
383
- setTimeout(() => {
384
- this.applyAllAgTransactions();
385
- }, timeoutInMs);
386
- }
387
365
  }
388
366
  });
389
367
  const onError = (error) => {
@@ -392,7 +370,7 @@ let GridProServerSideDatasource = class GridProServerSideDatasource extends Life
392
370
  this.handleErrors(((_a = error.receivedMessage) === null || _a === void 0 ? void 0 : _a.ERROR) || error.message, 'stream');
393
371
  };
394
372
  this.liveUpdatesStream = this.connect
395
- .stream(this.resourceName, () => { }, onError, existingParams !== null && existingParams !== void 0 ? existingParams : this.params)
373
+ .stream(this.resourceName, () => { }, onError, existingParams !== null && existingParams !== void 0 ? existingParams : this.datasource.dataserverOnlyParams)
396
374
  .subscribe((message) => streamOnMessage(message));
397
375
  // return this.connect.stream(
398
376
  // this.resourceName,
@@ -417,9 +395,16 @@ let GridProServerSideDatasource = class GridProServerSideDatasource extends Life
417
395
  getAgColumnDefs(fieldsMetadata) {
418
396
  return __awaiter(this, void 0, void 0, function* () {
419
397
  const colDefsFromGenesisData = this.generateColumnDefsFromMetadata(fieldsMetadata, getServerSideFilterParamsByFieldType);
420
- colDefsFromGenesisData.forEach((colDef) => {
421
- colDef.sortable = [].concat(...this.indexes.values()).includes(colDef.field);
422
- });
398
+ if (this.datasource.resourceType === ResourceType.DATASERVER) {
399
+ colDefsFromGenesisData.forEach((colDef) => {
400
+ colDef.sortable = [].concat(...this.indexes.values()).includes(colDef.field);
401
+ });
402
+ }
403
+ else {
404
+ colDefsFromGenesisData.forEach((colDef) => {
405
+ colDef.sortable = true;
406
+ });
407
+ }
423
408
  const colDefsMergedWithTemplateDefs = yield this.agGrid.mergeAllColumnDefsAndStates(colDefsFromGenesisData, true);
424
409
  return colDefsMergedWithTemplateDefs;
425
410
  });
@@ -440,6 +425,9 @@ __decorate([
440
425
  __decorate([
441
426
  attr({ mode: 'boolean', attribute: 'live-updates' })
442
427
  ], GridProServerSideDatasource.prototype, "liveUpdates", void 0);
428
+ __decorate([
429
+ attr({ attribute: 'paging-mode' })
430
+ ], GridProServerSideDatasource.prototype, "pagingMode", void 0);
443
431
  __decorate([
444
432
  observable
445
433
  ], GridProServerSideDatasource.prototype, "request", void 0);
@@ -1,7 +1,6 @@
1
1
  import { __awaiter, __decorate } from "tslib";
2
2
  import { Auth, Connect, logger, } from '@genesislcap/foundation-comms';
3
3
  import { UUID } from '@genesislcap/foundation-utils';
4
- import { getAvailableIndexes, getAvailableIndexFields } from '../utils';
5
4
  /**
6
5
  * Base class for server-side resource datasources used in Grid Pro SSRM implementations.
7
6
  * Provides common logic for filtering, sorting, and pagination.
@@ -10,6 +9,7 @@ import { getAvailableIndexes, getAvailableIndexFields } from '../utils';
10
9
  */
11
10
  export class BaseServerSideDatasource {
12
11
  constructor(options) {
12
+ var _a;
13
13
  this.rowData = new Map();
14
14
  /**
15
15
  * The number of rows in the grid. THIS DO NOT CONSIDER CRITERIA_MATCH scenarios.
@@ -36,13 +36,18 @@ export class BaseServerSideDatasource {
36
36
  this.rowId = options.rowId;
37
37
  this.pagination = options.pagination;
38
38
  this.zeroBasedViewNumber = options.zeroBasedViewNumber;
39
+ this.pagingMode = options.pagingMode;
40
+ this.criteriaOnlyRequest = (_a = options.criteriaOnlyRequest) !== null && _a !== void 0 ? _a : false;
39
41
  }
40
42
  getRows(params) {
41
43
  throw new Error('Method not implemented.');
42
44
  }
43
- setupFilteringAndSorting(params) {
45
+ /**
46
+ * Handles filtering setup for server-side datasources.
47
+ * Common logic used by both dataserver and req-rep implementations.
48
+ */
49
+ setupFiltering(params) {
44
50
  return __awaiter(this, void 0, void 0, function* () {
45
- var _a;
46
51
  const filterModelBeingApplied = params.request.filterModel;
47
52
  const filtersAreBeingApplied = Object.keys(filterModelBeingApplied).length > 0;
48
53
  const filtersAreGettingCleaned = Object.keys(filterModelBeingApplied).length === 0;
@@ -61,40 +66,17 @@ export class BaseServerSideDatasource {
61
66
  return;
62
67
  }
63
68
  }
64
- const toBeAppliedSortModel = params.request.sortModel;
65
- if (((_a = this.currentSortModel) === null || _a === void 0 ? void 0 : _a.length) !== toBeAppliedSortModel.length ||
66
- toBeAppliedSortModel.length > 0) {
67
- if (toBeAppliedSortModel.length === 0 && this.currentSortModel) {
68
- this.calculatedRowsCount = 0;
69
- this.currentSortModel = null;
70
- this.resourceParams.ORDER_BY = null;
71
- this.resourceParams.REVERSE = null;
72
- yield this.refreshDatasource(params);
73
- return;
74
- }
75
- else if (toBeAppliedSortModel.length > 0) {
76
- const coldIdBeingSorted = toBeAppliedSortModel[0].colId; // Not allowing multiple sorts by user
77
- const sortTypeBeingApplied = toBeAppliedSortModel[0].sort;
78
- const orderByAndToBeSortedColIds = this.getOrderByAndToBeSortedColIds(this.resourceIndexes, coldIdBeingSorted);
79
- if (!orderByAndToBeSortedColIds) {
80
- this.calculatedRowsCount = 0;
81
- const availableIndexes = getAvailableIndexes(this.resourceIndexes);
82
- const availableIndexFields = getAvailableIndexFields(this.resourceIndexes);
83
- logger.warn('The FIELD/column (${coldIdBeingSorted}) being sorted is not part of an INDEX, required for the [orderBy] operation. See https://learn.genesis.global/docs/database/data-types/index-entities/');
84
- logger.debug('Available indexes:', availableIndexes);
85
- logger.debug('Columns that can be sorted with the available indexes:', availableIndexFields);
86
- params.fail();
87
- return;
88
- }
89
- else if (JSON.stringify(toBeAppliedSortModel) !== JSON.stringify(this.currentSortModel)) {
90
- this.currentSortModel = toBeAppliedSortModel;
91
- this.resourceParams.ORDER_BY = orderByAndToBeSortedColIds.orderBy;
92
- this.resourceParams.REVERSE = sortTypeBeingApplied === 'desc' ? true : false;
93
- yield this.refreshDatasource(params);
94
- return;
95
- }
96
- }
97
- }
69
+ });
70
+ }
71
+ /**
72
+ * Legacy method that combines filtering and sorting.
73
+ * Kept for backward compatibility. New implementations should use setupFiltering and setupSorting directly.
74
+ * @deprecated Use setupFiltering() and setupSorting() separately instead
75
+ */
76
+ setupFilteringAndSorting(params) {
77
+ return __awaiter(this, void 0, void 0, function* () {
78
+ yield this.setupFiltering(params);
79
+ yield this.setupSorting(params);
98
80
  });
99
81
  }
100
82
  destroy() {
@@ -245,7 +227,7 @@ export class BaseServerSideDatasource {
245
227
  .filter((k) => this.currentFilterModel[k].filterType === filterType);
246
228
  }
247
229
  getPageNumber(start, recordsPerPage, totalRecords, zeroBasedViewNumber = true) {
248
- if (start > totalRecords) {
230
+ if (totalRecords !== undefined && start > totalRecords) {
249
231
  start = Math.floor((totalRecords - 1) / recordsPerPage) * recordsPerPage + 1;
250
232
  }
251
233
  const currentPageIndex = Math.ceil(start / recordsPerPage);
@@ -280,6 +262,22 @@ export class BaseServerSideDatasource {
280
262
  get isNotFirstViewNumber() {
281
263
  return this.zeroBasedViewNumber ? this.currentSequenceId > 0 : this.currentSequenceId > 1;
282
264
  }
265
+ /**
266
+ * Determines the effective paging mode based on criteriaOnlyRequest availability and user settings
267
+ */
268
+ getEffectivePagingMode() {
269
+ // If user explicitly set a paging mode
270
+ if (this.pagingMode) {
271
+ // If criteriaOnlyRequest is not available but user wants offsetBased, warn and use viewBased
272
+ if (this.pagingMode === 'offsetBased' && !this.criteriaOnlyRequest) {
273
+ logger.warn('offsetBased paging mode requires criteriaOnlyRequest support. Falling back to viewBased mode.');
274
+ return 'viewBased';
275
+ }
276
+ return this.pagingMode;
277
+ }
278
+ // Auto-determine based on criteriaOnlyRequest availability
279
+ return this.criteriaOnlyRequest ? 'offsetBased' : 'viewBased';
280
+ }
283
281
  }
284
282
  __decorate([
285
283
  Auth
@@ -1,6 +1,7 @@
1
1
  import { __awaiter } from "tslib";
2
2
  import { MessageType, dataServerResultFilter, logger, } from '@genesislcap/foundation-comms';
3
3
  import { DOM } from '@microsoft/fast-element';
4
+ import { getAvailableIndexes, getAvailableIndexFields } from '../utils';
4
5
  import { BaseServerSideDatasource } from './server-side.resource-base';
5
6
  /**
6
7
  * The DATASERVER IServerSideDatasource implementation, used for SSRM (Server-Side Row Model) in the grid.
@@ -24,7 +25,9 @@ export class DataserverServerSideDatasource extends BaseServerSideDatasource {
24
25
  }
25
26
  getRows(params) {
26
27
  return __awaiter(this, void 0, void 0, function* () {
27
- yield this.setupFilteringAndSorting(params);
28
+ // Use separated filtering and sorting setup
29
+ yield this.setupFiltering(params);
30
+ yield this.setupSorting(params);
28
31
  if (this.pagination && !this.isNewPageSize && this.currentSequenceId > 0) {
29
32
  params.success(this.lastSuccessRowData);
30
33
  return;
@@ -115,6 +118,49 @@ export class DataserverServerSideDatasource extends BaseServerSideDatasource {
115
118
  this.lastSuccessRowData = successRowData;
116
119
  params.success(successRowData);
117
120
  }
121
+ /**
122
+ * Dataserver-specific sorting setup that validates columns are part of an index.
123
+ * This is required because dataserver needs indexed columns for efficient sorting.
124
+ */
125
+ setupSorting(params) {
126
+ return __awaiter(this, void 0, void 0, function* () {
127
+ var _a;
128
+ const toBeAppliedSortModel = params.request.sortModel;
129
+ if (((_a = this.currentSortModel) === null || _a === void 0 ? void 0 : _a.length) !== toBeAppliedSortModel.length ||
130
+ toBeAppliedSortModel.length > 0) {
131
+ if (toBeAppliedSortModel.length === 0 && this.currentSortModel) {
132
+ this.calculatedRowsCount = 0;
133
+ this.currentSortModel = null;
134
+ this.resourceParams.ORDER_BY = null;
135
+ this.resourceParams.REVERSE = null;
136
+ yield this.refreshDatasource(params);
137
+ return;
138
+ }
139
+ else if (toBeAppliedSortModel.length > 0) {
140
+ const coldIdBeingSorted = toBeAppliedSortModel[0].colId; // Not allowing multiple sorts by user
141
+ const sortTypeBeingApplied = toBeAppliedSortModel[0].sort;
142
+ const orderByAndToBeSortedColIds = this.getOrderByAndToBeSortedColIds(this.resourceIndexes, coldIdBeingSorted);
143
+ if (!orderByAndToBeSortedColIds) {
144
+ this.calculatedRowsCount = 0;
145
+ const availableIndexes = getAvailableIndexes(this.resourceIndexes);
146
+ const availableIndexFields = getAvailableIndexFields(this.resourceIndexes);
147
+ logger.warn(`The FIELD/column (${coldIdBeingSorted}) being sorted is not part of an INDEX, required for the [orderBy] operation. See https://learn.genesis.global/docs/database/data-types/index-entities/`);
148
+ logger.debug('Available indexes:', availableIndexes);
149
+ logger.debug('Columns that can be sorted with the available indexes:', availableIndexFields);
150
+ params.fail();
151
+ return;
152
+ }
153
+ else if (JSON.stringify(toBeAppliedSortModel) !== JSON.stringify(this.currentSortModel)) {
154
+ this.currentSortModel = toBeAppliedSortModel;
155
+ this.resourceParams.ORDER_BY = orderByAndToBeSortedColIds.orderBy;
156
+ this.resourceParams.REVERSE = sortTypeBeingApplied === 'desc' ? true : false;
157
+ yield this.refreshDatasource(params);
158
+ return;
159
+ }
160
+ }
161
+ }
162
+ });
163
+ }
118
164
  destroy() {
119
165
  const _super = Object.create(null, {
120
166
  destroy: { get: () => super.destroy }
@@ -10,41 +10,84 @@ export class ReqRepServerSideDatasource extends BaseServerSideDatasource {
10
10
  constructor(options) {
11
11
  var _a;
12
12
  super(options);
13
+ // Track the total discovered row count when we reach the last page
14
+ this.discoveredTotalRowCount = null;
15
+ this.currentNextOffset = 0;
13
16
  this.createReqRepRequestFunc = options.createReqRepRequestFunc;
14
- if (!((_a = options.resourceParams) === null || _a === void 0 ? void 0 : _a.VIEW_NUMBER)) {
15
- this.resourceParams.VIEW_NUMBER = this.zeroBasedViewNumber ? 0 : 1;
17
+ const effectivePagingMode = this.getEffectivePagingMode();
18
+ // Initialize based on paging mode
19
+ if (effectivePagingMode === 'viewBased') {
20
+ if (!((_a = options.resourceParams) === null || _a === void 0 ? void 0 : _a.VIEW_NUMBER)) {
21
+ this.resourceParams.VIEW_NUMBER = this.zeroBasedViewNumber ? 0 : 1;
22
+ }
23
+ }
24
+ else {
25
+ // offsetBased
26
+ if (!options.resourceParams.OFFSET) {
27
+ this.resourceParams.OFFSET = 0;
28
+ }
16
29
  }
17
30
  }
18
31
  getRows(params) {
19
32
  return __awaiter(this, void 0, void 0, function* () {
20
33
  var _a;
21
- yield this.setupFilteringAndSorting(params);
34
+ // Use custom filtering and sorting setup for req-rep
35
+ yield this.setupFiltering(params);
36
+ yield this.setupSorting(params);
22
37
  if (this.pagination && !this.isNewPageSize && this.currentSequenceId > 0) {
23
38
  params.success(this.lastSuccessRowData);
24
39
  return;
25
40
  }
26
- if (this.currentSequenceId !== null && this.currentSequenceId >= 0 && this.moreRows) {
27
- if (this.pagination) {
28
- this.resourceParams.VIEW_NUMBER = this.getPageNumber(params.request.startRow, this.maxRows, this.maxView, this.zeroBasedViewNumber);
41
+ const effectivePagingMode = this.getEffectivePagingMode();
42
+ if (effectivePagingMode === 'viewBased') {
43
+ if (this.currentSequenceId !== null && this.currentSequenceId >= 0 && this.moreRows) {
44
+ if (this.pagination) {
45
+ this.resourceParams.VIEW_NUMBER = this.getPageNumber(params.request.startRow, this.maxRows, undefined, // Don't pass maxView as totalRecords since it's not a valid total count
46
+ this.zeroBasedViewNumber);
47
+ }
48
+ else {
49
+ this.resourceParams.VIEW_NUMBER += 1;
50
+ }
51
+ }
52
+ }
53
+ else {
54
+ // offsetBased
55
+ if (this.currentNextOffset > 0 && this.currentNextOffset !== params.request.startRow) {
56
+ this.resourceParams.OFFSET = this.currentNextOffset;
29
57
  }
30
58
  else {
31
- this.resourceParams.VIEW_NUMBER += 1;
59
+ this.resourceParams.OFFSET = params.request.startRow;
32
60
  }
33
61
  }
34
62
  const requestParams = {
35
- DETAILS: {
36
- CRITERIA_MATCH: this.resourceParams.CRITERIA_MATCH,
37
- MAX_ROWS: this.resourceParams.MAX_ROWS,
38
- VIEW_NUMBER: this.resourceParams.VIEW_NUMBER,
39
- },
63
+ DETAILS: this.buildRequestDetails(effectivePagingMode),
40
64
  };
41
65
  const requestResult = yield this.createReqRepRequestFunc(requestParams);
42
- // TODO: massive limitation on the GSF. It should return -1 if it's already the last view/record (but it doesn't, next will have 0 rows then the NEXT_VIEW=-1).
66
+ // Check if MORE_ROWS is available in the response (GSF 8.14+ only)
67
+ const hasMoreRowsInResult = 'MORE_ROWS' in requestResult;
43
68
  let isLastView = false;
44
- if (requestResult.NEXT_VIEW !== -1) {
45
- const preCheckRequestParams = Object.assign(Object.assign({}, requestParams), { DETAILS: Object.assign(Object.assign({}, requestParams.DETAILS), { VIEW_NUMBER: requestResult.NEXT_VIEW }) });
46
- const moreRowsPreCheck = yield this.createReqRepRequestFunc(preCheckRequestParams);
47
- isLastView = moreRowsPreCheck.NEXT_VIEW === -1 && ((_a = moreRowsPreCheck.REPLY) === null || _a === void 0 ? void 0 : _a.length) === 0;
69
+ // Fall back to the existing logic for backwards compatibility
70
+ if (effectivePagingMode === 'viewBased') {
71
+ // Massive limitation on the GSF. It should return -1 if it's already the last view/record (but it doesn't, next will have 0 rows then the NEXT_VIEW=-1).
72
+ if (hasMoreRowsInResult) {
73
+ // Only works with GSF 8.14+
74
+ isLastView = !requestResult.MORE_ROWS;
75
+ }
76
+ else if (requestResult.NEXT_VIEW !== -1) {
77
+ const preCheckRequestParams = Object.assign(Object.assign({}, requestParams), { DETAILS: Object.assign(Object.assign({}, requestParams.DETAILS), { VIEW_NUMBER: requestResult.NEXT_VIEW }) });
78
+ const moreRowsPreCheck = yield this.createReqRepRequestFunc(preCheckRequestParams);
79
+ isLastView = moreRowsPreCheck.NEXT_VIEW === -1 && ((_a = moreRowsPreCheck.REPLY) === null || _a === void 0 ? void 0 : _a.length) === 0;
80
+ }
81
+ }
82
+ else {
83
+ // offsetBased: check if NEXT_OFFSET exists and is valid
84
+ isLastView = hasMoreRowsInResult && !requestResult.MORE_ROWS;
85
+ if ('NEXT_OFFSET' in requestResult && requestResult.NEXT_OFFSET !== -1) {
86
+ this.currentNextOffset = requestResult.NEXT_OFFSET;
87
+ }
88
+ else {
89
+ this.currentNextOffset = 0;
90
+ }
48
91
  }
49
92
  let applyResult = true;
50
93
  if (applyResult) {
@@ -54,7 +97,7 @@ export class ReqRepServerSideDatasource extends BaseServerSideDatasource {
54
97
  });
55
98
  }
56
99
  applyServerSideData(params, result, isLastView) {
57
- var _a;
100
+ var _a, _b;
58
101
  const messageType = result.MESSAGE_TYPE;
59
102
  if (messageType &&
60
103
  (messageType === MessageType.LOGOFF_ACK || messageType === MessageType.MSG_NACK)) {
@@ -68,8 +111,27 @@ export class ReqRepServerSideDatasource extends BaseServerSideDatasource {
68
111
  params.fail();
69
112
  return;
70
113
  }
71
- this.moreRows =
72
- !isLastView && result.NEXT_VIEW !== -1 && result.NEXT_VIEW > this.resourceParams.VIEW_NUMBER;
114
+ const effectivePagingMode = this.getEffectivePagingMode();
115
+ // TODO: the code below will be tweaked/removed when gsf <8.14 is no longer supported
116
+ if ('MORE_ROWS' in result) {
117
+ this.moreRows = result.MORE_ROWS;
118
+ }
119
+ else {
120
+ // Fall back to the existing logic for backwards compatibility
121
+ if (effectivePagingMode === 'viewBased') {
122
+ this.moreRows =
123
+ !isLastView &&
124
+ result.NEXT_VIEW !== -1 &&
125
+ result.NEXT_VIEW > this.resourceParams.VIEW_NUMBER;
126
+ }
127
+ else {
128
+ // offsetBased
129
+ this.moreRows =
130
+ !isLastView &&
131
+ result.NEXT_OFFSET !== -1 &&
132
+ result.NEXT_OFFSET > this.resourceParams.OFFSET;
133
+ }
134
+ }
73
135
  if (result.REPLY) {
74
136
  this.handleCurrentStreamLoad(result.REPLY);
75
137
  }
@@ -80,9 +142,27 @@ export class ReqRepServerSideDatasource extends BaseServerSideDatasource {
80
142
  params.success(successRowData);
81
143
  return;
82
144
  }
83
- this.currentSequenceId = this.resourceParams.VIEW_NUMBER; // result.NEXT_VIEW > 0 ? result.NEXT_VIEW - 1 : 0;
145
+ // Update current sequence ID based on paging mode
146
+ if (effectivePagingMode === 'viewBased') {
147
+ this.currentSequenceId = this.resourceParams.VIEW_NUMBER;
148
+ }
149
+ else {
150
+ // For offsetBased, use OFFSET / maxRows to get the sequence
151
+ this.currentSequenceId = Math.floor(this.resourceParams.OFFSET / this.maxRows);
152
+ }
84
153
  this.sourceRef = result.SOURCE_REF;
85
- this.serverRowsCount += (_a = result.ROWS_COUNT) !== null && _a !== void 0 ? _a : this.rowData.size;
154
+ // For req-rep, store the total row count when we reach the last page
155
+ if (!this.moreRows) {
156
+ const currentBatchSize = this.rowData.size;
157
+ this.discoveredTotalRowCount = params.request.startRow + currentBatchSize;
158
+ }
159
+ // Reset serverRowsCount accumulation for req-rep pagination
160
+ if (this.pagination) {
161
+ this.serverRowsCount = (_a = result.ROWS_COUNT) !== null && _a !== void 0 ? _a : this.rowData.size;
162
+ }
163
+ else {
164
+ this.serverRowsCount += (_b = result.ROWS_COUNT) !== null && _b !== void 0 ? _b : this.rowData.size;
165
+ }
86
166
  const successRowData = {
87
167
  rowData: Array.from(this.rowData.values()),
88
168
  };
@@ -91,30 +171,25 @@ export class ReqRepServerSideDatasource extends BaseServerSideDatasource {
91
171
  params.success(successRowData);
92
172
  }
93
173
  getCorrectRowCount(params) {
94
- const lastRow = this.moreRows ? -1 : params.request.startRow + this.serverRowsCount;
95
- const currentLastRowNumber = params.request.endRow;
96
- this.calculatedRowsCount = this.serverRowsCount || currentLastRowNumber;
97
- const defaultCount = Math.min(lastRow, this.maxView);
98
174
  let rowCount;
99
175
  if (this.pagination) {
100
- rowCount = !this.resourceParams.CRITERIA_MATCH ? Math.min(lastRow, this.maxView) : undefined;
101
- if (this.resourceParams.CRITERIA_MATCH) {
102
- rowCount = defaultCount;
176
+ if (this.moreRows) {
177
+ // More data available, return -1 to indicate unknown total
178
+ rowCount = -1;
103
179
  }
104
- if (!this.moreRows && lastRow > this.calculatedRowsCount) {
105
- rowCount = this.calculatedRowsCount;
180
+ else {
181
+ // Use discovered total if available, otherwise calculate from current position
182
+ rowCount = this.discoveredTotalRowCount || params.request.startRow + this.rowData.size;
106
183
  }
107
184
  return rowCount;
108
185
  }
109
- if (currentLastRowNumber === lastRow) {
110
- rowCount = lastRow;
111
- }
112
- else if (currentLastRowNumber > this.maxView ||
113
- currentLastRowNumber > this.calculatedRowsCount) {
114
- rowCount = Math.min(defaultCount, this.calculatedRowsCount);
186
+ // Non-pagination mode (streaming)
187
+ if (this.moreRows) {
188
+ rowCount = -1; // More data available, unknown total
115
189
  }
116
- else if (!this.moreRows && lastRow > this.calculatedRowsCount) {
117
- rowCount = this.calculatedRowsCount;
190
+ else {
191
+ // Use discovered total or calculate from current batch
192
+ rowCount = this.discoveredTotalRowCount || params.request.startRow + this.rowData.size;
118
193
  }
119
194
  return rowCount;
120
195
  }
@@ -136,4 +211,64 @@ export class ReqRepServerSideDatasource extends BaseServerSideDatasource {
136
211
  });
137
212
  this.rowData = rows;
138
213
  }
214
+ /**
215
+ * Req-rep specific sorting setup that allows any column to be sorted
216
+ * (unlike dataserver which requires indexed columns only)
217
+ */
218
+ setupSorting(params) {
219
+ return __awaiter(this, void 0, void 0, function* () {
220
+ var _a;
221
+ const toBeAppliedSortModel = params.request.sortModel;
222
+ if (((_a = this.currentSortModel) === null || _a === void 0 ? void 0 : _a.length) !== toBeAppliedSortModel.length ||
223
+ toBeAppliedSortModel.length > 0) {
224
+ if (toBeAppliedSortModel.length === 0 && this.currentSortModel) {
225
+ this.calculatedRowsCount = 0;
226
+ this.currentSortModel = null;
227
+ this.resourceParams.ORDER_BY = undefined;
228
+ yield this.refreshDatasource(params);
229
+ return;
230
+ }
231
+ else if (toBeAppliedSortModel.length > 0) {
232
+ const coldIdBeingSorted = toBeAppliedSortModel[0].colId; // Not allowing multiple sorts by user
233
+ const sortTypeBeingApplied = toBeAppliedSortModel[0].sort;
234
+ // For req-rep, we can sort by any column without requiring it to be part of an index
235
+ if (JSON.stringify(toBeAppliedSortModel) !== JSON.stringify(this.currentSortModel)) {
236
+ this.currentSortModel = toBeAppliedSortModel;
237
+ this.resourceParams.ORDER_BY =
238
+ coldIdBeingSorted + (sortTypeBeingApplied === 'desc' ? ' DESC' : ' ASC'); // Use the column directly
239
+ yield this.refreshDatasource(params);
240
+ return;
241
+ }
242
+ }
243
+ }
244
+ });
245
+ }
246
+ refreshDatasource(params) {
247
+ const _super = Object.create(null, {
248
+ refreshDatasource: { get: () => super.refreshDatasource }
249
+ });
250
+ return __awaiter(this, void 0, void 0, function* () {
251
+ // Reset discovered total when refreshing (sorting/filtering changes)
252
+ this.discoveredTotalRowCount = null;
253
+ this.currentNextOffset = 0;
254
+ // Reset pagination parameters to start from beginning
255
+ this.resourceParams.VIEW_NUMBER = this.zeroBasedViewNumber ? 0 : 1;
256
+ this.resourceParams.OFFSET = 0;
257
+ yield _super.refreshDatasource.call(this, params);
258
+ });
259
+ }
260
+ buildRequestDetails(effectivePagingMode) {
261
+ const baseDetails = {
262
+ CRITERIA_MATCH: this.resourceParams.CRITERIA_MATCH,
263
+ MAX_ROWS: this.resourceParams.MAX_ROWS,
264
+ ORDER_BY: this.resourceParams.ORDER_BY,
265
+ };
266
+ if (effectivePagingMode === 'viewBased') {
267
+ return Object.assign(Object.assign({}, baseDetails), { VIEW_NUMBER: this.resourceParams.VIEW_NUMBER });
268
+ }
269
+ else {
270
+ // offsetBased
271
+ return Object.assign(Object.assign({}, baseDetails), { OFFSET: this.resourceParams.OFFSET });
272
+ }
273
+ }
139
274
  }