@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.
Files changed (55) hide show
  1. package/LICENSE +43 -43
  2. package/dist/index.es6.js +25 -13
  3. package/dist/index.es6.js.map +1 -1
  4. package/dist/index.js +25 -13
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.min.js +2 -2
  7. package/dist/index.min.js.map +1 -1
  8. package/package.json +12 -12
  9. package/src/__package__.ts +3 -3
  10. package/src/dashy.css +239 -239
  11. package/src/dashy.ts +521 -521
  12. package/src/ddl1/DDLApi.ts +229 -229
  13. package/src/ddl1/FlyoutButton.ts +120 -120
  14. package/src/ddl1/Graph.ts +93 -93
  15. package/src/ddl1/HTML.ts +77 -77
  16. package/src/ddl1/HipieDDL.ts +2437 -2437
  17. package/src/ddl1/HipieDDLMixin.ts +380 -380
  18. package/src/ddl1/Tabbed.ts +91 -91
  19. package/src/ddl1/TargetMarshaller.ts +57 -57
  20. package/src/ddl2/PopupManager.ts +89 -89
  21. package/src/ddl2/activities/activity.ts +431 -431
  22. package/src/ddl2/activities/databomb.ts +237 -237
  23. package/src/ddl2/activities/datasource.ts +52 -52
  24. package/src/ddl2/activities/dspicker.ts +106 -106
  25. package/src/ddl2/activities/filter.ts +542 -542
  26. package/src/ddl2/activities/form.ts +153 -153
  27. package/src/ddl2/activities/groupby.ts +439 -439
  28. package/src/ddl2/activities/hipiepipeline.ts +114 -114
  29. package/src/ddl2/activities/limit.ts +49 -49
  30. package/src/ddl2/activities/logicalfile.ts +62 -62
  31. package/src/ddl2/activities/nullview.ts +12 -12
  32. package/src/ddl2/activities/project.ts +764 -764
  33. package/src/ddl2/activities/rest.ts +568 -568
  34. package/src/ddl2/activities/roxie.ts +490 -490
  35. package/src/ddl2/activities/sampledata.json +16264 -16264
  36. package/src/ddl2/activities/sort.ts +176 -176
  37. package/src/ddl2/activities/wuresult.ts +395 -395
  38. package/src/ddl2/dashboard.css +13 -13
  39. package/src/ddl2/dashboard.ts +330 -330
  40. package/src/ddl2/dashboardDockPanel.ts +123 -123
  41. package/src/ddl2/dashboardGrid.ts +202 -202
  42. package/src/ddl2/ddl.ts +410 -410
  43. package/src/ddl2/ddleditor.ts +60 -60
  44. package/src/ddl2/dsTable.ts +238 -238
  45. package/src/ddl2/dvTable.ts +31 -31
  46. package/src/ddl2/graphadapter.ts +297 -297
  47. package/src/ddl2/javascriptadapter.ts +354 -354
  48. package/src/ddl2/model/element.ts +398 -398
  49. package/src/ddl2/model/visualization.ts +351 -351
  50. package/src/ddl2/model/vizChartPanel.ts +149 -149
  51. package/src/ddl2/pipelinePanel.css +4 -4
  52. package/src/ddl2/pipelinePanel.ts +465 -465
  53. package/src/index.ts +26 -26
  54. package/types/__package__.d.ts +2 -2
  55. package/types-3.4/__package__.d.ts +2 -2
@@ -1,542 +1,542 @@
1
- import { PropertyExt, publish } from "@hpcc-js/common";
2
- import { DDL2 } from "@hpcc-js/ddl-shim";
3
- import { hashSum } from "@hpcc-js/util";
4
- import { Element, ElementContainer } from "../model/element";
5
- import { Activity, IActivityError, ReferencedFields } from "./activity";
6
-
7
- function createFilter(condition: DDL2.IMappingConditionType, lf: string, val: string | number): (localRow: any) => boolean {
8
- const isString = typeof val === "string";
9
- switch (condition) {
10
- case "==":
11
- return (localRow) => isString && typeof localRow[lf] === "string" ? localRow[lf].trim() === val : localRow[lf] === val;
12
- case "!=":
13
- return (localRow) => isString && typeof localRow[lf] === "string" ? localRow[lf].trim() !== val : localRow[lf] !== val;
14
- case "<":
15
- return (localRow) => localRow[lf] < val;
16
- case "<=":
17
- return (localRow) => localRow[lf] <= val;
18
- case ">":
19
- return (localRow) => localRow[lf] > val;
20
- case ">=":
21
- return (localRow) => localRow[lf] >= val;
22
- default:
23
- throw new Error(`Unknown filter condition: ${condition}`);
24
- }
25
- }
26
-
27
- export class ColumnMapping extends PropertyExt {
28
- private _owner: RemoteFilter;
29
-
30
- @publish(null, "set", "Filter Fields", function (this: ColumnMapping) { return this.sourceOutFields(); }, {
31
- optional: true,
32
- disable: (w: ColumnMapping): boolean => !w._owner.source(),
33
- validate: (w: ColumnMapping): boolean => w.sourceOutFields().indexOf(w.remoteField()) >= 0
34
- })
35
- remoteField: publish<this, string>;
36
- remoteField_exists: () => boolean;
37
- remoteField_valid: () => boolean;
38
- @publish(null, "set", "Local Fields", function (this: ColumnMapping) { return this.localFields(); }, {
39
- optional: true,
40
- disable: (w: ColumnMapping): boolean => !w._owner.source(),
41
- validate: (w: ColumnMapping): boolean => w.localFields().indexOf(w.localField()) >= 0
42
- })
43
- localField: publish<this, string>;
44
- localField_exists: () => boolean;
45
- localField_valid: () => boolean;
46
- @publish("==", "set", "Filter Fields", ["==", "!=", ">", ">=", "<", "<=", "range", "in"])
47
- condition: publish<this, DDL2.IMappingConditionType>;
48
- @publish(false, "boolean", "Ignore null filters")
49
- nullable: publish<this, boolean>;
50
-
51
- validate(prefix: string): IActivityError[] {
52
- const retVal: IActivityError[] = [];
53
- if (!this.remoteField_valid()) {
54
- retVal.push({
55
- source: `${prefix}.remoteField`,
56
- msg: `Invalid remoteField: "${this.remoteField()}"`,
57
- hint: `expected: ${JSON.stringify(this.sourceOutFields())}`
58
- });
59
- }
60
- if (!this.localField_valid()) {
61
- retVal.push({
62
- source: `${prefix}.localField`,
63
- msg: `Invalid localField: "${this.localField()}"`,
64
- hint: `expected: ${JSON.stringify(this.localFields())}`
65
- });
66
- }
67
- return retVal;
68
- }
69
-
70
- constructor() {
71
- super();
72
- }
73
-
74
- owner(): RemoteFilter;
75
- owner(_: RemoteFilter): this;
76
- owner(_?: RemoteFilter): RemoteFilter | this {
77
- if (!arguments.length) return this._owner;
78
- this._owner = _;
79
- return this;
80
- }
81
-
82
- valid(): boolean {
83
- return this.localField_exists() || this.remoteField_exists();
84
- }
85
-
86
- toDDL(): DDL2.IMapping {
87
- return {
88
- remoteFieldID: this.remoteField(),
89
- localFieldID: this.localField(),
90
- condition: this.condition(),
91
- nullable: this.nullable()
92
- };
93
- }
94
-
95
- fromDDL(ddl: DDL2.IMapping): this {
96
- return this
97
- .remoteField(ddl.remoteFieldID)
98
- .localField(ddl.localFieldID)
99
- .condition(ddl.condition)
100
- .nullable(ddl.nullable)
101
- ;
102
- }
103
-
104
- static fromDDL(ddl: DDL2.IMapping): ColumnMapping {
105
- return new ColumnMapping().fromDDL(ddl);
106
- }
107
-
108
- hash() {
109
- return hashSum({
110
- remoteField: this.remoteField(),
111
- localField: this.localField(),
112
- condition: this.condition(),
113
- nullable: this.nullable()
114
- });
115
- }
116
-
117
- localFields(): string[] {
118
- return this._owner.inFields().map(field => field.id);
119
- }
120
-
121
- sourceOutFields(): string[] {
122
- return this._owner.sourceOutFields().map(field => field.id);
123
- }
124
-
125
- remoteValues(filterSelection: any[]): Array<number | string> {
126
- const rf = this.remoteField();
127
- return filterSelection.map(sel => {
128
- const retVal = sel[rf];
129
- if (typeof retVal === "string") {
130
- return retVal.trim();
131
- }
132
- return retVal;
133
- });
134
- }
135
-
136
- createFilterDescription(filterSelection: any[]): string {
137
- switch (this.condition()) {
138
- case "in":
139
- case "range":
140
- return `${this.localField()} ${this.condition()} [${this.remoteValues(filterSelection).join(", ")}]`;
141
- default:
142
- return `${this.localField()} ${this.condition()} ${this.remoteValues(filterSelection)[0]}`;
143
- }
144
- }
145
-
146
- createFilter(filterSelection: any[]): (localRow: any) => boolean {
147
- const lf = this.localField();
148
- const fsArr = this.remoteValues(filterSelection);
149
- switch (this.condition()) {
150
- case "range":
151
- if (this.nullable() && (fsArr.length < 2 || fsArr[0] === fsArr[1])) {
152
- return (localRow) => true;
153
- }
154
- return (localRow) => localRow[lf] >= fsArr[0] && localRow[lf] <= fsArr[1];
155
- case "in":
156
- if (this.nullable() && fsArr.length === 0) {
157
- return (localRow) => true;
158
- }
159
- return (localRow) => fsArr.some(fs => typeof localRow[lf] === "string" ? localRow[lf].trim() === fs : localRow[lf] === fs);
160
- default:
161
- const fs0 = fsArr[0];
162
- if (this.nullable() && (fs0 === undefined || fs0 === null || fs0 === "")) {
163
- return (localRow) => true;
164
- }
165
- return createFilter(this.condition(), lf, fs0);
166
- }
167
- }
168
- }
169
- ColumnMapping.prototype._class += " ColumnMapping";
170
-
171
- export class RemoteFilter extends PropertyExt {
172
- private _owner: Filters;
173
-
174
- @publish(null, "set", "Activity", function (this: RemoteFilter) { return this.visualizationIDs(); }, {
175
- optional: true,
176
- validate: (w: RemoteFilter): boolean => w.visualizationIDs().indexOf(w.source()) >= 0
177
- })
178
- source: publish<this, string>;
179
- source_exists: () => boolean;
180
- source_valid: () => boolean;
181
- @publish([], "propertyArray", "Mappings", null, { autoExpand: ColumnMapping })
182
- mappings: publish<this, ColumnMapping[]>;
183
-
184
- validate(prefix: string): IActivityError[] {
185
- let retVal: IActivityError[] = [];
186
- if (!this.source_valid()) {
187
- retVal.push({
188
- source: `${prefix}.source.${this.source()}`,
189
- msg: `Invalid source: "${this.source()}"`,
190
- hint: `expected: ${JSON.stringify(this.visualizationIDs())}`
191
- });
192
- }
193
- if (this.source_exists() && this.validMappings().length === 0) {
194
- retVal.push({
195
- source: `${prefix}.source.${this.source()}`,
196
- msg: `Invalid mappings: "${this.source()}"`,
197
- hint: "expected minimum of 1 mapping"
198
- });
199
- }
200
- for (const mapping of this.validMappings()) {
201
- retVal = retVal.concat(mapping.validate(`${prefix}.${this.source()}.mappings`));
202
- }
203
- return retVal;
204
- }
205
-
206
- constructor() {
207
- super();
208
- }
209
-
210
- owner(): Filters;
211
- owner(_: Filters): this;
212
- owner(_?: Filters): Filters | this {
213
- if (!arguments.length) return this._owner;
214
- this._owner = _;
215
- return this;
216
- }
217
-
218
- valid(): boolean {
219
- return !!this.source() && this.validMappings().length > 0;
220
- }
221
-
222
- toDDL(): DDL2.IFilterCondition {
223
- return {
224
- viewID: this.source(),
225
- mappings: this.ddlMappings()
226
- };
227
- }
228
-
229
- fromDDL(ddl: DDL2.IFilterCondition): this {
230
- return this
231
- .source(ddl.viewID)
232
- .ddlMappings(ddl.mappings)
233
- ;
234
- }
235
-
236
- static fromDDL(ddl: DDL2.IFilterCondition): RemoteFilter {
237
- return new RemoteFilter().fromDDL(ddl);
238
- }
239
-
240
- ddlMappings(): DDL2.IMapping[];
241
- ddlMappings(_: DDL2.IMapping[]): this;
242
- ddlMappings(_?: DDL2.IMapping[]): DDL2.IMapping[] | this {
243
- if (!arguments.length) return this.validMappings().map(mapping => mapping.toDDL());
244
- this.mappings(_.map(mapping => ColumnMapping.fromDDL(mapping)));
245
- return this;
246
- }
247
-
248
- visualizationIDs() {
249
- return this._owner.visualizationIDs();
250
- }
251
-
252
- hash(): string {
253
- return hashSum({
254
- source: this.source(),
255
- mappings: this.validMappings().map(mapping => mapping.hash()),
256
- selection: this.sourceSelection()
257
- });
258
- }
259
-
260
- validMappings(): ColumnMapping[] {
261
- return this.mappings().filter(mapping => mapping.valid());
262
- }
263
-
264
- appendMappings(mappings: Array<{ remoteField: string, localField: string, condition: DDL2.IMappingConditionType }>): this {
265
- for (const mapping of mappings) {
266
- this.mappings().push(new ColumnMapping()
267
- .owner(this)
268
- .remoteField(mapping.remoteField)
269
- .localField(mapping.localField)
270
- .condition(mapping.condition)
271
- );
272
- }
273
- return this;
274
- }
275
-
276
- inFields(): ReadonlyArray<DDL2.IField> {
277
- return this._owner.inFields();
278
- }
279
-
280
- sourceViz(): Element {
281
- return this._owner.visualization(this.source());
282
- }
283
-
284
- sourceOutFields(): ReadonlyArray<DDL2.IField> {
285
- return this.sourceViz().hipiePipeline().selectionFields();
286
- }
287
-
288
- sourceSelection(): any[] {
289
- return this.sourceViz().selection();
290
- }
291
-
292
- createFilter(): (localRow: any) => boolean {
293
- const selection = this.sourceSelection();
294
- const mappingFilters = this.validMappings().map(mapping => mapping.createFilter(selection));
295
- return (row: object): boolean => mappingFilters.every(mappingFilter => mappingFilter(row));
296
- }
297
-
298
- createFilterDescription(): string {
299
- const selection = this.sourceSelection();
300
- const mappingFilterDescs = this.validMappings().map(mapping => mapping.createFilterDescription(selection));
301
- return mappingFilterDescs.join(", ");
302
- }
303
- }
304
- RemoteFilter.prototype._class += " Filter";
305
-
306
- export class StaticFilter extends PropertyExt {
307
- private _owner: Filters;
308
-
309
- @publish(null, "set", "Local Fields", function (this: ColumnMapping) { return this.localFields(); }, {
310
- optional: true,
311
- validate: (w: StaticFilter): boolean => w.localFields().indexOf(w.localField()) >= 0
312
- })
313
- localField: publish<this, string>;
314
- localField_exists: () => boolean;
315
- localField_valid: () => boolean;
316
- @publish("==", "set", "Filter Fields", ["==", "!=", ">", ">=", "<", "<="])
317
- condition: publish<this, DDL2.IMappingConditionType>;
318
- @publish("", "any", "Static Value")
319
- value: publish<this, string | number | boolean>;
320
- value_exists: () => boolean;
321
- value_valid: () => boolean;
322
- @publish("number", "set", "Static Value Type", ["number", "string"])
323
- valueType: publish<this, "number" | "string">;
324
-
325
- validate(prefix: string): IActivityError[] {
326
- const retVal: IActivityError[] = [];
327
- if (!this.localField_valid()) {
328
- retVal.push({
329
- source: `${prefix}.localField`,
330
- msg: `Invalid localField: "${this.localField()}"`,
331
- hint: `expected: ${JSON.stringify(this.localFields())}`
332
- });
333
- }
334
- return retVal;
335
- }
336
-
337
- constructor() {
338
- super();
339
- }
340
-
341
- owner(): Filters;
342
- owner(_: Filters): this;
343
- owner(_?: Filters): Filters | this {
344
- if (!arguments.length) return this._owner;
345
- this._owner = _;
346
- return this;
347
- }
348
-
349
- coerceValue(): string | number;
350
- coerceValue(_: string | number): this;
351
- coerceValue(_?: string | number): string | number | this {
352
- if (arguments.length === 0) {
353
- switch (this.valueType()) {
354
- case "number":
355
- return +this.value();
356
- case "string":
357
- default:
358
- return "" + this.value();
359
- }
360
- }
361
- this.value(_);
362
- if (typeof _ === "number") {
363
- this.valueType("number");
364
- } else {
365
- this.valueType("string");
366
- }
367
- return this;
368
- }
369
-
370
- valid(): boolean {
371
- return this.localField_exists() && this.value_exists();
372
- }
373
-
374
- toDDL(): DDL2.IFilterStaticCondition {
375
- return {
376
- localFieldID: this.localField(),
377
- condition: this.condition(),
378
- value: this.coerceValue()
379
- };
380
- }
381
-
382
- fromDDL(ddl: DDL2.IFilterStaticCondition): this {
383
- return this
384
- .localField(ddl.localFieldID)
385
- .condition(ddl.condition)
386
- .coerceValue(ddl.value)
387
- ;
388
- }
389
-
390
- static fromDDL(ddl: DDL2.IFilterStaticCondition): StaticFilter {
391
- return new StaticFilter().fromDDL(ddl);
392
- }
393
-
394
- hash() {
395
- return hashSum({
396
- localField: this.localField(),
397
- condition: this.condition(),
398
- value: this.value(),
399
- valueType: this.valueType()
400
- });
401
- }
402
-
403
- localFields(): string[] {
404
- return this._owner.inFields().map(field => field.id);
405
- }
406
-
407
- createFilterDescription(): string {
408
- return `${this.localField()} ${this.condition()} ${this.coerceValue()}`;
409
- }
410
-
411
- createFilter(): (localRow: any) => boolean {
412
- return createFilter(this.condition(), this.localField(), this.coerceValue());
413
- }
414
- }
415
- StaticFilter.prototype._class += " StaticFilter";
416
-
417
- type FilterT = RemoteFilter | StaticFilter;
418
-
419
- export class Filters extends Activity {
420
- static Filter = RemoteFilter;
421
- static Mapping = ColumnMapping;
422
-
423
- @publish([], "propertyArray", "Remote Filter", null, { autoExpand: RemoteFilter })
424
- remoteFilter: publish<this, RemoteFilter[]>;
425
-
426
- @publish([], "propertyArray", "Static Filter", null, { autoExpand: StaticFilter })
427
- staticFilter: publish<this, StaticFilter[]>;
428
-
429
- validate(): IActivityError[] {
430
- let retVal: IActivityError[] = [];
431
- for (const filter of this.validFilters()) {
432
- retVal = retVal.concat(filter.validate("filter"));
433
- }
434
- return retVal;
435
- }
436
-
437
- constructor(private _ec: ElementContainer) {
438
- super();
439
- }
440
-
441
- toDDL(): DDL2.IFilter {
442
- return {
443
- type: "filter",
444
- conditions: this.conditions()
445
- };
446
- }
447
-
448
- fromDDL(ddl: DDL2.IFilter): this {
449
- return this
450
- .conditions(ddl.conditions)
451
- ;
452
- }
453
-
454
- static fromDDL(ec: ElementContainer, ddl: DDL2.IFilter): Filters {
455
- return new Filters(ec).fromDDL(ddl);
456
- }
457
-
458
- conditions(): DDL2.FilterCondition[];
459
- conditions(_: DDL2.FilterCondition[]): this;
460
- conditions(_?: DDL2.FilterCondition[]): DDL2.FilterCondition[] | this {
461
- if (!arguments.length) return this.validFilters().map(filter => filter.toDDL());
462
- const remoteFilters: RemoteFilter[] = [];
463
- const staticFilters: StaticFilter[] = [];
464
- _.forEach(fc => {
465
- if (DDL2.isIFilterCondition(fc)) {
466
- remoteFilters.push(RemoteFilter.fromDDL(fc));
467
- } else {
468
- staticFilters.push(StaticFilter.fromDDL(fc));
469
- }
470
- });
471
- this.remoteFilter(remoteFilters);
472
- this.staticFilter(staticFilters);
473
- return this;
474
- }
475
-
476
- visualizationIDs(): string[] {
477
- return this._ec.elementIDs();
478
- }
479
-
480
- visualization(sourceID: string | PropertyExt): Element {
481
- return this._ec.element(sourceID);
482
- }
483
-
484
- // Activity overrides ---
485
- hash(): string {
486
- return hashSum(this.validFilters().map(f => {
487
- return {
488
- filter: f.hash()
489
- };
490
- }));
491
- }
492
-
493
- exists(): boolean {
494
- return this.validFilters().length > 0;
495
- }
496
-
497
- updatedBy(): string[] {
498
- return this.validRemoteFilters().map(filter => filter.source());
499
- }
500
-
501
- referencedFields(refs: ReferencedFields): void {
502
- super.referencedFields(refs);
503
- const localFieldIDs: string[] = [];
504
- for (const filter of this.validRemoteFilters()) {
505
- const filterSource = filter.sourceViz().hipiePipeline();
506
- const remoteFieldIDs: string[] = [];
507
- for (const mapping of filter.validMappings()) {
508
- localFieldIDs.push(mapping.localField());
509
- remoteFieldIDs.push(mapping.remoteField());
510
- }
511
- filterSource.resolveFields(refs, remoteFieldIDs);
512
- }
513
- super.resolveInFields(refs, localFieldIDs);
514
- }
515
-
516
- exec(): Promise<void> {
517
- return super.exec();
518
- }
519
-
520
- computeData(): ReadonlyArray<object> {
521
- const data = super.computeData();
522
- if (data.length === 0 || !this.exists()) return data;
523
- const filters = this.validFilters().map(filter => filter.createFilter());
524
- return data.filter(row => {
525
- return filters.every(filter => filter(row));
526
- });
527
- }
528
-
529
- // --- --- ---
530
- validRemoteFilters(): RemoteFilter[] {
531
- return this.remoteFilter().filter(filter => filter.valid());
532
- }
533
-
534
- validStaticFilters(): StaticFilter[] {
535
- return this.staticFilter().filter(filter => filter.valid());
536
- }
537
-
538
- validFilters(): FilterT[] {
539
- return [...this.validRemoteFilters(), ...this.validStaticFilters()];
540
- }
541
- }
542
- Filters.prototype._class += " Filters";
1
+ import { PropertyExt, publish } from "@hpcc-js/common";
2
+ import { DDL2 } from "@hpcc-js/ddl-shim";
3
+ import { hashSum } from "@hpcc-js/util";
4
+ import { Element, ElementContainer } from "../model/element";
5
+ import { Activity, IActivityError, ReferencedFields } from "./activity";
6
+
7
+ function createFilter(condition: DDL2.IMappingConditionType, lf: string, val: string | number): (localRow: any) => boolean {
8
+ const isString = typeof val === "string";
9
+ switch (condition) {
10
+ case "==":
11
+ return (localRow) => isString && typeof localRow[lf] === "string" ? localRow[lf].trim() === val : localRow[lf] === val;
12
+ case "!=":
13
+ return (localRow) => isString && typeof localRow[lf] === "string" ? localRow[lf].trim() !== val : localRow[lf] !== val;
14
+ case "<":
15
+ return (localRow) => localRow[lf] < val;
16
+ case "<=":
17
+ return (localRow) => localRow[lf] <= val;
18
+ case ">":
19
+ return (localRow) => localRow[lf] > val;
20
+ case ">=":
21
+ return (localRow) => localRow[lf] >= val;
22
+ default:
23
+ throw new Error(`Unknown filter condition: ${condition}`);
24
+ }
25
+ }
26
+
27
+ export class ColumnMapping extends PropertyExt {
28
+ private _owner: RemoteFilter;
29
+
30
+ @publish(null, "set", "Filter Fields", function (this: ColumnMapping) { return this.sourceOutFields(); }, {
31
+ optional: true,
32
+ disable: (w: ColumnMapping): boolean => !w._owner.source(),
33
+ validate: (w: ColumnMapping): boolean => w.sourceOutFields().indexOf(w.remoteField()) >= 0
34
+ })
35
+ remoteField: publish<this, string>;
36
+ remoteField_exists: () => boolean;
37
+ remoteField_valid: () => boolean;
38
+ @publish(null, "set", "Local Fields", function (this: ColumnMapping) { return this.localFields(); }, {
39
+ optional: true,
40
+ disable: (w: ColumnMapping): boolean => !w._owner.source(),
41
+ validate: (w: ColumnMapping): boolean => w.localFields().indexOf(w.localField()) >= 0
42
+ })
43
+ localField: publish<this, string>;
44
+ localField_exists: () => boolean;
45
+ localField_valid: () => boolean;
46
+ @publish("==", "set", "Filter Fields", ["==", "!=", ">", ">=", "<", "<=", "range", "in"])
47
+ condition: publish<this, DDL2.IMappingConditionType>;
48
+ @publish(false, "boolean", "Ignore null filters")
49
+ nullable: publish<this, boolean>;
50
+
51
+ validate(prefix: string): IActivityError[] {
52
+ const retVal: IActivityError[] = [];
53
+ if (!this.remoteField_valid()) {
54
+ retVal.push({
55
+ source: `${prefix}.remoteField`,
56
+ msg: `Invalid remoteField: "${this.remoteField()}"`,
57
+ hint: `expected: ${JSON.stringify(this.sourceOutFields())}`
58
+ });
59
+ }
60
+ if (!this.localField_valid()) {
61
+ retVal.push({
62
+ source: `${prefix}.localField`,
63
+ msg: `Invalid localField: "${this.localField()}"`,
64
+ hint: `expected: ${JSON.stringify(this.localFields())}`
65
+ });
66
+ }
67
+ return retVal;
68
+ }
69
+
70
+ constructor() {
71
+ super();
72
+ }
73
+
74
+ owner(): RemoteFilter;
75
+ owner(_: RemoteFilter): this;
76
+ owner(_?: RemoteFilter): RemoteFilter | this {
77
+ if (!arguments.length) return this._owner;
78
+ this._owner = _;
79
+ return this;
80
+ }
81
+
82
+ valid(): boolean {
83
+ return this.localField_exists() || this.remoteField_exists();
84
+ }
85
+
86
+ toDDL(): DDL2.IMapping {
87
+ return {
88
+ remoteFieldID: this.remoteField(),
89
+ localFieldID: this.localField(),
90
+ condition: this.condition(),
91
+ nullable: this.nullable()
92
+ };
93
+ }
94
+
95
+ fromDDL(ddl: DDL2.IMapping): this {
96
+ return this
97
+ .remoteField(ddl.remoteFieldID)
98
+ .localField(ddl.localFieldID)
99
+ .condition(ddl.condition)
100
+ .nullable(ddl.nullable)
101
+ ;
102
+ }
103
+
104
+ static fromDDL(ddl: DDL2.IMapping): ColumnMapping {
105
+ return new ColumnMapping().fromDDL(ddl);
106
+ }
107
+
108
+ hash() {
109
+ return hashSum({
110
+ remoteField: this.remoteField(),
111
+ localField: this.localField(),
112
+ condition: this.condition(),
113
+ nullable: this.nullable()
114
+ });
115
+ }
116
+
117
+ localFields(): string[] {
118
+ return this._owner.inFields().map(field => field.id);
119
+ }
120
+
121
+ sourceOutFields(): string[] {
122
+ return this._owner.sourceOutFields().map(field => field.id);
123
+ }
124
+
125
+ remoteValues(filterSelection: any[]): Array<number | string> {
126
+ const rf = this.remoteField();
127
+ return filterSelection.map(sel => {
128
+ const retVal = sel[rf];
129
+ if (typeof retVal === "string") {
130
+ return retVal.trim();
131
+ }
132
+ return retVal;
133
+ });
134
+ }
135
+
136
+ createFilterDescription(filterSelection: any[]): string {
137
+ switch (this.condition()) {
138
+ case "in":
139
+ case "range":
140
+ return `${this.localField()} ${this.condition()} [${this.remoteValues(filterSelection).join(", ")}]`;
141
+ default:
142
+ return `${this.localField()} ${this.condition()} ${this.remoteValues(filterSelection)[0]}`;
143
+ }
144
+ }
145
+
146
+ createFilter(filterSelection: any[]): (localRow: any) => boolean {
147
+ const lf = this.localField();
148
+ const fsArr = this.remoteValues(filterSelection);
149
+ switch (this.condition()) {
150
+ case "range":
151
+ if (this.nullable() && (fsArr.length < 2 || fsArr[0] === fsArr[1])) {
152
+ return (localRow) => true;
153
+ }
154
+ return (localRow) => localRow[lf] >= fsArr[0] && localRow[lf] <= fsArr[1];
155
+ case "in":
156
+ if (this.nullable() && fsArr.length === 0) {
157
+ return (localRow) => true;
158
+ }
159
+ return (localRow) => fsArr.some(fs => typeof localRow[lf] === "string" ? localRow[lf].trim() === fs : localRow[lf] === fs);
160
+ default:
161
+ const fs0 = fsArr[0];
162
+ if (this.nullable() && (fs0 === undefined || fs0 === null || fs0 === "")) {
163
+ return (localRow) => true;
164
+ }
165
+ return createFilter(this.condition(), lf, fs0);
166
+ }
167
+ }
168
+ }
169
+ ColumnMapping.prototype._class += " ColumnMapping";
170
+
171
+ export class RemoteFilter extends PropertyExt {
172
+ private _owner: Filters;
173
+
174
+ @publish(null, "set", "Activity", function (this: RemoteFilter) { return this.visualizationIDs(); }, {
175
+ optional: true,
176
+ validate: (w: RemoteFilter): boolean => w.visualizationIDs().indexOf(w.source()) >= 0
177
+ })
178
+ source: publish<this, string>;
179
+ source_exists: () => boolean;
180
+ source_valid: () => boolean;
181
+ @publish([], "propertyArray", "Mappings", null, { autoExpand: ColumnMapping })
182
+ mappings: publish<this, ColumnMapping[]>;
183
+
184
+ validate(prefix: string): IActivityError[] {
185
+ let retVal: IActivityError[] = [];
186
+ if (!this.source_valid()) {
187
+ retVal.push({
188
+ source: `${prefix}.source.${this.source()}`,
189
+ msg: `Invalid source: "${this.source()}"`,
190
+ hint: `expected: ${JSON.stringify(this.visualizationIDs())}`
191
+ });
192
+ }
193
+ if (this.source_exists() && this.validMappings().length === 0) {
194
+ retVal.push({
195
+ source: `${prefix}.source.${this.source()}`,
196
+ msg: `Invalid mappings: "${this.source()}"`,
197
+ hint: "expected minimum of 1 mapping"
198
+ });
199
+ }
200
+ for (const mapping of this.validMappings()) {
201
+ retVal = retVal.concat(mapping.validate(`${prefix}.${this.source()}.mappings`));
202
+ }
203
+ return retVal;
204
+ }
205
+
206
+ constructor() {
207
+ super();
208
+ }
209
+
210
+ owner(): Filters;
211
+ owner(_: Filters): this;
212
+ owner(_?: Filters): Filters | this {
213
+ if (!arguments.length) return this._owner;
214
+ this._owner = _;
215
+ return this;
216
+ }
217
+
218
+ valid(): boolean {
219
+ return !!this.source() && this.validMappings().length > 0;
220
+ }
221
+
222
+ toDDL(): DDL2.IFilterCondition {
223
+ return {
224
+ viewID: this.source(),
225
+ mappings: this.ddlMappings()
226
+ };
227
+ }
228
+
229
+ fromDDL(ddl: DDL2.IFilterCondition): this {
230
+ return this
231
+ .source(ddl.viewID)
232
+ .ddlMappings(ddl.mappings)
233
+ ;
234
+ }
235
+
236
+ static fromDDL(ddl: DDL2.IFilterCondition): RemoteFilter {
237
+ return new RemoteFilter().fromDDL(ddl);
238
+ }
239
+
240
+ ddlMappings(): DDL2.IMapping[];
241
+ ddlMappings(_: DDL2.IMapping[]): this;
242
+ ddlMappings(_?: DDL2.IMapping[]): DDL2.IMapping[] | this {
243
+ if (!arguments.length) return this.validMappings().map(mapping => mapping.toDDL());
244
+ this.mappings(_.map(mapping => ColumnMapping.fromDDL(mapping)));
245
+ return this;
246
+ }
247
+
248
+ visualizationIDs() {
249
+ return this._owner.visualizationIDs();
250
+ }
251
+
252
+ hash(): string {
253
+ return hashSum({
254
+ source: this.source(),
255
+ mappings: this.validMappings().map(mapping => mapping.hash()),
256
+ selection: this.sourceSelection()
257
+ });
258
+ }
259
+
260
+ validMappings(): ColumnMapping[] {
261
+ return this.mappings().filter(mapping => mapping.valid());
262
+ }
263
+
264
+ appendMappings(mappings: Array<{ remoteField: string, localField: string, condition: DDL2.IMappingConditionType }>): this {
265
+ for (const mapping of mappings) {
266
+ this.mappings().push(new ColumnMapping()
267
+ .owner(this)
268
+ .remoteField(mapping.remoteField)
269
+ .localField(mapping.localField)
270
+ .condition(mapping.condition)
271
+ );
272
+ }
273
+ return this;
274
+ }
275
+
276
+ inFields(): ReadonlyArray<DDL2.IField> {
277
+ return this._owner.inFields();
278
+ }
279
+
280
+ sourceViz(): Element {
281
+ return this._owner.visualization(this.source());
282
+ }
283
+
284
+ sourceOutFields(): ReadonlyArray<DDL2.IField> {
285
+ return this.sourceViz().hipiePipeline().selectionFields();
286
+ }
287
+
288
+ sourceSelection(): any[] {
289
+ return this.sourceViz().selection();
290
+ }
291
+
292
+ createFilter(): (localRow: any) => boolean {
293
+ const selection = this.sourceSelection();
294
+ const mappingFilters = this.validMappings().map(mapping => mapping.createFilter(selection));
295
+ return (row: object): boolean => mappingFilters.every(mappingFilter => mappingFilter(row));
296
+ }
297
+
298
+ createFilterDescription(): string {
299
+ const selection = this.sourceSelection();
300
+ const mappingFilterDescs = this.validMappings().map(mapping => mapping.createFilterDescription(selection));
301
+ return mappingFilterDescs.join(", ");
302
+ }
303
+ }
304
+ RemoteFilter.prototype._class += " Filter";
305
+
306
+ export class StaticFilter extends PropertyExt {
307
+ private _owner: Filters;
308
+
309
+ @publish(null, "set", "Local Fields", function (this: ColumnMapping) { return this.localFields(); }, {
310
+ optional: true,
311
+ validate: (w: StaticFilter): boolean => w.localFields().indexOf(w.localField()) >= 0
312
+ })
313
+ localField: publish<this, string>;
314
+ localField_exists: () => boolean;
315
+ localField_valid: () => boolean;
316
+ @publish("==", "set", "Filter Fields", ["==", "!=", ">", ">=", "<", "<="])
317
+ condition: publish<this, DDL2.IMappingConditionType>;
318
+ @publish("", "any", "Static Value")
319
+ value: publish<this, string | number | boolean>;
320
+ value_exists: () => boolean;
321
+ value_valid: () => boolean;
322
+ @publish("number", "set", "Static Value Type", ["number", "string"])
323
+ valueType: publish<this, "number" | "string">;
324
+
325
+ validate(prefix: string): IActivityError[] {
326
+ const retVal: IActivityError[] = [];
327
+ if (!this.localField_valid()) {
328
+ retVal.push({
329
+ source: `${prefix}.localField`,
330
+ msg: `Invalid localField: "${this.localField()}"`,
331
+ hint: `expected: ${JSON.stringify(this.localFields())}`
332
+ });
333
+ }
334
+ return retVal;
335
+ }
336
+
337
+ constructor() {
338
+ super();
339
+ }
340
+
341
+ owner(): Filters;
342
+ owner(_: Filters): this;
343
+ owner(_?: Filters): Filters | this {
344
+ if (!arguments.length) return this._owner;
345
+ this._owner = _;
346
+ return this;
347
+ }
348
+
349
+ coerceValue(): string | number;
350
+ coerceValue(_: string | number): this;
351
+ coerceValue(_?: string | number): string | number | this {
352
+ if (arguments.length === 0) {
353
+ switch (this.valueType()) {
354
+ case "number":
355
+ return +this.value();
356
+ case "string":
357
+ default:
358
+ return "" + this.value();
359
+ }
360
+ }
361
+ this.value(_);
362
+ if (typeof _ === "number") {
363
+ this.valueType("number");
364
+ } else {
365
+ this.valueType("string");
366
+ }
367
+ return this;
368
+ }
369
+
370
+ valid(): boolean {
371
+ return this.localField_exists() && this.value_exists();
372
+ }
373
+
374
+ toDDL(): DDL2.IFilterStaticCondition {
375
+ return {
376
+ localFieldID: this.localField(),
377
+ condition: this.condition(),
378
+ value: this.coerceValue()
379
+ };
380
+ }
381
+
382
+ fromDDL(ddl: DDL2.IFilterStaticCondition): this {
383
+ return this
384
+ .localField(ddl.localFieldID)
385
+ .condition(ddl.condition)
386
+ .coerceValue(ddl.value)
387
+ ;
388
+ }
389
+
390
+ static fromDDL(ddl: DDL2.IFilterStaticCondition): StaticFilter {
391
+ return new StaticFilter().fromDDL(ddl);
392
+ }
393
+
394
+ hash() {
395
+ return hashSum({
396
+ localField: this.localField(),
397
+ condition: this.condition(),
398
+ value: this.value(),
399
+ valueType: this.valueType()
400
+ });
401
+ }
402
+
403
+ localFields(): string[] {
404
+ return this._owner.inFields().map(field => field.id);
405
+ }
406
+
407
+ createFilterDescription(): string {
408
+ return `${this.localField()} ${this.condition()} ${this.coerceValue()}`;
409
+ }
410
+
411
+ createFilter(): (localRow: any) => boolean {
412
+ return createFilter(this.condition(), this.localField(), this.coerceValue());
413
+ }
414
+ }
415
+ StaticFilter.prototype._class += " StaticFilter";
416
+
417
+ type FilterT = RemoteFilter | StaticFilter;
418
+
419
+ export class Filters extends Activity {
420
+ static Filter = RemoteFilter;
421
+ static Mapping = ColumnMapping;
422
+
423
+ @publish([], "propertyArray", "Remote Filter", null, { autoExpand: RemoteFilter })
424
+ remoteFilter: publish<this, RemoteFilter[]>;
425
+
426
+ @publish([], "propertyArray", "Static Filter", null, { autoExpand: StaticFilter })
427
+ staticFilter: publish<this, StaticFilter[]>;
428
+
429
+ validate(): IActivityError[] {
430
+ let retVal: IActivityError[] = [];
431
+ for (const filter of this.validFilters()) {
432
+ retVal = retVal.concat(filter.validate("filter"));
433
+ }
434
+ return retVal;
435
+ }
436
+
437
+ constructor(private _ec: ElementContainer) {
438
+ super();
439
+ }
440
+
441
+ toDDL(): DDL2.IFilter {
442
+ return {
443
+ type: "filter",
444
+ conditions: this.conditions()
445
+ };
446
+ }
447
+
448
+ fromDDL(ddl: DDL2.IFilter): this {
449
+ return this
450
+ .conditions(ddl.conditions)
451
+ ;
452
+ }
453
+
454
+ static fromDDL(ec: ElementContainer, ddl: DDL2.IFilter): Filters {
455
+ return new Filters(ec).fromDDL(ddl);
456
+ }
457
+
458
+ conditions(): DDL2.FilterCondition[];
459
+ conditions(_: DDL2.FilterCondition[]): this;
460
+ conditions(_?: DDL2.FilterCondition[]): DDL2.FilterCondition[] | this {
461
+ if (!arguments.length) return this.validFilters().map(filter => filter.toDDL());
462
+ const remoteFilters: RemoteFilter[] = [];
463
+ const staticFilters: StaticFilter[] = [];
464
+ _.forEach(fc => {
465
+ if (DDL2.isIFilterCondition(fc)) {
466
+ remoteFilters.push(RemoteFilter.fromDDL(fc));
467
+ } else {
468
+ staticFilters.push(StaticFilter.fromDDL(fc));
469
+ }
470
+ });
471
+ this.remoteFilter(remoteFilters);
472
+ this.staticFilter(staticFilters);
473
+ return this;
474
+ }
475
+
476
+ visualizationIDs(): string[] {
477
+ return this._ec.elementIDs();
478
+ }
479
+
480
+ visualization(sourceID: string | PropertyExt): Element {
481
+ return this._ec.element(sourceID);
482
+ }
483
+
484
+ // Activity overrides ---
485
+ hash(): string {
486
+ return hashSum(this.validFilters().map(f => {
487
+ return {
488
+ filter: f.hash()
489
+ };
490
+ }));
491
+ }
492
+
493
+ exists(): boolean {
494
+ return this.validFilters().length > 0;
495
+ }
496
+
497
+ updatedBy(): string[] {
498
+ return this.validRemoteFilters().map(filter => filter.source());
499
+ }
500
+
501
+ referencedFields(refs: ReferencedFields): void {
502
+ super.referencedFields(refs);
503
+ const localFieldIDs: string[] = [];
504
+ for (const filter of this.validRemoteFilters()) {
505
+ const filterSource = filter.sourceViz().hipiePipeline();
506
+ const remoteFieldIDs: string[] = [];
507
+ for (const mapping of filter.validMappings()) {
508
+ localFieldIDs.push(mapping.localField());
509
+ remoteFieldIDs.push(mapping.remoteField());
510
+ }
511
+ filterSource.resolveFields(refs, remoteFieldIDs);
512
+ }
513
+ super.resolveInFields(refs, localFieldIDs);
514
+ }
515
+
516
+ exec(): Promise<void> {
517
+ return super.exec();
518
+ }
519
+
520
+ computeData(): ReadonlyArray<object> {
521
+ const data = super.computeData();
522
+ if (data.length === 0 || !this.exists()) return data;
523
+ const filters = this.validFilters().map(filter => filter.createFilter());
524
+ return data.filter(row => {
525
+ return filters.every(filter => filter(row));
526
+ });
527
+ }
528
+
529
+ // --- --- ---
530
+ validRemoteFilters(): RemoteFilter[] {
531
+ return this.remoteFilter().filter(filter => filter.valid());
532
+ }
533
+
534
+ validStaticFilters(): StaticFilter[] {
535
+ return this.staticFilter().filter(filter => filter.valid());
536
+ }
537
+
538
+ validFilters(): FilterT[] {
539
+ return [...this.validRemoteFilters(), ...this.validStaticFilters()];
540
+ }
541
+ }
542
+ Filters.prototype._class += " Filters";