@cubejs-client/core 1.3.15 → 1.3.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/{cubejs-client-core.js → cubejs-client-core.cjs.js} +1016 -411
  2. package/dist/cubejs-client-core.cjs.js.map +1 -0
  3. package/dist/cubejs-client-core.umd.js +2901 -12088
  4. package/dist/cubejs-client-core.umd.js.map +1 -1
  5. package/dist/src/HttpTransport.d.ts +54 -0
  6. package/dist/src/HttpTransport.d.ts.map +1 -0
  7. package/dist/src/HttpTransport.js +55 -0
  8. package/dist/src/Meta.d.ts +62 -0
  9. package/dist/src/Meta.d.ts.map +1 -0
  10. package/dist/src/Meta.js +150 -0
  11. package/dist/src/ProgressResult.d.ts +8 -0
  12. package/dist/src/ProgressResult.d.ts.map +1 -0
  13. package/dist/src/ProgressResult.js +11 -0
  14. package/dist/src/RequestError.d.ts +6 -0
  15. package/dist/src/RequestError.d.ts.map +1 -0
  16. package/dist/src/RequestError.js +7 -0
  17. package/dist/src/ResultSet.d.ts +430 -0
  18. package/dist/src/ResultSet.d.ts.map +1 -0
  19. package/dist/src/ResultSet.js +952 -0
  20. package/dist/src/SqlQuery.d.ts +17 -0
  21. package/dist/src/SqlQuery.d.ts.map +1 -0
  22. package/dist/src/SqlQuery.js +11 -0
  23. package/dist/src/index.d.ts +194 -0
  24. package/dist/src/index.d.ts.map +1 -0
  25. package/dist/src/index.js +411 -0
  26. package/dist/src/index.umd.d.ts +3 -0
  27. package/dist/src/index.umd.d.ts.map +1 -0
  28. package/dist/src/index.umd.js +6 -0
  29. package/dist/src/time.d.ts +70 -0
  30. package/dist/src/time.d.ts.map +1 -0
  31. package/dist/src/time.js +249 -0
  32. package/dist/src/types.d.ts +424 -0
  33. package/dist/src/types.d.ts.map +1 -0
  34. package/dist/src/types.js +1 -0
  35. package/dist/src/utils.d.ts +19 -0
  36. package/dist/src/utils.d.ts.map +1 -0
  37. package/dist/src/utils.js +294 -0
  38. package/dist/test/CubeApi.test.d.ts +7 -0
  39. package/dist/test/CubeApi.test.d.ts.map +1 -0
  40. package/dist/test/CubeApi.test.js +279 -0
  41. package/dist/test/HttpTransport.test.d.ts +2 -0
  42. package/dist/test/HttpTransport.test.d.ts.map +1 -0
  43. package/dist/test/HttpTransport.test.js +244 -0
  44. package/dist/test/ResultSet.test.d.ts +7 -0
  45. package/dist/test/ResultSet.test.d.ts.map +1 -0
  46. package/dist/test/ResultSet.test.js +1725 -0
  47. package/dist/test/compare-date-range.test.d.ts +2 -0
  48. package/dist/test/compare-date-range.test.d.ts.map +1 -0
  49. package/dist/test/compare-date-range.test.js +742 -0
  50. package/dist/test/data-blending.test.d.ts +2 -0
  51. package/dist/test/data-blending.test.d.ts.map +1 -0
  52. package/dist/test/data-blending.test.js +423 -0
  53. package/dist/test/default-heuristics.test.d.ts +2 -0
  54. package/dist/test/default-heuristics.test.d.ts.map +1 -0
  55. package/dist/test/default-heuristics.test.js +108 -0
  56. package/dist/test/drill-down.test.d.ts +2 -0
  57. package/dist/test/drill-down.test.d.ts.map +1 -0
  58. package/dist/test/drill-down.test.js +373 -0
  59. package/dist/test/fixtures/datablending/load-responses.json +261 -0
  60. package/dist/test/granularity.test.d.ts +2 -0
  61. package/dist/test/granularity.test.d.ts.map +1 -0
  62. package/dist/test/granularity.test.js +218 -0
  63. package/dist/test/helpers.d.ts +283 -0
  64. package/dist/test/helpers.d.ts.map +1 -0
  65. package/dist/test/helpers.js +974 -0
  66. package/dist/test/index.test.d.ts +7 -0
  67. package/dist/test/index.test.d.ts.map +1 -0
  68. package/dist/test/index.test.js +370 -0
  69. package/dist/test/table.test.d.ts +2 -0
  70. package/dist/test/table.test.d.ts.map +1 -0
  71. package/dist/test/table.test.js +757 -0
  72. package/dist/test/utils.test.d.ts +2 -0
  73. package/dist/test/utils.test.d.ts.map +1 -0
  74. package/dist/test/utils.test.js +32 -0
  75. package/package.json +26 -21
  76. package/dist/cubejs-client-core.esm.js +0 -1639
  77. package/dist/cubejs-client-core.esm.js.map +0 -1
  78. package/dist/cubejs-client-core.js.map +0 -1
  79. package/index.d.ts +0 -1338
  80. package/src/HttpTransport.js +0 -60
  81. package/src/HttpTransport.test.js +0 -117
  82. package/src/Meta.js +0 -142
  83. package/src/ProgressResult.js +0 -13
  84. package/src/RequestError.js +0 -7
  85. package/src/ResultSet.js +0 -746
  86. package/src/SqlQuery.js +0 -13
  87. package/src/index.js +0 -398
  88. package/src/index.test.js +0 -454
  89. package/src/index.umd.js +0 -8
  90. package/src/tests/ResultSet.test.js +0 -1655
  91. package/src/tests/compare-date-range.test.js +0 -753
  92. package/src/tests/data-blending.test.js +0 -432
  93. package/src/tests/default-heuristics.test.js +0 -118
  94. package/src/tests/drill-down.test.js +0 -402
  95. package/src/tests/fixtures/datablending/load-responses.json +0 -261
  96. package/src/tests/granularity.test.js +0 -225
  97. package/src/tests/table.test.js +0 -791
  98. package/src/tests/utils.test.js +0 -35
  99. package/src/time.js +0 -296
  100. package/src/utils.js +0 -368
@@ -1,35 +0,0 @@
1
- import 'jest';
2
-
3
- import { defaultOrder } from '../utils';
4
- import { dayRange, TIME_SERIES } from '../time';
5
-
6
- describe('utils', () => {
7
- test('default order', () => {
8
- const query = {
9
- measures: ['Orders.count'],
10
- timeDimensions: [
11
- {
12
- dimension: 'Orders.createdAt',
13
- granularity: 'day',
14
- },
15
- ],
16
- };
17
- expect(defaultOrder(query)).toStrictEqual({
18
- 'Orders.createdAt': 'asc',
19
- });
20
- });
21
-
22
- test('time series', () => {
23
- const range = dayRange('2021-01-01 00:00:00.000', '2021-01-07 00:00:00.000');
24
-
25
- expect(TIME_SERIES.day(range)).toStrictEqual([
26
- '2021-01-01T00:00:00.000',
27
- '2021-01-02T00:00:00.000',
28
- '2021-01-03T00:00:00.000',
29
- '2021-01-04T00:00:00.000',
30
- '2021-01-05T00:00:00.000',
31
- '2021-01-06T00:00:00.000',
32
- '2021-01-07T00:00:00.000',
33
- ]);
34
- });
35
- });
package/src/time.js DELETED
@@ -1,296 +0,0 @@
1
- import dayjs from 'dayjs';
2
- import quarterOfYear from 'dayjs/plugin/quarterOfYear';
3
- import duration from 'dayjs/plugin/duration';
4
- import isoWeek from 'dayjs/plugin/isoWeek';
5
- import en from 'dayjs/locale/en';
6
-
7
- dayjs.extend(quarterOfYear);
8
- dayjs.extend(duration);
9
- dayjs.extend(isoWeek);
10
-
11
- export const GRANULARITIES = [
12
- { name: undefined, title: 'w/o grouping' },
13
- { name: 'second', title: 'Second' },
14
- { name: 'minute', title: 'Minute' },
15
- { name: 'hour', title: 'Hour' },
16
- { name: 'day', title: 'Day' },
17
- { name: 'week', title: 'Week' },
18
- { name: 'month', title: 'Month' },
19
- { name: 'quarter', title: 'Quarter' },
20
- { name: 'year', title: 'Year' },
21
- ];
22
-
23
- export const DEFAULT_GRANULARITY = 'day';
24
-
25
- // When granularity is week, weekStart Value must be 1. However, since the client can change it globally
26
- // (https://day.js.org/docs/en/i18n/changing-locale) So the function below has been added.
27
- export const internalDayjs = (...args) => dayjs(...args).locale({ ...en, weekStart: 1 });
28
-
29
- export const TIME_SERIES = {
30
- day: (range) => range.by('d').map(d => d.format('YYYY-MM-DDT00:00:00.000')),
31
- month: (range) => range.snapTo('month').by('M').map(d => d.format('YYYY-MM-01T00:00:00.000')),
32
- year: (range) => range.snapTo('year').by('y').map(d => d.format('YYYY-01-01T00:00:00.000')),
33
- hour: (range) => range.by('h').map(d => d.format('YYYY-MM-DDTHH:00:00.000')),
34
- minute: (range) => range.by('m').map(d => d.format('YYYY-MM-DDTHH:mm:00.000')),
35
- second: (range) => range.by('s').map(d => d.format('YYYY-MM-DDTHH:mm:ss.000')),
36
- week: (range) => range.snapTo('week').by('w').map(d => d.startOf('week').format('YYYY-MM-DDT00:00:00.000')),
37
- quarter: (range) => range.snapTo('quarter').by('quarter').map(d => d.startOf('quarter').format(
38
- 'YYYY-MM-DDT00:00:00.000'
39
- )),
40
- };
41
-
42
- export const isPredefinedGranularity = (granularity) => !!TIME_SERIES[granularity];
43
-
44
- export const DateRegex = /^\d\d\d\d-\d\d-\d\d$/;
45
- export const LocalDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z?$/;
46
-
47
- export const dayRange = (from, to) => ({
48
- by: (value) => {
49
- const results = [];
50
-
51
- let start = internalDayjs(from);
52
- const end = internalDayjs(to);
53
-
54
- while (start.isBefore(end) || start.isSame(end)) {
55
- results.push(start);
56
- start = start.add(1, value);
57
- }
58
-
59
- return results;
60
- },
61
- snapTo: (value) => dayRange(internalDayjs(from).startOf(value), internalDayjs(to).endOf(value)),
62
- start: internalDayjs(from),
63
- end: internalDayjs(to),
64
- });
65
-
66
- /**
67
- * Parse PostgreSQL-like interval string into object
68
- * E.g. '2 years 15 months 100 weeks 99 hours 15 seconds'
69
- * Negative units are also supported
70
- * E.g. '-2 months 5 days -10 hours'
71
- *
72
- * TODO: It's copy/paste of parseSqlInterval from @cubejs-backend/shared [time.ts]
73
- * It's not referenced to omit imports of moment.js staff.
74
- * Probably one day we should choose one implementation and reuse it in other places.
75
- */
76
- export function parseSqlInterval(intervalStr) {
77
- const interval = {};
78
- const parts = intervalStr.split(/\s+/);
79
-
80
- for (let i = 0; i < parts.length; i += 2) {
81
- const value = parseInt(parts[i], 10);
82
- const unit = parts[i + 1];
83
-
84
- // Remove ending 's' (e.g., 'days' -> 'day')
85
- const singularUnit = unit.endsWith('s') ? unit.slice(0, -1) : unit;
86
- interval[singularUnit] = value;
87
- }
88
-
89
- return interval;
90
- }
91
-
92
- /**
93
- * Adds interval to provided date.
94
- * TODO: It's copy/paste of addInterval from @cubejs-backend/shared [time.ts]
95
- * but operates with dayjs instead of moment.js
96
- * @param {dayjs} date
97
- * @param interval
98
- * @returns {dayjs}
99
- */
100
- export function addInterval(date, interval) {
101
- let res = date.clone();
102
-
103
- Object.entries(interval).forEach(([key, value]) => {
104
- res = res.add(value, key);
105
- });
106
-
107
- return res;
108
- }
109
-
110
- /**
111
- * Adds interval to provided date.
112
- * TODO: It's copy/paste of subtractInterval from @cubejs-backend/shared [time.ts]
113
- * but operates with dayjs instead of moment.js
114
- * @param {dayjs} date
115
- * @param interval
116
- * @returns {dayjs}
117
- */
118
- export function subtractInterval(date, interval) {
119
- let res = date.clone();
120
-
121
- Object.entries(interval).forEach(([key, value]) => {
122
- res = res.subtract(value, key);
123
- });
124
-
125
- return res;
126
- }
127
-
128
- /**
129
- * Returns the closest date prior to date parameter aligned with the origin point
130
- * TODO: It's copy/paste of alignToOrigin from @cubejs-backend/shared [time.ts]
131
- * but operates with dayjs instead of moment.js
132
- */
133
- function alignToOrigin(startDate, interval, origin) {
134
- let alignedDate = startDate.clone();
135
- let intervalOp;
136
- let isIntervalNegative = false;
137
-
138
- let offsetDate = addInterval(origin, interval);
139
-
140
- // The easiest way to check the interval sign
141
- if (offsetDate.isBefore(origin)) {
142
- isIntervalNegative = true;
143
- }
144
-
145
- offsetDate = origin.clone();
146
-
147
- if (startDate.isBefore(origin)) {
148
- intervalOp = isIntervalNegative ? addInterval : subtractInterval;
149
-
150
- while (offsetDate.isAfter(startDate)) {
151
- offsetDate = intervalOp(offsetDate, interval);
152
- }
153
- alignedDate = offsetDate;
154
- } else {
155
- intervalOp = isIntervalNegative ? subtractInterval : addInterval;
156
-
157
- while (offsetDate.isBefore(startDate)) {
158
- alignedDate = offsetDate.clone();
159
- offsetDate = intervalOp(offsetDate, interval);
160
- }
161
-
162
- if (offsetDate.isSame(startDate)) {
163
- alignedDate = offsetDate;
164
- }
165
- }
166
-
167
- return alignedDate;
168
- }
169
-
170
- /**
171
- * Returns the time series points for the custom interval
172
- * TODO: It's almost a copy/paste of timeSeriesFromCustomInterval from
173
- * @cubejs-backend/shared [time.ts] but operates with dayjs instead of moment.js
174
- */
175
- export const timeSeriesFromCustomInterval = (from, to, granularity) => {
176
- const intervalParsed = parseSqlInterval(granularity.interval);
177
- const start = internalDayjs(from);
178
- const end = internalDayjs(to);
179
- let origin = granularity.origin ? internalDayjs(granularity.origin) : internalDayjs().startOf('year');
180
- if (granularity.offset) {
181
- origin = addInterval(origin, parseSqlInterval(granularity.offset));
182
- }
183
- let alignedStart = alignToOrigin(start, intervalParsed, origin);
184
-
185
- const dates = [];
186
-
187
- while (alignedStart.isBefore(end) || alignedStart.isSame(end)) {
188
- dates.push(alignedStart.format('YYYY-MM-DDTHH:mm:ss.000'));
189
- alignedStart = addInterval(alignedStart, intervalParsed);
190
- }
191
-
192
- return dates;
193
- };
194
-
195
- /**
196
- * Returns the lowest time unit for the interval
197
- * @protected
198
- * @param {string} interval
199
- * @returns {string}
200
- */
201
- export const diffTimeUnitForInterval = (interval) => {
202
- if (/second/i.test(interval)) {
203
- return 'second';
204
- } else if (/minute/i.test(interval)) {
205
- return 'minute';
206
- } else if (/hour/i.test(interval)) {
207
- return 'hour';
208
- } else if (/day/i.test(interval)) {
209
- return 'day';
210
- } else if (/week/i.test(interval)) {
211
- return 'day';
212
- } else if (/month/i.test(interval)) {
213
- return 'month';
214
- } else if (/quarter/i.test(interval)) {
215
- return 'month';
216
- } else /* if (/year/i.test(interval)) */ {
217
- return 'year';
218
- }
219
- };
220
-
221
- const granularityOrder = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second'];
222
-
223
- export const minGranularityForIntervals = (i1, i2) => {
224
- const g1 = diffTimeUnitForInterval(i1);
225
- const g2 = diffTimeUnitForInterval(i2);
226
- const g1pos = granularityOrder.indexOf(g1);
227
- const g2pos = granularityOrder.indexOf(g2);
228
-
229
- if (g1pos > g2pos) {
230
- return g1;
231
- }
232
-
233
- return g2;
234
- };
235
-
236
- export const granularityFor = (dateStr) => {
237
- const dayjsDate = internalDayjs(dateStr);
238
- const month = dayjsDate.month();
239
- const date = dayjsDate.date();
240
- const hours = dayjsDate.hour();
241
- const minutes = dayjsDate.minute();
242
- const seconds = dayjsDate.second();
243
- const milliseconds = dayjsDate.millisecond();
244
- const weekDay = dayjsDate.isoWeekday();
245
-
246
- if (
247
- month === 0 &&
248
- date === 1 &&
249
- hours === 0 &&
250
- minutes === 0 &&
251
- seconds === 0 &&
252
- milliseconds === 0
253
- ) {
254
- return 'year';
255
- } else if (
256
- date === 1 &&
257
- hours === 0 &&
258
- minutes === 0 &&
259
- seconds === 0 &&
260
- milliseconds === 0
261
- ) {
262
- return 'month';
263
- } else if (
264
- weekDay === 1 &&
265
- hours === 0 &&
266
- minutes === 0 &&
267
- seconds === 0 &&
268
- milliseconds === 0
269
- ) {
270
- return 'week';
271
- } else if (
272
- hours === 0 &&
273
- minutes === 0 &&
274
- seconds === 0 &&
275
- milliseconds === 0
276
- ) {
277
- return 'day';
278
- } else if (
279
- minutes === 0 &&
280
- seconds === 0 &&
281
- milliseconds === 0
282
- ) {
283
- return 'hour';
284
- } else if (
285
- seconds === 0 &&
286
- milliseconds === 0
287
- ) {
288
- return 'minute';
289
- } else if (
290
- milliseconds === 0
291
- ) {
292
- return 'second';
293
- }
294
-
295
- return 'second'; // TODO return 'millisecond';
296
- };
package/src/utils.js DELETED
@@ -1,368 +0,0 @@
1
- import { clone, equals, fromPairs, indexBy, prop, toPairs } from 'ramda';
2
- import { DEFAULT_GRANULARITY } from './time';
3
-
4
- export function removeEmptyQueryFields(_query) {
5
- const query = _query || {};
6
-
7
- return fromPairs(
8
- toPairs(query)
9
- .map(([key, value]) => {
10
- if (
11
- ['measures', 'dimensions', 'segments', 'timeDimensions', 'filters'].includes(key)
12
- ) {
13
- if (Array.isArray(value) && value.length === 0) {
14
- return null;
15
- }
16
- }
17
-
18
- if (key === 'order' && value) {
19
- if (Array.isArray(value) && !value.length) {
20
- return null;
21
- } else if (!Object.keys(value).length) {
22
- return null;
23
- }
24
- }
25
-
26
- return [key, value];
27
- })
28
- .filter(Boolean)
29
- );
30
- }
31
-
32
- export function validateQuery(_query) {
33
- const query = _query || {};
34
-
35
- return removeEmptyQueryFields({
36
- ...query,
37
- filters: (query.filters || []).filter((f) => f.operator),
38
- timeDimensions: (query.timeDimensions || []).filter(
39
- (td) => !(!td.dateRange && !td.granularity)
40
- ),
41
- });
42
- }
43
-
44
- export function areQueriesEqual(query1 = {}, query2 = {}) {
45
- return (
46
- equals(
47
- Object.entries((query1 && query1.order) || {}),
48
- Object.entries((query2 && query2.order) || {})
49
- ) && equals(query1, query2)
50
- );
51
- }
52
-
53
- export function defaultOrder(query) {
54
- const granularity = (query.timeDimensions || []).find((d) => d.granularity);
55
-
56
- if (granularity) {
57
- return {
58
- [granularity.dimension]: 'asc',
59
- };
60
- } else if (
61
- (query.measures || []).length > 0 &&
62
- (query.dimensions || []).length > 0
63
- ) {
64
- return {
65
- [query.measures[0]]: 'desc',
66
- };
67
- } else if ((query.dimensions || []).length > 0) {
68
- return {
69
- [query.dimensions[0]]: 'asc',
70
- };
71
- }
72
-
73
- return {};
74
- }
75
-
76
- export function defaultHeuristics(newState, oldQuery = {}, options) {
77
- const { query, ...props } = clone(newState);
78
- const { meta, sessionGranularity } = options;
79
- const granularity = sessionGranularity || DEFAULT_GRANULARITY;
80
-
81
- let state = {
82
- query,
83
- ...props,
84
- };
85
-
86
- let newQuery = null;
87
- if (!areQueriesEqual(query, oldQuery)) {
88
- newQuery = query;
89
- }
90
-
91
- if (Array.isArray(newQuery) || Array.isArray(oldQuery)) {
92
- return newState;
93
- }
94
-
95
- if (newQuery) {
96
- if (
97
- (oldQuery.timeDimensions || []).length === 1 &&
98
- (newQuery.timeDimensions || []).length === 1 &&
99
- newQuery.timeDimensions[0].granularity &&
100
- oldQuery.timeDimensions[0].granularity !==
101
- newQuery.timeDimensions[0].granularity
102
- ) {
103
- state = {
104
- ...state,
105
- sessionGranularity: newQuery.timeDimensions[0].granularity,
106
- };
107
- }
108
-
109
- if (
110
- ((oldQuery.measures || []).length === 0 &&
111
- (newQuery.measures || []).length > 0) ||
112
- ((oldQuery.measures || []).length === 1 &&
113
- (newQuery.measures || []).length === 1 &&
114
- oldQuery.measures[0] !== newQuery.measures[0])
115
- ) {
116
- const [td] = newQuery.timeDimensions || [];
117
- const defaultTimeDimension = meta.defaultTimeDimensionNameFor(
118
- newQuery.measures[0]
119
- );
120
- newQuery = {
121
- ...newQuery,
122
- timeDimensions: defaultTimeDimension
123
- ? [
124
- {
125
- dimension: defaultTimeDimension,
126
- granularity: (td && td.granularity) || granularity,
127
- dateRange: td && td.dateRange,
128
- },
129
- ]
130
- : [],
131
- };
132
-
133
- return {
134
- ...state,
135
- pivotConfig: null,
136
- shouldApplyHeuristicOrder: true,
137
- query: newQuery,
138
- chartType: defaultTimeDimension ? 'line' : 'number',
139
- };
140
- }
141
-
142
- if (
143
- (oldQuery.dimensions || []).length === 0 &&
144
- (newQuery.dimensions || []).length > 0
145
- ) {
146
- newQuery = {
147
- ...newQuery,
148
- timeDimensions: (newQuery.timeDimensions || []).map((td) => ({
149
- ...td,
150
- granularity: undefined,
151
- })),
152
- };
153
-
154
- return {
155
- ...state,
156
- pivotConfig: null,
157
- shouldApplyHeuristicOrder: true,
158
- query: newQuery,
159
- chartType: 'table',
160
- };
161
- }
162
-
163
- if (
164
- (oldQuery.dimensions || []).length > 0 &&
165
- (newQuery.dimensions || []).length === 0
166
- ) {
167
- newQuery = {
168
- ...newQuery,
169
- timeDimensions: (newQuery.timeDimensions || []).map((td) => ({
170
- ...td,
171
- granularity: td.granularity || granularity,
172
- })),
173
- };
174
-
175
- return {
176
- ...state,
177
- pivotConfig: null,
178
- shouldApplyHeuristicOrder: true,
179
- query: newQuery,
180
- chartType: (newQuery.timeDimensions || []).length ? 'line' : 'number',
181
- };
182
- }
183
-
184
- if (
185
- ((oldQuery.dimensions || []).length > 0 ||
186
- (oldQuery.measures || []).length > 0) &&
187
- (newQuery.dimensions || []).length === 0 &&
188
- (newQuery.measures || []).length === 0
189
- ) {
190
- newQuery = {
191
- ...newQuery,
192
- timeDimensions: [],
193
- filters: [],
194
- };
195
-
196
- return {
197
- ...state,
198
- pivotConfig: null,
199
- shouldApplyHeuristicOrder: true,
200
- query: newQuery,
201
- sessionGranularity: null,
202
- };
203
- }
204
- return state;
205
- }
206
-
207
- if (state.chartType) {
208
- const newChartType = state.chartType;
209
- if (
210
- (newChartType === 'line' || newChartType === 'area') &&
211
- (oldQuery.timeDimensions || []).length === 1 &&
212
- !oldQuery.timeDimensions[0].granularity
213
- ) {
214
- const [td] = oldQuery.timeDimensions;
215
- return {
216
- ...state,
217
- pivotConfig: null,
218
- query: {
219
- ...oldQuery,
220
- timeDimensions: [{ ...td, granularity }],
221
- },
222
- };
223
- }
224
-
225
- if (
226
- (newChartType === 'pie' ||
227
- newChartType === 'table' ||
228
- newChartType === 'number') &&
229
- (oldQuery.timeDimensions || []).length === 1 &&
230
- oldQuery.timeDimensions[0].granularity
231
- ) {
232
- const [td] = oldQuery.timeDimensions;
233
- return {
234
- ...state,
235
- pivotConfig: null,
236
- shouldApplyHeuristicOrder: true,
237
- query: {
238
- ...oldQuery,
239
- timeDimensions: [{ ...td, granularity: undefined }],
240
- },
241
- };
242
- }
243
- }
244
-
245
- return state;
246
- }
247
-
248
- export function isQueryPresent(query) {
249
- if (!query) {
250
- return false;
251
- }
252
-
253
- return (Array.isArray(query) ? query : [query]).every(
254
- (q) => (q.measures && q.measures.length) ||
255
- (q.dimensions && q.dimensions.length) ||
256
- (q.timeDimensions && q.timeDimensions.length)
257
- );
258
- }
259
-
260
- export function movePivotItem(
261
- pivotConfig,
262
- sourceIndex,
263
- destinationIndex,
264
- sourceAxis,
265
- destinationAxis
266
- ) {
267
- const nextPivotConfig = {
268
- ...pivotConfig,
269
- x: [...pivotConfig.x],
270
- y: [...pivotConfig.y],
271
- };
272
- const id = pivotConfig[sourceAxis][sourceIndex];
273
- const lastIndex = nextPivotConfig[destinationAxis].length - 1;
274
-
275
- if (id === 'measures') {
276
- destinationIndex = lastIndex + 1;
277
- } else if (
278
- sourceAxis === destinationAxis &&
279
- destinationIndex >= lastIndex &&
280
- nextPivotConfig[destinationAxis][lastIndex] === 'measures'
281
- ) {
282
- destinationIndex = lastIndex - 1;
283
- } else if (
284
- sourceAxis !== destinationAxis &&
285
- destinationIndex > lastIndex &&
286
- nextPivotConfig[destinationAxis][lastIndex] === 'measures'
287
- ) {
288
- destinationIndex = lastIndex;
289
- }
290
-
291
- nextPivotConfig[sourceAxis].splice(sourceIndex, 1);
292
- nextPivotConfig[destinationAxis].splice(destinationIndex, 0, id);
293
-
294
- return nextPivotConfig;
295
- }
296
-
297
- export function moveItemInArray(list, sourceIndex, destinationIndex) {
298
- const result = [...list];
299
- const [removed] = result.splice(sourceIndex, 1);
300
- result.splice(destinationIndex, 0, removed);
301
-
302
- return result;
303
- }
304
-
305
- export function flattenFilters(filters = []) {
306
- return filters.reduce((memo, filter) => {
307
- if (filter.or || filter.and) {
308
- return [...memo, ...flattenFilters(filter.or || filter.and)];
309
- }
310
-
311
- return [...memo, filter];
312
- }, []);
313
- }
314
-
315
- export function getQueryMembers(query = {}) {
316
- const keys = ['measures', 'dimensions', 'segments'];
317
- const members = new Set();
318
-
319
- keys.forEach((key) => (query[key] || []).forEach((member) => members.add(member)));
320
- (query.timeDimensions || []).forEach((td) => members.add(td.dimension));
321
-
322
- flattenFilters(query.filters).forEach((filter) => members.add(filter.dimension || filter.member));
323
-
324
- return [...members];
325
- }
326
-
327
- export function getOrderMembersFromOrder(orderMembers, order) {
328
- const ids = new Set();
329
- const indexedOrderMembers = indexBy(prop('id'), orderMembers);
330
- const entries = Array.isArray(order) ? order : Object.entries(order || {});
331
- const nextOrderMembers = [];
332
-
333
- entries.forEach(([memberId, currentOrder]) => {
334
- if (currentOrder !== 'none' && indexedOrderMembers[memberId]) {
335
- ids.add(memberId);
336
- nextOrderMembers.push({
337
- ...indexedOrderMembers[memberId],
338
- order: currentOrder,
339
- });
340
- }
341
- });
342
- orderMembers.forEach((member) => {
343
- if (!ids.has(member.id)) {
344
- nextOrderMembers.push({
345
- ...member,
346
- order: member.order || 'none',
347
- });
348
- }
349
- });
350
-
351
- return nextOrderMembers;
352
- }
353
-
354
- export function aliasSeries(values, index, pivotConfig, duplicateMeasures) {
355
- const nonNullValues = values.filter((value) => value != null);
356
-
357
- if (
358
- pivotConfig &&
359
- pivotConfig.aliasSeries &&
360
- pivotConfig.aliasSeries[index]
361
- ) {
362
- return [pivotConfig.aliasSeries[index], ...nonNullValues];
363
- } else if (duplicateMeasures.has(nonNullValues[0])) {
364
- return [index, ...nonNullValues];
365
- }
366
-
367
- return nonNullValues;
368
- }