@visactor/vbi 0.4.17 → 0.4.20
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/builder/adapters/index.d.ts +1 -0
- package/dist/builder/adapters/vquery-vseed/build-vquery.d.ts +3 -0
- package/dist/builder/adapters/vquery-vseed/build-vseed.d.ts +3 -0
- package/dist/builder/adapters/vquery-vseed/index.d.ts +7 -0
- package/dist/builder/adapters/vquery-vseed/types.d.ts +4 -0
- package/dist/builder/{vbi-builder.d.ts → builder.d.ts} +8 -8
- package/dist/builder/features/chart-type/chart-type-builder.d.ts +20 -1
- package/dist/builder/features/chart-type/dimension-encoding.d.ts +4 -0
- package/dist/builder/features/chart-type/measure-encoding.d.ts +4 -0
- package/dist/builder/features/chart-type/reapply-dimension-encodings.d.ts +2 -0
- package/dist/builder/features/chart-type/reapply-measure-encodings.d.ts +2 -0
- package/dist/builder/features/dimensions/dim-builder.d.ts +3 -2
- package/dist/builder/features/dimensions/dim-node-builder.d.ts +32 -1
- package/dist/builder/features/havingFilter/having-builder.d.ts +2 -2
- package/dist/builder/features/havingFilter/having-node-builder.d.ts +10 -1
- package/dist/builder/features/measures/mea-builder.d.ts +3 -2
- package/dist/builder/features/measures/mea-node-builder.d.ts +33 -3
- package/dist/builder/features/whereFilter/where-builder.d.ts +2 -2
- package/dist/builder/features/whereFilter/where-node-builder.d.ts +11 -2
- package/dist/builder/index.d.ts +2 -1
- package/dist/builder/modules/build.d.ts +2 -2
- package/dist/builder/modules/index.d.ts +2 -5
- package/dist/builder/modules/is-empty.d.ts +1 -1
- package/dist/index.cjs +1578 -386
- package/dist/index.d.ts +6 -3
- package/dist/index.js +1567 -384
- package/dist/pipeline/vqueryDSL/aggregateMap.d.ts +50 -0
- package/dist/pipeline/vqueryDSL/buildOrderBy.d.ts +2 -0
- package/dist/pipeline/vqueryDSL/index.d.ts +2 -3
- package/dist/pipeline/vqueryDSL/resolveDatePredicate.d.ts +7 -0
- package/dist/pipeline/vqueryDSL/types.d.ts +6 -6
- package/dist/types/builder/VBIInterface.d.ts +7 -7
- package/dist/types/builder/adapter.d.ts +23 -0
- package/dist/types/builder/build-vseed.d.ts +3 -0
- package/dist/types/builder/context.d.ts +2 -2
- package/dist/types/builder/index.d.ts +4 -2
- package/dist/types/builder/observe.d.ts +2 -1
- package/dist/types/connector/query.d.ts +1 -0
- package/dist/types/dsl/dimensions/aggregate.d.ts +15 -0
- package/dist/types/dsl/dimensions/dimensions.d.ts +62 -0
- package/dist/types/dsl/encoding.d.ts +2 -2
- package/dist/types/dsl/havingFilter/having.d.ts +20 -1
- package/dist/types/dsl/index.d.ts +6 -4
- package/dist/types/dsl/measures/aggregate.d.ts +14 -2
- package/dist/types/dsl/measures/measures.d.ts +177 -8
- package/dist/types/dsl/sort.d.ts +13 -0
- package/dist/types/dsl/vbi/vbi.d.ts +103 -7
- package/dist/types/dsl/whereFilter/date.d.ts +95 -0
- package/dist/types/dsl/whereFilter/filters.d.ts +142 -5
- package/dist/utils/filter-guards.d.ts +2 -2
- package/dist/vbi/create-vbi.d.ts +14 -14
- package/dist/vbi/from/from-vbi-dsl-input.d.ts +4 -3
- package/dist/vbi/from/set-base-dsl-fields.d.ts +2 -2
- package/dist/vbi/generate-empty-dsl.d.ts +2 -2
- package/dist/vbi/normalize/types.d.ts +3 -3
- package/dist/vbi.d.ts +1 -14
- package/package.json +5 -5
- package/dist/builder/modules/build-vquery.d.ts +0 -4
- package/dist/builder/modules/build-vseed.d.ts +0 -8
- package/dist/builder/modules/create-builder-features.d.ts +0 -14
package/dist/index.cjs
CHANGED
|
@@ -27,16 +27,19 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
27
27
|
HavingFilterBuilder: ()=>HavingFilterBuilder,
|
|
28
28
|
WhereFilterBuilder: ()=>WhereFilterBuilder,
|
|
29
29
|
isVBIHavingGroup: ()=>isVBIHavingGroup,
|
|
30
|
-
|
|
30
|
+
resolveVBIChartBuilderAdapters: ()=>resolveVBIChartBuilderAdapters,
|
|
31
31
|
VBI: ()=>VBI,
|
|
32
32
|
isVBIHavingFilter: ()=>isVBIHavingFilter,
|
|
33
|
-
findTreeNodesBy: ()=>vseed_namespaceObject.findTreeNodesBy,
|
|
34
33
|
ThemeBuilder: ()=>ThemeBuilder,
|
|
34
|
+
findTreeNodesBy: ()=>vseed_namespaceObject.findTreeNodesBy,
|
|
35
35
|
id: ()=>id_id,
|
|
36
|
+
createVBI: ()=>createVBI,
|
|
36
37
|
MeasuresBuilder: ()=>MeasuresBuilder,
|
|
37
38
|
LimitBuilder: ()=>LimitBuilder,
|
|
38
39
|
DimensionsBuilder: ()=>DimensionsBuilder,
|
|
39
40
|
ChartTypeBuilder: ()=>ChartTypeBuilder,
|
|
41
|
+
VBIChartBuilder: ()=>VBIChartBuilder,
|
|
42
|
+
defaultVBIChartBuilderAdapters: ()=>defaultVBIChartBuilderAdapters,
|
|
40
43
|
isVBIFilter: ()=>isVBIFilter,
|
|
41
44
|
isVBIWhereGroup: ()=>isVBIWhereGroup,
|
|
42
45
|
preorderTraverse: ()=>vseed_namespaceObject.preorderTraverse,
|
|
@@ -55,229 +58,7 @@ const getConnector = async (id)=>{
|
|
|
55
58
|
return connector;
|
|
56
59
|
};
|
|
57
60
|
const external_yjs_namespaceObject = require("yjs");
|
|
58
|
-
const applyUpdateToDoc = (doc, update, transactionOrigin)=>{
|
|
59
|
-
external_yjs_namespaceObject.applyUpdate(doc, update, transactionOrigin);
|
|
60
|
-
};
|
|
61
|
-
const encodeDocStateAsUpdate = (doc, targetStateVector)=>external_yjs_namespaceObject.encodeStateAsUpdate(doc, targetStateVector);
|
|
62
|
-
const buildVBIDSL = (dsl)=>dsl.toJSON();
|
|
63
61
|
const external_remeda_namespaceObject = require("remeda");
|
|
64
|
-
const buildSelect = (queryDSL, context)=>{
|
|
65
|
-
const { vbiDSL } = context;
|
|
66
|
-
const measures = vbiDSL.measures;
|
|
67
|
-
const dimensions = vbiDSL.dimensions;
|
|
68
|
-
const result = {
|
|
69
|
-
...queryDSL
|
|
70
|
-
};
|
|
71
|
-
const measureNodes = measures.filter((measure)=>MeasuresBuilder.isMeasureNode(measure));
|
|
72
|
-
const measureSelects = measureNodes.map((measure)=>({
|
|
73
|
-
field: measure.field,
|
|
74
|
-
alias: measure.alias,
|
|
75
|
-
aggr: measure.aggregate
|
|
76
|
-
}));
|
|
77
|
-
const dimensionNodes = dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension));
|
|
78
|
-
const dimensionSelects = dimensionNodes.map((dimension)=>({
|
|
79
|
-
field: dimension.field,
|
|
80
|
-
alias: dimension.alias
|
|
81
|
-
}));
|
|
82
|
-
result.select = measureSelects.concat(dimensionSelects);
|
|
83
|
-
return result;
|
|
84
|
-
};
|
|
85
|
-
const buildGroupBy = (queryDSL, context)=>{
|
|
86
|
-
const result = {
|
|
87
|
-
...queryDSL
|
|
88
|
-
};
|
|
89
|
-
const { vbiDSL } = context;
|
|
90
|
-
const dimensions = vbiDSL.dimensions;
|
|
91
|
-
const dimensionNodes = dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension));
|
|
92
|
-
result.groupBy = dimensionNodes.map((dimension)=>dimension.field);
|
|
93
|
-
return result;
|
|
94
|
-
};
|
|
95
|
-
const buildWhere = (queryDSL, context)=>{
|
|
96
|
-
const { vbiDSL } = context;
|
|
97
|
-
const whereFilter = vbiDSL.whereFilter;
|
|
98
|
-
if (!whereFilter || 0 === whereFilter.conditions.length) return queryDSL;
|
|
99
|
-
const result = {
|
|
100
|
-
...queryDSL
|
|
101
|
-
};
|
|
102
|
-
result.where = mapGroupToCondition(whereFilter);
|
|
103
|
-
return result;
|
|
104
|
-
};
|
|
105
|
-
function isWhereGroup(clause) {
|
|
106
|
-
return 'op' in clause && 'conditions' in clause;
|
|
107
|
-
}
|
|
108
|
-
function mapClauseToCondition(clause) {
|
|
109
|
-
if (isWhereGroup(clause)) return [
|
|
110
|
-
mapGroupToCondition(clause)
|
|
111
|
-
];
|
|
112
|
-
return mapFilterToCondition(clause);
|
|
113
|
-
}
|
|
114
|
-
function mapGroupToCondition(group) {
|
|
115
|
-
return {
|
|
116
|
-
op: group.op,
|
|
117
|
-
conditions: group.conditions.flatMap(mapClauseToCondition)
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
function mapFilterToCondition(filter) {
|
|
121
|
-
if ('between' === filter.op || 'not between' === filter.op) return handleBetweenFilter(filter);
|
|
122
|
-
return handleSimpleFilter(filter);
|
|
123
|
-
}
|
|
124
|
-
function handleBetweenFilter(filter) {
|
|
125
|
-
const value = normalizeBetweenValue(filter.value);
|
|
126
|
-
const lowerCondition = void 0 !== value.min && null !== value.min && '' !== value.min ? {
|
|
127
|
-
field: filter.field,
|
|
128
|
-
op: '<' === value.leftOp ? '>' : '>=',
|
|
129
|
-
value: value.min
|
|
130
|
-
} : void 0;
|
|
131
|
-
const upperCondition = void 0 !== value.max && null !== value.max && '' !== value.max ? {
|
|
132
|
-
field: filter.field,
|
|
133
|
-
op: '<' === value.rightOp ? '<' : '<=',
|
|
134
|
-
value: value.max
|
|
135
|
-
} : void 0;
|
|
136
|
-
if ('not between' === filter.op) {
|
|
137
|
-
const outsideConditions = [
|
|
138
|
-
lowerCondition && invertLowerBound(lowerCondition),
|
|
139
|
-
upperCondition && invertUpperBound(upperCondition)
|
|
140
|
-
].filter(Boolean);
|
|
141
|
-
if (outsideConditions.length <= 1) return outsideConditions;
|
|
142
|
-
return [
|
|
143
|
-
{
|
|
144
|
-
op: 'or',
|
|
145
|
-
conditions: outsideConditions
|
|
146
|
-
}
|
|
147
|
-
];
|
|
148
|
-
}
|
|
149
|
-
return [
|
|
150
|
-
lowerCondition,
|
|
151
|
-
upperCondition
|
|
152
|
-
].filter(Boolean);
|
|
153
|
-
}
|
|
154
|
-
function normalizeBetweenValue(value) {
|
|
155
|
-
if (Array.isArray(value)) return {
|
|
156
|
-
min: value[0],
|
|
157
|
-
max: value[1],
|
|
158
|
-
leftOp: '<=',
|
|
159
|
-
rightOp: '<='
|
|
160
|
-
};
|
|
161
|
-
if ('object' == typeof value && null !== value) return value;
|
|
162
|
-
return {};
|
|
163
|
-
}
|
|
164
|
-
function invertLowerBound(condition) {
|
|
165
|
-
return {
|
|
166
|
-
field: condition.field,
|
|
167
|
-
op: '>' === condition.op ? '<=' : '<',
|
|
168
|
-
value: condition.value
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
function invertUpperBound(condition) {
|
|
172
|
-
return {
|
|
173
|
-
field: condition.field,
|
|
174
|
-
op: '<' === condition.op ? '>=' : '>',
|
|
175
|
-
value: condition.value
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
function handleSimpleFilter(filter) {
|
|
179
|
-
let mappedOp = filter.op ?? '=';
|
|
180
|
-
const value = filter.value;
|
|
181
|
-
if (Array.isArray(value)) {
|
|
182
|
-
if ('=' === mappedOp) mappedOp = 'in';
|
|
183
|
-
if ('!=' === mappedOp) mappedOp = 'not in';
|
|
184
|
-
}
|
|
185
|
-
return [
|
|
186
|
-
{
|
|
187
|
-
field: filter.field,
|
|
188
|
-
op: mappedOp,
|
|
189
|
-
value
|
|
190
|
-
}
|
|
191
|
-
];
|
|
192
|
-
}
|
|
193
|
-
const buildHaving = (queryDSL, context)=>{
|
|
194
|
-
const { vbiDSL } = context;
|
|
195
|
-
const havingFilter = vbiDSL.havingFilter;
|
|
196
|
-
if (!havingFilter || 0 === havingFilter.conditions.length) return queryDSL;
|
|
197
|
-
const result = {
|
|
198
|
-
...queryDSL
|
|
199
|
-
};
|
|
200
|
-
result.having = {
|
|
201
|
-
op: havingFilter.op,
|
|
202
|
-
conditions: havingFilter.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
203
|
-
};
|
|
204
|
-
return result;
|
|
205
|
-
};
|
|
206
|
-
function isHavingGroup(clause) {
|
|
207
|
-
return 'op' in clause && 'conditions' in clause;
|
|
208
|
-
}
|
|
209
|
-
function buildHaving_mapClauseToCondition(clause) {
|
|
210
|
-
if (isHavingGroup(clause)) return [
|
|
211
|
-
buildHaving_mapGroupToCondition(clause)
|
|
212
|
-
];
|
|
213
|
-
return buildHaving_mapFilterToCondition(clause);
|
|
214
|
-
}
|
|
215
|
-
function buildHaving_mapGroupToCondition(group) {
|
|
216
|
-
return {
|
|
217
|
-
op: group.op,
|
|
218
|
-
conditions: group.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
function buildHaving_mapFilterToCondition(filter) {
|
|
222
|
-
const mappedOp = filter.op ?? '=';
|
|
223
|
-
return [
|
|
224
|
-
{
|
|
225
|
-
field: filter.field,
|
|
226
|
-
op: mappedOp,
|
|
227
|
-
value: filter.value
|
|
228
|
-
}
|
|
229
|
-
];
|
|
230
|
-
}
|
|
231
|
-
const buildLimit = (queryDSL, context)=>{
|
|
232
|
-
const result = {
|
|
233
|
-
...queryDSL
|
|
234
|
-
};
|
|
235
|
-
const limit = context.vbiDSL.limit ?? 1000;
|
|
236
|
-
result.limit = limit;
|
|
237
|
-
return result;
|
|
238
|
-
};
|
|
239
|
-
const buildVQuery = (vbiDSL, builder)=>{
|
|
240
|
-
const wrapper = (processor)=>(queryDSL)=>processor(queryDSL, {
|
|
241
|
-
vbiDSL,
|
|
242
|
-
builder
|
|
243
|
-
});
|
|
244
|
-
return (0, external_remeda_namespaceObject.pipe)({}, wrapper(buildSelect), wrapper(buildGroupBy), wrapper(buildWhere), wrapper(buildHaving), wrapper(buildLimit));
|
|
245
|
-
};
|
|
246
|
-
const buildVQueryDSL = (dsl, builder)=>{
|
|
247
|
-
const vbiDSL = buildVBIDSL(dsl);
|
|
248
|
-
return buildVQuery(vbiDSL, builder);
|
|
249
|
-
};
|
|
250
|
-
const buildVSeedDSL = async ({ vbiDSL, queryDSL })=>{
|
|
251
|
-
const connectorId = vbiDSL.connectorId;
|
|
252
|
-
const connector = await getConnector(connectorId);
|
|
253
|
-
const schema = await connector.discoverSchema();
|
|
254
|
-
const queryResult = await connector.query({
|
|
255
|
-
queryDSL,
|
|
256
|
-
schema,
|
|
257
|
-
connectorId
|
|
258
|
-
});
|
|
259
|
-
return {
|
|
260
|
-
chartType: vbiDSL.chartType,
|
|
261
|
-
dataset: queryResult.dataset,
|
|
262
|
-
theme: vbiDSL.theme,
|
|
263
|
-
locale: vbiDSL.locale
|
|
264
|
-
};
|
|
265
|
-
};
|
|
266
|
-
const getCollectionLength = (value)=>{
|
|
267
|
-
if (value instanceof external_yjs_namespaceObject.Array) return value.length;
|
|
268
|
-
if (Array.isArray(value)) return value.length;
|
|
269
|
-
return 0;
|
|
270
|
-
};
|
|
271
|
-
const isEmptyVBIDSL = (dsl)=>{
|
|
272
|
-
const dimensionsLength = getCollectionLength(dsl.get('dimensions'));
|
|
273
|
-
const measuresLength = getCollectionLength(dsl.get('measures'));
|
|
274
|
-
return 0 === dimensionsLength && 0 === measuresLength;
|
|
275
|
-
};
|
|
276
|
-
const getBuilderSchema = async (dsl)=>{
|
|
277
|
-
const connectorId = dsl.get('connectorId');
|
|
278
|
-
const connector = await getConnector(connectorId);
|
|
279
|
-
return connector.discoverSchema();
|
|
280
|
-
};
|
|
281
62
|
class MeasureNodeBuilder {
|
|
282
63
|
yMap;
|
|
283
64
|
constructor(yMap){
|
|
@@ -289,6 +70,12 @@ class MeasureNodeBuilder {
|
|
|
289
70
|
getField() {
|
|
290
71
|
return this.yMap.get('field');
|
|
291
72
|
}
|
|
73
|
+
getEncoding() {
|
|
74
|
+
return this.yMap.get('encoding');
|
|
75
|
+
}
|
|
76
|
+
getSort() {
|
|
77
|
+
return this.yMap.get('sort');
|
|
78
|
+
}
|
|
292
79
|
setAlias(alias) {
|
|
293
80
|
this.yMap.set('alias', alias);
|
|
294
81
|
return this;
|
|
@@ -297,10 +84,29 @@ class MeasureNodeBuilder {
|
|
|
297
84
|
this.yMap.set('encoding', encoding);
|
|
298
85
|
return this;
|
|
299
86
|
}
|
|
87
|
+
setSort(sort) {
|
|
88
|
+
this.yMap.set('sort', sort);
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
300
91
|
setAggregate(aggregate) {
|
|
301
92
|
this.yMap.set('aggregate', aggregate);
|
|
302
93
|
return this;
|
|
303
94
|
}
|
|
95
|
+
setFormat(format) {
|
|
96
|
+
this.yMap.set('format', format);
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
getFormat() {
|
|
100
|
+
return this.yMap.get('format');
|
|
101
|
+
}
|
|
102
|
+
clearFormat() {
|
|
103
|
+
this.yMap.delete('format');
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
clearSort() {
|
|
107
|
+
this.yMap.delete('sort');
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
304
110
|
toJSON() {
|
|
305
111
|
return this.yMap.toJSON();
|
|
306
112
|
}
|
|
@@ -335,9 +141,369 @@ const normalizeMeasureNodeIds = (measures)=>{
|
|
|
335
141
|
});
|
|
336
142
|
};
|
|
337
143
|
const locateMeasureIndexById = (measures, measureId)=>measures.toArray().findIndex((item)=>item.get('id') === measureId);
|
|
144
|
+
const MEASURE_ENCODING_SUPPORT = {
|
|
145
|
+
table: [
|
|
146
|
+
'column'
|
|
147
|
+
],
|
|
148
|
+
pivotTable: [
|
|
149
|
+
'detail'
|
|
150
|
+
],
|
|
151
|
+
column: [
|
|
152
|
+
'yAxis',
|
|
153
|
+
'detail',
|
|
154
|
+
'color',
|
|
155
|
+
'label',
|
|
156
|
+
'tooltip'
|
|
157
|
+
],
|
|
158
|
+
columnParallel: [
|
|
159
|
+
'yAxis',
|
|
160
|
+
'detail',
|
|
161
|
+
'color',
|
|
162
|
+
'label',
|
|
163
|
+
'tooltip'
|
|
164
|
+
],
|
|
165
|
+
columnPercent: [
|
|
166
|
+
'yAxis',
|
|
167
|
+
'detail',
|
|
168
|
+
'color',
|
|
169
|
+
'label',
|
|
170
|
+
'tooltip'
|
|
171
|
+
],
|
|
172
|
+
line: [
|
|
173
|
+
'yAxis',
|
|
174
|
+
'detail',
|
|
175
|
+
'color',
|
|
176
|
+
'label',
|
|
177
|
+
'tooltip'
|
|
178
|
+
],
|
|
179
|
+
area: [
|
|
180
|
+
'yAxis',
|
|
181
|
+
'detail',
|
|
182
|
+
'color',
|
|
183
|
+
'label',
|
|
184
|
+
'tooltip'
|
|
185
|
+
],
|
|
186
|
+
areaPercent: [
|
|
187
|
+
'yAxis',
|
|
188
|
+
'detail',
|
|
189
|
+
'color',
|
|
190
|
+
'label',
|
|
191
|
+
'tooltip'
|
|
192
|
+
],
|
|
193
|
+
bar: [
|
|
194
|
+
'xAxis',
|
|
195
|
+
'detail',
|
|
196
|
+
'color',
|
|
197
|
+
'label',
|
|
198
|
+
'tooltip'
|
|
199
|
+
],
|
|
200
|
+
barParallel: [
|
|
201
|
+
'xAxis',
|
|
202
|
+
'detail',
|
|
203
|
+
'color',
|
|
204
|
+
'label',
|
|
205
|
+
'tooltip'
|
|
206
|
+
],
|
|
207
|
+
barPercent: [
|
|
208
|
+
'xAxis',
|
|
209
|
+
'detail',
|
|
210
|
+
'color',
|
|
211
|
+
'label',
|
|
212
|
+
'tooltip'
|
|
213
|
+
],
|
|
214
|
+
dualAxis: [
|
|
215
|
+
'primaryYAxis',
|
|
216
|
+
'secondaryYAxis',
|
|
217
|
+
'color',
|
|
218
|
+
'label',
|
|
219
|
+
'tooltip'
|
|
220
|
+
],
|
|
221
|
+
scatter: [
|
|
222
|
+
'xAxis',
|
|
223
|
+
'yAxis',
|
|
224
|
+
'size',
|
|
225
|
+
'color',
|
|
226
|
+
'label',
|
|
227
|
+
'tooltip'
|
|
228
|
+
],
|
|
229
|
+
pie: [
|
|
230
|
+
'angle',
|
|
231
|
+
'detail',
|
|
232
|
+
'color',
|
|
233
|
+
'label',
|
|
234
|
+
'tooltip'
|
|
235
|
+
],
|
|
236
|
+
donut: [
|
|
237
|
+
'angle',
|
|
238
|
+
'detail',
|
|
239
|
+
'color',
|
|
240
|
+
'label',
|
|
241
|
+
'tooltip'
|
|
242
|
+
],
|
|
243
|
+
rose: [
|
|
244
|
+
'radius',
|
|
245
|
+
'detail',
|
|
246
|
+
'color',
|
|
247
|
+
'label',
|
|
248
|
+
'tooltip'
|
|
249
|
+
],
|
|
250
|
+
roseParallel: [
|
|
251
|
+
'radius',
|
|
252
|
+
'detail',
|
|
253
|
+
'color',
|
|
254
|
+
'label',
|
|
255
|
+
'tooltip'
|
|
256
|
+
],
|
|
257
|
+
radar: [
|
|
258
|
+
'radius',
|
|
259
|
+
'detail',
|
|
260
|
+
'color',
|
|
261
|
+
'label',
|
|
262
|
+
'tooltip'
|
|
263
|
+
],
|
|
264
|
+
funnel: [
|
|
265
|
+
'size',
|
|
266
|
+
'detail',
|
|
267
|
+
'color',
|
|
268
|
+
'label',
|
|
269
|
+
'tooltip'
|
|
270
|
+
],
|
|
271
|
+
heatmap: [
|
|
272
|
+
'color',
|
|
273
|
+
'detail',
|
|
274
|
+
'label',
|
|
275
|
+
'tooltip'
|
|
276
|
+
],
|
|
277
|
+
histogram: [
|
|
278
|
+
'value',
|
|
279
|
+
'x0',
|
|
280
|
+
'x1',
|
|
281
|
+
'yAxis',
|
|
282
|
+
'detail',
|
|
283
|
+
'color',
|
|
284
|
+
'label',
|
|
285
|
+
'tooltip'
|
|
286
|
+
],
|
|
287
|
+
boxplot: [
|
|
288
|
+
'value',
|
|
289
|
+
'q1',
|
|
290
|
+
'q3',
|
|
291
|
+
'min',
|
|
292
|
+
'max',
|
|
293
|
+
'median',
|
|
294
|
+
'outliers',
|
|
295
|
+
'color',
|
|
296
|
+
'label',
|
|
297
|
+
'tooltip'
|
|
298
|
+
],
|
|
299
|
+
treeMap: [
|
|
300
|
+
'size',
|
|
301
|
+
'detail',
|
|
302
|
+
'color',
|
|
303
|
+
'label',
|
|
304
|
+
'tooltip'
|
|
305
|
+
],
|
|
306
|
+
sunburst: [
|
|
307
|
+
'size',
|
|
308
|
+
'detail',
|
|
309
|
+
'color',
|
|
310
|
+
'label',
|
|
311
|
+
'tooltip'
|
|
312
|
+
],
|
|
313
|
+
circlePacking: [
|
|
314
|
+
'size',
|
|
315
|
+
'detail',
|
|
316
|
+
'color',
|
|
317
|
+
'label',
|
|
318
|
+
'tooltip'
|
|
319
|
+
],
|
|
320
|
+
raceBar: [
|
|
321
|
+
'xAxis',
|
|
322
|
+
'detail',
|
|
323
|
+
'color',
|
|
324
|
+
'label',
|
|
325
|
+
'tooltip'
|
|
326
|
+
],
|
|
327
|
+
raceColumn: [
|
|
328
|
+
'yAxis',
|
|
329
|
+
'detail',
|
|
330
|
+
'color',
|
|
331
|
+
'label',
|
|
332
|
+
'tooltip'
|
|
333
|
+
],
|
|
334
|
+
raceLine: [
|
|
335
|
+
'yAxis',
|
|
336
|
+
'detail',
|
|
337
|
+
'color',
|
|
338
|
+
'label',
|
|
339
|
+
'tooltip'
|
|
340
|
+
],
|
|
341
|
+
raceScatter: [
|
|
342
|
+
'xAxis',
|
|
343
|
+
'yAxis',
|
|
344
|
+
'size',
|
|
345
|
+
'color',
|
|
346
|
+
'label',
|
|
347
|
+
'tooltip'
|
|
348
|
+
],
|
|
349
|
+
racePie: [
|
|
350
|
+
'angle',
|
|
351
|
+
'detail',
|
|
352
|
+
'color',
|
|
353
|
+
'label',
|
|
354
|
+
'tooltip'
|
|
355
|
+
],
|
|
356
|
+
raceDonut: [
|
|
357
|
+
'angle',
|
|
358
|
+
'detail',
|
|
359
|
+
'color',
|
|
360
|
+
'label',
|
|
361
|
+
'tooltip'
|
|
362
|
+
]
|
|
363
|
+
};
|
|
364
|
+
const repeatEncoding = (first, rest = first)=>(index)=>0 === index ? first : rest;
|
|
365
|
+
const STRATEGY_BY_CHART_TYPE = {
|
|
366
|
+
[vseed_namespaceObject.ChartTypeEnum.Table]: {
|
|
367
|
+
supported: MEASURE_ENCODING_SUPPORT.table,
|
|
368
|
+
recommend: repeatEncoding('column')
|
|
369
|
+
},
|
|
370
|
+
[vseed_namespaceObject.ChartTypeEnum.PivotTable]: {
|
|
371
|
+
supported: MEASURE_ENCODING_SUPPORT.pivotTable,
|
|
372
|
+
recommend: repeatEncoding('detail')
|
|
373
|
+
},
|
|
374
|
+
[vseed_namespaceObject.ChartTypeEnum.Column]: {
|
|
375
|
+
supported: MEASURE_ENCODING_SUPPORT.column,
|
|
376
|
+
recommend: repeatEncoding('yAxis')
|
|
377
|
+
},
|
|
378
|
+
[vseed_namespaceObject.ChartTypeEnum.ColumnParallel]: {
|
|
379
|
+
supported: MEASURE_ENCODING_SUPPORT.columnParallel,
|
|
380
|
+
recommend: repeatEncoding('yAxis')
|
|
381
|
+
},
|
|
382
|
+
[vseed_namespaceObject.ChartTypeEnum.ColumnPercent]: {
|
|
383
|
+
supported: MEASURE_ENCODING_SUPPORT.columnPercent,
|
|
384
|
+
recommend: repeatEncoding('yAxis')
|
|
385
|
+
},
|
|
386
|
+
[vseed_namespaceObject.ChartTypeEnum.Line]: {
|
|
387
|
+
supported: MEASURE_ENCODING_SUPPORT.line,
|
|
388
|
+
recommend: repeatEncoding('yAxis')
|
|
389
|
+
},
|
|
390
|
+
[vseed_namespaceObject.ChartTypeEnum.Area]: {
|
|
391
|
+
supported: MEASURE_ENCODING_SUPPORT.area,
|
|
392
|
+
recommend: repeatEncoding('yAxis')
|
|
393
|
+
},
|
|
394
|
+
[vseed_namespaceObject.ChartTypeEnum.AreaPercent]: {
|
|
395
|
+
supported: MEASURE_ENCODING_SUPPORT.areaPercent,
|
|
396
|
+
recommend: repeatEncoding('yAxis')
|
|
397
|
+
},
|
|
398
|
+
[vseed_namespaceObject.ChartTypeEnum.Bar]: {
|
|
399
|
+
supported: MEASURE_ENCODING_SUPPORT.bar,
|
|
400
|
+
recommend: repeatEncoding('xAxis')
|
|
401
|
+
},
|
|
402
|
+
[vseed_namespaceObject.ChartTypeEnum.BarParallel]: {
|
|
403
|
+
supported: MEASURE_ENCODING_SUPPORT.barParallel,
|
|
404
|
+
recommend: repeatEncoding('xAxis')
|
|
405
|
+
},
|
|
406
|
+
[vseed_namespaceObject.ChartTypeEnum.BarPercent]: {
|
|
407
|
+
supported: MEASURE_ENCODING_SUPPORT.barPercent,
|
|
408
|
+
recommend: repeatEncoding('xAxis')
|
|
409
|
+
},
|
|
410
|
+
[vseed_namespaceObject.ChartTypeEnum.DualAxis]: {
|
|
411
|
+
supported: MEASURE_ENCODING_SUPPORT.dualAxis,
|
|
412
|
+
recommend: (index)=>0 === index ? 'primaryYAxis' : 'secondaryYAxis'
|
|
413
|
+
},
|
|
414
|
+
[vseed_namespaceObject.ChartTypeEnum.Scatter]: {
|
|
415
|
+
supported: MEASURE_ENCODING_SUPPORT.scatter,
|
|
416
|
+
recommend: (index)=>0 === index ? 'xAxis' : 'yAxis'
|
|
417
|
+
},
|
|
418
|
+
[vseed_namespaceObject.ChartTypeEnum.Pie]: {
|
|
419
|
+
supported: MEASURE_ENCODING_SUPPORT.pie,
|
|
420
|
+
recommend: repeatEncoding('angle')
|
|
421
|
+
},
|
|
422
|
+
[vseed_namespaceObject.ChartTypeEnum.Donut]: {
|
|
423
|
+
supported: MEASURE_ENCODING_SUPPORT.donut,
|
|
424
|
+
recommend: repeatEncoding('angle')
|
|
425
|
+
},
|
|
426
|
+
[vseed_namespaceObject.ChartTypeEnum.Rose]: {
|
|
427
|
+
supported: MEASURE_ENCODING_SUPPORT.rose,
|
|
428
|
+
recommend: repeatEncoding('radius')
|
|
429
|
+
},
|
|
430
|
+
[vseed_namespaceObject.ChartTypeEnum.RoseParallel]: {
|
|
431
|
+
supported: MEASURE_ENCODING_SUPPORT.roseParallel,
|
|
432
|
+
recommend: repeatEncoding('radius')
|
|
433
|
+
},
|
|
434
|
+
[vseed_namespaceObject.ChartTypeEnum.Radar]: {
|
|
435
|
+
supported: MEASURE_ENCODING_SUPPORT.radar,
|
|
436
|
+
recommend: repeatEncoding('radius')
|
|
437
|
+
},
|
|
438
|
+
[vseed_namespaceObject.ChartTypeEnum.Funnel]: {
|
|
439
|
+
supported: MEASURE_ENCODING_SUPPORT.funnel,
|
|
440
|
+
recommend: repeatEncoding('size')
|
|
441
|
+
},
|
|
442
|
+
[vseed_namespaceObject.ChartTypeEnum.Heatmap]: {
|
|
443
|
+
supported: MEASURE_ENCODING_SUPPORT.heatmap,
|
|
444
|
+
recommend: repeatEncoding('color')
|
|
445
|
+
},
|
|
446
|
+
[vseed_namespaceObject.ChartTypeEnum.Histogram]: {
|
|
447
|
+
supported: MEASURE_ENCODING_SUPPORT.histogram,
|
|
448
|
+
recommend: repeatEncoding('value')
|
|
449
|
+
},
|
|
450
|
+
[vseed_namespaceObject.ChartTypeEnum.Boxplot]: {
|
|
451
|
+
supported: MEASURE_ENCODING_SUPPORT.boxplot,
|
|
452
|
+
recommend: repeatEncoding('value')
|
|
453
|
+
},
|
|
454
|
+
[vseed_namespaceObject.ChartTypeEnum.TreeMap]: {
|
|
455
|
+
supported: MEASURE_ENCODING_SUPPORT.treeMap,
|
|
456
|
+
recommend: repeatEncoding('size')
|
|
457
|
+
},
|
|
458
|
+
[vseed_namespaceObject.ChartTypeEnum.Sunburst]: {
|
|
459
|
+
supported: MEASURE_ENCODING_SUPPORT.sunburst,
|
|
460
|
+
recommend: repeatEncoding('size')
|
|
461
|
+
},
|
|
462
|
+
[vseed_namespaceObject.ChartTypeEnum.CirclePacking]: {
|
|
463
|
+
supported: MEASURE_ENCODING_SUPPORT.circlePacking,
|
|
464
|
+
recommend: repeatEncoding('size')
|
|
465
|
+
},
|
|
466
|
+
[vseed_namespaceObject.ChartTypeEnum.RaceBar]: {
|
|
467
|
+
supported: MEASURE_ENCODING_SUPPORT.raceBar,
|
|
468
|
+
recommend: repeatEncoding('xAxis')
|
|
469
|
+
},
|
|
470
|
+
[vseed_namespaceObject.ChartTypeEnum.RaceColumn]: {
|
|
471
|
+
supported: MEASURE_ENCODING_SUPPORT.raceColumn,
|
|
472
|
+
recommend: repeatEncoding('yAxis')
|
|
473
|
+
},
|
|
474
|
+
[vseed_namespaceObject.ChartTypeEnum.RaceLine]: {
|
|
475
|
+
supported: MEASURE_ENCODING_SUPPORT.raceLine,
|
|
476
|
+
recommend: repeatEncoding('yAxis')
|
|
477
|
+
},
|
|
478
|
+
[vseed_namespaceObject.ChartTypeEnum.RaceScatter]: {
|
|
479
|
+
supported: MEASURE_ENCODING_SUPPORT.raceScatter,
|
|
480
|
+
recommend: (index)=>0 === index ? 'xAxis' : 'yAxis'
|
|
481
|
+
},
|
|
482
|
+
[vseed_namespaceObject.ChartTypeEnum.RacePie]: {
|
|
483
|
+
supported: MEASURE_ENCODING_SUPPORT.racePie,
|
|
484
|
+
recommend: repeatEncoding('angle')
|
|
485
|
+
},
|
|
486
|
+
[vseed_namespaceObject.ChartTypeEnum.RaceDonut]: {
|
|
487
|
+
supported: MEASURE_ENCODING_SUPPORT.raceDonut,
|
|
488
|
+
recommend: repeatEncoding('angle')
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
const DEFAULT_STRATEGY = STRATEGY_BY_CHART_TYPE[vseed_namespaceObject.ChartTypeEnum.Table];
|
|
492
|
+
const getSupportedMeasureEncodingsForChartType = (chartType)=>[
|
|
493
|
+
...(STRATEGY_BY_CHART_TYPE[chartType] || DEFAULT_STRATEGY).supported
|
|
494
|
+
];
|
|
495
|
+
const getRecommendedMeasureEncodingsForChartType = (chartType, measureCount)=>{
|
|
496
|
+
const strategy = STRATEGY_BY_CHART_TYPE[chartType] || DEFAULT_STRATEGY;
|
|
497
|
+
if (measureCount <= 0) return [];
|
|
498
|
+
return Array.from({
|
|
499
|
+
length: measureCount
|
|
500
|
+
}, (_, index)=>strategy.recommend(index));
|
|
501
|
+
};
|
|
338
502
|
class MeasuresBuilder {
|
|
503
|
+
doc;
|
|
339
504
|
dsl;
|
|
340
505
|
constructor(doc, dsl){
|
|
506
|
+
this.doc = doc;
|
|
341
507
|
this.dsl = dsl;
|
|
342
508
|
doc.transact(()=>{
|
|
343
509
|
const measures = getOrCreateMeasures(this.dsl);
|
|
@@ -345,38 +511,47 @@ class MeasuresBuilder {
|
|
|
345
511
|
});
|
|
346
512
|
}
|
|
347
513
|
add(field, callback) {
|
|
514
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
515
|
+
const chartType = this.dsl.get('chartType') || 'table';
|
|
516
|
+
const [encoding] = getRecommendedMeasureEncodingsForChartType(chartType, measures.length + 1).slice(-1);
|
|
348
517
|
const measure = {
|
|
349
518
|
id: id_id.uuid(),
|
|
350
519
|
alias: field,
|
|
351
520
|
field,
|
|
352
|
-
encoding
|
|
521
|
+
encoding,
|
|
353
522
|
aggregate: {
|
|
354
523
|
func: 'sum'
|
|
355
524
|
}
|
|
356
525
|
};
|
|
357
526
|
const yMap = new external_yjs_namespaceObject.Map();
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
527
|
+
this.doc.transact(()=>{
|
|
528
|
+
for (const [key, value] of Object.entries(measure))yMap.set(key, value);
|
|
529
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
530
|
+
measures.push([
|
|
531
|
+
yMap
|
|
532
|
+
]);
|
|
533
|
+
const node = new MeasureNodeBuilder(yMap);
|
|
534
|
+
callback(node);
|
|
535
|
+
});
|
|
365
536
|
return this;
|
|
366
537
|
}
|
|
367
538
|
remove(id) {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
539
|
+
this.doc.transact(()=>{
|
|
540
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
541
|
+
const index = locateMeasureIndexById(measures, id);
|
|
542
|
+
if (-1 !== index) measures.delete(index, 1);
|
|
543
|
+
});
|
|
371
544
|
return this;
|
|
372
545
|
}
|
|
373
546
|
update(id, callback) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
547
|
+
this.doc.transact(()=>{
|
|
548
|
+
const measures = getOrCreateMeasures(this.dsl);
|
|
549
|
+
const index = locateMeasureIndexById(measures, id);
|
|
550
|
+
if (-1 === index) throw new Error(`Measure with id "${id}" not found`);
|
|
551
|
+
const measureYMap = measures.get(index);
|
|
552
|
+
const node = new MeasureNodeBuilder(measureYMap);
|
|
553
|
+
callback(node);
|
|
554
|
+
});
|
|
380
555
|
return this;
|
|
381
556
|
}
|
|
382
557
|
find(predicate) {
|
|
@@ -397,9 +572,9 @@ class MeasuresBuilder {
|
|
|
397
572
|
}
|
|
398
573
|
observe(callback) {
|
|
399
574
|
const measures = getOrCreateMeasures(this.dsl);
|
|
400
|
-
measures.
|
|
575
|
+
measures.observeDeep(callback);
|
|
401
576
|
return ()=>{
|
|
402
|
-
measures.
|
|
577
|
+
measures.unobserveDeep(callback);
|
|
403
578
|
};
|
|
404
579
|
}
|
|
405
580
|
static isMeasureNode(node) {
|
|
@@ -420,10 +595,36 @@ class DimensionNodeBuilder {
|
|
|
420
595
|
getField() {
|
|
421
596
|
return this.yMap.get('field');
|
|
422
597
|
}
|
|
598
|
+
getEncoding() {
|
|
599
|
+
return this.yMap.get('encoding');
|
|
600
|
+
}
|
|
601
|
+
getSort() {
|
|
602
|
+
return this.yMap.get('sort');
|
|
603
|
+
}
|
|
423
604
|
setAlias(alias) {
|
|
424
605
|
this.yMap.set('alias', alias);
|
|
425
606
|
return this;
|
|
426
607
|
}
|
|
608
|
+
setEncoding(encoding) {
|
|
609
|
+
this.yMap.set('encoding', encoding);
|
|
610
|
+
return this;
|
|
611
|
+
}
|
|
612
|
+
setSort(sort) {
|
|
613
|
+
this.yMap.set('sort', sort);
|
|
614
|
+
return this;
|
|
615
|
+
}
|
|
616
|
+
setAggregate(aggregate) {
|
|
617
|
+
this.yMap.set('aggregate', aggregate);
|
|
618
|
+
return this;
|
|
619
|
+
}
|
|
620
|
+
clearAggregate() {
|
|
621
|
+
this.yMap.delete('aggregate');
|
|
622
|
+
return this;
|
|
623
|
+
}
|
|
624
|
+
clearSort() {
|
|
625
|
+
this.yMap.delete('sort');
|
|
626
|
+
return this;
|
|
627
|
+
}
|
|
427
628
|
toJSON() {
|
|
428
629
|
return this.yMap.toJSON();
|
|
429
630
|
}
|
|
@@ -441,9 +642,423 @@ const normalizeDimensionNodeIds = (dimensions)=>{
|
|
|
441
642
|
});
|
|
442
643
|
};
|
|
443
644
|
const locateDimensionIndexById = (dimensions, dimensionId)=>dimensions.toArray().findIndex((item)=>item.get('id') === dimensionId);
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
645
|
+
const DIMENSION_ENCODING_SUPPORT = {
|
|
646
|
+
table: [
|
|
647
|
+
'column'
|
|
648
|
+
],
|
|
649
|
+
pivotTable: [
|
|
650
|
+
'row',
|
|
651
|
+
'column'
|
|
652
|
+
],
|
|
653
|
+
column: [
|
|
654
|
+
'xAxis',
|
|
655
|
+
'color',
|
|
656
|
+
'detail',
|
|
657
|
+
'tooltip',
|
|
658
|
+
'label',
|
|
659
|
+
'row',
|
|
660
|
+
'column'
|
|
661
|
+
],
|
|
662
|
+
columnParallel: [
|
|
663
|
+
'xAxis',
|
|
664
|
+
'color',
|
|
665
|
+
'detail',
|
|
666
|
+
'tooltip',
|
|
667
|
+
'label',
|
|
668
|
+
'row',
|
|
669
|
+
'column'
|
|
670
|
+
],
|
|
671
|
+
columnPercent: [
|
|
672
|
+
'xAxis',
|
|
673
|
+
'color',
|
|
674
|
+
'detail',
|
|
675
|
+
'tooltip',
|
|
676
|
+
'label',
|
|
677
|
+
'row',
|
|
678
|
+
'column'
|
|
679
|
+
],
|
|
680
|
+
line: [
|
|
681
|
+
'xAxis',
|
|
682
|
+
'color',
|
|
683
|
+
'detail',
|
|
684
|
+
'tooltip',
|
|
685
|
+
'label',
|
|
686
|
+
'row',
|
|
687
|
+
'column'
|
|
688
|
+
],
|
|
689
|
+
area: [
|
|
690
|
+
'xAxis',
|
|
691
|
+
'color',
|
|
692
|
+
'detail',
|
|
693
|
+
'tooltip',
|
|
694
|
+
'label',
|
|
695
|
+
'row',
|
|
696
|
+
'column'
|
|
697
|
+
],
|
|
698
|
+
areaPercent: [
|
|
699
|
+
'xAxis',
|
|
700
|
+
'color',
|
|
701
|
+
'detail',
|
|
702
|
+
'tooltip',
|
|
703
|
+
'label',
|
|
704
|
+
'row',
|
|
705
|
+
'column'
|
|
706
|
+
],
|
|
707
|
+
dualAxis: [
|
|
708
|
+
'xAxis',
|
|
709
|
+
'color',
|
|
710
|
+
'detail',
|
|
711
|
+
'tooltip',
|
|
712
|
+
'label',
|
|
713
|
+
'row',
|
|
714
|
+
'column'
|
|
715
|
+
],
|
|
716
|
+
bar: [
|
|
717
|
+
'yAxis',
|
|
718
|
+
'color',
|
|
719
|
+
'detail',
|
|
720
|
+
'tooltip',
|
|
721
|
+
'label',
|
|
722
|
+
'row',
|
|
723
|
+
'column'
|
|
724
|
+
],
|
|
725
|
+
barParallel: [
|
|
726
|
+
'yAxis',
|
|
727
|
+
'color',
|
|
728
|
+
'detail',
|
|
729
|
+
'tooltip',
|
|
730
|
+
'label',
|
|
731
|
+
'row',
|
|
732
|
+
'column'
|
|
733
|
+
],
|
|
734
|
+
barPercent: [
|
|
735
|
+
'yAxis',
|
|
736
|
+
'color',
|
|
737
|
+
'detail',
|
|
738
|
+
'tooltip',
|
|
739
|
+
'label',
|
|
740
|
+
'row',
|
|
741
|
+
'column'
|
|
742
|
+
],
|
|
743
|
+
pie: [
|
|
744
|
+
'color',
|
|
745
|
+
'detail',
|
|
746
|
+
'tooltip',
|
|
747
|
+
'label',
|
|
748
|
+
'row',
|
|
749
|
+
'column'
|
|
750
|
+
],
|
|
751
|
+
donut: [
|
|
752
|
+
'color',
|
|
753
|
+
'detail',
|
|
754
|
+
'tooltip',
|
|
755
|
+
'label',
|
|
756
|
+
'row',
|
|
757
|
+
'column'
|
|
758
|
+
],
|
|
759
|
+
funnel: [
|
|
760
|
+
'color',
|
|
761
|
+
'detail',
|
|
762
|
+
'tooltip',
|
|
763
|
+
'label',
|
|
764
|
+
'row',
|
|
765
|
+
'column'
|
|
766
|
+
],
|
|
767
|
+
scatter: [
|
|
768
|
+
'color',
|
|
769
|
+
'detail',
|
|
770
|
+
'tooltip',
|
|
771
|
+
'label',
|
|
772
|
+
'row',
|
|
773
|
+
'column'
|
|
774
|
+
],
|
|
775
|
+
rose: [
|
|
776
|
+
'angle',
|
|
777
|
+
'color',
|
|
778
|
+
'detail',
|
|
779
|
+
'tooltip',
|
|
780
|
+
'label',
|
|
781
|
+
'row',
|
|
782
|
+
'column'
|
|
783
|
+
],
|
|
784
|
+
roseParallel: [
|
|
785
|
+
'angle',
|
|
786
|
+
'color',
|
|
787
|
+
'detail',
|
|
788
|
+
'tooltip',
|
|
789
|
+
'label',
|
|
790
|
+
'row',
|
|
791
|
+
'column'
|
|
792
|
+
],
|
|
793
|
+
radar: [
|
|
794
|
+
'angle',
|
|
795
|
+
'color',
|
|
796
|
+
'detail',
|
|
797
|
+
'tooltip',
|
|
798
|
+
'label',
|
|
799
|
+
'row',
|
|
800
|
+
'column'
|
|
801
|
+
],
|
|
802
|
+
heatmap: [
|
|
803
|
+
'xAxis',
|
|
804
|
+
'yAxis',
|
|
805
|
+
'color',
|
|
806
|
+
'detail',
|
|
807
|
+
'tooltip',
|
|
808
|
+
'label',
|
|
809
|
+
'row',
|
|
810
|
+
'column'
|
|
811
|
+
],
|
|
812
|
+
boxplot: [
|
|
813
|
+
'xAxis',
|
|
814
|
+
'color',
|
|
815
|
+
'tooltip',
|
|
816
|
+
'label',
|
|
817
|
+
'row',
|
|
818
|
+
'column'
|
|
819
|
+
],
|
|
820
|
+
histogram: [
|
|
821
|
+
'color',
|
|
822
|
+
'detail',
|
|
823
|
+
'tooltip',
|
|
824
|
+
'label',
|
|
825
|
+
'row',
|
|
826
|
+
'column'
|
|
827
|
+
],
|
|
828
|
+
treeMap: [
|
|
829
|
+
'hierarchy',
|
|
830
|
+
'detail',
|
|
831
|
+
'tooltip',
|
|
832
|
+
'label',
|
|
833
|
+
'row',
|
|
834
|
+
'column'
|
|
835
|
+
],
|
|
836
|
+
sunburst: [
|
|
837
|
+
'hierarchy',
|
|
838
|
+
'detail',
|
|
839
|
+
'tooltip',
|
|
840
|
+
'label',
|
|
841
|
+
'row',
|
|
842
|
+
'column'
|
|
843
|
+
],
|
|
844
|
+
circlePacking: [
|
|
845
|
+
'hierarchy',
|
|
846
|
+
'detail',
|
|
847
|
+
'tooltip',
|
|
848
|
+
'label',
|
|
849
|
+
'row',
|
|
850
|
+
'column'
|
|
851
|
+
],
|
|
852
|
+
raceBar: [
|
|
853
|
+
'player',
|
|
854
|
+
'yAxis',
|
|
855
|
+
'color',
|
|
856
|
+
'detail',
|
|
857
|
+
'tooltip',
|
|
858
|
+
'label',
|
|
859
|
+
'row',
|
|
860
|
+
'column'
|
|
861
|
+
],
|
|
862
|
+
raceColumn: [
|
|
863
|
+
'player',
|
|
864
|
+
'xAxis',
|
|
865
|
+
'color',
|
|
866
|
+
'detail',
|
|
867
|
+
'tooltip',
|
|
868
|
+
'label',
|
|
869
|
+
'row',
|
|
870
|
+
'column'
|
|
871
|
+
],
|
|
872
|
+
raceLine: [
|
|
873
|
+
'player',
|
|
874
|
+
'xAxis',
|
|
875
|
+
'color',
|
|
876
|
+
'detail',
|
|
877
|
+
'tooltip',
|
|
878
|
+
'label',
|
|
879
|
+
'row',
|
|
880
|
+
'column'
|
|
881
|
+
],
|
|
882
|
+
raceScatter: [
|
|
883
|
+
'player',
|
|
884
|
+
'color',
|
|
885
|
+
'detail',
|
|
886
|
+
'tooltip',
|
|
887
|
+
'label',
|
|
888
|
+
'row',
|
|
889
|
+
'column'
|
|
890
|
+
],
|
|
891
|
+
racePie: [
|
|
892
|
+
'player',
|
|
893
|
+
'color',
|
|
894
|
+
'detail',
|
|
895
|
+
'tooltip',
|
|
896
|
+
'label',
|
|
897
|
+
'row',
|
|
898
|
+
'column'
|
|
899
|
+
],
|
|
900
|
+
raceDonut: [
|
|
901
|
+
'player',
|
|
902
|
+
'color',
|
|
903
|
+
'detail',
|
|
904
|
+
'tooltip',
|
|
905
|
+
'label',
|
|
906
|
+
'row',
|
|
907
|
+
'column'
|
|
908
|
+
]
|
|
909
|
+
};
|
|
910
|
+
const dimension_encoding_repeatEncoding = (first, rest = first)=>(index)=>0 === index ? first : rest;
|
|
911
|
+
const alternateEncoding = (a, b)=>(index)=>index % 2 === 0 ? a : b;
|
|
912
|
+
const dimension_encoding_STRATEGY_BY_CHART_TYPE = {
|
|
913
|
+
[vseed_namespaceObject.ChartTypeEnum.Table]: {
|
|
914
|
+
supported: DIMENSION_ENCODING_SUPPORT.table,
|
|
915
|
+
recommend: dimension_encoding_repeatEncoding('column')
|
|
916
|
+
},
|
|
917
|
+
[vseed_namespaceObject.ChartTypeEnum.PivotTable]: {
|
|
918
|
+
supported: DIMENSION_ENCODING_SUPPORT.pivotTable,
|
|
919
|
+
recommend: alternateEncoding('column', 'row')
|
|
920
|
+
},
|
|
921
|
+
[vseed_namespaceObject.ChartTypeEnum.Column]: {
|
|
922
|
+
supported: DIMENSION_ENCODING_SUPPORT.column,
|
|
923
|
+
recommend: dimension_encoding_repeatEncoding('xAxis', 'color')
|
|
924
|
+
},
|
|
925
|
+
[vseed_namespaceObject.ChartTypeEnum.ColumnParallel]: {
|
|
926
|
+
supported: DIMENSION_ENCODING_SUPPORT.columnParallel,
|
|
927
|
+
recommend: dimension_encoding_repeatEncoding('xAxis', 'color')
|
|
928
|
+
},
|
|
929
|
+
[vseed_namespaceObject.ChartTypeEnum.ColumnPercent]: {
|
|
930
|
+
supported: DIMENSION_ENCODING_SUPPORT.columnPercent,
|
|
931
|
+
recommend: dimension_encoding_repeatEncoding('xAxis', 'color')
|
|
932
|
+
},
|
|
933
|
+
[vseed_namespaceObject.ChartTypeEnum.Line]: {
|
|
934
|
+
supported: DIMENSION_ENCODING_SUPPORT.line,
|
|
935
|
+
recommend: dimension_encoding_repeatEncoding('xAxis', 'color')
|
|
936
|
+
},
|
|
937
|
+
[vseed_namespaceObject.ChartTypeEnum.Area]: {
|
|
938
|
+
supported: DIMENSION_ENCODING_SUPPORT.area,
|
|
939
|
+
recommend: dimension_encoding_repeatEncoding('xAxis', 'color')
|
|
940
|
+
},
|
|
941
|
+
[vseed_namespaceObject.ChartTypeEnum.AreaPercent]: {
|
|
942
|
+
supported: DIMENSION_ENCODING_SUPPORT.areaPercent,
|
|
943
|
+
recommend: dimension_encoding_repeatEncoding('xAxis', 'color')
|
|
944
|
+
},
|
|
945
|
+
[vseed_namespaceObject.ChartTypeEnum.DualAxis]: {
|
|
946
|
+
supported: DIMENSION_ENCODING_SUPPORT.dualAxis,
|
|
947
|
+
recommend: dimension_encoding_repeatEncoding('xAxis', 'color')
|
|
948
|
+
},
|
|
949
|
+
[vseed_namespaceObject.ChartTypeEnum.Bar]: {
|
|
950
|
+
supported: DIMENSION_ENCODING_SUPPORT.bar,
|
|
951
|
+
recommend: dimension_encoding_repeatEncoding('yAxis', 'color')
|
|
952
|
+
},
|
|
953
|
+
[vseed_namespaceObject.ChartTypeEnum.BarParallel]: {
|
|
954
|
+
supported: DIMENSION_ENCODING_SUPPORT.barParallel,
|
|
955
|
+
recommend: dimension_encoding_repeatEncoding('yAxis', 'color')
|
|
956
|
+
},
|
|
957
|
+
[vseed_namespaceObject.ChartTypeEnum.BarPercent]: {
|
|
958
|
+
supported: DIMENSION_ENCODING_SUPPORT.barPercent,
|
|
959
|
+
recommend: dimension_encoding_repeatEncoding('yAxis', 'color')
|
|
960
|
+
},
|
|
961
|
+
[vseed_namespaceObject.ChartTypeEnum.Pie]: {
|
|
962
|
+
supported: DIMENSION_ENCODING_SUPPORT.pie,
|
|
963
|
+
recommend: dimension_encoding_repeatEncoding('color')
|
|
964
|
+
},
|
|
965
|
+
[vseed_namespaceObject.ChartTypeEnum.Donut]: {
|
|
966
|
+
supported: DIMENSION_ENCODING_SUPPORT.donut,
|
|
967
|
+
recommend: dimension_encoding_repeatEncoding('color')
|
|
968
|
+
},
|
|
969
|
+
[vseed_namespaceObject.ChartTypeEnum.Funnel]: {
|
|
970
|
+
supported: DIMENSION_ENCODING_SUPPORT.funnel,
|
|
971
|
+
recommend: dimension_encoding_repeatEncoding('color')
|
|
972
|
+
},
|
|
973
|
+
[vseed_namespaceObject.ChartTypeEnum.Scatter]: {
|
|
974
|
+
supported: DIMENSION_ENCODING_SUPPORT.scatter,
|
|
975
|
+
recommend: dimension_encoding_repeatEncoding('color')
|
|
976
|
+
},
|
|
977
|
+
[vseed_namespaceObject.ChartTypeEnum.Rose]: {
|
|
978
|
+
supported: DIMENSION_ENCODING_SUPPORT.rose,
|
|
979
|
+
recommend: dimension_encoding_repeatEncoding('angle', 'color')
|
|
980
|
+
},
|
|
981
|
+
[vseed_namespaceObject.ChartTypeEnum.RoseParallel]: {
|
|
982
|
+
supported: DIMENSION_ENCODING_SUPPORT.roseParallel,
|
|
983
|
+
recommend: dimension_encoding_repeatEncoding('angle', 'color')
|
|
984
|
+
},
|
|
985
|
+
[vseed_namespaceObject.ChartTypeEnum.Radar]: {
|
|
986
|
+
supported: DIMENSION_ENCODING_SUPPORT.radar,
|
|
987
|
+
recommend: dimension_encoding_repeatEncoding('angle', 'color')
|
|
988
|
+
},
|
|
989
|
+
[vseed_namespaceObject.ChartTypeEnum.Heatmap]: {
|
|
990
|
+
supported: DIMENSION_ENCODING_SUPPORT.heatmap,
|
|
991
|
+
recommend: dimension_encoding_repeatEncoding('xAxis', 'yAxis')
|
|
992
|
+
},
|
|
993
|
+
[vseed_namespaceObject.ChartTypeEnum.Boxplot]: {
|
|
994
|
+
supported: DIMENSION_ENCODING_SUPPORT.boxplot,
|
|
995
|
+
recommend: dimension_encoding_repeatEncoding('xAxis', 'color')
|
|
996
|
+
},
|
|
997
|
+
[vseed_namespaceObject.ChartTypeEnum.Histogram]: {
|
|
998
|
+
supported: DIMENSION_ENCODING_SUPPORT.histogram,
|
|
999
|
+
recommend: dimension_encoding_repeatEncoding('color')
|
|
1000
|
+
},
|
|
1001
|
+
[vseed_namespaceObject.ChartTypeEnum.TreeMap]: {
|
|
1002
|
+
supported: DIMENSION_ENCODING_SUPPORT.treeMap,
|
|
1003
|
+
recommend: dimension_encoding_repeatEncoding('hierarchy')
|
|
1004
|
+
},
|
|
1005
|
+
[vseed_namespaceObject.ChartTypeEnum.Sunburst]: {
|
|
1006
|
+
supported: DIMENSION_ENCODING_SUPPORT.sunburst,
|
|
1007
|
+
recommend: dimension_encoding_repeatEncoding('hierarchy')
|
|
1008
|
+
},
|
|
1009
|
+
[vseed_namespaceObject.ChartTypeEnum.CirclePacking]: {
|
|
1010
|
+
supported: DIMENSION_ENCODING_SUPPORT.circlePacking,
|
|
1011
|
+
recommend: dimension_encoding_repeatEncoding('hierarchy')
|
|
1012
|
+
},
|
|
1013
|
+
[vseed_namespaceObject.ChartTypeEnum.RaceBar]: {
|
|
1014
|
+
supported: DIMENSION_ENCODING_SUPPORT.raceBar,
|
|
1015
|
+
recommend: (index)=>{
|
|
1016
|
+
if (0 === index) return 'player';
|
|
1017
|
+
if (1 === index) return 'yAxis';
|
|
1018
|
+
return 'color';
|
|
1019
|
+
}
|
|
1020
|
+
},
|
|
1021
|
+
[vseed_namespaceObject.ChartTypeEnum.RaceColumn]: {
|
|
1022
|
+
supported: DIMENSION_ENCODING_SUPPORT.raceColumn,
|
|
1023
|
+
recommend: (index)=>{
|
|
1024
|
+
if (0 === index) return 'player';
|
|
1025
|
+
if (1 === index) return 'xAxis';
|
|
1026
|
+
return 'color';
|
|
1027
|
+
}
|
|
1028
|
+
},
|
|
1029
|
+
[vseed_namespaceObject.ChartTypeEnum.RaceLine]: {
|
|
1030
|
+
supported: DIMENSION_ENCODING_SUPPORT.raceLine,
|
|
1031
|
+
recommend: (index)=>0 === index ? 'player' : 'color'
|
|
1032
|
+
},
|
|
1033
|
+
[vseed_namespaceObject.ChartTypeEnum.RaceScatter]: {
|
|
1034
|
+
supported: DIMENSION_ENCODING_SUPPORT.raceScatter,
|
|
1035
|
+
recommend: (index)=>0 === index ? 'player' : 'color'
|
|
1036
|
+
},
|
|
1037
|
+
[vseed_namespaceObject.ChartTypeEnum.RacePie]: {
|
|
1038
|
+
supported: DIMENSION_ENCODING_SUPPORT.racePie,
|
|
1039
|
+
recommend: (index)=>0 === index ? 'player' : 'color'
|
|
1040
|
+
},
|
|
1041
|
+
[vseed_namespaceObject.ChartTypeEnum.RaceDonut]: {
|
|
1042
|
+
supported: DIMENSION_ENCODING_SUPPORT.raceDonut,
|
|
1043
|
+
recommend: (index)=>0 === index ? 'player' : 'color'
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
const dimension_encoding_DEFAULT_STRATEGY = dimension_encoding_STRATEGY_BY_CHART_TYPE[vseed_namespaceObject.ChartTypeEnum.Table];
|
|
1047
|
+
const getSupportedDimensionEncodingsForChartType = (chartType)=>[
|
|
1048
|
+
...(dimension_encoding_STRATEGY_BY_CHART_TYPE[chartType] || dimension_encoding_DEFAULT_STRATEGY).supported
|
|
1049
|
+
];
|
|
1050
|
+
const getRecommendedDimensionEncodingsForChartType = (chartType, dimensionCount)=>{
|
|
1051
|
+
const strategy = dimension_encoding_STRATEGY_BY_CHART_TYPE[chartType] || dimension_encoding_DEFAULT_STRATEGY;
|
|
1052
|
+
if (dimensionCount <= 0) return [];
|
|
1053
|
+
return Array.from({
|
|
1054
|
+
length: dimensionCount
|
|
1055
|
+
}, (_, index)=>strategy.recommend(index));
|
|
1056
|
+
};
|
|
1057
|
+
class DimensionsBuilder {
|
|
1058
|
+
doc;
|
|
1059
|
+
dsl;
|
|
1060
|
+
constructor(doc, dsl){
|
|
1061
|
+
this.doc = doc;
|
|
447
1062
|
this.dsl = dsl;
|
|
448
1063
|
doc.transact(()=>{
|
|
449
1064
|
const dimensions = getOrCreateDimensions(this.dsl);
|
|
@@ -451,34 +1066,44 @@ class DimensionsBuilder {
|
|
|
451
1066
|
});
|
|
452
1067
|
}
|
|
453
1068
|
add(field, callback) {
|
|
1069
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
1070
|
+
const chartType = this.dsl.get('chartType') || 'table';
|
|
1071
|
+
const [encoding] = getRecommendedDimensionEncodingsForChartType(chartType, dimensions.length + 1).slice(-1);
|
|
454
1072
|
const dimension = {
|
|
455
1073
|
id: id_id.uuid(),
|
|
456
1074
|
alias: field,
|
|
457
|
-
field
|
|
1075
|
+
field,
|
|
1076
|
+
encoding
|
|
458
1077
|
};
|
|
459
1078
|
const yMap = new external_yjs_namespaceObject.Map();
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
1079
|
+
this.doc.transact(()=>{
|
|
1080
|
+
for (const [key, value] of Object.entries(dimension))yMap.set(key, value);
|
|
1081
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
1082
|
+
dimensions.push([
|
|
1083
|
+
yMap
|
|
1084
|
+
]);
|
|
1085
|
+
const node = new DimensionNodeBuilder(yMap);
|
|
1086
|
+
callback(node);
|
|
1087
|
+
});
|
|
467
1088
|
return this;
|
|
468
1089
|
}
|
|
469
1090
|
remove(id) {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
1091
|
+
this.doc.transact(()=>{
|
|
1092
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
1093
|
+
const index = locateDimensionIndexById(dimensions, id);
|
|
1094
|
+
if (-1 !== index) dimensions.delete(index, 1);
|
|
1095
|
+
});
|
|
473
1096
|
return this;
|
|
474
1097
|
}
|
|
475
1098
|
update(id, callback) {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
1099
|
+
this.doc.transact(()=>{
|
|
1100
|
+
const dimensions = getOrCreateDimensions(this.dsl);
|
|
1101
|
+
const index = locateDimensionIndexById(dimensions, id);
|
|
1102
|
+
if (-1 === index) throw new Error(`Dimension with id "${id}" not found`);
|
|
1103
|
+
const dimensionYMap = dimensions.get(index);
|
|
1104
|
+
const node = new DimensionNodeBuilder(dimensionYMap);
|
|
1105
|
+
callback(node);
|
|
1106
|
+
});
|
|
482
1107
|
return this;
|
|
483
1108
|
}
|
|
484
1109
|
find(predicate) {
|
|
@@ -499,9 +1124,9 @@ class DimensionsBuilder {
|
|
|
499
1124
|
}
|
|
500
1125
|
observe(callback) {
|
|
501
1126
|
const dimensions = getOrCreateDimensions(this.dsl);
|
|
502
|
-
dimensions.
|
|
1127
|
+
dimensions.observeDeep(callback);
|
|
503
1128
|
return ()=>{
|
|
504
|
-
dimensions.
|
|
1129
|
+
dimensions.unobserveDeep(callback);
|
|
505
1130
|
};
|
|
506
1131
|
}
|
|
507
1132
|
static isDimensionNode(node) {
|
|
@@ -511,9 +1136,27 @@ class DimensionsBuilder {
|
|
|
511
1136
|
return 'children' in node;
|
|
512
1137
|
}
|
|
513
1138
|
}
|
|
1139
|
+
const reapplyDimensionEncodings = (dsl, chartType)=>{
|
|
1140
|
+
const dimensions = getOrCreateDimensions(dsl);
|
|
1141
|
+
const nodes = dimensions.toArray().filter((item)=>item instanceof external_yjs_namespaceObject.Map && 'string' == typeof item.get('field'));
|
|
1142
|
+
const encodings = getRecommendedDimensionEncodingsForChartType(chartType, nodes.length);
|
|
1143
|
+
nodes.forEach((node, index)=>{
|
|
1144
|
+
node.set('encoding', encodings[index]);
|
|
1145
|
+
});
|
|
1146
|
+
};
|
|
1147
|
+
const reapplyMeasureEncodings = (dsl, chartType)=>{
|
|
1148
|
+
const measures = getOrCreateMeasures(dsl);
|
|
1149
|
+
const nodes = measures.toArray().filter((item)=>item instanceof external_yjs_namespaceObject.Map && 'string' == typeof item.get('field'));
|
|
1150
|
+
const encodings = getRecommendedMeasureEncodingsForChartType(chartType, nodes.length);
|
|
1151
|
+
nodes.forEach((node, index)=>{
|
|
1152
|
+
node.set('encoding', encodings[index]);
|
|
1153
|
+
});
|
|
1154
|
+
};
|
|
514
1155
|
class ChartTypeBuilder {
|
|
1156
|
+
doc;
|
|
515
1157
|
dsl;
|
|
516
|
-
constructor(
|
|
1158
|
+
constructor(doc, dsl){
|
|
1159
|
+
this.doc = doc;
|
|
517
1160
|
this.dsl = dsl;
|
|
518
1161
|
}
|
|
519
1162
|
observe(callback) {
|
|
@@ -526,11 +1169,29 @@ class ChartTypeBuilder {
|
|
|
526
1169
|
};
|
|
527
1170
|
}
|
|
528
1171
|
changeChartType(chartType) {
|
|
529
|
-
this.
|
|
1172
|
+
this.doc.transact(()=>{
|
|
1173
|
+
this.dsl.set('chartType', chartType);
|
|
1174
|
+
reapplyDimensionEncodings(this.dsl, chartType);
|
|
1175
|
+
reapplyMeasureEncodings(this.dsl, chartType);
|
|
1176
|
+
});
|
|
530
1177
|
}
|
|
531
1178
|
getChartType() {
|
|
532
1179
|
return this.dsl.get('chartType') || 'table';
|
|
533
1180
|
}
|
|
1181
|
+
getSupportedDimensionEncodings() {
|
|
1182
|
+
return getSupportedDimensionEncodingsForChartType(this.getChartType());
|
|
1183
|
+
}
|
|
1184
|
+
getRecommendedDimensionEncodings(dimensionCount) {
|
|
1185
|
+
const resolvedCount = dimensionCount ?? this.dsl.get('dimensions')?.length;
|
|
1186
|
+
return getRecommendedDimensionEncodingsForChartType(this.getChartType(), resolvedCount);
|
|
1187
|
+
}
|
|
1188
|
+
getSupportedMeasureEncodings() {
|
|
1189
|
+
return getSupportedMeasureEncodingsForChartType(this.getChartType());
|
|
1190
|
+
}
|
|
1191
|
+
getRecommendedMeasureEncodings(measureCount) {
|
|
1192
|
+
const resolvedCount = measureCount ?? this.dsl.get('measures')?.length;
|
|
1193
|
+
return getRecommendedMeasureEncodingsForChartType(this.getChartType(), resolvedCount);
|
|
1194
|
+
}
|
|
534
1195
|
toJSON() {
|
|
535
1196
|
return this.dsl.get('chartType') || 'table';
|
|
536
1197
|
}
|
|
@@ -538,25 +1199,35 @@ class ChartTypeBuilder {
|
|
|
538
1199
|
return [
|
|
539
1200
|
vseed_namespaceObject.ChartTypeEnum.Table,
|
|
540
1201
|
vseed_namespaceObject.ChartTypeEnum.PivotTable,
|
|
541
|
-
vseed_namespaceObject.ChartTypeEnum.Line,
|
|
542
1202
|
vseed_namespaceObject.ChartTypeEnum.Column,
|
|
543
|
-
vseed_namespaceObject.ChartTypeEnum.ColumnPercent,
|
|
544
1203
|
vseed_namespaceObject.ChartTypeEnum.ColumnParallel,
|
|
545
|
-
vseed_namespaceObject.ChartTypeEnum.
|
|
1204
|
+
vseed_namespaceObject.ChartTypeEnum.ColumnPercent,
|
|
1205
|
+
vseed_namespaceObject.ChartTypeEnum.Bar,
|
|
546
1206
|
vseed_namespaceObject.ChartTypeEnum.BarParallel,
|
|
1207
|
+
vseed_namespaceObject.ChartTypeEnum.BarPercent,
|
|
1208
|
+
vseed_namespaceObject.ChartTypeEnum.Line,
|
|
547
1209
|
vseed_namespaceObject.ChartTypeEnum.Area,
|
|
548
1210
|
vseed_namespaceObject.ChartTypeEnum.AreaPercent,
|
|
549
1211
|
vseed_namespaceObject.ChartTypeEnum.DualAxis,
|
|
550
1212
|
vseed_namespaceObject.ChartTypeEnum.Scatter,
|
|
551
|
-
vseed_namespaceObject.ChartTypeEnum.Rose,
|
|
552
|
-
vseed_namespaceObject.ChartTypeEnum.RoseParallel,
|
|
553
1213
|
vseed_namespaceObject.ChartTypeEnum.Pie,
|
|
554
1214
|
vseed_namespaceObject.ChartTypeEnum.Donut,
|
|
1215
|
+
vseed_namespaceObject.ChartTypeEnum.Rose,
|
|
1216
|
+
vseed_namespaceObject.ChartTypeEnum.RoseParallel,
|
|
555
1217
|
vseed_namespaceObject.ChartTypeEnum.Radar,
|
|
556
1218
|
vseed_namespaceObject.ChartTypeEnum.Funnel,
|
|
557
1219
|
vseed_namespaceObject.ChartTypeEnum.Heatmap,
|
|
558
1220
|
vseed_namespaceObject.ChartTypeEnum.Boxplot,
|
|
559
|
-
vseed_namespaceObject.ChartTypeEnum.Histogram
|
|
1221
|
+
vseed_namespaceObject.ChartTypeEnum.Histogram,
|
|
1222
|
+
vseed_namespaceObject.ChartTypeEnum.TreeMap,
|
|
1223
|
+
vseed_namespaceObject.ChartTypeEnum.Sunburst,
|
|
1224
|
+
vseed_namespaceObject.ChartTypeEnum.CirclePacking,
|
|
1225
|
+
vseed_namespaceObject.ChartTypeEnum.RaceBar,
|
|
1226
|
+
vseed_namespaceObject.ChartTypeEnum.RaceColumn,
|
|
1227
|
+
vseed_namespaceObject.ChartTypeEnum.RaceLine,
|
|
1228
|
+
vseed_namespaceObject.ChartTypeEnum.RaceScatter,
|
|
1229
|
+
vseed_namespaceObject.ChartTypeEnum.RacePie,
|
|
1230
|
+
vseed_namespaceObject.ChartTypeEnum.RaceDonut
|
|
560
1231
|
];
|
|
561
1232
|
}
|
|
562
1233
|
}
|
|
@@ -567,7 +1238,7 @@ function createWhereGroup(op = 'and', groupId = 'root') {
|
|
|
567
1238
|
yMap.set('conditions', new external_yjs_namespaceObject.Array());
|
|
568
1239
|
return yMap;
|
|
569
1240
|
}
|
|
570
|
-
function
|
|
1241
|
+
function isWhereGroup(yMap) {
|
|
571
1242
|
return void 0 !== yMap.get('op') && void 0 !== yMap.get('conditions');
|
|
572
1243
|
}
|
|
573
1244
|
function findEntry(collection, entryId) {
|
|
@@ -579,7 +1250,7 @@ function findEntry(collection, entryId) {
|
|
|
579
1250
|
index,
|
|
580
1251
|
item
|
|
581
1252
|
};
|
|
582
|
-
if (
|
|
1253
|
+
if (isWhereGroup(item)) {
|
|
583
1254
|
const nestedCollection = item.get('conditions');
|
|
584
1255
|
const nestedMatch = findEntry(nestedCollection, entryId);
|
|
585
1256
|
if (nestedMatch) return nestedMatch;
|
|
@@ -612,6 +1283,15 @@ class WhereFilterNodeBuilder {
|
|
|
612
1283
|
this.yMap.set('value', value);
|
|
613
1284
|
return this;
|
|
614
1285
|
}
|
|
1286
|
+
setDate(predicate) {
|
|
1287
|
+
this.yMap.set('op', 'date');
|
|
1288
|
+
this.yMap.set('value', predicate);
|
|
1289
|
+
return this;
|
|
1290
|
+
}
|
|
1291
|
+
getDate() {
|
|
1292
|
+
if ('date' !== this.yMap.get('op')) return;
|
|
1293
|
+
return this.yMap.get('value');
|
|
1294
|
+
}
|
|
615
1295
|
toJSON() {
|
|
616
1296
|
return this.yMap.toJSON();
|
|
617
1297
|
}
|
|
@@ -772,7 +1452,7 @@ class WhereFilterBuilder {
|
|
|
772
1452
|
};
|
|
773
1453
|
}
|
|
774
1454
|
static isGroup(yMap) {
|
|
775
|
-
return
|
|
1455
|
+
return isWhereGroup(yMap);
|
|
776
1456
|
}
|
|
777
1457
|
static isNode(yMap) {
|
|
778
1458
|
return void 0 !== yMap.get('field');
|
|
@@ -785,7 +1465,7 @@ function createHavingGroup(op = 'and', groupId = 'root') {
|
|
|
785
1465
|
yMap.set('conditions', new external_yjs_namespaceObject.Array());
|
|
786
1466
|
return yMap;
|
|
787
1467
|
}
|
|
788
|
-
function
|
|
1468
|
+
function isHavingGroup(yMap) {
|
|
789
1469
|
return void 0 !== yMap.get('op') && void 0 !== yMap.get('conditions');
|
|
790
1470
|
}
|
|
791
1471
|
function having_utils_findEntry(collection, entryId) {
|
|
@@ -797,7 +1477,7 @@ function having_utils_findEntry(collection, entryId) {
|
|
|
797
1477
|
index,
|
|
798
1478
|
item
|
|
799
1479
|
};
|
|
800
|
-
if (
|
|
1480
|
+
if (isHavingGroup(item)) {
|
|
801
1481
|
const nestedCollection = item.get('conditions');
|
|
802
1482
|
const nestedMatch = having_utils_findEntry(nestedCollection, entryId);
|
|
803
1483
|
if (nestedMatch) return nestedMatch;
|
|
@@ -818,6 +1498,9 @@ class HavingFilterNodeBuilder {
|
|
|
818
1498
|
getOperator() {
|
|
819
1499
|
return this.yMap.get('op');
|
|
820
1500
|
}
|
|
1501
|
+
getAggregate() {
|
|
1502
|
+
return this.yMap.get('aggregate');
|
|
1503
|
+
}
|
|
821
1504
|
setValue(value) {
|
|
822
1505
|
this.yMap.set('value', value);
|
|
823
1506
|
return this;
|
|
@@ -826,6 +1509,10 @@ class HavingFilterNodeBuilder {
|
|
|
826
1509
|
this.yMap.set('op', operator);
|
|
827
1510
|
return this;
|
|
828
1511
|
}
|
|
1512
|
+
setAggregate(aggregate) {
|
|
1513
|
+
this.yMap.set('aggregate', aggregate);
|
|
1514
|
+
return this;
|
|
1515
|
+
}
|
|
829
1516
|
toJSON() {
|
|
830
1517
|
return this.yMap.toJSON();
|
|
831
1518
|
}
|
|
@@ -852,6 +1539,9 @@ class HavingGroupBuilder {
|
|
|
852
1539
|
const yMap = new external_yjs_namespaceObject.Map();
|
|
853
1540
|
yMap.set('id', id_id.uuid());
|
|
854
1541
|
yMap.set('field', field);
|
|
1542
|
+
yMap.set('aggregate', {
|
|
1543
|
+
func: 'sum'
|
|
1544
|
+
});
|
|
855
1545
|
this.getConditions().push([
|
|
856
1546
|
yMap
|
|
857
1547
|
]);
|
|
@@ -909,6 +1599,9 @@ class HavingFilterBuilder {
|
|
|
909
1599
|
const yMap = new external_yjs_namespaceObject.Map();
|
|
910
1600
|
yMap.set('id', id_id.uuid());
|
|
911
1601
|
yMap.set('field', field);
|
|
1602
|
+
yMap.set('aggregate', {
|
|
1603
|
+
func: 'sum'
|
|
1604
|
+
});
|
|
912
1605
|
this.getConditions().push([
|
|
913
1606
|
yMap
|
|
914
1607
|
]);
|
|
@@ -986,7 +1679,7 @@ class HavingFilterBuilder {
|
|
|
986
1679
|
};
|
|
987
1680
|
}
|
|
988
1681
|
static isGroup(yMap) {
|
|
989
|
-
return
|
|
1682
|
+
return isHavingGroup(yMap);
|
|
990
1683
|
}
|
|
991
1684
|
static isNode(yMap) {
|
|
992
1685
|
return void 0 !== yMap.get('field');
|
|
@@ -1085,20 +1778,531 @@ class UndoManager {
|
|
|
1085
1778
|
this.manager.clear(clearUndoStack, clearRedoStack);
|
|
1086
1779
|
}
|
|
1087
1780
|
}
|
|
1088
|
-
const
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1781
|
+
const VBI_TO_VQUERY_MEASURE_AGGR_FUNC_MAP = {
|
|
1782
|
+
count: 'count',
|
|
1783
|
+
countDistinct: 'count_distinct',
|
|
1784
|
+
sum: 'sum',
|
|
1785
|
+
avg: 'avg',
|
|
1786
|
+
min: 'min',
|
|
1787
|
+
max: 'max',
|
|
1788
|
+
variance: 'variance',
|
|
1789
|
+
variancePop: 'variance_pop',
|
|
1790
|
+
stddev: 'stddev',
|
|
1791
|
+
median: 'median',
|
|
1792
|
+
quantile: 'quantile'
|
|
1793
|
+
};
|
|
1794
|
+
const VBI_TO_VQUERY_DIMENSION_AGGR_FUNC_MAP = {
|
|
1795
|
+
toYear: 'to_year',
|
|
1796
|
+
toQuarter: 'to_quarter',
|
|
1797
|
+
toMonth: 'to_month',
|
|
1798
|
+
toWeek: 'to_week',
|
|
1799
|
+
toDay: 'to_day',
|
|
1800
|
+
toHour: 'to_hour',
|
|
1801
|
+
toMinute: 'to_minute',
|
|
1802
|
+
toSecond: 'to_second'
|
|
1803
|
+
};
|
|
1804
|
+
const mapAggregateForVQuery = (aggregate)=>{
|
|
1805
|
+
if (!aggregate) return aggregate;
|
|
1806
|
+
const mappedFunc = VBI_TO_VQUERY_MEASURE_AGGR_FUNC_MAP[aggregate.func] ?? aggregate.func;
|
|
1807
|
+
return {
|
|
1808
|
+
...aggregate,
|
|
1809
|
+
func: mappedFunc
|
|
1810
|
+
};
|
|
1811
|
+
};
|
|
1812
|
+
const mapDimensionAggregateForVQuery = (aggregate)=>{
|
|
1813
|
+
if (!aggregate) return aggregate;
|
|
1814
|
+
const mappedFunc = VBI_TO_VQUERY_DIMENSION_AGGR_FUNC_MAP[aggregate.func] ?? aggregate.func;
|
|
1815
|
+
return {
|
|
1816
|
+
...aggregate,
|
|
1817
|
+
func: mappedFunc
|
|
1818
|
+
};
|
|
1819
|
+
};
|
|
1820
|
+
const buildSelect = (queryDSL, context)=>{
|
|
1821
|
+
const { vbiDSL } = context;
|
|
1822
|
+
const measures = vbiDSL.measures;
|
|
1823
|
+
const dimensions = vbiDSL.dimensions;
|
|
1824
|
+
const result = {
|
|
1825
|
+
...queryDSL
|
|
1826
|
+
};
|
|
1827
|
+
const measureNodes = measures.filter((measure)=>MeasuresBuilder.isMeasureNode(measure));
|
|
1828
|
+
const measureSelects = measureNodes.map((measure)=>({
|
|
1829
|
+
field: measure.field,
|
|
1830
|
+
alias: measure.id,
|
|
1831
|
+
aggr: mapAggregateForVQuery(measure.aggregate)
|
|
1832
|
+
}));
|
|
1833
|
+
const dimensionNodes = dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension));
|
|
1834
|
+
const dimensionSelects = dimensionNodes.map((dimension)=>{
|
|
1835
|
+
const aggregate = mapDimensionAggregateForVQuery(dimension.aggregate);
|
|
1836
|
+
if (!aggregate) return {
|
|
1837
|
+
field: dimension.field,
|
|
1838
|
+
alias: dimension.id
|
|
1839
|
+
};
|
|
1840
|
+
return {
|
|
1841
|
+
field: dimension.field,
|
|
1842
|
+
alias: dimension.id,
|
|
1843
|
+
aggr: aggregate
|
|
1844
|
+
};
|
|
1098
1845
|
});
|
|
1099
|
-
|
|
1846
|
+
result.select = [
|
|
1847
|
+
...measureSelects,
|
|
1848
|
+
...dimensionSelects
|
|
1849
|
+
];
|
|
1850
|
+
return result;
|
|
1851
|
+
};
|
|
1852
|
+
const buildGroupBy = (queryDSL, context)=>{
|
|
1853
|
+
const result = {
|
|
1854
|
+
...queryDSL
|
|
1855
|
+
};
|
|
1856
|
+
const { vbiDSL } = context;
|
|
1857
|
+
const dimensions = vbiDSL.dimensions;
|
|
1858
|
+
const dimensionNodes = dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension));
|
|
1859
|
+
result.groupBy = dimensionNodes.map((dimension)=>dimension.aggregate ? dimension.id : dimension.field);
|
|
1860
|
+
return result;
|
|
1861
|
+
};
|
|
1862
|
+
function resolveDatePredicate(predicate, now) {
|
|
1863
|
+
switch(predicate.type){
|
|
1864
|
+
case 'range':
|
|
1865
|
+
return resolveRange(predicate);
|
|
1866
|
+
case 'period':
|
|
1867
|
+
return resolvePeriod(predicate);
|
|
1868
|
+
case 'relative':
|
|
1869
|
+
return resolveRelative(predicate, now ?? new Date());
|
|
1870
|
+
case 'current':
|
|
1871
|
+
return resolveCurrent(predicate, now ?? new Date());
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
function resolveRange(p) {
|
|
1875
|
+
return {
|
|
1876
|
+
start: toDateString(p.start),
|
|
1877
|
+
end: toDateString(p.end),
|
|
1878
|
+
bounds: p.bounds ?? '[)'
|
|
1879
|
+
};
|
|
1880
|
+
}
|
|
1881
|
+
function resolvePeriod(p) {
|
|
1882
|
+
switch(p.unit){
|
|
1883
|
+
case 'year':
|
|
1884
|
+
return {
|
|
1885
|
+
start: `${p.year}-01-01`,
|
|
1886
|
+
end: `${p.year + 1}-01-01`,
|
|
1887
|
+
bounds: '[)'
|
|
1888
|
+
};
|
|
1889
|
+
case 'quarter':
|
|
1890
|
+
return resolveQuarter(p.year, p.quarter);
|
|
1891
|
+
case 'month':
|
|
1892
|
+
return resolveMonth(p.year, p.month);
|
|
1893
|
+
case 'week':
|
|
1894
|
+
return resolveISOWeek(p.year, p.week);
|
|
1895
|
+
case 'day':
|
|
1896
|
+
return resolveDay(p.date);
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
function resolveQuarter(year, quarter) {
|
|
1900
|
+
const startMonth = (quarter - 1) * 3 + 1;
|
|
1901
|
+
const start = formatDate(year, startMonth, 1);
|
|
1902
|
+
const endDate = new Date(Date.UTC(year, startMonth - 1 + 3, 1));
|
|
1903
|
+
return {
|
|
1904
|
+
start,
|
|
1905
|
+
end: utcToDateString(endDate),
|
|
1906
|
+
bounds: '[)'
|
|
1907
|
+
};
|
|
1908
|
+
}
|
|
1909
|
+
function resolveMonth(year, month) {
|
|
1910
|
+
const start = formatDate(year, month, 1);
|
|
1911
|
+
const endDate = new Date(Date.UTC(year, month, 1));
|
|
1912
|
+
return {
|
|
1913
|
+
start,
|
|
1914
|
+
end: utcToDateString(endDate),
|
|
1915
|
+
bounds: '[)'
|
|
1916
|
+
};
|
|
1917
|
+
}
|
|
1918
|
+
function resolveISOWeek(year, week) {
|
|
1919
|
+
const jan4 = new Date(Date.UTC(year, 0, 4));
|
|
1920
|
+
const dayOfWeek = jan4.getUTCDay() || 7;
|
|
1921
|
+
const monday = new Date(jan4.getTime() - (dayOfWeek - 1) * 86400000);
|
|
1922
|
+
const weekStart = new Date(monday.getTime() + (week - 1) * 604800000);
|
|
1923
|
+
const weekEnd = new Date(weekStart.getTime() + 604800000);
|
|
1924
|
+
return {
|
|
1925
|
+
start: utcToDateString(weekStart),
|
|
1926
|
+
end: utcToDateString(weekEnd),
|
|
1927
|
+
bounds: '[)'
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1930
|
+
function resolveDay(date) {
|
|
1931
|
+
const d = 'string' == typeof date ? new Date(date + 'T00:00:00Z') : date;
|
|
1932
|
+
const next = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate() + 1));
|
|
1933
|
+
return {
|
|
1934
|
+
start: utcToDateString(d),
|
|
1935
|
+
end: utcToDateString(next),
|
|
1936
|
+
bounds: '[)'
|
|
1937
|
+
};
|
|
1938
|
+
}
|
|
1939
|
+
function resolveRelative(p, now) {
|
|
1940
|
+
const today = truncateToDay(now);
|
|
1941
|
+
const offset = 'last' === p.mode ? -p.amount : p.amount;
|
|
1942
|
+
const shifted = shiftDate(today, offset, p.unit);
|
|
1943
|
+
if ('last' === p.mode) return {
|
|
1944
|
+
start: utcToDateString(shifted),
|
|
1945
|
+
end: utcToDateString(today),
|
|
1946
|
+
bounds: '[)'
|
|
1947
|
+
};
|
|
1948
|
+
return {
|
|
1949
|
+
start: utcToDateString(today),
|
|
1950
|
+
end: utcToDateString(shifted),
|
|
1951
|
+
bounds: '[)'
|
|
1952
|
+
};
|
|
1953
|
+
}
|
|
1954
|
+
function resolveCurrent(p, now) {
|
|
1955
|
+
const offset = p.offset ?? 0;
|
|
1956
|
+
const base = truncateToDay(now);
|
|
1957
|
+
const periodStart = getPeriodStart(base, p.unit, offset);
|
|
1958
|
+
const periodEnd = shiftDate(periodStart, 1, p.unit);
|
|
1959
|
+
return {
|
|
1960
|
+
start: utcToDateString(periodStart),
|
|
1961
|
+
end: utcToDateString(periodEnd),
|
|
1962
|
+
bounds: '[)'
|
|
1963
|
+
};
|
|
1964
|
+
}
|
|
1965
|
+
function getPeriodStart(date, unit, offset) {
|
|
1966
|
+
const y = date.getUTCFullYear();
|
|
1967
|
+
const m = date.getUTCMonth();
|
|
1968
|
+
switch(unit){
|
|
1969
|
+
case 'year':
|
|
1970
|
+
return new Date(Date.UTC(y + offset, 0, 1));
|
|
1971
|
+
case 'quarter':
|
|
1972
|
+
{
|
|
1973
|
+
const q = Math.floor(m / 3);
|
|
1974
|
+
return new Date(Date.UTC(y, (q + offset) * 3, 1));
|
|
1975
|
+
}
|
|
1976
|
+
case 'month':
|
|
1977
|
+
return new Date(Date.UTC(y, m + offset, 1));
|
|
1978
|
+
case 'week':
|
|
1979
|
+
{
|
|
1980
|
+
const dow = date.getUTCDay() || 7;
|
|
1981
|
+
const monday = new Date(date.getTime() - (dow - 1) * 86400000);
|
|
1982
|
+
return new Date(monday.getTime() + 7 * offset * 86400000);
|
|
1983
|
+
}
|
|
1984
|
+
case 'day':
|
|
1985
|
+
return new Date(Date.UTC(y, m, date.getUTCDate() + offset));
|
|
1986
|
+
default:
|
|
1987
|
+
return date;
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
function shiftDate(date, amount, unit) {
|
|
1991
|
+
const y = date.getUTCFullYear();
|
|
1992
|
+
const m = date.getUTCMonth();
|
|
1993
|
+
const d = date.getUTCDate();
|
|
1994
|
+
switch(unit){
|
|
1995
|
+
case 'year':
|
|
1996
|
+
return new Date(Date.UTC(y + amount, m, d));
|
|
1997
|
+
case 'quarter':
|
|
1998
|
+
return new Date(Date.UTC(y, m + 3 * amount, d));
|
|
1999
|
+
case 'month':
|
|
2000
|
+
return new Date(Date.UTC(y, m + amount, d));
|
|
2001
|
+
case 'week':
|
|
2002
|
+
return new Date(date.getTime() + 7 * amount * 86400000);
|
|
2003
|
+
case 'day':
|
|
2004
|
+
return new Date(Date.UTC(y, m, d + amount));
|
|
2005
|
+
default:
|
|
2006
|
+
return date;
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
function truncateToDay(date) {
|
|
2010
|
+
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
|
|
2011
|
+
}
|
|
2012
|
+
function toDateString(input) {
|
|
2013
|
+
if ('string' == typeof input) return input;
|
|
2014
|
+
return utcToDateString(input);
|
|
2015
|
+
}
|
|
2016
|
+
function utcToDateString(date) {
|
|
2017
|
+
return formatDate(date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate());
|
|
2018
|
+
}
|
|
2019
|
+
function formatDate(year, month, day) {
|
|
2020
|
+
const y = String(year);
|
|
2021
|
+
const m = String(month).padStart(2, '0');
|
|
2022
|
+
const d = String(day).padStart(2, '0');
|
|
2023
|
+
return `${y}-${m}-${d}`;
|
|
2024
|
+
}
|
|
2025
|
+
const buildWhere = (queryDSL, context)=>{
|
|
2026
|
+
const { vbiDSL } = context;
|
|
2027
|
+
const whereFilter = vbiDSL.whereFilter;
|
|
2028
|
+
if (!whereFilter || 0 === whereFilter.conditions.length) return queryDSL;
|
|
2029
|
+
const result = {
|
|
2030
|
+
...queryDSL
|
|
2031
|
+
};
|
|
2032
|
+
result.where = mapGroupToCondition(whereFilter);
|
|
2033
|
+
return result;
|
|
2034
|
+
};
|
|
2035
|
+
function buildWhere_isWhereGroup(clause) {
|
|
2036
|
+
return 'op' in clause && 'conditions' in clause;
|
|
2037
|
+
}
|
|
2038
|
+
function mapClauseToCondition(clause) {
|
|
2039
|
+
if (buildWhere_isWhereGroup(clause)) return [
|
|
2040
|
+
mapGroupToCondition(clause)
|
|
2041
|
+
];
|
|
2042
|
+
return mapFilterToCondition(clause);
|
|
2043
|
+
}
|
|
2044
|
+
function mapGroupToCondition(group) {
|
|
2045
|
+
return {
|
|
2046
|
+
op: group.op,
|
|
2047
|
+
conditions: group.conditions.flatMap((c)=>mapClauseToCondition(c))
|
|
2048
|
+
};
|
|
2049
|
+
}
|
|
2050
|
+
function mapFilterToCondition(filter) {
|
|
2051
|
+
if ('date' === filter.op) return handleDateFilter(filter.field, filter.value);
|
|
2052
|
+
if ('between' === filter.op || 'not between' === filter.op) return handleBetweenFilter(filter);
|
|
2053
|
+
return handleSimpleFilter(filter);
|
|
2054
|
+
}
|
|
2055
|
+
function handleDateFilter(field, predicate) {
|
|
2056
|
+
const range = resolveDatePredicate(predicate);
|
|
2057
|
+
const startOp = '>=';
|
|
2058
|
+
const endOp = '[]' === range.bounds ? '<=' : '<';
|
|
2059
|
+
return [
|
|
2060
|
+
{
|
|
2061
|
+
field,
|
|
2062
|
+
op: startOp,
|
|
2063
|
+
value: range.start
|
|
2064
|
+
},
|
|
2065
|
+
{
|
|
2066
|
+
field,
|
|
2067
|
+
op: endOp,
|
|
2068
|
+
value: range.end
|
|
2069
|
+
}
|
|
2070
|
+
];
|
|
2071
|
+
}
|
|
2072
|
+
function handleBetweenFilter(filter) {
|
|
2073
|
+
const value = normalizeBetweenValue(filter.value);
|
|
2074
|
+
const lowerCondition = void 0 !== value.min && null !== value.min && '' !== value.min ? {
|
|
2075
|
+
field: filter.field,
|
|
2076
|
+
op: '<' === value.leftOp ? '>' : '>=',
|
|
2077
|
+
value: value.min
|
|
2078
|
+
} : void 0;
|
|
2079
|
+
const upperCondition = void 0 !== value.max && null !== value.max && '' !== value.max ? {
|
|
2080
|
+
field: filter.field,
|
|
2081
|
+
op: '<' === value.rightOp ? '<' : '<=',
|
|
2082
|
+
value: value.max
|
|
2083
|
+
} : void 0;
|
|
2084
|
+
if ('not between' === filter.op) {
|
|
2085
|
+
const outsideConditions = [
|
|
2086
|
+
lowerCondition && invertLowerBound(lowerCondition),
|
|
2087
|
+
upperCondition && invertUpperBound(upperCondition)
|
|
2088
|
+
].filter(Boolean);
|
|
2089
|
+
if (outsideConditions.length <= 1) return outsideConditions;
|
|
2090
|
+
return [
|
|
2091
|
+
{
|
|
2092
|
+
op: 'or',
|
|
2093
|
+
conditions: outsideConditions
|
|
2094
|
+
}
|
|
2095
|
+
];
|
|
2096
|
+
}
|
|
2097
|
+
return [
|
|
2098
|
+
lowerCondition,
|
|
2099
|
+
upperCondition
|
|
2100
|
+
].filter(Boolean);
|
|
2101
|
+
}
|
|
2102
|
+
function normalizeBetweenValue(value) {
|
|
2103
|
+
if (Array.isArray(value)) return {
|
|
2104
|
+
min: value[0],
|
|
2105
|
+
max: value[1],
|
|
2106
|
+
leftOp: '<=',
|
|
2107
|
+
rightOp: '<='
|
|
2108
|
+
};
|
|
2109
|
+
if ('object' == typeof value && null !== value) return value;
|
|
2110
|
+
return {};
|
|
2111
|
+
}
|
|
2112
|
+
function invertLowerBound(condition) {
|
|
2113
|
+
return {
|
|
2114
|
+
field: condition.field,
|
|
2115
|
+
op: '>' === condition.op ? '<=' : '<',
|
|
2116
|
+
value: condition.value
|
|
2117
|
+
};
|
|
2118
|
+
}
|
|
2119
|
+
function invertUpperBound(condition) {
|
|
2120
|
+
return {
|
|
2121
|
+
field: condition.field,
|
|
2122
|
+
op: '<' === condition.op ? '>=' : '>',
|
|
2123
|
+
value: condition.value
|
|
2124
|
+
};
|
|
2125
|
+
}
|
|
2126
|
+
function handleSimpleFilter(filter) {
|
|
2127
|
+
let mappedOp = filter.op;
|
|
2128
|
+
const value = filter.value;
|
|
2129
|
+
if (Array.isArray(value)) {
|
|
2130
|
+
if ('=' === mappedOp) mappedOp = 'in';
|
|
2131
|
+
if ('!=' === mappedOp) mappedOp = 'not in';
|
|
2132
|
+
}
|
|
2133
|
+
return [
|
|
2134
|
+
{
|
|
2135
|
+
field: filter.field,
|
|
2136
|
+
op: mappedOp,
|
|
2137
|
+
value
|
|
2138
|
+
}
|
|
2139
|
+
];
|
|
2140
|
+
}
|
|
2141
|
+
const buildHaving = (queryDSL, context)=>{
|
|
2142
|
+
const { vbiDSL } = context;
|
|
2143
|
+
const havingFilter = vbiDSL.havingFilter;
|
|
2144
|
+
if (!havingFilter || 0 === havingFilter.conditions.length) return queryDSL;
|
|
2145
|
+
const result = {
|
|
2146
|
+
...queryDSL
|
|
2147
|
+
};
|
|
2148
|
+
result.having = {
|
|
2149
|
+
op: havingFilter.op,
|
|
2150
|
+
conditions: havingFilter.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
2151
|
+
};
|
|
2152
|
+
return result;
|
|
2153
|
+
};
|
|
2154
|
+
function buildHaving_isHavingGroup(clause) {
|
|
2155
|
+
return 'op' in clause && 'conditions' in clause;
|
|
2156
|
+
}
|
|
2157
|
+
function buildHaving_mapClauseToCondition(clause) {
|
|
2158
|
+
if (buildHaving_isHavingGroup(clause)) return [
|
|
2159
|
+
buildHaving_mapGroupToCondition(clause)
|
|
2160
|
+
];
|
|
2161
|
+
return buildHaving_mapFilterToCondition(clause);
|
|
2162
|
+
}
|
|
2163
|
+
function buildHaving_mapGroupToCondition(group) {
|
|
2164
|
+
return {
|
|
2165
|
+
op: group.op,
|
|
2166
|
+
conditions: group.conditions.flatMap(buildHaving_mapClauseToCondition)
|
|
2167
|
+
};
|
|
2168
|
+
}
|
|
2169
|
+
function buildHaving_mapFilterToCondition(filter) {
|
|
2170
|
+
const mappedOp = normalizeOperator(filter.op, filter.value);
|
|
2171
|
+
const aggregate = mapAggregateForVQuery(filter.aggregate);
|
|
2172
|
+
return [
|
|
2173
|
+
{
|
|
2174
|
+
field: filter.field,
|
|
2175
|
+
aggr: aggregate,
|
|
2176
|
+
op: mappedOp,
|
|
2177
|
+
value: filter.value
|
|
2178
|
+
}
|
|
2179
|
+
];
|
|
2180
|
+
}
|
|
2181
|
+
function normalizeOperator(op, value) {
|
|
2182
|
+
let mappedOp = op;
|
|
2183
|
+
if (Array.isArray(value)) {
|
|
2184
|
+
if ('=' === mappedOp) mappedOp = 'in';
|
|
2185
|
+
if ('!=' === mappedOp) mappedOp = 'not in';
|
|
2186
|
+
}
|
|
2187
|
+
return mappedOp;
|
|
2188
|
+
}
|
|
2189
|
+
const toOrderItem = (node)=>({
|
|
2190
|
+
field: node.id,
|
|
2191
|
+
order: node.sort?.order
|
|
2192
|
+
});
|
|
2193
|
+
const buildOrderBy = (queryDSL, context)=>{
|
|
2194
|
+
const result = {
|
|
2195
|
+
...queryDSL
|
|
2196
|
+
};
|
|
2197
|
+
const dimensions = context.vbiDSL.dimensions.filter(DimensionsBuilder.isDimensionNode);
|
|
2198
|
+
const measures = context.vbiDSL.measures.filter(MeasuresBuilder.isMeasureNode);
|
|
2199
|
+
const sortedDimensions = dimensions.filter((node)=>node.sort);
|
|
2200
|
+
const sortedMeasures = measures.filter((node)=>node.sort);
|
|
2201
|
+
const sortedNodes = [
|
|
2202
|
+
...sortedDimensions,
|
|
2203
|
+
...sortedMeasures
|
|
2204
|
+
];
|
|
2205
|
+
if (sortedNodes.length > 0) {
|
|
2206
|
+
result.orderBy = sortedNodes.map(toOrderItem);
|
|
2207
|
+
return result;
|
|
2208
|
+
}
|
|
2209
|
+
const firstDimension = dimensions[0];
|
|
2210
|
+
if (firstDimension) result.orderBy = [
|
|
2211
|
+
{
|
|
2212
|
+
field: firstDimension.id,
|
|
2213
|
+
order: 'asc'
|
|
2214
|
+
}
|
|
2215
|
+
];
|
|
2216
|
+
return result;
|
|
2217
|
+
};
|
|
2218
|
+
const buildLimit = (queryDSL, context)=>{
|
|
2219
|
+
const result = {
|
|
2220
|
+
...queryDSL
|
|
2221
|
+
};
|
|
2222
|
+
const limit = context.vbiDSL.limit ?? 1000;
|
|
2223
|
+
result.limit = limit;
|
|
2224
|
+
return result;
|
|
2225
|
+
};
|
|
2226
|
+
const buildVQuery = (vbiDSL, builder)=>{
|
|
2227
|
+
const wrapper = (processor)=>(queryDSL)=>processor(queryDSL, {
|
|
2228
|
+
vbiDSL,
|
|
2229
|
+
builder
|
|
2230
|
+
});
|
|
2231
|
+
return (0, external_remeda_namespaceObject.pipe)({}, wrapper(buildSelect), wrapper(buildGroupBy), wrapper(buildWhere), wrapper(buildHaving), wrapper(buildOrderBy), wrapper(buildLimit));
|
|
2232
|
+
};
|
|
2233
|
+
const buildVQueryDSL = ({ vbiDSL, builder })=>buildVQuery(vbiDSL, builder);
|
|
2234
|
+
const buildVSeedDSL = async ({ vbiDSL, queryDSL, options })=>{
|
|
2235
|
+
const connectorId = vbiDSL.connectorId;
|
|
2236
|
+
const connector = await getConnector(connectorId);
|
|
2237
|
+
const schema = await connector.discoverSchema();
|
|
2238
|
+
const queryResult = await connector.query({
|
|
2239
|
+
queryDSL,
|
|
2240
|
+
schema,
|
|
2241
|
+
connectorId,
|
|
2242
|
+
signal: options.signal
|
|
2243
|
+
});
|
|
2244
|
+
const measures = vbiDSL.measures.filter((measure)=>MeasuresBuilder.isMeasureNode(measure)).map((measure)=>{
|
|
2245
|
+
const nextMeasure = {
|
|
2246
|
+
id: measure.id,
|
|
2247
|
+
alias: measure.alias
|
|
2248
|
+
};
|
|
2249
|
+
if (measure.encoding) nextMeasure.encoding = measure.encoding;
|
|
2250
|
+
if (measure.format) if ('autoFormat' in measure.format && true === measure.format.autoFormat) nextMeasure.autoFormat = true;
|
|
2251
|
+
else {
|
|
2252
|
+
nextMeasure.autoFormat = false;
|
|
2253
|
+
nextMeasure.numFormat = Object.fromEntries(Object.entries(measure.format).filter(([key])=>'autoFormat' !== key));
|
|
2254
|
+
}
|
|
2255
|
+
return nextMeasure;
|
|
2256
|
+
});
|
|
2257
|
+
const dimensions = vbiDSL.dimensions.filter((dimension)=>DimensionsBuilder.isDimensionNode(dimension)).map((dimension)=>{
|
|
2258
|
+
const nextDimension = {
|
|
2259
|
+
id: dimension.id,
|
|
2260
|
+
alias: dimension.alias
|
|
2261
|
+
};
|
|
2262
|
+
if (dimension.encoding) nextDimension.encoding = dimension.encoding;
|
|
2263
|
+
return nextDimension;
|
|
2264
|
+
});
|
|
2265
|
+
return {
|
|
2266
|
+
chartType: vbiDSL.chartType,
|
|
2267
|
+
dataset: queryResult.dataset,
|
|
2268
|
+
dimensions,
|
|
2269
|
+
measures,
|
|
2270
|
+
theme: vbiDSL.theme,
|
|
2271
|
+
locale: vbiDSL.locale
|
|
2272
|
+
};
|
|
2273
|
+
};
|
|
2274
|
+
const defaultVBIChartBuilderAdapters = {
|
|
2275
|
+
buildVQuery: buildVQueryDSL,
|
|
2276
|
+
buildVSeed: buildVSeedDSL
|
|
2277
|
+
};
|
|
2278
|
+
const resolveVBIChartBuilderAdapters = (adapters)=>({
|
|
2279
|
+
buildVQuery: adapters?.buildVQuery ?? defaultVBIChartBuilderAdapters.buildVQuery,
|
|
2280
|
+
buildVSeed: adapters?.buildVSeed ?? defaultVBIChartBuilderAdapters.buildVSeed
|
|
2281
|
+
});
|
|
2282
|
+
const applyUpdateToDoc = (doc, update, transactionOrigin)=>{
|
|
2283
|
+
external_yjs_namespaceObject.applyUpdate(doc, update, transactionOrigin);
|
|
2284
|
+
};
|
|
2285
|
+
const encodeDocStateAsUpdate = (doc, targetStateVector)=>external_yjs_namespaceObject.encodeStateAsUpdate(doc, targetStateVector);
|
|
2286
|
+
const buildVBIChartDSL = (dsl)=>dsl.toJSON();
|
|
2287
|
+
const getCollectionLength = (value)=>{
|
|
2288
|
+
if (value instanceof external_yjs_namespaceObject.Array) return value.length;
|
|
2289
|
+
if (Array.isArray(value)) return value.length;
|
|
2290
|
+
return 0;
|
|
2291
|
+
};
|
|
2292
|
+
const isEmptyVBIChartDSL = (dsl)=>{
|
|
2293
|
+
const dimensionsLength = getCollectionLength(dsl.get('dimensions'));
|
|
2294
|
+
const measuresLength = getCollectionLength(dsl.get('measures'));
|
|
2295
|
+
return 0 === dimensionsLength && 0 === measuresLength;
|
|
2296
|
+
};
|
|
2297
|
+
const getBuilderSchema = async (dsl)=>{
|
|
2298
|
+
const connectorId = dsl.get('connectorId');
|
|
2299
|
+
const connector = await getConnector(connectorId);
|
|
2300
|
+
return connector.discoverSchema();
|
|
2301
|
+
};
|
|
2302
|
+
class VBIChartBuilder {
|
|
1100
2303
|
doc;
|
|
1101
2304
|
dsl;
|
|
2305
|
+
adapters;
|
|
1102
2306
|
chartType;
|
|
1103
2307
|
measures;
|
|
1104
2308
|
dimensions;
|
|
@@ -1108,39 +2312,52 @@ class VBIBuilder {
|
|
|
1108
2312
|
locale;
|
|
1109
2313
|
limit;
|
|
1110
2314
|
undoManager;
|
|
1111
|
-
constructor(doc){
|
|
2315
|
+
constructor(doc, options){
|
|
1112
2316
|
this.doc = doc;
|
|
1113
2317
|
this.dsl = doc.getMap('dsl');
|
|
1114
|
-
|
|
1115
|
-
this.undoManager =
|
|
1116
|
-
this.chartType =
|
|
1117
|
-
this.measures =
|
|
1118
|
-
this.dimensions =
|
|
1119
|
-
this.havingFilter =
|
|
1120
|
-
this.whereFilter =
|
|
1121
|
-
this.theme =
|
|
1122
|
-
this.locale =
|
|
1123
|
-
this.limit =
|
|
2318
|
+
this.adapters = resolveVBIChartBuilderAdapters(options?.adapters);
|
|
2319
|
+
this.undoManager = new UndoManager(this.dsl);
|
|
2320
|
+
this.chartType = new ChartTypeBuilder(doc, this.dsl);
|
|
2321
|
+
this.measures = new MeasuresBuilder(doc, this.dsl);
|
|
2322
|
+
this.dimensions = new DimensionsBuilder(doc, this.dsl);
|
|
2323
|
+
this.havingFilter = new HavingFilterBuilder(doc, this.dsl);
|
|
2324
|
+
this.whereFilter = new WhereFilterBuilder(doc, this.dsl);
|
|
2325
|
+
this.theme = new ThemeBuilder(doc, this.dsl);
|
|
2326
|
+
this.locale = new LocaleBuilder(doc, this.dsl);
|
|
2327
|
+
this.limit = new LimitBuilder(doc, this.dsl);
|
|
1124
2328
|
}
|
|
1125
2329
|
applyUpdate = (update, transactionOrigin)=>applyUpdateToDoc(this.doc, update, transactionOrigin);
|
|
1126
2330
|
encodeStateAsUpdate = (targetStateVector)=>encodeDocStateAsUpdate(this.doc, targetStateVector);
|
|
1127
|
-
buildVSeed = async ()=>{
|
|
2331
|
+
buildVSeed = async (options = {})=>{
|
|
1128
2332
|
const vbiDSL = this.build();
|
|
1129
|
-
const queryDSL = this.buildVQuery(
|
|
1130
|
-
|
|
2333
|
+
const queryDSL = this.adapters.buildVQuery({
|
|
2334
|
+
dsl: this.dsl,
|
|
1131
2335
|
vbiDSL,
|
|
1132
|
-
|
|
2336
|
+
builder: this
|
|
2337
|
+
});
|
|
2338
|
+
return this.adapters.buildVSeed({
|
|
2339
|
+
dsl: this.dsl,
|
|
2340
|
+
vbiDSL,
|
|
2341
|
+
queryDSL,
|
|
2342
|
+
options,
|
|
2343
|
+
builder: this
|
|
2344
|
+
});
|
|
2345
|
+
};
|
|
2346
|
+
buildVQuery = ()=>{
|
|
2347
|
+
const vbiDSL = this.build();
|
|
2348
|
+
return this.adapters.buildVQuery({
|
|
2349
|
+
dsl: this.dsl,
|
|
2350
|
+
vbiDSL,
|
|
2351
|
+
builder: this
|
|
1133
2352
|
});
|
|
1134
2353
|
};
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
isEmpty = ()=>isEmptyVBIDSL(this.dsl);
|
|
2354
|
+
build = ()=>buildVBIChartDSL(this.dsl);
|
|
2355
|
+
isEmpty = ()=>isEmptyVBIChartDSL(this.dsl);
|
|
1138
2356
|
getSchema = async ()=>getBuilderSchema(this.dsl);
|
|
1139
2357
|
}
|
|
1140
2358
|
const shouldEnsureIdForObject = (obj, ensureId)=>{
|
|
1141
2359
|
if (true === ensureId) return true;
|
|
1142
|
-
|
|
1143
|
-
return false;
|
|
2360
|
+
return 'field' === ensureId && 'string' == typeof obj.field;
|
|
1144
2361
|
};
|
|
1145
2362
|
const toYMap = (obj, ensureId = false)=>{
|
|
1146
2363
|
const yMap = new external_yjs_namespaceObject.Map();
|
|
@@ -1148,23 +2365,9 @@ const toYMap = (obj, ensureId = false)=>{
|
|
|
1148
2365
|
for (const [key, value] of Object.entries(obj)){
|
|
1149
2366
|
if (('conditions' === key || 'children' === key) && Array.isArray(value)) {
|
|
1150
2367
|
const yArr = new external_yjs_namespaceObject.Array();
|
|
1151
|
-
for (const child of value)
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
child
|
|
1155
|
-
]);
|
|
1156
|
-
continue;
|
|
1157
|
-
}
|
|
1158
|
-
if ('object' == typeof child && null !== child) {
|
|
1159
|
-
yArr.push([
|
|
1160
|
-
toYMap(child, ensureId)
|
|
1161
|
-
]);
|
|
1162
|
-
continue;
|
|
1163
|
-
}
|
|
1164
|
-
yArr.push([
|
|
1165
|
-
child
|
|
1166
|
-
]);
|
|
1167
|
-
}
|
|
2368
|
+
for (const child of value)yArr.push([
|
|
2369
|
+
toYMap(child, ensureId)
|
|
2370
|
+
]);
|
|
1168
2371
|
yMap.set(key, yArr);
|
|
1169
2372
|
continue;
|
|
1170
2373
|
}
|
|
@@ -1174,65 +2377,34 @@ const toYMap = (obj, ensureId = false)=>{
|
|
|
1174
2377
|
};
|
|
1175
2378
|
const ensureYArray = (arr, ensureId = false)=>{
|
|
1176
2379
|
if (!arr) return new external_yjs_namespaceObject.Array();
|
|
1177
|
-
if (arr instanceof external_yjs_namespaceObject.Array) return arr;
|
|
1178
2380
|
const yArr = new external_yjs_namespaceObject.Array();
|
|
1179
|
-
for (const item of arr)
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
item
|
|
1183
|
-
]);
|
|
1184
|
-
continue;
|
|
1185
|
-
}
|
|
1186
|
-
if ('object' == typeof item && null !== item) {
|
|
1187
|
-
yArr.push([
|
|
1188
|
-
toYMap(item, ensureId)
|
|
1189
|
-
]);
|
|
1190
|
-
continue;
|
|
1191
|
-
}
|
|
1192
|
-
yArr.push([
|
|
1193
|
-
item
|
|
1194
|
-
]);
|
|
1195
|
-
}
|
|
2381
|
+
for (const item of arr)yArr.push([
|
|
2382
|
+
toYMap(item, ensureId)
|
|
2383
|
+
]);
|
|
1196
2384
|
return yArr;
|
|
1197
2385
|
};
|
|
1198
|
-
const
|
|
2386
|
+
const ensureWhereGroup = (whereFilter)=>{
|
|
2387
|
+
const source = whereFilter ?? {
|
|
1199
2388
|
id: 'root',
|
|
1200
2389
|
op: 'and',
|
|
1201
2390
|
conditions: []
|
|
1202
|
-
}
|
|
1203
|
-
const
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
if (sourceWhereFilter instanceof external_yjs_namespaceObject.Map) {
|
|
1208
|
-
if (!(whereGroup.get('conditions') instanceof external_yjs_namespaceObject.Array)) whereGroup.set('conditions', new external_yjs_namespaceObject.Array());
|
|
1209
|
-
if (!whereGroup.get('id')) whereGroup.set('id', 'root');
|
|
1210
|
-
if (!whereGroup.get('op')) whereGroup.set('op', 'and');
|
|
1211
|
-
return whereGroup;
|
|
1212
|
-
}
|
|
1213
|
-
whereGroup.set('id', sourceWhereFilter.id ?? 'root');
|
|
1214
|
-
whereGroup.set('op', sourceWhereFilter.op ?? 'and');
|
|
1215
|
-
whereGroup.set('conditions', ensureYArray(sourceWhereFilter.conditions, true));
|
|
2391
|
+
};
|
|
2392
|
+
const whereGroup = createWhereGroup();
|
|
2393
|
+
whereGroup.set('id', source.id);
|
|
2394
|
+
whereGroup.set('op', source.op);
|
|
2395
|
+
whereGroup.set('conditions', ensureYArray(source.conditions, true));
|
|
1216
2396
|
return whereGroup;
|
|
1217
2397
|
};
|
|
1218
|
-
const
|
|
2398
|
+
const ensureHavingGroup = (havingFilter)=>{
|
|
2399
|
+
const source = havingFilter ?? {
|
|
1219
2400
|
id: 'root',
|
|
1220
2401
|
op: 'and',
|
|
1221
2402
|
conditions: []
|
|
1222
|
-
}
|
|
1223
|
-
const
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
if (sourceHavingFilter instanceof external_yjs_namespaceObject.Map) {
|
|
1228
|
-
if (!(havingGroup.get('conditions') instanceof external_yjs_namespaceObject.Array)) havingGroup.set('conditions', new external_yjs_namespaceObject.Array());
|
|
1229
|
-
if (!havingGroup.get('id')) havingGroup.set('id', 'root');
|
|
1230
|
-
if (!havingGroup.get('op')) havingGroup.set('op', 'and');
|
|
1231
|
-
return havingGroup;
|
|
1232
|
-
}
|
|
1233
|
-
havingGroup.set('id', sourceHavingFilter.id ?? 'root');
|
|
1234
|
-
havingGroup.set('op', sourceHavingFilter.op ?? 'and');
|
|
1235
|
-
havingGroup.set('conditions', ensureYArray(sourceHavingFilter.conditions, true));
|
|
2403
|
+
};
|
|
2404
|
+
const havingGroup = createHavingGroup();
|
|
2405
|
+
havingGroup.set('id', source.id);
|
|
2406
|
+
havingGroup.set('op', source.op);
|
|
2407
|
+
havingGroup.set('conditions', ensureYArray(source.conditions, true));
|
|
1236
2408
|
return havingGroup;
|
|
1237
2409
|
};
|
|
1238
2410
|
const setBaseDSLFields = (dsl, vbi)=>{
|
|
@@ -1243,7 +2415,7 @@ const setBaseDSLFields = (dsl, vbi)=>{
|
|
|
1243
2415
|
if (vbi.locale) dsl.set('locale', vbi.locale);
|
|
1244
2416
|
if (void 0 !== vbi.version) dsl.set('version', vbi.version);
|
|
1245
2417
|
};
|
|
1246
|
-
const
|
|
2418
|
+
const createChartBuilderFromVBIChartDSLInput = (vbi, options)=>{
|
|
1247
2419
|
const doc = new external_yjs_namespaceObject.Doc();
|
|
1248
2420
|
const dsl = doc.getMap('dsl');
|
|
1249
2421
|
doc.transact(()=>{
|
|
@@ -1253,9 +2425,9 @@ const fromVBIDSLInput = (vbi)=>{
|
|
|
1253
2425
|
dsl.set('measures', ensureYArray(vbi.measures, 'field'));
|
|
1254
2426
|
dsl.set('dimensions', ensureYArray(vbi.dimensions, 'field'));
|
|
1255
2427
|
});
|
|
1256
|
-
return new
|
|
2428
|
+
return new VBIChartBuilder(doc, options);
|
|
1257
2429
|
};
|
|
1258
|
-
const
|
|
2430
|
+
const generateEmptyChartDSL = (connectorId)=>({
|
|
1259
2431
|
connectorId,
|
|
1260
2432
|
chartType: 'table',
|
|
1261
2433
|
measures: [],
|
|
@@ -1274,14 +2446,28 @@ const generateEmptyDSL = (connectorId)=>({
|
|
|
1274
2446
|
locale: 'zh-CN',
|
|
1275
2447
|
version: 0
|
|
1276
2448
|
});
|
|
1277
|
-
const
|
|
2449
|
+
const mergeBuilderOptions = (base, overrides)=>{
|
|
2450
|
+
if (!base) return overrides;
|
|
2451
|
+
if (!overrides) return base;
|
|
2452
|
+
return {
|
|
2453
|
+
...base,
|
|
2454
|
+
...overrides,
|
|
2455
|
+
adapters: {
|
|
2456
|
+
...base.adapters,
|
|
2457
|
+
...overrides.adapters
|
|
2458
|
+
}
|
|
2459
|
+
};
|
|
2460
|
+
};
|
|
2461
|
+
function createVBI(defaultBuilderOptions) {
|
|
2462
|
+
const createChart = (vbi, builderOptions)=>createChartBuilderFromVBIChartDSLInput(vbi, mergeBuilderOptions(defaultBuilderOptions, builderOptions));
|
|
2463
|
+
return {
|
|
1278
2464
|
connectorMap: connectorMap,
|
|
1279
2465
|
registerConnector: registerConnector,
|
|
1280
2466
|
getConnector: getConnector,
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
2467
|
+
generateEmptyChartDSL: generateEmptyChartDSL,
|
|
2468
|
+
createChart
|
|
2469
|
+
};
|
|
2470
|
+
}
|
|
1285
2471
|
const VBI = createVBI();
|
|
1286
2472
|
exports.ChartTypeBuilder = __webpack_exports__.ChartTypeBuilder;
|
|
1287
2473
|
exports.DimensionsBuilder = __webpack_exports__.DimensionsBuilder;
|
|
@@ -1292,9 +2478,11 @@ exports.MeasuresBuilder = __webpack_exports__.MeasuresBuilder;
|
|
|
1292
2478
|
exports.ThemeBuilder = __webpack_exports__.ThemeBuilder;
|
|
1293
2479
|
exports.UndoManager = __webpack_exports__.UndoManager;
|
|
1294
2480
|
exports.VBI = __webpack_exports__.VBI;
|
|
1295
|
-
exports.
|
|
2481
|
+
exports.VBIChartBuilder = __webpack_exports__.VBIChartBuilder;
|
|
1296
2482
|
exports.WhereFilterBuilder = __webpack_exports__.WhereFilterBuilder;
|
|
1297
2483
|
exports.buildVQuery = __webpack_exports__.buildVQuery;
|
|
2484
|
+
exports.createVBI = __webpack_exports__.createVBI;
|
|
2485
|
+
exports.defaultVBIChartBuilderAdapters = __webpack_exports__.defaultVBIChartBuilderAdapters;
|
|
1298
2486
|
exports.findTreeNodesBy = __webpack_exports__.findTreeNodesBy;
|
|
1299
2487
|
exports.id = __webpack_exports__.id;
|
|
1300
2488
|
exports.isVBIFilter = __webpack_exports__.isVBIFilter;
|
|
@@ -1302,6 +2490,7 @@ exports.isVBIHavingFilter = __webpack_exports__.isVBIHavingFilter;
|
|
|
1302
2490
|
exports.isVBIHavingGroup = __webpack_exports__.isVBIHavingGroup;
|
|
1303
2491
|
exports.isVBIWhereGroup = __webpack_exports__.isVBIWhereGroup;
|
|
1304
2492
|
exports.preorderTraverse = __webpack_exports__.preorderTraverse;
|
|
2493
|
+
exports.resolveVBIChartBuilderAdapters = __webpack_exports__.resolveVBIChartBuilderAdapters;
|
|
1305
2494
|
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
1306
2495
|
"ChartTypeBuilder",
|
|
1307
2496
|
"DimensionsBuilder",
|
|
@@ -1312,16 +2501,19 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
|
1312
2501
|
"ThemeBuilder",
|
|
1313
2502
|
"UndoManager",
|
|
1314
2503
|
"VBI",
|
|
1315
|
-
"
|
|
2504
|
+
"VBIChartBuilder",
|
|
1316
2505
|
"WhereFilterBuilder",
|
|
1317
2506
|
"buildVQuery",
|
|
2507
|
+
"createVBI",
|
|
2508
|
+
"defaultVBIChartBuilderAdapters",
|
|
1318
2509
|
"findTreeNodesBy",
|
|
1319
2510
|
"id",
|
|
1320
2511
|
"isVBIFilter",
|
|
1321
2512
|
"isVBIHavingFilter",
|
|
1322
2513
|
"isVBIHavingGroup",
|
|
1323
2514
|
"isVBIWhereGroup",
|
|
1324
|
-
"preorderTraverse"
|
|
2515
|
+
"preorderTraverse",
|
|
2516
|
+
"resolveVBIChartBuilderAdapters"
|
|
1325
2517
|
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
1326
2518
|
Object.defineProperty(exports, '__esModule', {
|
|
1327
2519
|
value: true
|