You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ri...@apache.org on 2020/03/09 22:53:55 UTC

[incubator-streampipes] branch dev updated: STREAMPIPES-98: Improve validation of dashboard widget settings

This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git


The following commit(s) were added to refs/heads/dev by this push:
     new fd2d430  STREAMPIPES-98: Improve validation of dashboard widget settings
fd2d430 is described below

commit fd2d430f2b259de77ee4968fb744442614c4e1ac
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Mon Mar 9 23:53:41 2020 +0100

    STREAMPIPES-98: Improve validation of dashboard widget settings
---
 .../static-color-picker.component.ts                   |  1 +
 .../static-mapping-nary.component.ts                   |  1 +
 .../static-mapping-unary.component.ts                  |  9 +++++++++
 .../static-one-of-input.component.html                 |  2 +-
 .../static-one-of-input.component.ts                   | 18 +++++++++++++++---
 .../dashboard/components/widgets/base/base-config.ts   |  8 ++++++++
 .../app/dashboard/components/widgets/map/map-config.ts |  2 +-
 .../widgets/trafficlight/traffic-light-config.ts       |  4 ++--
 .../add-widget/add-visualization-dialog.component.html |  6 ++++--
 .../add-widget/add-visualization-dialog.component.ts   |  9 +++++++++
 ui/src/app/dashboard/registry/widget-config-builder.ts |  6 ++++--
 .../sdk/extractor/static-property-extractor.ts         | 10 ++++++----
 12 files changed, 61 insertions(+), 15 deletions(-)

diff --git a/ui/src/app/connect/static-properties/static-color-picker/static-color-picker.component.ts b/ui/src/app/connect/static-properties/static-color-picker/static-color-picker.component.ts
index 3c9b1bc..159c256 100644
--- a/ui/src/app/connect/static-properties/static-color-picker/static-color-picker.component.ts
+++ b/ui/src/app/connect/static-properties/static-color-picker/static-color-picker.component.ts
@@ -50,6 +50,7 @@ export class StaticColorPickerComponent implements OnInit {
                 Validators.required
             ]),
         })
+        this.inputEmitter.emit(true);
     }
 
     valueChange(inputValue) {
diff --git a/ui/src/app/connect/static-properties/static-mapping-nary/static-mapping-nary.component.ts b/ui/src/app/connect/static-properties/static-mapping-nary/static-mapping-nary.component.ts
index d278a99..79ef900 100644
--- a/ui/src/app/connect/static-properties/static-mapping-nary/static-mapping-nary.component.ts
+++ b/ui/src/app/connect/static-properties/static-mapping-nary/static-mapping-nary.component.ts
@@ -52,6 +52,7 @@ export class StaticMappingNaryComponent extends StaticMappingComponent implement
         if (!this.staticProperty.selectedProperties) {
             this.staticProperty.selectedProperties = [];
         }
+        this.inputEmitter.emit(true);
     }
 
     selectOption(property: EventProperty, $event) {
diff --git a/ui/src/app/connect/static-properties/static-mapping-unary/static-mapping-unary.component.ts b/ui/src/app/connect/static-properties/static-mapping-unary/static-mapping-unary.component.ts
index 4903750..6a201b0 100644
--- a/ui/src/app/connect/static-properties/static-mapping-unary/static-mapping-unary.component.ts
+++ b/ui/src/app/connect/static-properties/static-mapping-unary/static-mapping-unary.component.ts
@@ -53,17 +53,26 @@ export class StaticMappingUnaryComponent extends StaticMappingComponent implemen
     }
 
     isInSelection(ep: EventProperty): boolean {
+        // TODO this quick-fixes a deserialization bug in Tson-LD
+        if (!Array.isArray(this.staticProperty.mapsFromOptions)) {
+            let value: string = this.staticProperty.mapsFromOptions as any;
+            this.staticProperty.mapsFromOptions = [value];
+        }
         return this.staticProperty.mapsFromOptions.some(maps => maps === this.firstStreamPropertySelector + ep.runtimeName);
     }
 
     ngOnInit() {
         this.availableProperties = this.extractPossibleSelections();
         this.availableProperties.forEach(ep => ep.propertySelector = this.firstStreamPropertySelector + ep.runtimeName);
+        if (!this.staticProperty.selectedProperty) {
+            this.staticProperty.selectedProperty = this.availableProperties[0].propertySelector;
+        }
         this.unaryTextForm = new FormGroup({
             'unaryStaticText':new FormControl(this.inputValue, [
                 Validators.required,
             ]),
         })
+        this.inputEmitter.emit(true);
     }
 
 
diff --git a/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.html b/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.html
index d77c554..fda0f0a 100644
--- a/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.html
+++ b/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.html
@@ -40,7 +40,7 @@
     <div *ngIf="staticProperty.horizontalRendering">
         <mat-form-field style="width: 100%">
             <mat-label>{{staticProperty.label}}</mat-label>
-            <mat-select>
+            <mat-select [(value)]="selectedOption">
                 <mat-option *ngFor="let option of staticProperty.options" [value]="option.id"
                             (click)="select(option.id)">
                     <label style="font-weight: normal">
diff --git a/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.ts b/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.ts
index d3bb403..3596cd1 100644
--- a/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.ts
+++ b/ui/src/app/connect/static-properties/static-one-of-input/static-one-of-input.component.ts
@@ -31,20 +31,32 @@ export class StaticOneOfInputComponent implements OnInit {
 
   @Output() inputEmitter: EventEmitter<Boolean> = new EventEmitter<Boolean>();
 
+  selectedOption: string;
+
   constructor() { }
 
   ngOnInit() {
-      for (let option of this.staticProperty.options) {
-          option.selected = false;
+      if (this.noneSelected()) {
+          if (this.staticProperty.options.length > 0) {
+              this.staticProperty.options[0].selected = true;
+              this.selectedOption = this.staticProperty.options[0].id;
+          }
+      } else {
+          this.selectedOption = this.staticProperty.options.find(option => option.selected).id;
       }
+      this.inputEmitter.emit(true);
+  }
+
+  noneSelected(): boolean {
+      return this.staticProperty.options.every(o => !(o.selected));
   }
 
   select(id) {
+      this.selectedOption = this.staticProperty.options.find(option => option.id === id).id;
       for (let option of this.staticProperty.options) {
           option.selected = false;
       }
       this.staticProperty.options.find(option => option.id === id).selected = true;
       this.inputEmitter.emit(true)
   }
-
 }
diff --git a/ui/src/app/dashboard/components/widgets/base/base-config.ts b/ui/src/app/dashboard/components/widgets/base/base-config.ts
index fc221cb..10c4989 100644
--- a/ui/src/app/dashboard/components/widgets/base/base-config.ts
+++ b/ui/src/app/dashboard/components/widgets/base/base-config.ts
@@ -17,8 +17,16 @@
  */
 
 import {DashboardWidgetSettings} from "../../../../core-model/dashboard/DashboardWidgetSettings";
+import {Tuple2} from "../../../../core-model/base/Tuple2";
 
 export abstract class WidgetConfig {
 
     abstract getConfig(): DashboardWidgetSettings;
+
+    makeOption(optionName: string): Tuple2<string, string> {
+        let option: Tuple2<string, string> = {} as Tuple2<string, string>;
+        option.a = optionName;
+        option.b = optionName.replace(" ", "-");
+        return option;
+    }
 }
\ No newline at end of file
diff --git a/ui/src/app/dashboard/components/widgets/map/map-config.ts b/ui/src/app/dashboard/components/widgets/map/map-config.ts
index fb72d9d..c5a902b 100644
--- a/ui/src/app/dashboard/components/widgets/map/map-config.ts
+++ b/ui/src/app/dashboard/components/widgets/map/map-config.ts
@@ -42,7 +42,7 @@ export class MapConfig extends WidgetConfig {
                 .requiredPropertyWithUnaryMapping(MapConfig.LONGITUDE_MAPPING_KEY, "Latitude field", "", EpRequirements.longitudeReq())
                 .requiredPropertyWithNaryMapping(MapConfig.ITEMS_MAPPING_KEY, "Fields to display", "", EpRequirements.anyProperty())
                 .build())
-            .requiredSingleValueSelection(MapConfig.MARKER_TYPE_KEY, "Marker type", "", ["Default", "Car"])
+            .requiredSingleValueSelection(MapConfig.MARKER_TYPE_KEY, "Marker type", "", [this.makeOption("Default"), this.makeOption("Car")])
             .build();
     }
 
diff --git a/ui/src/app/dashboard/components/widgets/trafficlight/traffic-light-config.ts b/ui/src/app/dashboard/components/widgets/trafficlight/traffic-light-config.ts
index e291cb6..52c1f8e 100644
--- a/ui/src/app/dashboard/components/widgets/trafficlight/traffic-light-config.ts
+++ b/ui/src/app/dashboard/components/widgets/trafficlight/traffic-light-config.ts
@@ -42,9 +42,9 @@ export class TrafficLightConfig extends WidgetConfig {
                 .requiredPropertyWithUnaryMapping(TrafficLightConfig.NUMBER_MAPPING_KEY, "Field to observe", "", EpRequirements.numberReq())
                 .build())
             .requiredIntegerParameter(TrafficLightConfig.CRITICAL_VALUE_KEY, "Threshold", "")
-            .requiredSingleValueSelection(TrafficLightConfig.CRITICAL_VALUE_LIMIT, "Operator", "", ["Upper Limit", "Under Limit"])
+            .requiredSingleValueSelection(TrafficLightConfig.CRITICAL_VALUE_LIMIT, "Operator", "", [this.makeOption("Upper" +
+            " Limit"), this.makeOption("Under Limit")])
             .requiredIntegerParameter(TrafficLightConfig.WARNING_RANGE_KEY, "Warning range (percent)", "")
             .build();
     }
-
 }
\ No newline at end of file
diff --git a/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.html b/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.html
index 273a974..a53de25 100644
--- a/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.html
+++ b/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.html
@@ -66,7 +66,8 @@
                     <div fxFlex="100" fxLayout="column">
                         <app-static-property *ngFor="let config of selectedWidget.config" [staticProperty]="config"
                                              [staticProperties]="selectedWidget.config"
-                                             [eventSchema]="selectedPipeline.schema"></app-static-property>
+                                             [eventSchema]="selectedPipeline.schema"
+                                             (validateEmitter)="validConfiguration($event)"></app-static-property>
                     </div>
 
                 </div>
@@ -83,7 +84,8 @@
         && !(data)">
             Back
         </button>
-        <button mat-button mat-raised-button color="primary" (click)="next()">
+        <button mat-button mat-raised-button color="primary" (click)="next()" [disabled]="'configure-widget' === page
+         && !configValid">
             <span *ngIf="!data && 'configure-widget' === page">Create</span>
             <span *ngIf="data && 'configure-widget' === page">Save</span>
             <span *ngIf="data == null && !('configure-widget' === page)">Next</span>
diff --git a/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.ts b/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.ts
index 73efcb8..ba0acc7 100644
--- a/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.ts
+++ b/ui/src/app/dashboard/dialogs/add-widget/add-visualization-dialog.component.ts
@@ -30,6 +30,7 @@ import {DashboardWidgetSettings} from "../../../core-model/dashboard/DashboardWi
 import {VisualizablePipeline} from "../../../core-model/dashboard/VisualizablePipeline";
 import {Dashboard} from "../../models/dashboard.model";
 import {MappingPropertyNary} from "../../../connect/model/MappingPropertyNary";
+import {ConfigurationInfo} from "../../../connect/model/message/ConfigurationInfo";
 
 @Component({
     selector: 'add-visualization-dialog-component',
@@ -64,6 +65,8 @@ export class AddVisualizationDialogComponent {
     page: any = "select-pipeline";
     dialogTitle: string;
 
+    configValid: boolean;
+
 
     constructor(
         public dialogRef: MatDialogRef<AddVisualizationDialogComponent>,
@@ -183,4 +186,10 @@ export class AddVisualizationDialogComponent {
         return this.elementIconText.getElementIconText(s);
     }
 
+    validConfiguration(valid: boolean) {
+        setTimeout(() => {
+            this.configValid = this.selectedWidget.config.every(sp => sp.isValid);
+        });
+    }
+
 }
\ No newline at end of file
diff --git a/ui/src/app/dashboard/registry/widget-config-builder.ts b/ui/src/app/dashboard/registry/widget-config-builder.ts
index cf1bb88..52a3a45 100644
--- a/ui/src/app/dashboard/registry/widget-config-builder.ts
+++ b/ui/src/app/dashboard/registry/widget-config-builder.ts
@@ -24,6 +24,7 @@ import {ColorPickerStaticProperty} from "../../connect/model/ColorPickerStaticPr
 import {OneOfStaticProperty} from "../../connect/model/OneOfStaticProperty";
 import {StaticProperty} from "../../connect/model/StaticProperty";
 import {Option} from "../../connect/model/Option";
+import {Tuple2} from "../../core-model/base/Tuple2";
 
 export class WidgetConfigBuilder {
 
@@ -101,14 +102,15 @@ export class WidgetConfigBuilder {
         return this;
     }
 
-    requiredSingleValueSelection(id: string, label: string, description: string, options: Array<string>): WidgetConfigBuilder {
+    requiredSingleValueSelection(id: string, label: string, description: string, options: Array<Tuple2<string, string>>): WidgetConfigBuilder {
         let osp: OneOfStaticProperty = new OneOfStaticProperty();
         this.prepareStaticProperty(id, label, description, osp);
 
         osp.options = [];
         options.forEach(o => {
             let option = new Option();
-            option.name = o;
+            option.name = o.a;
+            option.internalName = o.b;
             osp.options.push(option);
         });
         this.widget.config.push(osp);
diff --git a/ui/src/app/dashboard/sdk/extractor/static-property-extractor.ts b/ui/src/app/dashboard/sdk/extractor/static-property-extractor.ts
index 5d3c143..00af63c 100644
--- a/ui/src/app/dashboard/sdk/extractor/static-property-extractor.ts
+++ b/ui/src/app/dashboard/sdk/extractor/static-property-extractor.ts
@@ -44,13 +44,15 @@ export class StaticPropertyExtractor {
         let sp: MappingPropertyNary = this.getStaticPropertyByName(internalId) as MappingPropertyNary;
         let properties: Array<string> = [];
         // TODO this quick-fixes a deserialization bug in Tson-LD
-        if (!Array.isArray(sp.selectedProperties)) {
+        if (sp.selectedProperties && !Array.isArray(sp.selectedProperties)) {
             let value: string = sp.selectedProperties as any;
             sp.selectedProperties = [value];
         }
-        sp.selectedProperties.forEach(ep => {
-           properties.push(this.removePrefix(ep));
-        });
+        if (sp.selectedProperties) {
+            sp.selectedProperties.forEach(ep => {
+                properties.push(this.removePrefix(ep));
+            });
+        }
         return properties;
     }