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/06/07 21:05:54 UTC

[incubator-streampipes] branch STREAMPIPES-145 updated (b675bf4 -> 6e85d52)

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

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


    from b675bf4  [STREAMPIPES-145] Add pipeline element options
     new b632949  [STREAMPIPES-145] Add tooltips to assembly
     new 6e85d52  [STREAMPIPES-145] Add dialog template

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../pipeline-assembly.component.html               |  8 +-
 .../components/pipeline/pipeline.component.ts      | 51 ++++++++----
 .../customize/customize.component.css}             |  0
 .../dialog/customize/customize.component.html}     |  0
 .../dialog/customize/customize.component.ts}       | 22 +++--
 .../src/app/editor-v2/dialog/panel/dialog-ref.ts   | 40 ++++-----
 .../dialog/panel/panel-dialog.component.html}      | 10 +--
 .../dialog/panel/panel-dialog.component.scss}      | 19 +++--
 .../dialog/panel/panel-dialog.component.ts}        | 50 +++++++----
 .../editor-v2/dialog/panel/panel-dialog.service.ts | 97 ++++++++++++++++++++++
 ui/src/app/editor-v2/editor.module.ts              | 13 ++-
 ui/src/app/editor-v2/model/editor.model.ts         | 12 ++-
 ui/src/app/editor-v2/services/editor.service.ts    | 28 ++++++-
 ui/src/app/editor-v2/services/jsplumb.service.ts   | 19 ++++-
 .../editor-v2/services/object-provider.service.ts  |  6 +-
 ui/src/app/services/rest-api.service.ts            |  8 --
 16 files changed, 289 insertions(+), 94 deletions(-)
 copy ui/src/app/editor-v2/{components/pipeline-element-options/pipeline-element-options.component.css => dialog/customize/customize.component.css} (100%)
 copy ui/src/app/{app-transport-monitoring/components/incoming/incoming-view.component.html => editor-v2/dialog/customize/customize.component.html} (100%)
 copy ui/src/app/{data-explorer-v2/components/widgets/utils/no-data/no-data-in-date-range.component.ts => editor-v2/dialog/customize/customize.component.ts} (65%)
 copy streampipes-model/src/main/java/org/apache/streampipes/model/monitoring/StreamPipesRuntimeError.java => ui/src/app/editor-v2/dialog/panel/dialog-ref.ts (59%)
 copy ui/src/app/{sensors/components/general/advanced-settings.tmpl.html => editor-v2/dialog/panel/panel-dialog.component.html} (73%)
 copy ui/src/app/{data-explorer/explorer-widget/explorer-visualisations/table/table.component.css => editor-v2/dialog/panel/panel-dialog.component.scss} (75%)
 copy ui/src/app/{data-explorer-v2/components/widgets/utils/select-properties/select-properties.component.ts => editor-v2/dialog/panel/panel-dialog.component.ts} (50%)
 create mode 100644 ui/src/app/editor-v2/dialog/panel/panel-dialog.service.ts


[incubator-streampipes] 01/02: [STREAMPIPES-145] Add tooltips to assembly

Posted by ri...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit b6329494e92c70d7e792e653abeb582f3f0872c8
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Sun Jun 7 18:17:14 2020 +0200

    [STREAMPIPES-145] Add tooltips to assembly
---
 .../components/pipeline-assembly/pipeline-assembly.component.html    | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.html b/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.html
index ae7723e..67dd075 100644
--- a/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.html
+++ b/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.html
@@ -46,7 +46,7 @@
                     (click)="zoomOut()">
                 <i class="material-icons">zoom_out</i>
             </button>
-            <button mat-button matTooltip="Auto Layout" [matTooltipPosition]="'below'"
+            <button mat-button matTooltip="Auto Layout" [matTooltipPosition]="'above'"
                     class="md-icon-button settings-bar-icon-button" (click)="autoLayout()">
                 <i class="material-icons">settings_overscan</i>
             </button>
@@ -87,7 +87,8 @@
                     </div>
                 </div>
             </div>
-            <button mat-button class="md-icon-button" ng-click="showClearAssemblyConfirmDialog($event)">
+            <button mat-button matTooltip="Clear Assembly Area" [matTooltipPosition]="'above'"
+                    class="md-icon-button" (click)="showClearAssemblyConfirmDialog($event)">
                 <i class="material-icons">clear</i>
                 <!--                <md-tooltip md-direction="top">-->
                 <!--                    Clear Assembly Area-->


[incubator-streampipes] 02/02: [STREAMPIPES-145] Add dialog template

Posted by ri...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 6e85d52a5b714b71814219fd07858e6f000ddc5d
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Sun Jun 7 23:05:40 2020 +0200

    [STREAMPIPES-145] Add dialog template
---
 .../pipeline-assembly.component.html               |  3 -
 .../components/pipeline/pipeline.component.ts      | 51 ++++++++----
 .../dialog/customize/customize.component.css       |  0
 .../dialog/customize/customize.component.html      | 18 ++++
 .../customize/customize.component.ts}              | 27 +++---
 .../panel/dialog-ref.ts}                           | 33 +++++---
 .../dialog/panel/panel-dialog.component.html       | 23 +++++
 .../panel/panel-dialog.component.scss}             | 26 +++---
 .../dialog/panel/panel-dialog.component.ts         | 67 +++++++++++++++
 .../editor-v2/dialog/panel/panel-dialog.service.ts | 97 ++++++++++++++++++++++
 ui/src/app/editor-v2/editor.module.ts              | 13 ++-
 ui/src/app/editor-v2/model/editor.model.ts         | 12 ++-
 ui/src/app/editor-v2/services/editor.service.ts    | 28 ++++++-
 ui/src/app/editor-v2/services/jsplumb.service.ts   | 19 ++++-
 .../editor-v2/services/object-provider.service.ts  |  6 +-
 ui/src/app/services/rest-api.service.ts            |  8 --
 16 files changed, 364 insertions(+), 67 deletions(-)

diff --git a/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.html b/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.html
index 67dd075..5680b95 100644
--- a/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.html
+++ b/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.html
@@ -90,9 +90,6 @@
             <button mat-button matTooltip="Clear Assembly Area" [matTooltipPosition]="'above'"
                     class="md-icon-button" (click)="showClearAssemblyConfirmDialog($event)">
                 <i class="material-icons">clear</i>
-                <!--                <md-tooltip md-direction="top">-->
-                <!--                    Clear Assembly Area-->
-                <!--                </md-tooltip>-->
             </button>
         </div>
     </div>
diff --git a/ui/src/app/editor-v2/components/pipeline/pipeline.component.ts b/ui/src/app/editor-v2/components/pipeline/pipeline.component.ts
index 2b56f80..be53fe5 100644
--- a/ui/src/app/editor-v2/components/pipeline/pipeline.component.ts
+++ b/ui/src/app/editor-v2/components/pipeline/pipeline.component.ts
@@ -24,18 +24,22 @@ import {JsplumbService} from "../../services/jsplumb.service";
 import {PipelineEditorService} from "../../services/pipeline-editor.service";
 import {JsplumbBridge} from "../../services/jsplumb-bridge.service";
 import {ShepherdService} from "../../../services/tour/shepherd.service";
-import {Component, Input, OnInit, Pipe} from "@angular/core";
+import {Component, InjectionToken, Input, OnInit, Pipe} from "@angular/core";
 import {
-  InvocablePipelineElementUnion,
+  InvocablePipelineElementUnion, PIPELINE_ELEMENT_TOKEN,
   PipelineElementConfig,
   PipelineElementUnion
 } from "../../model/editor.model";
 import {
+  CustomOutputStrategy,
   DataProcessorInvocation,
   Pipeline,
   SpDataStream
 } from "../../../core-model/gen/streampipes-model";
 import {ObjectProvider} from "../../services/object-provider.service";
+import {PanelDialogService} from "../../dialog/panel/panel-dialog.service";
+import {CustomizeComponent} from "../../dialog/customize/customize.component";
+import {DialogRef} from "../../dialog/panel/dialog-ref";
 
 @Component({
   selector: 'pipeline',
@@ -87,7 +91,8 @@ export class PipelineComponent implements OnInit {
               // TransitionService,
               private ShepherdService: ShepherdService,
               private PipelineValidationService: PipelineValidationService,
-              private RestApi: RestApi) {
+              private RestApi: RestApi,
+              private PanelDialogService: PanelDialogService) {
     this.plumbReady = false;
     this.currentMouseOverElement = "";
     this.currentPipelineModel = new Pipeline();
@@ -281,26 +286,19 @@ export class PipelineComponent implements OnInit {
       var pe = this.ObjectProvider.findElement(info.target.id, this.rawPipelineModel);
       if (pe.settings.openCustomize) {
         this.currentPipelineModel = this.ObjectProvider.makePipeline(this.rawPipelineModel);
-        console.log(this.currentPipelineModel);
         pe.settings.loadingStatus = true;
         this.ObjectProvider.updatePipeline(this.currentPipelineModel)
-            .then(msg => {
-              let data = msg.data;
+            .subscribe(pipelineModificationMessage => {
               pe.settings.loadingStatus = false;
-              if (data.success) {
+              if (pipelineModificationMessage.success) {
                 info.targetEndpoint.setType("token");
                 this.validatePipeline();
-                this.modifyPipeline(data.pipelineModifications);
+                this.modifyPipeline(pipelineModificationMessage.pipelineModifications);
                 var sourceEndpoint = this.JsplumbBridge.selectEndpoints({element: info.targetEndpoint.elementId});
                 if (this.PipelineEditorService.isFullyConnected(pe)) {
                   let payload = pe.payload as InvocablePipelineElementUnion;
                   if ((payload.staticProperties && payload.staticProperties.length > 0) || this.isCustomOutput(pe)) {
-                    this.EditorDialogManager.showCustomizeDialog($("#" +pe.payload.dom), sourceEndpoint, pe.payload, false)
-                        .then(() => {
-                          this.JsplumbService.activateEndpoint(pe.payload.dom, !payload.uncompleted);
-                        }, () => {
-                          this.JsplumbService.activateEndpoint(pe.payload.dom, !payload.uncompleted);
-                        });
+                    this.showCustomizeDialog(pe);
                   } else {
                     //this.$rootScope.$broadcast("SepaElementConfigured", pe.payload.DOM);
                     (pe.payload as InvocablePipelineElementUnion).configured = true;
@@ -308,7 +306,7 @@ export class PipelineComponent implements OnInit {
                 }
               } else {
                 this.JsplumbBridge.detach(info.connection);
-                this.EditorDialogManager.showMatchingErrorDialog(data);
+                this.EditorDialogManager.showMatchingErrorDialog(pipelineModificationMessage);
               }
             });
       }
@@ -338,7 +336,7 @@ export class PipelineComponent implements OnInit {
   isCustomOutput(pe) {
     var custom = false;
     angular.forEach(pe.payload.outputStrategies, strategy => {
-      if (strategy.type == 'org.apache.streampipes.model.output.CustomOutputStrategy') {
+      if (strategy instanceof CustomOutputStrategy) {
         custom = true;
       }
     });
@@ -353,5 +351,26 @@ export class PipelineComponent implements OnInit {
     });
   }
 
+  showCustomizeDialog(pipelineElement: PipelineElementConfig) {
+    const inputMap = {};
+    inputMap["pipelineElement"] = pipelineElement;
+
+    const dialogRef = this.PanelDialogService.open(CustomizeComponent, {
+      width: "400px",
+      title: "Customize " + pipelineElement.payload.name
+    }, inputMap);
+
+    dialogRef.afterClosed().subscribe(c => {
+
+    });
+
+    // this.EditorDialogManager.showCustomizeDialog($("#" +pe.payload.dom), sourceEndpoint, pe.payload, false)
+    //     .then(() => {
+    //       this.JsplumbService.activateEndpoint(pe.payload.dom, !payload.uncompleted);
+    //     }, () => {
+    //       this.JsplumbService.activateEndpoint(pe.payload.dom, !payload.uncompleted);
+    //     });
+  }
+
 
 }
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/dialog/customize/customize.component.css b/ui/src/app/editor-v2/dialog/customize/customize.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/ui/src/app/editor-v2/dialog/customize/customize.component.html b/ui/src/app/editor-v2/dialog/customize/customize.component.html
new file mode 100644
index 0000000..e40d375
--- /dev/null
+++ b/ui/src/app/editor-v2/dialog/customize/customize.component.html
@@ -0,0 +1,18 @@
+<!--
+  ~ 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.
+  ~
+  -->
+
diff --git a/ui/src/app/editor-v2/services/editor.service.ts b/ui/src/app/editor-v2/dialog/customize/customize.component.ts
similarity index 61%
copy from ui/src/app/editor-v2/services/editor.service.ts
copy to ui/src/app/editor-v2/dialog/customize/customize.component.ts
index 42f8cc2..9e9811b 100644
--- a/ui/src/app/editor-v2/services/editor.service.ts
+++ b/ui/src/app/editor-v2/dialog/customize/customize.component.ts
@@ -16,19 +16,26 @@
  *
  */
 
-import {Injectable} from "@angular/core";
-import {HttpClient} from "@angular/common/http";
-import {AuthStatusService} from "../../services/auth-status.service";
-import {TsonLdSerializerService} from "../../platform-services/tsonld-serializer.service";
+import {Component, Input, OnInit} from "@angular/core";
+import {PipelineElementConfig} from "../../model/editor.model";
+import {DialogRef} from "../panel/dialog-ref";
 
-@Injectable()
-export class EditorService {
+@Component({
+  selector: 'customize-pipeline-element',
+  templateUrl: './customize.component.html',
+  styleUrls: ['./customize.component.css']
+})
+export class CustomizeComponent implements OnInit {
 
-    constructor(private http: HttpClient,
-                private authStatusService: AuthStatusService,
-                private tsonLdSerializerService: TsonLdSerializerService) {
-    }
+  @Input()
+  pipelineElement: PipelineElementConfig;
 
+  constructor(private dialogRef: DialogRef<CustomizeComponent>) {
 
+  }
+
+  ngOnInit(): void {
+
+  }
 
 }
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/services/editor.service.ts b/ui/src/app/editor-v2/dialog/panel/dialog-ref.ts
similarity index 56%
copy from ui/src/app/editor-v2/services/editor.service.ts
copy to ui/src/app/editor-v2/dialog/panel/dialog-ref.ts
index 42f8cc2..9cf9e6a 100644
--- a/ui/src/app/editor-v2/services/editor.service.ts
+++ b/ui/src/app/editor-v2/dialog/panel/dialog-ref.ts
@@ -16,19 +16,32 @@
  *
  */
 
-import {Injectable} from "@angular/core";
-import {HttpClient} from "@angular/common/http";
-import {AuthStatusService} from "../../services/auth-status.service";
-import {TsonLdSerializerService} from "../../platform-services/tsonld-serializer.service";
+import {ComponentRef} from "@angular/core";
+import {OverlayRef} from "@angular/cdk/overlay";
+import {Observable, Subject} from "rxjs";
 
-@Injectable()
-export class EditorService {
+export class DialogRef<T> {
+  private _componentInstance: ComponentRef<T>;
+  private subject: Subject<any> = new Subject<any>();
 
-    constructor(private http: HttpClient,
-                private authStatusService: AuthStatusService,
-                private tsonLdSerializerService: TsonLdSerializerService) {
-    }
+  constructor(private overlayRef: OverlayRef) {
+  }
 
+  get componentInstance() {
+    return this._componentInstance;
+  }
 
+  set componentInstance(c: ComponentRef<T>) {
+    this._componentInstance = c;
+  }
+
+  public close(data?: any) {
+    this.overlayRef.dispose();
+    this.subject.next(data);
+  }
+
+  public afterClosed(): Observable<any> {
+    return this.subject;
+  }
 
 }
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/dialog/panel/panel-dialog.component.html b/ui/src/app/editor-v2/dialog/panel/panel-dialog.component.html
new file mode 100644
index 0000000..23c2f5f
--- /dev/null
+++ b/ui/src/app/editor-v2/dialog/panel/panel-dialog.component.html
@@ -0,0 +1,23 @@
+<!--
+  ~ 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 style="display:flex;justify-content:space-between;padding:0.5rem;width:100%">
+    <span class="dialog-title">{{ dialogTitle }}</span>
+    <button mat-button mat-icon-button (click)="closeDialog()"><i class="material-icons">clear</i></button>
+</div>
+<ng-template cdkPortalOutlet #portal></ng-template>
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/services/editor.service.ts b/ui/src/app/editor-v2/dialog/panel/panel-dialog.component.scss
similarity index 62%
copy from ui/src/app/editor-v2/services/editor.service.ts
copy to ui/src/app/editor-v2/dialog/panel/panel-dialog.component.scss
index 42f8cc2..cdeec74 100644
--- a/ui/src/app/editor-v2/services/editor.service.ts
+++ b/ui/src/app/editor-v2/dialog/panel/panel-dialog.component.scss
@@ -16,19 +16,19 @@
  *
  */
 
-import {Injectable} from "@angular/core";
-import {HttpClient} from "@angular/common/http";
-import {AuthStatusService} from "../../services/auth-status.service";
-import {TsonLdSerializerService} from "../../platform-services/tsonld-serializer.service";
-
-@Injectable()
-export class EditorService {
-
-    constructor(private http: HttpClient,
-                private authStatusService: AuthStatusService,
-                private tsonLdSerializerService: TsonLdSerializerService) {
-    }
-
+@import '../../../../scss/sp/colors';
 
+app-dialog-container {
+    width: 100%;
+    display: grid;
+    grid-template-rows: 40px 1fr;
+    padding: 0 10px;
+    background-color: #fff
+}
 
+.dialog-title {
+    font-weight: bold;
+    background: $sp-color-primary;
+    padding:20px;
+    color:white;
 }
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/dialog/panel/panel-dialog.component.ts b/ui/src/app/editor-v2/dialog/panel/panel-dialog.component.ts
new file mode 100644
index 0000000..2ba2715
--- /dev/null
+++ b/ui/src/app/editor-v2/dialog/panel/panel-dialog.component.ts
@@ -0,0 +1,67 @@
+/*
+ * 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 {CdkPortalOutlet, ComponentPortal, Portal} from "@angular/cdk/portal";
+import {
+  Component,
+  EventEmitter,
+  Input,
+  OnInit,
+  Output,
+  ViewChild,
+  ViewEncapsulation
+} from "@angular/core";
+
+@Component({
+  selector: "app-dialog-container",
+  templateUrl: './panel-dialog.component.html',
+  encapsulation: ViewEncapsulation.None,
+  styleUrls: ['./panel-dialog.component.scss']
+})
+export class PanelDialogComponent<T> implements OnInit {
+
+  @Input()
+  dialogTitle = "";
+
+  @Input()
+  comp: ComponentPortal<T>;
+
+  @Output()
+  containerEvent = new EventEmitter<{ key: "CLOSE" }>();
+
+  @ViewChild("portal", {read: CdkPortalOutlet, static: true})
+  portal: CdkPortalOutlet;
+
+  @Input()
+  selectedPortal: Portal<T>;
+
+  constructor() {
+  }
+
+  ngOnInit() {
+  }
+
+  attach() {
+    const c = this.portal.attach(this.selectedPortal);
+    return c.instance;
+  }
+
+  closeDialog() {
+    this.containerEvent.emit({key: "CLOSE"});
+  }
+}
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/dialog/panel/panel-dialog.service.ts b/ui/src/app/editor-v2/dialog/panel/panel-dialog.service.ts
new file mode 100644
index 0000000..69947ac
--- /dev/null
+++ b/ui/src/app/editor-v2/dialog/panel/panel-dialog.service.ts
@@ -0,0 +1,97 @@
+/*
+ * 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 {ComponentType, Overlay, OverlayRef,} from "@angular/cdk/overlay";
+import {ComponentPortal, PortalInjector,} from "@angular/cdk/portal";
+import {PanelDialogComponent} from "./panel-dialog.component";
+import {DialogConfig} from "../../model/editor.model";
+import {ComponentRef, Injectable, Injector} from "@angular/core";
+import {DialogRef} from "./dialog-ref";
+
+@Injectable({
+  providedIn: "root"
+})
+export class PanelDialogService {
+
+  constructor(private overlay: Overlay, private injector: Injector) {
+
+  }
+
+  public open<T>(component: ComponentType<T>,
+                 config?: DialogConfig,
+                 inputMap?: Object): DialogRef<T> {
+    config = config || {width: "auto", title: ""};
+
+    const positionStrategy = this.overlay
+        .position()
+        .global()
+        .top("0")
+        .right("0");
+
+    const overlay = this.overlay.create({
+      hasBackdrop: true,
+      positionStrategy,
+      panelClass: "dialog-container",
+      width: config.width,
+      maxWidth: "90vw",
+      height: "100vh"
+    });
+
+    const dialogPreview = new ComponentPortal(PanelDialogComponent);
+    const dialogContainerRef = overlay.attach(dialogPreview);
+    dialogContainerRef.instance.dialogTitle = config.title;
+    const dialogRef = new DialogRef<T>(overlay);
+
+    const injector = this.createInjector(dialogRef);
+    dialogContainerRef.instance.selectedPortal = new ComponentPortal(component,
+        null, injector);
+    dialogRef.componentInstance = dialogContainerRef.instance.attach();
+
+    Object.keys(inputMap).forEach(key => {
+      dialogRef.componentInstance[key] = inputMap[key];
+    })
+
+    this.applyDialogProperties(dialogContainerRef, overlay, config);
+
+    return dialogRef;
+  }
+
+  private applyDialogProperties(componentRef: ComponentRef<any>,
+                                overlayRef: OverlayRef,
+                                config: DialogConfig
+  ) {
+    componentRef.instance.containerEvent.subscribe(e => {
+      if (e.key === "CLOSE") {
+        overlayRef.dispose();
+      }
+    });
+    if (!config.disableClose) {
+      overlayRef.backdropClick().subscribe(() => overlayRef.dispose());
+    }
+  }
+
+  private createInjector<T>(dialogRef: DialogRef<T>) {
+    const injectorMap = new WeakMap();
+    injectorMap.set(DialogRef, dialogRef);
+    return new PortalInjector(this.injector, injectorMap);
+  }
+}
+
+
+
+
diff --git a/ui/src/app/editor-v2/editor.module.ts b/ui/src/app/editor-v2/editor.module.ts
index 25bfd62..936e1f2 100644
--- a/ui/src/app/editor-v2/editor.module.ts
+++ b/ui/src/app/editor-v2/editor.module.ts
@@ -43,6 +43,11 @@ import {PipelineComponent} from "./components/pipeline/pipeline.component";
 import {ObjectProvider} from "./services/object-provider.service";
 import {PipelineElementOptionsComponent} from "./components/pipeline-element-options/pipeline-element-options.component";
 import {PipelineElementRecommendationService} from "./services/pipeline-element-recommendation.service";
+import {PortalModule} from "@angular/cdk/portal";
+import {OverlayModule} from "@angular/cdk/overlay";
+import {PanelDialogComponent} from "./dialog/panel/panel-dialog.component";
+import {PanelDialogService} from "./dialog/panel/panel-dialog.service";
+import {CustomizeComponent} from "./dialog/customize/customize.component";
 
 @NgModule({
     imports: [
@@ -55,14 +60,18 @@ import {PipelineElementRecommendationService} from "./services/pipeline-element-
         CustomMaterialModule,
         FormsModule,
         ConnectModule,
+        PortalModule,
+        OverlayModule
     ],
     declarations: [
+        CustomizeComponent,
         EditorComponent,
         PipelineAssemblyComponent,
         PipelineElementIconStandComponent,
         PipelineElementComponent,
         PipelineElementOptionsComponent,
-        PipelineComponent
+        PipelineComponent,
+        PanelDialogComponent
     ],
     providers: [
         EditorService,
@@ -76,6 +85,7 @@ import {PipelineElementRecommendationService} from "./services/pipeline-element-
         JsplumbService,
         JsplumbConfigService,
         ObjectProvider,
+        PanelDialogService,
         PipelineEditorService,
         PipelinePositioningService,
         PipelineValidationService,
@@ -98,6 +108,7 @@ import {PipelineElementRecommendationService} from "./services/pipeline-element-
     ],
     entryComponents: [
         EditorComponent,
+        PanelDialogComponent
     ]
 })
 export class EditorModule {
diff --git a/ui/src/app/editor-v2/model/editor.model.ts b/ui/src/app/editor-v2/model/editor.model.ts
index 025fbdc..9a98ce9 100644
--- a/ui/src/app/editor-v2/model/editor.model.ts
+++ b/ui/src/app/editor-v2/model/editor.model.ts
@@ -22,6 +22,7 @@ import {
   SpDataStream
 } from "../../core-model/gen/streampipes-model";
 import {EditorConstants} from "../constants/editor.constants";
+import {InjectionToken} from "@angular/core";
 
 export type PipelineElementHolder = {
   [key: string]: Array<PipelineElementUnion>;
@@ -51,6 +52,15 @@ export enum PipelineElementType {
   DataSink
 }
 
+export interface DialogConfig {
+  width?: string;
+  disableClose?: boolean;
+  autoFocus?: boolean;
+  title: string;
+}
+
 export type PipelineElementUnion = SpDataSet | SpDataStream | DataProcessorInvocation | DataSinkInvocation;
 
-export type InvocablePipelineElementUnion = DataProcessorInvocation | DataSinkInvocation;
\ No newline at end of file
+export type InvocablePipelineElementUnion = DataProcessorInvocation | DataSinkInvocation;
+
+export const PIPELINE_ELEMENT_TOKEN = new InjectionToken<{}>('pipelineElement');
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/services/editor.service.ts b/ui/src/app/editor-v2/services/editor.service.ts
index 42f8cc2..309c386 100644
--- a/ui/src/app/editor-v2/services/editor.service.ts
+++ b/ui/src/app/editor-v2/services/editor.service.ts
@@ -20,13 +20,37 @@ import {Injectable} from "@angular/core";
 import {HttpClient} from "@angular/common/http";
 import {AuthStatusService} from "../../services/auth-status.service";
 import {TsonLdSerializerService} from "../../platform-services/tsonld-serializer.service";
+import {
+    DataProcessorInvocation, PipelineElementRecommendationMessage,
+    PipelineModificationMessage
+} from "../../core-model/gen/streampipes-model";
+import {Observable} from "rxjs";
 
 @Injectable()
 export class EditorService {
 
     constructor(private http: HttpClient,
-                private authStatusService: AuthStatusService,
-                private tsonLdSerializerService: TsonLdSerializerService) {
+                private authStatusService: AuthStatusService) {
+    }
+
+    recommendPipelineElement(pipeline): Observable<PipelineElementRecommendationMessage> {
+        return this.http.post(this.pipelinesResourceUrl +"/recommend", pipeline)
+            .map(data => PipelineElementRecommendationMessage.fromData(data as any));
+    }
+
+    updatePartialPipeline(pipeline): Observable<PipelineModificationMessage> {
+        return this.http.post(this.pipelinesResourceUrl +"/update", pipeline)
+            .map(data => {
+                return PipelineModificationMessage.fromData(data as any);
+            });
+    }
+
+    private get baseUrl() {
+        return '/streampipes-backend';
+    }
+
+    private get pipelinesResourceUrl() {
+        return this.baseUrl + '/api/v2/users/' + this.authStatusService.email + '/pipelines'
     }
 
 
diff --git a/ui/src/app/editor-v2/services/jsplumb.service.ts b/ui/src/app/editor-v2/services/jsplumb.service.ts
index e91e841..2c773e5 100644
--- a/ui/src/app/editor-v2/services/jsplumb.service.ts
+++ b/ui/src/app/editor-v2/services/jsplumb.service.ts
@@ -22,6 +22,11 @@ import {Inject, Injectable} from "@angular/core";
 import {PipelineElementConfig, PipelineElementUnion} from "../model/editor.model";
 import {PipelineElementTypeUtils} from "../utils/editor.utils";
 import * as angular from "angular";
+import {
+    DataProcessorInvocation, DataSinkInvocation,
+    SpDataSet,
+    SpDataStream
+} from "../../core-model/gen/streampipes-model";
 
 @Injectable()
 export class JsplumbService {
@@ -147,7 +152,7 @@ export class JsplumbService {
         let pipelineElementConfig = {} as PipelineElementConfig;
         pipelineElementConfig.type = PipelineElementTypeUtils
             .toCssShortHand(PipelineElementTypeUtils.fromType(pipelineElement))
-        pipelineElementConfig.payload = angular.copy(pipelineElement)
+        pipelineElementConfig.payload = this.clone(pipelineElement);
         pipelineElementConfig.settings = {connectable: connectable,
             openCustomize: !(pipelineElement as any).configured,
             preview: isPreview,
@@ -166,6 +171,18 @@ export class JsplumbService {
         return pipelineElementConfig;
     }
 
+    clone(pipelineElement: PipelineElementUnion) {
+        if (pipelineElement instanceof SpDataSet) {
+            return SpDataSet.fromData(pipelineElement, new SpDataSet());
+        } else if (pipelineElement instanceof SpDataStream) {
+            return SpDataStream.fromData(pipelineElement, new SpDataStream());
+        } else if (pipelineElement instanceof DataProcessorInvocation) {
+            return DataProcessorInvocation.fromData(pipelineElement, new DataProcessorInvocation());
+        } else {
+            return DataSinkInvocation.fromData(pipelineElement, new DataSinkInvocation());
+        }
+    }
+
     makeId(count) {
         var text = "";
         var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
diff --git a/ui/src/app/editor-v2/services/object-provider.service.ts b/ui/src/app/editor-v2/services/object-provider.service.ts
index bd07a51..bbf1cff 100644
--- a/ui/src/app/editor-v2/services/object-provider.service.ts
+++ b/ui/src/app/editor-v2/services/object-provider.service.ts
@@ -22,12 +22,14 @@ import {RestApi} from "../../services/rest-api.service";
 import {JsplumbBridge} from "./jsplumb-bridge.service";
 import {InvocablePipelineElementUnion, PipelineElementConfig} from "../model/editor.model";
 import {InvocableStreamPipesEntity, Pipeline} from "../../core-model/gen/streampipes-model";
+import {EditorService} from "./editor.service";
 
 @Injectable()
 export class ObjectProvider {
 
     constructor(private RestApi: RestApi,
-                private JsplumbBridge: JsplumbBridge) {
+                private JsplumbBridge: JsplumbBridge,
+                private EditorService: EditorService) {
     }
 
     prepareElement(pipelineElement: InvocablePipelineElementUnion) {
@@ -91,7 +93,7 @@ export class ObjectProvider {
     }
 
     updatePipeline(pipeline: Pipeline) {
-        return this.RestApi.updatePartialPipeline(pipeline);
+        return this.EditorService.updatePartialPipeline(pipeline);
     };
 
     storePipeline(pipeline) {
diff --git a/ui/src/app/services/rest-api.service.ts b/ui/src/app/services/rest-api.service.ts
index bceb0bd..ad9491e 100644
--- a/ui/src/app/services/rest-api.service.ts
+++ b/ui/src/app/services/rest-api.service.ts
@@ -268,15 +268,7 @@ export class RestApi {
         return this.$http.post(this.urlBase() +"/pe/options", resolvableOptionsParameterRequest);
     }
 
-    recommendPipelineElement(pipeline) {
-        return this.$http.post(this.urlBase() +"/pipelines/recommend", pipeline);
-    }
 
-    updatePartialPipeline(pipeline) {
-        return this.$http.post(this.urlBase() +"/pipelines/update", pipeline, {
-            ignoreLoadingBar: true
-        });
-    }
 
     updateDataSet(dataSet) {
         return this.$http.post(this.urlBase() +"/pipelines/update/dataset", dataSet);