@hpcc-js/marshaller 2.28.7 → 2.28.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +43 -43
- package/dist/index.es6.js +25 -13
- package/dist/index.es6.js.map +1 -1
- package/dist/index.js +25 -13
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +1 -1
- package/package.json +12 -12
- package/src/__package__.ts +3 -3
- package/src/dashy.css +239 -239
- package/src/dashy.ts +521 -521
- package/src/ddl1/DDLApi.ts +229 -229
- package/src/ddl1/FlyoutButton.ts +120 -120
- package/src/ddl1/Graph.ts +93 -93
- package/src/ddl1/HTML.ts +77 -77
- package/src/ddl1/HipieDDL.ts +2437 -2437
- package/src/ddl1/HipieDDLMixin.ts +380 -380
- package/src/ddl1/Tabbed.ts +91 -91
- package/src/ddl1/TargetMarshaller.ts +57 -57
- package/src/ddl2/PopupManager.ts +89 -89
- package/src/ddl2/activities/activity.ts +431 -431
- package/src/ddl2/activities/databomb.ts +237 -237
- package/src/ddl2/activities/datasource.ts +52 -52
- package/src/ddl2/activities/dspicker.ts +106 -106
- package/src/ddl2/activities/filter.ts +542 -542
- package/src/ddl2/activities/form.ts +153 -153
- package/src/ddl2/activities/groupby.ts +439 -439
- package/src/ddl2/activities/hipiepipeline.ts +114 -114
- package/src/ddl2/activities/limit.ts +49 -49
- package/src/ddl2/activities/logicalfile.ts +62 -62
- package/src/ddl2/activities/nullview.ts +12 -12
- package/src/ddl2/activities/project.ts +764 -764
- package/src/ddl2/activities/rest.ts +568 -568
- package/src/ddl2/activities/roxie.ts +490 -490
- package/src/ddl2/activities/sampledata.json +16264 -16264
- package/src/ddl2/activities/sort.ts +176 -176
- package/src/ddl2/activities/wuresult.ts +395 -395
- package/src/ddl2/dashboard.css +13 -13
- package/src/ddl2/dashboard.ts +330 -330
- package/src/ddl2/dashboardDockPanel.ts +123 -123
- package/src/ddl2/dashboardGrid.ts +202 -202
- package/src/ddl2/ddl.ts +410 -410
- package/src/ddl2/ddleditor.ts +60 -60
- package/src/ddl2/dsTable.ts +238 -238
- package/src/ddl2/dvTable.ts +31 -31
- package/src/ddl2/graphadapter.ts +297 -297
- package/src/ddl2/javascriptadapter.ts +354 -354
- package/src/ddl2/model/element.ts +398 -398
- package/src/ddl2/model/visualization.ts +351 -351
- package/src/ddl2/model/vizChartPanel.ts +149 -149
- package/src/ddl2/pipelinePanel.css +4 -4
- package/src/ddl2/pipelinePanel.ts +465 -465
- package/src/index.ts +26 -26
- package/types/__package__.d.ts +2 -2
- package/types-3.4/__package__.d.ts +2 -2
|
@@ -1,351 +1,351 @@
|
|
|
1
|
-
import { Area, Bar, Bubble, Column, Contour, HexBin, Line, Pie, Radar, RadialBar, Scatter, Step, WordCloud } from "@hpcc-js/chart";
|
|
2
|
-
import { Database, EntityRectList, InputField, PropertyExt, publish, publishProxy, Widget } from "@hpcc-js/common";
|
|
3
|
-
import { DDL2 } from "@hpcc-js/ddl-shim";
|
|
4
|
-
import { Table } from "@hpcc-js/dgrid";
|
|
5
|
-
import { FieldForm } from "@hpcc-js/form";
|
|
6
|
-
import { AdjacencyGraph, DataGraph } from "@hpcc-js/graph";
|
|
7
|
-
import { ChoroplethCounties, ChoroplethStates, Leaflet } from "@hpcc-js/map";
|
|
8
|
-
import { isArray } from "@hpcc-js/util";
|
|
9
|
-
import { HipiePipeline } from "../activities/hipiepipeline";
|
|
10
|
-
import { ComputedField, Mappings, MultiField } from "../activities/project";
|
|
11
|
-
import { ElementContainer } from "./element";
|
|
12
|
-
import { VizChartPanel } from "./vizChartPanel";
|
|
13
|
-
|
|
14
|
-
export type VizType = "Table" | "FieldForm" |
|
|
15
|
-
"Area" | "Bubble" | "Bar" | "Column" | "Contour" | "HexBin" | "Line" | "Pie" | "WordCloud" | "Radar" | "RadialBar" | "Scatter" | "Step" |
|
|
16
|
-
"USCountiesChoropleth" | "USStatesChoropleth" | "ClusterPins" |
|
|
17
|
-
"EntityRectList" | "AdjacencyGraph" | "DataGraph";
|
|
18
|
-
const VizTypeMap: { [key: string]: new (...args: any[]) => object } = {
|
|
19
|
-
Table, FieldForm,
|
|
20
|
-
Area, Bubble, Bar, Column, Contour, HexBin, Line, Pie, Radar, RadialBar, Scatter, Step, WordCloud,
|
|
21
|
-
USCountiesChoropleth: ChoroplethCounties, USStatesChoropleth: ChoroplethStates, ClusterPins: Leaflet.ClusterPins,
|
|
22
|
-
EntityRectList, AdjacencyGraph, DataGraph
|
|
23
|
-
};
|
|
24
|
-
export const VizTypeSet = [];
|
|
25
|
-
for (const key in VizTypeMap) {
|
|
26
|
-
VizTypeSet.push(key);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function typeClass(type: VizType): any {
|
|
30
|
-
const retVal = VizTypeMap[type];
|
|
31
|
-
return retVal || Table;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function typeNew(type: VizType): Widget {
|
|
35
|
-
const ChartClass = VizTypeMap[type];
|
|
36
|
-
const retVal = new (ChartClass || Table)() as Widget;
|
|
37
|
-
|
|
38
|
-
// Override default properties as needed ---
|
|
39
|
-
if (retVal instanceof FieldForm) {
|
|
40
|
-
retVal
|
|
41
|
-
.validate(false)
|
|
42
|
-
.allowEmptyRequest(true)
|
|
43
|
-
;
|
|
44
|
-
} else if (retVal instanceof AdjacencyGraph) {
|
|
45
|
-
retVal
|
|
46
|
-
.uidColumn("uid")
|
|
47
|
-
.labelColumn("label")
|
|
48
|
-
.iconColumn("icon")
|
|
49
|
-
.linksColumn("links")
|
|
50
|
-
.linkUidColumn("uid")
|
|
51
|
-
.linkLabelColumn("label")
|
|
52
|
-
;
|
|
53
|
-
}
|
|
54
|
-
return retVal;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function typeInputs(type: VizType): InputField[] {
|
|
58
|
-
return typeClass(type).__inputs || [];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export class Visualization extends PropertyExt {
|
|
62
|
-
@publishProxy("_chartPanel")
|
|
63
|
-
title: publish<this, string>;
|
|
64
|
-
@publishProxy("_chartPanel")
|
|
65
|
-
description: publish<this, string>;
|
|
66
|
-
@publish(DDL2.VisibilitySet[0], "set", "Type", DDL2.VisibilitySet)
|
|
67
|
-
_visibility: DDL2.VisibilityType;
|
|
68
|
-
visibility(): DDL2.VisibilityType;
|
|
69
|
-
visibility(_: DDL2.VisibilityType): this;
|
|
70
|
-
visibility(_?: DDL2.VisibilityType): DDL2.VisibilityType | this {
|
|
71
|
-
if (!arguments.length) return this._visibility;
|
|
72
|
-
if (this._visibility !== _) {
|
|
73
|
-
this.chartPanel().target(null);
|
|
74
|
-
}
|
|
75
|
-
this._visibility = _;
|
|
76
|
-
return this;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
@publish("Table", "set", "Type", VizTypeSet)
|
|
80
|
-
_chartType: VizType;
|
|
81
|
-
chartType(): VizType;
|
|
82
|
-
chartType(_: VizType, props?: { [prop: string]: any }): this;
|
|
83
|
-
chartType(_?: VizType, props?: { [prop: string]: any }): VizType | this {
|
|
84
|
-
if (!arguments.length) return this._chartType;
|
|
85
|
-
if (VizTypeSet.indexOf(_) === -1) {
|
|
86
|
-
_ = "Table";
|
|
87
|
-
}
|
|
88
|
-
this._chartType = _;
|
|
89
|
-
this.typeChanged();
|
|
90
|
-
if (props) {
|
|
91
|
-
const widget = this.chartPanel().widget();
|
|
92
|
-
for (const prop in props) {
|
|
93
|
-
if (typeof widget[prop] === "function") {
|
|
94
|
-
widget[prop](props[prop]);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return this;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
@publish(null, "set", "Secondary Data View (e.g. graph edges)", function (this: Visualization) { return this.visualizationIDs(); }, { optional: true })
|
|
102
|
-
secondaryDataviewID: publish<this, string>;
|
|
103
|
-
secondaryDataviewID_exists: () => boolean;
|
|
104
|
-
secondaryDataviewID_valid: () => boolean;
|
|
105
|
-
|
|
106
|
-
@publish(null, "widget", "Mappings", undefined, { render: false, internal: true })
|
|
107
|
-
mappings: publish<this, Mappings>;
|
|
108
|
-
@publish([], "widget", "Widget")
|
|
109
|
-
_chartPanel: VizChartPanel;
|
|
110
|
-
chartPanel(): VizChartPanel;
|
|
111
|
-
chartPanel(_: VizChartPanel): this;
|
|
112
|
-
chartPanel(_?: VizChartPanel): VizChartPanel | this {
|
|
113
|
-
if (!arguments.length) return this._chartPanel;
|
|
114
|
-
this._chartPanel = _;
|
|
115
|
-
this._chartPanel
|
|
116
|
-
.on("click", (row: any, col: string, sel: boolean, more) => this.click(row, col, sel, more))
|
|
117
|
-
.on("vertex_click", (row: any, col: string, sel: boolean) => this.vertex_click(row, col, sel))
|
|
118
|
-
;
|
|
119
|
-
for (const key in VizTypeMap) {
|
|
120
|
-
if (this._chartPanel.widget() instanceof VizTypeMap[key]) {
|
|
121
|
-
this._chartType = key as VizType;
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return this;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
protected _hipiePipeline: HipiePipeline;
|
|
129
|
-
constructor(protected _ec: ElementContainer, hipiePipeline: HipiePipeline) {
|
|
130
|
-
super();
|
|
131
|
-
this._hipiePipeline = hipiePipeline;
|
|
132
|
-
this.mappings(new Mappings());
|
|
133
|
-
this.chartPanel(new VizChartPanel());
|
|
134
|
-
this.typeChanged();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
visualizationIDs(): string[] {
|
|
138
|
-
return this._ec.elementIDs().filter(id => id !== this.id());
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
_prevChartType;
|
|
142
|
-
typeChanged() {
|
|
143
|
-
if (this._prevChartType !== this._chartType) {
|
|
144
|
-
this._prevChartType = this._chartType;
|
|
145
|
-
this.refreshMappings();
|
|
146
|
-
const chart = typeNew(this._chartType);
|
|
147
|
-
this.chartPanel().widget(chart);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
properties(): DDL2.IWidgetProperties;
|
|
152
|
-
properties(_: DDL2.IWidgetProperties): this;
|
|
153
|
-
properties(_?: DDL2.IWidgetProperties): DDL2.IWidgetProperties | this {
|
|
154
|
-
if (!arguments.length) return this.chartPanel().serialize();
|
|
155
|
-
this.chartPanel().deserialize(_);
|
|
156
|
-
|
|
157
|
-
return this;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
refreshMappings(): this {
|
|
161
|
-
const mappings = this.mappings();
|
|
162
|
-
mappings.sourceActivity(this._hipiePipeline);
|
|
163
|
-
const cfs = mappings.validComputedFields();
|
|
164
|
-
const inFields = mappings.inFields();
|
|
165
|
-
const taken = {};
|
|
166
|
-
mappings.computedFields(typeInputs(this._chartType).map((input, idx) => {
|
|
167
|
-
let retVal: MultiField | ComputedField = cfs[idx];
|
|
168
|
-
if (retVal) {
|
|
169
|
-
if (retVal instanceof MultiField) {
|
|
170
|
-
} else {
|
|
171
|
-
retVal.label(input.id);
|
|
172
|
-
}
|
|
173
|
-
} else {
|
|
174
|
-
if (input.multi) {
|
|
175
|
-
retVal = new MultiField()
|
|
176
|
-
.owner(mappings)
|
|
177
|
-
.label(input.id)
|
|
178
|
-
;
|
|
179
|
-
const computedFields: ComputedField[] = [];
|
|
180
|
-
for (const inField of inFields) {
|
|
181
|
-
if ((input.type === "any" || input.type === inField.type) && !taken[inField.id]) {
|
|
182
|
-
taken[inField.id] = true;
|
|
183
|
-
computedFields.push(new ComputedField()
|
|
184
|
-
.label(inField.id)
|
|
185
|
-
.type("=")
|
|
186
|
-
.column1(inField.id)
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
retVal.multiFields(computedFields);
|
|
191
|
-
} else {
|
|
192
|
-
retVal = new ComputedField()
|
|
193
|
-
.owner(mappings)
|
|
194
|
-
.label(input.id)
|
|
195
|
-
.type("=")
|
|
196
|
-
;
|
|
197
|
-
for (const inField of inFields) {
|
|
198
|
-
if ((input.type === "any" || input.type === inField.type) && !taken[inField.id]) {
|
|
199
|
-
taken[inField.id] = true;
|
|
200
|
-
retVal.column1(inField.id);
|
|
201
|
-
break;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
return retVal;
|
|
207
|
-
}));
|
|
208
|
-
return this;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
_prevFields: ReadonlyArray<DDL2.IField> = [];
|
|
212
|
-
_prevLinkFields: ReadonlyArray<DDL2.IField> = [];
|
|
213
|
-
_prevData: ReadonlyArray<object> = [];
|
|
214
|
-
refreshData(): Promise<void> {
|
|
215
|
-
const mappings = this.mappings();
|
|
216
|
-
|
|
217
|
-
const fields = mappings.outFields();
|
|
218
|
-
const dbFields = this.toDBFields(fields);
|
|
219
|
-
let linkFields: ReadonlyArray<DDL2.IField>;
|
|
220
|
-
let dbLinkFields = [];
|
|
221
|
-
const se = this._ec.element(this.secondaryDataviewID());
|
|
222
|
-
if (se) {
|
|
223
|
-
linkFields = se.mappings().outFields();
|
|
224
|
-
dbLinkFields = this.toDBFields(linkFields);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const fieldsChanged = this._prevFields !== fields || this._prevLinkFields !== linkFields;
|
|
228
|
-
if (fieldsChanged) {
|
|
229
|
-
this._prevFields = fields;
|
|
230
|
-
if (this.chartType() === "DataGraph") {
|
|
231
|
-
const dataGraph = this.chartPanel().widget() as DataGraph;
|
|
232
|
-
dataGraph.vertexColumns(dbFields.map(f => f.label()));
|
|
233
|
-
dataGraph.edgeColumns(dbLinkFields.map(f => f.label()));
|
|
234
|
-
} else {
|
|
235
|
-
this.chartPanel().fields(dbFields.filter(f => f.id() !== "__lparam"));
|
|
236
|
-
}
|
|
237
|
-
} else {
|
|
238
|
-
console.warn(`***${this.id()} Immutable Fields***`);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const data = mappings.outData();
|
|
242
|
-
const dataChanged = this._prevData !== data;
|
|
243
|
-
if (dataChanged) {
|
|
244
|
-
this._prevData = data;
|
|
245
|
-
const mappedData = this.toDBData(dbFields, data);
|
|
246
|
-
if (this.chartType() === "DataGraph") {
|
|
247
|
-
const dataGraph = this.chartPanel().widget() as DataGraph;
|
|
248
|
-
dataGraph.vertices(mappedData);
|
|
249
|
-
if (se) {
|
|
250
|
-
const linkData = se.mappings().outData();
|
|
251
|
-
const mappedLinkData = this.toDBData(dbLinkFields, linkData);
|
|
252
|
-
dataGraph.edges(mappedLinkData);
|
|
253
|
-
}
|
|
254
|
-
} else {
|
|
255
|
-
this.chartPanel().data(mappedData);
|
|
256
|
-
}
|
|
257
|
-
} else {
|
|
258
|
-
console.warn(`${this.id()} Immutable Data!`);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
if (fieldsChanged || dataChanged) {
|
|
262
|
-
return this.chartPanel().renderPromise().then(() => { });
|
|
263
|
-
}
|
|
264
|
-
return Promise.resolve();
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
private fieldTypeTodbFieldType(type: DDL2.IFieldType): Database.FieldType {
|
|
268
|
-
switch (type) {
|
|
269
|
-
case "dataset":
|
|
270
|
-
return "nested";
|
|
271
|
-
case "boolean":
|
|
272
|
-
return "boolean";
|
|
273
|
-
case "number":
|
|
274
|
-
return "number";
|
|
275
|
-
case "string":
|
|
276
|
-
default:
|
|
277
|
-
return "string";
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
toDBFields(fields: ReadonlyArray<DDL2.IField>): Database.Field[] {
|
|
282
|
-
const retVal: Database.Field[] = [];
|
|
283
|
-
for (const field of fields || []) {
|
|
284
|
-
const f = new Database.Field()
|
|
285
|
-
.type(this.fieldTypeTodbFieldType(field.type))
|
|
286
|
-
.id(field.id)
|
|
287
|
-
.label(field.id)
|
|
288
|
-
;
|
|
289
|
-
switch (field.type) {
|
|
290
|
-
case "dataset":
|
|
291
|
-
f.children(this.toDBFields(field.children));
|
|
292
|
-
break;
|
|
293
|
-
case "object":
|
|
294
|
-
// TODO: For __lparam we should do nothing - not 100% if that is correct for "real" data (we don't really support "object" anyway)?
|
|
295
|
-
break;
|
|
296
|
-
}
|
|
297
|
-
retVal.push(f);
|
|
298
|
-
}
|
|
299
|
-
return retVal;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
toDBData(fields: Database.Field[], data: ReadonlyArray<object> | Readonly<object>) {
|
|
303
|
-
const _data: ReadonlyArray<object> = isArray(data) ? data : [data];
|
|
304
|
-
return _data.map((row: any) => {
|
|
305
|
-
const retVal = [];
|
|
306
|
-
for (const field of fields) {
|
|
307
|
-
if (field.type() === "nested") {
|
|
308
|
-
retVal.push(this.toDBData(field.children() as Database.Field[], row[field.id()].Row || row[field.id()]));
|
|
309
|
-
} else {
|
|
310
|
-
retVal.push(row[field.label()]);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
return retVal;
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
exec(): Promise<void[]> {
|
|
318
|
-
const promises = [];
|
|
319
|
-
if (this.secondaryDataviewID_exists()) {
|
|
320
|
-
const secondaryElementID = this.secondaryDataviewID();
|
|
321
|
-
const secondaryElement = this._ec.element(secondaryElementID);
|
|
322
|
-
if (secondaryElement) {
|
|
323
|
-
promises.push(secondaryElement.visualization().exec());
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const mappings = this.mappings();
|
|
328
|
-
mappings.sourceActivity(this._hipiePipeline);
|
|
329
|
-
promises.push(mappings.refreshMeta().then(() => {
|
|
330
|
-
return mappings.exec();
|
|
331
|
-
}));
|
|
332
|
-
|
|
333
|
-
return Promise.all(promises);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
refresh(): Promise<void> {
|
|
337
|
-
this.chartPanel().startProgress && this.chartPanel().startProgress();
|
|
338
|
-
return this.exec().then(() => {
|
|
339
|
-
this.chartPanel().finishProgress && this.chartPanel().finishProgress();
|
|
340
|
-
return this.refreshData();
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
// Events ---
|
|
345
|
-
click(row: any, col: string, sel: boolean, more?) {
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
vertex_click(row: any, col: string, sel: boolean) {
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
Visualization.prototype._class += " Visualization";
|
|
1
|
+
import { Area, Bar, Bubble, Column, Contour, HexBin, Line, Pie, Radar, RadialBar, Scatter, Step, WordCloud } from "@hpcc-js/chart";
|
|
2
|
+
import { Database, EntityRectList, InputField, PropertyExt, publish, publishProxy, Widget } from "@hpcc-js/common";
|
|
3
|
+
import { DDL2 } from "@hpcc-js/ddl-shim";
|
|
4
|
+
import { Table } from "@hpcc-js/dgrid";
|
|
5
|
+
import { FieldForm } from "@hpcc-js/form";
|
|
6
|
+
import { AdjacencyGraph, DataGraph } from "@hpcc-js/graph";
|
|
7
|
+
import { ChoroplethCounties, ChoroplethStates, Leaflet } from "@hpcc-js/map";
|
|
8
|
+
import { isArray } from "@hpcc-js/util";
|
|
9
|
+
import { HipiePipeline } from "../activities/hipiepipeline";
|
|
10
|
+
import { ComputedField, Mappings, MultiField } from "../activities/project";
|
|
11
|
+
import { ElementContainer } from "./element";
|
|
12
|
+
import { VizChartPanel } from "./vizChartPanel";
|
|
13
|
+
|
|
14
|
+
export type VizType = "Table" | "FieldForm" |
|
|
15
|
+
"Area" | "Bubble" | "Bar" | "Column" | "Contour" | "HexBin" | "Line" | "Pie" | "WordCloud" | "Radar" | "RadialBar" | "Scatter" | "Step" |
|
|
16
|
+
"USCountiesChoropleth" | "USStatesChoropleth" | "ClusterPins" |
|
|
17
|
+
"EntityRectList" | "AdjacencyGraph" | "DataGraph";
|
|
18
|
+
const VizTypeMap: { [key: string]: new (...args: any[]) => object } = {
|
|
19
|
+
Table, FieldForm,
|
|
20
|
+
Area, Bubble, Bar, Column, Contour, HexBin, Line, Pie, Radar, RadialBar, Scatter, Step, WordCloud,
|
|
21
|
+
USCountiesChoropleth: ChoroplethCounties, USStatesChoropleth: ChoroplethStates, ClusterPins: Leaflet.ClusterPins,
|
|
22
|
+
EntityRectList, AdjacencyGraph, DataGraph
|
|
23
|
+
};
|
|
24
|
+
export const VizTypeSet = [];
|
|
25
|
+
for (const key in VizTypeMap) {
|
|
26
|
+
VizTypeSet.push(key);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function typeClass(type: VizType): any {
|
|
30
|
+
const retVal = VizTypeMap[type];
|
|
31
|
+
return retVal || Table;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function typeNew(type: VizType): Widget {
|
|
35
|
+
const ChartClass = VizTypeMap[type];
|
|
36
|
+
const retVal = new (ChartClass || Table)() as Widget;
|
|
37
|
+
|
|
38
|
+
// Override default properties as needed ---
|
|
39
|
+
if (retVal instanceof FieldForm) {
|
|
40
|
+
retVal
|
|
41
|
+
.validate(false)
|
|
42
|
+
.allowEmptyRequest(true)
|
|
43
|
+
;
|
|
44
|
+
} else if (retVal instanceof AdjacencyGraph) {
|
|
45
|
+
retVal
|
|
46
|
+
.uidColumn("uid")
|
|
47
|
+
.labelColumn("label")
|
|
48
|
+
.iconColumn("icon")
|
|
49
|
+
.linksColumn("links")
|
|
50
|
+
.linkUidColumn("uid")
|
|
51
|
+
.linkLabelColumn("label")
|
|
52
|
+
;
|
|
53
|
+
}
|
|
54
|
+
return retVal;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function typeInputs(type: VizType): InputField[] {
|
|
58
|
+
return typeClass(type).__inputs || [];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export class Visualization extends PropertyExt {
|
|
62
|
+
@publishProxy("_chartPanel")
|
|
63
|
+
title: publish<this, string>;
|
|
64
|
+
@publishProxy("_chartPanel")
|
|
65
|
+
description: publish<this, string>;
|
|
66
|
+
@publish(DDL2.VisibilitySet[0], "set", "Type", DDL2.VisibilitySet)
|
|
67
|
+
_visibility: DDL2.VisibilityType;
|
|
68
|
+
visibility(): DDL2.VisibilityType;
|
|
69
|
+
visibility(_: DDL2.VisibilityType): this;
|
|
70
|
+
visibility(_?: DDL2.VisibilityType): DDL2.VisibilityType | this {
|
|
71
|
+
if (!arguments.length) return this._visibility;
|
|
72
|
+
if (this._visibility !== _) {
|
|
73
|
+
this.chartPanel().target(null);
|
|
74
|
+
}
|
|
75
|
+
this._visibility = _;
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@publish("Table", "set", "Type", VizTypeSet)
|
|
80
|
+
_chartType: VizType;
|
|
81
|
+
chartType(): VizType;
|
|
82
|
+
chartType(_: VizType, props?: { [prop: string]: any }): this;
|
|
83
|
+
chartType(_?: VizType, props?: { [prop: string]: any }): VizType | this {
|
|
84
|
+
if (!arguments.length) return this._chartType;
|
|
85
|
+
if (VizTypeSet.indexOf(_) === -1) {
|
|
86
|
+
_ = "Table";
|
|
87
|
+
}
|
|
88
|
+
this._chartType = _;
|
|
89
|
+
this.typeChanged();
|
|
90
|
+
if (props) {
|
|
91
|
+
const widget = this.chartPanel().widget();
|
|
92
|
+
for (const prop in props) {
|
|
93
|
+
if (typeof widget[prop] === "function") {
|
|
94
|
+
widget[prop](props[prop]);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@publish(null, "set", "Secondary Data View (e.g. graph edges)", function (this: Visualization) { return this.visualizationIDs(); }, { optional: true })
|
|
102
|
+
secondaryDataviewID: publish<this, string>;
|
|
103
|
+
secondaryDataviewID_exists: () => boolean;
|
|
104
|
+
secondaryDataviewID_valid: () => boolean;
|
|
105
|
+
|
|
106
|
+
@publish(null, "widget", "Mappings", undefined, { render: false, internal: true })
|
|
107
|
+
mappings: publish<this, Mappings>;
|
|
108
|
+
@publish([], "widget", "Widget")
|
|
109
|
+
_chartPanel: VizChartPanel;
|
|
110
|
+
chartPanel(): VizChartPanel;
|
|
111
|
+
chartPanel(_: VizChartPanel): this;
|
|
112
|
+
chartPanel(_?: VizChartPanel): VizChartPanel | this {
|
|
113
|
+
if (!arguments.length) return this._chartPanel;
|
|
114
|
+
this._chartPanel = _;
|
|
115
|
+
this._chartPanel
|
|
116
|
+
.on("click", (row: any, col: string, sel: boolean, more) => this.click(row, col, sel, more))
|
|
117
|
+
.on("vertex_click", (row: any, col: string, sel: boolean) => this.vertex_click(row, col, sel))
|
|
118
|
+
;
|
|
119
|
+
for (const key in VizTypeMap) {
|
|
120
|
+
if (this._chartPanel.widget() instanceof VizTypeMap[key]) {
|
|
121
|
+
this._chartType = key as VizType;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return this;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
protected _hipiePipeline: HipiePipeline;
|
|
129
|
+
constructor(protected _ec: ElementContainer, hipiePipeline: HipiePipeline) {
|
|
130
|
+
super();
|
|
131
|
+
this._hipiePipeline = hipiePipeline;
|
|
132
|
+
this.mappings(new Mappings());
|
|
133
|
+
this.chartPanel(new VizChartPanel());
|
|
134
|
+
this.typeChanged();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
visualizationIDs(): string[] {
|
|
138
|
+
return this._ec.elementIDs().filter(id => id !== this.id());
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
_prevChartType;
|
|
142
|
+
typeChanged() {
|
|
143
|
+
if (this._prevChartType !== this._chartType) {
|
|
144
|
+
this._prevChartType = this._chartType;
|
|
145
|
+
this.refreshMappings();
|
|
146
|
+
const chart = typeNew(this._chartType);
|
|
147
|
+
this.chartPanel().widget(chart);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
properties(): DDL2.IWidgetProperties;
|
|
152
|
+
properties(_: DDL2.IWidgetProperties): this;
|
|
153
|
+
properties(_?: DDL2.IWidgetProperties): DDL2.IWidgetProperties | this {
|
|
154
|
+
if (!arguments.length) return this.chartPanel().serialize();
|
|
155
|
+
this.chartPanel().deserialize(_);
|
|
156
|
+
|
|
157
|
+
return this;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
refreshMappings(): this {
|
|
161
|
+
const mappings = this.mappings();
|
|
162
|
+
mappings.sourceActivity(this._hipiePipeline);
|
|
163
|
+
const cfs = mappings.validComputedFields();
|
|
164
|
+
const inFields = mappings.inFields();
|
|
165
|
+
const taken = {};
|
|
166
|
+
mappings.computedFields(typeInputs(this._chartType).map((input, idx) => {
|
|
167
|
+
let retVal: MultiField | ComputedField = cfs[idx];
|
|
168
|
+
if (retVal) {
|
|
169
|
+
if (retVal instanceof MultiField) {
|
|
170
|
+
} else {
|
|
171
|
+
retVal.label(input.id);
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
if (input.multi) {
|
|
175
|
+
retVal = new MultiField()
|
|
176
|
+
.owner(mappings)
|
|
177
|
+
.label(input.id)
|
|
178
|
+
;
|
|
179
|
+
const computedFields: ComputedField[] = [];
|
|
180
|
+
for (const inField of inFields) {
|
|
181
|
+
if ((input.type === "any" || input.type === inField.type) && !taken[inField.id]) {
|
|
182
|
+
taken[inField.id] = true;
|
|
183
|
+
computedFields.push(new ComputedField()
|
|
184
|
+
.label(inField.id)
|
|
185
|
+
.type("=")
|
|
186
|
+
.column1(inField.id)
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
retVal.multiFields(computedFields);
|
|
191
|
+
} else {
|
|
192
|
+
retVal = new ComputedField()
|
|
193
|
+
.owner(mappings)
|
|
194
|
+
.label(input.id)
|
|
195
|
+
.type("=")
|
|
196
|
+
;
|
|
197
|
+
for (const inField of inFields) {
|
|
198
|
+
if ((input.type === "any" || input.type === inField.type) && !taken[inField.id]) {
|
|
199
|
+
taken[inField.id] = true;
|
|
200
|
+
retVal.column1(inField.id);
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return retVal;
|
|
207
|
+
}));
|
|
208
|
+
return this;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
_prevFields: ReadonlyArray<DDL2.IField> = [];
|
|
212
|
+
_prevLinkFields: ReadonlyArray<DDL2.IField> = [];
|
|
213
|
+
_prevData: ReadonlyArray<object> = [];
|
|
214
|
+
refreshData(): Promise<void> {
|
|
215
|
+
const mappings = this.mappings();
|
|
216
|
+
|
|
217
|
+
const fields = mappings.outFields();
|
|
218
|
+
const dbFields = this.toDBFields(fields);
|
|
219
|
+
let linkFields: ReadonlyArray<DDL2.IField>;
|
|
220
|
+
let dbLinkFields = [];
|
|
221
|
+
const se = this._ec.element(this.secondaryDataviewID());
|
|
222
|
+
if (se) {
|
|
223
|
+
linkFields = se.mappings().outFields();
|
|
224
|
+
dbLinkFields = this.toDBFields(linkFields);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const fieldsChanged = this._prevFields !== fields || this._prevLinkFields !== linkFields;
|
|
228
|
+
if (fieldsChanged) {
|
|
229
|
+
this._prevFields = fields;
|
|
230
|
+
if (this.chartType() === "DataGraph") {
|
|
231
|
+
const dataGraph = this.chartPanel().widget() as DataGraph;
|
|
232
|
+
dataGraph.vertexColumns(dbFields.map(f => f.label()));
|
|
233
|
+
dataGraph.edgeColumns(dbLinkFields.map(f => f.label()));
|
|
234
|
+
} else {
|
|
235
|
+
this.chartPanel().fields(dbFields.filter(f => f.id() !== "__lparam"));
|
|
236
|
+
}
|
|
237
|
+
} else {
|
|
238
|
+
console.warn(`***${this.id()} Immutable Fields***`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const data = mappings.outData();
|
|
242
|
+
const dataChanged = this._prevData !== data;
|
|
243
|
+
if (dataChanged) {
|
|
244
|
+
this._prevData = data;
|
|
245
|
+
const mappedData = this.toDBData(dbFields, data);
|
|
246
|
+
if (this.chartType() === "DataGraph") {
|
|
247
|
+
const dataGraph = this.chartPanel().widget() as DataGraph;
|
|
248
|
+
dataGraph.vertices(mappedData);
|
|
249
|
+
if (se) {
|
|
250
|
+
const linkData = se.mappings().outData();
|
|
251
|
+
const mappedLinkData = this.toDBData(dbLinkFields, linkData);
|
|
252
|
+
dataGraph.edges(mappedLinkData);
|
|
253
|
+
}
|
|
254
|
+
} else {
|
|
255
|
+
this.chartPanel().data(mappedData);
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
console.warn(`${this.id()} Immutable Data!`);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (fieldsChanged || dataChanged) {
|
|
262
|
+
return this.chartPanel().renderPromise().then(() => { });
|
|
263
|
+
}
|
|
264
|
+
return Promise.resolve();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
private fieldTypeTodbFieldType(type: DDL2.IFieldType): Database.FieldType {
|
|
268
|
+
switch (type) {
|
|
269
|
+
case "dataset":
|
|
270
|
+
return "nested";
|
|
271
|
+
case "boolean":
|
|
272
|
+
return "boolean";
|
|
273
|
+
case "number":
|
|
274
|
+
return "number";
|
|
275
|
+
case "string":
|
|
276
|
+
default:
|
|
277
|
+
return "string";
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
toDBFields(fields: ReadonlyArray<DDL2.IField>): Database.Field[] {
|
|
282
|
+
const retVal: Database.Field[] = [];
|
|
283
|
+
for (const field of fields || []) {
|
|
284
|
+
const f = new Database.Field()
|
|
285
|
+
.type(this.fieldTypeTodbFieldType(field.type))
|
|
286
|
+
.id(field.id)
|
|
287
|
+
.label(field.id)
|
|
288
|
+
;
|
|
289
|
+
switch (field.type) {
|
|
290
|
+
case "dataset":
|
|
291
|
+
f.children(this.toDBFields(field.children));
|
|
292
|
+
break;
|
|
293
|
+
case "object":
|
|
294
|
+
// TODO: For __lparam we should do nothing - not 100% if that is correct for "real" data (we don't really support "object" anyway)?
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
retVal.push(f);
|
|
298
|
+
}
|
|
299
|
+
return retVal;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
toDBData(fields: Database.Field[], data: ReadonlyArray<object> | Readonly<object>) {
|
|
303
|
+
const _data: ReadonlyArray<object> = isArray(data) ? data : [data];
|
|
304
|
+
return _data.map((row: any) => {
|
|
305
|
+
const retVal = [];
|
|
306
|
+
for (const field of fields) {
|
|
307
|
+
if (field.type() === "nested") {
|
|
308
|
+
retVal.push(this.toDBData(field.children() as Database.Field[], row[field.id()].Row || row[field.id()]));
|
|
309
|
+
} else {
|
|
310
|
+
retVal.push(row[field.label()]);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return retVal;
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
exec(): Promise<void[]> {
|
|
318
|
+
const promises = [];
|
|
319
|
+
if (this.secondaryDataviewID_exists()) {
|
|
320
|
+
const secondaryElementID = this.secondaryDataviewID();
|
|
321
|
+
const secondaryElement = this._ec.element(secondaryElementID);
|
|
322
|
+
if (secondaryElement) {
|
|
323
|
+
promises.push(secondaryElement.visualization().exec());
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const mappings = this.mappings();
|
|
328
|
+
mappings.sourceActivity(this._hipiePipeline);
|
|
329
|
+
promises.push(mappings.refreshMeta().then(() => {
|
|
330
|
+
return mappings.exec();
|
|
331
|
+
}));
|
|
332
|
+
|
|
333
|
+
return Promise.all(promises);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
refresh(): Promise<void> {
|
|
337
|
+
this.chartPanel().startProgress && this.chartPanel().startProgress();
|
|
338
|
+
return this.exec().then(() => {
|
|
339
|
+
this.chartPanel().finishProgress && this.chartPanel().finishProgress();
|
|
340
|
+
return this.refreshData();
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Events ---
|
|
345
|
+
click(row: any, col: string, sel: boolean, more?) {
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
vertex_click(row: any, col: string, sel: boolean) {
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
Visualization.prototype._class += " Visualization";
|