@deephaven/iris-grid 0.13.3-beta.2 → 0.13.5

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 (184) hide show
  1. package/dist/AdvancedFilterCreator.d.ts +63 -69
  2. package/dist/AdvancedFilterCreator.d.ts.map +1 -1
  3. package/dist/AdvancedFilterCreator.js +73 -79
  4. package/dist/AdvancedFilterCreator.js.map +1 -1
  5. package/dist/AdvancedFilterCreatorSelectValue.d.ts +45 -45
  6. package/dist/AdvancedFilterCreatorSelectValue.d.ts.map +1 -1
  7. package/dist/AdvancedFilterCreatorSelectValue.js +36 -32
  8. package/dist/AdvancedFilterCreatorSelectValue.js.map +1 -1
  9. package/dist/AdvancedFilterCreatorSelectValueList.d.ts +52 -47
  10. package/dist/AdvancedFilterCreatorSelectValueList.d.ts.map +1 -1
  11. package/dist/AdvancedFilterCreatorSelectValueList.js +39 -24
  12. package/dist/AdvancedFilterCreatorSelectValueList.js.map +1 -1
  13. package/dist/ColumnStatistics.d.ts +22 -34
  14. package/dist/ColumnStatistics.d.ts.map +1 -1
  15. package/dist/ColumnStatistics.js +12 -8
  16. package/dist/ColumnStatistics.js.map +1 -1
  17. package/dist/CrossColumnSearch.d.ts +24 -26
  18. package/dist/CrossColumnSearch.d.ts.map +1 -1
  19. package/dist/CrossColumnSearch.js +13 -9
  20. package/dist/CrossColumnSearch.js.map +1 -1
  21. package/dist/FilterInputField.d.ts +51 -48
  22. package/dist/FilterInputField.d.ts.map +1 -1
  23. package/dist/FilterInputField.js +27 -30
  24. package/dist/FilterInputField.js.map +1 -1
  25. package/dist/IrisGrid.d.ts +453 -409
  26. package/dist/IrisGrid.d.ts.map +1 -1
  27. package/dist/IrisGrid.js +449 -514
  28. package/dist/IrisGrid.js.map +1 -1
  29. package/dist/IrisGridCellOverflowModal.d.ts +1 -1
  30. package/dist/IrisGridCellOverflowModal.d.ts.map +1 -1
  31. package/dist/IrisGridCellOverflowModal.js.map +1 -1
  32. package/dist/IrisGridCopyHandler.d.ts +46 -52
  33. package/dist/IrisGridCopyHandler.d.ts.map +1 -1
  34. package/dist/IrisGridCopyHandler.js +38 -22
  35. package/dist/IrisGridCopyHandler.js.map +1 -1
  36. package/dist/IrisGridMetricCalculator.d.ts +4 -5
  37. package/dist/IrisGridMetricCalculator.d.ts.map +1 -1
  38. package/dist/IrisGridMetricCalculator.js +1 -5
  39. package/dist/IrisGridMetricCalculator.js.map +1 -1
  40. package/dist/IrisGridModel.d.ts +35 -37
  41. package/dist/IrisGridModel.d.ts.map +1 -1
  42. package/dist/IrisGridModel.js +3 -19
  43. package/dist/IrisGridModel.js.map +1 -1
  44. package/dist/IrisGridModelFactory.d.ts +5 -7
  45. package/dist/IrisGridModelFactory.d.ts.map +1 -1
  46. package/dist/IrisGridModelFactory.js +5 -5
  47. package/dist/IrisGridModelFactory.js.map +1 -1
  48. package/dist/IrisGridModelUpdater.d.ts +11 -13
  49. package/dist/IrisGridModelUpdater.d.ts.map +1 -1
  50. package/dist/IrisGridModelUpdater.js.map +1 -1
  51. package/dist/IrisGridPartitionSelector.d.ts +39 -38
  52. package/dist/IrisGridPartitionSelector.d.ts.map +1 -1
  53. package/dist/IrisGridPartitionSelector.js +24 -18
  54. package/dist/IrisGridPartitionSelector.js.map +1 -1
  55. package/dist/IrisGridProxyModel.d.ts +32 -111
  56. package/dist/IrisGridProxyModel.d.ts.map +1 -1
  57. package/dist/IrisGridProxyModel.js +170 -212
  58. package/dist/IrisGridProxyModel.js.map +1 -1
  59. package/dist/IrisGridRenderer.d.ts +31 -59
  60. package/dist/IrisGridRenderer.d.ts.map +1 -1
  61. package/dist/IrisGridRenderer.js +46 -92
  62. package/dist/IrisGridRenderer.js.map +1 -1
  63. package/dist/IrisGridTableModel.d.ts +147 -48
  64. package/dist/IrisGridTableModel.d.ts.map +1 -1
  65. package/dist/IrisGridTableModel.js +1381 -58
  66. package/dist/IrisGridTableModel.js.map +1 -1
  67. package/dist/IrisGridTestUtils.d.ts +14 -18
  68. package/dist/IrisGridTestUtils.d.ts.map +1 -1
  69. package/dist/IrisGridTestUtils.js +1 -29
  70. package/dist/IrisGridTestUtils.js.map +1 -1
  71. package/dist/IrisGridTheme.d.ts +3 -35
  72. package/dist/IrisGridTheme.d.ts.map +1 -1
  73. package/dist/IrisGridTheme.js.map +1 -1
  74. package/dist/IrisGridTreeTableModel.d.ts +7 -26
  75. package/dist/IrisGridTreeTableModel.d.ts.map +1 -1
  76. package/dist/IrisGridTreeTableModel.js +14 -24
  77. package/dist/IrisGridTreeTableModel.js.map +1 -1
  78. package/dist/IrisGridUtils.d.ts +162 -257
  79. package/dist/IrisGridUtils.d.ts.map +1 -1
  80. package/dist/IrisGridUtils.js +95 -132
  81. package/dist/IrisGridUtils.js.map +1 -1
  82. package/dist/MissingKeyError.d.ts +3 -5
  83. package/dist/MissingKeyError.d.ts.map +1 -1
  84. package/dist/MissingKeyError.js.map +1 -1
  85. package/dist/PartitionSelectorSearch.d.ts +40 -61
  86. package/dist/PartitionSelectorSearch.d.ts.map +1 -1
  87. package/dist/PartitionSelectorSearch.js +15 -25
  88. package/dist/PartitionSelectorSearch.js.map +1 -1
  89. package/dist/PendingDataBottomBar.d.ts +6 -3
  90. package/dist/PendingDataBottomBar.d.ts.map +1 -1
  91. package/dist/PendingDataBottomBar.js.map +1 -1
  92. package/dist/TableViewportUpdater.d.ts +55 -39
  93. package/dist/TableViewportUpdater.d.ts.map +1 -1
  94. package/dist/TableViewportUpdater.js +64 -42
  95. package/dist/TableViewportUpdater.js.map +1 -1
  96. package/dist/TreeTableViewportUpdater.d.ts +37 -29
  97. package/dist/TreeTableViewportUpdater.d.ts.map +1 -1
  98. package/dist/TreeTableViewportUpdater.js +50 -39
  99. package/dist/TreeTableViewportUpdater.js.map +1 -1
  100. package/dist/index.d.ts +0 -9
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +0 -9
  103. package/dist/index.js.map +1 -1
  104. package/dist/mousehandlers/IrisGridCellOverflowMouseHandler.d.ts.map +1 -1
  105. package/dist/mousehandlers/IrisGridCellOverflowMouseHandler.js.map +1 -1
  106. package/dist/mousehandlers/IrisGridColumnSelectMouseHandler.d.ts +1 -1
  107. package/dist/mousehandlers/IrisGridColumnSelectMouseHandler.d.ts.map +1 -1
  108. package/dist/mousehandlers/IrisGridColumnSelectMouseHandler.js +0 -2
  109. package/dist/mousehandlers/IrisGridColumnSelectMouseHandler.js.map +1 -1
  110. package/dist/mousehandlers/IrisGridColumnTooltipMouseHandler.js +1 -1
  111. package/dist/mousehandlers/IrisGridColumnTooltipMouseHandler.js.map +1 -1
  112. package/dist/mousehandlers/IrisGridContextMenuHandler.d.ts +130 -41
  113. package/dist/mousehandlers/IrisGridContextMenuHandler.d.ts.map +1 -1
  114. package/dist/mousehandlers/IrisGridContextMenuHandler.js +317 -426
  115. package/dist/mousehandlers/IrisGridContextMenuHandler.js.map +1 -1
  116. package/dist/mousehandlers/IrisGridFilterMouseHandler.d.ts.map +1 -1
  117. package/dist/mousehandlers/IrisGridFilterMouseHandler.js +2 -2
  118. package/dist/mousehandlers/IrisGridFilterMouseHandler.js.map +1 -1
  119. package/dist/mousehandlers/IrisGridSortMouseHandler.js +1 -1
  120. package/dist/mousehandlers/IrisGridSortMouseHandler.js.map +1 -1
  121. package/dist/mousehandlers/PendingMouseHandler.d.ts +4 -8
  122. package/dist/mousehandlers/PendingMouseHandler.d.ts.map +1 -1
  123. package/dist/mousehandlers/PendingMouseHandler.js +5 -4
  124. package/dist/mousehandlers/PendingMouseHandler.js.map +1 -1
  125. package/dist/sidebar/ChartBuilder.d.ts +33 -48
  126. package/dist/sidebar/ChartBuilder.d.ts.map +1 -1
  127. package/dist/sidebar/ChartBuilder.js +27 -28
  128. package/dist/sidebar/ChartBuilder.js.map +1 -1
  129. package/dist/sidebar/CustomColumnBuilder.d.ts +41 -51
  130. package/dist/sidebar/CustomColumnBuilder.d.ts.map +1 -1
  131. package/dist/sidebar/CustomColumnBuilder.js +18 -22
  132. package/dist/sidebar/CustomColumnBuilder.js.map +1 -1
  133. package/dist/sidebar/CustomColumnInput.d.ts +36 -26
  134. package/dist/sidebar/CustomColumnInput.d.ts.map +1 -1
  135. package/dist/sidebar/CustomColumnInput.js +20 -11
  136. package/dist/sidebar/CustomColumnInput.js.map +1 -1
  137. package/dist/sidebar/InputEditor.d.ts +35 -34
  138. package/dist/sidebar/InputEditor.d.ts.map +1 -1
  139. package/dist/sidebar/InputEditor.js +24 -43
  140. package/dist/sidebar/InputEditor.js.map +1 -1
  141. package/dist/sidebar/RollupRows.d.ts +52 -67
  142. package/dist/sidebar/RollupRows.d.ts.map +1 -1
  143. package/dist/sidebar/RollupRows.js +53 -51
  144. package/dist/sidebar/RollupRows.js.map +1 -1
  145. package/dist/sidebar/SelectDistinctBuilder.d.ts +21 -27
  146. package/dist/sidebar/SelectDistinctBuilder.d.ts.map +1 -1
  147. package/dist/sidebar/SelectDistinctBuilder.js +10 -6
  148. package/dist/sidebar/SelectDistinctBuilder.js.map +1 -1
  149. package/dist/sidebar/TableCsvExporter.d.ts +39 -42
  150. package/dist/sidebar/TableCsvExporter.d.ts.map +1 -1
  151. package/dist/sidebar/TableCsvExporter.js +20 -12
  152. package/dist/sidebar/TableCsvExporter.js.map +1 -1
  153. package/dist/sidebar/TableSaver.d.ts +60 -59
  154. package/dist/sidebar/TableSaver.d.ts.map +1 -1
  155. package/dist/sidebar/TableSaver.js +68 -154
  156. package/dist/sidebar/TableSaver.js.map +1 -1
  157. package/dist/sidebar/VisibilityOrderingBuilder.d.ts +45 -56
  158. package/dist/sidebar/VisibilityOrderingBuilder.d.ts.map +1 -1
  159. package/dist/sidebar/VisibilityOrderingBuilder.js +29 -34
  160. package/dist/sidebar/VisibilityOrderingBuilder.js.map +1 -1
  161. package/dist/sidebar/aggregations/Aggregations.d.ts.map +1 -1
  162. package/dist/sidebar/aggregations/Aggregations.js.map +1 -1
  163. package/dist/sidebar/conditional-formatting/ConditionalFormattingMenu.d.ts +1 -2
  164. package/dist/sidebar/conditional-formatting/ConditionalFormattingMenu.d.ts.map +1 -1
  165. package/dist/sidebar/conditional-formatting/ConditionalFormattingMenu.js.map +1 -1
  166. package/dist/sidebar/conditional-formatting/ConditionalFormattingUtils.d.ts +5 -6
  167. package/dist/sidebar/conditional-formatting/ConditionalFormattingUtils.d.ts.map +1 -1
  168. package/dist/sidebar/conditional-formatting/ConditionalFormattingUtils.js +0 -5
  169. package/dist/sidebar/conditional-formatting/ConditionalFormattingUtils.js.map +1 -1
  170. package/dist/sidebar/icons/index.d.ts +7 -7
  171. package/dist/sidebar/icons/index.d.ts.map +1 -1
  172. package/dist/sidebar/icons/index.js.map +1 -1
  173. package/dist/sidebar/index.d.ts +12 -12
  174. package/dist/sidebar/index.d.ts.map +1 -1
  175. package/dist/sidebar/index.js.map +1 -1
  176. package/package.json +16 -17
  177. package/dist/CommonTypes.d.ts +0 -58
  178. package/dist/CommonTypes.d.ts.map +0 -1
  179. package/dist/CommonTypes.js +0 -2
  180. package/dist/CommonTypes.js.map +0 -1
  181. package/dist/IrisGridTableModelTemplate.d.ts +0 -219
  182. package/dist/IrisGridTableModelTemplate.d.ts.map +0 -1
  183. package/dist/IrisGridTableModelTemplate.js +0 -1623
  184. package/dist/IrisGridTableModelTemplate.js.map +0 -1
@@ -1,3 +1,7 @@
1
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
2
+
3
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
4
+
1
5
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
2
6
 
3
7
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
@@ -6,49 +10,285 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
6
10
 
7
11
  /* eslint class-methods-use-this: "off" */
8
12
  import memoize from 'memoize-one';
9
- import { GridRange, GridUtils } from '@deephaven/grid';
13
+ import throttle from 'lodash.throttle';
14
+ import { GridRange, GridUtils, memoizeClear } from '@deephaven/grid';
15
+ import dh from '@deephaven/jsapi-shim';
16
+ import { Formatter, FormatterUtils, TableUtils } from '@deephaven/jsapi-utils';
10
17
  import Log from '@deephaven/log';
11
- import { Formatter, TableUtils } from '@deephaven/jsapi-utils';
12
- import { EventShimCustomEvent, PromiseUtils, assertNotNull } from '@deephaven/utils';
18
+ import { PromiseUtils } from '@deephaven/utils';
13
19
  import IrisGridModel from "./IrisGridModel.js";
14
- import IrisGridTableModelTemplate from "./IrisGridTableModelTemplate.js";
20
+ import AggregationOperation from "./sidebar/aggregations/AggregationOperation.js";
21
+ import IrisGridUtils from "./IrisGridUtils.js";
22
+ import MissingKeyError from "./MissingKeyError.js";
15
23
  var log = Log.module('IrisGridTableModel');
16
- var EMPTY_ARRAY = Object.freeze([]);
24
+ var SET_VIEWPORT_THROTTLE = 150;
25
+ var APPLY_VIEWPORT_THROTTLE = 0;
17
26
  /**
18
27
  * Model for a grid showing an iris data table
19
28
  */
20
29
 
21
- class IrisGridTableModel extends IrisGridTableModelTemplate {
30
+ class IrisGridTableModel extends IrisGridModel {
22
31
  /**
23
- * @param table Iris data table to be used in the model
24
- * @param formatter The formatter to use when getting formats
25
- * @param inputTable Iris input table associated with this table
32
+ * @param {dh.Table} table Iris data table to be used in the model
33
+ * @param {Formatter} formatter The formatter to use when getting formats
34
+ * @param {dh.InputTable} inputTable Iris input table associated with this table
26
35
  */
27
36
  constructor(table) {
28
- var formatter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Formatter();
29
- var inputTable = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
30
- super(table, formatter, inputTable);
31
-
32
- _defineProperty(this, "userFrozenColumns", void 0);
37
+ var _formatter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Formatter();
33
38
 
34
- _defineProperty(this, "customColumnList", void 0);
39
+ var inputTable = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
40
+ super();
35
41
 
36
- _defineProperty(this, "formatColumnList", void 0);
42
+ _defineProperty(this, "getMemoizedColumnMap", memoize(tableColumns => {
43
+ var columnMap = new Map();
44
+ tableColumns.forEach(col => columnMap.set(col.name, col));
45
+ return columnMap;
46
+ }));
37
47
 
38
- _defineProperty(this, "getMemoizedFrontColumns", memoize(layoutHintsFrontColumns => layoutHintsFrontColumns !== null && layoutHintsFrontColumns !== void 0 ? layoutHintsFrontColumns : EMPTY_ARRAY));
48
+ _defineProperty(this, "getMemoizedFrontColumns", memoize(layoutHintsFrontColumns => layoutHintsFrontColumns !== null && layoutHintsFrontColumns !== void 0 ? layoutHintsFrontColumns : []));
39
49
 
40
- _defineProperty(this, "getMemoizedBackColumns", memoize(layoutHintsBackColumns => layoutHintsBackColumns !== null && layoutHintsBackColumns !== void 0 ? layoutHintsBackColumns : EMPTY_ARRAY));
50
+ _defineProperty(this, "getMemoizedBackColumns", memoize(layoutHintsBackColumns => layoutHintsBackColumns !== null && layoutHintsBackColumns !== void 0 ? layoutHintsBackColumns : []));
41
51
 
42
52
  _defineProperty(this, "getMemoizedFrozenColumns", memoize((layoutHintsFrozenColumns, userFrozenColumns) => {
43
53
  var _ref;
44
54
 
45
- return (_ref = userFrozenColumns !== null && userFrozenColumns !== void 0 ? userFrozenColumns : layoutHintsFrozenColumns) !== null && _ref !== void 0 ? _ref : EMPTY_ARRAY;
55
+ return (_ref = userFrozenColumns !== null && userFrozenColumns !== void 0 ? userFrozenColumns : layoutHintsFrozenColumns) !== null && _ref !== void 0 ? _ref : [];
56
+ }));
57
+
58
+ _defineProperty(this, "getColumnIndicesByNameMap", memoize(columns => {
59
+ var indices = new Map();
60
+ columns.forEach((_ref2, i) => {
61
+ var {
62
+ name
63
+ } = _ref2;
64
+ return indices.set(name, i);
65
+ });
66
+ return indices;
46
67
  }));
47
68
 
48
69
  _defineProperty(this, "getCachedFilterableColumnSet", memoize(columns => new Set(columns.map((_, index) => index))));
49
70
 
71
+ _defineProperty(this, "getCachedFormattedString", memoizeClear((formatter, value, columnType, columnName, formatOverride) => formatter.getFormattedString(value, columnType, columnName, formatOverride), {
72
+ max: 10000
73
+ }));
74
+
75
+ _defineProperty(this, "getCachedCustomColumnFormatFlag", memoizeClear(FormatterUtils.isCustomColumnFormatDefined, {
76
+ max: 10000
77
+ }));
78
+
79
+ _defineProperty(this, "getCachedViewportRowRange", memoize((top, bottom) => {
80
+ var viewHeight = bottom - top;
81
+ var viewportTop = Math.max(0, top - viewHeight * IrisGridTableModel.ROW_BUFFER_PAGES);
82
+ var viewportBottom = bottom + viewHeight * IrisGridTableModel.ROW_BUFFER_PAGES;
83
+ return [viewportTop, viewportBottom];
84
+ }));
85
+
86
+ _defineProperty(this, "getCachedPendingErrors", memoize((pendingDataMap, columns, keyColumnCount) => {
87
+ var map = new Map();
88
+ pendingDataMap.forEach((row, rowIndex) => {
89
+ var {
90
+ data: rowData
91
+ } = row;
92
+
93
+ for (var i = 0; i < keyColumnCount; i += 1) {
94
+ if (!rowData.has(i)) {
95
+ if (!map.has(rowIndex)) {
96
+ map.set(rowIndex, []);
97
+ }
98
+
99
+ map.get(rowIndex).push(new MissingKeyError(rowIndex, columns[i].name));
100
+ }
101
+ }
102
+ });
103
+ return map;
104
+ }));
105
+
106
+ this.handleTableDisconnect = this.handleTableDisconnect.bind(this);
107
+ this.handleTableReconnect = this.handleTableReconnect.bind(this);
108
+ this.handleTableUpdate = this.handleTableUpdate.bind(this);
109
+ this.handleTotalsUpdate = this.handleTotalsUpdate.bind(this);
110
+ this.handleRequestFailed = this.handleRequestFailed.bind(this);
111
+ this.handleCustomColumnsChanged = this.handleCustomColumnsChanged.bind(this);
112
+ this.setViewport = throttle(this.setViewport.bind(this), SET_VIEWPORT_THROTTLE);
113
+ this.applyViewport = throttle(this.applyViewport.bind(this), APPLY_VIEWPORT_THROTTLE, {
114
+ leading: false
115
+ });
116
+ this.irisFormatter = _formatter;
117
+ this.inputTable = inputTable;
118
+ this.listenerCount = 0;
119
+ this.subscription = null;
120
+ this.table = table;
121
+ this.viewport = null;
122
+ this.viewportData = null;
123
+ this.formattedStringData = [];
124
+ this.pendingStringData = [];
125
+ this.isSaveInProgress = false;
126
+ this.totalsTable = null;
127
+ this.totalsTablePromise = null;
128
+ this.totals = null;
129
+ this.totalsDataMap = null;
50
130
  this.customColumnList = [];
51
- this.formatColumnList = [];
131
+ this.formatColumnList = []; // Map from new row index to their values. Only for input tables that can have new rows added.
132
+ // The index of these rows start at 0, and they are appended at the end of the regular table data.
133
+ // These rows can be sparse, so using a map instead of an array.
134
+
135
+ this.pendingNewDataMap = new Map();
136
+ this.pendingNewRowCount = 0;
137
+ this.userFrozenColumns = null;
138
+ }
139
+
140
+ close() {
141
+ this.table.close();
142
+
143
+ if (this.totalsTable !== null) {
144
+ this.totalsTable.close();
145
+ }
146
+
147
+ if (this.totalsTablePromise !== null) {
148
+ this.totalsTablePromise.cancel();
149
+ }
150
+ }
151
+
152
+ startListening() {
153
+ super.startListening();
154
+ this.table.addEventListener(dh.Table.EVENT_DISCONNECT, this.handleTableDisconnect);
155
+ this.table.addEventListener(dh.Table.EVENT_RECONNECT, this.handleTableReconnect);
156
+ this.table.addEventListener(dh.Table.EVENT_UPDATED, this.handleTableUpdate);
157
+ this.table.addEventListener(dh.Client.EVENT_REQUEST_FAILED, this.handleRequestFailed);
158
+ this.table.addEventListener(dh.Table.EVENT_CUSTOMCOLUMNSCHANGED, this.handleCustomColumnsChanged);
159
+
160
+ if (this.totalsTable != null) {
161
+ this.addTotalsListeners(this.totalsTable);
162
+ }
163
+
164
+ this.applyViewport();
165
+ }
166
+
167
+ stopListening() {
168
+ super.stopListening();
169
+ this.table.removeEventListener(dh.Table.EVENT_DISCONNECT, this.handleTableDisconnect);
170
+ this.table.removeEventListener(dh.Table.EVENT_RECONNECT, this.handleTableReconnect);
171
+ this.table.removeEventListener(dh.Table.EVENT_UPDATED, this.handleTableUpdate);
172
+ this.table.removeEventListener(dh.Client.EVENT_REQUEST_FAILED, this.handleRequestFailed);
173
+ this.table.removeEventListener(dh.Table.EVENT_CUSTOMCOLUMNSCHANGED, this.handleCustomColumnsChanged);
174
+
175
+ if (this.totalsTable != null) {
176
+ this.removeTotalsListeners(this.totalsTable);
177
+ }
178
+
179
+ this.closeSubscription();
180
+ }
181
+
182
+ addTotalsListeners(totalsTable) {
183
+ totalsTable.addEventListener(dh.Table.EVENT_UPDATED, this.handleTotalsUpdate); // Totals table only has one row of data
184
+
185
+ totalsTable.setViewport(0, 0);
186
+ }
187
+
188
+ removeTotalsListeners(totalsTable) {
189
+ totalsTable.removeEventListener(dh.Table.EVENT_UPDATED, this.handleTotalsUpdate);
190
+ }
191
+
192
+ handleTableDisconnect() {
193
+ this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.DISCONNECT));
194
+ }
195
+
196
+ handleTableReconnect() {
197
+ this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.RECONNECT));
198
+ }
199
+
200
+ handleTableUpdate(event) {
201
+ this.copyViewportData(event.detail);
202
+ this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));
203
+ }
204
+
205
+ handleTotalsUpdate(event) {
206
+ this.copyTotalsData(event.detail);
207
+ this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));
208
+ }
209
+
210
+ handleRequestFailed(event) {
211
+ this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.REQUEST_FAILED, event));
212
+ }
213
+
214
+ handleCustomColumnsChanged() {
215
+ this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.COLUMNS_CHANGED, {
216
+ detail: this.columns
217
+ }));
218
+ }
219
+
220
+ get rowCount() {
221
+ var _this$totals$operatio, _this$totals, _this$totals$operatio2;
222
+
223
+ return this.table.size + ((_this$totals$operatio = (_this$totals = this.totals) === null || _this$totals === void 0 ? void 0 : (_this$totals$operatio2 = _this$totals.operationOrder) === null || _this$totals$operatio2 === void 0 ? void 0 : _this$totals$operatio2.length) !== null && _this$totals$operatio !== void 0 ? _this$totals$operatio : 0) + this.pendingNewRowCount;
224
+ }
225
+
226
+ get pendingDataErrors() {
227
+ var _this$inputTable$keyC, _this$inputTable;
228
+
229
+ return this.getCachedPendingErrors(this.pendingNewDataMap, this.columns, (_this$inputTable$keyC = (_this$inputTable = this.inputTable) === null || _this$inputTable === void 0 ? void 0 : _this$inputTable.keyColumns.length) !== null && _this$inputTable$keyC !== void 0 ? _this$inputTable$keyC : 0);
230
+ }
231
+
232
+ get pendingDataMap() {
233
+ return this.pendingNewDataMap;
234
+ }
235
+
236
+ set pendingDataMap(map) {
237
+ if (map === this.pendingNewDataMap) {
238
+ return;
239
+ }
240
+
241
+ map.forEach((row, rowIndex) => {
242
+ if (!IrisGridUtils.isValidIndex(rowIndex)) {
243
+ throw new Error('Invalid rowIndex', rowIndex);
244
+ }
245
+
246
+ var {
247
+ data
248
+ } = row;
249
+ data.forEach((value, columnIndex) => {
250
+ if (!IrisGridUtils.isValidIndex(columnIndex)) {
251
+ throw new Error('Invalid columnIndex', columnIndex);
252
+ }
253
+ });
254
+ });
255
+ this.pendingNewDataMap = map;
256
+ this.pendingNewRowCount = Math.max(this.pendingNewRowCount, this.maxPendingDataRow);
257
+ this.formattedStringData = [];
258
+ this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.PENDING_DATA_UPDATED));
259
+ }
260
+
261
+ get pendingRowCount() {
262
+ return this.pendingNewRowCount;
263
+ }
264
+
265
+ set pendingRowCount(count) {
266
+ if (count === this.pendingNewRowCount) {
267
+ return;
268
+ }
269
+
270
+ this.pendingNewRowCount = Math.max(0, count, this.maxPendingDataRow);
271
+ this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));
272
+ }
273
+
274
+ get maxPendingDataRow() {
275
+ return this.pendingNewDataMap.size > 0 ? Math.max(...this.pendingNewDataMap.keys()) + 1 : 0;
276
+ }
277
+
278
+ get columnCount() {
279
+ return this.columns.length;
280
+ }
281
+
282
+ get floatingBottomRowCount() {
283
+ var _this$totals2, _this$totals$operatio3, _this$totals3, _this$totals3$operati;
284
+
285
+ return (_this$totals2 = this.totals) !== null && _this$totals2 !== void 0 && _this$totals2.showOnTop ? 0 : (_this$totals$operatio3 = (_this$totals3 = this.totals) === null || _this$totals3 === void 0 ? void 0 : (_this$totals3$operati = _this$totals3.operationOrder) === null || _this$totals3$operati === void 0 ? void 0 : _this$totals3$operati.length) !== null && _this$totals$operatio3 !== void 0 ? _this$totals$operatio3 : 0;
286
+ }
287
+
288
+ get floatingTopRowCount() {
289
+ var _this$totals4, _this$totals$operatio4, _this$totals5, _this$totals5$operati;
290
+
291
+ return (_this$totals4 = this.totals) !== null && _this$totals4 !== void 0 && _this$totals4.showOnTop ? (_this$totals$operatio4 = (_this$totals5 = this.totals) === null || _this$totals5 === void 0 ? void 0 : (_this$totals5$operati = _this$totals5.operationOrder) === null || _this$totals5$operati === void 0 ? void 0 : _this$totals5$operati.length) !== null && _this$totals$operatio4 !== void 0 ? _this$totals$operatio4 : 0 : 0;
52
292
  }
53
293
 
54
294
  get isExportAvailable() {
@@ -78,6 +318,205 @@ class IrisGridTableModel extends IrisGridTableModelTemplate {
78
318
  get isFormatColumnsAvailable() {
79
319
  return this.table.applyCustomColumns != null;
80
320
  }
321
+
322
+ get isChartBuilderAvailable() {
323
+ return true;
324
+ }
325
+
326
+ get isTotalsAvailable() {
327
+ return this.table.getTotalsTable != null;
328
+ }
329
+
330
+ get isEditable() {
331
+ return !this.isSaveInProgress && this.inputTable != null;
332
+ }
333
+
334
+ cacheFormattedValue(x, y, text) {
335
+ if (this.formattedStringData[x] == null) {
336
+ this.formattedStringData[x] = [];
337
+ }
338
+
339
+ this.formattedStringData[x][y] = text;
340
+ }
341
+
342
+ cachePendingValue(x, y, text) {
343
+ if (this.pendingStringData[x] == null) {
344
+ this.pendingStringData[x] = [];
345
+ }
346
+
347
+ this.pendingStringData[x][y] = text;
348
+ }
349
+
350
+ clearPendingValue(x, y) {
351
+ var column = this.pendingStringData[x];
352
+
353
+ if (column != null) {
354
+ delete column[y];
355
+ }
356
+ }
357
+
358
+ textValueForCell(x, y) {
359
+ var _this$pendingStringDa, _this$formattedString;
360
+
361
+ // First check if there's any pending values we should read from
362
+ if (((_this$pendingStringDa = this.pendingStringData[x]) === null || _this$pendingStringDa === void 0 ? void 0 : _this$pendingStringDa[y]) !== undefined) {
363
+ return this.pendingStringData[x][y];
364
+ } // Use a separate cache from memoization just for the strings that are currently displayed
365
+
366
+
367
+ if (((_this$formattedString = this.formattedStringData[x]) === null || _this$formattedString === void 0 ? void 0 : _this$formattedString[y]) === undefined) {
368
+ var _this$totalsColumn;
369
+
370
+ var value = this.valueForCell(x, y);
371
+
372
+ if (value == null) {
373
+ return null;
374
+ }
375
+
376
+ var column = (_this$totalsColumn = this.totalsColumn(x, y)) !== null && _this$totalsColumn !== void 0 ? _this$totalsColumn : this.columns[x];
377
+ var hasCustomColumnFormat = this.getCachedCustomColumnFormatFlag(this.formatter, column.name, column.type);
378
+ var formatOverride = null;
379
+
380
+ if (!hasCustomColumnFormat) {
381
+ var formatForCell = this.formatForCell(x, y);
382
+
383
+ if ((formatForCell === null || formatForCell === void 0 ? void 0 : formatForCell.formatString) != null) {
384
+ formatOverride = formatForCell;
385
+ }
386
+ }
387
+
388
+ var text = this.displayString(value, column.type, column.name, formatOverride);
389
+ this.cacheFormattedValue(x, y, text);
390
+ }
391
+
392
+ return this.formattedStringData[x][y];
393
+ }
394
+
395
+ textForCell(x, y) {
396
+ var text = this.textValueForCell(x, y);
397
+
398
+ if (text == null && this.isKeyColumn(x)) {
399
+ var pendingRow = this.pendingRow(y);
400
+
401
+ if (this.pendingDataMap.has(pendingRow)) {
402
+ // Asterisk to show a value is required for a key column on a row that has some data entered
403
+ return '*';
404
+ }
405
+ }
406
+
407
+ return text;
408
+ }
409
+
410
+ truncationCharForCell(x) {
411
+ var column = this.columns[x];
412
+ var {
413
+ type
414
+ } = column;
415
+
416
+ if (TableUtils.isNumberType(type) && this.formatter.truncateNumbersWithPound) {
417
+ return '#';
418
+ }
419
+
420
+ return undefined;
421
+ }
422
+
423
+ colorForCell(x, y, theme) {
424
+ var data = this.dataForCell(x, y);
425
+
426
+ if (data) {
427
+ var {
428
+ format,
429
+ value
430
+ } = data;
431
+
432
+ if (value == null || value === '') {
433
+ return theme.nullStringColor;
434
+ }
435
+
436
+ if (format && format.color) {
437
+ return format.color;
438
+ }
439
+
440
+ if (this.isPendingRow(y)) {
441
+ // Data entered in a pending row
442
+ return theme.pendingTextColor;
443
+ } // Fallback to formatting based on the value/type of the cell
444
+
445
+
446
+ if (value != null) {
447
+ var _this$totalsColumn2;
448
+
449
+ var column = (_this$totalsColumn2 = this.totalsColumn(x, y)) !== null && _this$totalsColumn2 !== void 0 ? _this$totalsColumn2 : this.columns[x];
450
+
451
+ if (TableUtils.isDateType(column.type) || column.name === 'Date') {
452
+ return theme.dateColor;
453
+ }
454
+
455
+ if (TableUtils.isNumberType(column.type)) {
456
+ if (value > 0) {
457
+ return theme.positiveNumberColor;
458
+ }
459
+
460
+ if (value < 0) {
461
+ return theme.negativeNumberColor;
462
+ }
463
+
464
+ return theme.zeroNumberColor;
465
+ }
466
+ }
467
+ } else if (this.isPendingRow(y) && this.isKeyColumn(x)) {
468
+ return theme.errorTextColor;
469
+ }
470
+
471
+ return theme.textColor;
472
+ }
473
+
474
+ backgroundColorForCell(x, y) {
475
+ var _this$formatForCell;
476
+
477
+ return (_this$formatForCell = this.formatForCell(x, y)) === null || _this$formatForCell === void 0 ? void 0 : _this$formatForCell.backgroundColor;
478
+ }
479
+
480
+ textAlignForCell(x) {
481
+ var column = this.columns[x];
482
+ var {
483
+ type
484
+ } = column;
485
+
486
+ if (TableUtils.isNumberType(type)) {
487
+ return 'right';
488
+ }
489
+
490
+ if (TableUtils.isDateType(type) || column.name === 'Date') {
491
+ return 'center';
492
+ }
493
+
494
+ return 'left';
495
+ }
496
+
497
+ textForColumnHeader(x) {
498
+ var column = this.columns[x];
499
+ return "".concat(column.name);
500
+ }
501
+
502
+ textForRowFooter(y) {
503
+ var totalsRow = this.totalsRow(y);
504
+
505
+ if (totalsRow != null) {
506
+ return this.totals.operationOrder[totalsRow];
507
+ }
508
+
509
+ return '';
510
+ }
511
+ /**
512
+ * Returns an array of the columns in the model
513
+ * The order of model columns should never change once established
514
+ */
515
+
516
+
517
+ get columns() {
518
+ return this.table.columns;
519
+ }
81
520
  /**
82
521
  * Used to get the initial moved columns based on layout hints
83
522
  */
@@ -89,7 +528,7 @@ class IrisGridTableModel extends IrisGridTableModelTemplate {
89
528
  if (this.frontColumns.length || this.backColumns.length || this.frozenColumns.length) {
90
529
  var usedColumns = new Set();
91
530
 
92
- var moveColumn = (name, toIndex) => {
531
+ var moveColumn = (name, index) => {
93
532
  if (usedColumns.has(name)) {
94
533
  throw new Error("Column specified in multiple layout hints: ".concat(name));
95
534
  }
@@ -101,7 +540,7 @@ class IrisGridTableModel extends IrisGridTableModelTemplate {
101
540
  }
102
541
 
103
542
  var visibleIndex = GridUtils.getVisibleIndex(modelIndex, movedColumns);
104
- movedColumns = GridUtils.moveItem(visibleIndex, toIndex, movedColumns);
543
+ movedColumns = GridUtils.moveItem(visibleIndex, index, movedColumns);
105
544
  };
106
545
 
107
546
  var frontIndex = 0;
@@ -123,6 +562,10 @@ class IrisGridTableModel extends IrisGridTableModelTemplate {
123
562
  return movedColumns;
124
563
  }
125
564
 
565
+ get columnMap() {
566
+ return this.getMemoizedColumnMap(this.table.columns);
567
+ }
568
+
126
569
  get frontColumns() {
127
570
  var _this$layoutHints;
128
571
 
@@ -149,10 +592,308 @@ class IrisGridTableModel extends IrisGridTableModelTemplate {
149
592
  return this.frozenColumns.length;
150
593
  }
151
594
 
595
+ get groupedColumns() {
596
+ return [];
597
+ }
598
+
152
599
  get description() {
153
600
  return this.table.description;
154
601
  }
155
602
 
603
+ row(y) {
604
+ var _this$totals$operatio5, _this$totals6, _this$totals6$operati, _this$totals$showOnTo, _this$totals7, _this$viewportData$of, _this$viewportData, _this$viewportData$ro, _this$viewportData2, _this$viewportData2$r;
605
+
606
+ var totalsRowCount = (_this$totals$operatio5 = (_this$totals6 = this.totals) === null || _this$totals6 === void 0 ? void 0 : (_this$totals6$operati = _this$totals6.operationOrder) === null || _this$totals6$operati === void 0 ? void 0 : _this$totals6$operati.length) !== null && _this$totals$operatio5 !== void 0 ? _this$totals$operatio5 : 0;
607
+ var showOnTop = (_this$totals$showOnTo = (_this$totals7 = this.totals) === null || _this$totals7 === void 0 ? void 0 : _this$totals7.showOnTop) !== null && _this$totals$showOnTo !== void 0 ? _this$totals$showOnTo : false;
608
+ var totalsRow = this.totalsRow(y);
609
+
610
+ if (totalsRow != null) {
611
+ var _this$totalsDataMap$g, _this$totalsDataMap;
612
+
613
+ var operation = this.totals.operationOrder[totalsRow];
614
+ return (_this$totalsDataMap$g = (_this$totalsDataMap = this.totalsDataMap) === null || _this$totalsDataMap === void 0 ? void 0 : _this$totalsDataMap.get(operation)) !== null && _this$totalsDataMap$g !== void 0 ? _this$totalsDataMap$g : null;
615
+ }
616
+
617
+ var pendingRow = this.pendingRow(y);
618
+
619
+ if (pendingRow != null) {
620
+ var _this$pendingNewDataM;
621
+
622
+ return (_this$pendingNewDataM = this.pendingNewDataMap.get(pendingRow)) !== null && _this$pendingNewDataM !== void 0 ? _this$pendingNewDataM : null;
623
+ }
624
+
625
+ var offset = (_this$viewportData$of = (_this$viewportData = this.viewportData) === null || _this$viewportData === void 0 ? void 0 : _this$viewportData.offset) !== null && _this$viewportData$of !== void 0 ? _this$viewportData$of : 0;
626
+ var viewportY = (showOnTop ? y - totalsRowCount : y) - offset;
627
+ return (_this$viewportData$ro = (_this$viewportData2 = this.viewportData) === null || _this$viewportData2 === void 0 ? void 0 : (_this$viewportData2$r = _this$viewportData2.rows) === null || _this$viewportData2$r === void 0 ? void 0 : _this$viewportData2$r[viewportY]) !== null && _this$viewportData$ro !== void 0 ? _this$viewportData$ro : null;
628
+ }
629
+ /**
630
+ * Retrieve the totals column if this is a totals row, or null otherwise
631
+ * @param {ModelIndex} x Column index to get the totals column from
632
+ * @param {ModelIndex} y Row index to get the totals column from
633
+ * @returns {dh.Column | null}
634
+ */
635
+
636
+
637
+ totalsColumn(x, y) {
638
+ var totalsRow = this.totalsRow(y);
639
+ if (totalsRow == null) return null;
640
+ var operation = this.totals.operationOrder[totalsRow];
641
+ var tableColumn = this.columns[x]; // If there's exactly one operation applied to this column, the totals table result column will just be the same
642
+ // If there's more than one operation, the totals table column will be the original name with two underscores and the operation appended
643
+
644
+ var operations = this.totals.operationMap[tableColumn.name];
645
+ var isOnlyOperation = (operations === null || operations === void 0 ? void 0 : operations.length) === 1 && operations[0] === operation;
646
+ var matchName = isOnlyOperation ? tableColumn.name : "".concat(tableColumn.name, "__").concat(operation);
647
+ return this.totalsTable.columns.find(column => column.name === matchName);
648
+ }
649
+ /**
650
+ * Translate from the row in the model to a row in the totals table.
651
+ * If the row is not a totals row, return null
652
+ * @param {number} y The row in the model to get the totals row for
653
+ * @returns {number|null} The row within the totals table if it's a totals row, null otherwise
654
+ */
655
+
656
+
657
+ totalsRow(y) {
658
+ var _this$totals$operatio6, _this$totals8, _this$totals8$operati, _this$totals$showOnTo2, _this$totals9;
659
+
660
+ var totalsRowCount = (_this$totals$operatio6 = (_this$totals8 = this.totals) === null || _this$totals8 === void 0 ? void 0 : (_this$totals8$operati = _this$totals8.operationOrder) === null || _this$totals8$operati === void 0 ? void 0 : _this$totals8$operati.length) !== null && _this$totals$operatio6 !== void 0 ? _this$totals$operatio6 : 0;
661
+ var showOnTop = (_this$totals$showOnTo2 = (_this$totals9 = this.totals) === null || _this$totals9 === void 0 ? void 0 : _this$totals9.showOnTop) !== null && _this$totals$showOnTo2 !== void 0 ? _this$totals$showOnTo2 : false;
662
+ var totalsRow = showOnTop ? y : y - this.table.size;
663
+
664
+ if (totalsRow >= 0 && totalsRow < totalsRowCount) {
665
+ return totalsRow;
666
+ }
667
+
668
+ return null;
669
+ }
670
+ /**
671
+ * Translate from the row in the model to a pending input row.
672
+ * If the row is not a pending input row, return null
673
+ * @param {number} y The row in the model to get the pending row for
674
+ * @returns {number|null} The row within the pending input rows if it's a pending row, null otherwise
675
+ */
676
+
677
+
678
+ pendingRow(y) {
679
+ var pendingRow = y - this.floatingTopRowCount - this.table.size;
680
+
681
+ if (pendingRow >= 0 && pendingRow < this.pendingNewRowCount) {
682
+ return pendingRow;
683
+ }
684
+
685
+ return null;
686
+ }
687
+ /**
688
+ * Check if a row is a totals table row
689
+ * @param {number} y The row in the model to check if it's a totals table row
690
+ * @returns {boolean} True if the row is a totals row, false if not
691
+ */
692
+
693
+
694
+ isTotalsRow(y) {
695
+ return this.totalsRow(y) != null;
696
+ }
697
+ /**
698
+ * Check if a row is a pending input row
699
+ * @param {number} y The row in the model to check if it's a pending new row
700
+ * @returns {boolean} True if the row is a pending new row, false if not
701
+ */
702
+
703
+
704
+ isPendingRow(y) {
705
+ return this.pendingRow(y) != null;
706
+ }
707
+
708
+ dataForCell(x, y) {
709
+ var _this$row;
710
+
711
+ return (_this$row = this.row(y)) === null || _this$row === void 0 ? void 0 : _this$row.data.get(x);
712
+ }
713
+
714
+ formatForCell(x, y) {
715
+ var _this$dataForCell;
716
+
717
+ return (_this$dataForCell = this.dataForCell(x, y)) === null || _this$dataForCell === void 0 ? void 0 : _this$dataForCell.format;
718
+ }
719
+
720
+ valueForCell(x, y) {
721
+ var data = this.dataForCell(x, y);
722
+
723
+ if (data) {
724
+ var _data$value;
725
+
726
+ return (_data$value = data.value) !== null && _data$value !== void 0 ? _data$value : null;
727
+ }
728
+
729
+ return undefined;
730
+ }
731
+
732
+ copyViewportData(data) {
733
+ if (!data) {
734
+ log.warn('invalid data!');
735
+ return;
736
+ }
737
+
738
+ this.viewportData = this.extractViewportData(data);
739
+ this.formattedStringData = [];
740
+ }
741
+
742
+ copyTotalsData(totalsData) {
743
+ var _this$totals$defaultO,
744
+ _this$totals10,
745
+ _this$totals11,
746
+ _this = this;
747
+
748
+ if (!totalsData) {
749
+ log.warn('invalid data!');
750
+ return;
751
+ }
752
+
753
+ var {
754
+ columns,
755
+ rows
756
+ } = totalsData;
757
+
758
+ if (rows.length !== 1) {
759
+ log.error('Unexpected number of rows received for totals table, ignoring update');
760
+ return;
761
+ }
762
+
763
+ var dataMap = new Map();
764
+ var row = rows[0];
765
+ var defaultOperation = (_this$totals$defaultO = (_this$totals10 = this.totals) === null || _this$totals10 === void 0 ? void 0 : _this$totals10.defaultOperation) !== null && _this$totals$defaultO !== void 0 ? _this$totals$defaultO : AggregationOperation.SUM;
766
+ var operationMap = (_this$totals11 = this.totals) === null || _this$totals11 === void 0 ? void 0 : _this$totals11.operationMap;
767
+
768
+ var _loop = function _loop(c) {
769
+ var _operationMap$name$, _operationMap$name;
770
+
771
+ var column = columns[c];
772
+ var [name, operation = (_operationMap$name$ = operationMap === null || operationMap === void 0 ? void 0 : (_operationMap$name = operationMap[name]) === null || _operationMap$name === void 0 ? void 0 : _operationMap$name[0]) !== null && _operationMap$name$ !== void 0 ? _operationMap$name$ : defaultOperation] = column.name.split('__');
773
+
774
+ if (!dataMap.has(operation)) {
775
+ dataMap.set(operation, {
776
+ data: new Map()
777
+ });
778
+ }
779
+
780
+ var {
781
+ data: rowData
782
+ } = dataMap.get(operation);
783
+
784
+ var columnIndex = _this.columns.findIndex(col => col.name === name);
785
+
786
+ rowData.set(columnIndex, {
787
+ value: row.get(column),
788
+ format: row.getFormat(column)
789
+ });
790
+ };
791
+
792
+ for (var c = 0; c < columns.length; c += 1) {
793
+ _loop(c);
794
+ }
795
+
796
+ log.debug2('copyTotalsData', dataMap);
797
+ this.totalsDataMap = dataMap;
798
+ this.formattedStringData = [];
799
+ }
800
+ /**
801
+ * Gets the model index for a column from its name
802
+ * @param {string} name The column name
803
+ * @returns {number | undefined} The ModelIndex if it exists
804
+ */
805
+
806
+
807
+ getColumnIndexByName(name) {
808
+ return this.getColumnIndicesByNameMap(this.columns).get(name);
809
+ }
810
+
811
+ /**
812
+ * Copies all the viewport data into an object that we can reference later.
813
+ * @param {ViewportData} data The data to copy from
814
+ */
815
+ extractViewportData(data) {
816
+ var newData = {
817
+ offset: data.offset,
818
+ rows: []
819
+ };
820
+ var {
821
+ columns
822
+ } = data;
823
+
824
+ for (var r = 0; r < data.rows.length; r += 1) {
825
+ var row = data.rows[r];
826
+ var newRow = this.extractViewportRow(row, columns);
827
+ newData.rows.push(newRow);
828
+ }
829
+
830
+ return newData;
831
+ }
832
+
833
+ extractViewportRow(row, columns) {
834
+ var data = new Map();
835
+
836
+ for (var c = 0; c < columns.length; c += 1) {
837
+ var column = columns[c];
838
+ data.set(this.getColumnIndexByName(column.name), {
839
+ value: row.get(column),
840
+ format: row.getFormat(column)
841
+ });
842
+ }
843
+
844
+ return {
845
+ data
846
+ };
847
+ }
848
+
849
+ closeSubscription() {
850
+ log.debug2('closeSubscription', this.subscription);
851
+
852
+ if (this.subscription) {
853
+ this.subscription.close();
854
+ this.subscription = null;
855
+ }
856
+
857
+ this.setViewport.cancel();
858
+ this.applyViewport.cancel();
859
+ }
860
+
861
+ get filter() {
862
+ return this.table.filter;
863
+ }
864
+
865
+ set filter(filter) {
866
+ this.closeSubscription();
867
+ this.table.applyFilter(filter);
868
+ this.applyViewport();
869
+ }
870
+
871
+ get formatter() {
872
+ return this.irisFormatter;
873
+ }
874
+
875
+ set formatter(formatter) {
876
+ this.irisFormatter = formatter;
877
+ this.formattedStringData = [];
878
+ this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.FORMATTER_UPDATED));
879
+ }
880
+
881
+ displayString(value, columnType) {
882
+ var columnName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
883
+ var formatOverride = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
884
+ return this.getCachedFormattedString(this.formatter, value, columnType, columnName, formatOverride);
885
+ }
886
+
887
+ get sort() {
888
+ return this.table.sort;
889
+ }
890
+
891
+ set sort(sort) {
892
+ this.closeSubscription();
893
+ this.table.applySort(sort);
894
+ this.applyViewport();
895
+ }
896
+
156
897
  get customColumns() {
157
898
  return this.customColumnList;
158
899
  }
@@ -203,9 +944,7 @@ class IrisGridTableModel extends IrisGridTableModelTemplate {
203
944
 
204
945
  updateFrozenColumns(columns) {
205
946
  this.userFrozenColumns = columns;
206
- this.dispatchEvent(new EventShimCustomEvent(IrisGridModel.EVENT.TABLE_CHANGED, {
207
- detail: this.table
208
- }));
947
+ this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.TABLE_CHANGED));
209
948
  }
210
949
 
211
950
  set totalsConfig(totalsConfig) {
@@ -226,7 +965,7 @@ class IrisGridTableModel extends IrisGridTableModelTemplate {
226
965
  this.setTotalsTable(null);
227
966
 
228
967
  if (totalsConfig == null) {
229
- this.dispatchEvent(new EventShimCustomEvent(IrisGridModel.EVENT.UPDATED));
968
+ this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));
230
969
  return;
231
970
  }
232
971
 
@@ -241,12 +980,199 @@ class IrisGridTableModel extends IrisGridTableModelTemplate {
241
980
 
242
981
  log.error('Unable to set next totalsTable', err);
243
982
  this.totalsTablePromise = null;
244
- this.dispatchEvent(new EventShimCustomEvent(IrisGridModel.EVENT.REQUEST_FAILED, {
983
+ this.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.REQUEST_FAILED, {
245
984
  detail: err
246
985
  }));
247
986
  });
248
987
  }
249
988
 
989
+ setTotalsTable(totalsTable) {
990
+ log.debug('setTotalsTable', totalsTable);
991
+
992
+ if (this.totalsTable !== null) {
993
+ if (this.listenerCount > 0) {
994
+ this.removeTotalsListeners(this.totalsTable);
995
+ }
996
+
997
+ this.totalsTable.close();
998
+ }
999
+
1000
+ this.totalsTable = totalsTable;
1001
+ this.totalsDataMap = null;
1002
+
1003
+ if (this.listenerCount > 0 && this.totalsTable != null) {
1004
+ this.addTotalsListeners(totalsTable);
1005
+ }
1006
+ }
1007
+
1008
+ setViewport(top, bottom, columns) {
1009
+ if (bottom < top) {
1010
+ log.error('Invalid viewport', top, bottom);
1011
+ return;
1012
+ }
1013
+
1014
+ var {
1015
+ viewport
1016
+ } = this;
1017
+
1018
+ if (viewport != null && viewport.top === top && viewport.bottom === bottom && viewport.columns === columns) {
1019
+ log.debug2('Ignoring duplicate viewport', viewport);
1020
+ return;
1021
+ }
1022
+
1023
+ this.viewport = {
1024
+ top,
1025
+ bottom,
1026
+ columns
1027
+ };
1028
+ log.debug2('setViewport', this.viewport);
1029
+ this.applyViewport();
1030
+ }
1031
+ /**
1032
+ * Applies the current viewport to the underlying table.
1033
+ */
1034
+
1035
+
1036
+ applyViewport() {
1037
+ if (!this.viewport) {
1038
+ return;
1039
+ }
1040
+
1041
+ log.debug2('applyViewport', this.viewport);
1042
+ var {
1043
+ top,
1044
+ bottom,
1045
+ columns
1046
+ } = this.viewport;
1047
+ var [viewportTop, viewportBottom] = this.getCachedViewportRowRange(top, bottom);
1048
+ this.applyBufferedViewport(viewportTop, viewportBottom, columns);
1049
+ }
1050
+
1051
+ applyBufferedViewport(viewportTop, viewportBottom, columns) {
1052
+ log.debug2('applyBufferedViewport', viewportTop, viewportBottom, columns);
1053
+
1054
+ if (this.subscription == null) {
1055
+ log.debug2('applyBufferedViewport creating new subscription');
1056
+ this.subscription = this.table.setViewport(viewportTop, viewportBottom, columns);
1057
+ } else {
1058
+ log.debug2('applyBufferedViewport using existing subscription');
1059
+ this.subscription.setViewport(viewportTop, viewportBottom, columns);
1060
+ }
1061
+ }
1062
+
1063
+ snapshot(ranges) {
1064
+ var _arguments = arguments,
1065
+ _this2 = this;
1066
+
1067
+ return _asyncToGenerator(function* () {
1068
+ var includeHeaders = _arguments.length > 1 && _arguments[1] !== undefined ? _arguments[1] : false;
1069
+ var formatValue = _arguments.length > 2 && _arguments[2] !== undefined ? _arguments[2] : value => value;
1070
+
1071
+ if (_this2.subscription == null) {
1072
+ throw new Error('No subscription available');
1073
+ }
1074
+
1075
+ var consolidated = GridRange.consolidate(ranges);
1076
+
1077
+ if (!IrisGridUtils.isValidSnapshotRanges(consolidated)) {
1078
+ throw new Error('Invalid snapshot ranges', ranges);
1079
+ } // Need to separate out the floating ranges as they're from a different source
1080
+
1081
+
1082
+ var topFloatingRowsSet = new Set();
1083
+ var tableRanges = [];
1084
+ var bottomFloatingRowsSet = new Set();
1085
+
1086
+ for (var i = 0; i < consolidated.length; i += 1) {
1087
+ var range = consolidated[i]; // Get the rows that are in the top aggregations section
1088
+
1089
+ for (var r = range.startRow; r <= range.endRow && r < _this2.floatingTopRowCount; r += 1) {
1090
+ topFloatingRowsSet.add(r);
1091
+ } // Separate out the range that is part of the actual table (ie. not the floating ranges, not aggregations)
1092
+
1093
+
1094
+ if (range.endRow >= _this2.floatingTopRowCount && range.startRow <= _this2.floatingTopRowCount + _this2.table.size) {
1095
+ tableRanges.push(new GridRange(range.startColumn, Math.min(Math.max(0, range.startRow - _this2.floatingTopRowCount)), range.endColumn, Math.min(Math.max(0, range.endRow - _this2.floatingTopRowCount), _this2.table.size - _this2.floatingTopRowCount)));
1096
+ } // Get the rows that are in the bottom aggregations section
1097
+
1098
+
1099
+ for (var _r = Math.max(range.startRow, _this2.floatingTopRowCount + _this2.table.size); _r <= range.endRow && _r < _this2.floatingTopRowCount + _this2.table.size + _this2.floatingBottomRowCount; _r += 1) {
1100
+ bottomFloatingRowsSet.add(_r);
1101
+ }
1102
+ }
1103
+
1104
+ var columns = IrisGridUtils.columnsFromRanges(consolidated, _this2.columns);
1105
+ var result = [];
1106
+
1107
+ if (includeHeaders) {
1108
+ result.push(columns.map(c => c.name));
1109
+ }
1110
+
1111
+ var topFloatingRows = [...topFloatingRowsSet].sort();
1112
+
1113
+ var _loop2 = function _loop2(_i) {
1114
+ var row = topFloatingRows[_i];
1115
+ var rowData = columns.map(column => formatValue(_this2.valueForCell(_this2.getColumnIndexByName(column.name), row), column));
1116
+
1117
+ if (includeHeaders) {
1118
+ rowData.push(_this2.textForRowFooter(row));
1119
+ }
1120
+
1121
+ result.push(rowData);
1122
+ };
1123
+
1124
+ for (var _i = 0; _i < topFloatingRows.length; _i += 1) {
1125
+ _loop2(_i);
1126
+ }
1127
+
1128
+ if (tableRanges.length > 0) {
1129
+ var rangeSet = IrisGridUtils.rangeSetFromRanges(tableRanges);
1130
+ var snapshot = yield _this2.subscription.snapshot(rangeSet, columns);
1131
+ result.push(...snapshot.rows.map(rowData => columns.map(column => formatValue(rowData.get(column), column))));
1132
+ }
1133
+
1134
+ var bottomFloatingRows = [...bottomFloatingRowsSet].sort();
1135
+
1136
+ var _loop3 = function _loop3(_i2) {
1137
+ var row = bottomFloatingRows[_i2];
1138
+ var rowData = columns.map(column => formatValue(_this2.valueForCell(_this2.getColumnIndexByName(column.name), row), column));
1139
+
1140
+ if (includeHeaders) {
1141
+ rowData.push(_this2.textForRowFooter(row));
1142
+ }
1143
+
1144
+ result.push(rowData);
1145
+ };
1146
+
1147
+ for (var _i2 = 0; _i2 < bottomFloatingRows.length; _i2 += 1) {
1148
+ _loop3(_i2);
1149
+ }
1150
+
1151
+ return result;
1152
+ })();
1153
+ }
1154
+ /**
1155
+ * Get a text snapshot of the provided ranges
1156
+ * @param {GridRange[]} ranges The ranges to get the snapshot for
1157
+ * @param {boolean} includeHeaders Whether to include the headers in the snapshot or not
1158
+ * @param {(unknown, dh.Column) => string} formatValue Function for formatting the raw value into a string
1159
+ * @returns {string} A formatted string of all the data, columns separated by `\t` and rows separated by `\n`
1160
+ */
1161
+
1162
+
1163
+ textSnapshot(ranges) {
1164
+ var _arguments2 = arguments,
1165
+ _this3 = this;
1166
+
1167
+ return _asyncToGenerator(function* () {
1168
+ var includeHeaders = _arguments2.length > 1 && _arguments2[1] !== undefined ? _arguments2[1] : false;
1169
+ var formatValue = _arguments2.length > 2 && _arguments2[2] !== undefined ? _arguments2[2] : value => "".concat(value);
1170
+ log.debug2('textSnapshot', ranges, includeHeaders);
1171
+ var data = yield _this3.snapshot(ranges, includeHeaders, formatValue);
1172
+ return data.map(row => row.join('\t')).join('\n');
1173
+ })();
1174
+ }
1175
+
250
1176
  get isFilterRequired() {
251
1177
  return this.table.isUncoalesced;
252
1178
  }
@@ -255,11 +1181,30 @@ class IrisGridTableModel extends IrisGridTableModelTemplate {
255
1181
  return this.getCachedFilterableColumnSet(this.columns).has(columnIndex);
256
1182
  }
257
1183
 
1184
+ valuesTable(column) {
1185
+ var _this4 = this;
1186
+
1187
+ return _asyncToGenerator(function* () {
1188
+ var table = null;
1189
+
1190
+ try {
1191
+ table = yield _this4.table.copy();
1192
+ table.applyFilter([]);
1193
+ table.applySort([]);
1194
+ return table.selectDistinct([column]);
1195
+ } finally {
1196
+ if (table != null) {
1197
+ table.close();
1198
+ }
1199
+ }
1200
+ })();
1201
+ }
1202
+
258
1203
  export() {
259
- var _this = this;
1204
+ var _this5 = this;
260
1205
 
261
1206
  return _asyncToGenerator(function* () {
262
- return _this.table.freeze();
1207
+ return _this5.table.freeze();
263
1208
  })();
264
1209
  }
265
1210
 
@@ -281,69 +1226,436 @@ class IrisGridTableModel extends IrisGridTableModelTemplate {
281
1226
  return this.frozenColumns.includes(this.columns[modelIndex].name);
282
1227
  }
283
1228
 
284
- delete(ranges) {
285
- var _superprop_getPendingDataMap = () => super.pendingDataMap,
286
- _superprop_setPendingDataMap = _value => super.pendingDataMap = _value,
287
- _this2 = this;
1229
+ isKeyColumn(x) {
1230
+ var _this$inputTable$keyC2, _this$inputTable2;
1231
+
1232
+ return x < ((_this$inputTable$keyC2 = (_this$inputTable2 = this.inputTable) === null || _this$inputTable2 === void 0 ? void 0 : _this$inputTable2.keyColumns.length) !== null && _this$inputTable$keyC2 !== void 0 ? _this$inputTable$keyC2 : 0);
1233
+ }
1234
+
1235
+ isRowMovable() {
1236
+ return false;
1237
+ }
1238
+
1239
+ isEditableRange(range) {
1240
+ return this.inputTable != null && GridRange.isBounded(range) && (this.isPendingRow(range.startRow) && this.isPendingRow(range.endRow) || range.startColumn >= this.inputTable.keyColumns.length && range.endColumn >= this.inputTable.keyColumns.length) && range.startRow >= this.floatingTopRowCount && range.startRow < this.floatingTopRowCount + this.table.size + this.pendingRowCount && range.endRow < this.floatingTopRowCount + this.table.size + this.pendingRowCount;
1241
+ }
1242
+
1243
+ isDeletableRange(range) {
1244
+ return this.inputTable != null && range.startRow != null && range.endRow != null && range.startRow >= this.floatingTopRowCount && range.startRow < this.floatingTopRowCount + this.table.size + this.pendingRowCount && range.endRow < this.floatingTopRowCount + this.table.size + this.pendingRowCount;
1245
+ }
1246
+
1247
+ isEditableRanges(ranges) {
1248
+ return ranges.every(range => this.isEditableRange(range));
1249
+ }
1250
+
1251
+ isDeletableRanges(ranges) {
1252
+ return ranges.every(range => this.isDeletableRange(range));
1253
+ }
1254
+ /**
1255
+ * @returns {GridRange} A range corresponding to the underlying table
1256
+ */
1257
+
1258
+
1259
+ getTableAreaRange() {
1260
+ return new GridRange(null, this.floatingTopRowCount, null, this.floatingTopRowCount + this.table.size - 1);
1261
+ }
1262
+ /**
1263
+ * @returns {GridRange} A range corresponding to the pending new rows
1264
+ */
1265
+
1266
+
1267
+ getPendingAreaRange() {
1268
+ return new GridRange(null, this.floatingTopRowCount + this.table.size, null, this.floatingTopRowCount + this.table.size + this.pendingNewRowCount - 1);
1269
+ }
1270
+ /**
1271
+ * Set value in an editable table
1272
+ * @param {number} x The column to set
1273
+ * @param {number} y The row to set
1274
+ * @param {string} value The value to set
1275
+ * @returns {Promise<void>} A promise that resolves successfully when the operation is complete, or rejects if there's an error
1276
+ */
1277
+
1278
+
1279
+ setValueForCell(x, y, text) {
1280
+ var _this6 = this;
288
1281
 
289
1282
  return _asyncToGenerator(function* () {
290
- var _this2$inputTable;
1283
+ // Cache the value in our pending string cache so that it stays displayed until our edit has been completed
1284
+ return _this6.setValueForRanges([new GridRange(x, y, x, y)], text);
1285
+ })();
1286
+ }
1287
+ /**
1288
+ * Set value in an editable table
1289
+ * @param {GridRange[]} ranges The ranges to set
1290
+ * @param {string} value The values to set
1291
+ * @returns {Promise<void>} A promise that resolves successfully when the operation is complete, or rejects if there's an error
1292
+ */
291
1293
 
292
- if (!_this2.isDeletableRanges(ranges)) {
293
- throw new Error("Undeletable ranges ".concat(ranges));
1294
+
1295
+ setValueForRanges(ranges, text) {
1296
+ var _this7 = this;
1297
+
1298
+ return _asyncToGenerator(function* () {
1299
+ if (!_this7.isEditableRanges(ranges)) {
1300
+ throw new Error('Uneditable ranges', ranges);
1301
+ }
1302
+
1303
+ try {
1304
+ // Cache the value in our pending string cache so that it stays displayed until our edit has been completed
1305
+ var columnSet = new Set(); // Formatted text for each column
1306
+ // Since there could be different formatting for each column, but the value will be the same across rows
1307
+
1308
+ var formattedText = [];
1309
+ GridRange.forEachCell(ranges, (x, y) => {
1310
+ var column = _this7.columns[x];
1311
+ columnSet.add(column);
1312
+
1313
+ if (formattedText[x] === undefined) {
1314
+ var value = TableUtils.makeValue(column.type, text, _this7.formatter.timeZone);
1315
+ formattedText[x] = value != null ? _this7.displayString(value, column.type, column.name) : null;
1316
+ }
1317
+
1318
+ _this7.cachePendingValue(x, y, formattedText[x]);
1319
+ }); // Take care of updates to the pending new area first, as they can be updated synchronously
1320
+
1321
+ var pendingAreaRange = _this7.getPendingAreaRange();
1322
+
1323
+ var pendingRanges = ranges.map(range => GridRange.intersection(pendingAreaRange, range)).filter(range => range != null).map(range => GridRange.offset(range, 0, -(_this7.floatingTopRowCount + _this7.table.size)));
1324
+
1325
+ if (pendingRanges.length > 0) {
1326
+ var newDataMap = new Map(_this7.pendingNewDataMap);
1327
+ GridRange.forEachCell(pendingRanges, (columnIndex, rowIndex) => {
1328
+ if (!newDataMap.has(rowIndex)) {
1329
+ newDataMap.set(rowIndex, {
1330
+ data: new Map()
1331
+ });
1332
+ }
1333
+
1334
+ var column = _this7.columns[columnIndex];
1335
+ var row = newDataMap.get(rowIndex);
1336
+ var {
1337
+ data: rowData
1338
+ } = row;
1339
+ var newRowData = new Map(rowData);
1340
+ var value = TableUtils.makeValue(column.type, text, _this7.formatter.timeZone);
1341
+
1342
+ if (value != null) {
1343
+ newRowData.set(columnIndex, {
1344
+ value
1345
+ });
1346
+ } else {
1347
+ newRowData.delete(columnIndex);
1348
+ }
1349
+
1350
+ if (newRowData.size > 0) {
1351
+ newDataMap.set(rowIndex, _objectSpread(_objectSpread({}, row), {}, {
1352
+ data: newRowData
1353
+ }));
1354
+ } else {
1355
+ newDataMap.delete(rowIndex);
1356
+ }
1357
+ });
1358
+ _this7.pendingDataMap = newDataMap;
1359
+ }
1360
+
1361
+ _this7.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));
1362
+
1363
+ var tableAreaRange = _this7.getTableAreaRange();
1364
+
1365
+ var tableRanges = ranges.map(range => GridRange.intersection(tableAreaRange, range)).filter(range => range != null);
1366
+
1367
+ if (tableRanges.length > 0) {
1368
+ // Get a snapshot of the full rows, as we need to write a full row when editing
1369
+ var data = yield _this7.snapshot(tableRanges.map(range => new GridRange(null, range.startRow, null, range.endRow)));
1370
+ var newRows = data.map(row => {
1371
+ var newRow = {};
1372
+
1373
+ for (var c = 0; c < _this7.columns.length; c += 1) {
1374
+ newRow[_this7.columns[c].name] = row[c];
1375
+ }
1376
+
1377
+ columnSet.forEach(column => {
1378
+ newRow[column.name] = TableUtils.makeValue(column.type, text, _this7.formatter.timeZone);
1379
+ });
1380
+ return newRow;
1381
+ });
1382
+ var result = yield _this7.inputTable.addRows(newRows);
1383
+ log.debug('setValueForRanges(', ranges, ',', text, ') set tableRanges', tableRanges, 'result', result);
1384
+ } // Add the changes to the formatted cache so it's still displayed until the update event is received
1385
+ // The update event could be received on the next tick, after the input rows have been committed,
1386
+ // so make sure we don't display stale data
1387
+
1388
+
1389
+ GridRange.forEachCell(ranges, (x, y) => {
1390
+ _this7.cacheFormattedValue(x, y, formattedText[x]);
1391
+ });
1392
+ } catch (err) {
1393
+ log.error('Unable to set ranges', ranges, text, err);
1394
+ } finally {
1395
+ GridRange.forEachCell(ranges, (x, y) => {
1396
+ _this7.clearPendingValue(x, y);
1397
+ });
1398
+ }
1399
+ })();
1400
+ }
1401
+
1402
+ setValues() {
1403
+ var _arguments3 = arguments,
1404
+ _this8 = this;
1405
+
1406
+ return _asyncToGenerator(function* () {
1407
+ var edits = _arguments3.length > 0 && _arguments3[0] !== undefined ? _arguments3[0] : [];
1408
+ log.debug('setValues(', edits, ')');
1409
+
1410
+ if (!edits.every(edit => {
1411
+ var _edit$column, _edit$row;
1412
+
1413
+ return _this8.isEditableRange(GridRange.makeCell((_edit$column = edit.column) !== null && _edit$column !== void 0 ? _edit$column : edit.x, (_edit$row = edit.row) !== null && _edit$row !== void 0 ? _edit$row : edit.y));
1414
+ })) {
1415
+ throw new Error('Uneditable ranges', edits);
1416
+ }
1417
+
1418
+ try {
1419
+ var newDataMap = new Map(_this8.pendingNewDataMap); // Cache the display values
1420
+
1421
+ edits.forEach(edit => {
1422
+ var _edit$column2, _edit$row2;
1423
+
1424
+ var {
1425
+ text
1426
+ } = edit;
1427
+ var x = (_edit$column2 = edit.column) !== null && _edit$column2 !== void 0 ? _edit$column2 : edit.x;
1428
+ var y = (_edit$row2 = edit.row) !== null && _edit$row2 !== void 0 ? _edit$row2 : edit.y;
1429
+ var column = _this8.columns[x];
1430
+ var value = TableUtils.makeValue(column.type, text, _this8.formatter.timeZone);
1431
+ var formattedText = value != null ? _this8.displayString(value, column.type, column.name) : null;
1432
+
1433
+ _this8.cachePendingValue(x, y, formattedText); // Take care of updates to the pending new area as well, as that can be updated synchronously
1434
+
1435
+
1436
+ var pendingRow = _this8.pendingRow(y);
1437
+
1438
+ if (pendingRow != null) {
1439
+ if (!newDataMap.has(pendingRow)) {
1440
+ newDataMap.set(pendingRow, {
1441
+ data: new Map()
1442
+ });
1443
+ }
1444
+
1445
+ var row = newDataMap.get(pendingRow);
1446
+ var {
1447
+ data: rowData
1448
+ } = row;
1449
+ var newRowData = new Map(rowData);
1450
+
1451
+ if (value != null) {
1452
+ newRowData.set(x, {
1453
+ value
1454
+ });
1455
+ } else {
1456
+ newRowData.delete(x);
1457
+ }
1458
+
1459
+ if (newRowData.size > 0) {
1460
+ newDataMap.set(pendingRow, _objectSpread(_objectSpread({}, row), {}, {
1461
+ data: newRowData
1462
+ }));
1463
+ } else {
1464
+ newDataMap.delete(pendingRow);
1465
+ }
1466
+ }
1467
+ });
1468
+ _this8.pendingDataMap = newDataMap; // Send an update right after setting the pending map so the values are displayed immediately
1469
+
1470
+ _this8.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED)); // Need to group by row...
1471
+
1472
+
1473
+ var rowEditMap = edits.reduce((rowMap, edit) => {
1474
+ var _edit$row3;
1475
+
1476
+ var y = (_edit$row3 = edit.row) !== null && _edit$row3 !== void 0 ? _edit$row3 : edit.y;
1477
+
1478
+ if (!rowMap.has(y)) {
1479
+ rowMap.set(y, []);
1480
+ }
1481
+
1482
+ rowMap.get(y).push(edit);
1483
+ return rowMap;
1484
+ }, new Map());
1485
+ var ranges = GridRange.consolidate(edits.map(edit => {
1486
+ var _edit$column3, _edit$row4;
1487
+
1488
+ return GridRange.makeCell((_edit$column3 = edit.column) !== null && _edit$column3 !== void 0 ? _edit$column3 : edit.x, (_edit$row4 = edit.row) !== null && _edit$row4 !== void 0 ? _edit$row4 : edit.y);
1489
+ }));
1490
+
1491
+ var tableAreaRange = _this8.getTableAreaRange();
1492
+
1493
+ var tableRanges = ranges.map(range => GridRange.intersection(tableAreaRange, range)).filter(range => range != null);
1494
+
1495
+ if (tableRanges.length > 0) {
1496
+ // Get a snapshot of the full rows, as we need to write a full row when editing
1497
+ var data = yield _this8.snapshot(tableRanges.map(range => new GridRange(null, range.startRow, null, range.endRow)));
1498
+ var newRows = data.map((row, dataIndex) => {
1499
+ var rowIndex = null;
1500
+ var r = dataIndex;
1501
+
1502
+ for (var i = 0; i < tableRanges.length; i += 1) {
1503
+ var range = tableRanges[i];
1504
+ var rangeRowCount = GridRange.rowCount([range]);
1505
+
1506
+ if (r < rangeRowCount) {
1507
+ rowIndex = range.startRow + r;
1508
+ break;
1509
+ }
1510
+
1511
+ r -= rangeRowCount;
1512
+ }
1513
+
1514
+ var newRow = {};
1515
+
1516
+ for (var c = 0; c < _this8.columns.length; c += 1) {
1517
+ newRow[_this8.columns[c].name] = row[c];
1518
+ }
1519
+
1520
+ var rowEdits = rowEditMap.get(rowIndex);
1521
+
1522
+ if (rowEdits != null) {
1523
+ rowEdits.forEach(edit => {
1524
+ var _edit$column4;
1525
+
1526
+ var column = _this8.columns[(_edit$column4 = edit.column) !== null && _edit$column4 !== void 0 ? _edit$column4 : edit.x];
1527
+ newRow[column.name] = TableUtils.makeValue(column.type, edit.text, _this8.formatter.timeZone);
1528
+ });
1529
+ }
1530
+
1531
+ return newRow;
1532
+ });
1533
+ log.info('setValues setting tableRanges', tableRanges);
1534
+ var result = yield _this8.inputTable.addRows(newRows);
1535
+ log.info('setValues set tableRanges', tableRanges, 'SUCCESS', result);
1536
+ } // We've sent the changes to the server, but have not yet got an update with those changes committed
1537
+ // Add the changes to the formatted cache so it's still displayed until the update event is received
1538
+ // The update event could be received on the next tick, after the input rows have been committed,
1539
+ // so make sure we don't display stale data
1540
+
1541
+
1542
+ edits.forEach(edit => {
1543
+ var _edit$column5, _edit$row5;
1544
+
1545
+ var {
1546
+ text
1547
+ } = edit;
1548
+ var x = (_edit$column5 = edit.column) !== null && _edit$column5 !== void 0 ? _edit$column5 : edit.x;
1549
+ var y = (_edit$row5 = edit.row) !== null && _edit$row5 !== void 0 ? _edit$row5 : edit.y;
1550
+ var column = _this8.columns[x];
1551
+ var value = TableUtils.makeValue(column.type, text, _this8.formatter.timeZone);
1552
+ var formattedText = value != null ? _this8.displayString(value, column.type, column.name) : null;
1553
+
1554
+ _this8.cacheFormattedValue(x, y, formattedText);
1555
+ });
1556
+ } finally {
1557
+ edits.forEach(edit => {
1558
+ _this8.clearPendingValue(edit.column, edit.row);
1559
+ });
1560
+ }
1561
+ })();
1562
+ }
1563
+
1564
+ commitPending() {
1565
+ var _this9 = this;
1566
+
1567
+ return _asyncToGenerator(function* () {
1568
+ if (_this9.pendingNewDataMap.size <= 0) {
1569
+ throw new Error('No pending changes to commit');
1570
+ }
1571
+
1572
+ try {
1573
+ var _this9$viewport$botto, _this9$viewport;
1574
+
1575
+ _this9.isSaveInProgress = true;
1576
+ var newRows = [];
1577
+
1578
+ _this9.pendingNewDataMap.forEach(row => {
1579
+ var newRow = {};
1580
+ row.data.forEach((_ref3, columnIndex) => {
1581
+ var {
1582
+ value
1583
+ } = _ref3;
1584
+ var column = _this9.columns[columnIndex];
1585
+ newRow[column.name] = value;
1586
+ });
1587
+ newRows.push(newRow);
1588
+ });
1589
+
1590
+ var result = yield _this9.inputTable.addRows(newRows);
1591
+ log.debug('commitPending()', _this9.pendingNewDataMap, 'result', result);
1592
+ _this9.pendingNewDataMap = new Map();
1593
+ _this9.pendingNewDataErrors = new Map();
1594
+ _this9.pendingNewRowCount = Math.max(0, ((_this9$viewport$botto = (_this9$viewport = _this9.viewport) === null || _this9$viewport === void 0 ? void 0 : _this9$viewport.bottom) !== null && _this9$viewport$botto !== void 0 ? _this9$viewport$botto : 0) - _this9.table.size);
1595
+ _this9.formattedStringData = [];
1596
+
1597
+ _this9.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.PENDING_DATA_UPDATED));
1598
+
1599
+ return result;
1600
+ } finally {
1601
+ _this9.isSaveInProgress = false;
1602
+ }
1603
+ })();
1604
+ }
1605
+
1606
+ editValueForCell(x, y) {
1607
+ return this.textValueForCell(x, y);
1608
+ }
1609
+
1610
+ delete(ranges) {
1611
+ var _this10 = this;
1612
+
1613
+ return _asyncToGenerator(function* () {
1614
+ if (!_this10.isDeletableRanges(ranges)) {
1615
+ throw new Error('Undeletable ranges', ranges);
294
1616
  }
295
1617
 
296
- assertNotNull(_this2.inputTable);
297
1618
  var {
298
1619
  keyColumns
299
- } = _this2.inputTable;
1620
+ } = _this10.inputTable;
300
1621
 
301
1622
  if (keyColumns.length === 0) {
302
1623
  throw new Error('No key columns to allow deletion');
303
1624
  }
304
1625
 
305
- var pendingAreaRange = _this2.getPendingAreaRange();
1626
+ var pendingAreaRange = _this10.getPendingAreaRange();
306
1627
 
307
- var pendingRanges = ranges.map(range => GridRange.intersection(pendingAreaRange, range)).filter(range => range != null).map(range => {
308
- assertNotNull(range);
309
- return GridRange.offset(range, 0, -(_this2.floatingTopRowCount + _this2.table.size));
310
- });
1628
+ var pendingRanges = ranges.map(range => GridRange.intersection(pendingAreaRange, range)).filter(range => range != null).map(range => GridRange.offset(range, 0, -(_this10.floatingTopRowCount + _this10.table.size)));
311
1629
 
312
1630
  if (pendingRanges.length > 0) {
313
- var newDataMap = new Map(_superprop_getPendingDataMap());
1631
+ var newDataMap = new Map(_this10.pendingNewDataMap);
314
1632
 
315
1633
  for (var i = 0; i < pendingRanges.length; i += 1) {
316
1634
  var pendingRange = pendingRanges[i];
317
- assertNotNull(pendingRange.startRow);
318
- assertNotNull(pendingRange.endRow);
319
1635
 
320
1636
  for (var r = pendingRange.startRow; r <= pendingRange.endRow; r += 1) {
321
1637
  newDataMap.delete(r);
322
1638
  }
323
1639
  }
324
1640
 
325
- _superprop_setPendingDataMap(newDataMap);
326
-
327
- _this2.formattedStringData = [];
1641
+ _this10.pendingNewDataMap = newDataMap;
1642
+ _this10.formattedStringData = [];
328
1643
 
329
- _this2.dispatchEvent(new EventShimCustomEvent(IrisGridModel.EVENT.PENDING_DATA_UPDATED));
1644
+ _this10.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.PENDING_DATA_UPDATED));
330
1645
 
331
- _this2.dispatchEvent(new EventShimCustomEvent(IrisGridModel.EVENT.UPDATED));
1646
+ _this10.dispatchEvent(new CustomEvent(IrisGridModel.EVENT.UPDATED));
332
1647
  }
333
1648
 
334
- var tableAreaRange = _this2.getTableAreaRange();
1649
+ var tableAreaRange = _this10.getTableAreaRange();
335
1650
 
336
1651
  var tableRanges = ranges.map(range => GridRange.intersection(tableAreaRange, range)).filter(range => range != null);
337
1652
 
338
1653
  if (tableRanges.length <= 0) {
339
- return;
1654
+ return null;
340
1655
  }
341
1656
 
342
1657
  var [data, deleteTable] = yield Promise.all([// Need to get the key values of each row
343
- _this2.snapshot(tableRanges.map(range => {
344
- assertNotNull(range);
345
- return new GridRange(0, range.startRow, keyColumns.length - 1, range.endRow);
346
- })), _this2.table.copy()]); // Now copy the existing table and filter it on the values in the snapshot for the key columns in the input table
1658
+ _this10.snapshot(tableRanges.map(range => new GridRange(0, range.startRow, keyColumns.length - 1, range.endRow))), _this10.table.copy()]); // Now copy the existing table and filter it on the values in the snapshot for the key columns in the input table
347
1659
 
348
1660
  var filters = data.map(row => {
349
1661
  var columnFilters = [];
@@ -362,11 +1674,22 @@ class IrisGridTableModel extends IrisGridTableModelTemplate {
362
1674
  });
363
1675
  var filter = filters.reduce((agg, curr) => agg ? agg.or(curr) : curr);
364
1676
  deleteTable.applyFilter([filter]);
365
- yield (_this2$inputTable = _this2.inputTable) === null || _this2$inputTable === void 0 ? void 0 : _this2$inputTable.deleteTable(deleteTable);
1677
+ var result = yield _this10.inputTable.deleteTable(deleteTable);
366
1678
  deleteTable.close();
1679
+ return result;
367
1680
  })();
368
1681
  }
369
1682
 
1683
+ isValidForCell(x, y, value) {
1684
+ try {
1685
+ var column = this.columns[x];
1686
+ TableUtils.makeValue(column.type, value, this.formatter.timeZone);
1687
+ return true;
1688
+ } catch (e) {
1689
+ return false;
1690
+ }
1691
+ }
1692
+
370
1693
  }
371
1694
 
372
1695
  _defineProperty(IrisGridTableModel, "ROW_BUFFER_PAGES", 1);