This is an automated email from the ASF dual-hosted git repository. riemer pushed a commit to branch STREAMPIPES-494 in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git
commit e939a0e54d3624c8a4ec0cf7a3d0538d9da4f400 Author: Dominik Riemer <[email protected]> AuthorDate: Mon Jan 3 22:06:26 2022 +0100 [STREAMPIPES-499] Bump Jsplumb dependency and migrate code --- ui/package.json | 8 +- .../pipeline-assembly.component.html | 6 +- .../pipeline-assembly.component.ts | 20 +- .../pipeline-element-options.component.ts | 87 +++--- .../components/pipeline/pipeline.component.html | 74 ++--- .../components/pipeline/pipeline.component.ts | 198 +++++++------ .../app/editor/services/jsplumb-bridge.service.ts | 37 ++- .../app/editor/services/jsplumb-config.service.ts | 87 ++++-- .../app/editor/services/jsplumb-factory.service.ts | 113 ++++---- ui/src/app/editor/services/jsplumb.service.ts | 66 ++--- .../app/editor/services/object-provider.service.ts | 10 +- .../services/pipeline-positioning.service.ts | 305 +++++++++++---------- .../editor/services/pipeline-validation.service.ts | 26 +- ui/src/scss/main.scss | 2 +- 14 files changed, 521 insertions(+), 518 deletions(-) diff --git a/ui/package.json b/ui/package.json index 7da712e..da51b0d 100644 --- a/ui/package.json +++ b/ui/package.json @@ -39,7 +39,12 @@ "@fortawesome/fontawesome-free": "5.12.1", "@ngx-loading-bar/core": "5.1.2", "@ngx-loading-bar/http-client": "5.1.2", - "@panzoom/panzoom": "^4.3.2", + "@jsplumb/core": "^5.3.1", + "@jsplumb/browser-ui": "^5.3.1", + "@jsplumb/connector-bezier": "^5.3.1", + "@jsplumb/util": "^5.3.1", + "@jsplumb/common": "^5.3.1", + "@panzoom/panzoom": "^4.4.3", "@stomp/ng2-stompjs": "7.2.0", "@swimlane/ngx-charts": "16.0.0", "angular-datatables": "^12.0.2", @@ -65,7 +70,6 @@ "jquery": "2.1.3", "jquery-ui-dist": "1.12.1", "jshint": "^2.13.1", - "jsplumb": "^2.15.5", "jszip": "3.2.1", "konva": "3.2.4", "leaflet": "1.6.0", 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 3463fcb..e32b4d1 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 @@ -121,8 +121,7 @@ </div> </div> </div> - <div id="assembly" class="canvas" #assembly> - <pipeline #pipelineComponent + <pipeline class="canvas jtk-surface" id="assembly" #pipelineComponent [pipelineValid]="pipelineValid" [canvasId]="'assembly'" [rawPipelineModel]="rawPipelineModel" @@ -132,9 +131,8 @@ [pipelineCanvasMetadata]="pipelineCanvasMetadata" [pipelineCacheRunning]="pipelineCacheRunning" (pipelineCachedChanged)="pipelineCached=$event" - (pipelineCacheRunningChanged)="pipelineCacheRunning=$event"> + (pipelineCacheRunningChanged)="pipelineCacheRunning=$event" style="position:absolute;"> </pipeline> - </div> </div> </div> </div> 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 079d03f..9658e17 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,16 +16,7 @@ * */ -import { - Component, - ElementRef, - EventEmitter, - Input, - NgZone, - OnInit, - Output, - ViewChild, -} from '@angular/core'; +import { Component, ElementRef, EventEmitter, Input, NgZone, OnInit, Output, ViewChild, } from '@angular/core'; import { JsplumbBridge } from '../../services/jsplumb-bridge.service'; import { PipelinePositioningService } from '../../services/pipeline-positioning.service'; import { PipelineValidationService } from '../../services/pipeline-validation.service'; @@ -116,7 +107,6 @@ export class PipelineAssemblyComponent implements OnInit { } ngOnInit(): void { - this.JsplumbBridge = this.JsPlumbFactoryService.getJsplumbBridge(false); if (this.currentModifiedPipelineId) { this.displayPipelineById(); } else { @@ -141,23 +131,21 @@ export class PipelineAssemblyComponent implements OnInit { } ngAfterViewInit() { + this.JsplumbBridge = this.JsPlumbFactoryService.getJsplumbBridge(this.preview); const elem = document.getElementById('assembly'); this.panzoom = Panzoom(elem, { maxScale: 5, - excludeClass: 'jtk-draggable', + excludeClass: "sp-no-pan", canvas: true, contain: 'outside' }); } autoLayout() { - this.PipelinePositioningService.layoutGraph('#assembly', 'span[id^=\'jsplumb\']', 110, false); + this.PipelinePositioningService.layoutGraph('#assembly', 'div[id^=\'jsplumb\']', 110, false); this.JsplumbBridge.repaintEverything(); } - toggleSelectMode() { - } - zoomOut() { this.doZoom(true); } diff --git a/ui/src/app/editor/components/pipeline-element-options/pipeline-element-options.component.ts b/ui/src/app/editor/components/pipeline-element-options/pipeline-element-options.component.ts index 9de810a..1d131a0 100644 --- a/ui/src/app/editor/components/pipeline-element-options/pipeline-element-options.component.ts +++ b/ui/src/app/editor/components/pipeline-element-options/pipeline-element-options.component.ts @@ -16,27 +16,23 @@ * */ -import {JsplumbBridge} from "../../services/jsplumb-bridge.service"; -import {JsplumbService} from "../../services/jsplumb.service"; -import {PipelineValidationService} from "../../services/pipeline-validation.service"; -import {RestApi} from "../../../services/rest-api.service"; -import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from "@angular/core"; -import {PipelineElementRecommendationService} from "../../services/pipeline-element-recommendation.service"; -import {ObjectProvider} from "../../services/object-provider.service"; -import { - InvocablePipelineElementUnion, - PipelineElementConfig, - PipelineElementUnion -} from "../../model/editor.model"; -import {SpDataStream, WildcardTopicDefinition} from "../../../core-model/gen/streampipes-model"; -import {EditorService} from "../../services/editor.service"; -import {PanelType} from "../../../core-ui/dialog/base-dialog/base-dialog.model"; -import {DialogService} from "../../../core-ui/dialog/base-dialog/base-dialog.service"; -import {CompatibleElementsComponent} from "../../dialog/compatible-elements/compatible-elements.component"; -import {Tuple2} from "../../../core-model/base/Tuple2"; -import { cloneDeep } from "lodash"; -import {Observable, Subscription} from "rxjs"; -import {JsplumbFactoryService} from "../../services/jsplumb-factory.service"; +import { JsplumbBridge } from '../../services/jsplumb-bridge.service'; +import { JsplumbService } from '../../services/jsplumb.service'; +import { PipelineValidationService } from '../../services/pipeline-validation.service'; +import { RestApi } from '../../../services/rest-api.service'; +import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; +import { PipelineElementRecommendationService } from '../../services/pipeline-element-recommendation.service'; +import { ObjectProvider } from '../../services/object-provider.service'; +import { InvocablePipelineElementUnion, PipelineElementConfig, PipelineElementUnion } from '../../model/editor.model'; +import { SpDataStream, WildcardTopicDefinition } from '../../../core-model/gen/streampipes-model'; +import { EditorService } from '../../services/editor.service'; +import { PanelType } from '../../../core-ui/dialog/base-dialog/base-dialog.model'; +import { DialogService } from '../../../core-ui/dialog/base-dialog/base-dialog.service'; +import { CompatibleElementsComponent } from '../../dialog/compatible-elements/compatible-elements.component'; +import { Tuple2 } from '../../../core-model/base/Tuple2'; +import { cloneDeep } from 'lodash'; +import { Subscription } from 'rxjs'; +import { JsplumbFactoryService } from '../../services/jsplumb-factory.service'; @Component({ selector: 'pipeline-element-options', @@ -83,25 +79,25 @@ export class PipelineElementOptionsComponent implements OnInit, OnDestroy { JsplumbBridge: JsplumbBridge; - constructor(private ObjectProvider: ObjectProvider, - private PipelineElementRecommendationService: PipelineElementRecommendationService, - private DialogService: DialogService, - private EditorService: EditorService, - private JsplumbFactoryService: JsplumbFactoryService, - private JsplumbService: JsplumbService, - private PipelineValidationService: PipelineValidationService, - private RestApi: RestApi) { + constructor(private objectProvider: ObjectProvider, + private pipelineElementRecommendationService: PipelineElementRecommendationService, + private dialogService: DialogService, + private editorService: EditorService, + private jsplumbFactoryService: JsplumbFactoryService, + private jsplumbService: JsplumbService, + private pipelineValidationService: PipelineValidationService, + private restApi: RestApi) { this.recommendationsAvailable = false; this.possibleElements = []; this.recommendedElements = []; this.recommendationsShown = false; - this.JsplumbBridge = this.JsplumbFactoryService.getJsplumbBridge(false); + this.JsplumbBridge = this.jsplumbFactoryService.getJsplumbBridge(false); } ngOnInit() { - this.pipelineElementConfiguredObservable = this.EditorService.pipelineElementConfigured$.subscribe(pipelineElementDomId => { + this.pipelineElementConfiguredObservable = this.editorService.pipelineElementConfigured$.subscribe(pipelineElementDomId => { this.pipelineElement.settings.openCustomize = false; - this.RestApi.updateCachedPipeline(this.rawPipelineModel); + this.restApi.updateCachedPipeline(this.rawPipelineModel); if (pipelineElementDomId === this.pipelineElement.payload.dom) { this.initRecs(this.pipelineElement.payload.dom); } @@ -120,39 +116,39 @@ export class PipelineElementOptionsComponent implements OnInit, OnDestroy { } customizeElement(pipelineElement: PipelineElementConfig) { - let restrictedEditMode = ! (this.isRootElement()); - let customizeInfo = {a: restrictedEditMode, b: pipelineElement} as Tuple2<Boolean, PipelineElementConfig>; + const restrictedEditMode = ! (this.isRootElement()); + const customizeInfo = {a: restrictedEditMode, b: pipelineElement} as Tuple2<Boolean, PipelineElementConfig>; this.customize.emit(customizeInfo); } openHelpDialog() { - this.EditorService.openHelpDialog(this.pipelineElement.payload); + this.editorService.openHelpDialog(this.pipelineElement.payload); } openCustomizeStreamDialog() { - //this.EditorDialogManager.showCustomizeStreamDialog(this.pipelineElement.payload); + // this.EditorDialogManager.showCustomizeStreamDialog(this.pipelineElement.payload); } initRecs(pipelineElementDomId) { - let clonedModel: PipelineElementConfig[] = cloneDeep(this.rawPipelineModel); + const clonedModel: PipelineElementConfig[] = cloneDeep(this.rawPipelineModel); clonedModel.forEach(pe => { if (pe.payload.dom === pipelineElementDomId && (pe.type !== 'stream' && pe.type !== 'set')) { pe.settings.completed = false; (pe.payload as InvocablePipelineElementUnion).configured = false; } - }) - var currentPipeline = this.ObjectProvider.makePipeline(clonedModel); - this.EditorService.recommendPipelineElement(currentPipeline).subscribe((result) => { + }); + const currentPipeline = this.objectProvider.makePipeline(clonedModel); + this.editorService.recommendPipelineElement(currentPipeline).subscribe((result) => { if (result.success) { - this.possibleElements = cloneDeep(this.PipelineElementRecommendationService.collectPossibleElements(this.allElements, result.possibleElements)); - this.recommendedElements = cloneDeep(this.PipelineElementRecommendationService.populateRecommendedList(this.allElements, result.recommendedElements)); + this.possibleElements = cloneDeep(this.pipelineElementRecommendationService.collectPossibleElements(this.allElements, result.possibleElements)); + this.recommendedElements = cloneDeep(this.pipelineElementRecommendationService.populateRecommendedList(this.allElements, result.recommendedElements)); this.recommendationsAvailable = true; } }); } openPossibleElementsDialog() { - const dialogRef = this.DialogService.open(CompatibleElementsComponent,{ + const dialogRef = this.dialogService.open(CompatibleElementsComponent, { panelType: PanelType.SLIDE_IN_PANEL, title: 'Compatible Elements', data: { @@ -173,12 +169,11 @@ export class PipelineElementOptionsComponent implements OnInit, OnDestroy { } isRootElement() { - return this.JsplumbBridge.getConnections({source: this.pipelineElement.payload.dom}).length === 0; + return this.JsplumbBridge.getConnections({source: document.getElementById(this.pipelineElement.payload.dom)}).length === 0; } isConfigured() { - if (this.isDataSource) return true; - else { + if (this.isDataSource) { return true; } else { return (this.pipelineElement.payload as InvocablePipelineElementUnion).configured; } } diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.html b/ui/src/app/editor/components/pipeline/pipeline.component.html index d7cce7f..571ddc9 100644 --- a/ui/src/app/editor/components/pipeline/pipeline.component.html +++ b/ui/src/app/editor/components/pipeline/pipeline.component.html @@ -16,43 +16,45 @@ ~ --> -<div style="z-index: 1" [ngStyle]="{width: canvasWidth, height: canvasHeight}" #outerCanvas> - <span 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"> - <span 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-invalid {{pipelineElement.type === 'stream' ? 'pi-stream' : 'pi-processor'}}" - *ngIf="!pipelineElement.settings.completed"> - <i class="material-icons pipeline-element-configuration-invalid-icon"> +<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" class="sp-no-pan"> + <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-invalid {{pipelineElement.type === 'stream' ? 'pi-stream' : 'pi-processor'}}" + *ngIf="!pipelineElement.settings.completed"> + <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 *ngIf="!preview" (delete)="handleDeleteOption($event)" - (customize)="showCustomizeDialog($event)" - [currentMouseOverElement]="currentMouseOverElement" - [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(' ', '_')"> - </pipeline-element-options> - <pipeline-element-preview *ngIf="previewModeActive && (pipelinePreview.supportedPipelineElementDomIds.indexOf(pipelineElement.payload.dom) > -1)" - [previewId]="pipelinePreview.previewId" - [pipelineElementDomId]="pipelineElement.payload.dom"> + </i> + </div> + <pipeline-element [pipelineElement]="pipelineElement.payload" [preview]="preview"></pipeline-element> + </div> + <pipeline-element-options *ngIf="!preview" (delete)="handleDeleteOption($event)" + (customize)="showCustomizeDialog($event)" + [currentMouseOverElement]="currentMouseOverElement" + [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(' ', '_')"> + </pipeline-element-options> + <pipeline-element-preview + *ngIf="previewModeActive && (pipelinePreview.supportedPipelineElementDomIds.indexOf(pipelineElement.payload.dom) > -1)" + [previewId]="pipelinePreview.previewId" + [pipelineElementDomId]="pipelineElement.payload.dom"> - </pipeline-element-preview> - </span> + </pipeline-element-preview> </div> diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.ts b/ui/src/app/editor/components/pipeline/pipeline.component.ts index 08288fc..f353df0 100644 --- a/ui/src/app/editor/components/pipeline/pipeline.component.ts +++ b/ui/src/app/editor/components/pipeline/pipeline.component.ts @@ -16,17 +16,13 @@ * */ -import {PipelineValidationService} from "../../services/pipeline-validation.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, EventEmitter, Input, NgZone, OnDestroy, OnInit, Output} from "@angular/core"; -import { - InvocablePipelineElementUnion, - PipelineElementConfig, - PipelineElementUnion -} from "../../model/editor.model"; +import { PipelineValidationService } from '../../services/pipeline-validation.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, EventEmitter, Input, NgZone, OnDestroy, OnInit, Output } from '@angular/core'; +import { InvocablePipelineElementUnion, PipelineElementConfig, PipelineElementUnion } from '../../model/editor.model'; import { CustomOutputStrategy, DataProcessorInvocation, @@ -36,20 +32,22 @@ import { PipelinePreviewModel, SpDataSet, SpDataStream -} from "../../../core-model/gen/streampipes-model"; -import {ObjectProvider} from "../../services/object-provider.service"; -import {CustomizeComponent} from "../../dialog/customize/customize.component"; -import {PanelType} from "../../../core-ui/dialog/base-dialog/base-dialog.model"; -import {DialogService} from "../../../core-ui/dialog/base-dialog/base-dialog.service"; -import {EditorService} from "../../services/editor.service"; -import {MatchingResultMessage} from "../../../core-model/gen/streampipes-model-client"; -import {MatchingErrorComponent} from "../../dialog/matching-error/matching-error.component"; -import {Tuple2} from "../../../core-model/base/Tuple2"; -import {ConfirmDialogComponent} from "../../../core-ui/dialog/confirm-dialog/confirm-dialog.component"; -import {MatDialog} from "@angular/material/dialog"; -import {forkJoin} from "rxjs"; -import {JsplumbFactoryService} from "../../services/jsplumb-factory.service"; -import {PipelinePositioningService} from "../../services/pipeline-positioning.service"; +} from '../../../core-model/gen/streampipes-model'; +import { ObjectProvider } from '../../services/object-provider.service'; +import { CustomizeComponent } from '../../dialog/customize/customize.component'; +import { PanelType } from '../../../core-ui/dialog/base-dialog/base-dialog.model'; +import { DialogService } from '../../../core-ui/dialog/base-dialog/base-dialog.service'; +import { EditorService } from '../../services/editor.service'; +import { MatchingResultMessage } from '../../../core-model/gen/streampipes-model-client'; +import { MatchingErrorComponent } from '../../dialog/matching-error/matching-error.component'; +import { Tuple2 } from '../../../core-model/base/Tuple2'; +import { ConfirmDialogComponent } from '../../../core-ui/dialog/confirm-dialog/confirm-dialog.component'; +import { MatDialog } from '@angular/material/dialog'; +import { forkJoin } from 'rxjs'; +import { JsplumbFactoryService } from '../../services/jsplumb-factory.service'; +import { PipelinePositioningService } from '../../services/pipeline-positioning.service'; +import { EVENT_CONNECTION_ABORT, EVENT_CONNECTION_DRAG } from '@jsplumb/browser-ui'; +import { EVENT_CONNECTION, EVENT_CONNECTION_DETACHED, EVENT_CONNECTION_MOVED } from '@jsplumb/core'; @Component({ selector: 'pipeline', @@ -88,21 +86,18 @@ export class PipelineComponent implements OnInit, OnDestroy { @Output() pipelineCacheRunningChanged: EventEmitter<boolean> = new EventEmitter<boolean>(); - availablePipelineElementCache: PipelineElementUnion[]; - plumbReady: boolean; currentMouseOverElement: string; currentPipelineModel: Pipeline; idCounter: any; currentZoomLevel: any; - TransitionService: any; - canvasWidth: string = "100%"; - canvasHeight: string = "100%"; + canvasWidth = '100%'; + canvasHeight = '100%'; JsplumbBridge: JsplumbBridge; - previewModeActive: boolean = false; + previewModeActive = false; pipelinePreview: PipelinePreviewModel; constructor(private JsplumbService: JsplumbService, @@ -115,9 +110,9 @@ export class PipelineComponent implements OnInit, OnDestroy { private PipelineValidationService: PipelineValidationService, private dialogService: DialogService, private dialog: MatDialog, - private ngZone: NgZone,) { + private ngZone: NgZone, ) { this.plumbReady = false; - this.currentMouseOverElement = ""; + this.currentMouseOverElement = ''; this.currentPipelineModel = new Pipeline(); this.idCounter = 0; @@ -126,14 +121,10 @@ export class PipelineComponent implements OnInit, OnDestroy { ngOnInit() { this.JsplumbBridge = this.JsplumbFactoryService.getJsplumbBridge(this.preview); - this.JsplumbBridge.setContainer(this.canvasId); this.initAssembly(); this.initPlumb(); } - ngAfterViewInit() { - } - validatePipeline() { setTimeout(() => { this.ngZone.run(() => { @@ -145,7 +136,7 @@ export class PipelineComponent implements OnInit, OnDestroy { ngOnDestroy() { this.deletePipelineElementPreview(false); - this.JsplumbBridge.deleteEveryEndpoint(); + this.JsplumbFactoryService.destroy(this.preview); this.plumbReady = false; } @@ -155,23 +146,23 @@ export class PipelineComponent implements OnInit, OnDestroy { updateOptionsClick(elementId) { if (this.currentMouseOverElement == elementId) { - this.currentMouseOverElement = ""; + 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; " + 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 + " " + return currentPipelineElement.type + ' ' + (currentPipelineElement.settings.openCustomize ? '' : '') + + currentPipelineElement.settings.connectable + ' ' + currentPipelineElement.settings.displaySettings; } @@ -191,9 +182,9 @@ export class PipelineComponent implements OnInit, OnDestroy { this.dialog.open(ConfirmDialogComponent, { width: '500px', data: { - "title": "Currently, it is not possible to mix data streams and data sets in a single pipeline.", - "confirmAndCancel": false, - "okTitle": "Ok", + 'title': 'Currently, it is not possible to mix data streams and data sets in a single pipeline.', + 'confirmAndCancel': false, + 'okTitle': 'Ok', }, }); } @@ -202,17 +193,16 @@ export class PipelineComponent implements OnInit, OnDestroy { return this.allElements.find(a => a.elementId === elementId); } - initAssembly() { ($('#assembly') as any).droppable({ - tolerance: "fit", + tolerance: 'fit', drop: (element, ui) => { - let pipelineElementId = ui.draggable.data("pe"); - let pipelineElement: PipelineElementUnion = this.findPipelineElementByElementId(pipelineElementId); + const pipelineElementId = ui.draggable.data('pe'); + const pipelineElement: PipelineElementUnion = this.findPipelineElementByElementId(pipelineElementId); if (ui.draggable.hasClass('draggable-icon')) { this.EditorService.makePipelineAssemblyEmpty(false); - let newElementId = pipelineElement.elementId + ":" + this.JsplumbService.makeId(5); - let pipelineElementConfig = this.JsplumbService.createNewPipelineElementConfig(pipelineElement, + const newElementId = pipelineElement.elementId + ':' + this.JsplumbService.makeId(5); + const pipelineElementConfig = this.JsplumbService.createNewPipelineElementConfig(pipelineElement, this.PipelineEditorService.getCoordinates(ui, this.currentZoomLevel), false, false, @@ -242,7 +232,7 @@ export class PipelineComponent implements OnInit, OnDestroy { }, 10); } if (this.ShepherdService.isTourActive()) { - this.ShepherdService.trigger("drop-" + pipelineElementConfig.type); + this.ShepherdService.trigger('drop-' + pipelineElementConfig.type); } } } @@ -251,7 +241,7 @@ export class PipelineComponent implements OnInit, OnDestroy { this.triggerPipelineCacheUpdate(); } - }); //End #assembly.droppable() + }); // End #assembly.droppable() } checkTopicModel(pipelineElementConfig: PipelineElementConfig) { @@ -262,12 +252,12 @@ export class PipelineComponent implements OnInit, OnDestroy { false); }, 10); - var streamDescription = pipelineElementConfig.payload as SpDataStream; + const streamDescription = pipelineElementConfig.payload as SpDataStream; if (streamDescription .eventGrounding .transportProtocols[0] - .topicDefinition["@class"] === "org.apache.streampipes.model.grounding.WildcardTopicDefinition") { - //this.EditorDialogManager.showCustomizeStreamDialog(streamDescription); + .topicDefinition['@class'] === 'org.apache.streampipes.model.grounding.WildcardTopicDefinition') { + // this.EditorDialogManager.showCustomizeStreamDialog(streamDescription); } } @@ -288,54 +278,56 @@ export class PipelineComponent implements OnInit, OnDestroy { initPlumb() { - //this.JsplumbService.prepareJsplumb(); + // this.JsplumbService.prepareJsplumb(); - this.JsplumbBridge.unbind("connection"); + this.JsplumbBridge.unbind(EVENT_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); + this.JsplumbBridge.bind(EVENT_CONNECTION_MOVED, (info) => { + const pe = this.ObjectProvider.findElement(info.newTargetEndpoint.elementId, this.rawPipelineModel); + const oldPe = this.ObjectProvider.findElement(info.originalTargetEndpoint.elementId, this.rawPipelineModel); (oldPe.payload as InvocablePipelineElementUnion).configured = false; (pe.payload as InvocablePipelineElementUnion).configured = false; }); - this.JsplumbBridge.bind("connectionDetached", (info, originalEvent) => { - var pe = this.ObjectProvider.findElement(info.targetEndpoint.elementId, this.rawPipelineModel); + this.JsplumbBridge.bind(EVENT_CONNECTION_DETACHED, (info) => { + const pe = this.ObjectProvider.findElement(info.targetEndpoint.elementId, this.rawPipelineModel); (pe.payload as InvocablePipelineElementUnion).configured = false; pe.settings.openCustomize = true; - info.targetEndpoint.setType("empty"); + info.targetEndpoint.setType('empty'); + this.JsplumbBridge.repaintEverything(); this.validatePipeline(); }); - this.JsplumbBridge.bind("connectionDrag", connection => { - this.JsplumbBridge.selectEndpoints().each(function (endpoint) { + this.JsplumbBridge.bind(EVENT_CONNECTION_DRAG, () => { + this.JsplumbBridge.selectEndpoints().each(endpoint => { if (endpoint.isTarget && endpoint.connections.length === 0) { - endpoint.setType("highlight"); + endpoint.setType('highlight'); } }); - + this.JsplumbBridge.repaintEverything(); }); - this.JsplumbBridge.bind("connectionAborted", connection => { + this.JsplumbBridge.bind(EVENT_CONNECTION_ABORT, () => { this.JsplumbBridge.selectEndpoints().each(endpoint => { if (endpoint.isTarget && endpoint.connections.length === 0) { - endpoint.setType("empty"); + endpoint.setType('empty'); } }); - }) + this.JsplumbBridge.repaintEverything(); + }); - this.JsplumbBridge.bind("connection", (info, originalEvent) => { - var pe = this.ObjectProvider.findElement(info.target.id, this.rawPipelineModel); + this.JsplumbBridge.bind(EVENT_CONNECTION, (info) => { + const 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) .subscribe(pipelineModificationMessage => { pe.settings.loadingStatus = false; - info.targetEndpoint.setType("token"); + info.targetEndpoint.setType('token'); this.validatePipeline(); this.modifyPipeline(pipelineModificationMessage.pipelineModifications); if (this.JsplumbService.isFullyConnected(pe, this.preview)) { - let payload = pe.payload as InvocablePipelineElementUnion; + const payload = pe.payload as InvocablePipelineElementUnion; if ((payload.staticProperties && payload.staticProperties.length > 0) || this.isCustomOutput(pe)) { this.showCustomizeDialog({a: false, b: pe}); } else { @@ -348,7 +340,7 @@ export class PipelineComponent implements OnInit, OnDestroy { pe.settings.loadingStatus = false; this.JsplumbBridge.detach(info.connection); if (Array.isArray(status.error)) { - let matchingResultMessage = (status.error as any[]).map(e => MatchingResultMessage.fromData(e as MatchingResultMessage)); + const matchingResultMessage = (status.error as any[]).map(e => MatchingResultMessage.fromData(e as MatchingResultMessage)); this.showMatchingErrorDialog(matchingResultMessage); } else { this.showErrorDialog(status.error.title, status.error.description); @@ -357,7 +349,7 @@ export class PipelineComponent implements OnInit, OnDestroy { } }); - window.onresize = (event) => { + window.onresize = () => { this.JsplumbBridge.repaintEverything(); }; @@ -369,9 +361,9 @@ export class PipelineComponent implements OnInit, OnDestroy { modifyPipeline(pipelineModifications) { if (pipelineModifications) { pipelineModifications.forEach(modification => { - var id = modification.domId; - if (id !== "undefined") { - var pe = this.ObjectProvider.findElement(id, this.rawPipelineModel); + const id = modification.domId; + if (id !== 'undefined') { + const pe = this.ObjectProvider.findElement(id, this.rawPipelineModel); (pe.payload as InvocablePipelineElementUnion).staticProperties = modification.staticProperties; (pe.payload as DataProcessorInvocation).outputStrategies = modification.outputStrategies; (pe.payload as InvocablePipelineElementUnion).inputStreams = modification.inputStreams; @@ -381,7 +373,7 @@ export class PipelineComponent implements OnInit, OnDestroy { } isCustomOutput(pe) { - var custom = false; + let custom = false; pe.payload.outputStrategies.forEach(strategy => { if (strategy instanceof CustomOutputStrategy) { custom = true; @@ -395,11 +387,11 @@ export class PipelineComponent implements OnInit, OnDestroy { this.pipelineCacheRunning = true; this.pipelineCacheRunningChanged.emit(this.pipelineCacheRunning); this.PipelinePositioningService.collectPipelineElementPositions(this.pipelineCanvasMetadata, this.rawPipelineModel); - let updateCachedPipeline = this.EditorService.updateCachedPipeline(this.rawPipelineModel); - let updateCachedCanvasMetadata = this.EditorService.updateCachedCanvasMetadata(this.pipelineCanvasMetadata); - forkJoin([updateCachedPipeline, updateCachedCanvasMetadata]).subscribe(msg => { + 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.pipelineCacheRunningChanged.emit(this.pipelineCacheRunning); this.pipelineCached = true; this.pipelineCachedChanged.emit(this.pipelineCached); }); @@ -410,10 +402,10 @@ export class PipelineComponent implements OnInit, OnDestroy { this.dialog.open(ConfirmDialogComponent, { width: '500px', data: { - "title": title, - "subtitle": description, - "okTitle": "Ok", - "confirmAndCancel": false + 'title': title, + 'subtitle': description, + 'okTitle': 'Ok', + 'confirmAndCancel': false }, }); } @@ -421,9 +413,9 @@ export class PipelineComponent implements OnInit, OnDestroy { showMatchingErrorDialog(matchingResultMessage: MatchingResultMessage[]) { this.dialogService.open(MatchingErrorComponent, { panelType: PanelType.STANDARD_PANEL, - title: "Invalid Connection", + title: 'Invalid Connection', data: { - "matchingResultMessage": matchingResultMessage + 'matchingResultMessage': matchingResultMessage } }); } @@ -431,11 +423,11 @@ export class PipelineComponent implements OnInit, OnDestroy { showCustomizeDialog(pipelineElementInfo: Tuple2<Boolean, PipelineElementConfig>) { const dialogRef = this.dialogService.open(CustomizeComponent, { panelType: PanelType.SLIDE_IN_PANEL, - title: "Customize " + pipelineElementInfo.b.payload.name, - width: "50vw", + title: 'Customize ' + pipelineElementInfo.b.payload.name, + width: '50vw', data: { - "pipelineElement": pipelineElementInfo.b, - "restrictedEditMode": pipelineElementInfo.a + 'pipelineElement': pipelineElementInfo.b, + 'restrictedEditMode': pipelineElementInfo.a } }); @@ -444,9 +436,9 @@ export class PipelineComponent implements OnInit, OnDestroy { pipelineElementInfo.b.settings.openCustomize = false; (pipelineElementInfo.b.payload as InvocablePipelineElementUnion).configured = true; if (!(pipelineElementInfo.b.payload instanceof DataSinkInvocation)) { - this.JsplumbBridge.activateEndpoint("out-" + pipelineElementInfo.b.payload.dom, pipelineElementInfo.b.settings.completed); + this.JsplumbBridge.activateEndpoint('out-' + pipelineElementInfo.b.payload.dom, pipelineElementInfo.b.settings.completed); } - this.JsplumbBridge.getSourceEndpoint(pipelineElementInfo.b.payload.dom).setType("token"); + this.JsplumbBridge.getSourceEndpoint(pipelineElementInfo.b.payload.dom).toggleType('token'); this.triggerPipelineCacheUpdate(); this.announceConfiguredElement(pipelineElementInfo.b); if (this.previewModeActive) { @@ -463,7 +455,7 @@ export class PipelineComponent implements OnInit, OnDestroy { initiatePipelineElementPreview() { if (!this.previewModeActive) { - let pipeline = this.ObjectProvider.makePipeline(this.rawPipelineModel); + const pipeline = this.ObjectProvider.makePipeline(this.rawPipelineModel); this.EditorService.initiatePipelinePreview(pipeline).subscribe(response => { this.pipelinePreview = response; this.previewModeActive = true; @@ -475,7 +467,7 @@ export class PipelineComponent implements OnInit, OnDestroy { deletePipelineElementPreview(resume: boolean) { if (this.previewModeActive) { - this.EditorService.deletePipelinePreviewRequest(this.pipelinePreview.previewId).subscribe(response => { + this.EditorService.deletePipelinePreviewRequest(this.pipelinePreview.previewId).subscribe(() => { this.previewModeActive = false; if (resume) { this.initiatePipelineElementPreview(); diff --git a/ui/src/app/editor/services/jsplumb-bridge.service.ts b/ui/src/app/editor/services/jsplumb-bridge.service.ts index ca94753..6a3eb77 100644 --- a/ui/src/app/editor/services/jsplumb-bridge.service.ts +++ b/ui/src/app/editor/services/jsplumb-bridge.service.ts @@ -16,16 +16,17 @@ * */ -import {jsPlumbInstance} from 'jsplumb' +import { BrowserJsPlumbInstance } from '@jsplumb/browser-ui'; +import { SelectOptions } from "@jsplumb/core"; export class JsplumbBridge { - constructor(private jsPlumbInstance: jsPlumbInstance) { + constructor(private jsPlumbInstance: BrowserJsPlumbInstance) { } activateEndpoint(endpointId: string, endpointEnabled: boolean) { let endpoint = this.getEndpointById(endpointId); - endpoint.setEnabled(endpointEnabled); + endpoint.enabled = endpointEnabled; } activateEndpointWithType(endpointId: string, endpointEnabled: boolean, endpointType: string) { @@ -48,15 +49,17 @@ export class JsplumbBridge { } repaintEverything() { - this.jsPlumbInstance.repaintEverything(true); + this.jsPlumbInstance.repaintEverything(); } deleteEveryEndpoint() { - this.jsPlumbInstance.deleteEveryEndpoint(); + // TODO + //this.jsPlumbInstance.destroy(); + //this.jsPlumbInstance.deleteEveryEndpoint(); } setContainer(container) { - this.jsPlumbInstance.setContainer(container); + this.jsPlumbInstance.setContainer(document.getElementById(container)); } unbind(element) { @@ -94,19 +97,21 @@ export class JsplumbBridge { getEndpointCount(id) { // @ts-ignore - return this.jsPlumbInstance.selectEndpoints({element: id}).length; + return this.jsPlumbInstance.selectEndpoints({element: document.getElementById(id)}).length; } detach(connection) { this.jsPlumbInstance.deleteConnection(connection); } - getConnections(filter) { - return this.jsPlumbInstance.getConnections(filter, {}); + getConnections(filter: SelectOptions<Element>) { + return this.jsPlumbInstance.getConnections(filter); } - addEndpoint(element, options) { - return this.jsPlumbInstance.addEndpoint(element, options); + addEndpoint(pipelineElementDomId: string, + options: any) { + options.cssClass = "sp-no-pan"; + return this.jsPlumbInstance.addEndpoint(document.getElementById(pipelineElementDomId), options); } connect(connection) { @@ -114,17 +119,13 @@ export class JsplumbBridge { } removeAllEndpoints(element) { - this.jsPlumbInstance.removeAllEndpoints(element); + this.jsPlumbInstance.removeAllEndpoints(document.getElementById(element)); } registerEndpointTypes(typeInfo) { this.jsPlumbInstance.registerEndpointTypes(typeInfo); } - draggable(element, option) { - this.jsPlumbInstance.draggable(element, option); - } - // TODO: Overloading Functions? setSuspendDrawing(bool1, bool2?) { if (bool2 === undefined) { @@ -135,12 +136,10 @@ export class JsplumbBridge { } getAllConnections() { - return this.jsPlumbInstance.getAllConnections(); + return this.jsPlumbInstance.getConnections(); } reset() { this.jsPlumbInstance.reset(); } } - -//JsplumbBridge.$inject = []; diff --git a/ui/src/app/editor/services/jsplumb-config.service.ts b/ui/src/app/editor/services/jsplumb-config.service.ts index 44de61c..2ddacd9 100644 --- a/ui/src/app/editor/services/jsplumb-config.service.ts +++ b/ui/src/app/editor/services/jsplumb-config.service.ts @@ -16,8 +16,10 @@ * */ -import {Injectable} from "@angular/core"; -import {JsplumbSettings} from "../model/jsplumb.model"; +import { Injectable } from "@angular/core"; +import { JsplumbSettings } from "../model/jsplumb.model"; +import { BezierConnector } from "@jsplumb/connector-bezier"; +import { EndpointTypeDescriptor } from "@jsplumb/core"; @Injectable() export class JsplumbConfigService { @@ -33,6 +35,37 @@ export class JsplumbConfigService { return this.makeConfig(this.makeSettings(6, 2, 15, 15, 1, 40)); } + getEndpointTypeConfig(): Record<string, EndpointTypeDescriptor> { + return { + "empty": { + paintStyle: { + fill: "white", + stroke: "#9E9E9E", + strokeWidth: 2, + } + }, + "token": { + paintStyle: { + fill: "#BDBDBD", + stroke: "#9E9E9E", + strokeWidth: 2 + }, + hoverPaintStyle: { + fill: "#BDBDBD", + stroke: "#4CAF50", + strokeWidth: 4, + } + }, + "highlight": { + paintStyle: { + fill: "white", + stroke: "#4CAF50", + strokeWidth: 4 + } + } + } + } + makeConfig(settings) { let config = {} as any; config.streamEndpointOptions = this.makeStreamEndpointOptions(settings); @@ -59,45 +92,29 @@ export class JsplumbConfigService { makeStreamEndpointOptions(settings: JsplumbSettings) { return { - endpoint: ["Dot", {radius: settings.dotRadius}], + endpoint: {type: "Dot", options: {radius: settings.dotRadius}}, connectorStyle: {stroke: "#BDBDBD", outlineStroke: "#BDBDBD", strokeWidth: settings.lineWidth}, - connector: ["Bezier", {curviness: settings.curviness}], - isSource: true, + connector: {type: BezierConnector.type, options: {curviness: settings.curviness}}, + source: true, + type: "token", maxConnections: -1, anchor: "Right", - type: "token", - connectorOverlays: [ - ["Arrow", { - width: settings.arrowWidth, length: settings.arrowLength, location: 0.5, id: "arrow", paintStyle: { - fillStyle: "#BDBDBD", - stroke: "#9E9E9E", - strokeWidth: settings.arrowLineWidth - } - }], - ] + connectorOverlays: this.defaultConnectorOverlay(settings) } } makeSepaEndpointOptions(settings) { return { - endpoint: ["Dot", {radius: settings.dotRadius}], + endpoint: {type: "Dot", options: {radius: settings.dotRadius}}, connectorStyle: { stroke: "#BDBDBD", outlineStroke: "#9E9E9E", strokeWidth: settings.lineWidth }, - connector: ["Bezier", {curviness: settings.curviness}], - isSource: true, + connector: {type: BezierConnector.type, options: {curviness: settings.curviness}}, + source: true, maxConnections: -1, anchor: "Right", type: "empty", - connectorOverlays: [ - ["Arrow", { - width: settings.arrowWidth, length: settings.arrowLength, location: 0.5, id: "arrow", paintStyle: { - fill: "#BDBDBD", - stroke: "#9E9E9E", - strokeWidth: settings.arrowLineWidth - } - }], - ], + connectorOverlays: this.defaultConnectorOverlay(settings), parameters: { endpointType: "output" } @@ -106,11 +123,23 @@ export class JsplumbConfigService { makeLeftTargetPointOptions(settings) { return { - endpoint: ["Dot", {radius: settings.dotRadius}], + endpoint: {type: "Dot", options: {radius: settings.dotRadius}}, type: "empty", anchor: "Left", - isTarget: true + target: true } } + defaultConnectorOverlay(settings) { + return [{ + type: "Arrow", options: { + width: settings.arrowWidth, length: settings.arrowLength, location: 0.5, id: "arrow", paintStyle: { + fillStyle: "#BDBDBD", + stroke: "#9E9E9E", + strokeWidth: settings.arrowLineWidth + } + } + }]; + } + } diff --git a/ui/src/app/editor/services/jsplumb-factory.service.ts b/ui/src/app/editor/services/jsplumb-factory.service.ts index ff16482..6671a82 100644 --- a/ui/src/app/editor/services/jsplumb-factory.service.ts +++ b/ui/src/app/editor/services/jsplumb-factory.service.ts @@ -16,70 +16,75 @@ * */ -import {jsPlumb, jsPlumbInstance} from "jsplumb"; -import {JsplumbBridge} from "./jsplumb-bridge.service"; -import {Injectable} from "@angular/core"; +import { JsPlumbInstance } from "@jsplumb/core"; +import { JsplumbBridge } from "./jsplumb-bridge.service"; +import { Injectable } from "@angular/core"; +import { BrowserJsPlumbInstance, ContainmentType, newInstance } from "@jsplumb/browser-ui"; +import { PipelineElementDraggedService } from "./pipeline-element-dragged.service"; +import { JsplumbConfigService } from "./jsplumb-config.service"; @Injectable() export class JsplumbFactoryService { - pipelineEditorInstance: jsPlumbInstance; - pipelinePreviewInstance: jsPlumbInstance; + pipelineEditorInstance: BrowserJsPlumbInstance; + pipelinePreviewInstance: BrowserJsPlumbInstance; - pipelineEditorBridge: JsplumbBridge; - pipelinePreviewBridge: JsplumbBridge; + pipelineEditorBridge: JsplumbBridge; + pipelinePreviewBridge: JsplumbBridge; - constructor() { - this.pipelineEditorInstance = this.makePipelineEditorInstance(); - this.pipelinePreviewInstance = this.makePipelinePreviewInstance(); + constructor(private pipelineElementDraggedService: PipelineElementDraggedService, + private jsplumbConfigService: JsplumbConfigService) { + } - this.pipelineEditorBridge = new JsplumbBridge(this.pipelineEditorInstance); - this.pipelinePreviewBridge = new JsplumbBridge(this.pipelinePreviewInstance); - - this.prepareJsplumb(this.pipelineEditorInstance); - this.prepareJsplumb(this.pipelinePreviewInstance); - } + 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; + } + } - getJsplumbBridge(previewConfig: boolean): JsplumbBridge { - return previewConfig ? this.pipelineEditorBridge : this.pipelinePreviewBridge; - } + makePipelineEditorInstance(): BrowserJsPlumbInstance { + return newInstance({ + container: document.getElementById("assembly"), dragOptions: { + containment: ContainmentType.parent, + cursor: 'pointer', + zIndex: 2000, + drag: params => { + this.pipelineElementDraggedService.notify({x: params.pos.x, y: params.pos.y}); + } + }, + }); + } - makePipelineEditorInstance(): jsPlumbInstance { - return jsPlumb.getInstance(); - } + makePipelinePreviewInstance(): BrowserJsPlumbInstance { + return newInstance({ + container: document.getElementById("assembly-preview"), + elementsDraggable: false + }); + } - makePipelinePreviewInstance(): jsPlumbInstance { - return jsPlumb.getInstance(); - } + prepareJsplumb(jsplumbInstance: JsPlumbInstance) { + jsplumbInstance.registerEndpointTypes(this.jsplumbConfigService.getEndpointTypeConfig()); + } - prepareJsplumb(jsplumbInstance: jsPlumbInstance) { - jsplumbInstance.registerEndpointTypes({ - "empty": { - paintStyle: { - fill: "white", - stroke: "#9E9E9E", - strokeWidth: 2, - } - }, - "token": { - paintStyle: { - fill: "#BDBDBD", - stroke: "#9E9E9E", - strokeWidth: 2 - }, - hoverPaintStyle: { - fill: "#BDBDBD", - stroke: "#4CAF50", - strokeWidth: 4, - } - }, - "highlight": { - paintStyle: { - fill: "white", - stroke: "#4CAF50", - strokeWidth: 4 + destroy(preview: boolean) { + if (preview) { + this.pipelinePreviewInstance.destroy(); + this.pipelinePreviewBridge = undefined; + } else { + this.pipelineEditorInstance.destroy(); + this.pipelineEditorBridge = undefined; } - } - }); - } + } } diff --git a/ui/src/app/editor/services/jsplumb.service.ts b/ui/src/app/editor/services/jsplumb.service.ts index 4a30738..7ac0e1c 100644 --- a/ui/src/app/editor/services/jsplumb.service.ts +++ b/ui/src/app/editor/services/jsplumb.service.ts @@ -16,15 +16,11 @@ * */ -import {JsplumbConfigService} from "./jsplumb-config.service"; -import {JsplumbBridge} from "./jsplumb-bridge.service"; -import {Injectable} from "@angular/core"; -import { - InvocablePipelineElementUnion, - PipelineElementConfig, - PipelineElementUnion -} from "../model/editor.model"; -import {PipelineElementTypeUtils} from "../utils/editor.utils"; +import { JsplumbConfigService } from "./jsplumb-config.service"; +import { JsplumbBridge } from "./jsplumb-bridge.service"; +import { Injectable } from "@angular/core"; +import { InvocablePipelineElementUnion, PipelineElementConfig, PipelineElementUnion } from "../model/editor.model"; +import { PipelineElementTypeUtils } from "../utils/editor.utils"; import { DataProcessorInvocation, DataSinkInvocation, @@ -33,9 +29,8 @@ import { SpDataStream, SpDataStreamUnion } from "../../core-model/gen/streampipes-model"; -import {PipelineElementDraggedService} from "./pipeline-element-dragged.service"; -import {JsplumbEndpointService} from "./jsplumb-endpoint.service"; -import {JsplumbFactoryService} from "./jsplumb-factory.service"; +import { JsplumbEndpointService } from "./jsplumb-endpoint.service"; +import { JsplumbFactoryService } from "./jsplumb-factory.service"; import { EditorService } from './editor.service'; @Injectable() @@ -46,8 +41,7 @@ export class JsplumbService { constructor(private JsplumbConfigService: JsplumbConfigService, private JsplumbFactory: JsplumbFactoryService, private jsplumbEndpointService: JsplumbEndpointService, - private editorService: EditorService, - private pipelineElementDraggedService: PipelineElementDraggedService) { + private editorService: EditorService) { } isFullyConnected(pipelineElementConfig: PipelineElementConfig, @@ -55,7 +49,7 @@ export class JsplumbService { let jsplumbBridge = this.JsplumbFactory.getJsplumbBridge(previewConfig); let payload = pipelineElementConfig.payload as InvocablePipelineElementUnion; return payload.inputStreams == null || - jsplumbBridge.getConnections({target: $("#" +payload.dom)}).length == payload.inputStreams.length; + jsplumbBridge.getConnections({target: document.getElementById(payload.dom)}).length == payload.inputStreams.length; } makeRawPipeline(pipelineModel: Pipeline, @@ -107,7 +101,7 @@ export class JsplumbService { createElement(pipelineModel: PipelineElementConfig[], pipelineElement: InvocablePipelineElementUnion, pipelineElementDomId: string) { - var pipelineElementDom = $("#" + pipelineElementDomId); + let pipelineElementDom = $("#" + pipelineElementDomId); let pipelineElementConfig = this.createNewPipelineElementConfigWithFixedCoordinates(pipelineElementDom, pipelineElement, false); pipelineModel.push(pipelineElementConfig); @@ -123,7 +117,7 @@ export class JsplumbService { pipelineElement: InvocablePipelineElementUnion, $parentElement, previewConfig: boolean) { - var $target; + let $target; if (pipelineElement instanceof DataProcessorInvocation) { $target = this.dataProcessorDropped(pipelineElementDomId, pipelineElement as DataProcessorInvocation, true, false); this.connectNodes($parentElement, $target, previewConfig); @@ -136,7 +130,7 @@ export class JsplumbService { connectNodes($parentElement, $target, previewConfig: boolean) { - var options; + let options; let jsplumbBridge = this.getBridge(previewConfig); if ($parentElement.hasClass("stream")) { // TODO: getJsplumbConfig depends on isPreview. Not implemented yet @@ -145,7 +139,7 @@ export class JsplumbService { // TODO: getJsplumbConfig depends on isPreview. Not implemented yet options = this.jsplumbEndpointService.getJsplumbConfig(true).sepaEndpointOptions; } - var sourceEndPoint; + let sourceEndPoint; if (jsplumbBridge.selectEndpoints({source: $parentElement}).length > 0) { if (!(jsplumbBridge.selectEndpoints({source: $parentElement}).get(0).isFull())) { sourceEndPoint = jsplumbBridge.selectEndpoints({source: $parentElement}).get(0) @@ -156,15 +150,15 @@ export class JsplumbService { sourceEndPoint = jsplumbBridge.addEndpoint($parentElement, options); } - var targetEndPoint = jsplumbBridge.selectEndpoints({target: $target}).get(0); + let targetEndPoint = jsplumbBridge.selectEndpoints({target: $target}).get(0); jsplumbBridge.connect({source: sourceEndPoint, target: targetEndPoint, detachable: true}); jsplumbBridge.repaintEverything(); } createNewPipelineElementConfigWithFixedCoordinates($parentElement, json, isPreview): PipelineElementConfig { - var x = $parentElement.position().left; - var y = $parentElement.position().top; + let x = $parentElement.position().left; + let y = $parentElement.position().top; return this.createNewPipelineElementConfigAtPosition(x, y, json, isPreview); } @@ -232,10 +226,10 @@ export class JsplumbService { } makeId(count: number) { - var text = ""; - var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let text = ""; + const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - for (var i = 0; i < count; i++) + for (let i = 0; i < count; i++) text += possible.charAt(Math.floor(Math.random() * possible.length)); return text; @@ -253,20 +247,15 @@ export class JsplumbService { return this.dataProcessorDropped(pipelineElementDomId, pipelineElement, endpoints, preview); } else if (pipelineElement instanceof DataSinkInvocation) { return this.dataSinkDropped(pipelineElementDomId, pipelineElement, endpoints, preview); - }; + } } dataSetDropped(pipelineElementDomId: string, pipelineElement: SpDataSet, endpoints: boolean, preview: boolean) { - - - let jsplumbBridge = this.getBridge(preview); - if (endpoints) { - this.makeDraggableIfNotPreview(pipelineElementDomId, jsplumbBridge, preview); let endpointOptions = this.jsplumbEndpointService.getStreamEndpoint(preview, pipelineElementDomId); jsplumbBridge.addEndpoint(pipelineElementDomId, endpointOptions); } @@ -280,7 +269,6 @@ export class JsplumbService { preview: boolean) { let jsplumbBridge = this.getBridge(preview); if (endpoints) { - this.makeDraggableIfNotPreview(pipelineElementDomId, jsplumbBridge, preview); let endpointOptions = this.jsplumbEndpointService.getStreamEndpoint(preview, pipelineElementDomId); jsplumbBridge.addEndpoint(pipelineElementDomId, endpointOptions); } @@ -305,8 +293,6 @@ export class JsplumbService { endpoints: boolean, preview: boolean): string { let jsplumbBridge = this.getBridge(preview); - this.makeDraggableIfNotPreview(pipelineElementDomId, jsplumbBridge, preview); - if (endpoints) { if (pipelineElement.inputStreams.length < 2) { //1 InputNode jsplumbBridge.addEndpoint(pipelineElementDomId, @@ -324,16 +310,4 @@ export class JsplumbService { getBridge(previewConfig: boolean): JsplumbBridge { return this.JsplumbFactory.getJsplumbBridge(previewConfig); } - - makeDraggableIfNotPreview(pipelineElementDomId: string, - jsplumbBridge: JsplumbBridge, - previewConfig: boolean) { - if (!previewConfig) { - jsplumbBridge.draggable(pipelineElementDomId, {containment: 'parent', - drag: (e => { - this.pipelineElementDraggedService.notify({x: e.pos[0], y: e.pos[1]}); - }) - }); - } - } } diff --git a/ui/src/app/editor/services/object-provider.service.ts b/ui/src/app/editor/services/object-provider.service.ts index ff64406..e644181 100644 --- a/ui/src/app/editor/services/object-provider.service.ts +++ b/ui/src/app/editor/services/object-provider.service.ts @@ -71,13 +71,7 @@ export class ObjectProvider { } findElement(elementId, rawPipelineModel: PipelineElementConfig[]): PipelineElementConfig { - let result = {} as PipelineElementConfig; - rawPipelineModel.forEach(pe => { - if (pe.payload.dom === elementId) { - result = pe; - } - }); - return result; + return rawPipelineModel.find(pe => pe.payload.dom === elementId) || {} as PipelineElementConfig; } addElementNew(pipeline, currentPipelineElements: PipelineElementConfig[]): Pipeline { @@ -88,7 +82,7 @@ export class ObjectProvider { let payload = pe.payload; payload = this.prepareElement(payload as InvocablePipelineElementUnion); let connections = JsplumbBridge.getConnections({ - target: $("#" + payload.dom) + target: document.getElementById(payload.dom) }); for (let i = 0; i < connections.length; i++) { payload.connectedTo.push(connections[i].sourceId); diff --git a/ui/src/app/editor/services/pipeline-positioning.service.ts b/ui/src/app/editor/services/pipeline-positioning.service.ts index bf41d28..8e6b682 100644 --- a/ui/src/app/editor/services/pipeline-positioning.service.ts +++ b/ui/src/app/editor/services/pipeline-positioning.service.ts @@ -17,163 +17,186 @@ */ 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"; +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"; import { - DataProcessorInvocation, - DataSinkInvocation, - PipelineCanvasMetadata, - PipelineElementMetadata, - SpDataStream + DataProcessorInvocation, + DataSinkInvocation, + PipelineCanvasMetadata, + PipelineElementMetadata, + SpDataStream } from "../../core-model/gen/streampipes-model"; -import {JsplumbFactoryService} from "./jsplumb-factory.service"; -import {ObjectProvider} from "./object-provider.service"; +import { JsplumbFactoryService } from "./jsplumb-factory.service"; +import { ObjectProvider } from "./object-provider.service"; +import { Connection } from "@jsplumb/core"; @Injectable() export class PipelinePositioningService { - constructor(private JsplumbService: JsplumbService, - private JsplumbConfigService: JsplumbConfigService, - private JsplumbFactoryService: JsplumbFactoryService, - private ObjectProvider: ObjectProvider) { - } + constructor(private JsplumbService: JsplumbService, + private JsplumbConfigService: JsplumbConfigService, + private JsplumbFactoryService: JsplumbFactoryService, + private ObjectProvider: ObjectProvider) { + } + + collectPipelineElementPositions(pipelineCanvasMetadata: PipelineCanvasMetadata, + rawPipelineModel: PipelineElementConfig[]): PipelineCanvasMetadata { + rawPipelineModel.forEach(pe => { + this.collectPipelineElementPosition(pe.payload.dom, pipelineCanvasMetadata); + }); + return pipelineCanvasMetadata; + } - collectPipelineElementPositions(pipelineCanvasMetadata: PipelineCanvasMetadata, - rawPipelineModel: PipelineElementConfig[]): PipelineCanvasMetadata { - rawPipelineModel.forEach(pe => { - this.collectPipelineElementPosition(pe.payload.dom, pipelineCanvasMetadata); - }); - return pipelineCanvasMetadata; + collectPipelineElementPosition(domId: string, + pipelineCanvasMetadata: PipelineCanvasMetadata) { + let elementRef = $(`#${domId}`); + if (elementRef && elementRef.position()) { + let leftPos = elementRef.position().left; + let topPos = elementRef.position().top; + if (!pipelineCanvasMetadata.pipelineElementMetadata) { + pipelineCanvasMetadata.pipelineElementMetadata = {}; + } + if (!pipelineCanvasMetadata.pipelineElementMetadata[domId]) { + pipelineCanvasMetadata.pipelineElementMetadata[domId] = new PipelineElementMetadata(); + } + pipelineCanvasMetadata.pipelineElementMetadata[domId].position = { + x: leftPos, + y: topPos + }; } + } - collectPipelineElementPosition(domId: string, - pipelineCanvasMetadata: PipelineCanvasMetadata) { - let elementRef = $(`#${domId}`); - if (elementRef && elementRef.position()) { - let leftPos = elementRef.position().left; - let topPos = elementRef.position().top; - if (!pipelineCanvasMetadata.pipelineElementMetadata) { - pipelineCanvasMetadata.pipelineElementMetadata = {}; - } - if (!pipelineCanvasMetadata.pipelineElementMetadata[domId]) { - pipelineCanvasMetadata.pipelineElementMetadata[domId] = new PipelineElementMetadata(); - } - pipelineCanvasMetadata.pipelineElementMetadata[domId].position = { - x: leftPos, - y: topPos - }; + displayPipeline(rawPipelineModel: PipelineElementConfig[], + targetCanvas, + previewConfig: boolean, + autoLayout: boolean, + pipelineCanvasMetadata?: PipelineCanvasMetadata) { + let jsPlumbBridge = this.JsplumbFactoryService.getJsplumbBridge(previewConfig); + + let jsplumbConfig = previewConfig ? + this.JsplumbConfigService.getPreviewConfig() : + this.JsplumbConfigService.getEditorConfig(); + + rawPipelineModel.forEach(currentPe => { + if (!currentPe.settings.disabled) { + if (currentPe.type === "stream" || currentPe.type === "set") { + this.JsplumbService.dataStreamDropped( + currentPe.payload.dom, + currentPe.payload as SpDataStream, + true, + previewConfig + ); + } + if (currentPe.type === "sepa") { + this.JsplumbService.dataProcessorDropped( + currentPe.payload.dom, + currentPe.payload as DataProcessorInvocation, + true, + previewConfig + ); + } + if (currentPe.type === "action") { + this.JsplumbService.dataSinkDropped( + currentPe.payload.dom, + currentPe.payload as DataSinkInvocation, + true, + previewConfig + ); } + } + }); + + this.connectPipelineElements(rawPipelineModel, previewConfig, jsplumbConfig, jsPlumbBridge); + if (autoLayout) { + this.layoutGraph( + targetCanvas, + "div[id^='jsplumb']", + previewConfig ? 75 : 110, + previewConfig + ); + } else if (pipelineCanvasMetadata) { + this.layoutGraphFromCanvasMetadata(pipelineCanvasMetadata); } + jsPlumbBridge.repaintEverything(); + } - displayPipeline(rawPipelineModel: PipelineElementConfig[], - targetCanvas, - previewConfig: boolean, - autoLayout: boolean, - pipelineCanvasMetadata?: PipelineCanvasMetadata) { - let jsPlumbBridge = this.JsplumbFactoryService.getJsplumbBridge(previewConfig); - let jsplumbConfig = previewConfig ? this.JsplumbConfigService.getPreviewConfig() : this.JsplumbConfigService.getEditorConfig(); - rawPipelineModel.forEach(currentPe => { - if (!currentPe.settings.disabled) { - if (currentPe.type === "stream" || currentPe.type === "set") { - this.JsplumbService.dataStreamDropped(currentPe.payload.dom, - currentPe.payload as SpDataStream, - true, - previewConfig); - } - if (currentPe.type === "sepa") { - this.JsplumbService.dataProcessorDropped(currentPe.payload.dom, currentPe.payload as DataProcessorInvocation, true, previewConfig); - } - if (currentPe.type === "action") { - this.JsplumbService.dataSinkDropped(currentPe.payload.dom, currentPe.payload as DataSinkInvocation, true, previewConfig); - } - } - }); + layoutGraph(canvasId: string, + nodeIdentifier: string, + dimension: number, + previewConfig: boolean) { - this.connectPipelineElements(rawPipelineModel, previewConfig, jsplumbConfig, jsPlumbBridge); - if (autoLayout) { - this.layoutGraph(targetCanvas, "span[id^='jsplumb']", previewConfig ? 75 : 110, previewConfig); - } else if (pipelineCanvasMetadata) { - this.layoutGraphFromCanvasMetadata(pipelineCanvasMetadata); + let jsPlumbBridge = this.JsplumbFactoryService.getJsplumbBridge(previewConfig); + let g = new dagre.graphlib.Graph(); + g.setGraph({rankdir: "LR", ranksep: previewConfig ? "50" : "100"}); + g.setDefaultEdgeLabel(function () { + return {} + }); + let nodes = $(canvasId).find(nodeIdentifier).get(); + nodes.forEach((n) => { + g.setNode(n.id, {label: n.id, width: dimension, height: dimension}); + }); + + let edges = jsPlumbBridge.getAllConnections() as Connection[]; + edges.forEach(edge => { + g.setEdge(edge.source.id, edge.target.id); + }); + + dagre.layout(g); + g.nodes().forEach(v => { + let elementRef = $(`#${v}`); + elementRef.css("left", g.node(v).x + "px"); + elementRef.css("top", g.node(v).y + "px"); + }); + } + + layoutGraphFromCanvasMetadata(pipelineCanvasMetadata: PipelineCanvasMetadata) { + Object.entries(pipelineCanvasMetadata.pipelineElementMetadata).forEach( + ([key, value]) => { + let elementRef = $(`#${key}`); + if (elementRef) { + elementRef.css("left", value.position.x + "px"); + elementRef.css("top", value.position.y + "px"); } - jsPlumbBridge.repaintEverything(); - } + } + ); + } - layoutGraph(canvasId: string, - nodeIdentifier: string, - dimension: number, - previewConfig: boolean) { - let jsPlumbBridge = this.JsplumbFactoryService.getJsplumbBridge(previewConfig); - let g = new dagre.graphlib.Graph(); - g.setGraph({rankdir: "LR", ranksep: previewConfig ? "50" : "100"}); - g.setDefaultEdgeLabel(function () { - return {}; - }); - - let nodes = $(canvasId).find(nodeIdentifier).get(); - nodes.forEach((n) => { - g.setNode(n.id, {label: n.id, width: dimension, height: dimension}); - }); - - let edges = jsPlumbBridge.getAllConnections(); - edges.forEach(edge => { - g.setEdge(edge.source.id, edge.target.id); - }); - - dagre.layout(g); - g.nodes().forEach(v => { - let elementRef = $(`#${v}`); - elementRef.css("left", g.node(v).x + "px"); - elementRef.css("top", g.node(v).y + "px"); - }); - } + connectPipelineElements(rawPipelineModel: PipelineElementConfig[], + previewConfig: boolean, + jsplumbConfig: any, + jsPlumbBridge: JsplumbBridge) { + let source, target; + jsPlumbBridge.setSuspendDrawing(true); + rawPipelineModel.forEach(pe => { + if (pe.type == "sepa" || pe.type == "action") { + if (!(pe.settings.disabled) && pe.payload.connectedTo) { + pe.payload.connectedTo.forEach((connection, index) => { + source = connection; + target = pe.payload.dom; - layoutGraphFromCanvasMetadata(pipelineCanvasMetadata: PipelineCanvasMetadata) { - Object.entries(pipelineCanvasMetadata.pipelineElementMetadata).forEach( - ([key, value]) => { - let elementRef = $(`#${key}`); - if (elementRef) { - elementRef.css("left", value.position.x + "px"); - elementRef.css("top", value.position.y + "px"); - } - } - ); - } + let sourceEndpointId = "out-" + connection; + let inTargetEndpointId = "in-" + index + "-" + pe.payload.dom; + jsPlumbBridge.connect( + { + uuids: [sourceEndpointId, inTargetEndpointId], + detachable: !previewConfig + } + ); + jsPlumbBridge.activateEndpointWithType(sourceEndpointId, true, "token"); + jsPlumbBridge.activateEndpointWithType(inTargetEndpointId, true, "token"); - connectPipelineElements(rawPipelineModel: PipelineElementConfig[], - previewConfig: boolean, - jsplumbConfig: any, - jsPlumbBridge: JsplumbBridge) { - let source, target; - jsPlumbBridge.setSuspendDrawing(true); - rawPipelineModel.forEach(pe => { - if (pe.type == "sepa" || pe.type == "action") { - if (!(pe.settings.disabled) && pe.payload.connectedTo) { - pe.payload.connectedTo.forEach((connection, index) => { - source = connection; - target = pe.payload.dom; - - let sourceEndpointId = "out-" + connection; - let inTargetEndpointId = "in-" + index + "-" + pe.payload.dom; - jsPlumbBridge.connect( - { - uuids: [sourceEndpointId, inTargetEndpointId], - detachable: !previewConfig - } - ); - jsPlumbBridge.activateEndpointWithType(sourceEndpointId, true, "token"); - jsPlumbBridge.activateEndpointWithType(inTargetEndpointId, true, "token"); - - if (!(pe.payload instanceof DataSinkInvocation) && !(this.ObjectProvider.hasConnectedPipelineElement(pe.payload.dom, rawPipelineModel))) { - let outTargetEndpointId = "out-" + pe.payload.dom; - jsPlumbBridge.activateEndpointWithType(outTargetEndpointId, true, "token"); - } - }); - } + if (!(pe.payload instanceof DataSinkInvocation) && + !(this.ObjectProvider.hasConnectedPipelineElement(pe.payload.dom, rawPipelineModel))) { + let outTargetEndpointId = "out-" + pe.payload.dom; + jsPlumbBridge.activateEndpointWithType(outTargetEndpointId, true, "token"); } - }); - jsPlumbBridge.setSuspendDrawing(false, true); - } + }); + } + } + }); + jsPlumbBridge.setSuspendDrawing(false, true); + } } diff --git a/ui/src/app/editor/services/pipeline-validation.service.ts b/ui/src/app/editor/services/pipeline-validation.service.ts index 3ce8951..b3329fe 100644 --- a/ui/src/app/editor/services/pipeline-validation.service.ts +++ b/ui/src/app/editor/services/pipeline-validation.service.ts @@ -23,6 +23,7 @@ import { PipelineElementConfig } from '../model/editor.model'; import { DataProcessorInvocation, DataSinkInvocation } from '../../core-model/gen/streampipes-model'; import { JsplumbFactoryService } from './jsplumb-factory.service'; import { UserErrorMessage } from '../../core-model/base/UserErrorMessage'; +import { Connection } from "@jsplumb/core"; @Injectable() export class PipelineValidationService { @@ -31,11 +32,11 @@ export class PipelineValidationService { pipelineValid = false; availableErrorMessages: UserErrorMessage[] = [ - new UserErrorMessage('Did you add a data stream?', 'Any pipeline needs at least one data stream.'), - new UserErrorMessage('Did you add a data sink?', 'Any pipeline needs at least one data sink.'), - new UserErrorMessage('Did you connect all elements?', 'No orphaned elements are allowed within a pipeline, make sure to connect all elements.'), - new UserErrorMessage('Separate pipelines', 'It seems you\'ve created more than one pipeline at once. Create only one pipeline at a time!'), - new UserErrorMessage('Did you configure all elements?', 'There\'s a pipeline element which is missing some configuration.') + new UserErrorMessage('Did you add a data stream?', 'Any pipeline needs at least one data stream.'), + new UserErrorMessage('Did you add a data sink?', 'Any pipeline needs at least one data sink.'), + new UserErrorMessage('Did you connect all elements?', 'No orphaned elements are allowed within a pipeline, make sure to connect all elements.'), + new UserErrorMessage('Separate pipelines', 'It seems you\'ve created more than one pipeline at once. Create only one pipeline at a time!'), + new UserErrorMessage('Did you configure all elements?', 'There\'s a pipeline element which is missing some configuration.') ]; constructor(private jsplumbFactoryService: JsplumbFactoryService) { @@ -61,10 +62,10 @@ export class PipelineValidationService { if (!this.isEmptyPipeline(rawPipelineModel)) { this.buildErrorMessages(streamInAssembly, - actionInAssembly, - allElementsConnected, - onlyOnePipelineCreated, - allElementsConfigured); + actionInAssembly, + allElementsConnected, + onlyOnePipelineCreated, + allElementsConfigured); } else { this.errorMessages = []; } @@ -76,7 +77,7 @@ export class PipelineValidationService { isEmptyPipeline(rawPipelineModel) { return !this.isActionInAssembly(rawPipelineModel) && - !this.isStreamInAssembly(rawPipelineModel) && !this.isInAssembly(rawPipelineModel, 'sepa'); + !this.isStreamInAssembly(rawPipelineModel) && !this.isInAssembly(rawPipelineModel, 'sepa'); } buildErrorMessages(streamInAssembly, actionInAssembly, allElementsConnected, onlyOnePipelineCreated, allElementsConfigured) { @@ -149,8 +150,7 @@ export class PipelineValidationService { g.setDefaultEdgeLabel(function () { return {}; }); - const nodes = $('#assembly').find('span[id^=\'jsplumb\']').get(); - + const nodes = $('#assembly').find('div[id^=\'jsplumb\']').get(); for (let i = 0; i < nodes.length; i++) { const n = nodes[i]; const elementOptions = this.getElementOptions(n.id, rawPipelineModel); @@ -163,7 +163,7 @@ export class PipelineValidationService { }); } } - const edges = jsplumbBridge.getAllConnections(); + const edges = jsplumbBridge.getAllConnections() as Connection[]; edges.forEach((edge, i) => { const c = edges[i]; g.setEdge(c.source.id, c.target.id); diff --git a/ui/src/scss/main.scss b/ui/src/scss/main.scss index 4ae48bf..8fcfa66 100644 --- a/ui/src/scss/main.scss +++ b/ui/src/scss/main.scss @@ -24,7 +24,7 @@ @import '~bootstrap/dist/css/bootstrap.css'; @import '~@fortawesome/fontawesome-free/css/all.css'; @import '~angular-ui-tree/dist/angular-ui-tree.min.css'; -@import '~jsplumb/css/jsplumbtoolkit-defaults.css'; +@import '~@jsplumb/browser-ui/css/jsplumbtoolkit.css'; @import '~ng-prettyjson/dist/ng-prettyjson.min.css'; @import '~prismjs/themes/prism.css'; @import '~angular-loading-bar/build/loading-bar.min.css';
