This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch 3119-refactor-pipeline-editor-ui-components
in repository https://gitbox.apache.org/repos/asf/streampipes.git
The following commit(s) were added to
refs/heads/3119-refactor-pipeline-editor-ui-components by this push:
new 7dcb1e2d14 chore(#3119): Improve pipeline editor component structure
7dcb1e2d14 is described below
commit 7dcb1e2d14060a066f8710ca1da54a79723ea19e
Author: Dominik Riemer <[email protected]>
AuthorDate: Fri Aug 9 15:49:46 2024 +0200
chore(#3119): Improve pipeline editor component structure
---
...e-assembly-drawing-area-pan-zoom.component.html | 48 +++
...-assembly-drawing-area-pan-zoom.component.scss} | 82 +----
...ine-assembly-drawing-area-pan-zoom.component.ts | 142 +++++++++
.../pipeline-assembly-drawing-area.component.html | 54 ++++
.../pipeline-assembly-drawing-area.component.scss} | 36 ++-
.../pipeline-assembly-drawing-area.component.ts | 188 ++++++++++++
...assembly-options-pipeline-cache.component.html} | 35 ++-
...assembly-options-pipeline-cache.component.scss} | 11 +-
...ne-assembly-options-pipeline-cache.component.ts | 66 ++++
.../pipeline-assembly-options.component.html | 89 ++++++
.../pipeline-assembly-options.component.scss} | 10 +-
.../pipeline-assembly-options.component.ts | 135 ++++++++
.../pipeline-assembly.component.html | 194 ++----------
.../pipeline-assembly.component.scss | 133 +-------
.../pipeline-assembly.component.ts | 339 +++------------------
.../pipeline-element-icon-stand-row.component.html | 0
.../pipeline-element-icon-stand-row.component.scss | 0
.../pipeline-element-icon-stand-row.component.ts | 6 +-
.../pipeline-element-icon-stand.component.ts | 2 -
.../dropped-pipeline-element.component.html | 103 +++++++
.../dropped-pipeline-element.component.ts | 79 +++++
.../components/pipeline/pipeline.component.html | 105 ++-----
.../components/pipeline/pipeline.component.ts | 180 +++--------
ui/src/app/editor/editor.component.html | 7 +-
ui/src/app/editor/editor.component.ts | 82 ++++-
ui/src/app/editor/editor.module.ts | 19 +-
.../app/editor/services/jsplumb-factory.service.ts | 44 +--
.../services/pipeline-positioning.service.ts | 4 -
.../elements/pipeline-elements-row.component.ts | 2 +-
.../preview/pipeline-preview.component.html | 25 +-
.../preview/pipeline-preview.component.ts | 74 ++---
.../pipeline-details.component.html | 1 -
32 files changed, 1255 insertions(+), 1040 deletions(-)
diff --git
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area-pan-zoom/pipeline-assembly-drawing-area-pan-zoom.component.html
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area-pan-zoom/pipeline-assembly-drawing-area-pan-zoom.component.html
new file mode 100644
index 0000000000..a14b4cc079
--- /dev/null
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area-pan-zoom/pipeline-assembly-drawing-area-pan-zoom.component.html
@@ -0,0 +1,48 @@
+<!--
+ ~ 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="pan-control">
+ <div class="pan-zoom-control-buttons">
+ <div class="pan-zoom-button pan-left" (click)="panLeft()">
+ <i class="material-icons">keyboard_arrow_left</i>
+ </div>
+ <div class="pan-zoom-button pan-right" (click)="panRight()">
+ <i class="material-icons">keyboard_arrow_right</i>
+ </div>
+ <div class="pan-zoom-button pan-home" (click)="panHome()">
+ <i class="material-icons">home</i>
+ </div>
+ <div class="pan-zoom-button pan-up" (click)="panUp()">
+ <i class="material-icons">keyboard_arrow_up</i>
+ </div>
+ <div class="pan-zoom-button pan-down" (click)="panDown()">
+ <i class="material-icons">keyboard_arrow_down</i>
+ </div>
+ </div>
+</div>
+<div class="zoom-control">
+ <div class="pan-zoom-control-buttons">
+ <div class="pan-zoom-button zoom-in" (click)="zoomIn()">
+ <i class="material-icons">zoom_in</i>
+ </div>
+ <mat-divider class="zoom-divider"></mat-divider>
+ <div class="pan-zoom-button zoom-out" (click)="zoomOut()">
+ <i class="material-icons">zoom_out</i>
+ </div>
+ </div>
+</div>
diff --git
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.scss
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area-pan-zoom/pipeline-assembly-drawing-area-pan-zoom.component.scss
similarity index 56%
copy from
ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.scss
copy to
ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area-pan-zoom/pipeline-assembly-drawing-area-pan-zoom.component.scss
index 7d714593ef..f68dd4723f 100644
---
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.scss
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area-pan-zoom/pipeline-assembly-drawing-area-pan-zoom.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
* 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.
@@ -16,65 +16,6 @@
*
*/
-@import '../../../../scss/_variables.scss';
-
-.mat-spinner-color::ng-deep svg circle {
- stroke: var(--color-accent) !important;
-}
-
-.pipeline-cache-progress {
- display: inline-block;
-}
-
-.pipeline-cache-block {
- height: 100%;
- margin-left: 15px;
-}
-
-.outerAssembly {
- left: 0;
- top: 0;
- display: flex;
- flex: 1 1 0;
- overflow: hidden;
-}
-
-.pipeline-canvas-outer {
- position: relative;
- width: 100%;
- height: 100%;
-}
-
-.canvas {
- //overflow: scroll;
- position: relative;
- left: 0px;
- top: 0px;
- height: 3000px;
- width: 4000px;
- z-index: 0;
- margin: -1px;
-
- background-color: var(--color-bg-1);
- background-image: var(--canvas-color);
- background-size: 15px 15px;
-}
-
-.pipeline-assembly-options {
- padding-left: 5px;
- border: 1px solid var(--color-bg-3);
- //background: #f6f6f6;
-}
-
-.assembly-border {
- border: 1px solid var(--color-bg-3);
-}
-
-.jtk-surface-nopan {
- overflow: scroll !important;
- cursor: default;
-}
-
.zoom-control {
position: absolute;
right: 10px;
@@ -87,15 +28,6 @@
border-radius: 10px;
}
-.pipeline-validation-hint {
- position: absolute;
- right: 10px;
- top: 20px;
- z-index: 10;
- background: var(--color-bg-1);
- box-shadow: 0.175em 0.175em 0 0 rgba(15, 28, 63, 0.125);
-}
-
.pan-control {
position: absolute;
right: 60px;
@@ -157,15 +89,3 @@
left: 28px;
top: 30px;
}
-
-.assembly-options-divider {
- width: 1px;
- height: 70%;
- margin-left: 10px;
- margin-right: 10px;
- background: var(--color-bg-3);
-}
-
-.color-warn {
- color: var(--color-warn);
-}
diff --git
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area-pan-zoom/pipeline-assembly-drawing-area-pan-zoom.component.ts
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area-pan-zoom/pipeline-assembly-drawing-area-pan-zoom.component.ts
new file mode 100644
index 0000000000..6685177b79
--- /dev/null
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area-pan-zoom/pipeline-assembly-drawing-area-pan-zoom.component.ts
@@ -0,0 +1,142 @@
+/*
+ * 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 {
+ AfterViewInit,
+ Component,
+ ElementRef,
+ Input,
+ OnDestroy,
+ OnInit,
+} from '@angular/core';
+import { JsplumbBridge } from '../../../../services/jsplumb-bridge.service';
+import Panzoom, { PanzoomObject } from '@panzoom/panzoom';
+import { Subscription } from 'rxjs';
+import { PipelineElementDraggedService } from
'../../../../services/pipeline-element-dragged.service';
+
+@Component({
+ selector: 'sp-pipeline-assembly-drawing-area-pan-zoom',
+ templateUrl: './pipeline-assembly-drawing-area-pan-zoom.component.html',
+ styleUrls: ['./pipeline-assembly-drawing-area-pan-zoom.component.scss'],
+})
+export class PipelineAssemblyDrawingAreaPanZoomComponent
+ implements OnInit, AfterViewInit, OnDestroy
+{
+ @Input()
+ jsplumbBridge: JsplumbBridge;
+
+ @Input()
+ pipelineCanvas: ElementRef;
+
+ panzoom: PanzoomObject;
+ moveSub: Subscription;
+ currentZoomLevel = 1;
+
+ constructor(
+ private pipelineElementDraggedService: PipelineElementDraggedService,
+ ) {}
+
+ ngOnInit() {
+ this.moveSub =
+
this.pipelineElementDraggedService.pipelineElementMovedSubject.subscribe(
+ position => {
+ 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) {
+ yOffset = -10;
+ }
+ if (position.x + currentPan.x > offsetWidth - 100) {
+ xOffset = -10;
+ }
+ if (xOffset < 0 || yOffset < 0) {
+ this.pan(xOffset, yOffset);
+ }
+ },
+ );
+ }
+
+ ngAfterViewInit() {
+ const elem = document.getElementById('assembly');
+ this.panzoom = Panzoom(elem, {
+ maxScale: 5,
+ excludeClass: 'sp-no-pan',
+ canvas: true,
+ contain: 'outside',
+ });
+ }
+
+ zoomOut() {
+ this.doZoom(true);
+ }
+
+ zoomIn() {
+ this.doZoom(false);
+ }
+
+ doZoom(zoomOut) {
+ zoomOut ? this.panzoom.zoomOut() : this.panzoom.zoomIn();
+ this.currentZoomLevel = this.panzoom.getScale();
+ this.jsplumbBridge.setZoom(this.currentZoomLevel);
+ this.jsplumbBridge.repaintEverything();
+ }
+
+ panLeft() {
+ this.pan(100, 0);
+ }
+
+ panRight() {
+ this.pan(-100, 0);
+ }
+
+ panUp() {
+ this.pan(0, 100);
+ }
+
+ panDown() {
+ this.pan(0, -100);
+ }
+
+ panHome() {
+ this.panAbsolute(0, 0);
+ }
+
+ pan(xOffset: number, yOffset: number) {
+ 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);
+ }
+
+ panAbsolute(x: number, y: number) {
+ this.panzoom.pan(x, y);
+ }
+
+ resetZoom(): void {
+ this.currentZoomLevel = 1;
+ this.jsplumbBridge.setZoom(this.currentZoomLevel);
+ }
+
+ ngOnDestroy() {
+ this.moveSub?.unsubscribe();
+ }
+}
diff --git
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.html
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.html
new file mode 100644
index 0000000000..98819f88e0
--- /dev/null
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.html
@@ -0,0 +1,54 @@
+<!--
+ ~ 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="pipeline-validation-hint">
+ <sp-error-hint
+ *ngIf="!readonly"
+ [displayMessages]="!isPipelineAssemblyEmpty()"
+ [errorMessages]="pipelineValidationService.errorMessages"
+ [validationString]="'Pipeline'"
+ >
+ </sp-error-hint>
+</div>
+
+<sp-pipeline-assembly-drawing-area-pan-zoom
+ #zoomComponent
+ [pipelineCanvas]="pipelineCanvas"
+ [jsplumbBridge]="jsplumbBridge"
+>
+</sp-pipeline-assembly-drawing-area-pan-zoom>
+
+<div class="pipeline-canvas-outer" #outerCanvas>
+ <sp-pipeline
+ class="canvas jtk-surface"
+ id="assembly"
+ #pipelineComponent
+ [pipelineValid]="pipelineValid"
+ [rawPipelineModel]="rawPipelineModel"
+ [allElements]="allElements"
+ [readonly]="readonly"
+ [metricsInfo]="metricsInfo"
+ [previewModeActive]="previewModeActive"
+ [pipelinePreview]="pipelinePreview"
+ (triggerPipelineCacheUpdateEmitter)="
+ triggerPipelineCacheUpdateEmitter.emit()
+ "
+ style="position: absolute"
+ >
+ </sp-pipeline>
+</div>
diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.scss
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.scss
similarity index 56%
copy from ui/src/app/editor/components/pipeline/pipeline.component.scss
copy to
ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.scss
index 13cbc4aacb..41e539ef31 100644
--- a/ui/src/app/editor/components/pipeline/pipeline.component.scss
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
* 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.
@@ -15,3 +15,37 @@
* limitations under the License.
*
*/
+
+.pipeline-validation-hint {
+ position: absolute;
+ right: 10px;
+ top: 20px;
+ z-index: 10;
+ background: var(--color-bg-1);
+ box-shadow: 0.175em 0.175em 0 0 rgba(15, 28, 63, 0.125);
+}
+
+.jtk-surface-nopan {
+ overflow: scroll !important;
+ cursor: default;
+}
+
+.pipeline-canvas-outer {
+ position: relative;
+ width: 100%;
+ height: 100%;
+}
+
+.canvas {
+ position: relative;
+ left: 0;
+ top: 0;
+ height: 3000px;
+ width: 4000px;
+ z-index: 0;
+ margin: -1px;
+
+ background-color: var(--color-bg-1);
+ background-image: var(--canvas-color);
+ background-size: 15px 15px;
+}
diff --git
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.ts
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.ts
new file mode 100644
index 0000000000..5169abe08e
--- /dev/null
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.ts
@@ -0,0 +1,188 @@
+/*
+ * 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,
+ ElementRef,
+ EventEmitter,
+ Input,
+ NgZone,
+ OnInit,
+ Output,
+ ViewChild,
+} from '@angular/core';
+import { JsplumbBridge } from '../../../services/jsplumb-bridge.service';
+import { PipelineComponent } from '../../pipeline/pipeline.component';
+import {
+ PipelineElementConfig,
+ PipelineElementUnion,
+} from '../../../model/editor.model';
+import { PipelineAssemblyDrawingAreaPanZoomComponent } from
'./pipeline-assembly-drawing-area-pan-zoom/pipeline-assembly-drawing-area-pan-zoom.component';
+import { PipelineValidationService } from
'../../../services/pipeline-validation.service';
+import {
+ PipelineCanvasMetadata,
+ PipelinePreviewModel,
+ SpMetricsEntry,
+} from '@streampipes/platform-services';
+import { EditorService } from '../../../services/editor.service';
+import { PipelinePositioningService } from
'../../../services/pipeline-positioning.service';
+import { HttpDownloadProgressEvent } from '@angular/common/http';
+import { LivePreviewService } from '../../../../services/live-preview.service';
+import { ObjectProvider } from '../../../services/object-provider.service';
+import { Subscription } from 'rxjs';
+
+@Component({
+ selector: 'sp-pipeline-assembly-drawing-area',
+ templateUrl: './pipeline-assembly-drawing-area.component.html',
+ styleUrls: ['./pipeline-assembly-drawing-area.component.scss'],
+})
+export class PipelineAssemblyDrawingAreaComponent implements OnInit {
+ @Input()
+ jsplumbBridge: JsplumbBridge;
+
+ @Input()
+ allElements: PipelineElementUnion[];
+
+ @Input()
+ rawPipelineModel: PipelineElementConfig[];
+
+ @Input()
+ pipelineCanvasMetadata: PipelineCanvasMetadata;
+
+ @Input()
+ pipelineCanvasMetadataAvailable: boolean;
+
+ @Input()
+ previewModeActive: boolean;
+
+ @Input()
+ readonly: boolean;
+
+ @Input()
+ metricsInfo: Record<string, SpMetricsEntry>;
+
+ @Output()
+ triggerPipelineCacheUpdateEmitter: EventEmitter<void> = new EventEmitter();
+
+ pipelineValid = false;
+ pipelinePreview: PipelinePreviewModel;
+ pipelinePreviewSub: Subscription;
+
+ @ViewChild('pipelineComponent')
+ pipelineComponent: PipelineComponent;
+
+ @ViewChild('zoomComponent')
+ zoomComponent: PipelineAssemblyDrawingAreaPanZoomComponent;
+ @ViewChild('outerCanvas') pipelineCanvas: ElementRef;
+
+ constructor(
+ public pipelineValidationService: PipelineValidationService,
+ private ngZone: NgZone,
+ private editorService: EditorService,
+ private pipelinePositioningService: PipelinePositioningService,
+ private livePreviewService: LivePreviewService,
+ private objectProvider: ObjectProvider,
+ ) {}
+
+ ngOnInit(): void {
+ if (this.rawPipelineModel.length > 0) {
+ this.displayPipelineInEditor(
+ !this.pipelineCanvasMetadataAvailable,
+ this.pipelineCanvasMetadata,
+ );
+ }
+ }
+
+ isPipelineAssemblyEmpty() {
+ return (
+ this.rawPipelineModel.length === 0 ||
+ this.rawPipelineModel.every(pe => pe.settings.disabled)
+ );
+ }
+
+ displayPipelineInEditor(
+ autoLayout: boolean,
+ pipelineCanvasMetadata?: PipelineCanvasMetadata,
+ ): void {
+ setTimeout(() => {
+ this.pipelinePositioningService.displayPipeline(
+ this.rawPipelineModel,
+ '#assembly',
+ false,
+ autoLayout,
+ pipelineCanvasMetadata,
+ );
+
+ this.editorService.makePipelineAssemblyEmpty(false);
+ this.ngZone.run(() => {
+ this.pipelineValid =
+ this.pipelineValidationService.isValidPipeline(
+ this.rawPipelineModel.filter(
+ pe => !pe.settings.disabled,
+ ),
+ false,
+ );
+ });
+ if (!this.readonly) {
+ this.pipelineComponent.triggerPipelineModification();
+ }
+ });
+ }
+
+ initiatePipelineElementPreview() {
+ if (!this.previewModeActive) {
+ const pipeline = this.objectProvider.makePipeline(
+ this.rawPipelineModel,
+ );
+ this.editorService
+ .initiatePipelinePreview(pipeline)
+ .subscribe(response => {
+ this.pipelinePreview = response;
+ this.previewModeActive = true;
+ this.pipelinePreviewSub = this.editorService
+ .getPipelinePreviewResult(response.previewId)
+ .subscribe(res => {
+ const data = this.livePreviewService.convert(
+ res as HttpDownloadProgressEvent,
+ );
+ this.livePreviewService.eventSub.next(data);
+ });
+ });
+ } else {
+ this.deletePipelineElementPreview(false);
+ }
+ }
+
+ deletePipelineElementPreview(resume: boolean) {
+ if (this.previewModeActive) {
+ this.pipelinePreviewSub?.unsubscribe();
+ this.editorService
+ .deletePipelinePreviewRequest(this.pipelinePreview.previewId)
+ .subscribe(() => {
+ this.previewModeActive = false;
+ if (resume) {
+ this.initiatePipelineElementPreview();
+ }
+ });
+ }
+ }
+
+ resetZoom(): void {
+ this.zoomComponent.resetZoom();
+ }
+}
diff --git
a/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options-pipeline-cache/pipeline-assembly-options-pipeline-cache.component.html
similarity index 53%
copy from
ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
copy to
ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options-pipeline-cache/pipeline-assembly-options-pipeline-cache.component.html
index ca4a4fc397..7a450fafce 100644
---
a/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options-pipeline-cache/pipeline-assembly-options-pipeline-cache.component.html
@@ -16,16 +16,31 @@
~
-->
-<div class="outer-assembly-preview">
- <div class="pipeline-canvas-outer canvas-preview-inner">
- <div id="{{ jspcanvas }}" class="canvas-preview">
- <sp-pipeline
- [canvasId]="jspcanvas"
- [metricsInfo]="metricsInfo"
- [rawPipelineModel]="rawPipelineModel"
- [preview]="true"
- ></sp-pipeline>
+<div
+ fxLayout="column"
+ fxLayoutAlign="start center"
+ class="pipeline-cache-block"
+>
+ <div
+ fxFlex="100"
+ fxLayoutAlign="start center"
+ fxLayout="row"
+ *ngIf="pipelineCached || pipelineCacheRunning"
+ >
+ <div fxLayout="row" fxLayoutAlign="start center">
+ <mat-spinner
+ [mode]="'indeterminate'"
+ color="accent"
+ [diameter]="15"
+ *ngIf="pipelineCacheRunning"
+ ></mat-spinner>
+ <span
+ > {{
+ pipelineCacheRunning
+ ? ' Saving pipeline modifications'
+ : 'All pipeline modifications saved.'
+ }}</span
+ >
</div>
</div>
- <ng-content></ng-content>
</div>
diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.scss
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options-pipeline-cache/pipeline-assembly-options-pipeline-cache.component.scss
similarity index 86%
copy from ui/src/app/editor/components/pipeline/pipeline.component.scss
copy to
ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options-pipeline-cache/pipeline-assembly-options-pipeline-cache.component.scss
index 13cbc4aacb..28eafec0a9 100644
--- a/ui/src/app/editor/components/pipeline/pipeline.component.scss
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options-pipeline-cache/pipeline-assembly-options-pipeline-cache.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
* 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.
@@ -15,3 +15,12 @@
* limitations under the License.
*
*/
+
+.pipeline-cache-progress {
+ display: inline-block;
+}
+
+.pipeline-cache-block {
+ height: 100%;
+ margin-left: 15px;
+}
diff --git
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options-pipeline-cache/pipeline-assembly-options-pipeline-cache.component.ts
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options-pipeline-cache/pipeline-assembly-options-pipeline-cache.component.ts
new file mode 100644
index 0000000000..5784af4cea
--- /dev/null
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options-pipeline-cache/pipeline-assembly-options-pipeline-cache.component.ts
@@ -0,0 +1,66 @@
+/*
+ * 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 } from '@angular/core';
+import { PipelineElementConfig } from '../../../../model/editor.model';
+import { forkJoin } from 'rxjs';
+import { PipelinePositioningService } from
'../../../../services/pipeline-positioning.service';
+import { EditorService } from '../../../../services/editor.service';
+import { PipelineCanvasMetadata } from '@streampipes/platform-services';
+
+@Component({
+ selector: 'sp-pipeline-assembly-options-pipeline-cache',
+ templateUrl: './pipeline-assembly-options-pipeline-cache.component.html',
+ styleUrls: ['./pipeline-assembly-options-pipeline-cache.component.scss'],
+})
+export class PipelineAssemblyOptionsPipelineCacheComponent {
+ pipelineCached = false;
+ pipelineCacheRunning = false;
+
+ @Input()
+ rawPipelineModel: PipelineElementConfig[];
+
+ @Input()
+ pipelineCanvasMetadata: PipelineCanvasMetadata;
+
+ constructor(
+ private pipelinePositioningService: PipelinePositioningService,
+ private editorService: EditorService,
+ ) {}
+
+ triggerPipelineCacheUpdate() {
+ setTimeout(() => {
+ this.pipelineCacheRunning = true;
+ this.pipelineCached = false;
+ this.pipelineCanvasMetadata =
+
this.pipelinePositioningService.collectPipelineElementPositions(
+ this.pipelineCanvasMetadata,
+ this.rawPipelineModel,
+ );
+ forkJoin([
+ this.editorService.updateCachedPipeline(this.rawPipelineModel),
+ this.editorService.updateCachedCanvasMetadata(
+ this.pipelineCanvasMetadata,
+ ),
+ ]).subscribe(() => {
+ this.pipelineCacheRunning = false;
+ this.pipelineCached = true;
+ });
+ });
+ }
+}
diff --git
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options.component.html
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options.component.html
new file mode 100644
index 0000000000..bbef21c3be
--- /dev/null
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options.component.html
@@ -0,0 +1,89 @@
+<!--
+ ~ 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 fxFlex="100" fxLayout="row" fxLayoutAlign="start center">
+ <button
+ mat-button
+ mat-raised-button
+ color="accent"
+ matTooltip="Save Pipeline"
+ [matTooltipPosition]="'above'"
+ [disabled]="!pipelineValidationService.pipelineValid"
+ (click)="savePipelineEmitter.emit()"
+ type="submit"
+ data-cy="sp-editor-save-pipeline"
+ >
+ <div fxLayoutAlign="start center" fxLayout="row">
+ <i class="material-icons">save</i>
+ <span> Save pipeline</span>
+ </div>
+ </button>
+ <span class="assembly-options-divider"></span>
+ <button
+ mat-button
+ color="accent"
+ matTooltip="Data Preview"
+ [matTooltipPosition]="'above'"
+ (click)="togglePreviewEmitter.emit()"
+ [disabled]="isPipelineAssemblyEmpty()"
+ >
+ <div fxLayoutAlign="start center" fxLayout="row">
+ <i class="material-icons">visibility</i>
+ <span *ngIf="!previewModeActive"> Enable live preview</span>
+ <span *ngIf="previewModeActive"> Disable live preview</span>
+ </div>
+ </button>
+ <span class="assembly-options-divider"></span>
+ <button
+ color="accent"
+ mat-icon-button
+ matTooltip="Auto Layout"
+ [matTooltipPosition]="'above'"
+ (click)="autoLayout()"
+ >
+ <i class="material-icons">settings_overscan</i>
+ </button>
+ <button
+ color="accent"
+ mat-icon-button
+ matTooltip="Add pipeline element"
+ [matTooltipPosition]="'above'"
+ (click)="openDiscoverDialog()"
+ data-cy="sp-editor-add-pipeline-element"
+ >
+ <i class="material-icons">add</i>
+ </button>
+ <sp-pipeline-assembly-options-pipeline-cache
+ [rawPipelineModel]="rawPipelineModel"
+ [pipelineCanvasMetadata]="pipelineCanvasMetadata"
+ #assemblyOptionsPipelineCacheComponent
+ >
+ </sp-pipeline-assembly-options-pipeline-cache>
+ <span fxFlex></span>
+ <button
+ color="accent"
+ mat-icon-button
+ matTooltip="Clear Assembly Area"
+ [matTooltipPosition]="'above'"
+ [disabled]="editorService.pipelineAssemblyEmpty"
+ (click)="showClearAssemblyConfirmDialog($event)"
+ data-cy="clear-assembly-area"
+ >
+ <i class="material-icons">clear</i>
+ </button>
+</div>
diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.scss
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options.component.scss
similarity index 84%
rename from ui/src/app/editor/components/pipeline/pipeline.component.scss
rename to
ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options.component.scss
index 13cbc4aacb..7f7266f016 100644
--- a/ui/src/app/editor/components/pipeline/pipeline.component.scss
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
* 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.
@@ -15,3 +15,11 @@
* limitations under the License.
*
*/
+
+.assembly-options-divider {
+ width: 1px;
+ height: 70%;
+ margin-left: 10px;
+ margin-right: 10px;
+ background: var(--color-bg-3);
+}
diff --git
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options.component.ts
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options.component.ts
new file mode 100644
index 0000000000..00ecb8e93b
--- /dev/null
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options.component.ts
@@ -0,0 +1,135 @@
+/*
+ * 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,
+ EventEmitter,
+ Input,
+ 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 {
+ ConfirmDialogComponent,
+ DialogService,
+ PanelType,
+} from '@streampipes/shared-ui';
+import { EditorService } from '../../../services/editor.service';
+import { MatDialog } from '@angular/material/dialog';
+import { PipelineElementDiscoveryComponent } from
'../../../dialog/pipeline-element-discovery/pipeline-element-discovery.component';
+import {
+ PipelineElementConfig,
+ PipelineElementUnion,
+} from '../../../model/editor.model';
+import { PipelineAssemblyOptionsPipelineCacheComponent } from
'./pipeline-assembly-options-pipeline-cache/pipeline-assembly-options-pipeline-cache.component';
+import { PipelineCanvasMetadata } from '@streampipes/platform-services';
+
+@Component({
+ selector: 'sp-pipeline-assembly-options',
+ templateUrl: './pipeline-assembly-options.component.html',
+ styleUrls: ['./pipeline-assembly-options.component.scss'],
+})
+export class PipelineAssemblyOptionsComponent {
+ @Input()
+ jsplumbBridge: JsplumbBridge;
+
+ @Input()
+ rawPipelineModel: PipelineElementConfig[];
+
+ @Input()
+ pipelineCanvasMetadata: PipelineCanvasMetadata;
+
+ @Input()
+ allElements: PipelineElementUnion[];
+
+ @Input()
+ previewModeActive: boolean;
+
+ @Output()
+ savePipelineEmitter: EventEmitter<void> = new EventEmitter<void>();
+
+ @Output()
+ clearAssemblyEmitter: EventEmitter<void> = new EventEmitter<void>();
+
+ @Output()
+ togglePreviewEmitter: EventEmitter<void> = new EventEmitter<void>();
+
+ @ViewChild('assemblyOptionsPipelineCacheComponent')
+ assemblyOptionsCacheComponent:
PipelineAssemblyOptionsPipelineCacheComponent;
+
+ constructor(
+ public editorService: EditorService,
+ public pipelineValidationService: PipelineValidationService,
+ private pipelinePositioningService: PipelinePositioningService,
+ private dialog: MatDialog,
+ private dialogService: DialogService,
+ ) {}
+
+ autoLayout() {
+ this.pipelinePositioningService.layoutGraph(
+ '#assembly',
+ "div[id^='jsplumb']",
+ 110,
+ false,
+ );
+ this.jsplumbBridge.repaintEverything();
+ }
+
+ openDiscoverDialog() {
+ this.dialogService.open(PipelineElementDiscoveryComponent, {
+ panelType: PanelType.SLIDE_IN_PANEL,
+ title: 'Discover pipeline elements',
+ width: '50vw',
+ data: {
+ currentElements: this.allElements,
+ rawPipelineModel: this.rawPipelineModel,
+ },
+ });
+ }
+
+ showClearAssemblyConfirmDialog(event: any) {
+ 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,
+ },
+ });
+ dialogRef.afterClosed().subscribe(ev => {
+ if (ev) {
+ this.clearAssemblyEmitter.emit();
+ }
+ });
+ }
+
+ isPipelineAssemblyEmpty() {
+ return (
+ this.rawPipelineModel.length === 0 ||
+ this.rawPipelineModel.every(pe => pe.settings.disabled)
+ );
+ }
+
+ triggerCacheUpdate(): void {
+ this.assemblyOptionsCacheComponent.triggerPipelineCacheUpdate();
+ }
+}
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 592cc32b32..e7d49b22b8 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
@@ -18,176 +18,32 @@
<div fxFlex="100" fxLayout="column">
<div class="pipeline-assembly-options page-container-nav">
- <div fxFlex="100" fxLayout="row" fxLayoutAlign="start center">
- <button
- mat-button
- mat-raised-button
- color="accent"
- matTooltip="Save Pipeline"
- [matTooltipPosition]="'above'"
- [disabled]="!pipelineValidationService.pipelineValid"
- (click)="submit()"
- type="submit"
- data-cy="sp-editor-save-pipeline"
- >
- <div fxLayoutAlign="start center" fxLayout="row">
- <i class="material-icons">save</i>
- <span> Save pipeline</span>
- </div>
- </button>
- <span class="assembly-options-divider"></span>
- <!-- TODO: Use this once copying of elements is supported -->
- <!-- <button mat-button mat-icon-button
matTooltip="Pan" [matTooltipPosition]="'above'"-->
- <!-- [disabled]="!selectMode"-->
- <!-- (click)="toggleSelectMode()">-->
- <!-- <i class="material-icons">open_with</i>-->
- <!-- </button>-->
- <!-- <button mat-button mat-icon-button
matTooltip="Select" [matTooltipPosition]="'above'"-->
- <!-- [disabled]="selectMode"-->
- <!-- (click)="toggleSelectMode()">-->
- <!-- <i class="material-icons">mode_edit</i>-->
- <!-- </button>-->
- <button
- mat-button
- color="accent"
- matTooltip="Data Preview"
- [matTooltipPosition]="'above'"
- (click)="triggerPipelinePreview()"
- [disabled]="isPipelineAssemblyEmpty()"
- >
- <div fxLayoutAlign="start center" fxLayout="row">
- <i class="material-icons">visibility</i>
- <span *ngIf="!pipelineComponent.previewModeActive"
- > Enable live preview</span
- >
- <span *ngIf="pipelineComponent.previewModeActive"
- > Disable live preview</span
- >
- </div>
- </button>
- <span class="assembly-options-divider"></span>
- <button
- color="accent"
- mat-icon-button
- matTooltip="Auto Layout"
- [matTooltipPosition]="'above'"
- (click)="autoLayout()"
- >
- <i class="material-icons">settings_overscan</i>
- </button>
- <button
- color="accent"
- mat-icon-button
- matTooltip="Add pipeline element"
- [matTooltipPosition]="'above'"
- (click)="openDiscoverDialog()"
- data-cy="sp-editor-add-pipeline-element"
- >
- <i class="material-icons">add</i>
- </button>
- <div
- fxLayout="column"
- fxLayoutAlign="start center"
- class="pipeline-cache-block"
- >
- <div
- fxFlex="100"
- fxLayoutAlign="start center"
- fxLayout="row"
- *ngIf="pipelineCached || pipelineCacheRunning"
- >
- <div
- *ngIf="pipelineCached"
- fxLayout="row"
- fxLayoutAlign="start center"
- >
- <mat-spinner
- [mode]="'indeterminate'"
- class="mat-spinner-color"
- [diameter]="15"
- *ngIf="pipelineCacheRunning"
- ></mat-spinner>
- <span
- > {{
- pipelineCacheRunning
- ? ' Saving pipeline modifications'
- : 'All pipeline modifications saved.'
- }}</span
- >
- </div>
- </div>
- </div>
- <span fxFlex></span>
- <button
- color="accent"
- mat-icon-button
- matTooltip="Clear Assembly Area"
- [matTooltipPosition]="'above'"
- [disabled]="editorService.pipelineAssemblyEmpty"
- (click)="showClearAssemblyConfirmDialog($event)"
- data-cy="clear-assembly-area"
- >
- <i class="material-icons">clear</i>
- </button>
- </div>
+ <sp-pipeline-assembly-options
+ #assemblyOptionsComponent
+ [rawPipelineModel]="rawPipelineModel"
+ [pipelineCanvasMetadata]="pipelineCanvasMetadata"
+ [allElements]="allElements"
+ [jsplumbBridge]="JsplumbBridge"
+ [previewModeActive]="previewModeActive"
+ (clearAssemblyEmitter)="clearAssembly()"
+ (togglePreviewEmitter)="togglePreview()"
+ (savePipelineEmitter)="submit()"
+ >
+ </sp-pipeline-assembly-options>
</div>
<div id="outerAssemblyArea" class="outerAssembly assembly-border">
- <div class="pipeline-canvas-outer" #outerCanvas>
- <div class="pipeline-validation-hint">
- <sp-error-hint
- [displayMessages]="!isPipelineAssemblyEmpty()"
- [errorMessages]="pipelineValidationService.errorMessages"
- [validationString]="'Pipeline'"
- >
- </sp-error-hint>
- </div>
- <div class="pan-control">
- <div class="pan-zoom-control-buttons">
- <div class="pan-zoom-button pan-left" (click)="panLeft()">
- <i class="material-icons">keyboard_arrow_left</i>
- </div>
- <div class="pan-zoom-button pan-right"
(click)="panRight()">
- <i class="material-icons">keyboard_arrow_right</i>
- </div>
- <div class="pan-zoom-button pan-home" (click)="panHome()">
- <i class="material-icons">home</i>
- </div>
- <div class="pan-zoom-button pan-up" (click)="panUp()">
- <i class="material-icons">keyboard_arrow_up</i>
- </div>
- <div class="pan-zoom-button pan-down" (click)="panDown()">
- <i class="material-icons">keyboard_arrow_down</i>
- </div>
- </div>
- </div>
- <div class="zoom-control">
- <div class="pan-zoom-control-buttons">
- <div class="pan-zoom-button zoom-in" (click)="zoomIn()">
- <i class="material-icons">zoom_in</i>
- </div>
- <mat-divider class="zoom-divider"></mat-divider>
- <div class="pan-zoom-button zoom-out" (click)="zoomOut()">
- <i class="material-icons">zoom_out</i>
- </div>
- </div>
- </div>
- <sp-pipeline
- class="canvas jtk-surface"
- id="assembly"
- #pipelineComponent
- [pipelineValid]="pipelineValid"
- [canvasId]="'assembly'"
- [rawPipelineModel]="rawPipelineModel"
- [allElements]="allElements"
- [preview]="false"
- [pipelineCached]="pipelineCached"
- [pipelineCanvasMetadata]="pipelineCanvasMetadata"
- [pipelineCacheRunning]="pipelineCacheRunning"
- (pipelineCachedChanged)="pipelineCached = $event"
- (pipelineCacheRunningChanged)="pipelineCacheRunning = $event"
- style="position: absolute"
- >
- </sp-pipeline>
- </div>
+ <sp-pipeline-assembly-drawing-area
+ #drawingAreaComponent
+ fxFlex="100"
+ style="position: relative"
+ (triggerPipelineCacheUpdateEmitter)="triggerCacheUpdate()"
+ [readonly]="readonly"
+ [allElements]="allElements"
+ [rawPipelineModel]="rawPipelineModel"
+ [pipelineCanvasMetadata]="pipelineCanvasMetadata"
+ [pipelineCanvasMetadataAvailable]="pipelineCanvasMetadataAvailable"
+ [jsplumbBridge]="JsplumbBridge"
+ >
+ </sp-pipeline-assembly-drawing-area>
</div>
</div>
diff --git
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.scss
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.scss
index 7d714593ef..5ea0cbc62b 100644
---
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.scss
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.scss
@@ -22,13 +22,9 @@
stroke: var(--color-accent) !important;
}
-.pipeline-cache-progress {
- display: inline-block;
-}
-
-.pipeline-cache-block {
- height: 100%;
- margin-left: 15px;
+.pipeline-assembly-options {
+ padding-left: 5px;
+ border: 1px solid var(--color-bg-3);
}
.outerAssembly {
@@ -39,133 +35,10 @@
overflow: hidden;
}
-.pipeline-canvas-outer {
- position: relative;
- width: 100%;
- height: 100%;
-}
-
-.canvas {
- //overflow: scroll;
- position: relative;
- left: 0px;
- top: 0px;
- height: 3000px;
- width: 4000px;
- z-index: 0;
- margin: -1px;
-
- background-color: var(--color-bg-1);
- background-image: var(--canvas-color);
- background-size: 15px 15px;
-}
-
-.pipeline-assembly-options {
- padding-left: 5px;
- border: 1px solid var(--color-bg-3);
- //background: #f6f6f6;
-}
-
.assembly-border {
border: 1px solid var(--color-bg-3);
}
-.jtk-surface-nopan {
- overflow: scroll !important;
- cursor: default;
-}
-
-.zoom-control {
- position: absolute;
- right: 10px;
- bottom: 10px;
- width: 40px;
- height: 80px;
- z-index: 10;
- background: var(--color-bg-1);
- box-shadow: 0.175em 0.175em 0 0 rgba(15, 28, 63, 0.125);
- border-radius: 10px;
-}
-
-.pipeline-validation-hint {
- position: absolute;
- right: 10px;
- top: 20px;
- z-index: 10;
- background: var(--color-bg-1);
- box-shadow: 0.175em 0.175em 0 0 rgba(15, 28, 63, 0.125);
-}
-
-.pan-control {
- position: absolute;
- right: 60px;
- bottom: 10px;
- width: 80px;
- height: 80px;
- background: var(--color-bg-1);
- box-shadow: 0.175em 0.175em 0 0 rgba(15, 28, 63, 0.125);
- border-radius: 50%;
- z-index: 10;
-}
-
-.pan-zoom-button {
- position: absolute;
- cursor: pointer;
- color: var(--color-accent);
-}
-
-.pan-zoom-control-buttons {
- position: relative;
-}
-
-.zoom-divider {
- top: 40px;
- position: relative;
-}
-
-.zoom-in {
- top: 8px;
- left: 8px;
-}
-
-.zoom-out {
- top: 48px;
- left: 8px;
-}
-
-.pan-up {
- left: 28px;
- top: 2px;
-}
-
-.pan-down {
- left: 28px;
- top: 58px;
-}
-
-.pan-left {
- left: -3px;
- top: 30px;
-}
-
-.pan-right {
- left: 55px;
- top: 30px;
-}
-
-.pan-home {
- left: 28px;
- top: 30px;
-}
-
-.assembly-options-divider {
- width: 1px;
- height: 70%;
- margin-left: 10px;
- margin-right: 10px;
- background: var(--color-bg-3);
-}
-
.color-warn {
color: var(--color-warn);
}
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 fa5c9afa1e..3486572eaa 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
@@ -16,96 +16,58 @@
*
*/
-import {
- AfterViewInit,
- Component,
- ElementRef,
- EventEmitter,
- Input,
- NgZone,
- OnDestroy,
- OnInit,
- Output,
- ViewChild,
-} from '@angular/core';
+import { AfterViewInit, Component, Input, 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 {
PipelineElementConfig,
PipelineElementUnion,
} from '../../model/editor.model';
import { ObjectProvider } from '../../services/object-provider.service';
-import {
- ConfirmDialogComponent,
- DialogService,
- PanelType,
- SpBreadcrumbService,
-} from '@streampipes/shared-ui';
+import { DialogService, PanelType } from '@streampipes/shared-ui';
import { SavePipelineComponent } from
'../../dialog/save-pipeline/save-pipeline.component';
-import { MatDialog } from '@angular/material/dialog';
import { EditorService } from '../../services/editor.service';
import {
Pipeline,
PipelineCanvasMetadata,
- PipelineCanvasMetadataService,
- PipelineService,
} from '@streampipes/platform-services';
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 { forkJoin, of, Subscription } from 'rxjs';
-import { PipelineElementDiscoveryComponent } from
'../../dialog/pipeline-element-discovery/pipeline-element-discovery.component';
-import { SpPipelineRoutes } from '../../../pipelines/pipelines.routes';
+import { forkJoin } from 'rxjs';
import { Router } from '@angular/router';
-import { catchError } from 'rxjs/operators';
+import { PipelineAssemblyDrawingAreaComponent } from
'./pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component';
+import { PipelineAssemblyOptionsComponent } from
'./pipeline-assembly-options/pipeline-assembly-options.component';
@Component({
selector: 'sp-pipeline-assembly',
templateUrl: './pipeline-assembly.component.html',
styleUrls: ['./pipeline-assembly.component.scss'],
})
-export class PipelineAssemblyComponent
- implements OnInit, AfterViewInit, OnDestroy
-{
+export class PipelineAssemblyComponent implements AfterViewInit {
@Input()
rawPipelineModel: PipelineElementConfig[];
@Input()
- currentModifiedPipelineId: string;
-
- @Input()
- allElements: PipelineElementUnion[];
-
- @Output()
- pipelineCanvasMaximizedEmitter: EventEmitter<boolean> =
- new EventEmitter<boolean>();
-
- JsplumbBridge: JsplumbBridge;
- currentZoomLevel: any;
- preview: any;
-
- selectMode: any;
originalPipeline: Pipeline;
- pipelineValid = false;
- pipelineCacheRunning = false;
- pipelineCached = false;
+ @Input()
+ pipelineCanvasMetadata: PipelineCanvasMetadata;
- pipelineCanvasMetadata: PipelineCanvasMetadata =
- new PipelineCanvasMetadata();
+ @Input()
pipelineCanvasMetadataAvailable = false;
- config: any = {};
- @ViewChild('outerCanvas') pipelineCanvas: ElementRef;
+ @Input()
+ allElements: PipelineElementUnion[];
- @ViewChild('pipelineComponent')
- pipelineComponent: PipelineComponent;
+ previewModeActive = false;
+ readonly: boolean;
- panzoom: PanzoomObject;
- moveSub: Subscription;
+ JsplumbBridge: JsplumbBridge;
+
+ @ViewChild('assemblyOptionsComponent')
+ assemblyOptionsComponent: PipelineAssemblyOptionsComponent;
+ @ViewChild('drawingAreaComponent')
+ drawingAreaComponent: PipelineAssemblyDrawingAreaComponent;
constructor(
private jsPlumbFactoryService: JsplumbFactoryService,
@@ -113,125 +75,34 @@ export class PipelineAssemblyComponent
private objectProvider: ObjectProvider,
public editorService: EditorService,
public pipelineValidationService: PipelineValidationService,
- private pipelineService: PipelineService,
- private jsplumbService: JsplumbService,
private dialogService: DialogService,
- private dialog: MatDialog,
- private ngZone: NgZone,
private router: Router,
- private pipelineElementDraggedService: PipelineElementDraggedService,
- private pipelineCanvasMetadataService: PipelineCanvasMetadataService,
- private breadcrumbService: SpBreadcrumbService,
- ) {
- this.selectMode = true;
- this.currentZoomLevel = 1;
- }
-
- ngOnInit(): void {
- if (this.currentModifiedPipelineId) {
- this.displayPipelineById(this.currentModifiedPipelineId);
- } else {
- this.checkAndDisplayCachedPipeline();
- }
- this.moveSub =
-
this.pipelineElementDraggedService.pipelineElementMovedSubject.subscribe(
- position => {
- 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) {
- yOffset = -10;
- }
- if (position.x + currentPan.x > offsetWidth - 100) {
- xOffset = -10;
- }
- if (xOffset < 0 || yOffset < 0) {
- this.pan(xOffset, yOffset);
- }
- },
- );
- }
+ ) {}
ngAfterViewInit() {
this.JsplumbBridge = this.jsPlumbFactoryService.getJsplumbBridge(
- this.preview,
+ this.readonly,
);
- const elem = document.getElementById('assembly');
- this.panzoom = Panzoom(elem, {
- maxScale: 5,
- excludeClass: 'sp-no-pan',
- canvas: true,
- contain: 'outside',
- });
- }
-
- autoLayout() {
- this.pipelinePositioningService.layoutGraph(
- '#assembly',
- "div[id^='jsplumb']",
- 110,
- false,
- );
- this.JsplumbBridge.repaintEverything();
- }
-
- zoomOut() {
- this.doZoom(true);
- }
-
- zoomIn() {
- this.doZoom(false);
- }
-
- doZoom(zoomOut) {
- zoomOut ? this.panzoom.zoomOut() : this.panzoom.zoomIn();
- this.currentZoomLevel = this.panzoom.getScale();
- this.JsplumbBridge.setZoom(this.currentZoomLevel);
- this.JsplumbBridge.repaintEverything();
- }
-
- showClearAssemblyConfirmDialog(event: any) {
- 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,
- },
- });
- dialogRef.afterClosed().subscribe(ev => {
- if (ev) {
- if (this.currentModifiedPipelineId) {
- this.currentModifiedPipelineId = undefined;
- }
- this.clearAssembly();
- this.editorService.makePipelineAssemblyEmpty(true);
- }
- });
}
/**
* clears the Assembly of all elements
*/
clearAssembly() {
+ this.editorService.makePipelineAssemblyEmpty(true);
this.JsplumbBridge.deleteEveryEndpoint();
this.rawPipelineModel = [];
- this.currentZoomLevel = 1;
- this.JsplumbBridge.setZoom(this.currentZoomLevel);
+ this.drawingAreaComponent.resetZoom();
this.JsplumbBridge.repaintEverything();
forkJoin([
this.editorService.removePipelineFromCache(),
this.editorService.removeCanvasMetadataFromCache(),
- ]).subscribe(msg => {
- this.pipelineCached = false;
- this.pipelineCacheRunning = false;
+ ]).subscribe(() => {
+ this.pipelineCanvasMetadata = new PipelineCanvasMetadata();
+ if (this.originalPipeline) {
+ this.router.navigate(['pipelines', 'create']);
+ }
});
}
@@ -239,7 +110,8 @@ export class PipelineAssemblyComponent
* Sends the pipeline to the server
*/
submit() {
- const pipelineModel = this.pipelineComponent.rawPipelineModel;
+ //const pipelineModel = this.pipelineComponent.rawPipelineModel;
+ const pipelineModel = this.rawPipelineModel;
const pipeline = this.objectProvider.makePipeline(pipelineModel);
this.pipelinePositioningService.collectPipelineElementPositions(
this.pipelineCanvasMetadata,
@@ -247,7 +119,7 @@ export class PipelineAssemblyComponent
);
pipeline.valid = this.pipelineValidationService.isValidPipeline(
pipelineModel,
- this.preview,
+ this.readonly,
);
const dialogRef = this.dialogService.open(SavePipelineComponent, {
panelType: PanelType.SLIDE_IN_PANEL,
@@ -265,9 +137,7 @@ export class PipelineAssemblyComponent
.subscribe((config: { reload: boolean; pipelineId: string }) => {
if (config?.reload) {
this.clearAssembly();
- this.editorService.makePipelineAssemblyEmpty(true);
this.rawPipelineModel = [];
- this.currentModifiedPipelineId = undefined;
setTimeout(() => {
this.router.navigate(['pipelines', 'create']);
});
@@ -275,149 +145,12 @@ export class PipelineAssemblyComponent
});
}
- checkAndDisplayCachedPipeline() {
- 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[];
- this.handleCanvasMetadataResponse(results[1]);
- this.displayPipelineInEditor(
- !this.pipelineCanvasMetadataAvailable,
- this.pipelineCanvasMetadata,
- );
- }
- });
- }
-
- displayPipelineById(pipelineId: string) {
- const pipelineReq = this.pipelineService.getPipelineById(pipelineId);
- const canvasMetadataReq = this.pipelineCanvasMetadataService
- .getPipelineCanvasMetadata(pipelineId)
- .pipe(
- catchError(error => {
- this.handleCanvasMetadataResponse(undefined);
- return of(undefined);
- }),
- );
-
- forkJoin([pipelineReq, canvasMetadataReq]).subscribe(
- ([pipelineResp, canvasResp]) => {
- if (pipelineResp) {
- this.originalPipeline = pipelineResp;
- this.breadcrumbService.updateBreadcrumb([
- SpPipelineRoutes.BASE,
- { label: this.originalPipeline.name },
- { label: 'Modify' },
- ]);
- this.rawPipelineModel =
this.jsplumbService.makeRawPipeline(
- this.originalPipeline,
- false,
- );
- }
- if (canvasResp !== undefined) {
- this.handleCanvasMetadataResponse(canvasResp);
- }
- this.displayPipelineInEditor(
- !this.pipelineCanvasMetadataAvailable,
- this.pipelineCanvasMetadata,
- );
- },
- );
- }
-
- handleCanvasMetadataResponse(canvasMetadata: PipelineCanvasMetadata) {
- if (canvasMetadata) {
- this.pipelineCanvasMetadata = canvasMetadata;
- this.pipelineCanvasMetadataAvailable = true;
- } else {
- this.pipelineCanvasMetadataAvailable = false;
- this.pipelineCanvasMetadata = new PipelineCanvasMetadata();
- }
- }
-
- displayPipelineInEditor(
- autoLayout: boolean,
- pipelineCanvasMetadata?: PipelineCanvasMetadata,
- ): void {
- setTimeout(() => {
- this.pipelinePositioningService.displayPipeline(
- this.rawPipelineModel,
- '#assembly',
- false,
- autoLayout,
- pipelineCanvasMetadata,
- );
- this.editorService.makePipelineAssemblyEmpty(false);
- this.ngZone.run(() => {
- this.pipelineValid =
- this.pipelineValidationService.isValidPipeline(
- this.rawPipelineModel.filter(
- pe => !pe.settings.disabled,
- ),
- false,
- );
- });
- this.pipelineComponent.triggerPipelineModification();
- });
- }
-
- isPipelineAssemblyEmpty() {
- return (
- this.rawPipelineModel.length === 0 ||
- this.rawPipelineModel.every(pe => pe.settings.disabled)
- );
- }
-
- panLeft() {
- this.pan(100, 0);
- }
-
- panRight() {
- this.pan(-100, 0);
- }
-
- panUp() {
- this.pan(0, 100);
- }
-
- panDown() {
- this.pan(0, -100);
- }
-
- panHome() {
- this.panAbsolute(0, 0);
- }
-
- pan(xOffset: number, yOffset: number) {
- 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);
- }
-
- panAbsolute(x: number, y: number) {
- this.panzoom.pan(x, y);
- }
-
- triggerPipelinePreview() {
- this.pipelineComponent.initiatePipelineElementPreview();
- }
-
- openDiscoverDialog() {
- this.dialogService.open(PipelineElementDiscoveryComponent, {
- panelType: PanelType.SLIDE_IN_PANEL,
- title: 'Discover pipeline elements',
- width: '50vw',
- data: {
- currentElements: this.allElements,
- rawPipelineModel: this.rawPipelineModel,
- },
- });
+ togglePreview(): void {
+ this.previewModeActive = !this.previewModeActive;
+ this.drawingAreaComponent.initiatePipelineElementPreview();
}
- ngOnDestroy() {
- this.moveSub?.unsubscribe();
+ triggerCacheUpdate(): void {
+ this.assemblyOptionsComponent.triggerCacheUpdate();
}
}
diff --git
a/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.html
b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.html
similarity index 100%
rename from
ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.html
rename to
ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.html
diff --git
a/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.scss
b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.scss
similarity index 100%
rename from
ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.scss
rename to
ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.scss
diff --git
a/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.ts
b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.ts
similarity index 91%
rename from
ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.ts
rename to
ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.ts
index ab0e2385c4..2fa186a3a7 100644
---
a/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.ts
+++
b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.ts
@@ -20,9 +20,9 @@ import { Component, Input, OnInit } from '@angular/core';
import {
PipelineElementType,
PipelineElementUnion,
-} from '../../model/editor.model';
-import { PipelineElementTypeUtils } from '../../utils/editor.utils';
-import { EditorService } from '../../services/editor.service';
+} from '../../../model/editor.model';
+import { PipelineElementTypeUtils } from '../../../utils/editor.utils';
+import { EditorService } from '../../../services/editor.service';
@Component({
selector: 'sp-pe-icon-stand-row',
diff --git
a/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.ts
b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.ts
index 88136e51d3..9e1c4e2340 100644
---
a/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.ts
+++
b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.ts
@@ -17,7 +17,6 @@
*/
import { AfterViewInit, Component, Input, OnInit } from '@angular/core';
-import { RestApi } from '../../../services/rest-api.service';
import {
PeCategory,
PipelineElementType,
@@ -72,7 +71,6 @@ export class PipelineElementIconStandComponent
};
constructor(
- private restApi: RestApi,
private editorService: EditorService,
private router: Router,
) {}
diff --git
a/ui/src/app/editor/components/pipeline/dropped-pipeline-element/dropped-pipeline-element.component.html
b/ui/src/app/editor/components/pipeline/dropped-pipeline-element/dropped-pipeline-element.component.html
new file mode 100644
index 0000000000..6004bdcb46
--- /dev/null
+++
b/ui/src/app/editor/components/pipeline/dropped-pipeline-element/dropped-pipeline-element.component.html
@@ -0,0 +1,103 @@
+<!--
+ ~ 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="z-index: 5" [ngClass]="elementCssClasses">
+ <div
+ class="pipeline-element-progress-container sp-fade"
+ *ngIf="pipelineElementConfig.settings.loadingStatus"
+ >
+ <mat-spinner
+ [mode]="'indeterminate'"
+ class="pipeline-element-progress"
+ [diameter]="40"
+ color="accent"
+ ></mat-spinner>
+ </div>
+ <div
+ class="pipeline-element-loading-container sp-fade-opacity"
+ *ngIf="pipelineElementConfig.settings.loadingStatus"
+ ></div>
+ <div
+ class="pipeline-element-configuration-status {{
+ pipelineElementConfig.type === 'stream'
+ ? 'pi-stream'
+ : 'pi-processor'
+ }}"
+ *ngIf="!readonly"
+ >
+ <i
+ class="material-icons pipeline-element-configuration-invalid-icon"
+ *ngIf="pipelineElementConfig.settings.completed === 3"
+ >
+ warning
+ </i>
+ <i
+ class="material-icons pipeline-element-configuration-modified-icon"
+ *ngIf="pipelineElementConfig.settings.completed === 2"
+ >
+ warning
+ </i>
+ <i
+ class="material-icons pipeline-element-configuration-ok-icon"
+ *ngIf="pipelineElementConfig.settings.completed === 1"
+ >
+ check_circle
+ </i>
+ </div>
+ <sp-pipeline-element
+ [pipelineElement]="pipelineElementConfig.payload"
+ ></sp-pipeline-element>
+</div>
+<sp-pipeline-element-statistics
+ *ngIf="metricsInfo"
+ [pipelineElement]="pipelineElementConfig.payload"
+ [metricsInfo]="metricsInfo[pipelineElementConfig.payload.elementId]"
+>
+</sp-pipeline-element-statistics>
+<sp-pipeline-element-options
+ *ngIf="!readonly"
+ (delete)="deleteEmitter.emit($event)"
+ (customize)="showCustomizeEmitter.emit($event)"
+ [currentMouseOverElement]="currentMouseOverElement"
+ [pipelineValid]="pipelineValid"
+ [allElements]="allElements"
+ [pipelineElement]="pipelineElementConfig"
+ [rawPipelineModel]="rawPipelineModel"
+ [pipelineElementId]="
+ pipelineElementConfig.type === 'stream' ||
+ pipelineElementConfig.type === 'set'
+ ? pipelineElementConfig.payload.elementId
+ : pipelineElementConfig.payload.belongsTo
+ "
+ [internalId]="pipelineElementConfig.payload.dom"
+ [attr.data-cy]="
+ 'sp-pe-menu-' +
+ pipelineElementConfig.payload.name.toLowerCase().replaceAll(' ', '_')
+ "
+>
+</sp-pipeline-element-options>
+<sp-pipeline-element-preview
+ *ngIf="
+ previewModeActive &&
+ pipelinePreview.supportedPipelineElementDomIds.indexOf(
+ pipelineElementConfig.payload.elementId
+ ) > -1
+ "
+ [previewId]="pipelinePreview.previewId"
+ [elementId]="pipelineElementConfig.payload.elementId"
+>
+</sp-pipeline-element-preview>
diff --git
a/ui/src/app/editor/components/pipeline/dropped-pipeline-element/dropped-pipeline-element.component.ts
b/ui/src/app/editor/components/pipeline/dropped-pipeline-element/dropped-pipeline-element.component.ts
new file mode 100644
index 0000000000..7c079c8408
--- /dev/null
+++
b/ui/src/app/editor/components/pipeline/dropped-pipeline-element/dropped-pipeline-element.component.ts
@@ -0,0 +1,79 @@
+/*
+ * 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, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import {
+ PipelineElementConfig,
+ PipelineElementUnion,
+} from '../../../model/editor.model';
+import {
+ PipelinePreviewModel,
+ SpMetricsEntry,
+} from '@streampipes/platform-services';
+
+@Component({
+ selector: 'sp-dropped-pipeline-element',
+ templateUrl: './dropped-pipeline-element.component.html',
+})
+export class DroppedPipelineElementComponent implements OnInit {
+ @Input()
+ pipelineElementConfig: PipelineElementConfig;
+
+ @Input()
+ readonly: boolean;
+
+ @Input()
+ allElements: PipelineElementUnion[];
+
+ @Input()
+ metricsInfo: Record<string, SpMetricsEntry>;
+
+ @Input()
+ previewModeActive: boolean;
+
+ @Input()
+ pipelinePreview: PipelinePreviewModel;
+
+ @Input()
+ rawPipelineModel: PipelineElementConfig[];
+
+ @Input()
+ currentMouseOverElement = '';
+
+ @Input()
+ pipelineValid: boolean;
+
+ @Output()
+ deleteEmitter: EventEmitter<PipelineElementConfig> = new EventEmitter();
+
+ @Output()
+ showCustomizeEmitter: EventEmitter<PipelineElementConfig> =
+ new EventEmitter();
+
+ elementCssClasses: string;
+
+ ngOnInit() {
+ this.applyCssClasses();
+ }
+
+ applyCssClasses(): void {
+ this.elementCssClasses = `${this.pipelineElementConfig.type}
+ ${this.pipelineElementConfig.settings.connectable}
+ ${this.pipelineElementConfig.settings.displaySettings}`;
+ }
+}
diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.html
b/ui/src/app/editor/components/pipeline/pipeline.component.html
index 53039821f5..20b984a570 100644
--- a/ui/src/app/editor/components/pipeline/pipeline.component.html
+++ b/ui/src/app/editor/components/pipeline/pipeline.component.html
@@ -16,96 +16,29 @@
~
-->
<div
- [attr.data-jtk-managed]="pipelineElement.payload.dom"
- id="{{ pipelineElement.payload.dom }}"
- style="{{ getElementCss(pipelineElement.settings) }}"
- (click)="updateOptionsClick(pipelineElement.payload.dom)"
- (mouseenter)="updateMouseover(pipelineElement.payload.dom)"
- (mouseleave)="updateMouseover('')"
- *ngFor="let pipelineElement of rawPipelineModel | enabledPipelineElement"
+ [attr.data-jtk-managed]="pipelineElementConfig.payload.dom"
+ id="{{ pipelineElementConfig.payload.dom }}"
class="sp-no-pan"
+ [ngStyle]="getCssStyle(pipelineElementConfig)"
+ (click)="updateOptionsClick(pipelineElementConfig.payload.dom)"
+ (mouseenter)="updateMouseover(pipelineElementConfig.payload.dom)"
+ (mouseleave)="updateMouseover('')"
+ *ngFor="
+ let pipelineElementConfig of rawPipelineModel | enabledPipelineElement
+ "
>
- <div style="z-index: 5" [ngClass]="getElementCssClasses(pipelineElement)">
- <div
- class="pipeline-element-progress-container sp-fade"
- *ngIf="pipelineElement.settings.loadingStatus"
- >
- <mat-spinner
- [mode]="'indeterminate'"
- class="pipeline-element-progress"
- [diameter]="40"
- color="accent"
- ></mat-spinner>
- </div>
- <div
- class="pipeline-element-loading-container sp-fade-opacity"
- *ngIf="pipelineElement.settings.loadingStatus"
- ></div>
- <div
- class="pipeline-element-configuration-status {{
- pipelineElement.type === 'stream' ? 'pi-stream' :
'pi-processor'
- }}"
- *ngIf="!preview"
- >
- <i
- class="material-icons
pipeline-element-configuration-invalid-icon"
- *ngIf="pipelineElement.settings.completed === 3"
- >
- warning
- </i>
- <i
- class="material-icons
pipeline-element-configuration-modified-icon"
- *ngIf="pipelineElement.settings.completed === 2"
- >
- warning
- </i>
- <i
- class="material-icons pipeline-element-configuration-ok-icon"
- *ngIf="pipelineElement.settings.completed === 1"
- >
- check_circle
- </i>
- </div>
- <sp-pipeline-element
- [pipelineElement]="pipelineElement.payload"
- ></sp-pipeline-element>
- </div>
- <sp-pipeline-element-statistics
- *ngIf="metricsInfo"
- [pipelineElement]="pipelineElement.payload"
- [metricsInfo]="metricsInfo[pipelineElement.payload.elementId]"
- >
- </sp-pipeline-element-statistics>
- <sp-pipeline-element-options
- *ngIf="!preview"
- (delete)="handleDeleteOption($event)"
- (customize)="showCustomizeDialog($event)"
+ <sp-dropped-pipeline-element
+ [allElements]="allElements"
[currentMouseOverElement]="currentMouseOverElement"
+ [metricsInfo]="metricsInfo"
+ [pipelineElementConfig]="pipelineElementConfig"
+ [previewModeActive]="previewModeActive"
+ [pipelinePreview]="pipelinePreview"
[pipelineValid]="pipelineValid"
- [allElements]="allElements"
- [pipelineElement]="pipelineElement"
[rawPipelineModel]="rawPipelineModel"
- [pipelineElementId]="
- pipelineElement.type === 'stream' || pipelineElement.type === 'set'
- ? pipelineElement.payload.elementId
- : pipelineElement.payload.belongsTo
- "
- [internalId]="pipelineElement.payload.dom"
- [attr.data-cy]="
- 'sp-pe-menu-' +
- pipelineElement.payload.name.toLowerCase().replaceAll(' ', '_')
- "
- >
- </sp-pipeline-element-options>
- <sp-pipeline-element-preview
- *ngIf="
- previewModeActive &&
- pipelinePreview.supportedPipelineElementDomIds.indexOf(
- pipelineElement.payload.elementId
- ) > -1
- "
- [previewId]="pipelinePreview.previewId"
- [elementId]="pipelineElement.payload.elementId"
+ [readonly]="readonly"
+ (showCustomizeEmitter)="showCustomizeDialog($event)"
+ (deleteEmitter)="handleDeleteOption($event)"
>
- </sp-pipeline-element-preview>
+ </sp-dropped-pipeline-element>
</div>
diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.ts
b/ui/src/app/editor/components/pipeline/pipeline.component.ts
index 0dcb022857..1cfdd1c2e0 100644
--- a/ui/src/app/editor/components/pipeline/pipeline.component.ts
+++ b/ui/src/app/editor/components/pipeline/pipeline.component.ts
@@ -43,7 +43,6 @@ import {
DataSinkInvocation,
Notification,
Pipeline,
- PipelineCanvasMetadata,
PipelineEdgeValidation,
PipelineModificationMessage,
PipelinePreviewModel,
@@ -60,9 +59,7 @@ import {
import { EditorService } from '../../services/editor.service';
import { MatchingErrorComponent } from
'../../dialog/matching-error/matching-error.component';
import { MatDialog } from '@angular/material/dialog';
-import { forkJoin, Subscription } from 'rxjs';
import { JsplumbFactoryService } from '../../services/jsplumb-factory.service';
-import { PipelinePositioningService } from
'../../services/pipeline-positioning.service';
import {
EVENT_CONNECTION,
EVENT_CONNECTION_ABORT,
@@ -72,21 +69,15 @@ import {
} from '@jsplumb/browser-ui';
import { PipelineStyleService } from '../../services/pipeline-style.service';
import { IdGeneratorService } from
'../../../core-services/id-generator/id-generator.service';
-import { LivePreviewService } from '../../../services/live-preview.service';
-import { HttpDownloadProgressEvent } from '@angular/common/http';
@Component({
selector: 'sp-pipeline',
templateUrl: './pipeline.component.html',
- styleUrls: ['./pipeline.component.scss'],
})
export class PipelineComponent implements OnInit, OnDestroy {
@Input()
pipelineValid: boolean;
- @Input()
- canvasId: string;
-
@Input()
rawPipelineModel: PipelineElementConfig[];
@@ -94,44 +85,35 @@ export class PipelineComponent implements OnInit, OnDestroy
{
allElements: PipelineElementUnion[];
@Input()
- preview: boolean;
+ readonly: boolean;
@Input()
- pipelineCached: boolean;
+ metricsInfo: Record<string, SpMetricsEntry>;
@Output()
- pipelineCachedChanged: EventEmitter<boolean> = new EventEmitter<boolean>();
-
- @Input()
- pipelineCacheRunning: boolean;
-
- @Input()
- pipelineCanvasMetadata: PipelineCanvasMetadata;
-
- @Input()
- metricsInfo: Record<string, SpMetricsEntry>;
+ deletePreviewEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
@Output()
- pipelineCacheRunningChanged: EventEmitter<boolean> =
- new EventEmitter<boolean>();
+ triggerPipelineCacheUpdateEmitter: EventEmitter<void> = new EventEmitter();
- currentMouseOverElement: string;
+ currentMouseOverElement = '';
currentPipelineModel: Pipeline;
idCounter: any;
currentZoomLevel: any;
JsplumbBridge: JsplumbBridge;
+ @Input()
previewModeActive = false;
+
+ @Input()
pipelinePreview: PipelinePreviewModel;
- pipelinePreviewSub: Subscription;
shouldOpenCustomizeSettings = false;
constructor(
private jsplumbService: JsplumbService,
private pipelineEditorService: PipelineEditorService,
- private pipelinePositioningService: PipelinePositioningService,
private jsplumbFactoryService: JsplumbFactoryService,
private objectProvider: ObjectProvider,
private editorService: EditorService,
@@ -142,9 +124,7 @@ export class PipelineComponent implements OnInit, OnDestroy
{
private dialogService: DialogService,
private dialog: MatDialog,
private ngZone: NgZone,
- private livePreviewService: LivePreviewService,
) {
- this.currentMouseOverElement = '';
this.currentPipelineModel = new Pipeline();
this.idCounter = 0;
@@ -153,10 +133,24 @@ export class PipelineComponent implements OnInit,
OnDestroy {
ngOnInit() {
this.JsplumbBridge = this.jsplumbFactoryService.getJsplumbBridge(
- this.preview,
+ this.readonly,
);
- this.initAssembly();
- this.initPlumb();
+ if (!this.readonly) {
+ this.initAssembly();
+ this.initPlumb();
+ }
+ }
+
+ getCssStyle(
+ pipelineElementConfig: PipelineElementConfig,
+ ): Record<string, string> {
+ return {
+ position: 'absolute',
+ width: '90px',
+ height: '90px',
+ left: pipelineElementConfig.settings.position.x + 'px',
+ top: pipelineElementConfig.settings.position.y + 'px',
+ };
}
validatePipeline(pm?: PipelineModificationMessage) {
@@ -167,7 +161,7 @@ export class PipelineComponent implements OnInit, OnDestroy
{
this.rawPipelineModel.filter(
pe => !pe.settings.disabled,
),
- this.preview,
+ this.readonly,
pm,
);
});
@@ -175,8 +169,8 @@ export class PipelineComponent implements OnInit, OnDestroy
{
}
ngOnDestroy() {
- this.deletePipelineElementPreview(false);
- this.jsplumbFactoryService.destroy(this.preview);
+ this.deletePreviewEmitter.emit(false);
+ this.jsplumbFactoryService.destroy();
}
@HostListener('window:beforeunload')
@@ -193,44 +187,6 @@ export class PipelineComponent implements OnInit,
OnDestroy {
this.currentMouseOverElement === elementId ? '' : elementId;
}
- getElementCss(currentPipelineElementSettings) {
- return (
- 'position:absolute;' +
- (this.preview ? 'width:90px;' : 'width:90px;') +
- (this.preview ? 'height:90px;' : 'height:90px;') +
- 'left: ' +
- currentPipelineElementSettings.position.x +
- 'px; ' +
- 'top: ' +
- currentPipelineElementSettings.position.y +
- 'px; '
- );
- }
-
- getElementCssClasses(currentPipelineElement: PipelineElementConfig) {
- return (
- currentPipelineElement.type +
- ' ' +
- currentPipelineElement.settings.connectable +
- ' ' +
- currentPipelineElement.settings.displaySettings
- );
- }
-
- isStreamInPipeline() {
- return this.isInPipeline('stream');
- }
-
- isSetInPipeline() {
- return this.isInPipeline('set');
- }
-
- isInPipeline(type: string) {
- return this.rawPipelineModel.some(
- x => x.type === type && !x.settings.disabled,
- );
- }
-
findPipelineElementByElementId(elementId: string) {
return this.allElements.find(a => a.elementId === elementId);
}
@@ -291,7 +247,7 @@ export class PipelineComponent implements OnInit, OnDestroy
{
}
this.JsplumbBridge.repaintEverything();
this.validatePipeline();
- this.triggerPipelineCacheUpdate();
+ this.triggerPipelineCacheUpdateEmitter.emit();
},
});
}
@@ -326,7 +282,7 @@ export class PipelineComponent implements OnInit, OnDestroy
{
}
this.JsplumbBridge.repaintEverything();
this.validatePipeline();
- this.triggerPipelineCacheUpdate();
+ this.triggerPipelineCacheUpdateEmitter.emit();
}
initPlumb() {
@@ -418,7 +374,7 @@ export class PipelineComponent implements OnInit, OnDestroy
{
if (
this.jsplumbService.isFullyConnected(
pe,
- this.preview,
+ this.readonly,
)
) {
const payload =
@@ -439,7 +395,7 @@ export class PipelineComponent implements OnInit, OnDestroy
{
PipelineElementConfigurationStatus.OK,
);
this.announceConfiguredElement(pe);
- this.triggerPipelineCacheUpdate();
+
this.triggerPipelineCacheUpdateEmitter.emit();
}
}
} else {
@@ -552,34 +508,6 @@ export class PipelineComponent implements OnInit,
OnDestroy {
return custom;
}
- triggerPipelineCacheUpdate() {
- setTimeout(() => {
- this.pipelineCacheRunning = true;
- this.pipelineCacheRunningChanged.emit(this.pipelineCacheRunning);
- this.pipelinePositioningService.collectPipelineElementPositions(
- this.pipelineCanvasMetadata,
- this.rawPipelineModel,
- );
- const updateCachedPipeline =
- this.editorService.updateCachedPipeline(this.rawPipelineModel);
- const updateCachedCanvasMetadata =
- this.editorService.updateCachedCanvasMetadata(
- this.pipelineCanvasMetadata,
- );
- forkJoin([
- updateCachedPipeline,
- updateCachedCanvasMetadata,
- ]).subscribe(() => {
- this.pipelineCacheRunning = false;
- this.pipelineCacheRunningChanged.emit(
- this.pipelineCacheRunning,
- );
- this.pipelineCached = true;
- this.pipelineCachedChanged.emit(this.pipelineCached);
- });
- });
- }
-
showErrorDialog(title: string, description: string) {
this.dialog.open(ConfirmDialogComponent, {
width: '500px',
@@ -624,10 +552,10 @@ export class PipelineComponent implements OnInit,
OnDestroy {
.updatePipeline(this.currentPipelineModel)
.subscribe(pm => {
this.modifyPipeline(pm);
- this.triggerPipelineCacheUpdate();
+ this.triggerPipelineCacheUpdateEmitter.emit();
this.announceConfiguredElement(pipelineElementConfig);
if (this.previewModeActive) {
- this.deletePipelineElementPreview(true);
+ this.deletePreviewEmitter.emit(true);
}
this.validatePipeline(pm);
});
@@ -641,44 +569,6 @@ export class PipelineComponent implements OnInit,
OnDestroy {
this.editorService.announceConfiguredElement(pe.payload.dom);
}
- initiatePipelineElementPreview() {
- if (!this.previewModeActive) {
- const pipeline = this.objectProvider.makePipeline(
- this.rawPipelineModel,
- );
- this.editorService
- .initiatePipelinePreview(pipeline)
- .subscribe(response => {
- this.pipelinePreview = response;
- this.previewModeActive = true;
- this.pipelinePreviewSub = this.editorService
- .getPipelinePreviewResult(response.previewId)
- .subscribe(res => {
- const data = this.livePreviewService.convert(
- res as HttpDownloadProgressEvent,
- );
- this.livePreviewService.eventSub.next(data);
- });
- });
- } else {
- this.deletePipelineElementPreview(false);
- }
- }
-
- deletePipelineElementPreview(resume: boolean) {
- if (this.previewModeActive) {
- this.pipelinePreviewSub?.unsubscribe();
- this.editorService
- .deletePipelinePreviewRequest(this.pipelinePreview.previewId)
- .subscribe(() => {
- this.previewModeActive = false;
- if (resume) {
- this.initiatePipelineElementPreview();
- }
- });
- }
- }
-
triggerPipelineModification() {
this.currentPipelineModel = this.objectProvider.makePipeline(
this.rawPipelineModel,
@@ -690,7 +580,7 @@ export class PipelineComponent implements OnInit, OnDestroy
{
this.pipelineValid =
this.pipelineValidationService.isValidPipeline(
this.rawPipelineModel,
- this.preview,
+ this.readonly,
pm,
);
});
diff --git a/ui/src/app/editor/editor.component.html
b/ui/src/app/editor/editor.component.html
index 27da459f4a..b334d81895 100644
--- a/ui/src/app/editor/editor.component.html
+++ b/ui/src/app/editor/editor.component.html
@@ -40,7 +40,7 @@
<div
id="shepherd-test"
style="
- padding: 0px;
+ padding: 0;
border-bottom: 1px solid #ffffff;
margin-right: 5px;
"
@@ -55,9 +55,12 @@
<sp-pipeline-assembly
fxFlex="100"
style="margin-left: 10px"
+ *ngIf="allElementsLoaded && allMetadataLoaded"
[rawPipelineModel]="rawPipelineModel"
[allElements]="allElements"
- [currentModifiedPipelineId]="currentModifiedPipelineId"
+ [originalPipeline]="originalPipeline"
+ [pipelineCanvasMetadata]="pipelineCanvasMetadata"
+ [pipelineCanvasMetadataAvailable]="pipelineCanvasMetadataAvailable"
>
</sp-pipeline-assembly>
</div>
diff --git a/ui/src/app/editor/editor.component.ts
b/ui/src/app/editor/editor.component.ts
index a6ed4a5a0b..e33fd34c47 100644
--- a/ui/src/app/editor/editor.component.ts
+++ b/ui/src/app/editor/editor.component.ts
@@ -17,15 +17,24 @@
*/
import { Component, OnInit } from '@angular/core';
-import { PipelineElementService } from '@streampipes/platform-services';
+import {
+ Pipeline,
+ PipelineCanvasMetadata,
+ PipelineCanvasMetadataService,
+ PipelineElementService,
+ PipelineService,
+} from '@streampipes/platform-services';
import {
PipelineElementConfig,
PipelineElementUnion,
} from './model/editor.model';
import { SpBreadcrumbService } from '@streampipes/shared-ui';
import { ActivatedRoute } from '@angular/router';
-import { zip } from 'rxjs';
+import { forkJoin, of, zip } from 'rxjs';
import { SpPipelineRoutes } from '../pipelines/pipelines.routes';
+import { catchError } from 'rxjs/operators';
+import { EditorService } from './services/editor.service';
+import { JsplumbService } from './services/jsplumb.service';
@Component({
selector: 'sp-editor',
@@ -36,21 +45,29 @@ export class EditorComponent implements OnInit {
allElements: PipelineElementUnion[] = [];
rawPipelineModel: PipelineElementConfig[] = [];
- currentModifiedPipelineId: string;
+ originalPipeline: Pipeline;
allElementsLoaded = false;
+ allMetadataLoaded = false;
+ pipelineCanvasMetadata: PipelineCanvasMetadata;
+ pipelineCanvasMetadataAvailable: boolean;
constructor(
private pipelineElementService: PipelineElementService,
private activatedRoute: ActivatedRoute,
private breadcrumbService: SpBreadcrumbService,
+ private editorService: EditorService,
+ private pipelineService: PipelineService,
+ private jsplumbService: JsplumbService,
+ private pipelineCanvasMetadataService: PipelineCanvasMetadataService,
) {}
ngOnInit() {
const pipelineId = this.activatedRoute.snapshot.params.pipelineId;
if (pipelineId) {
- this.currentModifiedPipelineId = pipelineId;
+ this.loadPipelineToModify(pipelineId);
} else {
+ this.loadCachedPipeline();
this.breadcrumbService.updateBreadcrumb([
SpPipelineRoutes.BASE,
{ label: 'New Pipeline' },
@@ -71,4 +88,61 @@ export class EditorComponent implements OnInit {
this.allElementsLoaded = true;
});
}
+
+ loadCachedPipeline() {
+ 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[];
+ this.handleCanvasMetadataResponse(results[1]);
+ } else {
+ this.pipelineCanvasMetadata = new PipelineCanvasMetadata();
+ this.pipelineCanvasMetadataAvailable = false;
+ }
+ this.allMetadataLoaded = true;
+ });
+ }
+
+ loadPipelineToModify(pipelineId: string) {
+ const pipelineReq = this.pipelineService.getPipelineById(pipelineId);
+ const canvasMetadataReq = this.pipelineCanvasMetadataService
+ .getPipelineCanvasMetadata(pipelineId)
+ .pipe(
+ catchError(() => {
+ this.handleCanvasMetadataResponse(undefined);
+ return of(undefined);
+ }),
+ );
+
+ forkJoin([pipelineReq, canvasMetadataReq]).subscribe(
+ ([pipelineResp, canvasResp]) => {
+ if (pipelineResp) {
+ this.originalPipeline = pipelineResp;
+ this.breadcrumbService.updateBreadcrumb([
+ SpPipelineRoutes.BASE,
+ { label: this.originalPipeline.name },
+ { label: 'Modify' },
+ ]);
+ this.rawPipelineModel =
this.jsplumbService.makeRawPipeline(
+ this.originalPipeline,
+ false,
+ );
+ }
+ this.handleCanvasMetadataResponse(canvasResp);
+ this.allMetadataLoaded = true;
+ },
+ );
+ }
+
+ handleCanvasMetadataResponse(canvasMetadata: PipelineCanvasMetadata) {
+ if (canvasMetadata !== undefined) {
+ this.pipelineCanvasMetadata = canvasMetadata;
+ this.pipelineCanvasMetadataAvailable = true;
+ } else {
+ this.pipelineCanvasMetadataAvailable = false;
+ this.pipelineCanvasMetadata = new PipelineCanvasMetadata();
+ }
+ }
}
diff --git a/ui/src/app/editor/editor.module.ts
b/ui/src/app/editor/editor.module.ts
index 32a6f823c6..8922b4ff6d 100644
--- a/ui/src/app/editor/editor.module.ts
+++ b/ui/src/app/editor/editor.module.ts
@@ -46,7 +46,7 @@ import { EnabledPipelineElementFilter } from
'./filter/enabled-pipeline-element.
import { PipelineElementPreviewComponent } from
'./components/pipeline-element-preview/pipeline-element-preview.component';
import { PipelineElementDiscoveryComponent } from
'./dialog/pipeline-element-discovery/pipeline-element-discovery.component';
import { PlatformServicesModule } from '@streampipes/platform-services';
-import { PipelineElementIconStandRowComponent } from
'./components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component';
+import { PipelineElementIconStandRowComponent } from
'./components/pipeline-element-icon-stand/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component';
import { PipelineElementTypeFilterPipe } from
'./services/pipeline-element-type-filter.pipe';
import { PipelineElementNameFilterPipe } from
'./services/pipeline-element-name-filter.pipe';
import { PipelineElementGroupFilterPipe } from
'./services/pipeline-element-group-filter.pipe';
@@ -77,6 +77,11 @@ import { MatSliderModule } from '@angular/material/slider';
import { PipelineElementStatisticsComponent } from
'./components/pipeline-element-statistics/pipeline-element-statistics.component';
import { PipelineElementStatisticsBadgeComponent } from
'./components/pipeline-element-statistics/pipeline-element-statistics-badge/pipeline-element-statistics-badge.component';
import { SavePipelineSettingsComponent } from
'./dialog/save-pipeline/save-pipeline-settings/save-pipeline-settings.component';
+import { PipelineAssemblyOptionsComponent } from
'./components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options.component';
+import { PipelineAssemblyOptionsPipelineCacheComponent } from
'./components/pipeline-assembly/pipeline-assembly-options/pipeline-assembly-options-pipeline-cache/pipeline-assembly-options-pipeline-cache.component';
+import { PipelineAssemblyDrawingAreaPanZoomComponent } from
'./components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area-pan-zoom/pipeline-assembly-drawing-area-pan-zoom.component';
+import { PipelineAssemblyDrawingAreaComponent } from
'./components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component';
+import { DroppedPipelineElementComponent } from
'./components/pipeline/dropped-pipeline-element/dropped-pipeline-element.component';
@NgModule({
imports: [
@@ -121,6 +126,7 @@ import { SavePipelineSettingsComponent } from
'./dialog/save-pipeline/save-pipel
CompatibleElementsComponent,
CustomizeComponent,
CustomOutputStrategyComponent,
+ DroppedPipelineElementComponent,
EditorComponent,
EnabledPipelineElementFilter,
MatchingErrorComponent,
@@ -128,6 +134,10 @@ import { SavePipelineSettingsComponent } from
'./dialog/save-pipeline/save-pipel
OutputStrategyComponent,
UserDefinedOutputStrategyComponent,
PipelineAssemblyComponent,
+ PipelineAssemblyDrawingAreaComponent,
+ PipelineAssemblyDrawingAreaPanZoomComponent,
+ PipelineAssemblyOptionsComponent,
+ PipelineAssemblyOptionsPipelineCacheComponent,
PipelineElementComponent,
PipelineElementDiscoveryComponent,
PipelineElementIconStandComponent,
@@ -147,7 +157,12 @@ import { SavePipelineSettingsComponent } from
'./dialog/save-pipeline/save-pipel
SafeCss,
],
providers: [SafeCss],
- exports: [EditorComponent, PipelineComponent, PipelineElementComponent],
+ exports: [
+ EditorComponent,
+ PipelineComponent,
+ PipelineElementComponent,
+ PipelineAssemblyDrawingAreaComponent,
+ ],
})
export class EditorModule {
constructor() {}
diff --git a/ui/src/app/editor/services/jsplumb-factory.service.ts
b/ui/src/app/editor/services/jsplumb-factory.service.ts
index 679b61d674..9d554cae82 100644
--- a/ui/src/app/editor/services/jsplumb-factory.service.ts
+++ b/ui/src/app/editor/services/jsplumb-factory.service.ts
@@ -30,10 +30,7 @@ import { JsplumbConfigService } from
'./jsplumb-config.service';
@Injectable({ providedIn: 'root' })
export class JsplumbFactoryService {
pipelineEditorInstance: BrowserJsPlumbInstance;
- pipelinePreviewInstance: BrowserJsPlumbInstance;
-
pipelineEditorBridge: JsplumbBridge;
- pipelinePreviewBridge: JsplumbBridge;
constructor(
private pipelineElementDraggedService: PipelineElementDraggedService,
@@ -41,26 +38,16 @@ export class JsplumbFactoryService {
) {}
getJsplumbBridge(previewConfig: boolean): JsplumbBridge {
- if (!previewConfig) {
- if (!this.pipelineEditorBridge) {
- this.pipelineEditorInstance =
this.makePipelineEditorInstance();
- this.prepareJsplumb(this.pipelineEditorInstance);
- this.pipelineEditorBridge = new JsplumbBridge(
- this.pipelineEditorInstance,
- );
- }
- return this.pipelineEditorBridge;
- } else {
- if (!this.pipelinePreviewBridge) {
- this.pipelinePreviewInstance =
- this.makePipelinePreviewInstance();
- this.prepareJsplumb(this.pipelinePreviewInstance);
- this.pipelinePreviewBridge = new JsplumbBridge(
- this.pipelinePreviewInstance,
- );
- }
- return this.pipelinePreviewBridge;
+ if (!this.pipelineEditorBridge) {
+ this.pipelineEditorInstance = previewConfig
+ ? this.makePipelinePreviewInstance()
+ : this.makePipelineEditorInstance();
+ this.prepareJsplumb(this.pipelineEditorInstance);
+ this.pipelineEditorBridge = new JsplumbBridge(
+ this.pipelineEditorInstance,
+ );
}
+ return this.pipelineEditorBridge;
}
makePipelineEditorInstance(): BrowserJsPlumbInstance {
@@ -82,7 +69,7 @@ export class JsplumbFactoryService {
makePipelinePreviewInstance(): BrowserJsPlumbInstance {
return newInstance({
- container: document.getElementById('assembly-preview'),
+ container: document.getElementById('assembly'),
elementsDraggable: false,
});
}
@@ -93,13 +80,8 @@ export class JsplumbFactoryService {
);
}
- destroy(preview: boolean) {
- if (preview) {
- this.pipelinePreviewInstance.destroy();
- this.pipelinePreviewBridge = undefined;
- } else {
- this.pipelineEditorInstance.destroy();
- this.pipelineEditorBridge = undefined;
- }
+ destroy() {
+ this.pipelineEditorInstance?.destroy();
+ this.pipelineEditorBridge = undefined;
}
}
diff --git a/ui/src/app/editor/services/pipeline-positioning.service.ts
b/ui/src/app/editor/services/pipeline-positioning.service.ts
index 1565101c72..52342e9e66 100644
--- a/ui/src/app/editor/services/pipeline-positioning.service.ts
+++ b/ui/src/app/editor/services/pipeline-positioning.service.ts
@@ -18,7 +18,6 @@
import * as dagre from 'dagre';
import { JsplumbBridge } from './jsplumb-bridge.service';
-import { JsplumbConfigService } from './jsplumb-config.service';
import { JsplumbService } from './jsplumb.service';
import { Injectable } from '@angular/core';
import { PipelineElementConfig } from '../model/editor.model';
@@ -37,7 +36,6 @@ import { Connection } from '@jsplumb/browser-ui';
export class PipelinePositioningService {
constructor(
private jsplumbService: JsplumbService,
- private jsplumbConfigService: JsplumbConfigService,
private jsplumbFactoryService: JsplumbFactoryService,
private objectProvider: ObjectProvider,
) {}
@@ -87,8 +85,6 @@ export class PipelinePositioningService {
const jsPlumbBridge =
this.jsplumbFactoryService.getJsplumbBridge(previewConfig);
- const jsplumbConfig = this.jsplumbConfigService.getEditorConfig();
-
rawPipelineModel.forEach(currentPe => {
if (!currentPe.settings.disabled) {
if (currentPe.type === 'stream' || currentPe.type === 'set') {
diff --git
a/ui/src/app/pipeline-details/components/pipeline-details-expansion-panel/pipeline-element-details-row/elements/pipeline-elements-row.component.ts
b/ui/src/app/pipeline-details/components/pipeline-details-expansion-panel/pipeline-element-details-row/elements/pipeline-elements-row.component.ts
index 1bee34607b..a19c8e059c 100644
---
a/ui/src/app/pipeline-details/components/pipeline-details-expansion-panel/pipeline-element-details-row/elements/pipeline-elements-row.component.ts
+++
b/ui/src/app/pipeline-details/components/pipeline-details-expansion-panel/pipeline-element-details-row/elements/pipeline-elements-row.component.ts
@@ -24,7 +24,7 @@ import { PipelineElementTypeUtils } from
'../../../../../editor/utils/editor.uti
selector: 'sp-pipeline-elements-row',
templateUrl: './pipeline-elements-row.component.html',
styleUrls: [
-
'../../../../../editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.scss',
+
'../../../../../editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.scss',
],
})
export class PipelineElementsRowComponent implements OnInit {
diff --git
a/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
b/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
index ca4a4fc397..6ff4085506 100644
---
a/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
+++
b/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
@@ -16,16 +16,21 @@
~
-->
-<div class="outer-assembly-preview">
- <div class="pipeline-canvas-outer canvas-preview-inner">
- <div id="{{ jspcanvas }}" class="canvas-preview">
- <sp-pipeline
- [canvasId]="jspcanvas"
- [metricsInfo]="metricsInfo"
- [rawPipelineModel]="rawPipelineModel"
- [preview]="true"
- ></sp-pipeline>
- </div>
+<div class="outer-assembly-preview" fxFlex="100">
+ <div class="outerAssembly" fxFlex="100">
+ <sp-pipeline-assembly-drawing-area
+ *ngIf="rawPipelineModel"
+ fxFlex="100"
+ style="position: relative"
+ [jsplumbBridge]="jsPlumbBridge"
+ [metricsInfo]="metricsInfo"
+ [rawPipelineModel]="rawPipelineModel"
+ [pipelineCanvasMetadata]="pipelineCanvasMetadata"
+ [pipelineCanvasMetadataAvailable]="
+ pipelineCanvasMetadata !== undefined
+ "
+ [readonly]="true"
+ ></sp-pipeline-assembly-drawing-area>
</div>
<ng-content></ng-content>
</div>
diff --git
a/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.ts
b/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.ts
index ce0208628d..3bea243bef 100644
---
a/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.ts
+++
b/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.ts
@@ -16,7 +16,14 @@
*
*/
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import {
+ AfterViewInit,
+ Component,
+ EventEmitter,
+ Input,
+ OnInit,
+ Output,
+} from '@angular/core';
import {
Pipeline,
PipelineCanvasMetadata,
@@ -26,20 +33,15 @@ import {
PipelineElementConfig,
PipelineElementUnion,
} from '../../../editor/model/editor.model';
-import { PipelinePositioningService } from
'../../../editor/services/pipeline-positioning.service';
import { JsplumbService } from '../../../editor/services/jsplumb.service';
-import { ObjectProvider } from
'../../../editor/services/object-provider.service';
-import { JsplumbFactoryService } from
'../../../editor/services/jsplumb-factory.service';
+import { JsplumbBridge } from
'../../../editor/services/jsplumb-bridge.service';
@Component({
selector: 'sp-pipeline-preview',
templateUrl: './pipeline-preview.component.html',
styleUrls: ['./pipeline-preview.component.scss'],
})
-export class PipelinePreviewComponent implements OnInit {
- @Input()
- jspcanvas: string;
-
+export class PipelinePreviewComponent implements OnInit, AfterViewInit {
@Input()
metricsInfo: Record<string, SpMetricsEntry>;
@@ -55,52 +57,18 @@ export class PipelinePreviewComponent implements OnInit {
selectedElementEmitter: EventEmitter<PipelineElementUnion> =
new EventEmitter<PipelineElementUnion>();
- constructor(
- private pipelinePositioningService: PipelinePositioningService,
- private jsplumbService: JsplumbService,
- private jsplumbFactoryService: JsplumbFactoryService,
- private objectProvider: ObjectProvider,
- ) {}
+ jsPlumbBridge: JsplumbBridge;
+
+ constructor(private jsplumbService: JsplumbService) {}
+
+ ngAfterViewInit() {
+ this.jsPlumbBridge = this.jsplumbService.getBridge(true);
+ }
ngOnInit() {
- setTimeout(() => {
- const canvasElementId = '#' + this.jspcanvas;
- this.rawPipelineModel = this.jsplumbService.makeRawPipeline(
- this.pipeline,
- true,
- );
- setTimeout(() => {
- this.pipelinePositioningService.displayPipeline(
- this.rawPipelineModel,
- canvasElementId,
- true,
- this.pipelineCanvasMetadata === undefined,
- this.pipelineCanvasMetadata,
- );
- const existingEndpointIds = [];
- setTimeout(() => {
- this.jsplumbFactoryService
- .getJsplumbBridge(true)
- .selectEndpoints()
- .each(endpoint => {
- if (
- existingEndpointIds.indexOf(
- endpoint.element.id,
- ) === -1
- ) {
- $(endpoint.element).click(() => {
- const payload =
- this.objectProvider.findElement(
- endpoint.element.id,
- this.rawPipelineModel,
- ).payload;
- this.selectedElementEmitter.emit(payload);
- });
- existingEndpointIds.push(endpoint.element.id);
- }
- });
- });
- });
- });
+ this.rawPipelineModel = this.jsplumbService.makeRawPipeline(
+ this.pipeline,
+ true,
+ );
}
}
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.html
b/ui/src/app/pipeline-details/pipeline-details.component.html
index f07f3464a6..9e38234ea6 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.html
+++ b/ui/src/app/pipeline-details/pipeline-details.component.html
@@ -32,7 +32,6 @@
</div>
<div fxFlex="100" fxLayout="column">
<sp-pipeline-preview
- [jspcanvas]="'assembly-preview'"
[metricsInfo]="metricsInfo"
[pipeline]="pipeline"
[pipelineCanvasMetadata]="pipelineCanvasMetadata"