@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.
- package/LICENSE.md +35 -0
- package/README.md +2 -0
- package/dist/__test-helpers__/testUtils.d.ts +30 -0
- package/dist/__test-helpers__/testUtils.js +89 -0
- package/dist/builders/index.d.ts +2 -0
- package/dist/builders/index.js +2 -0
- package/dist/builders/pivot-data-builder.d.ts +34 -0
- package/dist/builders/pivot-data-builder.js +182 -0
- package/dist/builders/socket-builder.d.ts +18 -0
- package/dist/builders/socket-builder.js +72 -0
- package/dist/cjs/__test-helpers__/testUtils.d.ts +30 -0
- package/dist/cjs/__test-helpers__/testUtils.js +104 -0
- package/dist/cjs/builders/index.d.ts +2 -0
- package/dist/cjs/builders/index.js +7 -0
- package/dist/cjs/builders/pivot-data-builder.d.ts +34 -0
- package/dist/cjs/builders/pivot-data-builder.js +186 -0
- package/dist/cjs/builders/socket-builder.d.ts +18 -0
- package/dist/cjs/builders/socket-builder.js +79 -0
- package/dist/cjs/data-handling/DataService.d.ts +672 -0
- package/dist/cjs/data-handling/DataService.js +1364 -0
- package/dist/cjs/data-handling/DivergenceComparator.d.ts +7 -0
- package/dist/cjs/data-handling/DivergenceComparator.js +20 -0
- package/dist/cjs/data-handling/constants.d.ts +44 -0
- package/dist/cjs/data-handling/constants.js +43 -0
- package/dist/cjs/data-handling/index.d.ts +3 -0
- package/dist/cjs/data-handling/index.js +23 -0
- package/dist/cjs/data-handling/types.d.ts +104 -0
- package/dist/cjs/data-handling/types.js +2 -0
- package/dist/cjs/data-handling/utils/createPivotTreeNode.d.ts +13 -0
- package/dist/cjs/data-handling/utils/createPivotTreeNode.js +21 -0
- package/dist/cjs/data-handling/utils/index.d.ts +4 -0
- package/dist/cjs/data-handling/utils/index.js +14 -0
- package/dist/cjs/data-handling/utils/jaqlProcessor.d.ts +122 -0
- package/dist/cjs/data-handling/utils/jaqlProcessor.js +661 -0
- package/dist/cjs/data-handling/utils/pivotTransforms.d.ts +74 -0
- package/dist/cjs/data-handling/utils/pivotTransforms.js +373 -0
- package/dist/cjs/data-handling/utils/plugins/PluginService.d.ts +135 -0
- package/dist/cjs/data-handling/utils/plugins/PluginService.js +383 -0
- package/dist/cjs/data-handling/utils/plugins/getters.d.ts +23 -0
- package/dist/cjs/data-handling/utils/plugins/getters.js +70 -0
- package/dist/cjs/data-handling/utils/plugins/types.d.ts +75 -0
- package/dist/cjs/data-handling/utils/plugins/types.js +2 -0
- package/dist/cjs/data-handling/utils/plugins/validator.d.ts +13 -0
- package/dist/cjs/data-handling/utils/plugins/validator.js +169 -0
- package/dist/cjs/data-load/AbstractDataLoadService.d.ts +256 -0
- package/dist/cjs/data-load/AbstractDataLoadService.js +473 -0
- package/dist/cjs/data-load/DataLoadService.d.ts +63 -0
- package/dist/cjs/data-load/DataLoadService.js +152 -0
- package/dist/cjs/data-load/SisenseDataLoadService.d.ts +44 -0
- package/dist/cjs/data-load/SisenseDataLoadService.js +87 -0
- package/dist/cjs/data-load/TestDataLoadService.d.ts +27 -0
- package/dist/cjs/data-load/TestDataLoadService.js +76 -0
- package/dist/cjs/data-load/constants.d.ts +13 -0
- package/dist/cjs/data-load/constants.js +28 -0
- package/dist/cjs/data-load/index.d.ts +6 -0
- package/dist/cjs/data-load/index.js +14 -0
- package/dist/cjs/data-load/sockets/SisenseSocket.d.ts +81 -0
- package/dist/cjs/data-load/sockets/SisenseSocket.js +162 -0
- package/dist/cjs/data-load/sockets/TestSocket.d.ts +61 -0
- package/dist/cjs/data-load/sockets/TestSocket.js +90 -0
- package/dist/cjs/data-load/sockets/helpers.d.ts +4 -0
- package/dist/cjs/data-load/sockets/helpers.js +27 -0
- package/dist/cjs/data-load/sockets/index.d.ts +2 -0
- package/dist/cjs/data-load/sockets/index.js +8 -0
- package/dist/cjs/data-load/types.d.ts +90 -0
- package/dist/cjs/data-load/types.js +2 -0
- package/dist/cjs/errors/LoadingCanceledError.d.ts +7 -0
- package/dist/cjs/errors/LoadingCanceledError.js +24 -0
- package/dist/cjs/errors/index.d.ts +1 -0
- package/dist/cjs/errors/index.js +6 -0
- package/dist/cjs/index.d.ts +17 -0
- package/dist/cjs/index.js +32 -0
- package/dist/cjs/package.json +12 -0
- package/dist/cjs/pivot-query-client.d.ts +13 -0
- package/dist/cjs/pivot-query-client.js +26 -0
- package/dist/cjs/tree-structure/AbstractTreeService.d.ts +308 -0
- package/dist/cjs/tree-structure/AbstractTreeService.js +716 -0
- package/dist/cjs/tree-structure/HeaderTreeService.d.ts +180 -0
- package/dist/cjs/tree-structure/HeaderTreeService.js +280 -0
- package/dist/cjs/tree-structure/TreeCellMap.d.ts +104 -0
- package/dist/cjs/tree-structure/TreeCellMap.js +145 -0
- package/dist/cjs/tree-structure/TreeService.d.ts +8 -0
- package/dist/cjs/tree-structure/TreeService.js +12 -0
- package/dist/cjs/tree-structure/constants.d.ts +6 -0
- package/dist/cjs/tree-structure/constants.js +10 -0
- package/dist/cjs/tree-structure/index.d.ts +5 -0
- package/dist/cjs/tree-structure/index.js +10 -0
- package/dist/cjs/tree-structure/types.d.ts +93 -0
- package/dist/cjs/tree-structure/types.js +2 -0
- package/dist/cjs/tree-structure/utils/index.d.ts +1 -0
- package/dist/cjs/tree-structure/utils/index.js +9 -0
- package/dist/cjs/tree-structure/utils/treeNode.d.ts +147 -0
- package/dist/cjs/tree-structure/utils/treeNode.js +534 -0
- package/dist/cjs/utils/array.d.ts +13 -0
- package/dist/cjs/utils/array.js +25 -0
- package/dist/cjs/utils/cloneObject.d.ts +30 -0
- package/dist/cjs/utils/cloneObject.js +225 -0
- package/dist/cjs/utils/index.d.ts +3 -0
- package/dist/cjs/utils/index.js +9 -0
- package/dist/cjs/utils/throttle.d.ts +12 -0
- package/dist/cjs/utils/throttle.js +39 -0
- package/dist/cjs/utils/types.d.ts +12 -0
- package/dist/cjs/utils/types.js +2 -0
- package/dist/data-handling/DataService.d.ts +672 -0
- package/dist/data-handling/DataService.js +1357 -0
- package/dist/data-handling/DivergenceComparator.d.ts +7 -0
- package/dist/data-handling/DivergenceComparator.js +16 -0
- package/dist/data-handling/constants.d.ts +44 -0
- package/dist/data-handling/constants.js +40 -0
- package/dist/data-handling/index.d.ts +3 -0
- package/dist/data-handling/index.js +4 -0
- package/dist/data-handling/types.d.ts +104 -0
- package/dist/data-handling/types.js +1 -0
- package/dist/data-handling/utils/createPivotTreeNode.d.ts +13 -0
- package/dist/data-handling/utils/createPivotTreeNode.js +17 -0
- package/dist/data-handling/utils/index.d.ts +4 -0
- package/dist/data-handling/utils/index.js +4 -0
- package/dist/data-handling/utils/jaqlProcessor.d.ts +122 -0
- package/dist/data-handling/utils/jaqlProcessor.js +621 -0
- package/dist/data-handling/utils/pivotTransforms.d.ts +74 -0
- package/dist/data-handling/utils/pivotTransforms.js +335 -0
- package/dist/data-handling/utils/plugins/PluginService.d.ts +135 -0
- package/dist/data-handling/utils/plugins/PluginService.js +379 -0
- package/dist/data-handling/utils/plugins/getters.d.ts +23 -0
- package/dist/data-handling/utils/plugins/getters.js +65 -0
- package/dist/data-handling/utils/plugins/types.d.ts +75 -0
- package/dist/data-handling/utils/plugins/types.js +1 -0
- package/dist/data-handling/utils/plugins/validator.d.ts +13 -0
- package/dist/data-handling/utils/plugins/validator.js +165 -0
- package/dist/data-load/AbstractDataLoadService.d.ts +256 -0
- package/dist/data-load/AbstractDataLoadService.js +466 -0
- package/dist/data-load/DataLoadService.d.ts +63 -0
- package/dist/data-load/DataLoadService.js +148 -0
- package/dist/data-load/SisenseDataLoadService.d.ts +44 -0
- package/dist/data-load/SisenseDataLoadService.js +83 -0
- package/dist/data-load/TestDataLoadService.d.ts +27 -0
- package/dist/data-load/TestDataLoadService.js +69 -0
- package/dist/data-load/constants.d.ts +13 -0
- package/dist/data-load/constants.js +25 -0
- package/dist/data-load/index.d.ts +6 -0
- package/dist/data-load/index.js +6 -0
- package/dist/data-load/sockets/SisenseSocket.d.ts +81 -0
- package/dist/data-load/sockets/SisenseSocket.js +155 -0
- package/dist/data-load/sockets/TestSocket.d.ts +61 -0
- package/dist/data-load/sockets/TestSocket.js +83 -0
- package/dist/data-load/sockets/helpers.d.ts +4 -0
- package/dist/data-load/sockets/helpers.js +23 -0
- package/dist/data-load/sockets/index.d.ts +2 -0
- package/dist/data-load/sockets/index.js +3 -0
- package/dist/data-load/types.d.ts +90 -0
- package/dist/data-load/types.js +1 -0
- package/dist/errors/LoadingCanceledError.d.ts +7 -0
- package/dist/errors/LoadingCanceledError.js +20 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +2 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +9 -0
- package/dist/pivot-query-client.d.ts +13 -0
- package/dist/pivot-query-client.js +22 -0
- package/dist/tree-structure/AbstractTreeService.d.ts +308 -0
- package/dist/tree-structure/AbstractTreeService.js +712 -0
- package/dist/tree-structure/HeaderTreeService.d.ts +180 -0
- package/dist/tree-structure/HeaderTreeService.js +276 -0
- package/dist/tree-structure/TreeCellMap.d.ts +104 -0
- package/dist/tree-structure/TreeCellMap.js +141 -0
- package/dist/tree-structure/TreeService.d.ts +8 -0
- package/dist/tree-structure/TreeService.js +8 -0
- package/dist/tree-structure/constants.d.ts +6 -0
- package/dist/tree-structure/constants.js +7 -0
- package/dist/tree-structure/index.d.ts +5 -0
- package/dist/tree-structure/index.js +4 -0
- package/dist/tree-structure/types.d.ts +93 -0
- package/dist/tree-structure/types.js +1 -0
- package/dist/tree-structure/utils/index.d.ts +1 -0
- package/dist/tree-structure/utils/index.js +1 -0
- package/dist/tree-structure/utils/treeNode.d.ts +147 -0
- package/dist/tree-structure/utils/treeNode.js +515 -0
- package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
- package/dist/utils/array.d.ts +13 -0
- package/dist/utils/array.js +21 -0
- package/dist/utils/cloneObject.d.ts +30 -0
- package/dist/utils/cloneObject.js +221 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/throttle.d.ts +12 -0
- package/dist/utils/throttle.js +35 -0
- package/dist/utils/types.d.ts +12 -0
- package/dist/utils/types.js +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,1357 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
/* eslint-disable @typescript-eslint/ban-types */
|
|
13
|
+
import EventEmitter from 'events';
|
|
14
|
+
import { MessageType } from '../data-load/constants.js';
|
|
15
|
+
import { LoadingCanceledError } from '../errors/index.js';
|
|
16
|
+
import { TreeService } from '../tree-structure/index.js';
|
|
17
|
+
import { treeNode } from '../tree-structure/utils/index.js';
|
|
18
|
+
import { cloneObject, findIndex, throttle } from '../utils/index.js';
|
|
19
|
+
import { PanelType, UserType } from './constants.js';
|
|
20
|
+
import { DivergenceComparator } from './DivergenceComparator.js';
|
|
21
|
+
import { createPivotTreeNode, jaqlProcessor, pivotTransforms, PluginService, } from './utils/index.js';
|
|
22
|
+
const getJaqlComposition = (jaql, rawMetadata) => {
|
|
23
|
+
const processedJaql = jaql || { metadata: [], grandTotals: null };
|
|
24
|
+
let { metadata } = processedJaql;
|
|
25
|
+
metadata = metadata.map((panel) => {
|
|
26
|
+
const field = panel.field || {};
|
|
27
|
+
// find format to compose from rawMetadata by field.index
|
|
28
|
+
const samePanel = rawMetadata.find(({ field: rawField }) => rawField && rawField.index === field.index);
|
|
29
|
+
const format = samePanel ? samePanel.format : null;
|
|
30
|
+
return format ? Object.assign(Object.assign({}, panel), { format }) : panel;
|
|
31
|
+
});
|
|
32
|
+
return Object.assign(Object.assign({}, processedJaql), { metadata });
|
|
33
|
+
};
|
|
34
|
+
export const DEFAULT_PAGE_SIZE = 100;
|
|
35
|
+
export const EVENT_DATA_LOAD = 'dataLoad';
|
|
36
|
+
export const EVENT_DATA_CHUNK_LOADED = 'dataChunkLoaded';
|
|
37
|
+
export const EVENT_DATABAR_CHUNK_LOADED = 'dataBarChunkLoaded';
|
|
38
|
+
export const EVENT_RANGEMINMAX_CHUNK_LOADED = 'rangeMinMaxChunkLoaded';
|
|
39
|
+
export const EVENT_GRAND_CHUNK_LOADED = 'grandChunkLoaded';
|
|
40
|
+
export const EVENT_DATA_FINISH_CHUNK_LOADED = 'dataFinishChunkLoaded';
|
|
41
|
+
export const EVENT_FINISH_CHUNK_LOADED = 'finishChunkLoaded';
|
|
42
|
+
export const EVENT_PROGRESS_ERROR = 'progressError';
|
|
43
|
+
export const EVENT_HEADER_CELL_FORMAT = 'headerCellFormat';
|
|
44
|
+
export const EVENT_DATA_CELL_FORMAT = 'dataCellFormat';
|
|
45
|
+
export const EVENT_TOTAL_ROWS_COUNT = 'totalRowsCountLoaded';
|
|
46
|
+
export const EVENT_TOTAL_COLUMNS_COUNT = 'totalColumnsCountLoaded';
|
|
47
|
+
export const NODES_CHUNK_SIZE_MAX = 1000;
|
|
48
|
+
// TODO Review if throttling is needed
|
|
49
|
+
export const THROTTLE_TIME_MS = 0;
|
|
50
|
+
const defaultOptions = {
|
|
51
|
+
throttle,
|
|
52
|
+
throttleTime: THROTTLE_TIME_MS,
|
|
53
|
+
PluginService,
|
|
54
|
+
skipInternalColorFormatting: false,
|
|
55
|
+
subtotalsForSingleRow: false,
|
|
56
|
+
};
|
|
57
|
+
export class DataService {
|
|
58
|
+
// eslint-disable-next-line max-lines-per-function
|
|
59
|
+
constructor(loadService, events, options) {
|
|
60
|
+
/**
|
|
61
|
+
*
|
|
62
|
+
*
|
|
63
|
+
* @private
|
|
64
|
+
*
|
|
65
|
+
* loaded data chunks group
|
|
66
|
+
*/
|
|
67
|
+
this.tempDataChunks = [];
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
* @private
|
|
71
|
+
*
|
|
72
|
+
* last not handled data chunks group index
|
|
73
|
+
*/
|
|
74
|
+
this.lastNotHandledChunkIndex = 0;
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @private
|
|
78
|
+
*
|
|
79
|
+
* last ready but not handled data chunks group index
|
|
80
|
+
*/
|
|
81
|
+
this.lastReadyNotHandledChunkIndex = 0;
|
|
82
|
+
/**
|
|
83
|
+
*
|
|
84
|
+
* @private
|
|
85
|
+
*
|
|
86
|
+
* Current rows nodes
|
|
87
|
+
*/
|
|
88
|
+
this.rowsGrand = undefined;
|
|
89
|
+
/**
|
|
90
|
+
*
|
|
91
|
+
@private */
|
|
92
|
+
this.rowsTreeService = undefined;
|
|
93
|
+
/**
|
|
94
|
+
*
|
|
95
|
+
@private */
|
|
96
|
+
this.columnsTreeService = undefined;
|
|
97
|
+
/**
|
|
98
|
+
*
|
|
99
|
+
@private */
|
|
100
|
+
this.cornerTreeService = undefined;
|
|
101
|
+
/**
|
|
102
|
+
@private */
|
|
103
|
+
this.pageSize = DEFAULT_PAGE_SIZE;
|
|
104
|
+
/**
|
|
105
|
+
*
|
|
106
|
+
@private */
|
|
107
|
+
this.isPaginated = false;
|
|
108
|
+
/**
|
|
109
|
+
*
|
|
110
|
+
* @private
|
|
111
|
+
*
|
|
112
|
+
* number of loaded pages
|
|
113
|
+
*/
|
|
114
|
+
this.loadedPagesCount = 0;
|
|
115
|
+
/**
|
|
116
|
+
*
|
|
117
|
+
* @private
|
|
118
|
+
*
|
|
119
|
+
* state for "loadData" method
|
|
120
|
+
*/
|
|
121
|
+
this.isLoadInProgress = false;
|
|
122
|
+
/**
|
|
123
|
+
*
|
|
124
|
+
@private */
|
|
125
|
+
this.loadAllPromise = undefined;
|
|
126
|
+
/**
|
|
127
|
+
*
|
|
128
|
+
@private */
|
|
129
|
+
this.loadAllPromiseResolve = undefined;
|
|
130
|
+
/**
|
|
131
|
+
*
|
|
132
|
+
@private */
|
|
133
|
+
this.loadAllPromiseReject = undefined;
|
|
134
|
+
/**
|
|
135
|
+
*
|
|
136
|
+
* @private
|
|
137
|
+
*
|
|
138
|
+
* defines if all data is loaded
|
|
139
|
+
*/
|
|
140
|
+
this.isWholeDataLoaded = false;
|
|
141
|
+
/**
|
|
142
|
+
*
|
|
143
|
+
* @private
|
|
144
|
+
*
|
|
145
|
+
* defines that data finish event is happened
|
|
146
|
+
*/
|
|
147
|
+
this.hasDataFinishEvent = false;
|
|
148
|
+
/**
|
|
149
|
+
*
|
|
150
|
+
* @private
|
|
151
|
+
*
|
|
152
|
+
* defines that data handler in progress
|
|
153
|
+
*/
|
|
154
|
+
this.isDataHandlerThrottled = false;
|
|
155
|
+
/**
|
|
156
|
+
*
|
|
157
|
+
* @private
|
|
158
|
+
*
|
|
159
|
+
* jaql request pure metadata
|
|
160
|
+
*/
|
|
161
|
+
this.metadata = [];
|
|
162
|
+
/**
|
|
163
|
+
*
|
|
164
|
+
* @private
|
|
165
|
+
*
|
|
166
|
+
* service for items indexation divergence
|
|
167
|
+
*/
|
|
168
|
+
this.divergenceComparator = new DivergenceComparator();
|
|
169
|
+
/**
|
|
170
|
+
*
|
|
171
|
+
@private */
|
|
172
|
+
this.rawJaql = undefined;
|
|
173
|
+
/**
|
|
174
|
+
*
|
|
175
|
+
* @private
|
|
176
|
+
*
|
|
177
|
+
* triggered events data storage
|
|
178
|
+
*/
|
|
179
|
+
this.triggeredEventsData = {};
|
|
180
|
+
/**
|
|
181
|
+
*
|
|
182
|
+
* @private
|
|
183
|
+
*
|
|
184
|
+
* plugins handlers
|
|
185
|
+
*/
|
|
186
|
+
this.callPlugins = [];
|
|
187
|
+
/**
|
|
188
|
+
* Handler for pivot metadata received event
|
|
189
|
+
*
|
|
190
|
+
* @returns {void}
|
|
191
|
+
*/
|
|
192
|
+
this.onMetadataHandler = () => {
|
|
193
|
+
const jaql = { metadata: this.getMetadata() };
|
|
194
|
+
const isSingleRowTree = this.isSingleRowTree();
|
|
195
|
+
if (isSingleRowTree) {
|
|
196
|
+
jaqlProcessor.normalizeSingleBranchTreeSortDetails(jaql);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
this.onHeadersHandler = (data) => {
|
|
200
|
+
// bind methods for injecting them into tree service builders
|
|
201
|
+
const getJaql = this.getJaql.bind(this);
|
|
202
|
+
const getRawJaql = this.getRawJaql.bind(this);
|
|
203
|
+
const applyIndexDivergence = this.applyIndexDivergence.bind(this);
|
|
204
|
+
const emitHeaderCellFormatEvent = (item, panel, jaql) => this.emit(EVENT_HEADER_CELL_FORMAT, item, panel, jaql, this.options);
|
|
205
|
+
// build columns tree service
|
|
206
|
+
const buildColumnsTreeService = DataService.createColumnsTreeServiceBuilder({
|
|
207
|
+
getJaql,
|
|
208
|
+
getRawJaql,
|
|
209
|
+
pluginService: this.pluginService,
|
|
210
|
+
applyIndexDivergence,
|
|
211
|
+
}, {
|
|
212
|
+
emitHeaderCellFormatEvent,
|
|
213
|
+
});
|
|
214
|
+
const columnsTreeServiceBuildResult = buildColumnsTreeService(data);
|
|
215
|
+
this.columnsTreeService = columnsTreeServiceBuildResult.columnsTreeService;
|
|
216
|
+
this.columnsCount = columnsTreeServiceBuildResult.columnsCount;
|
|
217
|
+
this.totalColumnsCount = columnsTreeServiceBuildResult.totalColumnsCount;
|
|
218
|
+
this.emit(EVENT_TOTAL_COLUMNS_COUNT, {
|
|
219
|
+
columnsCount: this.columnsCount || 0,
|
|
220
|
+
totalColumnsCount: this.totalColumnsCount || 0,
|
|
221
|
+
});
|
|
222
|
+
// build corner tree service
|
|
223
|
+
const buildCornerTreeService = DataService.createCornerTreeServiceBuilder({
|
|
224
|
+
getJaql,
|
|
225
|
+
getRawJaql,
|
|
226
|
+
pluginService: this.pluginService,
|
|
227
|
+
columnsTreeService: this.columnsTreeService,
|
|
228
|
+
}, {
|
|
229
|
+
emitHeaderCellFormatEvent,
|
|
230
|
+
});
|
|
231
|
+
const { cornerTreeService } = buildCornerTreeService();
|
|
232
|
+
this.cornerTreeService = cornerTreeService;
|
|
233
|
+
};
|
|
234
|
+
this.onDataHandler = (data) => {
|
|
235
|
+
// store the data chunk into temporary storage
|
|
236
|
+
// this step is NOT throttled because we want to make
|
|
237
|
+
// ALL data chunks coming (regardless of the rate) is captured
|
|
238
|
+
this.tempDataChunks = this.tempDataChunks || [];
|
|
239
|
+
if (Array.isArray(data)) {
|
|
240
|
+
(data || []).forEach((item) => {
|
|
241
|
+
DataService.fillDataChunks(this.tempDataChunks, item, this.pageSize);
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
DataService.fillDataChunks(this.tempDataChunks, data, this.pageSize);
|
|
246
|
+
}
|
|
247
|
+
// the data processing step CAN be throttled
|
|
248
|
+
// However, method onDataHandlerThrottle needs logic
|
|
249
|
+
// to maintain the LAST processed chunk
|
|
250
|
+
if (this.tempDataChunks.length) {
|
|
251
|
+
this.isDataHandlerThrottled = true;
|
|
252
|
+
// @ts-ignore
|
|
253
|
+
this.onDataHandlerThrottle();
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
this.onGrandHandler = (data) => {
|
|
257
|
+
const rows = this.preProcessTree([data], PanelType.ROWS);
|
|
258
|
+
const mainNode = rows[0];
|
|
259
|
+
const name = 'Rows grand total';
|
|
260
|
+
const grandData = mainNode ? mainNode.data : [];
|
|
261
|
+
const node = treeNode.create(name, undefined, grandData);
|
|
262
|
+
const grandTotalNode = createPivotTreeNode(node, PanelType.ROWS);
|
|
263
|
+
grandTotalNode.userType = UserType.GRAND_TOTAL;
|
|
264
|
+
this.postProcessTree([grandTotalNode]);
|
|
265
|
+
this.postProcessData([grandTotalNode]);
|
|
266
|
+
this.rowsGrand = grandTotalNode;
|
|
267
|
+
this.emit(EVENT_GRAND_CHUNK_LOADED, treeNode.wrapInRootNode(this.rowsGrand));
|
|
268
|
+
};
|
|
269
|
+
this.onFinishHandler = () => {
|
|
270
|
+
this.emit(EVENT_FINISH_CHUNK_LOADED, {
|
|
271
|
+
totalRows: typeof this.totalRowsCount === 'number' ? this.totalRowsCount : this.getTotalItemsCount(),
|
|
272
|
+
totalColumns: typeof this.totalColumnsCount === 'number'
|
|
273
|
+
? this.totalColumnsCount
|
|
274
|
+
: this.getLoadedColumnsCount(), // backward compatibility
|
|
275
|
+
});
|
|
276
|
+
};
|
|
277
|
+
this.onTotalRowsHandler = (data) => {
|
|
278
|
+
const { rowsCount, queryRowsCount, limitReached } = data || {};
|
|
279
|
+
this.totalRowsCount = rowsCount;
|
|
280
|
+
this.totalRecordsCount = queryRowsCount;
|
|
281
|
+
this.limitReached = limitReached;
|
|
282
|
+
this.emit(EVENT_TOTAL_ROWS_COUNT, data);
|
|
283
|
+
};
|
|
284
|
+
this.onDataBarsHandler = (chunk) => {
|
|
285
|
+
const { data = [] } = chunk;
|
|
286
|
+
let offset = 0;
|
|
287
|
+
if (this.cornerTreeService) {
|
|
288
|
+
offset = this.cornerTreeService.getTreeChildLength();
|
|
289
|
+
}
|
|
290
|
+
this.dataBars = [...Array(offset), ...data];
|
|
291
|
+
this.emit(EVENT_DATABAR_CHUNK_LOADED, this.dataBars);
|
|
292
|
+
};
|
|
293
|
+
this.onRangeMinMaxHandler = (chunk) => {
|
|
294
|
+
const { data = [] } = chunk;
|
|
295
|
+
const jaql = this.getJaql();
|
|
296
|
+
const measuresTree = jaqlProcessor.getMetadataTree(jaql, PanelType.MEASURES);
|
|
297
|
+
const measures = treeNode.getChildren(measuresTree);
|
|
298
|
+
const rangeMinMax = [];
|
|
299
|
+
measures.forEach((measure, index) => {
|
|
300
|
+
// align indexes in case disabled measures
|
|
301
|
+
rangeMinMax[measure.measureJaqlIndex || 0] = data[index];
|
|
302
|
+
});
|
|
303
|
+
this.rangeMinMax = rangeMinMax;
|
|
304
|
+
this.emit(EVENT_RANGEMINMAX_CHUNK_LOADED, this.rangeMinMax);
|
|
305
|
+
};
|
|
306
|
+
this.onDataFinishHandler = ({ rowsCount } = {}) => {
|
|
307
|
+
this.finishRequest();
|
|
308
|
+
this.rowsCount = rowsCount;
|
|
309
|
+
if (this.tempDataChunks.length) {
|
|
310
|
+
const chunkLast = this.tempDataChunks[this.tempDataChunks.length - 1];
|
|
311
|
+
chunkLast.ready = true;
|
|
312
|
+
}
|
|
313
|
+
// @ts-ignore
|
|
314
|
+
this.onDataHandlerThrottle();
|
|
315
|
+
this.checkLoadPromise();
|
|
316
|
+
this.emit(EVENT_DATA_FINISH_CHUNK_LOADED, {
|
|
317
|
+
limitedRows: this.rowsCount,
|
|
318
|
+
limitedColumns: this.columnsCount,
|
|
319
|
+
});
|
|
320
|
+
};
|
|
321
|
+
this.onErrorHandler = (data) => {
|
|
322
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
323
|
+
// eslint-disable-next-line no-console
|
|
324
|
+
console.warn(`DataService data loading error "${JSON.stringify(data)}"`);
|
|
325
|
+
}
|
|
326
|
+
if (!this.isLoadInProgress &&
|
|
327
|
+
!this.isWholeDataLoaded &&
|
|
328
|
+
!(data instanceof LoadingCanceledError)) {
|
|
329
|
+
// post load error
|
|
330
|
+
this.emit(EVENT_PROGRESS_ERROR, data);
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
this.loadService = loadService;
|
|
334
|
+
this.events = events || new EventEmitter();
|
|
335
|
+
this.options = Object.assign(Object.assign({}, defaultOptions), options);
|
|
336
|
+
this.attachEvent();
|
|
337
|
+
this.onDataHandlerThrottle = this.options.throttle(() => {
|
|
338
|
+
const chunkIndex = findIndex(this.tempDataChunks, (item) => item.ready && !item.handled, this.lastReadyNotHandledChunkIndex);
|
|
339
|
+
if (chunkIndex === -1) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
this.lastReadyNotHandledChunkIndex = chunkIndex;
|
|
343
|
+
const chunk = this.tempDataChunks[chunkIndex];
|
|
344
|
+
const rows = this.preProcessTree(chunk.list, PanelType.ROWS);
|
|
345
|
+
const modifiedRows = this.modifyTree(rows, PanelType.ROWS);
|
|
346
|
+
this.postProcessTree(modifiedRows, { skipFormatEvent: true });
|
|
347
|
+
this.postProcessData(modifiedRows, { skipFormatEvent: true });
|
|
348
|
+
const wrappedModifiedRows = treeNode.wrapInRootNode(modifiedRows);
|
|
349
|
+
if (this.rowsTreeService) {
|
|
350
|
+
this.rowsTreeService.extend(wrappedModifiedRows);
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
this.rowsTreeService = new TreeService(wrappedModifiedRows, true);
|
|
354
|
+
}
|
|
355
|
+
this.emit(EVENT_DATA_CHUNK_LOADED, this.getLoadedElementsCount());
|
|
356
|
+
chunk.handled = true;
|
|
357
|
+
const nextChunkIndex = findIndex(this.tempDataChunks, (item) => !item.handled, this.lastNotHandledChunkIndex);
|
|
358
|
+
if (nextChunkIndex !== -1) {
|
|
359
|
+
this.lastNotHandledChunkIndex = nextChunkIndex;
|
|
360
|
+
// Note: removed `setImmediate` as not support
|
|
361
|
+
this.onDataHandlerThrottle();
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
this.isDataHandlerThrottled = false;
|
|
365
|
+
}
|
|
366
|
+
if (this.hasDataFinishEvent && this.tempDataChunks.length) {
|
|
367
|
+
const chunkLast = this.tempDataChunks[this.tempDataChunks.length - 1];
|
|
368
|
+
chunkLast.ready = true;
|
|
369
|
+
}
|
|
370
|
+
if (this.hasDataFinishEvent && nextChunkIndex === -1) {
|
|
371
|
+
this.finishRequest();
|
|
372
|
+
this.checkLoadPromise();
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
this.checkLoadPromise();
|
|
376
|
+
}
|
|
377
|
+
}, this.options.throttleTime);
|
|
378
|
+
}
|
|
379
|
+
destroy() {
|
|
380
|
+
this.detachEvent();
|
|
381
|
+
this.rowsGrand = undefined;
|
|
382
|
+
this.rowsTreeService = undefined;
|
|
383
|
+
this.columnsTreeService = undefined;
|
|
384
|
+
this.cornerTreeService = undefined;
|
|
385
|
+
this.tempDataChunks = [];
|
|
386
|
+
this.lastNotHandledChunkIndex = 0;
|
|
387
|
+
this.lastReadyNotHandledChunkIndex = 0;
|
|
388
|
+
this.events.removeAllListeners();
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Subscribe to event notification
|
|
392
|
+
*
|
|
393
|
+
* @param {string} eventName - event name to subscribe
|
|
394
|
+
* @param {Function} callback - event handler
|
|
395
|
+
* @returns {void}
|
|
396
|
+
*/
|
|
397
|
+
on(eventName, callback) {
|
|
398
|
+
this.events.on(eventName, callback);
|
|
399
|
+
if (this.triggeredEventsData[eventName]) {
|
|
400
|
+
this.triggeredEventsData[eventName].forEach((payload) => {
|
|
401
|
+
// Note: removed `setImmediate` as not supported
|
|
402
|
+
this.events.emit(eventName, ...payload);
|
|
403
|
+
});
|
|
404
|
+
delete this.triggeredEventsData[eventName];
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Emits event with payload
|
|
409
|
+
*
|
|
410
|
+
* @param {string} eventName - event name to emit
|
|
411
|
+
* @param {Array<any>} payload - event payload
|
|
412
|
+
* @returns {void}
|
|
413
|
+
*/
|
|
414
|
+
emit(eventName, ...payload) {
|
|
415
|
+
const eventListeners = this.events.listeners(eventName);
|
|
416
|
+
if (eventListeners.length === 0) {
|
|
417
|
+
this.triggeredEventsData[eventName] = this.triggeredEventsData[eventName] || [];
|
|
418
|
+
this.triggeredEventsData[eventName].push(payload);
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
this.events.emit(eventName, ...payload);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Unsubscribe from event notification
|
|
426
|
+
*
|
|
427
|
+
* @param {string} eventName - event name to unsubscribe from
|
|
428
|
+
* @param {Function} callback - event handler
|
|
429
|
+
* @returns {void}
|
|
430
|
+
*/
|
|
431
|
+
off(eventName, callback) {
|
|
432
|
+
this.events.removeListener(eventName, callback);
|
|
433
|
+
if (this.triggeredEventsData[eventName]) {
|
|
434
|
+
delete this.triggeredEventsData[eventName];
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Initialize start data loading
|
|
439
|
+
*
|
|
440
|
+
* @param {JaqlRequest} [jaql] - JAQL request object
|
|
441
|
+
* @param {object} [options] - additional options
|
|
442
|
+
* @param {number} [options.pageSize=100] - page size to wait
|
|
443
|
+
* @param {boolean} [options.isPaginated=false] - defines which type of treeService to return,
|
|
444
|
+
* partial or paginated
|
|
445
|
+
* @param {Array<JaqlPanel>} [options.metadata] - jaql's metadata
|
|
446
|
+
* @param {boolean} [options.cacheResult=false] - cache result for next call or not
|
|
447
|
+
* @returns {Promise<any>} - promise with initial data to render
|
|
448
|
+
*/
|
|
449
|
+
// eslint-disable-next-line max-lines-per-function,sonarjs/cognitive-complexity
|
|
450
|
+
loadData(jaql, options) {
|
|
451
|
+
// console.log('loadData', jaql, options);
|
|
452
|
+
const { pageSize = DEFAULT_PAGE_SIZE, isPaginated = false, cacheResult = false, metadata, } = options || {};
|
|
453
|
+
const pageSizeIsNotChanged = this.pageSize === pageSize;
|
|
454
|
+
this.clearLoadAllPromise();
|
|
455
|
+
if (jaql) {
|
|
456
|
+
this.clearCache();
|
|
457
|
+
// TODO review this
|
|
458
|
+
// this.onDataHandlerThrottle.cancel();
|
|
459
|
+
}
|
|
460
|
+
this.pageSize = pageSize;
|
|
461
|
+
this.isPaginated = isPaginated;
|
|
462
|
+
this.emit(EVENT_DATA_LOAD);
|
|
463
|
+
if (this.loadPromiseCache && pageSizeIsNotChanged) {
|
|
464
|
+
const loadPromise = Promise.resolve(this.loadPromiseCache);
|
|
465
|
+
this.loadPromiseCache = undefined;
|
|
466
|
+
return loadPromise;
|
|
467
|
+
}
|
|
468
|
+
this.isLoadInProgress = true;
|
|
469
|
+
if (jaql) {
|
|
470
|
+
this.metadata = metadata || [];
|
|
471
|
+
this.rawJaql = getJaqlComposition(jaql, this.metadata);
|
|
472
|
+
// console.log('getJaqlComposition', jaql, this.metadata, this.rawJaql);
|
|
473
|
+
this.initPluginService(this.rawJaql);
|
|
474
|
+
this.loadService
|
|
475
|
+
.load(jaql)
|
|
476
|
+
.then((data) => {
|
|
477
|
+
if (data === null || data === undefined) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
const isDataNotExist = !('data' in data);
|
|
481
|
+
const isDataTransferFinished = data.dataFinish[0];
|
|
482
|
+
if (isDataTransferFinished && isDataNotExist) {
|
|
483
|
+
// eslint-disable-next-line no-throw-literal
|
|
484
|
+
throw {
|
|
485
|
+
error: {
|
|
486
|
+
error: true,
|
|
487
|
+
details: 'metadata undefined.',
|
|
488
|
+
},
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
})
|
|
492
|
+
.catch((data) => {
|
|
493
|
+
if (this.loadPromiseReject) {
|
|
494
|
+
this.loadPromiseReject(data.error);
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
const loadPromise = new Promise((resolve, reject) => {
|
|
499
|
+
this.loadPromiseResolve = resolve;
|
|
500
|
+
this.loadPromiseReject = reject;
|
|
501
|
+
})
|
|
502
|
+
.then((loadedCount) => this.sendInitPage(loadedCount))
|
|
503
|
+
.then((data) => {
|
|
504
|
+
if (cacheResult) {
|
|
505
|
+
this.loadPromiseCache = data;
|
|
506
|
+
}
|
|
507
|
+
this.loadedPagesCount = 1;
|
|
508
|
+
return data;
|
|
509
|
+
})
|
|
510
|
+
.catch((err) => {
|
|
511
|
+
if (err instanceof LoadingCanceledError) {
|
|
512
|
+
this.clearLoadPromise();
|
|
513
|
+
}
|
|
514
|
+
throw err;
|
|
515
|
+
});
|
|
516
|
+
this.checkLoadPromise();
|
|
517
|
+
return loadPromise;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Sets Promise that resolves after all data loaded
|
|
521
|
+
*
|
|
522
|
+
* @returns {Promise<{ loadedRowsCount: number, totalItemsCount: number }>} - promise with
|
|
523
|
+
* loaded items count
|
|
524
|
+
*/
|
|
525
|
+
loadAllData() {
|
|
526
|
+
if (this.isWholeDataLoaded) {
|
|
527
|
+
const allDataInfo = {
|
|
528
|
+
loadedRowsCount: this.getLoadedElementsCount(),
|
|
529
|
+
totalItemsCount: typeof this.totalRowsCount === 'number' ? this.totalRowsCount : this.getTotalItemsCount(),
|
|
530
|
+
totalRecordsCount: this.totalRecordsCount,
|
|
531
|
+
limitReached: this.limitReached,
|
|
532
|
+
dataBars: this.dataBars,
|
|
533
|
+
rangeMinMax: this.rangeMinMax,
|
|
534
|
+
};
|
|
535
|
+
if (this.columnsCount !== 0 && this.totalColumnsCount !== 0) {
|
|
536
|
+
allDataInfo.columnsCount = this.columnsCount;
|
|
537
|
+
allDataInfo.totalColumnsCount = this.totalColumnsCount;
|
|
538
|
+
}
|
|
539
|
+
return Promise.resolve(allDataInfo);
|
|
540
|
+
}
|
|
541
|
+
if (!this.loadAllPromise) {
|
|
542
|
+
this.loadAllPromise = new Promise((resolve, reject) => {
|
|
543
|
+
this.loadAllPromiseResolve = resolve;
|
|
544
|
+
this.loadAllPromiseReject = reject;
|
|
545
|
+
})
|
|
546
|
+
.then(() => ({
|
|
547
|
+
loadedRowsCount: this.getLoadedElementsCount(),
|
|
548
|
+
totalItemsCount: typeof this.totalRowsCount === 'number'
|
|
549
|
+
? this.totalRowsCount
|
|
550
|
+
: this.getTotalItemsCount(),
|
|
551
|
+
totalRecordsCount: this.totalRecordsCount,
|
|
552
|
+
limitReached: this.limitReached,
|
|
553
|
+
dataBars: this.dataBars,
|
|
554
|
+
rangeMinMax: this.rangeMinMax,
|
|
555
|
+
}))
|
|
556
|
+
.catch((err) => {
|
|
557
|
+
if (err instanceof LoadingCanceledError) {
|
|
558
|
+
this.clearLoadAllPromise();
|
|
559
|
+
}
|
|
560
|
+
throw err;
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
return this.loadAllPromise;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* public method for selecting page and setting new page size
|
|
567
|
+
*
|
|
568
|
+
* @param {number} selected - page number
|
|
569
|
+
* @param {number} pageSize - set page size (optional)
|
|
570
|
+
* @returns {Promise<{rowsTreeService, columnsTreeService, cornerTreeService, isLastPage}>}
|
|
571
|
+
* - returns private method's call with panel's treeServices
|
|
572
|
+
*/
|
|
573
|
+
getSelectedPageData(selected, pageSize) {
|
|
574
|
+
return Promise.resolve(this.sendPaginatedPage(selected, pageSize));
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* public method for selecting page by indexes
|
|
578
|
+
*
|
|
579
|
+
* @param {number} from - first row's index
|
|
580
|
+
* @param {number} to - last row's index
|
|
581
|
+
* @param {boolean} lastPage - append grandTotals
|
|
582
|
+
* @returns {Promise<{rowsTreeService, columnsTreeService, cornerTreeService, isLastPage}>}
|
|
583
|
+
* - returns private method's call with panel's treeServices
|
|
584
|
+
*/
|
|
585
|
+
getIndexedPageData(from, to, lastPage = false) {
|
|
586
|
+
return Promise.resolve(this.sendPartialPage(from, to, lastPage));
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Returns current jaql request object
|
|
590
|
+
*
|
|
591
|
+
* @returns {JaqlRequest} - jaql request object
|
|
592
|
+
*/
|
|
593
|
+
getJaql() {
|
|
594
|
+
return (this.loadService.getJaql() || {
|
|
595
|
+
metadata: [],
|
|
596
|
+
grandTotals: null,
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Defines data structure
|
|
601
|
+
*
|
|
602
|
+
* @returns {boolean} - true - single branch tree
|
|
603
|
+
*/
|
|
604
|
+
isSingleRowTree() {
|
|
605
|
+
return this.loadService.isSingleRowTree();
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Set cell process handlers
|
|
609
|
+
*
|
|
610
|
+
* @param {Array<PluginConfig>} handlers - object with target and handler
|
|
611
|
+
* @returns {void}
|
|
612
|
+
*/
|
|
613
|
+
setPluginHandlers(handlers) {
|
|
614
|
+
this.callPlugins = handlers;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Set global styles for all cells
|
|
618
|
+
*
|
|
619
|
+
* @param {GlobalStyles} [styles] - object with target and handler
|
|
620
|
+
* @returns {void}
|
|
621
|
+
*/
|
|
622
|
+
setGlobalStyles(styles) {
|
|
623
|
+
this.globalStyles = styles;
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Returns current raw jaql request object
|
|
627
|
+
*
|
|
628
|
+
* @returns {JaqlRequest} - composition of required jaql fields
|
|
629
|
+
* @private
|
|
630
|
+
*/
|
|
631
|
+
getRawJaql() {
|
|
632
|
+
return this.rawJaql || this.getJaql();
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Returns current jaql request metadata array
|
|
636
|
+
*
|
|
637
|
+
* @returns {Array<JaqlPanel>} - jaql request metadata
|
|
638
|
+
* @private
|
|
639
|
+
*/
|
|
640
|
+
getMetadata() {
|
|
641
|
+
return this.metadata.length > 0 ? this.metadata : this.getJaql().metadata;
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Pre-process initial tree structure
|
|
645
|
+
*
|
|
646
|
+
* @param {Array<TreeNode>} items - items to normalize
|
|
647
|
+
* @param {string} type - items types to normalize
|
|
648
|
+
* @param {object} options - additional options
|
|
649
|
+
* @param {number} [options.level=0] - tree level, for internal use only
|
|
650
|
+
* @param {object} [options.measurePath={}] - items types to normalize
|
|
651
|
+
* @returns {Array<PivotTreeNode>} - normalized list of items
|
|
652
|
+
*/
|
|
653
|
+
preProcessTree(items, type, options) {
|
|
654
|
+
return pivotTransforms.preProcessTree(items, type, this.getJaql(), options);
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Post-process final tree structure with formatting event
|
|
658
|
+
*
|
|
659
|
+
* @param {PivotTreeNode} items - list of PivotTreeNode items
|
|
660
|
+
* @param {object} [options] - additional options
|
|
661
|
+
* @param {boolean} [options.skipFormatEvent] - process tree but skip format event trigger
|
|
662
|
+
* @param {boolean} [options.onlyFormatEvents] - process tree with format event trigger only
|
|
663
|
+
* @param {Function} [options.iterateFn] - iterate function to call for each tree node
|
|
664
|
+
* @returns {void}
|
|
665
|
+
*/
|
|
666
|
+
postProcessTree(items, options) {
|
|
667
|
+
const emitFn = (item, panel, jaql) => this.emit(EVENT_HEADER_CELL_FORMAT, item, panel, jaql, this.options);
|
|
668
|
+
const extendedOptions = Object.assign(Object.assign({}, (options || {})), { emitFn });
|
|
669
|
+
return pivotTransforms.postProcessTree(items, this.getRawJaql(), extendedOptions);
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Post-process data list with formatting event
|
|
673
|
+
*
|
|
674
|
+
* @param {PivotTreeNode} items - list of PivotTreeNode rows items
|
|
675
|
+
* @param {object} [options] - additional options
|
|
676
|
+
* @param {boolean} [options.skipFormatEvent] - process data list but skip format event trigger
|
|
677
|
+
* @param {boolean} [options.onlyFormatEvents] - process data list with format event
|
|
678
|
+
* trigger only
|
|
679
|
+
* @returns {void}
|
|
680
|
+
*/
|
|
681
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
682
|
+
postProcessData(items, options) {
|
|
683
|
+
const { skipFormatEvent = false, onlyFormatEvents = false } = options || {};
|
|
684
|
+
const columns = this.columnsTreeService ? this.columnsTreeService.getLastLevelNodes() : [];
|
|
685
|
+
const rows = treeNode.getLastLevelNodes(items);
|
|
686
|
+
const jaql = this.getRawJaql();
|
|
687
|
+
if (skipFormatEvent) {
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
rows.forEach((rowTreeNode) => {
|
|
691
|
+
const rowItem = createPivotTreeNode(rowTreeNode);
|
|
692
|
+
columns.forEach((columnTreeNode) => {
|
|
693
|
+
const columnItem = createPivotTreeNode(columnTreeNode);
|
|
694
|
+
const measurePanel = jaqlProcessor.getMetadataPanelByIndex(jaql, columnItem.measureJaqlIndex, PanelType.MEASURES);
|
|
695
|
+
if (typeof rowItem.data !== 'undefined' && typeof columnItem.index !== 'undefined') {
|
|
696
|
+
const { data = [] } = rowItem;
|
|
697
|
+
const { index } = columnItem;
|
|
698
|
+
const value = data[index];
|
|
699
|
+
const item = typeof value === 'object' && value !== null && value !== undefined ? value : { value };
|
|
700
|
+
data[index] = item;
|
|
701
|
+
if (onlyFormatEvents || !skipFormatEvent) {
|
|
702
|
+
const { skipInternalColorFormatting = false } = this.options;
|
|
703
|
+
if (!skipInternalColorFormatting) {
|
|
704
|
+
pivotTransforms.applyColorFormatting(item, rowItem, columnItem, measurePanel);
|
|
705
|
+
}
|
|
706
|
+
this.emit(EVENT_DATA_CELL_FORMAT, item, rowItem, columnItem, measurePanel, jaql, this.options);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Modify tree structure for subtotals and grand totals and some customization
|
|
714
|
+
*
|
|
715
|
+
* @param {Array<PivotTreeNode>} items - base items to modify
|
|
716
|
+
* @param {string} type - items types to normalize
|
|
717
|
+
* @param {TreeNode} originalData - initial data object
|
|
718
|
+
* @returns {PivotTreeNode | Array<PivotTreeNode>} - normalized list of items
|
|
719
|
+
*/
|
|
720
|
+
modifyTree(items, type, originalData) {
|
|
721
|
+
const jaql = this.getJaql();
|
|
722
|
+
return pivotTransforms.modifyTree(items, type, jaql, {
|
|
723
|
+
originalData,
|
|
724
|
+
applyIndexDivergence: this.applyIndexDivergence.bind(this),
|
|
725
|
+
subtotalsForSingleRow: this.options.subtotalsForSingleRow,
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* method calculates divergence by prev indexes
|
|
730
|
+
*
|
|
731
|
+
* @param {Array<PivotTreeNode>} items - data to modify divergence and apply
|
|
732
|
+
* @returns {void}
|
|
733
|
+
* @private
|
|
734
|
+
*/
|
|
735
|
+
applyIndexDivergence(items) {
|
|
736
|
+
this.divergenceComparator = new DivergenceComparator(items, this.divergenceComparator);
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* method creates plugin service instance for pivot
|
|
740
|
+
*
|
|
741
|
+
* @param {JaqlRequest} jaql - data to modify divergence and apply
|
|
742
|
+
* @returns {void}
|
|
743
|
+
* @private
|
|
744
|
+
*/
|
|
745
|
+
initPluginService(jaql) {
|
|
746
|
+
this.pluginService = new this.options.PluginService(this.callPlugins, jaql, this.globalStyles);
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* Cancel current loading process
|
|
750
|
+
*
|
|
751
|
+
* @returns {void}
|
|
752
|
+
*/
|
|
753
|
+
cancelLoading() {
|
|
754
|
+
const loadingCanceledError = new LoadingCanceledError();
|
|
755
|
+
if (this.loadPromiseReject && typeof this.loadPromiseReject === 'function') {
|
|
756
|
+
this.loadPromiseReject(loadingCanceledError);
|
|
757
|
+
}
|
|
758
|
+
if (this.loadAllPromiseReject && typeof this.loadAllPromiseReject === 'function') {
|
|
759
|
+
this.loadAllPromiseReject(loadingCanceledError);
|
|
760
|
+
}
|
|
761
|
+
this.detachEvent();
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Returns final page size, excluding grand totals rows for example
|
|
765
|
+
*
|
|
766
|
+
* @returns {number} - page size
|
|
767
|
+
* @private
|
|
768
|
+
*/
|
|
769
|
+
getPageSize() {
|
|
770
|
+
return this.pageSize;
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
*
|
|
774
|
+
* Send result for "loadData" function after promise resolve
|
|
775
|
+
*
|
|
776
|
+
* @param {number} loadedCount - count of already loaded rows
|
|
777
|
+
* @returns {{
|
|
778
|
+
* rowsTreeService: TreeServiceI,
|
|
779
|
+
* columnsTreeService: TreeServiceI,
|
|
780
|
+
* corner: TreeNode,
|
|
781
|
+
* values: TreeNode,
|
|
782
|
+
* cellsMetadata: Map<string, Metadata>
|
|
783
|
+
* }} - object with initial data
|
|
784
|
+
* @private
|
|
785
|
+
*/
|
|
786
|
+
sendInitPage(loadedCount) {
|
|
787
|
+
if (this.loadService.hasError() || !this.loadService.hasData()) {
|
|
788
|
+
return DataService.getEmptyPage();
|
|
789
|
+
}
|
|
790
|
+
let partialRowsService;
|
|
791
|
+
let cellsMetadata;
|
|
792
|
+
const pageSize = this.getPageSize();
|
|
793
|
+
if (this.rowsTreeService) {
|
|
794
|
+
const from = 0;
|
|
795
|
+
const to = pageSize > loadedCount ? loadedCount : pageSize;
|
|
796
|
+
const cloneFn = DataService.cloneTreeNode;
|
|
797
|
+
const partialTree = this.rowsTreeService.getPartialTree(from, to, { cloneFn });
|
|
798
|
+
if (this.rowsGrand) {
|
|
799
|
+
partialTree.push(cloneObject(this.rowsGrand));
|
|
800
|
+
}
|
|
801
|
+
this.postProcessTree(partialTree, {
|
|
802
|
+
onlyFormatEvents: true,
|
|
803
|
+
iterateFn: treeNode.clearNodeCache,
|
|
804
|
+
});
|
|
805
|
+
this.postProcessData(partialTree, { onlyFormatEvents: true });
|
|
806
|
+
const deepLength = this.rowsTreeService ? this.rowsTreeService.getTreeDeepsLength() : 0;
|
|
807
|
+
const wrappedModifiedRows = treeNode.wrapInRootNode(partialTree);
|
|
808
|
+
if (this.pluginService && wrappedModifiedRows && wrappedModifiedRows.children) {
|
|
809
|
+
this.pluginService.applyToRows(wrappedModifiedRows.children);
|
|
810
|
+
cellsMetadata = this.pluginService.metadataCache;
|
|
811
|
+
}
|
|
812
|
+
partialRowsService = new TreeService(wrappedModifiedRows, true, deepLength);
|
|
813
|
+
partialRowsService.hasGrandTotals = !!this.rowsGrand;
|
|
814
|
+
}
|
|
815
|
+
const isLastPage = this.isWholeDataLoaded && pageSize >= loadedCount;
|
|
816
|
+
return {
|
|
817
|
+
rowsTreeService: partialRowsService,
|
|
818
|
+
columnsTreeService: this.columnsTreeService,
|
|
819
|
+
cornerTreeService: this.cornerTreeService,
|
|
820
|
+
isLastPage,
|
|
821
|
+
cellsMetadata,
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* Sets Page Size and returns Tree Services
|
|
826
|
+
*
|
|
827
|
+
* @param {number} selected - page number -- STARTING FROM 0
|
|
828
|
+
* @param {number} [newPageSize] - set new pageSize
|
|
829
|
+
* @returns {{
|
|
830
|
+
* rowsTreeService: null,
|
|
831
|
+
* columnsTreeService: TreeServiceI,
|
|
832
|
+
* cornerTreeService: TreeServiceI,
|
|
833
|
+
* isLastPage: boolean
|
|
834
|
+
* }} - returns panel's treeServices
|
|
835
|
+
* @private
|
|
836
|
+
*/
|
|
837
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
838
|
+
sendPaginatedPage(selected, newPageSize) {
|
|
839
|
+
if (this.loadService.hasError() || !this.loadService.hasData()) {
|
|
840
|
+
return DataService.getEmptyPage();
|
|
841
|
+
}
|
|
842
|
+
if (newPageSize) {
|
|
843
|
+
this.pageSize = newPageSize;
|
|
844
|
+
}
|
|
845
|
+
const pageSize = this.getPageSize();
|
|
846
|
+
const loadedCount = this.getLoadedElementsCount();
|
|
847
|
+
if (selected * pageSize >= loadedCount) {
|
|
848
|
+
throw new Error('Selected page is out of elements range!');
|
|
849
|
+
}
|
|
850
|
+
if (selected < 0) {
|
|
851
|
+
throw new Error('Selected page must be >= 0');
|
|
852
|
+
}
|
|
853
|
+
let partialRowsService;
|
|
854
|
+
let cellsMetadata;
|
|
855
|
+
if (this.rowsTreeService) {
|
|
856
|
+
const from = selected >= 0 ? selected * pageSize : 0;
|
|
857
|
+
const to = (selected + 1) * pageSize > loadedCount ? loadedCount : (selected + 1) * pageSize;
|
|
858
|
+
const cloneFn = DataService.cloneTreeNode;
|
|
859
|
+
const partialTree = this.rowsTreeService.getPartialTree(from, to, { cloneFn });
|
|
860
|
+
if (this.rowsGrand) {
|
|
861
|
+
partialTree.push(cloneObject(this.rowsGrand));
|
|
862
|
+
}
|
|
863
|
+
this.postProcessTree(partialTree, {
|
|
864
|
+
onlyFormatEvents: true,
|
|
865
|
+
iterateFn: treeNode.clearNodeCache,
|
|
866
|
+
});
|
|
867
|
+
this.postProcessData(partialTree, { onlyFormatEvents: true });
|
|
868
|
+
const deepLength = this.rowsTreeService ? this.rowsTreeService.getTreeDeepsLength() : 0;
|
|
869
|
+
const wrappedModifiedRows = treeNode.wrapInRootNode(partialTree);
|
|
870
|
+
if (this.pluginService && wrappedModifiedRows && wrappedModifiedRows.children) {
|
|
871
|
+
this.pluginService.applyToRows(wrappedModifiedRows.children);
|
|
872
|
+
cellsMetadata = this.pluginService.metadataCache;
|
|
873
|
+
}
|
|
874
|
+
partialRowsService = new TreeService(wrappedModifiedRows, true, deepLength);
|
|
875
|
+
partialRowsService.hasGrandTotals = !!this.rowsGrand;
|
|
876
|
+
}
|
|
877
|
+
return {
|
|
878
|
+
rowsTreeService: partialRowsService,
|
|
879
|
+
columnsTreeService: this.columnsTreeService,
|
|
880
|
+
cornerTreeService: this.cornerTreeService,
|
|
881
|
+
isLastPage: true,
|
|
882
|
+
cellsMetadata,
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Returns partial tree by indexes
|
|
887
|
+
*
|
|
888
|
+
* @param {number} paramFrom - start index
|
|
889
|
+
* @param {number} paramTo - stop index
|
|
890
|
+
* @param {boolean} lastPage - append grandTotals
|
|
891
|
+
* @returns {{
|
|
892
|
+
* rowsTreeService: TreeServiceI,
|
|
893
|
+
* columnsTreeService: TreeServiceI,
|
|
894
|
+
* cornerTreeService: TreeServiceI,
|
|
895
|
+
* isLastPage: boolean
|
|
896
|
+
* }} - returns panel's treeServices
|
|
897
|
+
* @private
|
|
898
|
+
*/
|
|
899
|
+
sendPartialPage(paramFrom, paramTo, lastPage) {
|
|
900
|
+
if (this.loadService.hasError() || !this.loadService.hasData()) {
|
|
901
|
+
return DataService.getEmptyPage();
|
|
902
|
+
}
|
|
903
|
+
const loadedCount = this.getLoadedElementsCount();
|
|
904
|
+
let [from, to] = [Math.min(paramFrom, paramTo), Math.max(paramFrom, paramTo)];
|
|
905
|
+
from = from >= 0 ? from : 0;
|
|
906
|
+
to = to >= 0 ? to : 0;
|
|
907
|
+
to = to < loadedCount ? to : loadedCount;
|
|
908
|
+
let rowsTreeService;
|
|
909
|
+
let cellsMetadata;
|
|
910
|
+
if (from > loadedCount) {
|
|
911
|
+
rowsTreeService = undefined;
|
|
912
|
+
}
|
|
913
|
+
else {
|
|
914
|
+
let partialTree;
|
|
915
|
+
if (this.rowsTreeService) {
|
|
916
|
+
const cloneFn = DataService.cloneTreeNode;
|
|
917
|
+
partialTree = this.rowsTreeService.getPartialTree(from, to, { cloneFn });
|
|
918
|
+
if (lastPage && this.rowsGrand) {
|
|
919
|
+
partialTree.push(cloneObject(this.rowsGrand));
|
|
920
|
+
}
|
|
921
|
+
this.postProcessTree(partialTree, {
|
|
922
|
+
onlyFormatEvents: true,
|
|
923
|
+
iterateFn: treeNode.clearNodeCache,
|
|
924
|
+
});
|
|
925
|
+
this.postProcessData(partialTree, { onlyFormatEvents: true });
|
|
926
|
+
}
|
|
927
|
+
const deepLength = this.rowsTreeService ? this.rowsTreeService.getTreeDeepsLength() : 0;
|
|
928
|
+
const wrappedModifiedRows = treeNode.wrapInRootNode(partialTree);
|
|
929
|
+
if (this.pluginService && wrappedModifiedRows && wrappedModifiedRows.children) {
|
|
930
|
+
this.pluginService.applyToRows(wrappedModifiedRows.children);
|
|
931
|
+
cellsMetadata = this.pluginService.metadataCache;
|
|
932
|
+
}
|
|
933
|
+
rowsTreeService = new TreeService(wrappedModifiedRows, true, deepLength);
|
|
934
|
+
rowsTreeService.hasGrandTotals = !!(lastPage && this.rowsGrand);
|
|
935
|
+
}
|
|
936
|
+
return {
|
|
937
|
+
rowsTreeService,
|
|
938
|
+
columnsTreeService: this.columnsTreeService,
|
|
939
|
+
cornerTreeService: this.cornerTreeService,
|
|
940
|
+
isLastPage: true,
|
|
941
|
+
cellsMetadata,
|
|
942
|
+
};
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
*
|
|
946
|
+
* Get current state of tree (not recommended to use before 'loadData')
|
|
947
|
+
*
|
|
948
|
+
* @returns {number} loadedCount - current loaded count of children
|
|
949
|
+
* @private
|
|
950
|
+
*/
|
|
951
|
+
getLoadedElementsCount() {
|
|
952
|
+
return this.rowsTreeService ? this.rowsTreeService.getTreeChildLength() : 0;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Returns total amount items count handled on back-end side
|
|
956
|
+
*
|
|
957
|
+
* @deprecated
|
|
958
|
+
* @returns {number} - items count
|
|
959
|
+
* @private
|
|
960
|
+
*/
|
|
961
|
+
getTotalItemsCount() {
|
|
962
|
+
return this.loadService.getTotalItemsCount();
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Getter for pivot table loaded columns number
|
|
966
|
+
*
|
|
967
|
+
* @deprecated
|
|
968
|
+
* @returns {number} loadedCount - current loaded pivot table columns count
|
|
969
|
+
* @private
|
|
970
|
+
*/
|
|
971
|
+
getLoadedColumnsCount() {
|
|
972
|
+
return this.columnsTreeService ? this.columnsTreeService.getTreeChildLength() : 0;
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* Attach events to load service
|
|
976
|
+
* This is a key function implementing the Observer pattern
|
|
977
|
+
* DataService acts as Observer and subscribes its handlers to various
|
|
978
|
+
* data loading events emitted by the load service.
|
|
979
|
+
*
|
|
980
|
+
*
|
|
981
|
+
* @returns {void}
|
|
982
|
+
* @private
|
|
983
|
+
*/
|
|
984
|
+
attachEvent() {
|
|
985
|
+
if (this.loadService.listenerCount(MessageType.HEADERS)) {
|
|
986
|
+
this.loadService.offAll(MessageType.HEADERS);
|
|
987
|
+
}
|
|
988
|
+
this.loadService.on(MessageType.HEADERS, this.onHeadersHandler);
|
|
989
|
+
this.loadService.on(MessageType.METADATA, this.onMetadataHandler);
|
|
990
|
+
this.loadService.on(MessageType.DATA, this.onDataHandler);
|
|
991
|
+
this.loadService.on(MessageType.GRAND, this.onGrandHandler);
|
|
992
|
+
this.loadService.on(MessageType.DATA_FINISH, this.onDataFinishHandler);
|
|
993
|
+
this.loadService.on(MessageType.TOTAL_ROWS, this.onTotalRowsHandler);
|
|
994
|
+
this.loadService.on(MessageType.DATABARS, this.onDataBarsHandler);
|
|
995
|
+
this.loadService.on(MessageType.RANGE_MIN_MAX, this.onRangeMinMaxHandler);
|
|
996
|
+
this.loadService.on(MessageType.FINISH, this.onFinishHandler);
|
|
997
|
+
this.loadService.on(MessageType.ERROR, this.onErrorHandler);
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* Dettach events from load service
|
|
1001
|
+
*
|
|
1002
|
+
* @returns {void}
|
|
1003
|
+
* @private
|
|
1004
|
+
*/
|
|
1005
|
+
detachEvent() {
|
|
1006
|
+
this.loadService.off(MessageType.HEADERS, this.onHeadersHandler);
|
|
1007
|
+
this.loadService.off(MessageType.METADATA, this.onMetadataHandler);
|
|
1008
|
+
this.loadService.off(MessageType.DATA, this.onDataHandler);
|
|
1009
|
+
this.loadService.off(MessageType.GRAND, this.onGrandHandler);
|
|
1010
|
+
this.loadService.off(MessageType.DATA_FINISH, this.onDataFinishHandler);
|
|
1011
|
+
this.loadService.off(MessageType.TOTAL_ROWS, this.onTotalRowsHandler);
|
|
1012
|
+
this.loadService.off(MessageType.DATABARS, this.onDataBarsHandler);
|
|
1013
|
+
this.loadService.off(MessageType.RANGE_MIN_MAX, this.onRangeMinMaxHandler);
|
|
1014
|
+
this.loadService.off(MessageType.FINISH, this.onFinishHandler);
|
|
1015
|
+
this.loadService.off(MessageType.ERROR, this.onErrorHandler);
|
|
1016
|
+
}
|
|
1017
|
+
/**
|
|
1018
|
+
* Check for enough data loaded and resolve promise of "loadData" function
|
|
1019
|
+
*
|
|
1020
|
+
* @returns {void}
|
|
1021
|
+
* @private
|
|
1022
|
+
*/
|
|
1023
|
+
checkLoadPromise() {
|
|
1024
|
+
if (!this.isLoadInProgress) {
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
const loadedCount = this.getLoadedElementsCount();
|
|
1028
|
+
if (loadedCount >= this.getPageSize() || this.isWholeDataLoaded) {
|
|
1029
|
+
this.isLoadInProgress = false;
|
|
1030
|
+
if (typeof this.loadPromiseResolve === 'function') {
|
|
1031
|
+
this.loadPromiseResolve(loadedCount);
|
|
1032
|
+
this.clearLoadPromise();
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
/**
|
|
1037
|
+
* @returns {void}
|
|
1038
|
+
* @private
|
|
1039
|
+
*/
|
|
1040
|
+
clearLoadAllPromise() {
|
|
1041
|
+
this.loadAllPromise = undefined;
|
|
1042
|
+
this.loadAllPromiseReject = undefined;
|
|
1043
|
+
this.loadAllPromiseResolve = undefined;
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* @returns {void}
|
|
1047
|
+
* @private
|
|
1048
|
+
*/
|
|
1049
|
+
clearLoadPromise() {
|
|
1050
|
+
this.loadPromiseReject = undefined;
|
|
1051
|
+
this.loadPromiseResolve = undefined;
|
|
1052
|
+
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Mark finish request
|
|
1055
|
+
*
|
|
1056
|
+
* @returns {void}
|
|
1057
|
+
* @private
|
|
1058
|
+
*/
|
|
1059
|
+
finishRequest() {
|
|
1060
|
+
this.hasDataFinishEvent = true;
|
|
1061
|
+
// even if the finish request arrives but the data handling is still being throttled
|
|
1062
|
+
// we cannot resolve the loadAllPromiseResolve because there are still data chunks
|
|
1063
|
+
// in temp storage to be processed
|
|
1064
|
+
if (this.isDataHandlerThrottled) {
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
this.isWholeDataLoaded = true;
|
|
1068
|
+
if (this.loadAllPromiseResolve && typeof this.loadAllPromiseResolve === 'function') {
|
|
1069
|
+
this.loadAllPromiseResolve();
|
|
1070
|
+
this.clearLoadAllPromise();
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Clear internal cache in case new JAQL request send
|
|
1075
|
+
*
|
|
1076
|
+
* @returns {void}
|
|
1077
|
+
* @private
|
|
1078
|
+
*/
|
|
1079
|
+
clearCache() {
|
|
1080
|
+
this.rowsGrand = undefined;
|
|
1081
|
+
this.rowsTreeService = undefined;
|
|
1082
|
+
this.columnsTreeService = undefined;
|
|
1083
|
+
this.loadedPagesCount = 0;
|
|
1084
|
+
this.hasDataFinishEvent = false;
|
|
1085
|
+
this.isWholeDataLoaded = false;
|
|
1086
|
+
this.isLoadInProgress = false;
|
|
1087
|
+
this.tempDataChunks = [];
|
|
1088
|
+
this.lastNotHandledChunkIndex = 0;
|
|
1089
|
+
this.lastReadyNotHandledChunkIndex = 0;
|
|
1090
|
+
this.isDataHandlerThrottled = false;
|
|
1091
|
+
}
|
|
1092
|
+
static getEmptyPage() {
|
|
1093
|
+
return {
|
|
1094
|
+
isLastPage: true,
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
static fillDataChunks(list, node, firstMaxSize = NODES_CHUNK_SIZE_MAX, maxSize = NODES_CHUNK_SIZE_MAX) {
|
|
1098
|
+
const isFirstChunk = list.length < 2;
|
|
1099
|
+
const maxChunkSize = isFirstChunk ? firstMaxSize : maxSize;
|
|
1100
|
+
let lastChunk = list[Math.max(0, list.length - 1)];
|
|
1101
|
+
let lastChunkNode;
|
|
1102
|
+
let createNewChunk = !lastChunk;
|
|
1103
|
+
if (!node ||
|
|
1104
|
+
(typeof node.children === 'undefined' &&
|
|
1105
|
+
typeof node.value === 'undefined' &&
|
|
1106
|
+
node.data &&
|
|
1107
|
+
!node.data.length)) {
|
|
1108
|
+
if (lastChunk) {
|
|
1109
|
+
lastChunk.ready = true;
|
|
1110
|
+
}
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
if (lastChunk) {
|
|
1114
|
+
const lastChunkNodeIndex = Math.max(0, lastChunk.list.length - 1);
|
|
1115
|
+
lastChunkNode = lastChunk.list[lastChunkNodeIndex];
|
|
1116
|
+
const lastChunkSizeStr = lastChunk.size ? `${lastChunk.size}` : '0';
|
|
1117
|
+
const lastChunkSize = parseInt(lastChunkSizeStr, 10);
|
|
1118
|
+
const afterLastChunkSize = lastChunkSize + (node.size || 1);
|
|
1119
|
+
if (lastChunk.handled ||
|
|
1120
|
+
(afterLastChunkSize > maxChunkSize &&
|
|
1121
|
+
!(lastChunkNode.isPart && lastChunkNode.value === node.value))) {
|
|
1122
|
+
createNewChunk = true;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
if (node &&
|
|
1126
|
+
node.isPart &&
|
|
1127
|
+
lastChunkNode &&
|
|
1128
|
+
(!lastChunkNode.isPart || lastChunkNode.value !== node.value)) {
|
|
1129
|
+
createNewChunk = true;
|
|
1130
|
+
if (lastChunkNode.value !== node.value) {
|
|
1131
|
+
lastChunkNode = undefined;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
if (createNewChunk) {
|
|
1135
|
+
if (lastChunk) {
|
|
1136
|
+
lastChunk.ready = true;
|
|
1137
|
+
}
|
|
1138
|
+
lastChunk = {
|
|
1139
|
+
list: [],
|
|
1140
|
+
size: 0,
|
|
1141
|
+
ready: false,
|
|
1142
|
+
handled: false,
|
|
1143
|
+
};
|
|
1144
|
+
list.push(lastChunk);
|
|
1145
|
+
}
|
|
1146
|
+
if (lastChunk) {
|
|
1147
|
+
if (lastChunkNode && lastChunkNode.isPart && node && node.isPart) {
|
|
1148
|
+
treeNode.deepMerge(lastChunkNode, node);
|
|
1149
|
+
lastChunk.size += node.size || 1;
|
|
1150
|
+
}
|
|
1151
|
+
else {
|
|
1152
|
+
lastChunk.list.push(node);
|
|
1153
|
+
lastChunk.size += node.size || 1;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
static cloneTreeNode(obj, skipChildren) {
|
|
1158
|
+
// return cloneObject(obj);
|
|
1159
|
+
const node = obj;
|
|
1160
|
+
const { children, isMapped, // eslint-disable-line no-unused-vars
|
|
1161
|
+
minLevel, // eslint-disable-line no-unused-vars
|
|
1162
|
+
childCount, // eslint-disable-line no-unused-vars
|
|
1163
|
+
childDeep, // eslint-disable-line no-unused-vars
|
|
1164
|
+
// @ts-ignore
|
|
1165
|
+
parent,
|
|
1166
|
+
// @ts-ignore
|
|
1167
|
+
master,
|
|
1168
|
+
// @ts-ignore
|
|
1169
|
+
data,
|
|
1170
|
+
// @ts-ignore
|
|
1171
|
+
state,
|
|
1172
|
+
// @ts-ignore
|
|
1173
|
+
style,
|
|
1174
|
+
// @ts-ignore
|
|
1175
|
+
store } = node, restNode = __rest(node, ["children", "isMapped", "minLevel", "childCount", "childDeep", "parent", "master", "data", "state", "style", "store"]);
|
|
1176
|
+
const clone = cloneObject(restNode);
|
|
1177
|
+
if (parent) {
|
|
1178
|
+
clone.parent = parent;
|
|
1179
|
+
}
|
|
1180
|
+
if (master) {
|
|
1181
|
+
clone.master = master;
|
|
1182
|
+
}
|
|
1183
|
+
if (data) {
|
|
1184
|
+
clone.data = cloneObject(data);
|
|
1185
|
+
}
|
|
1186
|
+
if (state) {
|
|
1187
|
+
clone.state = cloneObject(state);
|
|
1188
|
+
}
|
|
1189
|
+
if (style) {
|
|
1190
|
+
clone.style = cloneObject(style);
|
|
1191
|
+
}
|
|
1192
|
+
if (store) {
|
|
1193
|
+
clone.store = cloneObject(store);
|
|
1194
|
+
}
|
|
1195
|
+
if (!skipChildren && children) {
|
|
1196
|
+
clone.children = children.map((ch) => {
|
|
1197
|
+
const clonedChild = DataService.cloneTreeNode(ch);
|
|
1198
|
+
// @ts-ignore
|
|
1199
|
+
clonedChild.parent = clone;
|
|
1200
|
+
return clonedChild;
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
return clone;
|
|
1204
|
+
}
|
|
1205
|
+
/**
|
|
1206
|
+
* @typedef {Function} buildColumnsTreeService
|
|
1207
|
+
* @param {HeaderTreeNode} originalColumnsTree
|
|
1208
|
+
* @returns {BuildColumnsTreeServiceResult}
|
|
1209
|
+
*/
|
|
1210
|
+
/**
|
|
1211
|
+
* @typedef {object} BuildColumnsTreeServiceResult
|
|
1212
|
+
* @property {TreeNode|undefined} columnsTree
|
|
1213
|
+
* @property {TreeService|undefined} columnsTreeService
|
|
1214
|
+
* @property {number} columnsCount
|
|
1215
|
+
* @property {number} totalColumnsCount
|
|
1216
|
+
*/
|
|
1217
|
+
/**
|
|
1218
|
+
* Creates builder function for building columns tree service
|
|
1219
|
+
*
|
|
1220
|
+
* @param {object} handlers - build handlers
|
|
1221
|
+
* @param {Function} handlers.getJaql - jaql getter
|
|
1222
|
+
* @param {Function} [handlers.getRawJaql] - raw jaql getter
|
|
1223
|
+
* @param {PluginService} [handlers.pluginService] - plugin service
|
|
1224
|
+
* @param {Function} [handlers.applyIndexDivergence] - helper for calculation indexes divergence
|
|
1225
|
+
* @param {object} [events] - build event emitters
|
|
1226
|
+
* @param {Function} events.emitHeaderCellFormatEvent - emits EVENT_HEADER_CELL_FORMAT event
|
|
1227
|
+
* @returns {buildColumnsTreeService} - build function
|
|
1228
|
+
*/
|
|
1229
|
+
static createColumnsTreeServiceBuilder(handlers, events) {
|
|
1230
|
+
return (originalColumnsTree) => {
|
|
1231
|
+
const jaql = handlers.getJaql();
|
|
1232
|
+
const rawJaql = handlers.getRawJaql
|
|
1233
|
+
? handlers.getRawJaql()
|
|
1234
|
+
: getJaqlComposition(jaql, jaql.metadata || []);
|
|
1235
|
+
const valuesTree = jaqlProcessor.getMetadataTree(jaql, PanelType.MEASURES);
|
|
1236
|
+
const valuesTreeChildren = treeNode.getChildren(valuesTree);
|
|
1237
|
+
const { preProcessTree, modifyTree, postProcessTree } = pivotTransforms;
|
|
1238
|
+
let columnsTree;
|
|
1239
|
+
let columnsTreeService;
|
|
1240
|
+
let columnsCount = 0;
|
|
1241
|
+
let totalColumnsCount = 0;
|
|
1242
|
+
if (treeNode.hasChildren(originalColumnsTree)) {
|
|
1243
|
+
if (originalColumnsTree.columnsCount && originalColumnsTree.totalColumnsCount) {
|
|
1244
|
+
columnsCount = originalColumnsTree.columnsCount;
|
|
1245
|
+
totalColumnsCount = originalColumnsTree.totalColumnsCount;
|
|
1246
|
+
}
|
|
1247
|
+
const columns = preProcessTree(originalColumnsTree, PanelType.COLUMNS, jaql);
|
|
1248
|
+
const modifiedColumns = modifyTree(columns, PanelType.COLUMNS, jaql, {
|
|
1249
|
+
originalData: originalColumnsTree,
|
|
1250
|
+
applyIndexDivergence: handlers.applyIndexDivergence,
|
|
1251
|
+
});
|
|
1252
|
+
postProcessTree(modifiedColumns, rawJaql, {
|
|
1253
|
+
emitFn: events && events.emitHeaderCellFormatEvent,
|
|
1254
|
+
});
|
|
1255
|
+
const wrappedModifiedColumns = treeNode.wrapInRootNode(modifiedColumns);
|
|
1256
|
+
if (handlers.pluginService && wrappedModifiedColumns && wrappedModifiedColumns.children) {
|
|
1257
|
+
handlers.pluginService.applyToColumns(wrappedModifiedColumns.children);
|
|
1258
|
+
}
|
|
1259
|
+
columnsTree = wrappedModifiedColumns;
|
|
1260
|
+
columnsTreeService = new TreeService(wrappedModifiedColumns);
|
|
1261
|
+
if (valuesTreeChildren.length === 1) {
|
|
1262
|
+
columnsTreeService.setValueNode(valuesTreeChildren[0]);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
else if (treeNode.hasChildren(valuesTree)) {
|
|
1266
|
+
if (originalColumnsTree.columnsCount && originalColumnsTree.totalColumnsCount) {
|
|
1267
|
+
columnsCount = originalColumnsTree.columnsCount;
|
|
1268
|
+
totalColumnsCount = originalColumnsTree.totalColumnsCount;
|
|
1269
|
+
}
|
|
1270
|
+
// columns limit
|
|
1271
|
+
if (typeof originalColumnsTree.maxChilds === 'number') {
|
|
1272
|
+
columnsCount = originalColumnsTree.maxChilds;
|
|
1273
|
+
valuesTree.children = treeNode
|
|
1274
|
+
.getChildren(valuesTree)
|
|
1275
|
+
.filter((item, index) => index < originalColumnsTree.maxChilds);
|
|
1276
|
+
}
|
|
1277
|
+
if (handlers.pluginService && valuesTree.children) {
|
|
1278
|
+
handlers.pluginService.applyToColumns(valuesTree.children);
|
|
1279
|
+
}
|
|
1280
|
+
postProcessTree(treeNode.getChildren(valuesTree), rawJaql, {
|
|
1281
|
+
emitFn: events && events.emitHeaderCellFormatEvent,
|
|
1282
|
+
});
|
|
1283
|
+
columnsTree = valuesTree;
|
|
1284
|
+
columnsTreeService = new TreeService(valuesTree);
|
|
1285
|
+
}
|
|
1286
|
+
else {
|
|
1287
|
+
if (handlers.pluginService) {
|
|
1288
|
+
handlers.pluginService.resetRowStartFrom();
|
|
1289
|
+
}
|
|
1290
|
+
columnsTree = undefined;
|
|
1291
|
+
columnsTreeService = undefined;
|
|
1292
|
+
columnsCount = 0;
|
|
1293
|
+
totalColumnsCount = 0;
|
|
1294
|
+
}
|
|
1295
|
+
return {
|
|
1296
|
+
columnsTree,
|
|
1297
|
+
columnsTreeService,
|
|
1298
|
+
columnsCount,
|
|
1299
|
+
totalColumnsCount,
|
|
1300
|
+
};
|
|
1301
|
+
};
|
|
1302
|
+
}
|
|
1303
|
+
/**
|
|
1304
|
+
* @typedef {Function} buildCornerTreeService
|
|
1305
|
+
* @param {HeaderTreeNode} originalColumnsTree
|
|
1306
|
+
* @returns {BuildCornerTreeServiceResult}
|
|
1307
|
+
*/
|
|
1308
|
+
/**
|
|
1309
|
+
* @typedef {object} BuildCornerTreeServiceResult
|
|
1310
|
+
* @property {TreeNode|undefined} columnsTree
|
|
1311
|
+
* @property {TreeService|undefined} columnsTreeService
|
|
1312
|
+
* @property {number} columnsCount
|
|
1313
|
+
* @property {number} totalColumnsCount
|
|
1314
|
+
*/
|
|
1315
|
+
/**
|
|
1316
|
+
* Creates builder function for building corners tree service
|
|
1317
|
+
*
|
|
1318
|
+
* @param {object} handlers - build handlers
|
|
1319
|
+
* @param {Function} handlers.getJaql - jaql getter
|
|
1320
|
+
* @param {Function} [handlers.getRawJaql] - raw jaql getter
|
|
1321
|
+
* @param {PluginService} [handlers.pluginService] - plugin service
|
|
1322
|
+
* @param {TreeServiceI} [handlers.columnsTreeService] - column tree service
|
|
1323
|
+
* @param {object} [events] - build event emitters
|
|
1324
|
+
* @param {Function} events.emitHeaderCellFormatEvent - emits EVENT_HEADER_CELL_FORMAT event
|
|
1325
|
+
* @returns {buildCornerTreeService} - build function
|
|
1326
|
+
*/
|
|
1327
|
+
static createCornerTreeServiceBuilder(handlers, events) {
|
|
1328
|
+
return () => {
|
|
1329
|
+
const jaql = handlers.getJaql();
|
|
1330
|
+
const rawJaql = handlers.getRawJaql
|
|
1331
|
+
? handlers.getRawJaql()
|
|
1332
|
+
: getJaqlComposition(jaql, jaql.metadata || []);
|
|
1333
|
+
const cornerTree = jaqlProcessor.getMetadataTree(jaql, PanelType.ROWS);
|
|
1334
|
+
let cornerTreeService;
|
|
1335
|
+
if (treeNode.hasChildren(cornerTree)) {
|
|
1336
|
+
// add user type to tree node
|
|
1337
|
+
treeNode.iterateThroughTree(treeNode.getChildren(cornerTree), (item) => {
|
|
1338
|
+
item.userType = UserType.CORNER;
|
|
1339
|
+
const panel = jaqlProcessor.getMetadataPanelByIndex(rawJaql, item.jaqlIndex, item.metadataType || '');
|
|
1340
|
+
if (events && events.emitHeaderCellFormatEvent) {
|
|
1341
|
+
events.emitHeaderCellFormatEvent(item, panel, rawJaql);
|
|
1342
|
+
}
|
|
1343
|
+
});
|
|
1344
|
+
let cornerDeep;
|
|
1345
|
+
if (handlers.columnsTreeService) {
|
|
1346
|
+
cornerDeep = handlers.columnsTreeService.getTreeDeepsLength();
|
|
1347
|
+
}
|
|
1348
|
+
if (handlers.pluginService) {
|
|
1349
|
+
handlers.pluginService.applyToHeaders(cornerTree);
|
|
1350
|
+
}
|
|
1351
|
+
cornerTreeService = new TreeService(cornerTree, false, cornerDeep);
|
|
1352
|
+
}
|
|
1353
|
+
return { cornerTree, cornerTreeService };
|
|
1354
|
+
};
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
export default DataService;
|