@genesislcap/grid-tabulator 14.262.1 → 14.263.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 (135) hide show
  1. package/dist/custom-elements.json +2613 -117
  2. package/dist/dts/cell/cell.d.ts +50 -0
  3. package/dist/dts/cell/cell.d.ts.map +1 -0
  4. package/dist/dts/cell/index.d.ts +1 -1
  5. package/dist/dts/cell/index.d.ts.map +1 -1
  6. package/dist/dts/cell-editors/date.editor.d.ts +75 -0
  7. package/dist/dts/cell-editors/date.editor.d.ts.map +1 -0
  8. package/dist/dts/cell-editors/index.d.ts +6 -0
  9. package/dist/dts/cell-editors/index.d.ts.map +1 -0
  10. package/dist/dts/cell-editors/multiselect.editor.d.ts +79 -0
  11. package/dist/dts/cell-editors/multiselect.editor.d.ts.map +1 -0
  12. package/dist/dts/cell-editors/number.editor.d.ts +76 -0
  13. package/dist/dts/cell-editors/number.editor.d.ts.map +1 -0
  14. package/dist/dts/cell-editors/select.editor.d.ts +83 -0
  15. package/dist/dts/cell-editors/select.editor.d.ts.map +1 -0
  16. package/dist/dts/cell-editors/string.editor.d.ts +67 -0
  17. package/dist/dts/cell-editors/string.editor.d.ts.map +1 -0
  18. package/dist/dts/cell-formatters/action.formatter.d.ts +45 -0
  19. package/dist/dts/cell-formatters/action.formatter.d.ts.map +1 -0
  20. package/dist/dts/cell-formatters/actions-menu.formatter.d.ts +57 -0
  21. package/dist/dts/cell-formatters/actions-menu.formatter.d.ts.map +1 -0
  22. package/dist/dts/cell-formatters/boolean.formatter.d.ts +27 -0
  23. package/dist/dts/cell-formatters/boolean.formatter.d.ts.map +1 -0
  24. package/dist/dts/cell-formatters/constants.d.ts +31 -0
  25. package/dist/dts/cell-formatters/constants.d.ts.map +1 -0
  26. package/dist/dts/cell-formatters/editable.formatter.d.ts +40 -0
  27. package/dist/dts/cell-formatters/editable.formatter.d.ts.map +1 -0
  28. package/dist/dts/cell-formatters/index.d.ts +27 -0
  29. package/dist/dts/cell-formatters/index.d.ts.map +1 -0
  30. package/dist/dts/cell-formatters/select.formatter.d.ts +43 -0
  31. package/dist/dts/cell-formatters/select.formatter.d.ts.map +1 -0
  32. package/dist/dts/cell-formatters/text.formatter.d.ts +36 -0
  33. package/dist/dts/cell-formatters/text.formatter.d.ts.map +1 -0
  34. package/dist/dts/column/column.d.ts +340 -0
  35. package/dist/dts/column/column.d.ts.map +1 -0
  36. package/dist/dts/column/index.d.ts +1 -1
  37. package/dist/dts/column/index.d.ts.map +1 -1
  38. package/dist/dts/datasource/client-side.datasource.d.ts +42 -16
  39. package/dist/dts/datasource/client-side.datasource.d.ts.map +1 -1
  40. package/dist/dts/grid-tabulator.components.d.ts +52 -4
  41. package/dist/dts/grid-tabulator.components.d.ts.map +1 -1
  42. package/dist/dts/grid-tabulator.d.ts +119 -11
  43. package/dist/dts/grid-tabulator.d.ts.map +1 -1
  44. package/dist/dts/grid-tabulator.definitions.d.ts +35 -0
  45. package/dist/dts/grid-tabulator.definitions.d.ts.map +1 -1
  46. package/dist/dts/grid-tabulator.styles.d.ts.map +1 -1
  47. package/dist/dts/grid-tabulator.types.d.ts +13 -1
  48. package/dist/dts/grid-tabulator.types.d.ts.map +1 -1
  49. package/dist/dts/index.d.ts +3 -1
  50. package/dist/dts/index.d.ts.map +1 -1
  51. package/dist/dts/types.d.ts +27 -0
  52. package/dist/dts/types.d.ts.map +1 -0
  53. package/dist/dts/utils/index.d.ts +1 -0
  54. package/dist/dts/utils/index.d.ts.map +1 -1
  55. package/dist/dts/utils/string-utils.d.ts +17 -0
  56. package/dist/dts/utils/string-utils.d.ts.map +1 -0
  57. package/dist/esm/cell/cell.js +66 -0
  58. package/dist/esm/cell/index.js +1 -1
  59. package/dist/esm/cell-editors/date.editor.js +92 -0
  60. package/dist/esm/cell-editors/index.js +5 -0
  61. package/dist/esm/cell-editors/multiselect.editor.js +105 -0
  62. package/dist/esm/cell-editors/number.editor.js +84 -0
  63. package/dist/esm/cell-editors/select.editor.js +91 -0
  64. package/dist/esm/cell-editors/string.editor.js +82 -0
  65. package/dist/esm/cell-formatters/action.formatter.js +73 -0
  66. package/dist/esm/cell-formatters/actions-menu.formatter.js +68 -0
  67. package/dist/esm/cell-formatters/boolean.formatter.js +25 -0
  68. package/dist/esm/cell-formatters/constants.js +31 -0
  69. package/dist/esm/cell-formatters/editable.formatter.js +21 -0
  70. package/dist/esm/cell-formatters/index.js +26 -0
  71. package/dist/esm/cell-formatters/select.formatter.js +32 -0
  72. package/dist/esm/cell-formatters/text.formatter.js +30 -0
  73. package/dist/esm/column/column.js +51 -0
  74. package/dist/esm/column/index.js +1 -1
  75. package/dist/esm/datasource/client-side.datasource.js +219 -91
  76. package/dist/esm/grid-tabulator.components.js +24 -11
  77. package/dist/esm/grid-tabulator.definitions.js +30 -0
  78. package/dist/esm/grid-tabulator.js +392 -27
  79. package/dist/esm/grid-tabulator.styles.js +15 -0
  80. package/dist/esm/grid-tabulator.types.js +13 -0
  81. package/dist/esm/index.js +1 -1
  82. package/dist/esm/types.js +1 -0
  83. package/dist/esm/utils/index.js +1 -0
  84. package/dist/esm/utils/string-utils.js +32 -0
  85. package/dist/grid-tabulator.api.json +1703 -466
  86. package/dist/grid-tabulator.d.ts +1237 -124
  87. package/docs/api/grid-tabulator.actionformatter.md +27 -0
  88. package/docs/api/grid-tabulator.actionsmenuformatter.md +27 -0
  89. package/docs/api/grid-tabulator.booleanformatter.md +27 -0
  90. package/docs/api/grid-tabulator.cellrendererfunc.md +15 -0
  91. package/docs/api/grid-tabulator.cellrendererparams.cell.md +13 -0
  92. package/docs/api/grid-tabulator.cellrendererparams.data.md +13 -0
  93. package/docs/api/grid-tabulator.cellrendererparams.formatterparams.md +13 -0
  94. package/docs/api/grid-tabulator.cellrendererparams.md +23 -0
  95. package/docs/api/grid-tabulator.cellrendererparams.value.md +13 -0
  96. package/docs/api/grid-tabulator.editableformatter.md +27 -0
  97. package/docs/api/grid-tabulator.foundationgridtabulatorcomponents.md +50 -4
  98. package/docs/api/grid-tabulator.gridtabulatorcell.connectedcallback.md +15 -0
  99. package/docs/api/grid-tabulator.gridtabulatorcell.destroy.md +15 -0
  100. package/docs/api/grid-tabulator.gridtabulatorcell.getelement.md +15 -0
  101. package/docs/api/grid-tabulator.gridtabulatorcell.init.md +22 -0
  102. package/docs/api/grid-tabulator.gridtabulatorcell.md +38 -0
  103. package/docs/api/grid-tabulator.gridtabulatorcell.refresh.md +22 -0
  104. package/docs/api/grid-tabulator.gridtabulatorcell.renderer.md +11 -0
  105. package/docs/api/grid-tabulator.gridtabulatorcell.rendererparams.md +11 -0
  106. package/docs/api/grid-tabulator.gridtabulatorcell.slottedrenderer.md +11 -0
  107. package/docs/api/grid-tabulator.gridtabulatorcell.slottedrendererchanged.md +15 -0
  108. package/docs/api/grid-tabulator.gridtabulatorcelleditortypes.md +24 -0
  109. package/docs/api/grid-tabulator.gridtabulatorcellrenderertypes.md +1 -0
  110. package/docs/api/grid-tabulator.gridtabulatorcolumn.deepclone.md +15 -0
  111. package/docs/api/grid-tabulator.gridtabulatorcolumn.definition.md +11 -0
  112. package/docs/api/grid-tabulator.gridtabulatorcolumn.md +33 -0
  113. package/docs/api/grid-tabulator.gridtabulatorcolumn.slottedcell.md +11 -0
  114. package/docs/api/grid-tabulator.gridtabulatorcolumn.slottedcellchanged.md +15 -0
  115. package/docs/api/grid-tabulator.md +11 -5
  116. package/docs/api/grid-tabulator.selectformatter.md +27 -0
  117. package/docs/api/grid-tabulator.textformatter.md +27 -0
  118. package/docs/api-report.md +328 -36
  119. package/package.json +16 -15
  120. package/dist/dts/cell-renderers/action.renderer.d.ts +0 -80
  121. package/dist/dts/cell-renderers/action.renderer.d.ts.map +0 -1
  122. package/dist/dts/cell-renderers/index.d.ts +0 -2
  123. package/dist/dts/cell-renderers/index.d.ts.map +0 -1
  124. package/dist/esm/cell-renderers/action.renderer.js +0 -107
  125. package/dist/esm/cell-renderers/index.js +0 -1
  126. package/docs/api/grid-tabulator.actionheightmultiplier.md +0 -18
  127. package/docs/api/grid-tabulator.actionrenderer.clickhandler.md +0 -15
  128. package/docs/api/grid-tabulator.actionrenderer.datatestid.md +0 -11
  129. package/docs/api/grid-tabulator.actionrenderer.init.md +0 -22
  130. package/docs/api/grid-tabulator.actionrenderer.md +0 -30
  131. package/docs/api/grid-tabulator.actionrenderer.params.md +0 -11
  132. package/docs/api/grid-tabulator.actionrenderer.pendingaction.md +0 -11
  133. package/docs/api/grid-tabulator.actionrendererparams.md +0 -26
  134. package/docs/api/grid-tabulator.foundationgridtabulatoractionrenderer.md +0 -26
  135. package/docs/api/grid-tabulator.tabulatoractionrendererstyles.md +0 -13
@@ -0,0 +1,51 @@
1
+ import { __decorate } from "tslib";
2
+ import { LifecycleMixin } from '@genesislcap/foundation-utils';
3
+ import { css, customElement, html, observable } from '@microsoft/fast-element';
4
+ import { FoundationElement } from '@microsoft/fast-foundation';
5
+ /**
6
+ * The GridTabulator Column element.
7
+ * @remarks Used inside the GridTabulator element to specify column definitions for a given column.
8
+ * @public
9
+ */
10
+ let GridTabulatorColumn = class GridTabulatorColumn extends LifecycleMixin(FoundationElement) {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.definition = {};
14
+ }
15
+ slottedCellChanged() { }
16
+ deepClone() {
17
+ const copy = super.deepClone();
18
+ copy.definition = {};
19
+ if (this.definition) {
20
+ Object.keys(this.definition).forEach((key) => {
21
+ if (typeof this.definition[key] === 'function') {
22
+ copy.definition[key] = this.definition[key].bind(copy);
23
+ }
24
+ else {
25
+ copy.definition[key] = structuredClone(this.definition[key]);
26
+ }
27
+ });
28
+ }
29
+ return copy;
30
+ }
31
+ };
32
+ __decorate([
33
+ observable
34
+ ], GridTabulatorColumn.prototype, "slottedCell", void 0);
35
+ __decorate([
36
+ observable
37
+ ], GridTabulatorColumn.prototype, "definition", void 0);
38
+ GridTabulatorColumn = __decorate([
39
+ customElement({
40
+ name: 'grid-tabulator-column',
41
+ template: html `
42
+ <slot></slot>
43
+ `,
44
+ styles: css `
45
+ :host {
46
+ display: none;
47
+ }
48
+ `,
49
+ })
50
+ ], GridTabulatorColumn);
51
+ export { GridTabulatorColumn };
@@ -1 +1 @@
1
- export {};
1
+ export * from './column';
@@ -1,15 +1,26 @@
1
1
  import { __awaiter, __decorate } from "tslib";
2
- import { Auth, Connect, dataServerResultFilter, Datasource, DatasourceEventHandler, DatasourceDefaults, MessageType, normaliseCriteria, ResourceType, } from '@genesislcap/foundation-comms';
2
+ import { Auth, Connect, dataServerResultFilter, Datasource, DatasourceEventHandler, DatasourceDefaults, FieldTypeEnum, MessageType, normaliseCriteria, ResourceType, } from '@genesislcap/foundation-comms';
3
3
  import { LifecycleMixin } from '@genesislcap/foundation-utils';
4
4
  import { attr, customElement, DOM, observable } from '@microsoft/fast-element';
5
5
  import { FoundationElement } from '@microsoft/fast-foundation';
6
6
  import { BehaviorSubject } from 'rxjs';
7
7
  import { debounceTime, skip, tap } from 'rxjs/operators';
8
- import { logger } from '../utils/logger';
9
- const criteriaDelimiter = ';';
10
- const criteriaJoin = ' && ';
8
+ import { dateTimeValueFormatter, dateValueFormatter } from '../grid-tabulator.definitions';
9
+ import { gridTabulatorEventNames } from '../grid-tabulator.definitions';
10
+ import { logger, mergeAndDedupColDefWithColumnState } from '../utils';
11
+ /**
12
+ * Delimiter for criteria in the datasource
13
+ * @alpha
14
+ */
15
+ export const criteriaDelimiter = ';';
16
+ /**
17
+ * Join operator for criteria in the datasource
18
+ * @alpha
19
+ */
20
+ export const criteriaJoin = ' && ';
11
21
  const withoutFullInit = null;
12
22
  const withoutColumnDefs = null;
23
+ const DEBOUNCE_INTERVAL_MS = 1000;
13
24
  /**
14
25
  * The Genesis Datasource element, for client-side data fetching and used exclusively by the GridTabulator element.
15
26
  * @alpha
@@ -17,6 +28,10 @@ const withoutColumnDefs = null;
17
28
  let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource extends LifecycleMixin(DatasourceEventHandler(FoundationElement)) {
18
29
  constructor() {
19
30
  super(...arguments);
31
+ /**
32
+ * Allows storing column layouts between datasource initializations
33
+ */
34
+ this.deferredColumnStates = [];
20
35
  this.isSnapshot = false;
21
36
  this.maxRows = DatasourceDefaults.MAX_ROWS_250;
22
37
  this.maxView = DatasourceDefaults.MAX_VIEW_1000;
@@ -24,6 +39,10 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
24
39
  this.movingView = false;
25
40
  this.reverse = false;
26
41
  this.restartOnReconnection = true;
42
+ /**
43
+ * Whether to keep column definitions when clearing row data
44
+ */
45
+ this.keepColDefsOnClearRowData = false;
27
46
  this.isRequestServer = false;
28
47
  this.requiresFullRowDataAndColDefs = true;
29
48
  this.dataSubWasLoggedOff = false;
@@ -42,9 +61,6 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
42
61
  return;
43
62
  this.restart();
44
63
  }
45
- datasourceStatusChanged(prev, next) {
46
- this.isRequestServer = next.type === ResourceType.REQUEST_SERVER;
47
- }
48
64
  connectedCallback() {
49
65
  super.connectedCallback();
50
66
  const shouldRunConnect = this.shouldRunConnect;
@@ -77,6 +93,8 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
77
93
  }
78
94
  deepClone() {
79
95
  const copy = super.deepClone();
96
+ copy.deferredGridOptions = structuredClone(this.deferredGridOptions);
97
+ copy.deferredColumnStates = structuredClone(this.deferredColumnStates);
80
98
  copy.request = structuredClone(this.request);
81
99
  return copy;
82
100
  }
@@ -105,6 +123,10 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
105
123
  this.rowIdAttr === DatasourceDefaults.REQUEST_SERVER_ROW_ID ||
106
124
  this.rowIdAttr === DatasourceDefaults.DATASERVER_ROW_ID);
107
125
  }
126
+ /**
127
+ * Returns the default row ID based on the resource type
128
+ * @internal
129
+ */
108
130
  get defaultRowIdByResourceType() {
109
131
  return this.isRequestServer
110
132
  ? DatasourceDefaults.REQUEST_SERVER_ROW_ID
@@ -118,17 +140,7 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
118
140
  init() {
119
141
  return __awaiter(this, void 0, void 0, function* () {
120
142
  if (this.gridTabulator) {
121
- this.gridTabulator.gridOptions = Object.assign({ index: this.rowId,
122
- // getRowId: (params) => params.data[this.rowId],
123
- layout: 'fitDataFill',
124
- // responsiveLayout: 'hide', // hide columns that dont fit on the table
125
- addRowPos: 'top',
126
- // history: true, // allow undo and redo actions on the table
127
- movableColumns: true, height: '100%', renderHorizontal: 'virtual',
128
- // columnDefaults: {
129
- // tooltip: true, // show tool tips on cells
130
- // },
131
- autoColumns: true, rowContextMenu: [
143
+ const gridOptions = Object.assign({ index: this.rowId, layout: 'fitDataFill', movableColumns: true, height: '100%', renderHorizontal: 'virtual', autoColumns: false, rowContextMenu: [
132
144
  {
133
145
  label: 'Download CSV',
134
146
  action: (e, column) => {
@@ -136,6 +148,7 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
136
148
  },
137
149
  },
138
150
  ], popupContainer: false }, this.deferredGridOptions);
151
+ this.gridTabulator.gridOptions = gridOptions;
139
152
  const filterDebounceTime = 600;
140
153
  this.updateSub = this.update
141
154
  .pipe(skip(1), debounceTime(filterDebounceTime), tap((f) => logger.debug('filters (debounced): ', f)))
@@ -145,6 +158,7 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
145
158
  return;
146
159
  }
147
160
  logger.warn(`Application not connected, datasource will not work. Falling back to local columnDefs/rowData.`);
161
+ this.handleErrors('Application not connected or datasource not initialized');
148
162
  });
149
163
  }
150
164
  /**
@@ -152,7 +166,7 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
152
166
  * @public
153
167
  */
154
168
  destroy() {
155
- var _a;
169
+ var _a, _b, _c;
156
170
  if (this.dataSub) {
157
171
  this.dataSub.unsubscribe();
158
172
  this.dataSub = undefined;
@@ -173,8 +187,12 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
173
187
  this.criteriaFromFilters = new Map();
174
188
  (_a = this.update) === null || _a === void 0 ? void 0 : _a.unsubscribe();
175
189
  this.update = new BehaviorSubject(new Map());
190
+ // IMPORTANT: Save column states before destroying the datasource
191
+ if ((_b = this.gridTabulator) === null || _b === void 0 ? void 0 : _b.grid) {
192
+ this.deferredColumnStates = this.gridTabulator.grid.getColumnLayout();
193
+ }
176
194
  // TODO: There may need to be a full destroy path. Datasources need some love!
177
- this.datasource.destroy();
195
+ (_c = this.datasource) === null || _c === void 0 ? void 0 : _c.destroy();
178
196
  }
179
197
  /**
180
198
  * Restarts the datasource, uses `deinit` and `init` in sequence.
@@ -199,24 +217,96 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
199
217
  clearRowData(withColumnDefs = true) {
200
218
  var _a, _b, _c, _d;
201
219
  this.rows = new Map();
202
- if (withColumnDefs) {
220
+ if (withColumnDefs && !this.keepColDefsOnClearRowData) {
203
221
  (_b = (_a = this.gridTabulator) === null || _a === void 0 ? void 0 : _a.grid) === null || _b === void 0 ? void 0 : _b.setColumns([]);
204
222
  }
205
223
  (_d = (_c = this.gridTabulator) === null || _c === void 0 ? void 0 : _c.grid) === null || _d === void 0 ? void 0 : _d.clearData();
206
224
  }
225
+ /**
226
+ * Handles errors by emitting an error event
227
+ */
228
+ handleErrors(errors) {
229
+ let message;
230
+ if (Array.isArray(errors)) {
231
+ const stringArray = errors.map((item) => {
232
+ if (typeof item === 'string') {
233
+ return item;
234
+ }
235
+ else if (typeof item === 'object' && item !== null && 'TEXT' in item) {
236
+ return item.TEXT;
237
+ }
238
+ else {
239
+ throw new Error('Array contains invalid elements');
240
+ }
241
+ });
242
+ message = stringArray.join(', ');
243
+ }
244
+ else {
245
+ message = errors;
246
+ }
247
+ if (this.gridTabulator) {
248
+ this.gridTabulator.setAttribute('ds-disconnected', 'ds-disconnected');
249
+ }
250
+ if (message) {
251
+ logger.error(message);
252
+ this.$emit(gridTabulatorEventNames.error, { message });
253
+ }
254
+ }
207
255
  /**
208
256
  * Sets the columnDefs and rowData for the grid.
209
257
  * @remarks This should only happen once, when the grid is first initialized. Follow up updates will use the agTransaction.
210
258
  * @internal
211
259
  */
212
260
  setRowData(rowData) {
213
- const agColumnDefs = null; // this.getAgColumnDefs(this.datasource.fieldMetadata);
214
- if (agColumnDefs) {
215
- this.gridTabulator.grid.setColumns(agColumnDefs);
216
- }
217
- const data = this.rowDataMapper ? this.rowDataMapper(rowData) : rowData;
218
- this.gridTabulator.grid.setData(data);
219
- this.requiresFullRowDataAndColDefs = false;
261
+ var _a;
262
+ return __awaiter(this, void 0, void 0, function* () {
263
+ const preExistingColumns = (_a = this.gridTabulator.grid) === null || _a === void 0 ? void 0 : _a.getColumns();
264
+ if (!preExistingColumns || preExistingColumns.length === 0) {
265
+ const columnDefs = yield this.getColumnDefs(this.datasource.fieldMetadata);
266
+ if (columnDefs) {
267
+ this.gridTabulator.grid.setColumns(columnDefs);
268
+ }
269
+ }
270
+ const data = this.rowDataMapper ? this.rowDataMapper(rowData) : rowData;
271
+ this.gridTabulator.grid.setData(data);
272
+ this.requiresFullRowDataAndColDefs = false;
273
+ });
274
+ }
275
+ /**
276
+ * Generate column definitions from the field metadata
277
+ * @param fieldsMetadata - The field metadata to generate column definitions from
278
+ */
279
+ getColumnDefs(fieldsMetadata) {
280
+ return __awaiter(this, void 0, void 0, function* () {
281
+ const columnDefsFromMetadata = fieldsMetadata === null || fieldsMetadata === void 0 ? void 0 : fieldsMetadata.map((field) => {
282
+ const columnDef = {
283
+ field: field.name,
284
+ title: field.name, // Default title is the field name
285
+ };
286
+ // Apply field-specific configurations
287
+ switch (field.type) {
288
+ case FieldTypeEnum.BOOLEAN:
289
+ if (this.gridTabulator.autoCellRendererByType) {
290
+ columnDef.formatter = 'boolean';
291
+ }
292
+ break;
293
+ case FieldTypeEnum.DATE:
294
+ columnDef.formatter = (cell) => dateValueFormatter({ value: cell.getValue() });
295
+ break;
296
+ case FieldTypeEnum.DATETIME:
297
+ columnDef.formatter = (cell) => dateTimeValueFormatter({ value: cell.getValue() });
298
+ break;
299
+ default:
300
+ break;
301
+ }
302
+ return columnDef;
303
+ });
304
+ // Merge with any saved column state
305
+ if (this.deferredColumnStates && this.deferredColumnStates.length > 0) {
306
+ return mergeAndDedupColDefWithColumnState(columnDefsFromMetadata, this.deferredColumnStates);
307
+ }
308
+ return columnDefsFromMetadata;
309
+ });
220
310
  }
221
311
  /**
222
312
  * Resets the grid data while keeping columnDefs and sends a DATA_LOGOFF message if it's a stream.
@@ -244,37 +334,56 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
244
334
  loadResourceData(withFullInit = true) {
245
335
  return __awaiter(this, void 0, void 0, function* () {
246
336
  const requiresMetadataFetch = withFullInit || !this.datasource.initialized;
247
- const initOK = yield this.datasource.init(this.datasourceOptions(), requiresMetadataFetch);
248
- if (!initOK) {
249
- logger.debug(`Genesis Datasource init failed for ${this.resourceName}`);
250
- this.clearRowData();
251
- return;
252
- }
253
- if (this.isSnapshot) {
254
- const result = yield this.datasource.snapshot();
255
- if (result) {
256
- const rowData = this.handleSnapshot(result);
257
- this.setRowData(rowData);
258
- }
259
- return;
260
- }
261
- logger.debug(`requesting stream for ${this.resourceName}`);
262
- this.dataSub = this.datasource.stream.subscribe((result) => {
263
- this.sourceRef = result.SOURCE_REF;
264
- const messageType = result.MESSAGE_TYPE;
265
- if (messageType && messageType === MessageType.LOGOFF_ACK) {
266
- this.dataSubWasLoggedOff = true;
337
+ try {
338
+ const initOK = yield this.datasource.init(this.datasourceOptions(), requiresMetadataFetch);
339
+ if (!initOK) {
340
+ logger.debug(`Genesis Datasource init failed for ${this.resourceName}`);
341
+ this.clearRowData();
342
+ this.handleErrors(`Genesis Datasource init failed for ${this.resourceName}`);
267
343
  return;
268
344
  }
269
- this.dataSubWasLoggedOff = false;
270
- if (result.ROW) {
271
- const nextMessage = dataServerResultFilter(result);
272
- this.handleStreamResult(nextMessage);
345
+ this.$emit('dataInit');
346
+ if (this.isSnapshot) {
347
+ const result = yield this.datasource.snapshot();
348
+ if (result) {
349
+ const rowData = this.handleSnapshot(result);
350
+ this.setRowData(rowData);
351
+ }
352
+ return;
273
353
  }
274
- else {
275
- this.handleStreamResult(result);
354
+ logger.debug(`requesting stream for ${this.resourceName}`);
355
+ this.dataSub = this.datasource.stream.subscribe((result) => {
356
+ if (result === null || result === void 0 ? void 0 : result.ERROR) {
357
+ this.handleErrors(result.ERROR);
358
+ return;
359
+ }
360
+ this.sourceRef = result.SOURCE_REF;
361
+ const messageType = result.MESSAGE_TYPE;
362
+ if (messageType && messageType === MessageType.LOGOFF_ACK) {
363
+ this.dataSubWasLoggedOff = true;
364
+ return;
365
+ }
366
+ this.dataSubWasLoggedOff = false;
367
+ if (result.ROW) {
368
+ const nextMessage = dataServerResultFilter(result);
369
+ this.handleStreamResult(nextMessage);
370
+ }
371
+ else {
372
+ this.handleStreamResult(result);
373
+ }
374
+ }, (error) => {
375
+ logger.error('Stream error:', error);
376
+ this.handleErrors((error === null || error === void 0 ? void 0 : error.message) || 'Stream error occurred');
377
+ });
378
+ }
379
+ catch (error) {
380
+ let errorMessage = (error === null || error === void 0 ? void 0 : error.message) || 'Unknown error occurred';
381
+ if (error.receivedMessage) {
382
+ errorMessage = error.receivedMessage.ERROR;
276
383
  }
277
- });
384
+ logger.error(errorMessage);
385
+ this.handleErrors(errorMessage);
386
+ }
278
387
  });
279
388
  }
280
389
  handleSnapshot(result) {
@@ -315,6 +424,7 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
315
424
  }
316
425
  applyRequestServerData(requestServerResult) {
317
426
  var _a;
427
+ const previousSize = this.rows.size;
318
428
  const requestServerData = requestServerResult.REPLY;
319
429
  if (!Array.isArray(requestServerData) ||
320
430
  !((_a = requestServerResult.MESSAGE_TYPE) === null || _a === void 0 ? void 0 : _a.startsWith('REP_'))) {
@@ -322,10 +432,26 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
322
432
  return;
323
433
  }
324
434
  if (this.requiresFullRowDataAndColDefs) {
435
+ let noRowIdError = false;
325
436
  requestServerData === null || requestServerData === void 0 ? void 0 : requestServerData.forEach((insertData) => {
326
- this.rows.set(insertData[this.rowId], insertData);
437
+ const insertDataRowId = insertData[this.rowId];
438
+ if (!insertDataRowId) {
439
+ if (!noRowIdError) {
440
+ const noRowIdMessage = `The specified rowId (${this.rowId}) is not present in the data. Since this is not a snapshot (isSnapshot=false), the data will not be loaded. Please provide a valid 'row-id' attribute.`;
441
+ logger.error(noRowIdMessage);
442
+ this.handleErrors(noRowIdMessage);
443
+ noRowIdError = true;
444
+ }
445
+ return;
446
+ }
447
+ this.rows.set(insertDataRowId, insertData);
327
448
  });
449
+ if (noRowIdError) {
450
+ this.destroy();
451
+ return;
452
+ }
328
453
  const rowData = this.rows.size > 0 ? Array.from(this.rows.values()) : requestServerData;
454
+ this.handleSizeChanged(previousSize, this.rows.size);
329
455
  this.setRowData(rowData);
330
456
  return;
331
457
  }
@@ -344,15 +470,18 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
344
470
  this.handleStreamDeletes(rowsToDelete);
345
471
  this.handleStreamUpdates(rowsToUpdate);
346
472
  this.applyTransaction();
473
+ this.handleSizeChanged(previousSize, this.rows.size);
347
474
  }
348
475
  applyDataserverData(dataServerResult) {
349
476
  var _a;
477
+ const previousSize = this.rows.size;
350
478
  if (this.requiresFullRowDataAndColDefs) {
351
479
  (_a = dataServerResult.inserts) === null || _a === void 0 ? void 0 : _a.forEach((insertData) => {
352
480
  this.rows.set(insertData[this.rowId], insertData);
353
481
  });
354
482
  const rowData = Array.from(this.rows.values());
355
483
  this.setRowData(rowData);
484
+ this.handleSizeChanged(previousSize, this.rows.size);
356
485
  return;
357
486
  }
358
487
  this.gridTransaction = { add: [], remove: [], update: [] };
@@ -360,6 +489,7 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
360
489
  this.handleStreamDeletes(dataServerResult.deletes);
361
490
  this.handleStreamUpdates(dataServerResult.updates);
362
491
  this.applyTransaction();
492
+ this.handleSizeChanged(previousSize, this.rows.size);
363
493
  }
364
494
  applyTransaction() {
365
495
  var _a, _b;
@@ -369,6 +499,19 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
369
499
  }
370
500
  if (((_b = transaction.update) === null || _b === void 0 ? void 0 : _b.length) > 0) {
371
501
  this.gridTabulator.grid.updateData(transaction.update);
502
+ // Apply row flashing if enabled
503
+ if (this.gridTabulator.enableRowFlashing) {
504
+ transaction.update.forEach((row) => {
505
+ const rowElement = this.gridTabulator.grid.getRow(row[this.rowId]);
506
+ if (rowElement) {
507
+ // Apply flash effect by adding a CSS class and then removing it
508
+ rowElement.getElement().classList.add('tabulator-row-flash');
509
+ setTimeout(() => {
510
+ rowElement.getElement().classList.remove('tabulator-row-flash');
511
+ }, DEBOUNCE_INTERVAL_MS);
512
+ }
513
+ });
514
+ }
372
515
  }
373
516
  transaction.remove.forEach((toRemove) => {
374
517
  this.gridTabulator.grid.deleteRow(toRemove[this.rowId]);
@@ -422,41 +565,17 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
422
565
  this.rows.set(updateData[this.rowId], updatedRow);
423
566
  });
424
567
  }
425
- // FUTURE: Work with the field types vs ag grid column def types!
426
- // private getAgColumnDefs(fieldsMetadata: FieldMetadata[]) {
427
- // const colDefsFromGenesisData: ColDef[] = fieldsMetadata?.flatMap((field: FieldMetadata) => {
428
- // const cellConfigs: ColDef = {};
429
- // cellConfigs.filterParams = getFilterParamsByFieldType(field.type);
430
- // switch (field.type) {
431
- // case FieldTypeEnum.BOOLEAN:
432
- // if (this.gridTabulator.autoCellRendererByType) {
433
- // cellConfigs.cellRenderer = GridTabulatorCellRendererTypes.boolean;
434
- // }
435
- // break;
436
- // case FieldTypeEnum.DATE:
437
- // cellConfigs.valueFormatter = dateValueFormatter;
438
- // break;
439
- // case FieldTypeEnum.DATETIME:
440
- // cellConfigs.valueFormatter = dateTimeValueFormatter;
441
- // break;
442
- // default:
443
- // break;
444
- // }
445
- // const templateColDef = this.gridTabulator.gridApi?.getColumnDef(field.name);
446
- // if (this.gridTabulator.onlyTemplateColDefs && !templateColDef) {
447
- // return [];
448
- // }
449
- // if (this.fields && !this.fields.includes(field.name)) {
450
- // return [];
451
- // }
452
- // return { field: field.name, ...cellConfigs, ...templateColDef };
453
- // });
454
- // const colDefsMergedWithTemplateDefs = this.gridTabulator.mergeAllColumnDefsAndStates(
455
- // colDefsFromGenesisData,
456
- // true,
457
- // );
458
- // return colDefsMergedWithTemplateDefs;
459
- // }
568
+ /**
569
+ * Emit event when the number of rows changes
570
+ */
571
+ handleSizeChanged(oldSize, newSize) {
572
+ if (oldSize === newSize)
573
+ return;
574
+ this.$emit('sizeChanged', {
575
+ value: newSize,
576
+ oldValue: oldSize,
577
+ });
578
+ }
460
579
  buildCriteria() {
461
580
  var _a;
462
581
  const initialCriteria = ((_a = this.criteria) === null || _a === void 0 ? void 0 : _a.split(criteriaDelimiter)) || [];
@@ -471,6 +590,9 @@ let GridTabulatorClientSideDatasource = class GridTabulatorClientSideDatasource
471
590
  this.criteriaFromFilters.delete(fieldName);
472
591
  this.update.next(this.criteriaFromFilters);
473
592
  }
593
+ datasourceStatusChanged(prev, next) {
594
+ this.isRequestServer = next.type === ResourceType.REQUEST_SERVER;
595
+ }
474
596
  };
475
597
  __decorate([
476
598
  Auth
@@ -484,6 +606,9 @@ __decorate([
484
606
  __decorate([
485
607
  observable
486
608
  ], GridTabulatorClientSideDatasource.prototype, "deferredGridOptions", void 0);
609
+ __decorate([
610
+ observable
611
+ ], GridTabulatorClientSideDatasource.prototype, "deferredColumnStates", void 0);
487
612
  __decorate([
488
613
  attr
489
614
  ], GridTabulatorClientSideDatasource.prototype, "criteria", void 0);
@@ -523,6 +648,9 @@ __decorate([
523
648
  __decorate([
524
649
  attr({ mode: 'boolean', attribute: 'restart-on-reconnection' })
525
650
  ], GridTabulatorClientSideDatasource.prototype, "restartOnReconnection", void 0);
651
+ __decorate([
652
+ attr({ mode: 'boolean', attribute: 'keep-col-defs-on-clear-row-data' })
653
+ ], GridTabulatorClientSideDatasource.prototype, "keepColDefsOnClearRowData", void 0);
526
654
  __decorate([
527
655
  observable
528
656
  ], GridTabulatorClientSideDatasource.prototype, "rowDataMapper", void 0);
@@ -1,20 +1,33 @@
1
- import { foundationGridTabulatorActionRenderer,
2
- // foundationGridProActionsMenuRenderer,
3
- // foundationAgBooleanRenderer,
4
- // foundationAgSelectRenderer,
5
- // foundationAgTextRenderer,
6
- } from './cell-renderers';
1
+ import { GridTabulatorCell } from './cell/cell';
2
+ import { foundationDateEditor } from './cell-editors/date.editor';
3
+ import { foundationMultiselectEditor } from './cell-editors/multiselect.editor';
4
+ import { foundationNumberEditor } from './cell-editors/number.editor';
5
+ import { foundationSelectEditor } from './cell-editors/select.editor';
6
+ import { foundationStringEditor } from './cell-editors/string.editor';
7
+ import { GridTabulatorColumn } from './column/column';
7
8
  import { foundationGridTabulator } from './grid-tabulator';
9
+ // Create component registration functions
10
+ const foundationGridTabulatorColumn = GridTabulatorColumn.compose({
11
+ baseName: 'grid-tabulator-column',
12
+ });
13
+ const foundationGridTabulatorCell = GridTabulatorCell.compose({
14
+ baseName: 'grid-tabulator-cell',
15
+ });
8
16
  /**
9
17
  * All `grid-tabulator` components.
10
18
  * @public
11
19
  */
12
20
  export const foundationGridTabulatorComponents = {
13
- foundationGridTabulatorActionRenderer,
14
- // foundationGridProActionsMenuRenderer,
15
- // foundationAgBooleanRenderer,
16
- // foundationAgTextRenderer,
17
- // foundationAgSelectRenderer,
21
+ // Cell editors
22
+ foundationDateEditor,
23
+ foundationNumberEditor,
24
+ foundationSelectEditor,
25
+ foundationStringEditor,
26
+ foundationMultiselectEditor,
27
+ // Column components
28
+ foundationGridTabulatorColumn,
29
+ foundationGridTabulatorCell,
30
+ // Grid component
18
31
  foundationGridTabulator,
19
32
  register(container, ...rest) {
20
33
  if (!container) {
@@ -1,4 +1,34 @@
1
1
  import { formatDateTimestamp, formatDateTimeTimestamp } from '@genesislcap/foundation-utils';
2
+ /**
3
+ * Event names for grid-tabulator
4
+ * @alpha
5
+ */
6
+ export const gridTabulatorEventNames = {
7
+ error: 'gridTabulator:error',
8
+ datasourceErrorClose: 'gridTabulator:datasourceErrorClose',
9
+ };
10
+ /**
11
+ * Error types for grid-tabulator
12
+ * @alpha
13
+ */
14
+ export const gridTabulatorErrorNames = {
15
+ datasource: 'datasource',
16
+ };
17
+ /**
18
+ * The special column field name for marking a cell as edited
19
+ * @alpha
20
+ */
21
+ export const EDITED_COLUMN_FIELD = '__EDITED_FIELD__';
22
+ /**
23
+ * The special column field name for marking a cell as having an error
24
+ * @alpha
25
+ */
26
+ export const ERROR_COLUMN_FIELD = '__ERROR_FIELD__';
27
+ /**
28
+ * Time in milliseconds to debounce resize events
29
+ * @alpha
30
+ */
31
+ export const DEBOUNCED_RESIZE_TIME = 400;
2
32
  /**
3
33
  * Get the filter type based on the field type.
4
34
  * @param type - The field type.