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

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


The following commit(s) were added to refs/heads/STREAMPIPES-380 by this push:
     new 8257e14  [STREAMPIPES-380] Add error message in connect when no 
timestamp is available
8257e14 is described below

commit 8257e147221c7ed96c875d038db51da340dae4a7
Author: Philipp Zehnder <[email protected]>
AuthorDate: Thu Jun 24 12:01:27 2021 +0200

    [STREAMPIPES-380] Add error message in connect when no timestamp is
    available
---
 .../event-schema/event-schema.component.html       |   6 +-
 .../event-schema/event-schema.component.ts         |   9 ++
 .../schema-editor-header.component.html            |  14 ++-
 .../schema-editor-header.component.ts              |   3 +
 ui/src/app/core-model/base/UserErrorMessage.ts     |  27 +++++
 ui/src/app/core-ui/core-ui.module.ts               |   5 +-
 .../core-ui/error-hint/error-hint.component.html   |  46 +++++++
 .../core-ui/error-hint/error-hint.component.scss   |  25 ++++
 .../app/core-ui/error-hint/error-hint.component.ts |  45 +++++++
 .../pipeline-assembly.component.html               |  32 +----
 .../pipeline-assembly.component.ts                 | 135 ++++++++++-----------
 .../editor/services/pipeline-validation.service.ts |  78 ++++++------
 12 files changed, 285 insertions(+), 140 deletions(-)

diff --git 
a/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.html
 
b/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.html
index 378c4ed..67edc60 100644
--- 
a/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.html
+++ 
b/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.html
@@ -22,13 +22,15 @@
 
         <div class="assemblyOptions sp-blue-bg">
             <sp-schema-editor-header
+                    [countSelected]="countSelected"
+                    [schemaErrorHints]="schemaErrorHints"
+                    [displayMessages]="validEventSchema"
                     (addNestedPropertyEmitter)="addNestedProperty()"
                     (addStaticValuePropertyEmitter)="addStaticValueProperty()"
                     (addTimestampPropertyEmitter)="addTimestampProperty()"
                     (guessSchemaEmitter)="guessSchema()"
                     (togglePreviewEmitter)="togglePreview()"
-                    
(removeSelectedPropertiesEmitter)="removeSelectedProperties()"
-                    [countSelected]="countSelected">
+                    
(removeSelectedPropertiesEmitter)="removeSelectedProperties()">
             </sp-schema-editor-header>
         </div>
 
diff --git 
a/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.ts
 
b/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.ts
index 18a8f9d..513929f 100644
--- 
a/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.ts
+++ 
b/ui/src/app/connect/components/schema-editor/event-schema/event-schema.component.ts
@@ -39,6 +39,7 @@ import {
   Notification
 } from '../../../../core-model/gen/streampipes-model';
 import { MatStepper } from '@angular/material/stepper';
+import { UserErrorMessage } from 
'../../../../core-model/base/UserErrorMessage';
 
 @Component({
   selector: 'sp-event-schema',
@@ -82,6 +83,8 @@ export class EventSchemaComponent implements OnChanges {
   errorMessages: Notification[];
   nodes: EventProperty[] = new Array<EventProperty>();
   validEventSchema = false;
+  schemaErrorHints: UserErrorMessage[] = [];
+
   options: ITreeOptions = {
     childrenField: 'eventProperties',
     allowDrag: () => {
@@ -218,6 +221,7 @@ export class EventSchemaComponent implements OnChanges {
   }
 
   private checkIfValid(eventSchema: EventSchema): boolean {
+
     let hasTimestamp = false;
     eventSchema.eventProperties.forEach(p => {
       if (p.domainProperties.indexOf('http://schema.org/DateTime') >  -1) {
@@ -225,6 +229,11 @@ export class EventSchemaComponent implements OnChanges {
       }
     });
 
+    this.schemaErrorHints = [];
+    if (!hasTimestamp) {
+      this.schemaErrorHints.push(new UserErrorMessage('Missing Timestamp', 
'The timestamp must be a UNIX timestamp in milliseconds. Edit the timestamp 
event property or add a timestamp with the button on the top left.'));
+    }
+
     return hasTimestamp;
   }
 }
diff --git 
a/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.html
 
b/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.html
index a42a31f..bd19b4d 100644
--- 
a/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.html
+++ 
b/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.html
@@ -33,11 +33,17 @@
             <button color="primary" mat-button (click)=guessSchema()>
                 <mat-icon matTooltip="Refresh Schema">refresh</mat-icon>
             </button>
-            <button color="primary" mat-button (click)=togglePreview()>
-                <mat-icon matTooltip="Show preview of 
schema">play_arrow</mat-icon>
-            </button>
+            <!--            <button color="primary" mat-button 
(click)=togglePreview()>-->
+            <!--                <mat-icon matTooltip="Show preview of 
schema">play_arrow</mat-icon>-->
+            <!--            </button>-->
         </div>
-        <div>
+        <div fxLayout="row" style="align-items: center;">
+                <sp-error-hint
+                        [errorMessages]="schemaErrorHints"
+                        [displayMessages]="!displayMessages">
+                </sp-error-hint>
+
+
             <button style="padding-right:0" color="primary" mat-button 
[disabled]="countSelected == 0"
                     (click)="removeSelectedProperties()">
                 <mat-icon matTooltip="Remove selected 
Properties">delete</mat-icon>
diff --git 
a/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.ts
 
b/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.ts
index 9c7eda3c..79298b1 100644
--- 
a/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.ts
+++ 
b/ui/src/app/connect/components/schema-editor/schema-editor-header/schema-editor-header.component.ts
@@ -17,6 +17,7 @@
  */
 
 import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { UserErrorMessage } from 
'../../../../core-model/base/UserErrorMessage';
 
 @Component({
   selector: 'sp-schema-editor-header',
@@ -27,6 +28,8 @@ export class SchemaEditorHeaderComponent implements OnInit {
 
 
   @Input() countSelected: number;
+  @Input() schemaErrorHints: UserErrorMessage[];
+  @Input() displayMessages: boolean;
 
   @Output() addNestedPropertyEmitter = new EventEmitter();
   @Output() addStaticValuePropertyEmitter = new EventEmitter();
diff --git a/ui/src/app/core-model/base/UserErrorMessage.ts 
b/ui/src/app/core-model/base/UserErrorMessage.ts
new file mode 100644
index 0000000..85322e0
--- /dev/null
+++ b/ui/src/app/core-model/base/UserErrorMessage.ts
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+export class UserErrorMessage {
+  public title: string;
+  public content: string;
+
+  constructor(title: string, content: string) {
+    this.title = title;
+    this.content = content;
+  }
+}
diff --git a/ui/src/app/core-ui/core-ui.module.ts 
b/ui/src/app/core-ui/core-ui.module.ts
index 4bd9e7f..806bad0 100644
--- a/ui/src/app/core-ui/core-ui.module.ts
+++ b/ui/src/app/core-ui/core-ui.module.ts
@@ -78,6 +78,7 @@ import { LabelListItemComponent } from 
'./labels/components/label-list-item/labe
 import { StatusWidgetComponent } from 
"./widget/status/status-widget.component";
 import { NgxChartsModule } from "@swimlane/ngx-charts";
 import { BarchartWidgetComponent } from 
"./widget/barchart/barchart-widget.component";
+import { ErrorHintComponent } from './error-hint/error-hint.component';
 
 @NgModule({
     imports: [
@@ -133,7 +134,8 @@ import { BarchartWidgetComponent } from 
"./widget/barchart/barchart-widget.compo
         StaticRuntimeResolvableAnyInputComponent,
         StaticRuntimeResolvableOneOfInputComponent,
         StatusWidgetComponent,
-        LabelListItemComponent
+        LabelListItemComponent,
+        ErrorHintComponent
     ],
     providers: [
         MatDatepickerModule,
@@ -176,6 +178,7 @@ import { BarchartWidgetComponent } from 
"./widget/barchart/barchart-widget.compo
     ImageViewerComponent,
     StatusWidgetComponent,
     BarchartWidgetComponent,
+    ErrorHintComponent
   ]
 })
 export class CoreUiModule {
diff --git a/ui/src/app/core-ui/error-hint/error-hint.component.html 
b/ui/src/app/core-ui/error-hint/error-hint.component.html
new file mode 100644
index 0000000..e0b062f
--- /dev/null
+++ b/ui/src/app/core-ui/error-hint/error-hint.component.html
@@ -0,0 +1,46 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+<div class="error-hint-position">
+    <div *ngIf="displayMessages"
+         class="pipeline-validation-summary {{errorMessages.length > 0 ? 
'pipeline-validation-summary-error' : ''}}"
+         (click)="toggleErrorMessagesDisplayed()">
+        <div fxLayout="row" fxLayoutAlign="center center">
+            <div fxLayout="row" fxLayoutAlign="start center">
+                <i class="material-icons" *ngIf="errorMessages.length > 
0">notifications</i>
+                <i class="material-icons"
+                   *ngIf="errorMessages.length === 0">done</i>
+            </div>
+            <div>
+                <span *ngIf="errorMessages.length === 0">{{validationString}} 
ok</span>
+                <span *ngIf="errorMessages.length > 
0">{{errorMessages.length}} {{errorMessages.length > 1 ? 'hints' : 
'hint'}}</span>
+            </div>
+        </div>
+    </div>
+    <div class="editor-error-notifications"
+         *ngIf="errorMessages.length > 0 && errorMessagesDisplayed">
+        <h5 class="error-hint-color">
+            <b>{{errorMessages.length}} {{errorMessages.length == 1 ? "error" 
: "errors"}}
+                found.</b></h5>
+        <hr/>
+        <div *ngFor="let errorMessage of errorMessages">
+            <b>{{errorMessage.title}}</b>
+            <div>{{errorMessage.content}}</div>
+            <hr/>
+        </div>
+    </div>
+</div>
diff --git a/ui/src/app/core-ui/error-hint/error-hint.component.scss 
b/ui/src/app/core-ui/error-hint/error-hint.component.scss
new file mode 100644
index 0000000..2bb9041
--- /dev/null
+++ b/ui/src/app/core-ui/error-hint/error-hint.component.scss
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+.error-hint-position {
+  position: relative;
+}
+
+.error-hint-color {
+  color: darkred;
+}
diff --git a/ui/src/app/core-ui/error-hint/error-hint.component.ts 
b/ui/src/app/core-ui/error-hint/error-hint.component.ts
new file mode 100644
index 0000000..3924f7f
--- /dev/null
+++ b/ui/src/app/core-ui/error-hint/error-hint.component.ts
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit } from '@angular/core';
+import { UserErrorMessage } from '../../core-model/base/UserErrorMessage';
+
+@Component({
+  selector: 'sp-error-hint',
+  templateUrl: './error-hint.component.html',
+  styleUrls: ['./error-hint.component.scss']
+})
+export class ErrorHintComponent implements OnInit {
+
+  @Input() errorMessages: UserErrorMessage[];
+  @Input() displayMessages = true;
+  @Input() validationString: string;
+
+  errorMessagesDisplayed: boolean;
+
+  constructor() { }
+
+  ngOnInit(): void {
+    this.errorMessagesDisplayed = false;
+  }
+
+  public toggleErrorMessagesDisplayed() {
+    this.errorMessagesDisplayed = !(this.errorMessagesDisplayed);
+  }
+
+}
diff --git 
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.html
 
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.html
index 41b76af..3463fcb 100644
--- 
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.html
+++ 
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.html
@@ -68,33 +68,11 @@
             </div>
             <span fxFlex></span>
             <div style="position:relative;">
-                <div *ngIf="!isPipelineAssemblyEmpty()"
-                     class="pipeline-validation-summary 
{{PipelineValidationService.errorMessages.length > 0 ? 
'pipeline-validation-summary-error' : ''}}"
-                     (click)="toggleErrorMessagesDisplayed()">
-                    <div fxLayout="row" fxLayoutAlign="center center">
-                        <div fxLayout="row" fxLayoutAlign="start center">
-                            <i class="material-icons" 
*ngIf="PipelineValidationService.errorMessages.length > 0">notifications</i>
-                            <i class="material-icons"
-                               
*ngIf="PipelineValidationService.errorMessages.length === 0">done</i>
-                        </div>
-                        <div>
-                            <span 
*ngIf="PipelineValidationService.errorMessages.length === 0">Pipeline ok</span>
-                            <span 
*ngIf="PipelineValidationService.errorMessages.length > 
0">{{PipelineValidationService.errorMessages.length}} 
{{PipelineValidationService.errorMessages.length > 1 ? 'hints' : 'hint'}}</span>
-                        </div>
-                    </div>
-                </div>
-                <div class="editor-error-notifications"
-                     *ngIf="PipelineValidationService.errorMessages.length > 0 
&& errorMessagesDisplayed">
-                    <h5 style="color:darkred">
-                        <b>{{PipelineValidationService.errorMessages.length}} 
{{PipelineValidationService.errorMessages.length == 1 ? "error" : "errors"}}
-                            found.</b></h5>
-                    <hr/>
-                    <div *ngFor="let errorMessage of 
PipelineValidationService.errorMessages">
-                        <b>{{errorMessage.title}}</b>
-                        <div>{{errorMessage.content}}</div>
-                        <hr/>
-                    </div>
-                </div>
+                <sp-error-hint
+                    [displayMessages]="!isPipelineAssemblyEmpty()"
+                    [errorMessages]="PipelineValidationService.errorMessages"
+                    [validationString]="'Pipeline'">
+                </sp-error-hint>
             </div>
             <button mat-button mat-icon-button
                     [matTooltip]="pipelineCanvasMaximized ? 'Minimize' : 
'Maximize'"
diff --git 
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts 
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts
index 41e3db0..ec7a592 100644
--- 
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts
+++ 
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts
@@ -25,29 +25,29 @@ import {
     OnInit,
     Output,
     ViewChild,
-} from "@angular/core";
-import {JsplumbBridge} from "../../services/jsplumb-bridge.service";
-import {PipelinePositioningService} from 
"../../services/pipeline-positioning.service";
-import {PipelineValidationService} from 
"../../services/pipeline-validation.service";
-import {JsplumbService} from "../../services/jsplumb.service";
-import {ShepherdService} from "../../../services/tour/shepherd.service";
-import {PipelineElementConfig, PipelineElementUnion} from 
"../../model/editor.model";
-import {ObjectProvider} from "../../services/object-provider.service";
-import {PanelType} from 
"../../../core-ui/dialog/base-dialog/base-dialog.model";
-import {SavePipelineComponent} from 
"../../dialog/save-pipeline/save-pipeline.component";
-import {DialogService} from 
"../../../core-ui/dialog/base-dialog/base-dialog.service";
-import {ConfirmDialogComponent} from 
"../../../core-ui/dialog/confirm-dialog/confirm-dialog.component";
-import {MatDialog} from "@angular/material/dialog";
-import {EditorService} from "../../services/editor.service";
-import {PipelineService} from 
"../../../platform-services/apis/pipeline.service";
-import {JsplumbFactoryService} from "../../services/jsplumb-factory.service";
-import Panzoom, {PanzoomObject} from "@panzoom/panzoom";
-import {PipelineElementDraggedService} from 
"../../services/pipeline-element-dragged.service";
-import {PipelineComponent} from "../pipeline/pipeline.component";
-import {PipelineCanvasMetadata} from 
"../../../core-model/gen/streampipes-model";
-import {forkJoin} from 'rxjs';
-import {PipelineCanvasMetadataService} from 
"../../../platform-services/apis/pipeline-canvas-metadata.service";
-import {PipelineElementDiscoveryComponent} from 
"../../dialog/pipeline-element-discovery/pipeline-element-discovery.component";
+} from '@angular/core';
+import { JsplumbBridge } from '../../services/jsplumb-bridge.service';
+import { PipelinePositioningService } from 
'../../services/pipeline-positioning.service';
+import { PipelineValidationService } from 
'../../services/pipeline-validation.service';
+import { JsplumbService } from '../../services/jsplumb.service';
+import { ShepherdService } from '../../../services/tour/shepherd.service';
+import { PipelineElementConfig, PipelineElementUnion } from 
'../../model/editor.model';
+import { ObjectProvider } from '../../services/object-provider.service';
+import { PanelType } from 
'../../../core-ui/dialog/base-dialog/base-dialog.model';
+import { SavePipelineComponent } from 
'../../dialog/save-pipeline/save-pipeline.component';
+import { DialogService } from 
'../../../core-ui/dialog/base-dialog/base-dialog.service';
+import { ConfirmDialogComponent } from 
'../../../core-ui/dialog/confirm-dialog/confirm-dialog.component';
+import { MatDialog } from '@angular/material/dialog';
+import { EditorService } from '../../services/editor.service';
+import { PipelineService } from 
'../../../platform-services/apis/pipeline.service';
+import { JsplumbFactoryService } from '../../services/jsplumb-factory.service';
+import Panzoom, { PanzoomObject } from '@panzoom/panzoom';
+import { PipelineElementDraggedService } from 
'../../services/pipeline-element-dragged.service';
+import { PipelineComponent } from '../pipeline/pipeline.component';
+import { PipelineCanvasMetadata } from 
'../../../core-model/gen/streampipes-model';
+import { forkJoin } from 'rxjs';
+import { PipelineCanvasMetadataService } from 
'../../../platform-services/apis/pipeline-canvas-metadata.service';
+import { PipelineElementDiscoveryComponent } from 
'../../dialog/pipeline-element-discovery/pipeline-element-discovery.component';
 
 
 @Component({
@@ -71,7 +71,7 @@ export class PipelineAssemblyComponent implements OnInit {
 
     JsplumbBridge: JsplumbBridge;
 
-    pipelineCanvasMaximized: boolean = false;
+    pipelineCanvasMaximized = false;
 
     currentMouseOverElement: any;
     currentZoomLevel: any;
@@ -81,20 +81,18 @@ export class PipelineAssemblyComponent implements OnInit {
     currentPipelineName: any;
     currentPipelineDescription: any;
 
-    errorMessagesDisplayed: any = false;
+    pipelineValid = false;
 
-    pipelineValid: boolean = false;
-
-    pipelineCacheRunning: boolean = false;
-    pipelineCached: boolean = false;
+    pipelineCacheRunning = false;
+    pipelineCached = false;
 
     pipelineCanvasMetadata: PipelineCanvasMetadata = new 
PipelineCanvasMetadata();
-    pipelineCanvasMetadataAvailable: boolean = false;
+    pipelineCanvasMetadataAvailable = false;
 
     config: any = {};
-    @ViewChild("outerCanvas") pipelineCanvas: ElementRef;
+    @ViewChild('outerCanvas') pipelineCanvas: ElementRef;
 
-    @ViewChild("pipelineComponent")
+    @ViewChild('pipelineComponent')
     pipelineComponent: PipelineComponent;
 
     panzoom: PanzoomObject;
@@ -125,9 +123,9 @@ export class PipelineAssemblyComponent implements OnInit {
             this.checkAndDisplayCachedPipeline();
         }
         
this.pipelineElementDraggedService.pipelineElementMovedSubject.subscribe(position
 => {
-            let offsetHeight = this.pipelineCanvas.nativeElement.offsetHeight;
-            let offsetWidth = this.pipelineCanvas.nativeElement.offsetWidth;
-            let currentPan = this.panzoom.getPan();
+            const offsetHeight = 
this.pipelineCanvas.nativeElement.offsetHeight;
+            const offsetWidth = this.pipelineCanvas.nativeElement.offsetWidth;
+            const currentPan = this.panzoom.getPan();
             let xOffset = 0;
             let yOffset = 0;
             if ((position.y + currentPan.y) > (offsetHeight - 100)) {
@@ -143,17 +141,17 @@ export class PipelineAssemblyComponent implements OnInit {
     }
 
     ngAfterViewInit() {
-        const elem = document.getElementById('assembly')
+        const elem = document.getElementById('assembly');
         this.panzoom = Panzoom(elem, {
             maxScale: 5,
-            excludeClass: "jtk-draggable",
+            excludeClass: 'jtk-draggable',
             canvas: true,
-            contain: "outside"
-        })
+            contain: 'outside'
+        });
     }
 
     autoLayout() {
-        this.PipelinePositioningService.layoutGraph("#assembly", 
"span[id^='jsplumb']", 110, false);
+        this.PipelinePositioningService.layoutGraph('#assembly', 
'span[id^=\'jsplumb\']', 110, false);
         this.JsplumbBridge.repaintEverything();
     }
 
@@ -176,14 +174,14 @@ export class PipelineAssemblyComponent implements OnInit {
     }
 
     showClearAssemblyConfirmDialog(event: any) {
-        let dialogRef = this.dialog.open(ConfirmDialogComponent, {
+        const dialogRef = this.dialog.open(ConfirmDialogComponent, {
             width: '500px',
             data: {
-                "title": "Do you really want to delete the current pipeline?",
-                "subtitle": "This cannot be undone.",
-                "cancelTitle": "No",
-                "okTitle": "Yes",
-                "confirmAndCancel": true
+                'title': 'Do you really want to delete the current pipeline?',
+                'subtitle': 'This cannot be undone.',
+                'cancelTitle': 'No',
+                'okTitle': 'Yes',
+                'confirmAndCancel': true
             },
         });
         dialogRef.afterClosed().subscribe(ev => {
@@ -195,32 +193,32 @@ export class PipelineAssemblyComponent implements OnInit {
                 this.EditorService.makePipelineAssemblyEmpty(true);
             }
         });
-    };
+    }
 
     /**
      * clears the Assembly of all elements
      */
     clearAssembly() {
-        //$('#assembly').children().not('#clear, #submit').remove();
+        // $('#assembly').children().not('#clear, #submit').remove();
         this.JsplumbBridge.deleteEveryEndpoint();
         this.rawPipelineModel = [];
         this.currentZoomLevel = 1;
         this.JsplumbBridge.setZoom(this.currentZoomLevel);
         this.JsplumbBridge.repaintEverything();
 
-        let removePipelineFromCache = 
this.EditorService.removePipelineFromCache();
-        let removeCanvasMetadataFromCache = 
this.EditorService.removeCanvasMetadataFromCache();
+        const removePipelineFromCache = 
this.EditorService.removePipelineFromCache();
+        const removeCanvasMetadataFromCache = 
this.EditorService.removeCanvasMetadataFromCache();
         forkJoin([removePipelineFromCache, 
removeCanvasMetadataFromCache]).subscribe(msg => {
             this.pipelineCached = false;
             this.pipelineCacheRunning = false;
         });
-    };
+    }
 
     /**
      * Sends the pipeline to the server
      */
     submit() {
-        var pipeline = 
this.ObjectProvider.makeFinalPipeline(this.rawPipelineModel);
+        const pipeline = 
this.ObjectProvider.makeFinalPipeline(this.rawPipelineModel);
         
this.PipelinePositioningService.collectPipelineElementPositions(this.pipelineCanvasMetadata,
 this.rawPipelineModel);
         pipeline.name = this.currentPipelineName;
         pipeline.description = this.currentPipelineDescription;
@@ -228,20 +226,20 @@ export class PipelineAssemblyComponent implements OnInit {
             pipeline._id = this.currentModifiedPipelineId;
         }
 
-        this.dialogService.open(SavePipelineComponent,{
+        this.dialogService.open(SavePipelineComponent, {
             panelType: PanelType.SLIDE_IN_PANEL,
-            title: "Save pipeline",
+            title: 'Save pipeline',
             data: {
-                "pipeline": pipeline,
-                "currentModifiedPipelineId": this.currentModifiedPipelineId,
-                "pipelineCanvasMetadata": this.pipelineCanvasMetadata
+                'pipeline': pipeline,
+                'currentModifiedPipelineId': this.currentModifiedPipelineId,
+                'pipelineCanvasMetadata': this.pipelineCanvasMetadata
             }
         });
     }
 
     checkAndDisplayCachedPipeline() {
-        let cachedPipeline = this.EditorService.getCachedPipeline();
-        let cachedCanvasMetadata = 
this.EditorService.getCachedPipelineCanvasMetadata();
+        const cachedPipeline = this.EditorService.getCachedPipeline();
+        const cachedCanvasMetadata = 
this.EditorService.getCachedPipelineCanvasMetadata();
         forkJoin([cachedPipeline, cachedCanvasMetadata]).subscribe(results => {
             if (results[0] && results[0].length > 0) {
                 this.rawPipelineModel = results[0] as PipelineElementConfig[];
@@ -251,10 +249,10 @@ export class PipelineAssemblyComponent implements OnInit {
     }
 
     displayPipelineById() {
-        let pipelineRequest = 
this.PipelineService.getPipelineById(this.currentModifiedPipelineId);
-        let canvasRequest = 
this.pipelineCanvasMetadataService.getPipelineCanvasMetadata(this.currentModifiedPipelineId);
+        const pipelineRequest = 
this.PipelineService.getPipelineById(this.currentModifiedPipelineId);
+        const canvasRequest = 
this.pipelineCanvasMetadataService.getPipelineCanvasMetadata(this.currentModifiedPipelineId);
         pipelineRequest.subscribe(pipelineResp => {
-                let pipeline = pipelineResp;
+                const pipeline = pipelineResp;
                 this.currentPipelineName = pipeline.name;
                 this.currentPipelineDescription = pipeline.description;
                 this.rawPipelineModel = 
this.JsplumbService.makeRawPipeline(pipeline, false);
@@ -264,7 +262,7 @@ export class PipelineAssemblyComponent implements OnInit {
                     this.handleCanvasMetadataResponse(undefined);
                 });
             });
-    };
+    }
 
     handleCanvasMetadataResponse(canvasMetadata: PipelineCanvasMetadata) {
         if (canvasMetadata) {
@@ -280,7 +278,7 @@ export class PipelineAssemblyComponent implements OnInit {
     displayPipelineInEditor(autoLayout,
                             pipelineCanvasMetadata?: PipelineCanvasMetadata) {
         setTimeout(() => {
-            
this.PipelinePositioningService.displayPipeline(this.rawPipelineModel, 
"#assembly", false, autoLayout, pipelineCanvasMetadata);
+            
this.PipelinePositioningService.displayPipeline(this.rawPipelineModel, 
'#assembly', false, autoLayout, pipelineCanvasMetadata);
             this.EditorService.makePipelineAssemblyEmpty(false);
             this.ngZone.run(() => {
                 this.pipelineValid = this.PipelineValidationService
@@ -290,9 +288,6 @@ export class PipelineAssemblyComponent implements OnInit {
         });
     }
 
-    toggleErrorMessagesDisplayed() {
-        this.errorMessagesDisplayed = !(this.errorMessagesDisplayed);
-    }
 
     isPipelineAssemblyEmpty() {
         return this.rawPipelineModel.length === 0 || 
this.rawPipelineModel.every(pe => pe.settings.disabled);
@@ -324,9 +319,9 @@ export class PipelineAssemblyComponent implements OnInit {
     }
 
     pan(xOffset: number, yOffset: number) {
-        let currentPan = this.panzoom.getPan();
-        let panX = Math.min(0, currentPan.x + xOffset);
-        let panY = Math.min(0, currentPan.y + yOffset);
+        const currentPan = this.panzoom.getPan();
+        const panX = Math.min(0, currentPan.x + xOffset);
+        const panY = Math.min(0, currentPan.y + yOffset);
         this.panzoom.pan(panX, panY);
     }
 
diff --git a/ui/src/app/editor/services/pipeline-validation.service.ts 
b/ui/src/app/editor/services/pipeline-validation.service.ts
index 24a3df2..3ce8951 100644
--- a/ui/src/app/editor/services/pipeline-validation.service.ts
+++ b/ui/src/app/editor/services/pipeline-validation.service.ts
@@ -17,34 +17,35 @@
  */
 
 import * as dagre from 'dagre';
-import {JsplumbBridge} from "./jsplumb-bridge.service";
-import {Injectable} from "@angular/core";
-import {PipelineElementConfig} from "../model/editor.model";
-import {DataProcessorInvocation, DataSinkInvocation} from 
"../../core-model/gen/streampipes-model";
-import {JsplumbFactoryService} from "./jsplumb-factory.service";
+import { JsplumbBridge } from './jsplumb-bridge.service';
+import { Injectable } from '@angular/core';
+import { PipelineElementConfig } from '../model/editor.model';
+import { DataProcessorInvocation, DataSinkInvocation } from 
'../../core-model/gen/streampipes-model';
+import { JsplumbFactoryService } from './jsplumb-factory.service';
+import { UserErrorMessage } from '../../core-model/base/UserErrorMessage';
 
 @Injectable()
 export class PipelineValidationService {
 
     errorMessages: any = [];
-    pipelineValid: boolean = false;
-
-    availableErrorMessages: any = [
-        {title: "Did you add a data stream?", content: "Any pipeline needs at 
least one data stream."},
-        {title: "Did you add a data sink?", content: "Any pipeline needs at 
least one data sink."},
-        {title: "Did you connect all elements?", content: "No orphaned 
elements are allowed within a pipeline, make sure to connect all elements."},
-        {title: "Separate pipelines", content: "It seems you've created more 
than one pipeline at once. Create only one pipeline at a time!"},
-        {title: "Did you configure all elements?", content: "There's a 
pipeline element which is missing some configuration."},
+    pipelineValid = false;
+
+    availableErrorMessages: UserErrorMessage[] = [
+      new UserErrorMessage('Did you add a data stream?', 'Any pipeline needs 
at least one data stream.'),
+      new UserErrorMessage('Did you add a data sink?', 'Any pipeline needs at 
least one data sink.'),
+      new UserErrorMessage('Did you connect all elements?', 'No orphaned 
elements are allowed within a pipeline, make sure to connect all elements.'),
+      new UserErrorMessage('Separate pipelines', 'It seems you\'ve created 
more than one pipeline at once. Create only one pipeline at a time!'),
+      new UserErrorMessage('Did you configure all elements?', 'There\'s a 
pipeline element which is missing some configuration.')
     ];
 
-    constructor(private JsplumbFactoryService: JsplumbFactoryService) {
+    constructor(private jsplumbFactoryService: JsplumbFactoryService) {
     }
 
     isValidPipeline(rawPipelineModel, previewConfig: boolean) {
-        let jsplumbBridge = 
this.JsplumbFactoryService.getJsplumbBridge(previewConfig);
-        let streamInAssembly = this.isStreamInAssembly(rawPipelineModel);
-        let sepaInAssembly = this.isSepaInAssembly(rawPipelineModel);
-        let actionInAssembly = this.isActionInAssembly(rawPipelineModel);
+        const jsplumbBridge = 
this.jsplumbFactoryService.getJsplumbBridge(previewConfig);
+        const streamInAssembly = this.isStreamInAssembly(rawPipelineModel);
+        const sepaInAssembly = this.isSepaInAssembly(rawPipelineModel);
+        const actionInAssembly = this.isActionInAssembly(rawPipelineModel);
         let allElementsConnected = true;
         let onlyOnePipelineCreated = true;
         let allElementsConfigured = true;
@@ -59,7 +60,11 @@ export class PipelineValidationService {
         }
 
         if (!this.isEmptyPipeline(rawPipelineModel)) {
-            this.buildErrorMessages(streamInAssembly, actionInAssembly, 
allElementsConnected, onlyOnePipelineCreated, allElementsConfigured);
+            this.buildErrorMessages(streamInAssembly,
+              actionInAssembly,
+              allElementsConnected,
+              onlyOnePipelineCreated,
+              allElementsConfigured);
         } else {
             this.errorMessages = [];
         }
@@ -70,7 +75,8 @@ export class PipelineValidationService {
     }
 
     isEmptyPipeline(rawPipelineModel) {
-        return !this.isActionInAssembly(rawPipelineModel) && 
!this.isStreamInAssembly(rawPipelineModel) && 
!this.isInAssembly(rawPipelineModel, 'sepa');
+        return !this.isActionInAssembly(rawPipelineModel) &&
+          !this.isStreamInAssembly(rawPipelineModel) && 
!this.isInAssembly(rawPipelineModel, 'sepa');
     }
 
     buildErrorMessages(streamInAssembly, actionInAssembly, 
allElementsConnected, onlyOnePipelineCreated, allElementsConfigured) {
@@ -99,36 +105,36 @@ export class PipelineValidationService {
     }
 
     allElementsConnected(rawPipelineModel, jsplumbBridge) {
-        let g = this.makeGraph(rawPipelineModel, jsplumbBridge);
+        const g = this.makeGraph(rawPipelineModel, jsplumbBridge);
         return g.nodes().every(node => this.isFullyConnected(g, node));
     }
 
     isFullyConnected(g, node) {
-        var nodeProperty = g.node(node);
+        const nodeProperty = g.node(node);
         return g.outEdges(node).length >= nodeProperty.endpointCount;
     }
 
     isStreamInAssembly(rawPipelineModel) {
-        return this.isInAssembly(rawPipelineModel, "stream") || 
this.isInAssembly(rawPipelineModel, "set");
+        return this.isInAssembly(rawPipelineModel, 'stream') || 
this.isInAssembly(rawPipelineModel, 'set');
     }
 
     isActionInAssembly(rawPipelineModel) {
-        return this.isInAssembly(rawPipelineModel, "action");
+        return this.isInAssembly(rawPipelineModel, 'action');
     }
 
     isSepaInAssembly(rawPipelineModel) {
-        return this.isInAssembly(rawPipelineModel, "sepa");
+        return this.isInAssembly(rawPipelineModel, 'sepa');
     }
 
     onlyOnePipelineCreated(rawPipelineModel, jsplumbBridge: JsplumbBridge) {
-        let g = this.makeGraph(rawPipelineModel, jsplumbBridge);
-        let tarjan = dagre.graphlib.alg.tarjan(g);
+        const g = this.makeGraph(rawPipelineModel, jsplumbBridge);
+        const tarjan = dagre.graphlib.alg.tarjan(g);
 
         return tarjan.length == 1;
     }
 
     isInAssembly(rawPipelineModel: PipelineElementConfig[], type) {
-        var isElementInAssembly = false;
+        let isElementInAssembly = false;
         rawPipelineModel.forEach(pe => {
             if (pe.type === type && !pe.settings.disabled) {
                 isElementInAssembly = true;
@@ -138,16 +144,16 @@ export class PipelineValidationService {
     }
 
     makeGraph(rawPipelineModel: PipelineElementConfig[], jsplumbBridge: 
JsplumbBridge) {
-        var g = new dagre.graphlib.Graph();
-        g.setGraph({rankdir: "LR"});
+        const g = new dagre.graphlib.Graph();
+        g.setGraph({rankdir: 'LR'});
         g.setDefaultEdgeLabel(function () {
             return {};
         });
-        var nodes = $("#assembly").find("span[id^='jsplumb']").get();
+        const nodes = $('#assembly').find('span[id^=\'jsplumb\']').get();
 
-        for (var i = 0; i < nodes.length; i++) {
-            var n = nodes[i];
-            var elementOptions = this.getElementOptions(n.id, 
rawPipelineModel);
+        for (let i = 0; i < nodes.length; i++) {
+            const n = nodes[i];
+            const elementOptions = this.getElementOptions(n.id, 
rawPipelineModel);
             if (!elementOptions.settings.disabled) {
                 g.setNode(n.id, {
                     label: n.id,
@@ -157,9 +163,9 @@ export class PipelineValidationService {
                 });
             }
         }
-        var edges = jsplumbBridge.getAllConnections();
+        const edges = jsplumbBridge.getAllConnections();
         edges.forEach((edge, i) => {
-            var c = edges[i];
+            const c = edges[i];
             g.setEdge(c.source.id, c.target.id);
             g.setEdge(c.target.id, c.source.id);
         });

Reply via email to