@sisense/sdk-pivot-query-client 2.17.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 (189) hide show
  1. package/LICENSE.md +35 -0
  2. package/README.md +2 -0
  3. package/dist/__test-helpers__/testUtils.d.ts +30 -0
  4. package/dist/__test-helpers__/testUtils.js +89 -0
  5. package/dist/builders/index.d.ts +2 -0
  6. package/dist/builders/index.js +2 -0
  7. package/dist/builders/pivot-data-builder.d.ts +34 -0
  8. package/dist/builders/pivot-data-builder.js +182 -0
  9. package/dist/builders/socket-builder.d.ts +18 -0
  10. package/dist/builders/socket-builder.js +72 -0
  11. package/dist/cjs/__test-helpers__/testUtils.d.ts +30 -0
  12. package/dist/cjs/__test-helpers__/testUtils.js +104 -0
  13. package/dist/cjs/builders/index.d.ts +2 -0
  14. package/dist/cjs/builders/index.js +7 -0
  15. package/dist/cjs/builders/pivot-data-builder.d.ts +34 -0
  16. package/dist/cjs/builders/pivot-data-builder.js +186 -0
  17. package/dist/cjs/builders/socket-builder.d.ts +18 -0
  18. package/dist/cjs/builders/socket-builder.js +79 -0
  19. package/dist/cjs/data-handling/DataService.d.ts +672 -0
  20. package/dist/cjs/data-handling/DataService.js +1364 -0
  21. package/dist/cjs/data-handling/DivergenceComparator.d.ts +7 -0
  22. package/dist/cjs/data-handling/DivergenceComparator.js +20 -0
  23. package/dist/cjs/data-handling/constants.d.ts +44 -0
  24. package/dist/cjs/data-handling/constants.js +43 -0
  25. package/dist/cjs/data-handling/index.d.ts +3 -0
  26. package/dist/cjs/data-handling/index.js +23 -0
  27. package/dist/cjs/data-handling/types.d.ts +104 -0
  28. package/dist/cjs/data-handling/types.js +2 -0
  29. package/dist/cjs/data-handling/utils/createPivotTreeNode.d.ts +13 -0
  30. package/dist/cjs/data-handling/utils/createPivotTreeNode.js +21 -0
  31. package/dist/cjs/data-handling/utils/index.d.ts +4 -0
  32. package/dist/cjs/data-handling/utils/index.js +14 -0
  33. package/dist/cjs/data-handling/utils/jaqlProcessor.d.ts +122 -0
  34. package/dist/cjs/data-handling/utils/jaqlProcessor.js +661 -0
  35. package/dist/cjs/data-handling/utils/pivotTransforms.d.ts +74 -0
  36. package/dist/cjs/data-handling/utils/pivotTransforms.js +373 -0
  37. package/dist/cjs/data-handling/utils/plugins/PluginService.d.ts +135 -0
  38. package/dist/cjs/data-handling/utils/plugins/PluginService.js +383 -0
  39. package/dist/cjs/data-handling/utils/plugins/getters.d.ts +23 -0
  40. package/dist/cjs/data-handling/utils/plugins/getters.js +70 -0
  41. package/dist/cjs/data-handling/utils/plugins/types.d.ts +75 -0
  42. package/dist/cjs/data-handling/utils/plugins/types.js +2 -0
  43. package/dist/cjs/data-handling/utils/plugins/validator.d.ts +13 -0
  44. package/dist/cjs/data-handling/utils/plugins/validator.js +169 -0
  45. package/dist/cjs/data-load/AbstractDataLoadService.d.ts +256 -0
  46. package/dist/cjs/data-load/AbstractDataLoadService.js +473 -0
  47. package/dist/cjs/data-load/DataLoadService.d.ts +63 -0
  48. package/dist/cjs/data-load/DataLoadService.js +152 -0
  49. package/dist/cjs/data-load/SisenseDataLoadService.d.ts +44 -0
  50. package/dist/cjs/data-load/SisenseDataLoadService.js +87 -0
  51. package/dist/cjs/data-load/TestDataLoadService.d.ts +27 -0
  52. package/dist/cjs/data-load/TestDataLoadService.js +76 -0
  53. package/dist/cjs/data-load/constants.d.ts +13 -0
  54. package/dist/cjs/data-load/constants.js +28 -0
  55. package/dist/cjs/data-load/index.d.ts +6 -0
  56. package/dist/cjs/data-load/index.js +14 -0
  57. package/dist/cjs/data-load/sockets/SisenseSocket.d.ts +81 -0
  58. package/dist/cjs/data-load/sockets/SisenseSocket.js +162 -0
  59. package/dist/cjs/data-load/sockets/TestSocket.d.ts +61 -0
  60. package/dist/cjs/data-load/sockets/TestSocket.js +90 -0
  61. package/dist/cjs/data-load/sockets/helpers.d.ts +4 -0
  62. package/dist/cjs/data-load/sockets/helpers.js +27 -0
  63. package/dist/cjs/data-load/sockets/index.d.ts +2 -0
  64. package/dist/cjs/data-load/sockets/index.js +8 -0
  65. package/dist/cjs/data-load/types.d.ts +90 -0
  66. package/dist/cjs/data-load/types.js +2 -0
  67. package/dist/cjs/errors/LoadingCanceledError.d.ts +7 -0
  68. package/dist/cjs/errors/LoadingCanceledError.js +24 -0
  69. package/dist/cjs/errors/index.d.ts +1 -0
  70. package/dist/cjs/errors/index.js +6 -0
  71. package/dist/cjs/index.d.ts +17 -0
  72. package/dist/cjs/index.js +32 -0
  73. package/dist/cjs/package.json +12 -0
  74. package/dist/cjs/pivot-query-client.d.ts +13 -0
  75. package/dist/cjs/pivot-query-client.js +26 -0
  76. package/dist/cjs/tree-structure/AbstractTreeService.d.ts +308 -0
  77. package/dist/cjs/tree-structure/AbstractTreeService.js +716 -0
  78. package/dist/cjs/tree-structure/HeaderTreeService.d.ts +180 -0
  79. package/dist/cjs/tree-structure/HeaderTreeService.js +280 -0
  80. package/dist/cjs/tree-structure/TreeCellMap.d.ts +104 -0
  81. package/dist/cjs/tree-structure/TreeCellMap.js +145 -0
  82. package/dist/cjs/tree-structure/TreeService.d.ts +8 -0
  83. package/dist/cjs/tree-structure/TreeService.js +12 -0
  84. package/dist/cjs/tree-structure/constants.d.ts +6 -0
  85. package/dist/cjs/tree-structure/constants.js +10 -0
  86. package/dist/cjs/tree-structure/index.d.ts +5 -0
  87. package/dist/cjs/tree-structure/index.js +10 -0
  88. package/dist/cjs/tree-structure/types.d.ts +93 -0
  89. package/dist/cjs/tree-structure/types.js +2 -0
  90. package/dist/cjs/tree-structure/utils/index.d.ts +1 -0
  91. package/dist/cjs/tree-structure/utils/index.js +9 -0
  92. package/dist/cjs/tree-structure/utils/treeNode.d.ts +147 -0
  93. package/dist/cjs/tree-structure/utils/treeNode.js +534 -0
  94. package/dist/cjs/utils/array.d.ts +13 -0
  95. package/dist/cjs/utils/array.js +25 -0
  96. package/dist/cjs/utils/cloneObject.d.ts +30 -0
  97. package/dist/cjs/utils/cloneObject.js +225 -0
  98. package/dist/cjs/utils/index.d.ts +3 -0
  99. package/dist/cjs/utils/index.js +9 -0
  100. package/dist/cjs/utils/throttle.d.ts +12 -0
  101. package/dist/cjs/utils/throttle.js +39 -0
  102. package/dist/cjs/utils/types.d.ts +12 -0
  103. package/dist/cjs/utils/types.js +2 -0
  104. package/dist/data-handling/DataService.d.ts +672 -0
  105. package/dist/data-handling/DataService.js +1357 -0
  106. package/dist/data-handling/DivergenceComparator.d.ts +7 -0
  107. package/dist/data-handling/DivergenceComparator.js +16 -0
  108. package/dist/data-handling/constants.d.ts +44 -0
  109. package/dist/data-handling/constants.js +40 -0
  110. package/dist/data-handling/index.d.ts +3 -0
  111. package/dist/data-handling/index.js +4 -0
  112. package/dist/data-handling/types.d.ts +104 -0
  113. package/dist/data-handling/types.js +1 -0
  114. package/dist/data-handling/utils/createPivotTreeNode.d.ts +13 -0
  115. package/dist/data-handling/utils/createPivotTreeNode.js +17 -0
  116. package/dist/data-handling/utils/index.d.ts +4 -0
  117. package/dist/data-handling/utils/index.js +4 -0
  118. package/dist/data-handling/utils/jaqlProcessor.d.ts +122 -0
  119. package/dist/data-handling/utils/jaqlProcessor.js +621 -0
  120. package/dist/data-handling/utils/pivotTransforms.d.ts +74 -0
  121. package/dist/data-handling/utils/pivotTransforms.js +335 -0
  122. package/dist/data-handling/utils/plugins/PluginService.d.ts +135 -0
  123. package/dist/data-handling/utils/plugins/PluginService.js +379 -0
  124. package/dist/data-handling/utils/plugins/getters.d.ts +23 -0
  125. package/dist/data-handling/utils/plugins/getters.js +65 -0
  126. package/dist/data-handling/utils/plugins/types.d.ts +75 -0
  127. package/dist/data-handling/utils/plugins/types.js +1 -0
  128. package/dist/data-handling/utils/plugins/validator.d.ts +13 -0
  129. package/dist/data-handling/utils/plugins/validator.js +165 -0
  130. package/dist/data-load/AbstractDataLoadService.d.ts +256 -0
  131. package/dist/data-load/AbstractDataLoadService.js +466 -0
  132. package/dist/data-load/DataLoadService.d.ts +63 -0
  133. package/dist/data-load/DataLoadService.js +148 -0
  134. package/dist/data-load/SisenseDataLoadService.d.ts +44 -0
  135. package/dist/data-load/SisenseDataLoadService.js +83 -0
  136. package/dist/data-load/TestDataLoadService.d.ts +27 -0
  137. package/dist/data-load/TestDataLoadService.js +69 -0
  138. package/dist/data-load/constants.d.ts +13 -0
  139. package/dist/data-load/constants.js +25 -0
  140. package/dist/data-load/index.d.ts +6 -0
  141. package/dist/data-load/index.js +6 -0
  142. package/dist/data-load/sockets/SisenseSocket.d.ts +81 -0
  143. package/dist/data-load/sockets/SisenseSocket.js +155 -0
  144. package/dist/data-load/sockets/TestSocket.d.ts +61 -0
  145. package/dist/data-load/sockets/TestSocket.js +83 -0
  146. package/dist/data-load/sockets/helpers.d.ts +4 -0
  147. package/dist/data-load/sockets/helpers.js +23 -0
  148. package/dist/data-load/sockets/index.d.ts +2 -0
  149. package/dist/data-load/sockets/index.js +3 -0
  150. package/dist/data-load/types.d.ts +90 -0
  151. package/dist/data-load/types.js +1 -0
  152. package/dist/errors/LoadingCanceledError.d.ts +7 -0
  153. package/dist/errors/LoadingCanceledError.js +20 -0
  154. package/dist/errors/index.d.ts +1 -0
  155. package/dist/errors/index.js +2 -0
  156. package/dist/index.d.ts +17 -0
  157. package/dist/index.js +9 -0
  158. package/dist/pivot-query-client.d.ts +13 -0
  159. package/dist/pivot-query-client.js +22 -0
  160. package/dist/tree-structure/AbstractTreeService.d.ts +308 -0
  161. package/dist/tree-structure/AbstractTreeService.js +712 -0
  162. package/dist/tree-structure/HeaderTreeService.d.ts +180 -0
  163. package/dist/tree-structure/HeaderTreeService.js +276 -0
  164. package/dist/tree-structure/TreeCellMap.d.ts +104 -0
  165. package/dist/tree-structure/TreeCellMap.js +141 -0
  166. package/dist/tree-structure/TreeService.d.ts +8 -0
  167. package/dist/tree-structure/TreeService.js +8 -0
  168. package/dist/tree-structure/constants.d.ts +6 -0
  169. package/dist/tree-structure/constants.js +7 -0
  170. package/dist/tree-structure/index.d.ts +5 -0
  171. package/dist/tree-structure/index.js +4 -0
  172. package/dist/tree-structure/types.d.ts +93 -0
  173. package/dist/tree-structure/types.js +1 -0
  174. package/dist/tree-structure/utils/index.d.ts +1 -0
  175. package/dist/tree-structure/utils/index.js +1 -0
  176. package/dist/tree-structure/utils/treeNode.d.ts +147 -0
  177. package/dist/tree-structure/utils/treeNode.js +515 -0
  178. package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
  179. package/dist/utils/array.d.ts +13 -0
  180. package/dist/utils/array.js +21 -0
  181. package/dist/utils/cloneObject.d.ts +30 -0
  182. package/dist/utils/cloneObject.js +221 -0
  183. package/dist/utils/index.d.ts +3 -0
  184. package/dist/utils/index.js +3 -0
  185. package/dist/utils/throttle.d.ts +12 -0
  186. package/dist/utils/throttle.js +35 -0
  187. package/dist/utils/types.d.ts +12 -0
  188. package/dist/utils/types.js +1 -0
  189. package/package.json +61 -0
@@ -0,0 +1,712 @@
1
+ import { Position } from './constants.js';
2
+ import { TreeCellMap } from './TreeCellMap.js';
3
+ import { treeNode } from './utils/index.js';
4
+ const keyCreator = (rowIndex, columnIndex) => `${rowIndex}-${columnIndex}`;
5
+ /**
6
+ * AbstractTreeService required as parent class to solve circular dependencies
7
+ * TreeService converts tree structure into grid structure, also it keeps inner grid structure
8
+ * to update cache system (via setCellCache) and receive merged cells (via updateMainCellMargins)
9
+ */
10
+ export class AbstractTreeService {
11
+ constructor(tree, isVertical = false, deep) {
12
+ this.hasGrandTotals = false;
13
+ /**
14
+ * Defines if tree will be converted to vertical or horizontal grid
15
+ *
16
+ *
17
+ * @private
18
+ */
19
+ this.isVertical = false;
20
+ /**
21
+ * Cache tree nodes by deep levels
22
+ *
23
+ *
24
+ * @private
25
+ */
26
+ this.columns = [];
27
+ /**
28
+ * Cache last levels tree nodes
29
+ *
30
+ *
31
+ * @private
32
+ */
33
+ this.lastLevel = [];
34
+ /**
35
+ * Mapping object between tree<>grid
36
+ *
37
+ *
38
+ * @private
39
+ */
40
+ this.map = {};
41
+ /**
42
+ * Metadata cache object
43
+ *
44
+ *
45
+ * @private
46
+ */
47
+ this.metadataCache = {};
48
+ this.isVertical = isVertical;
49
+ this.deep = deep;
50
+ if (tree) {
51
+ this.tree = tree;
52
+ this.columns = this.cacheLevels(treeNode.getChildren(this.tree));
53
+ }
54
+ }
55
+ destroy() {
56
+ this.tree = undefined;
57
+ this.columns = [];
58
+ this.lastLevel = [];
59
+ this.map = {};
60
+ this.metadataCache = {};
61
+ this.valueNode = undefined;
62
+ this.grid = undefined;
63
+ }
64
+ getMainCellWidth(rowIndex, columnIndex, columnWidth, borderWidth, options = { offsetTop: -1, columnsOffset: 0 }) {
65
+ const { columnsOffset = 0 } = options;
66
+ const item = this.getItem(rowIndex, columnIndex);
67
+ const isMergedColumn = item && item.hasChildren() && item.hasColCell();
68
+ let width = Number.NaN;
69
+ let hasAllWidth = true;
70
+ if (item && isMergedColumn) {
71
+ const childColCells = item.getColCell();
72
+ const parentItemWidth = columnWidth({ index: columnIndex + columnsOffset });
73
+ width = childColCells.reduce((prev, curr) => {
74
+ const currentWidth = columnWidth({ index: curr.colIndex + columnsOffset });
75
+ if (!currentWidth) {
76
+ hasAllWidth = false;
77
+ }
78
+ return prev + currentWidth;
79
+ }, parentItemWidth);
80
+ width -= borderWidth;
81
+ width = Math.ceil(width);
82
+ }
83
+ return hasAllWidth ? width : Number.NaN;
84
+ }
85
+ /**
86
+ * Adds additional tree node to current state
87
+ *
88
+ * @param {TreeNode} tree - new treeNode
89
+ * @returns {void}
90
+ */
91
+ extend(tree) {
92
+ if (tree) {
93
+ this.grid = undefined;
94
+ this.tree = treeNode.merge(this.tree, tree);
95
+ this.columns = this.cacheLevels(treeNode.getChildren(tree), this.columns);
96
+ }
97
+ }
98
+ /**
99
+ * Returns grid (2d list) of tree structure
100
+ *
101
+ * @returns {Array<Array<TreeNode | string>>} - 2d list
102
+ */
103
+ getGrid() {
104
+ if (this.grid) {
105
+ return this.grid;
106
+ }
107
+ let rows = this.getTreeDeepsLength();
108
+ let cols = this.getTreeChildLength();
109
+ if (this.isVertical) {
110
+ [rows, cols] = [cols, rows];
111
+ this.map = this.fillMapVertical(treeNode.getChildren(this.tree), cols, this.map);
112
+ }
113
+ else {
114
+ this.map = this.fillMap(treeNode.getChildren(this.tree), rows, this.map);
115
+ }
116
+ this.grid = Array.from(Array(rows)).map((rO, rowIndex) => Array.from(Array(cols)).map((cO, colIndex) => {
117
+ const key = keyCreator(rowIndex, colIndex);
118
+ const mapItem = this.map[key];
119
+ if (!mapItem) {
120
+ throw new Error(`Key "${key}" does not found in TreeService`);
121
+ }
122
+ return mapItem.node ? mapItem.node : mapItem.parent;
123
+ }));
124
+ return this.grid;
125
+ }
126
+ /**
127
+ * Returns part of current grid according to "from" - "to" position
128
+ *
129
+ * @param {number} from - start rows index for partial grid
130
+ * @param {number} to - stop rows index for partial grid
131
+ * @returns {Array<Array<TreeNode | string>>} - partial grid
132
+ */
133
+ getPartialGrid(from, to) {
134
+ if (!this.isVertical) {
135
+ throw new Error('"getPartialGrid" can only be used for "vertical" tree');
136
+ }
137
+ const cols = this.getTreeDeepsLength();
138
+ const treeChild = treeNode.getChildren(this.tree);
139
+ const { nodes, start, stop } = treeNode.getNodesByChildCount(treeChild, from, to);
140
+ this.fillMapVertical(nodes, cols, this.map, {
141
+ parentRowIndex: start,
142
+ parentColIndex: 0,
143
+ prevChildren: 0,
144
+ parentKey: '',
145
+ });
146
+ const finalFrom = Math.max(start, from);
147
+ const finalTo = Math.min(stop, to);
148
+ const finalCount = Math.max(0, finalTo - from);
149
+ return Array.from(Array(finalCount)).map((rO, rowIndex) => Array.from(Array(cols)).map((cO, colIndex) => {
150
+ const index = finalFrom + rowIndex;
151
+ const key = keyCreator(index, colIndex);
152
+ const mapItem = this.map[key];
153
+ if (!mapItem) {
154
+ throw new Error(`Key "${key}" does not found in TreeService`);
155
+ }
156
+ return mapItem.node ? mapItem.node : mapItem.parent || '';
157
+ }));
158
+ }
159
+ /**
160
+ * Returns part of current tree with possible cut nodes according to "from" - "to" position
161
+ *
162
+ * @param {number} from - start rows index for partial grid
163
+ * @param {number} [to] - stop rows index for partial grid
164
+ * @param {object} [options] - additional options
165
+ * @param {Function} [options.cloneFn] - replace default clone function with specific one
166
+ * @returns {Array<TreeNode>} - partial tree
167
+ */
168
+ getPartialTree(from, to, options) {
169
+ const treeChild = treeNode.getChildren(this.tree);
170
+ return treeNode.getCutNodesByChildCount(treeChild, from, to, options);
171
+ }
172
+ /**
173
+ * Returns TreeNode item if exist for appropriate coordinates (rowIndex, columnIndex)
174
+ *
175
+ * @param {number} rowIndex - row index
176
+ * @param {number} columnIndex - column index
177
+ * @returns {TreeNode|undefined} - TreeNode item
178
+ */
179
+ getTreeNode(rowIndex, columnIndex) {
180
+ const mapItem = this.getItem(rowIndex, columnIndex);
181
+ if (mapItem && mapItem.node) {
182
+ return mapItem.node;
183
+ }
184
+ return undefined;
185
+ }
186
+ /**
187
+ * Defines if cell with (rowIndex, columnIndex) coordinate is children cell or main one
188
+ *
189
+ * @param {number} rowIndex - row index of the cell
190
+ * @param {number} columnIndex - column index of the cell
191
+ * @returns {boolean} - true - if children, false if main one
192
+ */
193
+ isChildren(rowIndex, columnIndex) {
194
+ const item = this.getItem(rowIndex, columnIndex);
195
+ if (item) {
196
+ return item.isChild();
197
+ // eslint-disable-next-line max-lines
198
+ }
199
+ if (typeof this.deep === 'number') {
200
+ if ((this.isVertical ? columnIndex : rowIndex) < this.deep) {
201
+ return true;
202
+ }
203
+ }
204
+ throw new Error(`Item "${rowIndex}-${columnIndex}" does not found in TreeService`);
205
+ }
206
+ /**
207
+ * Defines if cell with (rowIndex, columnIndex) coordinate has children column/row cells or not
208
+ *
209
+ * @param {number} rowIndex - row index of the cell
210
+ * @param {number} columnIndex - column index of the cell
211
+ * @returns {boolean} - true - has children column/row cells, false - does not have
212
+ */
213
+ hasChildren(rowIndex, columnIndex) {
214
+ const item = this.getItem(rowIndex, columnIndex);
215
+ if (item) {
216
+ return item.hasChildren();
217
+ }
218
+ throw new Error(`Item "${rowIndex}-${columnIndex}" does not found in TreeService`);
219
+ }
220
+ /**
221
+ * Updates merge object for the cell if it has children cells
222
+ *
223
+ * @param {number} rowIndex - cell row index
224
+ * @param {number} columnIndex - cell column index
225
+ * @returns {object} - new merge object
226
+ */
227
+ getMainCellSpans(rowIndex, columnIndex) {
228
+ const spans = {};
229
+ const mainItem = this.getItem(rowIndex, columnIndex);
230
+ if (mainItem && mainItem.hasColCell()) {
231
+ spans.colSpan = mainItem.getColCell().length + 1;
232
+ }
233
+ if (mainItem && mainItem.hasRowCell()) {
234
+ spans.rowSpan = mainItem.getRowCell().length + 1;
235
+ }
236
+ return spans;
237
+ }
238
+ /**
239
+ * Align start index in case of long merged cell
240
+ *
241
+ * @param {number} startIndex - initial start index
242
+ * @param {boolean} isVertical - defines if it is vertical grid or not
243
+ * @returns {number} - new start index
244
+ */
245
+ alignStartIndex(startIndex, isVertical = false) {
246
+ let row = 0;
247
+ let col = startIndex;
248
+ if (isVertical) {
249
+ row = startIndex;
250
+ col = 0;
251
+ }
252
+ if (this.isVertical === isVertical) {
253
+ let curItem = this.getItem(row, col);
254
+ if (curItem && curItem.isChild()) {
255
+ curItem = this.getItemByKey(curItem.parent || '');
256
+ }
257
+ if (curItem) {
258
+ return isVertical ? curItem.rowIndex : curItem.colIndex;
259
+ }
260
+ }
261
+ return startIndex;
262
+ }
263
+ /**
264
+ * Align stop index in case of long merged cell
265
+ *
266
+ * @param {number} stopIndex - initial stop index
267
+ * @param {boolean} isVertical - defines if it is vertical grid or not
268
+ * @returns {number} - new stop index
269
+ */
270
+ alignStopIndex(stopIndex, isVertical = false) {
271
+ let row = 0;
272
+ let col = stopIndex;
273
+ if (isVertical) {
274
+ row = stopIndex;
275
+ col = 0;
276
+ }
277
+ if (this.isVertical === isVertical) {
278
+ let curItem = this.getItem(row, col);
279
+ if (curItem && curItem.isChild()) {
280
+ curItem = this.getItemByKey(curItem.parent || '');
281
+ }
282
+ if (curItem) {
283
+ return isVertical ? curItem.getStopRowIndex() : curItem.getStopColIndex();
284
+ }
285
+ }
286
+ return stopIndex;
287
+ }
288
+ /**
289
+ * Returns number of last children for the tree
290
+ *
291
+ * @param {Array<TreeNode> | TreeNode} item - tree node or list of nodes
292
+ * @param {{ callCount: number, clearCache: boolean }} options - options for state
293
+ * @returns {number} - count of last children
294
+ */
295
+ getTreeChildLength(item = treeNode.getChildren(this.tree), options) {
296
+ return treeNode.getChildLength(item, options);
297
+ }
298
+ /**
299
+ * Returns deep level of the tree
300
+ *
301
+ * @param {Array<TreeNode> | TreeNode} item - tree node or list of nodes
302
+ * @param {{ callCount: number, clearCache: boolean }} options - options for inner state
303
+ * @returns {number} - count of last children
304
+ */
305
+ getTreeDeepsLength(item = treeNode.getChildren(this.tree), options) {
306
+ if (typeof this.deep !== 'undefined' && this.deep !== undefined) {
307
+ return this.deep;
308
+ }
309
+ return treeNode.getDeepLength(item, options);
310
+ }
311
+ /**
312
+ * Returns array of last tree nodes
313
+ *
314
+ * @returns {Array<TreeNode>} - list of tree nodes
315
+ */
316
+ getLastLevelNodes() {
317
+ return this.lastLevel;
318
+ }
319
+ /**
320
+ * Extract 2D array of data base on columnsTreeService
321
+ *
322
+ * @param {TreeServiceI} columnsTreeService - tree service according to which align the data
323
+ * @returns {Array<Array<any>>} - 2D array of data
324
+ */
325
+ extractData(columnsTreeService) {
326
+ if (!columnsTreeService) {
327
+ return [];
328
+ }
329
+ const columsLastNodes = columnsTreeService.getLastLevelNodes();
330
+ const sortIndexes = columsLastNodes.map((node) => node.index);
331
+ return this.getLastLevelNodes().map((node) => {
332
+ if (typeof node.data === 'undefined') {
333
+ return [node.data];
334
+ }
335
+ if (sortIndexes) {
336
+ return sortIndexes.map((index) => {
337
+ let data;
338
+ if (typeof index !== 'undefined' && node.data) {
339
+ data = node.data[index];
340
+ }
341
+ return data;
342
+ });
343
+ }
344
+ return node.data;
345
+ });
346
+ }
347
+ /**
348
+ * Returns cell meta information
349
+ *
350
+ * @param {number} rowIndex - cell row index
351
+ * @param {number} columnIndex - cell column index
352
+ * @param {{ to: number }} [options] - additional configuration options
353
+ * @returns {{levels: Array<string>, siblings: Array<string>}} - meta information
354
+ */
355
+ // eslint-disable-next-line max-lines-per-function,sonarjs/cognitive-complexity
356
+ getMetadata(rowIndex, columnIndex, options) {
357
+ const levelCount = this.getTreeDeepsLength();
358
+ if (rowIndex === Infinity) {
359
+ // eslint-disable-next-line no-param-reassign
360
+ rowIndex = levelCount ? levelCount - 1 : levelCount;
361
+ }
362
+ if (columnIndex === Infinity) {
363
+ // eslint-disable-next-line no-param-reassign
364
+ columnIndex = levelCount ? levelCount - 1 : levelCount;
365
+ }
366
+ const key = `${rowIndex}-${columnIndex}`;
367
+ if (this.metadataCache[key]) {
368
+ return this.metadataCache[key];
369
+ }
370
+ let mapItem = this.getItemByKey(key);
371
+ if (!mapItem) {
372
+ throw new Error(`Can not find metadata info for ${key} cell`);
373
+ }
374
+ let nodeItem = mapItem ? mapItem.node : undefined;
375
+ // looking for parent
376
+ if (!nodeItem) {
377
+ mapItem = this.getItemByKey(mapItem.parent || '');
378
+ }
379
+ if (!mapItem) {
380
+ throw new Error(`Can not find metadata info for parent ${key} cell`);
381
+ }
382
+ nodeItem = mapItem ? mapItem.node : undefined;
383
+ const nextMapItem = this.getItemByKey(`${rowIndex + 1}-${columnIndex}`);
384
+ const nextNodeItem = nextMapItem ? nextMapItem.node : undefined;
385
+ // levels info
386
+ const level = (nodeItem && nodeItem.level) || 0;
387
+ const lastLevel = this.isVertical ? mapItem.getStopColIndex() : mapItem.getStopRowIndex();
388
+ // siblings info
389
+ let { indexInParent, siblingCount } = mapItem.getIndexInParent();
390
+ let lastIndexInParent = indexInParent;
391
+ // fix sibling for partial tree top/first level
392
+ if (level === 0) {
393
+ siblingCount = this.getTreeChildLength();
394
+ indexInParent = this.isVertical ? mapItem.rowIndex : mapItem.colIndex;
395
+ lastIndexInParent =
396
+ indexInParent +
397
+ (this.isVertical ? mapItem.getRowCell().length : mapItem.getColCell().length);
398
+ }
399
+ if (options) {
400
+ // pagination
401
+ const maxCount = options.to - options.from;
402
+ if (siblingCount <= maxCount && lastIndexInParent > maxCount - 1) {
403
+ lastIndexInParent = maxCount - 1;
404
+ }
405
+ }
406
+ const data = {
407
+ levels: [],
408
+ siblings: [],
409
+ root: undefined,
410
+ parent: undefined,
411
+ valueNode: this.valueNode,
412
+ nextNode: nextNodeItem,
413
+ };
414
+ const { indexDivergence } = nodeItem || {};
415
+ if (typeof indexDivergence === 'number') {
416
+ const siblingsStatus = indexDivergence === 0 ? Position.EVEN : Position.ODD;
417
+ data.siblings.push(siblingsStatus);
418
+ }
419
+ if (level === 0) {
420
+ data.levels.push(Position.FIRST);
421
+ }
422
+ if (lastLevel === levelCount - 1) {
423
+ data.levels.push(Position.LAST);
424
+ }
425
+ if (indexInParent === 0) {
426
+ data.siblings.push(Position.FIRST);
427
+ }
428
+ if (lastIndexInParent === siblingCount - 1) {
429
+ data.siblings.push(Position.LAST);
430
+ }
431
+ // get root node
432
+ if (nodeItem && level !== 0) {
433
+ const rootRowIndex = this.isVertical ? rowIndex : 0;
434
+ const rootColumnIndex = this.isVertical ? 0 : columnIndex;
435
+ data.root = this.getMetadata(rootRowIndex, rootColumnIndex, options);
436
+ }
437
+ const parentMapItem = this.getItemByKey(mapItem.parent || '');
438
+ // get parent node
439
+ if (parentMapItem && level !== 0) {
440
+ data.parent = this.getMetadata(parentMapItem.rowIndex, parentMapItem.colIndex, options);
441
+ }
442
+ if (options) {
443
+ // pagination
444
+ const startIndex = this.isVertical ? mapItem.rowIndex : mapItem.colIndex;
445
+ const stopIndex = this.isVertical ? mapItem.getStopRowIndex() : mapItem.getStopColIndex();
446
+ let parentStopIndex;
447
+ if (parentMapItem) {
448
+ parentStopIndex = this.isVertical
449
+ ? parentMapItem.getStopRowIndex()
450
+ : parentMapItem.getStopColIndex();
451
+ }
452
+ if (parentStopIndex !== undefined && parentStopIndex >= options.to - options.from) {
453
+ // item is cut
454
+ if (stopIndex >= options.to - options.from - 1 && !data.siblings.includes(Position.LAST)) {
455
+ data.siblings.push(Position.LAST);
456
+ }
457
+ }
458
+ if (startIndex === 0 && !data.siblings.includes(Position.FIRST)) {
459
+ // in paginated case we always has min cell
460
+ data.siblings.push(Position.FIRST);
461
+ }
462
+ }
463
+ this.metadataCache[key] = data;
464
+ return data;
465
+ }
466
+ /**
467
+ * Sets value node when it's single
468
+ *
469
+ * @param {TreeNode} valueNode - values measure node
470
+ * @returns {void}
471
+ */
472
+ setValueNode(valueNode) {
473
+ if (typeof valueNode === 'object') {
474
+ this.valueNode = valueNode;
475
+ }
476
+ }
477
+ /**
478
+ * Fills cache object with nodes by appropriate deep level
479
+ *
480
+ * @param {Array<TreeNode>} list - list of nodes to cache
481
+ * @param {Array<Array<TreeNode>>} cache - cache object
482
+ * @param {{level: number }} options - internal recursive state
483
+ * @returns {Array<Array<TreeNode>>} - cache object
484
+ *
485
+ * @private
486
+ */
487
+ cacheLevels(list, cache = [], options = { level: 0 }) {
488
+ const { level } = options;
489
+ list.forEach((item) => {
490
+ if (!cache[level]) {
491
+ // eslint-disable-next-line no-param-reassign
492
+ cache[level] = [];
493
+ }
494
+ treeNode.setLevel(item, level);
495
+ cache[level].push(item);
496
+ if (treeNode.hasChildren(item)) {
497
+ const childLevel = level + 1;
498
+ this.cacheLevels(treeNode.getChildren(item), cache, { level: childLevel });
499
+ }
500
+ else {
501
+ this.lastLevel.push(item);
502
+ }
503
+ });
504
+ return cache;
505
+ }
506
+ /**
507
+ * Fill horizontal grid map according to tree structure
508
+ *
509
+ * @param {Array<TreeNode>} children - list of tree nodes
510
+ * @param {number} rows - deep level rows
511
+ * @param {object} map - map object to fill
512
+ * @param {{parentColIndex: number, prevChildren: number}} initState - state object for
513
+ * recursive calls
514
+ * @returns {object} - map object
515
+ *
516
+ * @private
517
+ */
518
+ fillMap(children, rows, map = {}, initState) {
519
+ const state = initState || {
520
+ parentRowIndex: 0,
521
+ parentColIndex: 0,
522
+ prevChildren: 0,
523
+ parentKey: '',
524
+ };
525
+ const childCount = children.length;
526
+ children.forEach((item, colIndex) => {
527
+ const { parentRowIndex, parentColIndex, prevChildren, parentKey } = state;
528
+ const rowIndex = treeNode.getLevel(item);
529
+ const rowStart = rowIndex + parentRowIndex;
530
+ const colStart = colIndex + parentColIndex + prevChildren;
531
+ const mainKey = keyCreator(rowStart, colStart);
532
+ const mapMainItem = this.createTreeCellMap({
533
+ rowIndex: rowStart,
534
+ colIndex: colStart,
535
+ node: item,
536
+ parent: parentKey,
537
+ });
538
+ mapMainItem.setIndexInParent(colIndex, childCount);
539
+ map[mainKey] = mapMainItem;
540
+ let col = 0;
541
+ let row = 0;
542
+ if (treeNode.hasChildren(item)) {
543
+ col = this.getTreeChildLength(item);
544
+ if (typeof item.minLevel === 'number') {
545
+ // min level in case values offset
546
+ row = item.minLevel + 1 - rowStart || 0;
547
+ }
548
+ }
549
+ else {
550
+ row = (rows || 0) - (rowStart || 0);
551
+ }
552
+ if (col > 1 || row > 1) {
553
+ // if has merged cells
554
+ this.fillChildMap(map, mainKey, rowStart, colStart, row, col);
555
+ }
556
+ if (treeNode.hasChildren(item)) {
557
+ const childState = Object.assign(Object.assign({}, state), { parentRowIndex: row > 1 ? row - 1 : 0, parentColIndex: colIndex + parentColIndex, parentKey: mainKey });
558
+ this.fillMap(treeNode.getChildren(item), rows, map, childState);
559
+ if (col > 1) {
560
+ state.prevChildren += col - 1;
561
+ }
562
+ }
563
+ });
564
+ return map;
565
+ }
566
+ /**
567
+ * Fill vertical grid map according to tree structure
568
+ *
569
+ * @param {Array<TreeNode>} children - list of tree nodes
570
+ * @param {number} cols - deep level columns
571
+ * @param {TreeCellMapCache} map - map object to fill
572
+ * @param {FillMapState} initState - state object for
573
+ * recursive calls
574
+ * @returns {object} - map object
575
+ *
576
+ * @private
577
+ */
578
+ fillMapVertical(children, cols, map = {}, initState) {
579
+ const state = initState || {
580
+ parentRowIndex: 0,
581
+ parentColIndex: 0,
582
+ prevChildren: 0,
583
+ parentKey: '',
584
+ };
585
+ const childCount = children.length;
586
+ children.forEach((item, rowIndex) => {
587
+ if (item.isMapped) {
588
+ state.parentRowIndex += treeNode.getChildLength(item) - 1;
589
+ return;
590
+ }
591
+ item.isMapped = true;
592
+ const { parentRowIndex, prevChildren, parentKey } = state;
593
+ const colIndex = treeNode.getLevel(item);
594
+ const rowStart = rowIndex + parentRowIndex + prevChildren;
595
+ const mainKey = keyCreator(rowStart, colIndex);
596
+ const mapMainItem = this.createTreeCellMap({
597
+ rowIndex: rowStart,
598
+ colIndex,
599
+ node: item,
600
+ parent: parentKey,
601
+ });
602
+ mapMainItem.setIndexInParent(rowIndex, childCount);
603
+ map[mainKey] = mapMainItem;
604
+ let col = 0;
605
+ let row = 0;
606
+ if (treeNode.hasChildren(item)) {
607
+ row = this.getTreeChildLength(item);
608
+ }
609
+ else {
610
+ col = (cols || 0) - (colIndex || 0);
611
+ }
612
+ if (col > 1 || row > 1) {
613
+ // if has merged cells
614
+ this.fillChildMap(map, mainKey, rowStart, colIndex, row, col);
615
+ }
616
+ if (treeNode.hasChildren(item)) {
617
+ const childState = Object.assign(Object.assign({}, state), { parentRowIndex: rowIndex + parentRowIndex, parentKey: mainKey });
618
+ this.fillMapVertical(treeNode.getChildren(item), cols, map, childState);
619
+ if (row > 1) {
620
+ state.prevChildren += row - 1;
621
+ }
622
+ }
623
+ });
624
+ return map;
625
+ }
626
+ /**
627
+ * Fill child items in map according to main cell merged row and col
628
+ *
629
+ * @param {object} map - map object to fill
630
+ * @param {string} mainKey - main cell key in map
631
+ * @param {number} rowStart - main cell row index
632
+ * @param {number} colStart - main cell column index
633
+ * @param {number} row - merged rows count
634
+ * @param {number} col - merged columns count
635
+ * @returns {void}
636
+ *
637
+ * @private
638
+ */
639
+ fillChildMap(map, mainKey, rowStart, colStart, row, col) {
640
+ const mapMainItem = map[mainKey];
641
+ const rowsCount = Math.max(1, row);
642
+ const colsCount = Math.max(1, col);
643
+ Array.from(Array(rowsCount)).forEach((r, rowAddIndex) => {
644
+ Array.from(Array(colsCount)).forEach((c, colAddIndex) => {
645
+ if (rowAddIndex === 0 && colAddIndex === 0) {
646
+ // skip main item
647
+ return;
648
+ }
649
+ const childRowIndex = rowStart + rowAddIndex;
650
+ const childColIndex = colStart + colAddIndex;
651
+ const childKey = keyCreator(childRowIndex, childColIndex);
652
+ const childColItem = this.createTreeCellMap({
653
+ rowIndex: childRowIndex,
654
+ colIndex: childColIndex,
655
+ parent: mainKey,
656
+ });
657
+ map[childKey] = childColItem;
658
+ if (rowAddIndex !== 0 && colAddIndex !== 0) {
659
+ // skip middle items
660
+ return;
661
+ }
662
+ if (colAddIndex === 0) {
663
+ mapMainItem.addRowCell(childColItem);
664
+ }
665
+ if (rowAddIndex === 0) {
666
+ mapMainItem.addColCell(childColItem);
667
+ }
668
+ });
669
+ });
670
+ }
671
+ /**
672
+ * Creates TreeCellMap instance
673
+ *
674
+ * @param {object} options - instance options
675
+ * @param {number} options.rowIndex - row index of cell map instance
676
+ * @param {number} options.colIndex - row index of cell map instance
677
+ * @param {TreeNode} [options.node] - TreeNode for main cell
678
+ * @param {string} [options.parent] - parent key for child item
679
+ * @returns {TreeCellMap} - TreeCellMap instance
680
+ *
681
+ * @private
682
+ */
683
+ // eslint-disable-next-line class-methods-use-this
684
+ createTreeCellMap({ rowIndex, colIndex, node, parent, }) {
685
+ return new TreeCellMap(rowIndex, colIndex, node, parent);
686
+ }
687
+ /**
688
+ * Returns TreeCellMapI item by key string
689
+ *
690
+ * @param {string} key - map key string
691
+ * @returns {TreeCellMapI|undefined} - TreeCellMapI instance or undefined
692
+ *
693
+ * @private
694
+ */
695
+ getItemByKey(key) {
696
+ return this.map[key];
697
+ }
698
+ /**
699
+ * Returns TreeCellMapI item by (row, col) coordinate
700
+ *
701
+ * @param {number} row - cell row index
702
+ * @param {number} col - cell column index
703
+ * @returns {TreeCellMapI|undefined} - TreeCellMapI instance or undefined
704
+ *
705
+ * @private
706
+ */
707
+ getItem(row, col) {
708
+ const key = keyCreator(row, col);
709
+ return this.getItemByKey(key);
710
+ }
711
+ }
712
+ export default AbstractTreeService;