You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ri...@apache.org on 2020/06/06 10:20:37 UTC
[incubator-streampipes] branch STREAMPIPES-145 updated:
[STREAMPIPES-145] Add pipeline component
This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch STREAMPIPES-145
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git
The following commit(s) were added to refs/heads/STREAMPIPES-145 by this push:
new 53a561e [STREAMPIPES-145] Add pipeline component
53a561e is described below
commit 53a561e02936a2b350088776223b999c669cae04
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Sat Jun 6 12:20:20 2020 +0200
[STREAMPIPES-145] Add pipeline component
---
.../pipeline-assembly.component.html | 16 +-
.../pipeline-assembly.component.ts | 13 +-
.../pipeline-element-icon-stand.component.html | 5 +-
.../pipeline-element-icon-stand.component.ts | 44 ++-
.../pipeline-element/pipeline-element.component.ts | 5 +-
.../components/pipeline/pipeline.component.css | 0
.../components/pipeline/pipeline.component.html | 47 +++
.../components/pipeline/pipeline.component.ts | 350 +++++++++++++++++++++
ui/src/app/editor-v2/constants/editor.constants.ts | 25 ++
ui/src/app/editor-v2/editor.component.html | 2 +-
ui/src/app/editor-v2/editor.component.ts | 77 +++--
ui/src/app/editor-v2/editor.module.ts | 10 +-
ui/src/app/editor-v2/model/editor.model.ts | 53 +++-
.../editor-v2/services/jsplumb-bridge.service.ts | 2 +
ui/src/app/editor-v2/services/jsplumb.service.ts | 42 +--
.../editor-v2/services/pipeline-editor.service.ts | 6 +-
ui/src/app/editor-v2/utils/editor.utils.ts | 97 ++++++
17 files changed, 692 insertions(+), 102 deletions(-)
diff --git a/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.html b/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.html
index 8f0545a..ddd04dc 100644
--- a/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.html
+++ b/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.html
@@ -102,14 +102,14 @@
</div>
</div>
<div id="outerAssemblyArea" class="outerAssembly sp-blue-border-nopadding">
- <div mwlDroppable id="assembly" class="canvas" (drop)="elementDropped($event)">
-<!-- <pipeline pipeline-valid="ctrl.pipelineValid"-->
-<!-- canvas-id="assembly"-->
-<!-- raw-pipeline-model="ctrl.rawPipelineModel"-->
-<!-- all-elements="ctrl.allElements"-->
-<!-- preview="false"-->
-<!-- pipeline-cached="ctrl.pipelineCached"-->
-<!-- pipeline-cache-running="ctrl.pipelineCacheRunning"></pipeline>-->
+ <div id="assembly" class="canvas">
+ <pipeline [pipelineValid]="pipelineValid"
+ [canvasId]="'assembly'"
+ [rawPipelineModel]="rawPipelineModel"
+ [allElements]="allElements"
+ [preview]="false"
+ [pipelineCached]="pipelineCached"
+ [pipelineCacheRunning]="pipelineCacheRunning"></pipeline>
</div>
</div>
</div>
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.ts b/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.ts
index b4fccc4..62c10a4 100644
--- a/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.ts
+++ b/ui/src/app/editor-v2/components/pipeline-assembly/pipeline-assembly.component.ts
@@ -28,6 +28,11 @@ import {JsplumbService} from "../../services/jsplumb.service";
import {RestApi} from "../../../services/rest-api.service";
import {TransitionService} from "../../../services/transition.service";
import {ShepherdService} from "../../../services/tour/shepherd.service";
+import {
+ PipelineElementConfig,
+ PipelineElementHolder,
+ PipelineElementUnion
+} from "../../model/editor.model";
@Component({
@@ -45,7 +50,7 @@ export class PipelineAssemblyComponent implements OnInit {
preview: any;
@Input()
- rawPipelineModel: any;
+ rawPipelineModel: PipelineElementConfig[];
selectMode: any;
currentPipelineName: any;
currentPipelineDescription: any;
@@ -54,7 +59,7 @@ export class PipelineAssemblyComponent implements OnInit {
currentModifiedPipelineId: any;
@Input()
- allElements: any;
+ allElements: PipelineElementUnion[];
errorMessagesDisplayed: any = false;
@@ -229,8 +234,4 @@ export class PipelineAssemblyComponent implements OnInit {
return this.rawPipelineModel.length === 0 || this.rawPipelineModel.every(pe => pe.settings.disabled);
}
- elementDropped($event) {
- console.log($event);
- }
-
}
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.html b/ui/src/app/editor-v2/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.html
index f797a9d..bdfac01 100644
--- a/ui/src/app/editor-v2/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.html
+++ b/ui/src/app/editor-v2/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.html
@@ -74,10 +74,11 @@
</div>
</div>
<div flex id="editor-icon-stand" class="icon-stand" *ngIf="currentElements">
- <span mwlDraggable id="{{ element.name }}" (mouseenter)="updateMouseOver(element.name)"
+ <span id="{{ element.appId }}" (mouseenter)="updateMouseOver(element.name)"
(mouseleave)="updateMouseOver('')"
*ngFor="let element of currentElements"
- class="draggable-icon tt" [dropData]="element"
+ class="draggable-icon tt"
+ [attr.data-pe]="element.elementId"
[ngClass]="activeCssClass">
<span id="container" style="position:relative;display:block;width:80px;height:80px;">
<pipeline-element id="pe-icon-stand-{{ element.appId }}" style="margin-left:-3%" [iconStandSize]="true" [pipelineElement]="element"
diff --git a/ui/src/app/editor-v2/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.ts b/ui/src/app/editor-v2/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.ts
index 784f89e..574ecb8 100644
--- a/ui/src/app/editor-v2/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.ts
+++ b/ui/src/app/editor-v2/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.ts
@@ -27,7 +27,8 @@ import {
SpDataSet,
SpDataStream
} from "../../../core-model/gen/streampipes-model";
-import {EditorComponent} from "../../editor.component";
+import {PipelineElementType, PipelineElementUnion} from "../../model/editor.model";
+import {PipelineElementTypeUtils} from "../../utils/editor.utils";
@Component({
@@ -38,13 +39,13 @@ import {EditorComponent} from "../../editor.component";
export class PipelineElementIconStandComponent implements OnInit {
@Input()
- currentElements: (SpDataSet | SpDataStream | DataProcessorInvocation | DataSinkInvocation)[];
+ currentElements: PipelineElementUnion[];
elementFilter: string;
availableOptions: any = [];
selectedOptions: any = [];
- _activeType: string;
+ _activeType: PipelineElementType;
activeCssClass: string;
currentElementName: string;
@@ -54,10 +55,13 @@ export class PipelineElementIconStandComponent implements OnInit {
}
ngOnInit(): void {
- console.log(this.activeType);
this.loadOptions(this.activeType);
}
+ ngAfterViewInit() {
+ this.makeDraggable();
+ }
+
openHelpDialog(pipelineElement) {
//this.EditorDialogManager.openHelpDialog(pipelineElement);
}
@@ -114,21 +118,31 @@ export class PipelineElementIconStandComponent implements OnInit {
}
@Input()
- set activeType(value: string) {
+ set activeType(value: PipelineElementType) {
this._activeType = value;
this.activeCssClass = this.makeActiveCssClass(value);
+ setTimeout(() => {
+ this.makeDraggable();
+ })
};
- makeActiveCssClass(elementType: string) {
- if (EditorComponent.DATA_STREAM_IDENTIFIER === elementType) {
- return "stream";
- } else if (EditorComponent.DATA_SET_IDENTIFIER === elementType) {
- return "set";
- } else if (EditorComponent.DATA_PROCESSOR_IDENTIFIER === elementType) {
- return "sepa";
- } else {
- return "action";
- }
+ makeActiveCssClass(elementType: PipelineElementType): string {
+ return PipelineElementTypeUtils.toCssShortHand(elementType);
}
+ makeDraggable() {
+ (<any>$('.draggable-icon')).draggable({
+ revert: 'invalid',
+ helper: 'clone',
+ stack: '.draggable-icon',
+ start: function (el, ui) {
+ ui.helper.appendTo('#content');
+ $('#outerAssemblyArea').css('border', '3px dashed #39b54a');
+ },
+ stop: function (el, ui) {
+ $('#outerAssemblyArea').css('border', '3px solid rgb(156, 156, 156)');
+ }
+ });
+ };
+
}
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/components/pipeline-element/pipeline-element.component.ts b/ui/src/app/editor-v2/components/pipeline-element/pipeline-element.component.ts
index e6dc952..00620aa 100644
--- a/ui/src/app/editor-v2/components/pipeline-element/pipeline-element.component.ts
+++ b/ui/src/app/editor-v2/components/pipeline-element/pipeline-element.component.ts
@@ -24,6 +24,7 @@ import * as angular from "angular";
import {RestApi} from "../../../services/rest-api.service";
import {ElementIconText} from "../../../services/get-element-icon-text.service";
import {ImageChecker} from "../../../services/image-checker.service";
+import {PipelineElementUnion} from "../../model/editor.model";
@Component({
@@ -37,7 +38,7 @@ export class PipelineElementComponent implements OnInit {
iconText: any;
@Input()
- pipelineElement: any;
+ pipelineElement: PipelineElementUnion;
@Input()
preview: any;
@@ -57,7 +58,6 @@ export class PipelineElementComponent implements OnInit {
}
ngOnInit(): void {
- console.log(this.pipelineElement);
this.iconText = this.ElementIconText.getElementIconText(this.pipelineElement.name);
this.checkImageAvailable();
}
@@ -94,5 +94,4 @@ export class PipelineElementComponent implements OnInit {
}
}
-
}
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/components/pipeline/pipeline.component.css b/ui/src/app/editor-v2/components/pipeline/pipeline.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/ui/src/app/editor-v2/components/pipeline/pipeline.component.html b/ui/src/app/editor-v2/components/pipeline/pipeline.component.html
new file mode 100644
index 0000000..9579975
--- /dev/null
+++ b/ui/src/app/editor-v2/components/pipeline/pipeline.component.html
@@ -0,0 +1,47 @@
+<!--
+ ~ 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 *ngFor="let pipelineElement of rawPipelineModel" style="width:100%;height:100%;z-index:1">
+ <div *ngIf="pipelineElement.settings.disabled == undefined || !pipelineElement.settings.disabled">
+ <span id="{{pipelineElement.payload.dom}}" style="{{getElementCss(pipelineElement.settings)}}"
+ (click)="updateOptionsClick(pipelineElement.payload.dom)" (mouseenter)="updateMouseover(pipelineElement.payload.dom)" (mouseleave)="updateMouseover('')">
+ <span style="z-index:5;"
+ [ngClass]="getElementCssClasses(pipelineElement)">
+ <div class="pipeline-element-progress-container sp-fade" *ngIf="pipelineElement.settings.loadingStatus">
+<!-- <md-progress-circular md-mode="indeterminate" class="pipeline-element-progress" md-diameter="40px"></md-progress-circular>-->
+ </div>
+ <div class="pipeline-element-loading-container sp-fade-opacity" *ngIf="pipelineElement.settings.loadingStatus"></div>
+ <div class="pipeline-element-configuration-invalid {{pipelineElement.type === 'stream' ? 'pi-stream' : 'pi-processor'}}" *ngIf="pipelineElement.payload.uncompleted">
+ <i class="material-icons pipeline-element-configuration-invalid-icon">
+ warning
+ </i>
+ </div>
+ <pipeline-element [pipelineElement]="pipelineElement.payload" [preview]="preview"></pipeline-element>
+ </span>
+<!-- <pipeline-element-options ng-if="!ctrl.preview" delete-function="ctrl.handleDeleteOption"-->
+<!-- current-mouse-over-element="ctrl.currentMouseOverElement"-->
+<!-- pipeline-valid="ctrl.pipelineValid"-->
+<!-- all-elements="ctrl.allElements"-->
+<!-- pipeline-element="pipelineElement"-->
+<!-- raw-pipeline-model="ctrl.rawPipelineModel"-->
+<!-- pipeline-element-id="pipelineElement.type == 'stream' ? pipelineElement.payload.elementId : pipelineElement.payload.belongsTo)"-->
+<!-- internal-id="" {{pipelineElement.payload.DOM}}">-->
+<!-- </pipeline-element-options>-->
+ </span>
+</div>
+</div>
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/components/pipeline/pipeline.component.ts b/ui/src/app/editor-v2/components/pipeline/pipeline.component.ts
new file mode 100644
index 0000000..a2ab01c
--- /dev/null
+++ b/ui/src/app/editor-v2/components/pipeline/pipeline.component.ts
@@ -0,0 +1,350 @@
+/*
+ * 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 * as angular from "angular";
+
+import {PipelineValidationService} from "../../../editor-v2/services/pipeline-validation.service";
+import {RestApi} from "../../../services/rest-api.service";
+import {JsplumbService} from "../../services/jsplumb.service";
+import {PipelineEditorService} from "../../services/pipeline-editor.service";
+import {JsplumbBridge} from "../../services/jsplumb-bridge.service";
+import {ShepherdService} from "../../../services/tour/shepherd.service";
+import {Component, Input, OnInit} from "@angular/core";
+import {
+ PipelineElementConfig,
+ PipelineElementHolder,
+ PipelineElementUnion
+} from "../../model/editor.model";
+import {SpDataStream} from "../../../core-model/gen/streampipes-model";
+
+@Component({
+ selector: 'pipeline',
+ templateUrl: './pipeline.component.html',
+ styleUrls: ['./pipeline.component.css']
+})
+export class PipelineComponent implements OnInit {
+
+ @Input()
+ pipelineValid: boolean;
+
+ @Input()
+ canvasId: string;
+
+ @Input()
+ rawPipelineModel: PipelineElementConfig[];
+
+ @Input()
+ allElements: PipelineElementUnion[];
+
+ @Input()
+ preview: boolean;
+
+ @Input()
+ pipelineCached: boolean;
+
+ @Input()
+ pipelineCacheRunning: boolean;
+
+ availablePipelineElementCache: PipelineElementUnion[];
+
+ DialogBuilder: any;
+ plumbReady: any;
+ objectProvider: any;
+ EditorDialogManager: any;
+ currentMouseOverElement: any;
+ currentPipelineModel: any;
+ idCounter: any;
+ currentZoomLevel: any;
+ TransitionService: any;
+
+ // remove later
+
+ constructor(private JsplumbService: JsplumbService,
+ private PipelineEditorService: PipelineEditorService,
+ private JsplumbBridge: JsplumbBridge,
+ //DialogBuilder,
+ //EditorDialogManager,
+ // TransitionService,
+ private ShepherdService: ShepherdService,
+ private PipelineValidationService: PipelineValidationService,
+ private RestApi: RestApi) {
+ this.plumbReady = false;
+ this.currentMouseOverElement = "";
+ this.currentPipelineModel = {};
+ this.idCounter = 0;
+
+ this.currentZoomLevel = 1;
+ }
+
+ ngOnInit() {
+ this.JsplumbBridge.setContainer(this.canvasId);
+ this.initAssembly();
+ this.initPlumb();
+ }
+
+ validatePipeline() {
+ //this.$timeout(() => {
+ this.pipelineValid = this.PipelineValidationService.isValidPipeline(this.rawPipelineModel);
+ //}, 200);
+ }
+
+ ngOnDestroy() {
+ this.JsplumbBridge.deleteEveryEndpoint();
+ this.plumbReady = false;
+ }
+
+ updateMouseover(elementId) {
+ this.currentMouseOverElement = elementId;
+ }
+
+ updateOptionsClick(elementId) {
+ if (this.currentMouseOverElement == elementId) {
+ this.currentMouseOverElement = "";
+ } else {
+ this.currentMouseOverElement = elementId;
+ }
+ }
+
+ getElementCss(currentPipelineElementSettings) {
+ return "position:absolute;"
+ + (this.preview ? "width:75px;" : "width:110px;")
+ + (this.preview ? "height:75px;" : "height:110px;")
+ + "left: " + currentPipelineElementSettings.position.x + "px; "
+ + "top: " + currentPipelineElementSettings.position.y + "px; "
+ }
+
+ getElementCssClasses(currentPipelineElement) {
+ return currentPipelineElement.type + " " + (currentPipelineElement.settings.openCustomize ? "" : "")
+ + currentPipelineElement.settings.connectable + " "
+ + currentPipelineElement.settings.displaySettings;
+ }
+
+ isStreamInPipeline() {
+ return this.isInPipeline('stream');
+ }
+
+ isSetInPipeline() {
+ return this.isInPipeline('set');
+ }
+
+ isInPipeline(type) {
+ return this.rawPipelineModel.some(x => (x.type == type && !(x.settings.disabled)));
+ }
+
+ showMixedStreamAlert() {
+ this.EditorDialogManager.showMixedStreamAlert();
+ }
+
+ findPipelineElementByElementId(elementId: string) {
+ return this.allElements.find(a => a.elementId === elementId);
+ }
+
+
+ initAssembly() {
+ ($('#assembly') as any).droppable({
+ tolerance: "fit",
+ drop: (element, ui) => {
+ let pipelineElementId = ui.draggable.data("pe");
+ let pipelineElement: PipelineElementUnion = this.findPipelineElementByElementId(pipelineElementId);
+ if (ui.draggable.hasClass('draggable-icon')) {
+ //this.TransitionService.makePipelineAssemblyEmpty(false);
+ var pipelineElementConfig = this.JsplumbService.createNewPipelineElementConfig(pipelineElement, this.PipelineEditorService.getCoordinates(ui, this.currentZoomLevel), false);
+ if ((this.isStreamInPipeline() && pipelineElementConfig.type == 'set') ||
+ this.isSetInPipeline() && pipelineElementConfig.type == 'stream') {
+ this.showMixedStreamAlert();
+ } else {
+ this.rawPipelineModel.push(pipelineElementConfig);
+ if (ui.draggable.hasClass('set')) {
+ setTimeout(() => {
+ setTimeout(() => {
+ this.JsplumbService.setDropped(pipelineElementConfig.payload.dom, pipelineElementConfig.payload, true, false);
+ });
+ });
+ }
+ else if (ui.draggable.hasClass('stream')) {
+ this.checkTopicModel(pipelineElementConfig);
+ } else if (ui.draggable.hasClass('sepa')) {
+ setTimeout(() => {
+ setTimeout(() => {
+ this.JsplumbService.sepaDropped(pipelineElementConfig.payload.dom, pipelineElementConfig.payload, true, false);
+ });
+ });
+ //Droppable Actions
+ } else if (ui.draggable.hasClass('action')) {
+ setTimeout(() => {
+ setTimeout(() => {
+ this.JsplumbService.actionDropped(pipelineElementConfig.payload.dom, pipelineElementConfig.payload, true, false);
+ });
+ });
+ }
+ if (this.ShepherdService.isTourActive()) {
+ this.ShepherdService.trigger("drop-" +pipelineElementConfig.type);
+ }
+ }
+ }
+ this.JsplumbBridge.repaintEverything();
+ this.validatePipeline();
+ this.triggerPipelineCacheUpdate();
+ }
+
+ }); //End #assembly.droppable()
+ }
+
+ checkTopicModel(pipelineElementConfig: PipelineElementConfig) {
+ setTimeout(() => {
+ setTimeout(() => {
+ this.JsplumbService.streamDropped(pipelineElementConfig.payload.dom, pipelineElementConfig.payload, true, false);
+ });
+ });
+
+ var streamDescription = pipelineElementConfig.payload as SpDataStream;
+ if (streamDescription
+ .eventGrounding
+ .transportProtocols[0]
+ .topicDefinition["@class"] === "org.apache.streampipes.model.grounding.WildcardTopicDefinition") {
+ this.EditorDialogManager.showCustomizeStreamDialog(streamDescription);
+ }
+ }
+
+ handleDeleteOption(pipelineElement) {
+ this.JsplumbBridge.removeAllEndpoints(pipelineElement.payload.dom);
+ angular.forEach(this.rawPipelineModel, pe => {
+ if (pe.payload.dom == pipelineElement.payload.DOM) {
+ pe.settings.disabled = true;
+ }
+ });
+ if (this.rawPipelineModel.every(pe => pe.settings.disabled)) {
+ this.TransitionService.makePipelineAssemblyEmpty(true);
+ }
+ this.JsplumbBridge.repaintEverything();
+ this.RestApi.updateCachedPipeline(this.rawPipelineModel);
+ }
+
+ initPlumb() {
+
+ this.JsplumbService.prepareJsplumb();
+
+ this.JsplumbBridge.unbind("connection");
+
+ this.JsplumbBridge.bind("connectionMoved", (info, originalEvent) => {
+ var pe = this.objectProvider.findElement(info.newTargetEndpoint.elementId, this.rawPipelineModel);
+ var oldPe = this.objectProvider.findElement(info.originalTargetEndpoint.elementId, this.rawPipelineModel);
+ oldPe.payload.configured = false;
+ pe.payload.configured = false;
+ });
+
+ this.JsplumbBridge.bind("connectionDetached", (info, originalEvent) => {
+ var pe = this.objectProvider.findElement(info.targetEndpoint.elementId, this.rawPipelineModel);
+ pe.payload.configured = false;
+ pe.settings.openCustomize = true;
+ info.targetEndpoint.setType("empty");
+ this.validatePipeline();
+ });
+
+ this.JsplumbBridge.bind("connectionDrag", connection => {
+ this.JsplumbBridge.selectEndpoints().each(function (endpoint) {
+ if (endpoint.isTarget && endpoint.connections.length === 0) {
+ endpoint.setType("highlight");
+ }
+ });
+
+ });
+ this.JsplumbBridge.bind("connectionAborted", connection => {
+ this.JsplumbBridge.selectEndpoints().each(endpoint => {
+ if (endpoint.isTarget && endpoint.connections.length === 0) {
+ endpoint.setType("empty");
+ }
+ });
+ })
+
+ this.JsplumbBridge.bind("connection", (info, originalEvent) => {
+ var pe = this.objectProvider.findElement(info.target.id, this.rawPipelineModel);
+ if (pe.settings.openCustomize) {
+ this.currentPipelineModel = this.objectProvider.makePipeline(this.rawPipelineModel);
+ pe.settings.loadingStatus = true;
+ this.objectProvider.updatePipeline(this.currentPipelineModel)
+ .then(msg => {
+ let data = msg.data;
+ pe.settings.loadingStatus = false;
+ if (data.success) {
+ info.targetEndpoint.setType("token");
+ this.validatePipeline();
+ this.modifyPipeline(data.pipelineModifications);
+ var sourceEndpoint = this.JsplumbBridge.selectEndpoints({element: info.targetEndpoint.elementId});
+ if (this.PipelineEditorService.isFullyConnected(pe)) {
+ if ((pe.payload.staticProperties && pe.payload.staticProperties.length > 0) || this.isCustomOutput(pe)) {
+ this.EditorDialogManager.showCustomizeDialog($("#" +pe.payload.DOM), sourceEndpoint, pe.payload, false)
+ .then(() => {
+ this.JsplumbService.activateEndpoint(pe.payload.DOM, !pe.payload.uncompleted);
+ }, () => {
+ this.JsplumbService.activateEndpoint(pe.payload.DOM, !pe.payload.uncompleted);
+ });
+ } else {
+ //this.$rootScope.$broadcast("SepaElementConfigured", pe.payload.DOM);
+ pe.payload.configured = true;
+ }
+ }
+ } else {
+ this.JsplumbBridge.detach(info.connection);
+ this.EditorDialogManager.showMatchingErrorDialog(data);
+ }
+ });
+ }
+ });
+
+ window.onresize = (event) => {
+ this.JsplumbBridge.repaintEverything();
+ };
+
+ setTimeout(() => {
+ this.plumbReady = true;
+ }, 100);
+ }
+
+ modifyPipeline(pipelineModifications) {
+ for (var i = 0, modification; modification = pipelineModifications[i]; i++) {
+ var id = modification.domId;
+ if (id !== "undefined") {
+ var pe = this.objectProvider.findElement(id, this.rawPipelineModel);
+ pe.payload.staticProperties = modification.staticProperties;
+ pe.payload.outputStrategies = modification.outputStrategies;
+ pe.payload.inputStreams = modification.inputStreams;
+ }
+ }
+ }
+
+ isCustomOutput(pe) {
+ var custom = false;
+ angular.forEach(pe.payload.outputStrategies, strategy => {
+ if (strategy.type == 'org.apache.streampipes.model.output.CustomOutputStrategy') {
+ custom = true;
+ }
+ });
+ return custom;
+ }
+
+ triggerPipelineCacheUpdate() {
+ this.pipelineCacheRunning = true;
+ this.RestApi.updateCachedPipeline(this.rawPipelineModel).then(msg => {
+ this.pipelineCacheRunning = false;
+ this.pipelineCached = true;
+ });
+ }
+
+
+}
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/constants/editor.constants.ts b/ui/src/app/editor-v2/constants/editor.constants.ts
new file mode 100644
index 0000000..8b5fc20
--- /dev/null
+++ b/ui/src/app/editor-v2/constants/editor.constants.ts
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+export class EditorConstants {
+
+ static readonly DATA_STREAM_IDENTIFIER = "org.apache.streampipes.model.SpDataStream";
+ static readonly DATA_SET_IDENTIFIER = "org.apache.streampipes.model.SpDataSet";
+ static readonly DATA_PROCESSOR_IDENTIFIER = "org.apache.streampipes.model.graph.DataProcessorInvocation";
+ static readonly DATA_SINK_IDENTIFIER = "org.apache.streampipes.model.graph.DataSinkInvoation";
+}
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/editor.component.html b/ui/src/app/editor-v2/editor.component.html
index 4fd7ad4..23f9e22 100644
--- a/ui/src/app/editor-v2/editor.component.html
+++ b/ui/src/app/editor-v2/editor.component.html
@@ -34,7 +34,7 @@
style="background-color:#f6f6f6;padding:0px;border-bottom:1px solid #ffffff">
<pipeline-element-icon-stand [activeType]="activeType"
[currentElements]="currentElements"
- element-filter="ctrl.elementFilter">
+ element-filter="ctrl.elementFilter" *ngIf="allElementsLoaded">
</pipeline-element-icon-stand>
</div>
<pipeline-assembly [rawPipelineModel]="rawPipelineModel" [allElements]="allElements"
diff --git a/ui/src/app/editor-v2/editor.component.ts b/ui/src/app/editor-v2/editor.component.ts
index 4a8fb91..444ff62 100644
--- a/ui/src/app/editor-v2/editor.component.ts
+++ b/ui/src/app/editor-v2/editor.component.ts
@@ -21,11 +21,18 @@ import {EditorService} from "./services/editor.service";
import {
DataProcessorInvocation,
DataSinkInvocation,
- DataSourceDescription, SpDataSet,
+ DataSourceDescription,
SpDataStream
} from "../core-model/gen/streampipes-model";
import {PipelineElementService} from "../platform-services/apis/pipeline-element.service";
-import {PipelineElementHolder} from "./model/editor.model";
+import {
+ PipelineElementConfig,
+ PipelineElementHolder,
+ PipelineElementType,
+ PipelineElementUnion
+} from "./model/editor.model";
+import {EditorConstants} from "./constants/editor.constants";
+import {PipelineElementTypeUtils} from "./utils/editor.utils";
@Component({
selector: 'editor',
@@ -34,40 +41,38 @@ import {PipelineElementHolder} from "./model/editor.model";
})
export class EditorComponent implements OnInit {
- static readonly DATA_STREAM_IDENTIFIER = "org.apache.streampipes.model.SpDataStream";
- static readonly DATA_SET_IDENTIFIER = "org.apache.streampipes.model.SpDataSet";
- static readonly DATA_PROCESSOR_IDENTIFIER = "org.apache.streampipes.model.graph.DataProcessorInvocation";
- static readonly DATA_SINK_IDENTIFIER = "org.apache.streampipes.model.graph.DataSinkInvoation";
-
selectedIndex: number = 1;
- activeType: string = EditorComponent.DATA_STREAM_IDENTIFIER;
+ activeType: PipelineElementType = PipelineElementType.DataStream;
availableDataStreams: SpDataStream[] = [];
availableDataProcessors: DataProcessorInvocation[] = [];
availableDataSinks: DataSinkInvocation[] = [];
- allElements: PipelineElementHolder[] = [];
- currentElements: (SpDataStream | DataProcessorInvocation | DataSinkInvocation)[] = [];
+ allElements: PipelineElementUnion[] = [];
+ currentElements: Array<(SpDataStream | DataProcessorInvocation | DataSinkInvocation)> = [];
- rawPipelineModel: any = [];
+ rawPipelineModel: PipelineElementConfig[] = [];
currentModifiedPipelineId: any;
+ elementsLoaded = [false, false, false];
+ allElementsLoaded: boolean = false;
+
tabs = [
{
title: 'Data Sets',
- type: EditorComponent.DATA_SET_IDENTIFIER
+ type: PipelineElementType.DataSet
},
{
title: 'Data Streams',
- type: EditorComponent.DATA_STREAM_IDENTIFIER
+ type: PipelineElementType.DataStream
},
{
title: 'Data Processors',
- type: EditorComponent.DATA_PROCESSOR_IDENTIFIER
+ type: PipelineElementType.DataProcessor
},
{
title: 'Data Sinks',
- type: EditorComponent.DATA_SINK_IDENTIFIER
+ type: PipelineElementType.DataSink
}
];
@@ -78,23 +83,31 @@ export class EditorComponent implements OnInit {
ngOnInit() {
this.pipelineElementService.getDataProcessors().subscribe(processors => {
this.availableDataProcessors = processors;
- this.allElements[EditorComponent.DATA_PROCESSOR_IDENTIFIER] = this.availableDataProcessors;
+ this.allElements = this.allElements.concat(processors);
+ this.afterPipelineElementLoaded(0);
});
this.pipelineElementService.getDataSources().subscribe(sources => {
this.availableDataStreams = this.collectStreams(sources);
- this.allElements[EditorComponent.DATA_STREAM_IDENTIFIER] = this.availableDataStreams
- .filter(ds => ds["@class"] == EditorComponent.DATA_STREAM_IDENTIFIER );
- this.allElements[EditorComponent.DATA_SET_IDENTIFIER] = this.availableDataStreams
- .filter(ds => ds["@class"] == EditorComponent.DATA_SET_IDENTIFIER );
- this.currentElements = this.allElements[EditorComponent.DATA_STREAM_IDENTIFIER];
+ this.allElements = this.allElements.concat(this.availableDataStreams);
+ this.selectPipelineElements(1);
+ this.afterPipelineElementLoaded(1);
});
this.pipelineElementService.getDataSinks().subscribe(sinks => {
this.availableDataSinks = sinks;
- this.allElements[EditorComponent.DATA_SINK_IDENTIFIER] = this.availableDataSinks;
+ this.allElements = this.allElements.concat(this.availableDataSinks);
+ this.afterPipelineElementLoaded(2);
})
}
+ afterPipelineElementLoaded(index: number) {
+ this.elementsLoaded[index] = true;
+ if (this.elementsLoaded.every(e => e === true)) {
+ this.allElementsLoaded = true;
+ //this.makeDraggable();
+ }
+ }
+
private collectStreams(sources: Array<DataSourceDescription>) {
let streams: SpDataStream[] = [];
sources.forEach(source => {
@@ -108,24 +121,10 @@ export class EditorComponent implements OnInit {
selectPipelineElements(index : number) {
this.selectedIndex = index;
this.activeType = this.tabs[index].type;
- this.currentElements = this.allElements[this.activeType];
- this.makeDraggable();
+ this.currentElements = this.allElements
+ .filter(pe => pe instanceof PipelineElementTypeUtils.toType(this.activeType));
+ console.log(this.currentElements);
}
- makeDraggable() {
- console.log("makuing drabbg");
- (<any>$('.draggable-icon')).draggable({
- revert: 'invalid',
- helper: 'clone',
- stack: '.draggable-icon',
- start: function (el, ui) {
- ui.helper.appendTo('#content');
- $('#outerAssemblyArea').css('border', '3px dashed #39b54a');
- },
- stop: function (el, ui) {
- $('#outerAssemblyArea').css('border', '3px solid rgb(156, 156, 156)');
- }
- });
- };
}
diff --git a/ui/src/app/editor-v2/editor.module.ts b/ui/src/app/editor-v2/editor.module.ts
index 54b1bae..8d3a5b4 100644
--- a/ui/src/app/editor-v2/editor.module.ts
+++ b/ui/src/app/editor-v2/editor.module.ts
@@ -40,6 +40,9 @@ import {JsplumbConfigService} from "./services/jsplumb-config.service";
import {PipelineEditorService} from "./services/pipeline-editor.service";
import {PipelineValidationService} from "./services/pipeline-validation.service";
import {DragAndDropModule} from "angular-draggable-droppable";
+import {PipelineComponent} from "./components/pipeline/pipeline.component";
+import {DragDropModule} from "@angular/cdk/drag-drop";
+import {DragulaModule} from "ng2-dragula";
@NgModule({
@@ -53,13 +56,16 @@ import {DragAndDropModule} from "angular-draggable-droppable";
CustomMaterialModule,
FormsModule,
ConnectModule,
- DragAndDropModule
+ DragAndDropModule,
+ DragDropModule,
+ DragulaModule
],
declarations: [
EditorComponent,
PipelineAssemblyComponent,
PipelineElementIconStandComponent,
- PipelineElementComponent
+ PipelineElementComponent,
+ PipelineComponent
],
providers: [
EditorService,
diff --git a/ui/src/app/editor-v2/model/editor.model.ts b/ui/src/app/editor-v2/model/editor.model.ts
index 4662d0c..fb302f4 100644
--- a/ui/src/app/editor-v2/model/editor.model.ts
+++ b/ui/src/app/editor-v2/model/editor.model.ts
@@ -1,9 +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.
+ *
+ */
+
import {
DataProcessorInvocation,
- DataSinkInvocation,
+ DataSinkInvocation, SpDataSet,
SpDataStream
} from "../../core-model/gen/streampipes-model";
+import {EditorConstants} from "../constants/editor.constants";
+
+export type PipelineElementHolder = {
+ [key: string]: Array<PipelineElementUnion>;
+};
+
+export interface PipelineElementConfig {
+ type: string,
+ settings: {
+ openCustomize: boolean,
+ preview: boolean,
+ displaySettings: string,
+ connectable: string,
+ disabled: boolean,
+ loadingStatus: boolean
+ position: {
+ x: number,
+ y: number
+ }
+ },
+ payload: PipelineElementUnion
+}
+
+export enum PipelineElementType {
+ DataSet,
+ DataStream,
+ DataProcessor,
+ DataSink
+}
-export interface PipelineElementHolder {
- [key: string]: (SpDataStream | DataProcessorInvocation | DataSinkInvocation);
-}
\ No newline at end of file
+export type PipelineElementUnion = SpDataSet | SpDataStream | DataProcessorInvocation | DataSinkInvocation;
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/services/jsplumb-bridge.service.ts b/ui/src/app/editor-v2/services/jsplumb-bridge.service.ts
index 82631d1..3b64e88 100644
--- a/ui/src/app/editor-v2/services/jsplumb-bridge.service.ts
+++ b/ui/src/app/editor-v2/services/jsplumb-bridge.service.ts
@@ -39,6 +39,8 @@ export class JsplumbBridge {
}
setContainer(container) {
+ console.log("container");
+ console.log(container);
jsPlumb.setContainer(container);
}
diff --git a/ui/src/app/editor-v2/services/jsplumb.service.ts b/ui/src/app/editor-v2/services/jsplumb.service.ts
index 45a7277..943e70e 100644
--- a/ui/src/app/editor-v2/services/jsplumb.service.ts
+++ b/ui/src/app/editor-v2/services/jsplumb.service.ts
@@ -19,6 +19,8 @@
import {JsplumbConfigService} from "./jsplumb-config.service";
import {JsplumbBridge} from "./jsplumb-bridge.service";
import {Inject, Injectable} from "@angular/core";
+import {PipelineElementConfig, PipelineElementUnion} from "../model/editor.model";
+import {PipelineElementTypeUtils} from "../utils/editor.utils";
@Injectable()
export class JsplumbService {
@@ -88,7 +90,7 @@ export class JsplumbService {
var pipelineElementConfig = this.createNewPipelineElementConfigWithFixedCoordinates(pipelineElementDom, pipelineElement, false);
pipelineModel.push(pipelineElementConfig);
this.$timeout(() => {
- this.createAssemblyElement(pipelineElementConfig.payload.DOM, pipelineElementConfig.payload, pipelineElementDom);
+ this.createAssemblyElement(pipelineElementConfig.payload.dom, pipelineElementConfig.payload, pipelineElementDom);
});
}
@@ -136,23 +138,27 @@ export class JsplumbService {
return this.createNewPipelineElementConfig(json, coord, isPreview);
}
- createNewPipelineElementConfig(json, coordinates, isPreview) {
- var displaySettings = isPreview ? 'connectable-preview' : 'connectable-editor';
- var connectable = "connectable";
- var pipelineElementConfig = {
- type: json.type, settings: {
- openCustomize: !json.configured,
- preview: isPreview,
- displaySettings: displaySettings,
- connectable: connectable,
- position: {
- x: coordinates.x,
- y: coordinates.y
- }
- }, payload: Object.assign({}, json)
- };
- if (!pipelineElementConfig.payload.DOM) {
- pipelineElementConfig.payload.DOM = "jsplumb_" + this.idCounter + "_" + this.makeId(4);
+ createNewPipelineElementConfig(pipelineElement: PipelineElementUnion,
+ coordinates,
+ isPreview: boolean): PipelineElementConfig {
+ let displaySettings = isPreview ? 'connectable-preview' : 'connectable-editor';
+ let connectable = "connectable";
+ let pipelineElementConfig = {} as PipelineElementConfig;
+ pipelineElementConfig.type = PipelineElementTypeUtils
+ .toCssShortHand(PipelineElementTypeUtils.fromType(pipelineElement))
+ pipelineElementConfig.payload = pipelineElement;
+ pipelineElementConfig.settings = {connectable: connectable,
+ openCustomize: (pipelineElement as any).configured,
+ preview: isPreview,
+ disabled: false,
+ loadingStatus: false,
+ displaySettings: displaySettings,
+ position: {
+ x: coordinates.x,
+ y: coordinates.y
+ }};
+ if (!pipelineElementConfig.payload.dom) {
+ pipelineElementConfig.payload.dom = "jsplumb_" + this.idCounter + "_" + this.makeId(4);
this.idCounter++;
}
diff --git a/ui/src/app/editor-v2/services/pipeline-editor.service.ts b/ui/src/app/editor-v2/services/pipeline-editor.service.ts
index 6d142a3..2d2b3a3 100644
--- a/ui/src/app/editor-v2/services/pipeline-editor.service.ts
+++ b/ui/src/app/editor-v2/services/pipeline-editor.service.ts
@@ -17,14 +17,12 @@
*/
import {Injectable} from "@angular/core";
+import {JsplumbBridge} from "./jsplumb-bridge.service";
@Injectable()
export class PipelineEditorService {
- JsplumbBridge: any;
-
- constructor(JsplumbBridge) {
- this.JsplumbBridge = JsplumbBridge;
+ constructor(private JsplumbBridge: JsplumbBridge) {
}
getCoordinates(ui, currentZoomLevel) {
diff --git a/ui/src/app/editor-v2/utils/editor.utils.ts b/ui/src/app/editor-v2/utils/editor.utils.ts
new file mode 100644
index 0000000..cae04e5
--- /dev/null
+++ b/ui/src/app/editor-v2/utils/editor.utils.ts
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import {EditorConstants} from "../constants/editor.constants";
+import {PipelineElementType, PipelineElementUnion} from "../model/editor.model";
+import {
+ DataProcessorInvocation,
+ DataSinkInvocation,
+ SpDataSet,
+ SpDataStream
+} from "../../core-model/gen/streampipes-model";
+
+export class PipelineElementTypeUtils {
+
+ static toClassName(element: PipelineElementType): string {
+ if (element === PipelineElementType.DataSet) {
+ return EditorConstants.DATA_SET_IDENTIFIER;
+ } else if (element === PipelineElementType.DataStream) {
+ return EditorConstants.DATA_STREAM_IDENTIFIER;
+ } else if (element === PipelineElementType.DataProcessor) {
+ return EditorConstants.DATA_PROCESSOR_IDENTIFIER;
+ } else {
+ return EditorConstants.DATA_SINK_IDENTIFIER;
+ }
+ }
+
+ static fromClassName(className: string): PipelineElementType {
+ if (className === EditorConstants.DATA_SET_IDENTIFIER) {
+ return PipelineElementType.DataSet;
+ } else if (className === EditorConstants.DATA_STREAM_IDENTIFIER) {
+ return PipelineElementType.DataStream;
+ } else if (className === EditorConstants.DATA_PROCESSOR_IDENTIFIER) {
+ return PipelineElementType.DataProcessor;
+ } else {
+ return PipelineElementType.DataSink;
+ }
+ }
+
+ static toCssShortHand(elementType: PipelineElementType) {
+ if (PipelineElementType.DataStream === elementType) {
+ return "stream";
+ } else if (PipelineElementType.DataSet === elementType) {
+ return "set";
+ } else if (PipelineElementType.DataProcessor === elementType) {
+ return "sepa";
+ } else {
+ return "action";
+ }
+ }
+
+ static fromType(pipelineElement: PipelineElementUnion) {
+ if (pipelineElement instanceof SpDataSet) {
+ return PipelineElementType.DataSet;
+ } else if (pipelineElement instanceof SpDataStream) {
+ return PipelineElementType.DataStream;
+ } else if (pipelineElement instanceof DataProcessorInvocation) {
+ return PipelineElementType.DataProcessor;
+ } else {
+ return PipelineElementType.DataSink;
+ }
+ }
+
+ static toType(elementType: PipelineElementType) {
+ if (PipelineElementType.DataStream === elementType) {
+ return SpDataStream;
+ } else if (PipelineElementType.DataSet === elementType) {
+ return SpDataSet;
+ } else if (PipelineElementType.DataProcessor === elementType) {
+ return DataProcessorInvocation;
+ } else {
+ return DataSinkInvocation;
+ }
+ }
+
+ static toString(pipelineElement: PipelineElementType): string {
+ return PipelineElementType[pipelineElement];
+ }
+
+ static parse(pipelineElement: string): PipelineElementType {
+ return PipelineElementType[pipelineElement];
+ }
+}
\ No newline at end of file