@cubejs-client/react 0.35.0 → 0.35.23
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/dist/cubejs-client-react.esm.js +76 -147
- package/dist/cubejs-client-react.esm.js.map +1 -1
- package/dist/cubejs-client-react.js +128 -321
- package/dist/cubejs-client-react.js.map +1 -1
- package/dist/cubejs-client-react.umd.js +198 -538
- package/dist/cubejs-client-react.umd.js.map +1 -1
- package/package.json +3 -3
|
@@ -14,33 +14,29 @@ class QueryRenderer extends React.Component {
|
|
|
14
14
|
loadSql: null,
|
|
15
15
|
updateOnlyOnStateChange: false,
|
|
16
16
|
resetResultSetOnChange: true
|
|
17
|
-
};
|
|
17
|
+
};
|
|
18
18
|
|
|
19
|
+
// @deprecated use `isQueryPresent` from `@cubejs-client/core`
|
|
19
20
|
static isQueryPresent(query) {
|
|
20
21
|
return isQueryPresent(query);
|
|
21
22
|
}
|
|
22
|
-
|
|
23
23
|
constructor(props) {
|
|
24
24
|
super(props);
|
|
25
25
|
this.state = {};
|
|
26
26
|
this.mutexObj = {};
|
|
27
27
|
}
|
|
28
|
-
|
|
29
28
|
componentDidMount() {
|
|
30
29
|
const {
|
|
31
30
|
query,
|
|
32
31
|
queries
|
|
33
32
|
} = this.props;
|
|
34
|
-
|
|
35
33
|
if (query) {
|
|
36
34
|
this.load(query);
|
|
37
35
|
}
|
|
38
|
-
|
|
39
36
|
if (queries) {
|
|
40
37
|
this.loadQueries(queries);
|
|
41
38
|
}
|
|
42
39
|
}
|
|
43
|
-
|
|
44
40
|
shouldComponentUpdate(nextProps, nextState) {
|
|
45
41
|
const {
|
|
46
42
|
query,
|
|
@@ -50,34 +46,27 @@ class QueryRenderer extends React.Component {
|
|
|
50
46
|
loadSql,
|
|
51
47
|
updateOnlyOnStateChange
|
|
52
48
|
} = this.props;
|
|
53
|
-
|
|
54
49
|
if (!updateOnlyOnStateChange) {
|
|
55
50
|
return true;
|
|
56
51
|
}
|
|
57
|
-
|
|
58
52
|
return !equals(nextProps.query, query) || !equals(nextProps.queries, queries) || (nextProps.render == null || render == null) && nextProps.render !== render || nextProps.cubeApi !== cubeApi || nextProps.loadSql !== loadSql || !equals(nextState, this.state) || nextProps.updateOnlyOnStateChange !== updateOnlyOnStateChange;
|
|
59
53
|
}
|
|
60
|
-
|
|
61
54
|
componentDidUpdate(prevProps) {
|
|
62
55
|
const {
|
|
63
56
|
query,
|
|
64
57
|
queries
|
|
65
58
|
} = this.props;
|
|
66
|
-
|
|
67
59
|
if (!equals(prevProps.query, query)) {
|
|
68
60
|
this.load(query);
|
|
69
61
|
}
|
|
70
|
-
|
|
71
62
|
if (!equals(prevProps.queries, queries)) {
|
|
72
63
|
this.loadQueries(queries);
|
|
73
64
|
}
|
|
74
65
|
}
|
|
75
|
-
|
|
76
66
|
cubeApi() {
|
|
77
67
|
// eslint-disable-next-line react/destructuring-assignment
|
|
78
68
|
return this.props.cubeApi || this.context && this.context.cubeApi;
|
|
79
69
|
}
|
|
80
|
-
|
|
81
70
|
load(query) {
|
|
82
71
|
const {
|
|
83
72
|
resetResultSetOnChange
|
|
@@ -94,7 +83,6 @@ class QueryRenderer extends React.Component {
|
|
|
94
83
|
loadSql
|
|
95
84
|
} = this.props;
|
|
96
85
|
const cubeApi = this.cubeApi();
|
|
97
|
-
|
|
98
86
|
if (query && isQueryPresent(query)) {
|
|
99
87
|
if (loadSql === 'only') {
|
|
100
88
|
cubeApi.sql(query, {
|
|
@@ -104,7 +92,8 @@ class QueryRenderer extends React.Component {
|
|
|
104
92
|
sqlQuery,
|
|
105
93
|
error: null,
|
|
106
94
|
isLoading: false
|
|
107
|
-
})).catch(error => this.setState({
|
|
95
|
+
})).catch(error => this.setState({
|
|
96
|
+
...(resetResultSetOnChange ? {
|
|
108
97
|
resultSet: null
|
|
109
98
|
} : {}),
|
|
110
99
|
error,
|
|
@@ -122,7 +111,8 @@ class QueryRenderer extends React.Component {
|
|
|
122
111
|
resultSet,
|
|
123
112
|
error: null,
|
|
124
113
|
isLoading: false
|
|
125
|
-
})).catch(error => this.setState({
|
|
114
|
+
})).catch(error => this.setState({
|
|
115
|
+
...(resetResultSetOnChange ? {
|
|
126
116
|
resultSet: null
|
|
127
117
|
} : {}),
|
|
128
118
|
error,
|
|
@@ -136,7 +126,8 @@ class QueryRenderer extends React.Component {
|
|
|
136
126
|
resultSet,
|
|
137
127
|
error: null,
|
|
138
128
|
isLoading: false
|
|
139
|
-
})).catch(error => this.setState({
|
|
129
|
+
})).catch(error => this.setState({
|
|
130
|
+
...(resetResultSetOnChange ? {
|
|
140
131
|
resultSet: null
|
|
141
132
|
} : {}),
|
|
142
133
|
error,
|
|
@@ -145,7 +136,6 @@ class QueryRenderer extends React.Component {
|
|
|
145
136
|
}
|
|
146
137
|
}
|
|
147
138
|
}
|
|
148
|
-
|
|
149
139
|
loadQueries(queries) {
|
|
150
140
|
const cubeApi = this.cubeApi();
|
|
151
141
|
const {
|
|
@@ -166,14 +156,14 @@ class QueryRenderer extends React.Component {
|
|
|
166
156
|
resultSet: fromPairs(resultSet),
|
|
167
157
|
error: null,
|
|
168
158
|
isLoading: false
|
|
169
|
-
})).catch(error => this.setState({
|
|
159
|
+
})).catch(error => this.setState({
|
|
160
|
+
...(resetResultSetOnChange ? {
|
|
170
161
|
resultSet: null
|
|
171
162
|
} : {}),
|
|
172
163
|
error,
|
|
173
164
|
isLoading: false
|
|
174
165
|
}));
|
|
175
166
|
}
|
|
176
|
-
|
|
177
167
|
render() {
|
|
178
168
|
const {
|
|
179
169
|
error,
|
|
@@ -193,31 +183,25 @@ class QueryRenderer extends React.Component {
|
|
|
193
183
|
},
|
|
194
184
|
sqlQuery
|
|
195
185
|
};
|
|
196
|
-
|
|
197
186
|
if (render) {
|
|
198
187
|
return render(loadState);
|
|
199
188
|
}
|
|
200
|
-
|
|
201
189
|
return null;
|
|
202
190
|
}
|
|
203
|
-
|
|
204
191
|
}
|
|
205
192
|
|
|
206
193
|
function _extends() {
|
|
207
|
-
_extends = Object.assign
|
|
194
|
+
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
208
195
|
for (var i = 1; i < arguments.length; i++) {
|
|
209
196
|
var source = arguments[i];
|
|
210
|
-
|
|
211
197
|
for (var key in source) {
|
|
212
198
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
213
199
|
target[key] = source[key];
|
|
214
200
|
}
|
|
215
201
|
}
|
|
216
202
|
}
|
|
217
|
-
|
|
218
203
|
return target;
|
|
219
204
|
};
|
|
220
|
-
|
|
221
205
|
return _extends.apply(this, arguments);
|
|
222
206
|
}
|
|
223
207
|
|
|
@@ -226,9 +210,11 @@ const QueryRendererWithTotals = ({
|
|
|
226
210
|
...restProps
|
|
227
211
|
}) => /*#__PURE__*/React.createElement(QueryRenderer, _extends({
|
|
228
212
|
queries: {
|
|
229
|
-
totals: {
|
|
213
|
+
totals: {
|
|
214
|
+
...query,
|
|
230
215
|
dimensions: [],
|
|
231
|
-
timeDimensions: query.timeDimensions ? query.timeDimensions.map(td => ({
|
|
216
|
+
timeDimensions: query.timeDimensions ? query.timeDimensions.map(td => ({
|
|
217
|
+
...td,
|
|
232
218
|
granularity: null
|
|
233
219
|
})) : undefined
|
|
234
220
|
},
|
|
@@ -240,12 +226,10 @@ function removeEmpty(obj) {
|
|
|
240
226
|
if (typeof obj !== 'object') {
|
|
241
227
|
return obj;
|
|
242
228
|
}
|
|
243
|
-
|
|
244
229
|
return Object.fromEntries(Object.entries(obj).filter(([, v]) => v != null).map(([k, v]) => {
|
|
245
230
|
if (Array.isArray(v)) {
|
|
246
231
|
return [k, v.map(removeEmpty)];
|
|
247
232
|
}
|
|
248
|
-
|
|
249
233
|
return [k, typeof v === 'object' ? removeEmpty(v) : v];
|
|
250
234
|
}));
|
|
251
235
|
}
|
|
@@ -295,29 +279,29 @@ class QueryBuilder extends React.Component {
|
|
|
295
279
|
setQuery: null,
|
|
296
280
|
vizState: null,
|
|
297
281
|
setVizState: null
|
|
298
|
-
};
|
|
299
|
-
// https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#anti-pattern-unconditionally-copying-props-to-state
|
|
282
|
+
};
|
|
300
283
|
|
|
284
|
+
// This is an anti-pattern, only kept for backward compatibility
|
|
285
|
+
// https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#anti-pattern-unconditionally-copying-props-to-state
|
|
301
286
|
static getDerivedStateFromProps(props, state) {
|
|
302
287
|
if (props.query || props.vizState) {
|
|
303
|
-
const nextState = {
|
|
288
|
+
const nextState = {
|
|
289
|
+
...state,
|
|
304
290
|
...(props.vizState || {})
|
|
305
291
|
};
|
|
306
|
-
|
|
307
292
|
if (Array.isArray(props.query)) {
|
|
308
293
|
throw new Error('Array of queries is not supported.');
|
|
309
294
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
query: {
|
|
295
|
+
return {
|
|
296
|
+
...nextState,
|
|
297
|
+
query: {
|
|
298
|
+
...nextState.query,
|
|
313
299
|
...(props.query || {})
|
|
314
300
|
}
|
|
315
301
|
};
|
|
316
302
|
}
|
|
317
|
-
|
|
318
303
|
return null;
|
|
319
304
|
}
|
|
320
|
-
|
|
321
305
|
static resolveMember(type, {
|
|
322
306
|
meta,
|
|
323
307
|
query
|
|
@@ -325,29 +309,27 @@ class QueryBuilder extends React.Component {
|
|
|
325
309
|
if (!meta) {
|
|
326
310
|
return [];
|
|
327
311
|
}
|
|
328
|
-
|
|
329
312
|
if (Array.isArray(query)) {
|
|
330
313
|
return query.reduce((memo, currentQuery) => memo.concat(QueryBuilder.resolveMember(type, {
|
|
331
314
|
meta,
|
|
332
315
|
query: currentQuery
|
|
333
316
|
})), []);
|
|
334
317
|
}
|
|
335
|
-
|
|
336
318
|
if (type === 'timeDimensions') {
|
|
337
|
-
return (query.timeDimensions || []).map((m, index) => ({
|
|
338
|
-
|
|
319
|
+
return (query.timeDimensions || []).map((m, index) => ({
|
|
320
|
+
...m,
|
|
321
|
+
dimension: {
|
|
322
|
+
...meta.resolveMember(m.dimension, 'dimensions'),
|
|
339
323
|
granularities
|
|
340
324
|
},
|
|
341
325
|
index
|
|
342
326
|
}));
|
|
343
327
|
}
|
|
344
|
-
|
|
345
328
|
return (query[type] || []).map((m, index) => ({
|
|
346
329
|
index,
|
|
347
330
|
...meta.resolveMember(m, type)
|
|
348
331
|
}));
|
|
349
332
|
}
|
|
350
|
-
|
|
351
333
|
constructor(props) {
|
|
352
334
|
super(props);
|
|
353
335
|
this.state = {
|
|
@@ -366,12 +348,10 @@ class QueryBuilder extends React.Component {
|
|
|
366
348
|
this.mutexObj = {};
|
|
367
349
|
this.orderMembersOrderKeys = [];
|
|
368
350
|
}
|
|
369
|
-
|
|
370
351
|
async componentDidMount() {
|
|
371
352
|
this.prevContext = this.context;
|
|
372
353
|
await this.fetchMeta();
|
|
373
354
|
}
|
|
374
|
-
|
|
375
355
|
async componentDidUpdate(prevProps) {
|
|
376
356
|
const {
|
|
377
357
|
schemaVersion,
|
|
@@ -380,16 +360,13 @@ class QueryBuilder extends React.Component {
|
|
|
380
360
|
const {
|
|
381
361
|
meta
|
|
382
362
|
} = this.state;
|
|
383
|
-
|
|
384
363
|
if (this.prevContext?.cubeApi !== this.context?.cubeApi) {
|
|
385
364
|
this.prevContext = this.context;
|
|
386
365
|
await this.fetchMeta();
|
|
387
366
|
}
|
|
388
|
-
|
|
389
367
|
if (prevProps.schemaVersion !== schemaVersion) {
|
|
390
368
|
try {
|
|
391
369
|
const newMeta = await this.cubeApi().meta();
|
|
392
|
-
|
|
393
370
|
if (!equals(newMeta, meta) && typeof onSchemaChange === 'function') {
|
|
394
371
|
onSchemaChange({
|
|
395
372
|
schemaVersion,
|
|
@@ -406,17 +383,14 @@ class QueryBuilder extends React.Component {
|
|
|
406
383
|
}
|
|
407
384
|
}
|
|
408
385
|
}
|
|
409
|
-
|
|
410
386
|
fetchMeta = async () => {
|
|
411
387
|
if (!this.cubeApi()) {
|
|
412
388
|
return;
|
|
413
389
|
}
|
|
414
|
-
|
|
415
390
|
let meta;
|
|
416
391
|
let metaError = null;
|
|
417
392
|
let richMetaError = null;
|
|
418
393
|
let metaErrorStack = null;
|
|
419
|
-
|
|
420
394
|
try {
|
|
421
395
|
this.setState({
|
|
422
396
|
isFetchingMeta: true
|
|
@@ -427,7 +401,6 @@ class QueryBuilder extends React.Component {
|
|
|
427
401
|
richMetaError = error;
|
|
428
402
|
metaErrorStack = error.response?.stack?.replace(error.message || '', '') || '';
|
|
429
403
|
}
|
|
430
|
-
|
|
431
404
|
this.setState({
|
|
432
405
|
meta,
|
|
433
406
|
metaError: metaError ? new Error(metaError.message || metaError.toString()) : null,
|
|
@@ -440,41 +413,33 @@ class QueryBuilder extends React.Component {
|
|
|
440
413
|
this.updateQuery({});
|
|
441
414
|
});
|
|
442
415
|
};
|
|
443
|
-
|
|
444
416
|
cubeApi() {
|
|
445
417
|
const {
|
|
446
418
|
cubeApi
|
|
447
|
-
} = this.props;
|
|
448
|
-
|
|
419
|
+
} = this.props;
|
|
420
|
+
// eslint-disable-next-line react/destructuring-assignment
|
|
449
421
|
return cubeApi || this.context && this.context.cubeApi;
|
|
450
422
|
}
|
|
451
|
-
|
|
452
423
|
getMissingMembers(query, meta) {
|
|
453
424
|
if (!meta) {
|
|
454
425
|
return [];
|
|
455
426
|
}
|
|
456
|
-
|
|
457
427
|
return getQueryMembers(query).map(member => {
|
|
458
428
|
const resolvedMember = meta.resolveMember(member, ['measures', 'dimensions', 'segments']);
|
|
459
|
-
|
|
460
429
|
if (resolvedMember.error) {
|
|
461
430
|
return member;
|
|
462
431
|
}
|
|
463
|
-
|
|
464
432
|
return false;
|
|
465
433
|
}).filter(Boolean);
|
|
466
434
|
}
|
|
467
|
-
|
|
468
435
|
isQueryPresent() {
|
|
469
436
|
const {
|
|
470
437
|
query
|
|
471
438
|
} = this.state;
|
|
472
439
|
return QueryRenderer.isQueryPresent(query);
|
|
473
440
|
}
|
|
474
|
-
|
|
475
441
|
prepareRenderProps(queryRendererProps) {
|
|
476
442
|
const getName = member => member.name;
|
|
477
|
-
|
|
478
443
|
const toTimeDimension = member => {
|
|
479
444
|
const rangeSelection = member.compareDateRange ? {
|
|
480
445
|
compareDateRange: member.compareDateRange
|
|
@@ -487,7 +452,6 @@ class QueryBuilder extends React.Component {
|
|
|
487
452
|
...rangeSelection
|
|
488
453
|
});
|
|
489
454
|
};
|
|
490
|
-
|
|
491
455
|
const toFilter = member => ({
|
|
492
456
|
member: member.member?.name || member.dimension?.name,
|
|
493
457
|
operator: member.operator,
|
|
@@ -495,7 +459,6 @@ class QueryBuilder extends React.Component {
|
|
|
495
459
|
values: member.values
|
|
496
460
|
})
|
|
497
461
|
});
|
|
498
|
-
|
|
499
462
|
const updateMethods = (memberType, toQuery = getName) => ({
|
|
500
463
|
add: member => {
|
|
501
464
|
const {
|
|
@@ -524,7 +487,6 @@ class QueryBuilder extends React.Component {
|
|
|
524
487
|
});
|
|
525
488
|
}
|
|
526
489
|
});
|
|
527
|
-
|
|
528
490
|
const {
|
|
529
491
|
meta,
|
|
530
492
|
metaError,
|
|
@@ -539,10 +501,12 @@ class QueryBuilder extends React.Component {
|
|
|
539
501
|
dryRunResponse,
|
|
540
502
|
metaErrorStack
|
|
541
503
|
} = this.state;
|
|
542
|
-
const flatFilters = uniqBy(filter => `${prop('member', filter)}${prop('operator', filter)}`, flattenFilters(meta && query.filters || []).map(filter => ({
|
|
504
|
+
const flatFilters = uniqBy(filter => `${prop('member', filter)}${prop('operator', filter)}`, flattenFilters(meta && query.filters || []).map(filter => ({
|
|
505
|
+
...filter,
|
|
543
506
|
member: filter.member || filter.dimension
|
|
544
507
|
})));
|
|
545
|
-
const filters = flatFilters.map((m, i) => ({
|
|
508
|
+
const filters = flatFilters.map((m, i) => ({
|
|
509
|
+
...m,
|
|
546
510
|
dimension: meta.resolveMember(m.member || m.dimension, ['dimensions', 'measures']),
|
|
547
511
|
operators: meta.filterOperatorsForMember(m.member || m.dimension, ['dimensions', 'measures']),
|
|
548
512
|
index: i
|
|
@@ -564,7 +528,6 @@ class QueryBuilder extends React.Component {
|
|
|
564
528
|
segments: [],
|
|
565
529
|
timeDimensions: []
|
|
566
530
|
};
|
|
567
|
-
|
|
568
531
|
if (meta) {
|
|
569
532
|
availableMeasures = meta.membersForQuery(query, 'measures');
|
|
570
533
|
availableDimensions = meta.membersForQuery(query, 'dimensions');
|
|
@@ -574,17 +537,18 @@ class QueryBuilder extends React.Component {
|
|
|
574
537
|
const cubeNames = uniq([...Object.keys(indexedMeasures), ...Object.keys(indexedDimensions)]).sort();
|
|
575
538
|
availableFilterMembers = cubeNames.map(name => {
|
|
576
539
|
const cube = indexedMeasures[name] || indexedDimensions[name];
|
|
577
|
-
return {
|
|
540
|
+
return {
|
|
541
|
+
...cube,
|
|
578
542
|
members: [...indexedMeasures[name]?.members, ...indexedDimensions[name]?.members].sort((a, b) => a.shortTitle > b.shortTitle ? 1 : -1)
|
|
579
543
|
};
|
|
580
544
|
});
|
|
581
545
|
}
|
|
582
|
-
|
|
583
546
|
const activeOrder = Array.isArray(query.order) ? Object.fromEntries(query.order) : query.order;
|
|
584
547
|
const members = [...measures, ...dimensions, ...timeDimensions.map(({
|
|
585
548
|
dimension
|
|
586
549
|
}) => dimension)];
|
|
587
|
-
let orderMembers = uniqBy(prop('id'), [
|
|
550
|
+
let orderMembers = uniqBy(prop('id'), [
|
|
551
|
+
// uniqBy prefers first, so these will only be added if not already in the query
|
|
588
552
|
...members.map(({
|
|
589
553
|
name,
|
|
590
554
|
title
|
|
@@ -593,19 +557,16 @@ class QueryBuilder extends React.Component {
|
|
|
593
557
|
title,
|
|
594
558
|
order: activeOrder?.[name] || 'none'
|
|
595
559
|
}))]);
|
|
596
|
-
|
|
597
560
|
if (this.orderMembersOrderKeys.length !== orderMembers.length) {
|
|
598
561
|
this.orderMembersOrderKeys = orderMembers.map(({
|
|
599
562
|
id
|
|
600
563
|
}) => id);
|
|
601
564
|
}
|
|
602
|
-
|
|
603
565
|
if (this.orderMembersOrderKeys.length) {
|
|
604
566
|
// Preserve order until the members change or manually re-ordered
|
|
605
567
|
// This is needed so that when an order member becomes active, it doesn't jump to the top of the list
|
|
606
568
|
orderMembers = (this.orderMembersOrderKeys || []).map(id => orderMembers.find(member => member.id === id)).filter(Boolean);
|
|
607
569
|
}
|
|
608
|
-
|
|
609
570
|
return {
|
|
610
571
|
meta,
|
|
611
572
|
metaError,
|
|
@@ -641,7 +602,8 @@ class QueryBuilder extends React.Component {
|
|
|
641
602
|
updateOrder: {
|
|
642
603
|
set: (memberId, newOrder = 'asc') => {
|
|
643
604
|
this.updateQuery({
|
|
644
|
-
order: orderMembers.map(orderMember => ({
|
|
605
|
+
order: orderMembers.map(orderMember => ({
|
|
606
|
+
...orderMember,
|
|
645
607
|
order: orderMember.id === memberId ? newOrder : orderMember.order
|
|
646
608
|
})).reduce((acc, {
|
|
647
609
|
id,
|
|
@@ -658,7 +620,6 @@ class QueryBuilder extends React.Component {
|
|
|
658
620
|
if (sourceIndex == null || destinationIndex == null) {
|
|
659
621
|
return;
|
|
660
622
|
}
|
|
661
|
-
|
|
662
623
|
const nextArray = moveItemInArray(orderMembers, sourceIndex, destinationIndex);
|
|
663
624
|
this.orderMembersOrderKeys = nextArray.map(({
|
|
664
625
|
id
|
|
@@ -688,11 +649,13 @@ class QueryBuilder extends React.Component {
|
|
|
688
649
|
limit
|
|
689
650
|
} = config;
|
|
690
651
|
this.updateVizState({
|
|
691
|
-
pivotConfig: {
|
|
652
|
+
pivotConfig: {
|
|
653
|
+
...pivotConfig,
|
|
692
654
|
...config
|
|
693
655
|
},
|
|
694
656
|
...(limit ? {
|
|
695
|
-
query: {
|
|
657
|
+
query: {
|
|
658
|
+
...query,
|
|
696
659
|
limit
|
|
697
660
|
}
|
|
698
661
|
} : null)
|
|
@@ -706,18 +669,17 @@ class QueryBuilder extends React.Component {
|
|
|
706
669
|
...queryRendererProps
|
|
707
670
|
};
|
|
708
671
|
}
|
|
709
|
-
|
|
710
672
|
updateQuery(queryUpdate) {
|
|
711
673
|
const {
|
|
712
674
|
query
|
|
713
675
|
} = this.state;
|
|
714
676
|
this.updateVizState({
|
|
715
|
-
query: removeEmptyQueryFields({
|
|
677
|
+
query: removeEmptyQueryFields({
|
|
678
|
+
...query,
|
|
716
679
|
...queryUpdate
|
|
717
680
|
})
|
|
718
681
|
});
|
|
719
682
|
}
|
|
720
|
-
|
|
721
683
|
async updateVizState(state) {
|
|
722
684
|
const {
|
|
723
685
|
setQuery,
|
|
@@ -730,77 +692,75 @@ class QueryBuilder extends React.Component {
|
|
|
730
692
|
meta
|
|
731
693
|
} = this.state;
|
|
732
694
|
const finalState = this.applyStateChangeHeuristics(state);
|
|
733
|
-
|
|
734
695
|
if (!finalState.query) {
|
|
735
|
-
finalState.query = {
|
|
696
|
+
finalState.query = {
|
|
697
|
+
...stateQuery
|
|
736
698
|
};
|
|
737
699
|
}
|
|
738
|
-
|
|
739
700
|
let vizStateSent = null;
|
|
740
|
-
|
|
741
701
|
const handleVizStateChange = currentState => {
|
|
742
702
|
const {
|
|
743
703
|
onVizStateChanged
|
|
744
704
|
} = this.props;
|
|
745
|
-
|
|
746
705
|
if (onVizStateChanged) {
|
|
747
|
-
const newVizState = pick(['chartType', 'pivotConfig', 'query'], currentState);
|
|
748
|
-
|
|
706
|
+
const newVizState = pick(['chartType', 'pivotConfig', 'query'], currentState);
|
|
707
|
+
// Don't run callbacks more than once unless the viz state has changed since last time
|
|
749
708
|
if (!vizStateSent || !equals(vizStateSent, newVizState)) {
|
|
750
|
-
onVizStateChanged(newVizState);
|
|
751
|
-
|
|
709
|
+
onVizStateChanged(newVizState);
|
|
710
|
+
// use clone to make sure we don't save object references
|
|
752
711
|
vizStateSent = clone(newVizState);
|
|
753
712
|
}
|
|
754
713
|
}
|
|
755
|
-
};
|
|
756
|
-
|
|
714
|
+
};
|
|
757
715
|
|
|
716
|
+
// deprecated, setters replaced by onVizStateChanged
|
|
758
717
|
const runSetters = currentState => {
|
|
759
718
|
if (setVizState) {
|
|
760
719
|
setVizState(pick(['chartType', 'pivotConfig', 'query'], currentState));
|
|
761
720
|
}
|
|
762
|
-
|
|
763
721
|
if (currentState.query && setQuery) {
|
|
764
722
|
setQuery(currentState.query);
|
|
765
723
|
}
|
|
766
724
|
};
|
|
767
|
-
|
|
768
725
|
if (finalState.shouldApplyHeuristicOrder) {
|
|
769
726
|
finalState.query.order = defaultOrder(finalState.query);
|
|
770
727
|
}
|
|
771
|
-
|
|
772
728
|
finalState.pivotConfig = ResultSet.getNormalizedPivotConfig(finalState.query, finalState.pivotConfig !== undefined ? finalState.pivotConfig : statePivotConfig);
|
|
773
729
|
finalState.missingMembers = this.getMissingMembers(finalState.query, meta);
|
|
774
|
-
finalState.chartType = finalState.chartType || state.chartType || chartType;
|
|
730
|
+
finalState.chartType = finalState.chartType || state.chartType || chartType;
|
|
775
731
|
|
|
776
|
-
|
|
732
|
+
// deprecated
|
|
733
|
+
runSetters({
|
|
734
|
+
...state,
|
|
777
735
|
query: finalState.query
|
|
778
|
-
});
|
|
736
|
+
});
|
|
779
737
|
|
|
780
|
-
|
|
738
|
+
// Update optimistically so that UI does not stutter
|
|
739
|
+
this.setState({
|
|
740
|
+
...finalState,
|
|
781
741
|
queryError: null
|
|
782
742
|
});
|
|
783
743
|
handleVizStateChange(finalState);
|
|
784
744
|
const shouldFetchDryRun = !equals(pick(['measures', 'dimensions', 'timeDimensions'], stateQuery), pick(['measures', 'dimensions', 'timeDimensions'], finalState.query));
|
|
785
|
-
|
|
786
745
|
if (shouldFetchDryRun && isQueryPresent(finalState.query) && finalState.missingMembers.length === 0) {
|
|
787
746
|
try {
|
|
788
747
|
const response = await this.cubeApi().dryRun(finalState.query, {
|
|
789
748
|
mutexObj: this.mutexObj
|
|
790
749
|
});
|
|
791
|
-
|
|
792
750
|
if (finalState.shouldApplyHeuristicOrder) {
|
|
793
|
-
finalState.query.order = (response.queryOrder || []).reduce((memo, current) => ({
|
|
751
|
+
finalState.query.order = (response.queryOrder || []).reduce((memo, current) => ({
|
|
752
|
+
...memo,
|
|
794
753
|
...current
|
|
795
754
|
}), {});
|
|
796
755
|
}
|
|
797
|
-
|
|
798
756
|
finalState.pivotConfig = ResultSet.getNormalizedPivotConfig(response.pivotQuery, finalState.pivotConfig);
|
|
799
757
|
finalState.validatedQuery = this.validatedQuery(finalState);
|
|
800
|
-
finalState.dryRunResponse = response;
|
|
758
|
+
finalState.dryRunResponse = response;
|
|
801
759
|
|
|
760
|
+
// deprecated
|
|
802
761
|
if (isQueryPresent(stateQuery)) {
|
|
803
|
-
runSetters({
|
|
762
|
+
runSetters({
|
|
763
|
+
...this.state,
|
|
804
764
|
...finalState
|
|
805
765
|
});
|
|
806
766
|
}
|
|
@@ -811,17 +771,14 @@ class QueryBuilder extends React.Component {
|
|
|
811
771
|
});
|
|
812
772
|
}
|
|
813
773
|
}
|
|
814
|
-
|
|
815
774
|
this.setState(finalState, () => handleVizStateChange(this.state));
|
|
816
775
|
}
|
|
817
|
-
|
|
818
776
|
validatedQuery(state) {
|
|
819
777
|
const {
|
|
820
778
|
query
|
|
821
779
|
} = state || this.state;
|
|
822
780
|
return validateQuery(query);
|
|
823
781
|
}
|
|
824
|
-
|
|
825
782
|
defaultHeuristics(newState) {
|
|
826
783
|
const {
|
|
827
784
|
query,
|
|
@@ -833,20 +790,16 @@ class QueryBuilder extends React.Component {
|
|
|
833
790
|
sessionGranularity: sessionGranularity || 'day'
|
|
834
791
|
});
|
|
835
792
|
}
|
|
836
|
-
|
|
837
793
|
applyStateChangeHeuristics(newState) {
|
|
838
794
|
const {
|
|
839
795
|
stateChangeHeuristics,
|
|
840
796
|
disableHeuristics
|
|
841
797
|
} = this.props;
|
|
842
|
-
|
|
843
798
|
if (disableHeuristics) {
|
|
844
799
|
return newState;
|
|
845
800
|
}
|
|
846
|
-
|
|
847
801
|
return stateChangeHeuristics && stateChangeHeuristics(this.state, newState) || this.defaultHeuristics(newState);
|
|
848
802
|
}
|
|
849
|
-
|
|
850
803
|
render() {
|
|
851
804
|
const {
|
|
852
805
|
query
|
|
@@ -856,7 +809,6 @@ class QueryBuilder extends React.Component {
|
|
|
856
809
|
render,
|
|
857
810
|
wrapWithQueryRenderer
|
|
858
811
|
} = this.props;
|
|
859
|
-
|
|
860
812
|
if (wrapWithQueryRenderer) {
|
|
861
813
|
return /*#__PURE__*/React.createElement(QueryRenderer, {
|
|
862
814
|
query: query,
|
|
@@ -866,7 +818,6 @@ class QueryBuilder extends React.Component {
|
|
|
866
818
|
if (render) {
|
|
867
819
|
return render(this.prepareRenderProps(queryRendererProps));
|
|
868
820
|
}
|
|
869
|
-
|
|
870
821
|
return null;
|
|
871
822
|
}
|
|
872
823
|
});
|
|
@@ -874,11 +825,9 @@ class QueryBuilder extends React.Component {
|
|
|
874
825
|
if (render) {
|
|
875
826
|
return render(this.prepareRenderProps());
|
|
876
827
|
}
|
|
877
|
-
|
|
878
828
|
return null;
|
|
879
829
|
}
|
|
880
830
|
}
|
|
881
|
-
|
|
882
831
|
}
|
|
883
832
|
|
|
884
833
|
function CubeProvider({
|
|
@@ -896,11 +845,9 @@ function CubeProvider({
|
|
|
896
845
|
|
|
897
846
|
function useDeepCompareMemoize(value) {
|
|
898
847
|
const ref = useRef([]);
|
|
899
|
-
|
|
900
848
|
if (!equals(value, ref.current)) {
|
|
901
849
|
ref.current = value;
|
|
902
850
|
}
|
|
903
|
-
|
|
904
851
|
return ref.current;
|
|
905
852
|
}
|
|
906
853
|
|
|
@@ -927,12 +874,10 @@ function useCubeFetch(method, options = {}) {
|
|
|
927
874
|
const {
|
|
928
875
|
skip = false
|
|
929
876
|
} = options;
|
|
930
|
-
|
|
931
877
|
async function load(loadOptions = {}, ignoreSkip = false) {
|
|
932
878
|
const cubeApi = options.cubeApi || context?.cubeApi;
|
|
933
879
|
const query = loadOptions.query || options.query;
|
|
934
880
|
const queryCondition = method === 'meta' ? true : query && isQueryPresent(query);
|
|
935
|
-
|
|
936
881
|
if (cubeApi && (ignoreSkip || !skip) && queryCondition) {
|
|
937
882
|
setError(null);
|
|
938
883
|
setResponse({
|
|
@@ -944,10 +889,8 @@ function useCubeFetch(method, options = {}) {
|
|
|
944
889
|
mutexKey: method
|
|
945
890
|
};
|
|
946
891
|
const args = method === 'meta' ? [coreOptions] : [query, coreOptions];
|
|
947
|
-
|
|
948
892
|
try {
|
|
949
893
|
const response = await cubeApi[method](...args);
|
|
950
|
-
|
|
951
894
|
if (isMounted()) {
|
|
952
895
|
setResponse({
|
|
953
896
|
response,
|
|
@@ -965,24 +908,26 @@ function useCubeFetch(method, options = {}) {
|
|
|
965
908
|
}
|
|
966
909
|
}
|
|
967
910
|
}
|
|
968
|
-
|
|
969
911
|
useEffect(() => {
|
|
970
912
|
load();
|
|
971
913
|
}, useDeepCompareMemoize([Object.keys(options.query?.order || {}), options, context]));
|
|
972
|
-
return {
|
|
914
|
+
return {
|
|
915
|
+
...response,
|
|
973
916
|
error,
|
|
974
917
|
refetch: options => load(options, true)
|
|
975
918
|
};
|
|
976
919
|
}
|
|
977
920
|
|
|
978
921
|
function useCubeSql(query, options = {}) {
|
|
979
|
-
return useCubeFetch('sql', {
|
|
922
|
+
return useCubeFetch('sql', {
|
|
923
|
+
...options,
|
|
980
924
|
query
|
|
981
925
|
});
|
|
982
926
|
}
|
|
983
927
|
|
|
984
928
|
function useDryRun(query, options = {}) {
|
|
985
|
-
return useCubeFetch('dryRun', {
|
|
929
|
+
return useCubeFetch('dryRun', {
|
|
930
|
+
...options,
|
|
986
931
|
query
|
|
987
932
|
});
|
|
988
933
|
}
|
|
@@ -991,7 +936,8 @@ function useLazyDryRun(query, options = {}) {
|
|
|
991
936
|
const {
|
|
992
937
|
refetch,
|
|
993
938
|
...result
|
|
994
|
-
} = useCubeFetch('dryRun', {
|
|
939
|
+
} = useCubeFetch('dryRun', {
|
|
940
|
+
...options,
|
|
995
941
|
query,
|
|
996
942
|
skip: true
|
|
997
943
|
});
|
|
@@ -1008,28 +954,22 @@ function useCubeQuery(query, options = {}) {
|
|
|
1008
954
|
const [error, setError] = useState(null);
|
|
1009
955
|
const context = useContext(CubeContext);
|
|
1010
956
|
let subscribeRequest = null;
|
|
1011
|
-
|
|
1012
957
|
const progressCallback = ({
|
|
1013
958
|
progressResponse
|
|
1014
959
|
}) => setProgress(progressResponse);
|
|
1015
|
-
|
|
1016
960
|
async function fetch() {
|
|
1017
961
|
const {
|
|
1018
962
|
resetResultSetOnChange
|
|
1019
963
|
} = options;
|
|
1020
964
|
const cubeApi = options.cubeApi || context?.cubeApi;
|
|
1021
|
-
|
|
1022
965
|
if (!cubeApi) {
|
|
1023
966
|
throw new Error('Cube API client is not provided');
|
|
1024
967
|
}
|
|
1025
|
-
|
|
1026
968
|
if (resetResultSetOnChange) {
|
|
1027
969
|
setResultSet(null);
|
|
1028
970
|
}
|
|
1029
|
-
|
|
1030
971
|
setError(null);
|
|
1031
972
|
setLoading(true);
|
|
1032
|
-
|
|
1033
973
|
try {
|
|
1034
974
|
const response = await cubeApi.load(query, {
|
|
1035
975
|
mutexObj: mutexRef.current,
|
|
@@ -1037,7 +977,6 @@ function useCubeQuery(query, options = {}) {
|
|
|
1037
977
|
progressCallback,
|
|
1038
978
|
castNumerics: Boolean(typeof options.castNumerics === 'boolean' ? options.castNumerics : context?.options?.castNumerics)
|
|
1039
979
|
});
|
|
1040
|
-
|
|
1041
980
|
if (isMounted()) {
|
|
1042
981
|
setResultSet(response);
|
|
1043
982
|
setProgress(null);
|
|
@@ -1049,42 +988,34 @@ function useCubeQuery(query, options = {}) {
|
|
|
1049
988
|
setProgress(null);
|
|
1050
989
|
}
|
|
1051
990
|
}
|
|
1052
|
-
|
|
1053
991
|
if (isMounted()) {
|
|
1054
992
|
setLoading(false);
|
|
1055
993
|
}
|
|
1056
994
|
}
|
|
1057
|
-
|
|
1058
995
|
useEffect(() => {
|
|
1059
996
|
const {
|
|
1060
997
|
skip = false,
|
|
1061
998
|
resetResultSetOnChange
|
|
1062
999
|
} = options;
|
|
1063
1000
|
const cubeApi = options.cubeApi || context?.cubeApi;
|
|
1064
|
-
|
|
1065
1001
|
if (!cubeApi) {
|
|
1066
1002
|
throw new Error('Cube API client is not provided');
|
|
1067
1003
|
}
|
|
1068
|
-
|
|
1069
1004
|
async function loadQuery() {
|
|
1070
1005
|
if (!skip && isQueryPresent(query)) {
|
|
1071
1006
|
if (!areQueriesEqual(currentQuery, query)) {
|
|
1072
1007
|
if (resetResultSetOnChange == null || resetResultSetOnChange) {
|
|
1073
1008
|
setResultSet(null);
|
|
1074
1009
|
}
|
|
1075
|
-
|
|
1076
1010
|
setCurrentQuery(query);
|
|
1077
1011
|
}
|
|
1078
|
-
|
|
1079
1012
|
setError(null);
|
|
1080
1013
|
setLoading(true);
|
|
1081
|
-
|
|
1082
1014
|
try {
|
|
1083
1015
|
if (subscribeRequest) {
|
|
1084
1016
|
await subscribeRequest.unsubscribe();
|
|
1085
1017
|
subscribeRequest = null;
|
|
1086
1018
|
}
|
|
1087
|
-
|
|
1088
1019
|
if (options.subscribe) {
|
|
1089
1020
|
subscribeRequest = cubeApi.subscribe(query, {
|
|
1090
1021
|
mutexObj: mutexRef.current,
|
|
@@ -1097,7 +1028,6 @@ function useCubeQuery(query, options = {}) {
|
|
|
1097
1028
|
} else {
|
|
1098
1029
|
setResultSet(result);
|
|
1099
1030
|
}
|
|
1100
|
-
|
|
1101
1031
|
setLoading(false);
|
|
1102
1032
|
setProgress(null);
|
|
1103
1033
|
}
|
|
@@ -1115,7 +1045,6 @@ function useCubeQuery(query, options = {}) {
|
|
|
1115
1045
|
}
|
|
1116
1046
|
}
|
|
1117
1047
|
}
|
|
1118
|
-
|
|
1119
1048
|
loadQuery();
|
|
1120
1049
|
return () => {
|
|
1121
1050
|
if (subscribeRequest) {
|