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 2022/02/14 17:41:17 UTC
[incubator-streampipes] branch experimental-module-federation-494 updated: [STREAMPIPES-510] Move pipeline editor selection panel to the left
This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch experimental-module-federation-494
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git
The following commit(s) were added to refs/heads/experimental-module-federation-494 by this push:
new 705a121 [STREAMPIPES-510] Move pipeline editor selection panel to the left
705a121 is described below
commit 705a121adcd03f302931726d0dfd7ec43dfe7b5c
Author: Dominik Riemer <do...@gmail.com>
AuthorDate: Mon Feb 14 18:40:50 2022 +0100
[STREAMPIPES-510] Move pipeline editor selection panel to the left
---
.../pipeline-assembly.component.html | 101 ++++---
.../pipeline-assembly.component.scss | 23 +-
.../pipeline-assembly.component.ts | 8 +-
.../pipeline-element-icon-stand-row.component.html | 58 ++++
.../pipeline-element-icon-stand-row.component.scss | 83 ++++++
.../pipeline-element-icon-stand-row.component.ts | 61 ++++
.../pipeline-element-icon-stand.component.html | 129 +++++---
.../pipeline-element-icon-stand.component.scss | 94 +++++-
.../pipeline-element-icon-stand.component.ts | 264 ++++++++---------
.../pipeline-element.component.css | 6 +-
.../pipeline-element.component.html | 2 +-
.../pipeline-element/pipeline-element.component.ts | 2 +-
.../components/pipeline/pipeline.component.css | 2 +-
.../components/pipeline/pipeline.component.html | 4 +-
.../components/pipeline/pipeline.component.ts | 10 +-
ui/src/app/editor/editor.component.html | 46 +--
ui/src/app/editor/editor.component.scss | 4 -
ui/src/app/editor/editor.component.ts | 329 ++++++++-------------
ui/src/app/editor/editor.module.ts | 9 +
ui/src/app/editor/model/editor.model.ts | 13 +-
ui/src/app/editor/services/editor.service.ts | 21 +-
.../pipeline-element-group-filter.pipe.ts} | 30 +-
.../pipeline-element-name-filter.pipe.ts} | 31 +-
.../pipeline-element-type-filter.pipe.ts} | 30 +-
.../app/services/get-element-icon-text.service.ts | 4 +-
ui/src/scss/sp/colors.scss | 1 +
ui/src/scss/sp/layout.scss | 2 +-
ui/src/scss/sp/main.scss | 7 +
ui/src/scss/sp/pipeline-element-options.scss | 7 +-
29 files changed, 798 insertions(+), 583 deletions(-)
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 9101a37..4e39a96 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
@@ -17,9 +17,12 @@
-->
<div fxFlex="100" fxLayout="column">
- <div class="pipeline-assembly-options sp-blue-bg">
+ <div class="pipeline-assembly-options sp-bg-lightgray page-container-nav">
<div fxFlex="100" fxLayout="row" fxLayoutAlign="start center">
- <button mat-button matTooltip="Save Pipeline" [matTooltipPosition]="'above'"
+ <button mat-button
+ mat-raised-button
+ color="accent"
+ matTooltip="Save Pipeline" [matTooltipPosition]="'above'"
[disabled]="!pipelineValidationService.pipelineValid"
(click)="submit()" type="submit"
data-cy="sp-editor-save-pipeline">
@@ -30,17 +33,20 @@
</button>
<span class="assembly-options-divider"></span>
<!-- TODO: Use this once copying of elements is supported -->
-<!-- <button mat-button mat-icon-button matTooltip="Pan" [matTooltipPosition]="'above'"-->
-<!-- [disabled]="!selectMode"-->
-<!-- (click)="toggleSelectMode()">-->
-<!-- <i class="material-icons">open_with</i>-->
-<!-- </button>-->
-<!-- <button mat-button mat-icon-button matTooltip="Select" [matTooltipPosition]="'above'"-->
-<!-- [disabled]="selectMode"-->
-<!-- (click)="toggleSelectMode()">-->
-<!-- <i class="material-icons">mode_edit</i>-->
-<!-- </button>-->
- <button mat-button matTooltip="Data Preview" [matTooltipPosition]="'above'"
+ <!-- <button mat-button mat-icon-button matTooltip="Pan" [matTooltipPosition]="'above'"-->
+ <!-- [disabled]="!selectMode"-->
+ <!-- (click)="toggleSelectMode()">-->
+ <!-- <i class="material-icons">open_with</i>-->
+ <!-- </button>-->
+ <!-- <button mat-button mat-icon-button matTooltip="Select" [matTooltipPosition]="'above'"-->
+ <!-- [disabled]="selectMode"-->
+ <!-- (click)="toggleSelectMode()">-->
+ <!-- <i class="material-icons">mode_edit</i>-->
+ <!-- </button>-->
+ <button mat-button
+ color="accent"
+ matTooltip="Data Preview"
+ [matTooltipPosition]="'above'"
(click)="triggerPipelinePreview()" [disabled]="isPipelineAssemblyEmpty()">
<div fxLayoutAlign="start center" fxLayout="row">
<i class="material-icons">visibility</i>
@@ -49,39 +55,35 @@
</div>
</button>
<span class="assembly-options-divider"></span>
- <button mat-button mat-icon-button matTooltip="Auto Layout" [matTooltipPosition]="'above'"
+ <button mat-button
+ color="accent"
+ mat-icon-button
+ matTooltip="Auto Layout" [matTooltipPosition]="'above'"
(click)="autoLayout()">
<i class="material-icons">settings_overscan</i>
</button>
- <button mat-button mat-icon-button matTooltip="Add pipeline element" [matTooltipPosition]="'above'"
+ <button mat-button
+ color="accent"
+ mat-icon-button
+ matTooltip="Add pipeline element" [matTooltipPosition]="'above'"
(click)="openDiscoverDialog()"
data-cy="sp-editor-add-pipeline-element">
<i class="material-icons">add</i>
</button>
<div fxLayout="column" fxLayoutAlign="start center" class="pipeline-cache-block">
- <div fxFlex="100" fxLayoutAlign="start center" fxLayout="row" *ngIf="pipelineCached || pipelineCacheRunning">
+ <div fxFlex="100" fxLayoutAlign="start center" fxLayout="row"
+ *ngIf="pipelineCached || pipelineCacheRunning">
<div *ngIf="pipelineCached" fxLayout="row" fxLayoutAlign="start center">
- <mat-spinner [mode]="'indeterminate'" class="mat-spinner-color" [diameter]="15" *ngIf="pipelineCacheRunning"></mat-spinner>
+ <mat-spinner [mode]="'indeterminate'" class="mat-spinner-color" [diameter]="15"
+ *ngIf="pipelineCacheRunning"></mat-spinner>
<span> {{pipelineCacheRunning ? ' Saving pipeline modifications' : 'All pipeline modifications saved.'}}</span>
</div>
</div>
</div>
<span fxFlex></span>
- <div style="position:relative;">
- <sp-error-hint
- [displayMessages]="!isPipelineAssemblyEmpty()"
- [errorMessages]="pipelineValidationService.errorMessages"
- [validationString]="'Pipeline'">
- </sp-error-hint>
- </div>
- <button mat-button mat-icon-button
- [matTooltip]="pipelineCanvasMaximized ? 'Minimize' : 'Maximize'"
- [matTooltipPosition]="'above'"
- (click)="toggleCanvasMaximized()">
- <i class="material-icons" *ngIf="!pipelineCanvasMaximized">open_in_full</i>
- <i class="material-icons" *ngIf="pipelineCanvasMaximized">close_fullscreen</i>
- </button>
- <button mat-button mat-icon-button matTooltip="Clear Assembly Area"
+ <button mat-button
+ color="accent"
+ mat-icon-button matTooltip="Clear Assembly Area"
[matTooltipPosition]="'above'"
[disabled]="editorService.pipelineAssemblyEmpty"
(click)="showClearAssemblyConfirmDialog($event)">
@@ -89,8 +91,15 @@
</button>
</div>
</div>
- <div id="outerAssemblyArea" class="outerAssembly sp-blue-border-nopadding">
+ <div id="outerAssemblyArea" class="outerAssembly assembly-border">
<div class="pipeline-canvas-outer" #outerCanvas>
+ <div class="pipeline-validation-hint">
+ <sp-error-hint
+ [displayMessages]="!isPipelineAssemblyEmpty()"
+ [errorMessages]="pipelineValidationService.errorMessages"
+ [validationString]="'Pipeline'">
+ </sp-error-hint>
+ </div>
<div class="pan-control">
<div class="pan-zoom-control-buttons">
<div class="pan-zoom-button pan-left" (click)="panLeft()">
@@ -121,18 +130,20 @@
</div>
</div>
</div>
- <pipeline class="canvas jtk-surface" id="assembly" #pipelineComponent
- [pipelineValid]="pipelineValid"
- [canvasId]="'assembly'"
- [rawPipelineModel]="rawPipelineModel"
- [allElements]="allElements"
- [preview]="false"
- [pipelineCached]="pipelineCached"
- [pipelineCanvasMetadata]="pipelineCanvasMetadata"
- [pipelineCacheRunning]="pipelineCacheRunning"
- (pipelineCachedChanged)="pipelineCached=$event"
- (pipelineCacheRunningChanged)="pipelineCacheRunning=$event" style="position:absolute;">
- </pipeline>
+ <pipeline class="canvas jtk-surface" id="assembly"
+ #pipelineComponent
+ [pipelineValid]="pipelineValid"
+ [canvasId]="'assembly'"
+ [rawPipelineModel]="rawPipelineModel"
+ [allElements]="allElements"
+ [preview]="false"
+ [pipelineCached]="pipelineCached"
+ [pipelineCanvasMetadata]="pipelineCanvasMetadata"
+ [pipelineCacheRunning]="pipelineCacheRunning"
+ (pipelineCachedChanged)="pipelineCached=$event"
+ (pipelineCacheRunningChanged)="pipelineCacheRunning=$event" style="position:absolute;">
+ </pipeline>
+
</div>
</div>
</div>
diff --git a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.scss b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.scss
index 9337454..52b217d 100644
--- a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.scss
+++ b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.scss
@@ -19,7 +19,7 @@
@import '../../../../scss/_variables.scss';
.mat-spinner-color::ng-deep svg circle{
- stroke: #FFFFFF !important;
+ stroke: var(--color-accent) !important;
}
.pipeline-cache-progress {
@@ -66,10 +66,14 @@
.pipeline-assembly-options {
padding-left: 5px;
- color: white;
+ border: 1px solid var(--color-bg-3);
//background: #f6f6f6;
}
+.assembly-border {
+ border: 1px solid var(--color-bg-3);
+}
+
.jtk-surface-nopan {
overflow: scroll !important;
cursor:default;
@@ -88,6 +92,15 @@
}
+.pipeline-validation-hint {
+ position: absolute;
+ right: 10px;
+ top: 20px;
+ z-index: 10;
+ background: var(--color-bg-1);
+ box-shadow: 0.175em 0.175em 0 0 rgba(15, 28, 63, 0.125);
+}
+
.pan-control {
position: absolute;
right: 60px;
@@ -151,13 +164,15 @@
}
.assembly-options-divider {
- width: 2px;
+ width: 1px;
height: 70%;
margin-left: 10px;
margin-right: 10px;
- background: #b8b8b8;
+ background: var(--color-bg-3);
}
.color-warn {
color: var(--color-warn);
}
+
+
diff --git a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts
index fd23987..7f3f189 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
@@ -40,7 +40,7 @@ import { DialogService } from '../../../core-ui/dialog/base-dialog/base-dialog.s
import { ConfirmDialogComponent } from '../../../core-ui/dialog/confirm-dialog/confirm-dialog.component';
import { MatDialog } from '@angular/material/dialog';
import { EditorService } from '../../services/editor.service';
-import { PipelineService, PipelineCanvasMetadataService, PipelineCanvasMetadata } from '@streampipes/platform-services';
+import { PipelineCanvasMetadata, PipelineCanvasMetadataService, PipelineService } from '@streampipes/platform-services';
import { JsplumbFactoryService } from '../../services/jsplumb-factory.service';
import Panzoom, { PanzoomObject } from '@panzoom/panzoom';
import { PipelineElementDraggedService } from '../../services/pipeline-element-dragged.service';
@@ -290,11 +290,6 @@ export class PipelineAssemblyComponent implements OnInit, AfterViewInit {
return this.rawPipelineModel.length === 0 || this.rawPipelineModel.every(pe => pe.settings.disabled);
}
- toggleCanvasMaximized() {
- this.pipelineCanvasMaximized = !(this.pipelineCanvasMaximized);
- this.pipelineCanvasMaximizedEmitter.emit(this.pipelineCanvasMaximized);
- }
-
panLeft() {
this.pan(100, 0);
}
@@ -341,5 +336,4 @@ export class PipelineAssemblyComponent implements OnInit, AfterViewInit {
}
});
}
-
}
diff --git a/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.html b/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.html
new file mode 100644
index 0000000..25eb72d
--- /dev/null
+++ b/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.html
@@ -0,0 +1,58 @@
+<!--
+ ~ 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 fxLayout="row"
+ class="draggable-pipeline-element"
+ fxFlex="100"
+ id="{{ element.appId }}"
+ [attr.data-pe]="element.elementId"
+ (mouseenter)="updateMouseOver(element.name)"
+ (mouseleave)="updateMouseOver('')">
+ <div fxFlex="50px">
+ <div matTooltip="{{element.name}}" [matTooltipPosition]="'above'"
+ class="draggable-icon-editor tt"
+ [ngClass]="activeCssClass">
+ <span id="container" class="pe-container">
+ <pipeline-element
+ id="pe-icon-stand-{{ element.appId }}"
+ style="margin-left:-3%"
+ [iconStandSize]="true"
+ [attr.data-cy]="'sp-pipeline-element-' + cypressName"
+ [pipelineElement]="element"
+ [preview]="false"></pipeline-element>
+ </span>
+ </div>
+ </div>
+ <div fxFlex fxLayoutAlign="start start" fxLayout="column">
+ <div class="element-name" fxLayoutAlign="start start">
+ {{element.name}}
+ </div>
+ <div class="element-description" *ngIf="currentMouseOver" fxLayoutAlign="start start">
+ <small>{{element.description}}</small>
+ </div>
+ </div>
+ <div fxLayoutAlign="end start" *ngIf="currentMouseOver">
+ <button mat-button
+ mat-raised-button
+ mat-icon-button
+ color="accent"
+ class="help-button-stand"
+ (click)="openHelpDialog(element)">?
+ </button>
+ </div>
+</div>
+
diff --git a/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.scss b/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.scss
new file mode 100644
index 0000000..085ba50
--- /dev/null
+++ b/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.scss
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ *
+ */
+
+.draggable-icon-editor {
+ cursor: move;
+ vertical-align: top;
+ background-color: var(--color-pe);
+ display: inline-block;
+ height: 35px;
+ width: 35px;
+ line-height: 35px;
+ box-shadow: 1px 1px 2px var(--color-shadow);
+ text-align: center;
+ z-index:100;
+}
+
+.draggable-icon-drag {
+ cursor: pointer;
+ vertical-align: top;
+ background: var(--color-pe);
+ display: inline-block;
+ height: 70px;
+ width: 70px;
+ line-height: 70px;
+ box-shadow: 1px 1px 2px var(--color-shadow);
+ text-align: center;
+ background: white;
+ z-index: 100;
+}
+
+.draggable-pipeline-element {
+ cursor: move;
+ z-index: 100;
+}
+
+.element-name {
+ font-size: 11pt;
+ font-weight: 500;
+}
+
+.element-description {
+ font-weight: 300;
+}
+
+.help-button-stand {
+ padding: 0;
+ min-width: 0;
+ width: 20px;
+ height: 20px;
+ flex-shrink: 0;
+ line-height: 20px;
+ border-radius: 0;
+ margin-right: 5px;
+}
+
+.pe-container {
+ position:relative;
+ display:block;
+ width:35px;
+ height:35px;
+}
+
+.pe-container-drag {
+ position:relative;
+ display:block;
+ width:70px;
+ height:70px;
+}
diff --git a/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.ts b/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.ts
new file mode 100644
index 0000000..bd799a0
--- /dev/null
+++ b/ui/src/app/editor/components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component.ts
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit, } from '@angular/core';
+import { PipelineElementType, PipelineElementUnion } from '../../model/editor.model';
+import { PipelineElementTypeUtils } from '../../utils/editor.utils';
+import { EditorService } from '../../services/editor.service';
+
+
+@Component({
+ selector: 'sp-pe-icon-stand-row',
+ templateUrl: './pipeline-element-icon-stand-row.component.html',
+ styleUrls: ['./pipeline-element-icon-stand-row.component.scss']
+})
+export class PipelineElementIconStandRowComponent implements OnInit {
+
+ @Input()
+ element: PipelineElementUnion;
+
+ activeCssClass: string;
+ cypressName: string;
+
+ currentMouseOver = false;
+
+ constructor(private editorService: EditorService) {
+
+ }
+
+ ngOnInit(): void {
+ const activeType = PipelineElementTypeUtils.fromClassName(this.element['@class']);
+ this.activeCssClass = this.makeActiveCssClass(activeType);
+ this.cypressName = this.element.name.toLowerCase().replace(' ', '_');
+ }
+
+ makeActiveCssClass(elementType: PipelineElementType): string {
+ return PipelineElementTypeUtils.toCssShortHand(elementType);
+ }
+
+ updateMouseOver(e: string) {
+ this.currentMouseOver = !this.currentMouseOver;
+ }
+
+ openHelpDialog(pipelineElement) {
+ this.editorService.openHelpDialog(pipelineElement);
+ }
+}
diff --git a/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.html b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.html
index e53dfee..21b8332 100644
--- a/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.html
+++ b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.html
@@ -16,60 +16,97 @@
~
-->
<div fxFlex="100" fxLayout="column" class="border">
- <div class="editorIconStandOptions" style="padding:0px;">
- <div fxFlex="100" fxLayout="row" fxLayoutAlign="start start" style="padding-top:2px;padding-left:10px;">
-
+ <div class="editorIconStandOptions sp-bg-lightgray page-container-nav" style="padding:0px;">
+ <div fxFlex="100" fxLayout="row" fxLayoutAlign="start center" style="padding-left:5px;">
<div fxLayoutAlign="start center" fxLayout="row">
- <div fxLayout="row" style="margin-right: 5px">
+ <div fxLayout="row" fxLayoutAlign="start center">
<i class="material-icons sp-accent">search</i>
- <input type="text" (keyup)="applyFilter()" [(ngModel)]="elementFilter" placeholder="Find Element"
+ <input type="text" (keyup)="makeDraggable()" [(ngModel)]="elementFilter" placeholder="Find Element"
style="border: none;border-bottom: solid 2px rgb(27, 20, 100);">
+ <button mat-button
+ mat-icon-button
+ color="accent"
+ (click)="startCreatePipelineTour()"
+ [matTooltip]="'Tutorial'" style="margin-right: 5px;">
+ <i class="material-icons">
+ school
+ </i>
+ </button>
</div>
- <div fxLayout="row">
- <button mat-button [matMenuTriggerFor]="menu"><div class="menu-text-color"><i class="material-icons">list</i> Filter by category</div></button>
- <mat-menu #menu="matMenu">
- <button mat-menu-item (click)="selectAllOptions()">
- <div class="menu-text-color"><i class="material-icons">done</i> Select all</div>
- </button>
- <button mat-menu-item (click)="deselectAllOptions()">
- <div class="menu-text-color"><i class="material-icons">clear</i> Deselect all</div>
- </button>
- <mat-divider></mat-divider>
- <button (click)="toggleOption(option)" mat-menu-item *ngFor="let option of currentCategories">
- <div class="menu-text-color" *ngIf="optionSelected(option)">
- <i class="material-icons">visibility</i> {{option.label}}
+ </div>
+ </div>
+ </div>
+ <div id="editor-icon-stand"
+ class="icon-stand"
+ *ngIf="allElements">
+ <div fxFlex="100"
+ fxLayout="column">
+ <div *ngFor="let availableType; let i = index of availableTypes"
+ fxLayout="column"
+ class="panel-outer">
+ <div class="panel-header"
+ fxLayout="row"
+ fxLayoutAlign="start center"
+ [ngStyle]="{background: 'var(--color-bg-2)'}">
+ <div class="panel-title"
+ fxLayoutAlign="start center">
+ {{availableType.title}}
+ </div>
+ <span fxFlex>
+ </span>
+ <button mat-icon-button
+ (click)="toggleOpen(availableType)"
+ *ngIf="!availableType.open">
+ <mat-icon>expand_more</mat-icon>
+ </button>
+ <button mat-icon-button
+ (click)="toggleOpen(availableType)"
+ *ngIf="availableType.open">
+ <mat-icon>expand_less</mat-icon>
+ </button>
+ </div>
+ <div fxFlex="100"
+ fxLayout="column"
+ *ngIf="availableType.open" class="panel-content">
+ <div fxLayout="row"
+ fxLayoutAlign="end center"
+ class="panel-options"
+ *ngIf="!(availableType.filters[0] === 1)">
+ <small>Sort: <a (click)="changeSorting(availableType, 'group')"
+ class="sort-option"
+ [ngClass]="availableType.sort === 'group' ? 'sort-selected' : 'sort-unselected'">Group</a> |
+ <a (click)="changeSorting(availableType, 'name')"
+ class="sort-option"
+ [ngClass]="availableType.sort === 'name' ? 'sort-selected' : 'sort-unselected'">Name</a></small>
+ </div>
+ <div fxFlex="100"
+ fxLayout="column"
+ *ngIf="availableType.sort === 'name'">
+ <div fxLayout="column"
+ fxFlex="100"
+ *ngFor="let element of allElements | pipelineElementType:availableType.filters | pipelineElementName:elementFilter"
+ class="pe-row">
+ <sp-pe-icon-stand-row [element]="element" fxFlex="100"></sp-pe-icon-stand-row>
+ </div>
+ </div>
+ <div fxFlex="100"
+ fxLayout="column"
+ *ngIf="availableType.sort === 'group' && categoriesReady">
+ <div *ngFor="let category of allCategories.get(availableType.filters[0])"
+ fxLayout="column">
+ <div class="group-outer">
+ <span class="group-title">{{category.label}}</span>
</div>
- <div class="menu-text-color" *ngIf="!optionSelected(option)">
- <i class="material-icons">visibility_off</i> {{option.label}}
+ <div fxLayout="column"
+ fxFlex="100"
+ *ngFor="let element of allElements | pipelineElementType:availableType.filters | pipelineElementName:elementFilter | pipelineElementGroup:category"
+ class="pe-row">
+ <sp-pe-icon-stand-row [element]="element" fxFlex="100"></sp-pe-icon-stand-row>
</div>
- </button>
- </mat-menu>
+ </div>
+ </div>
</div>
</div>
</div>
</div>
- <div flex id="editor-icon-stand" class="icon-stand" *ngIf="currentlyFilteredElements">
- <span matTooltip="{{element.name}}" [matTooltipPosition]="'above'" [matTooltipClass]="tooltip" id="{{ element.appId }}" (mouseenter)="updateMouseOver(element.name)"
- (mouseleave)="updateMouseOver('')"
- *ngFor="let element of currentlyFilteredElements"
- 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"
- [attr.data-cy]="'sp-pipeline-element-' + element.name.toLowerCase().replaceAll(' ', '_')"
- [pipelineElement]="element"
- [preview]="false"></pipeline-element>
- <span style="display:block;width:100%;height:100%;position:absolute; top:0; left:0;"
- *ngIf="currentElementName===element.name">
- <span class="help-button-icon-stand" style="z-index:10"><button mat-button mat-icon-button
- (click)="openHelpDialog(element)"
- style="margin:0px;font-size:20px;">?</button>
- </span>
- </span>
- </span>
- </span>
- </div>
</div>
diff --git a/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.scss b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.scss
index d5a2288..ca19855 100644
--- a/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.scss
+++ b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.scss
@@ -19,20 +19,94 @@
@import '../../../../scss/_variables.scss';
.menu-text-color {
- color: var(--color-accent);
- display: flex;
- align-items: center;
+ color: var(--color-accent);
+ display: flex;
+ align-items: center;
}
.icon-stand {
- max-height: 200px;
- padding-bottom: 1%;
- overflow-y: auto;
- border-top: 0px;
- background: var(--color-bg-1);
+ max-height: calc(100vh - 118px);
+ overflow-y: auto;
+ background: var(--color-bg-1);
+ margin-top: 5px;
}
.border {
- border: 1px solid var(--color-bg-2);
- border-top: 0;
+ border: 1px solid var(--color-bg-3);
+}
+
+.pe-row {
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-left: 5px;
+}
+
+
+.pe-row:nth-child(even) {
+ background-color: var(--color-bg-1);
+}
+
+.pe-row:nth-child(odd) {
+ background-color: var(--color-bg-0);
+}
+
+.pe-row:hover {
+ background-color: var(--color-bg-2);
+ cursor: pointer;
+}
+
+.panel-header {
+ padding: 3px;
+}
+
+.panel-title {
+ font-weight: 400;
+ padding-left: 5px;
+}
+
+.panel-options {
+ margin-top: 10px;
+ margin-bottom: 5px;
+ margin-right: 5px;
+}
+
+.panel-content {
+ margin-top: 10px;
+}
+
+.sort-selected {
+ padding: 3px;
+ background: var(--color-accent);
+ color: white;
+}
+
+.sort-unselected {
+ padding: 3px;
+ color: var(--color-accent);
+}
+
+.panel-outer {
+ margin-bottom: 10px;
+ margin-left: 0;
+ margin-right: 0px;
+ border-right: 1px solid var(--color-bg-3);
+ border-bottom: 1px solid var(--color-bg-3);
+ border-top: 1px solid var(--color-bg-3);
+}
+
+.group-outer {
+ margin-top: 15px;
+ margin-bottom: 10px;
+}
+
+.group-title {
+ padding-left: 5px;
+ padding-right: 5px;
+ border-radius: 3px;
+ font-size: small;
+ background: var(--color-primary);
+}
+
+.sort-option {
+ cursor: pointer;
}
diff --git a/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.ts b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.ts
index 5abe418..3efdf09 100644
--- a/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.ts
+++ b/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.ts
@@ -16,162 +16,132 @@
*
*/
-import { AfterViewInit, Component, Input, OnInit, } from '@angular/core';
+import { AfterViewInit, Component, EventEmitter, Input, OnInit, Output, } from '@angular/core';
import { RestApi } from '../../../services/rest-api.service';
-import {
- PipelineElementIdentifier,
- PipelineElementType,
- PipelineElementUnion
-} from '../../model/editor.model';
-import { PipelineElementTypeUtils } from '../../utils/editor.utils';
+import { PeCategory, PipelineElementType, PipelineElementUnion } from '../../model/editor.model';
import { EditorService } from '../../services/editor.service';
import { zip } from 'rxjs';
@Component({
- selector: 'pipeline-element-icon-stand',
- templateUrl: './pipeline-element-icon-stand.component.html',
- styleUrls: ['./pipeline-element-icon-stand.component.scss']
+ selector: 'pipeline-element-icon-stand',
+ templateUrl: './pipeline-element-icon-stand.component.html',
+ styleUrls: ['./pipeline-element-icon-stand.component.scss']
})
export class PipelineElementIconStandComponent implements OnInit, AfterViewInit {
-
- _currentElements: PipelineElementUnion[];
-
- currentlyFilteredElements: PipelineElementUnion[];
-
- elementFilter = '';
- allCategories: any = [];
- currentCategories: any = [];
- selectedOptions: any = [];
-
- _activeType: PipelineElementType;
- activeCssClass: string;
-
- currentElementName: string;
-
- constructor(private restApi: RestApi,
- private editorService: EditorService) {
-
- }
-
- ngOnInit(): void {
- this.loadOptions();
- }
-
- ngAfterViewInit() {
- this.makeDraggable();
- }
-
- openHelpDialog(pipelineElement) {
- this.editorService.openHelpDialog(pipelineElement);
- }
-
- updateMouseOver(elementAppId: string) {
- this.currentElementName = elementAppId;
- }
-
- loadOptions() {
- zip(this.editorService.getEpCategories(),
- this.editorService.getEpaCategories(),
- this.editorService.getEcCategories()).subscribe((results) => {
- this.allCategories[PipelineElementType.DataStream] = results[0];
- this.allCategories[PipelineElementType.DataSet] = results[0];
- this.allCategories[PipelineElementType.DataProcessor] = results[1];
- this.allCategories[PipelineElementType.DataSink] = results[2];
- this.currentCategories = this.allCategories[0];
- this.selectedOptions = [...this.currentCategories];
- });
- }
-
- applyFilter() {
- this.currentlyFilteredElements = this.currentElements.filter(el => {
- return this.matchesText(el) && this.matchesCategory(el);
- });
- this.makeDraggable();
- }
-
- matchesText(el: PipelineElementUnion): boolean {
- return this.elementFilter === '' || el.name.toLowerCase().includes(this.elementFilter.toLowerCase());
- }
-
- matchesCategory(el: PipelineElementUnion): boolean {
- return this._activeType === PipelineElementType.DataStream ||
- this._activeType === PipelineElementType.DataSet ?
- this.selectedOptions.some(c => el.category.some(cg => c.type === cg)) :
- this.selectedOptions.some(c => !(el.category) || el.category.length === 0 || el.category.some(cg => c.code === cg));
- }
-
- toggleOption(option) {
- if (this.optionSelected(option)) {
- this.selectedOptions.splice(option, 1);
- } else {
- this.selectedOptions.push(option);
- }
- this.applyFilter();
- }
-
- optionSelected(option) {
- return this._activeType === PipelineElementType.DataStream ||
- this._activeType === PipelineElementType.DataSet ?
- this.selectedOptions.map(o => o.type).indexOf(option.type) > -1 :
- this.selectedOptions.map(o => o.code).indexOf(option.code) > -1;
- }
-
- selectAllOptions() {
- this.selectedOptions = [...this.currentCategories];
- this.applyFilter();
- }
-
- deselectAllOptions() {
- this.selectedOptions = [];
- this.applyFilter();
- }
-
- @Input()
- set activeType(value: PipelineElementIdentifier) {
- const activeType = PipelineElementTypeUtils.fromClassName(value);
- this._activeType = activeType;
- if (this.allCategories.length > 0) {
- this.currentCategories = this.allCategories[this._activeType];
- this.selectedOptions = [...this.currentCategories];
+ availableTypes = [
+ {
+ title: 'Data Sources',
+ filters: [PipelineElementType.DataStream, PipelineElementType.DataSet],
+ open: true,
+ color: 'var(--color-stream)',
+ sort: 'name'
+ },
+ {
+ title: 'Data Processors',
+ filters: [PipelineElementType.DataProcessor],
+ open: true,
+ color: 'var(--color-processor)',
+ sort: 'name'
+ },
+ {
+ title: 'Data Sinks',
+ filters: [PipelineElementType.DataSink],
+ open: true,
+ color: 'var(--color-sink)',
+ sort: 'name'
+ }];
+
+ @Input()
+ allElements: PipelineElementUnion[];
+
+ @Output()
+ startTourEmitter: EventEmitter<void> = new EventEmitter<void>();
+
+ elementFilter = '';
+ allCategories: Map<PipelineElementType, PeCategory[]> = new Map();
+ categoriesReady = false;
+ uncategorized: PeCategory = {code: 'UNCATEGORIZED', label: 'Uncategorized', description: ''};
+
+ constructor(private restApi: RestApi,
+ private editorService: EditorService) {
+
+ }
+
+ ngOnInit(): void {
+ this.loadOptions();
+ }
+
+ ngAfterViewInit() {
+ this.makeDraggable();
+ }
+
+ loadOptions() {
+ zip(this.editorService.getEpCategories(),
+ this.editorService.getEpaCategories(),
+ this.editorService.getEcCategories()).subscribe((results) => {
+ results[0] = this.sort(results[0]).filter(category => this.filterForExistingCategories(category));
+ results[1] = this.sort(results[1]).filter(category => this.filterForExistingCategories(category));
+ results[2] = this.sort(results[2]).filter(category => this.filterForExistingCategories(category));
+ this.allCategories.set(PipelineElementType.DataStream, results[0]);
+ this.allCategories.set(PipelineElementType.DataProcessor, results[1]);
+ this.allCategories.set(PipelineElementType.DataSink, results[2]);
+ this.categoriesReady = true;
+ });
+ }
+
+ filterForExistingCategories(category: PeCategory): boolean {
+ return this.allElements
+ .filter(element => element.category)
+ .find(element => element.category.find(elCat => elCat === category.code)) !== undefined ||
+ ((category.code === this.uncategorized.code) && this.allElements.find(element => (!element.category)) !== undefined);
+ }
+
+ sort(categories: PeCategory[]) {
+ return categories.sort((a, b) => {
+ return a.label.localeCompare(b.label);
+ });
+ }
+
+ makeDraggable() {
+ setTimeout(() => {
+ ($('.draggable-pipeline-element') as any).draggable({
+ revert: 'invalid',
+ helper: ((ev) => {
+ const draggable = $(ev.currentTarget).find('.draggable-icon-editor').first().clone();
+ const draggableContainer = $(draggable).find('.pe-container').first();
+ $(draggable).removeClass('draggable-icon-editor');
+ $(draggable).addClass('draggable-icon-drag');
+ $(draggableContainer).removeClass('pe-container');
+ $(draggableContainer).addClass('pe-container-drag');
+ return draggable.clone();
+ }),
+ stack: '.draggable-pipeline-element',
+ start(el, ui) {
+ ui.helper.appendTo('#content');
+ $('#outerAssemblyArea').css('border', '3px dashed #39b54a');
+ },
+ stop(el, ui) {
+ $('#outerAssemblyArea').css('border', '1px solid var(--color-bg-3)');
}
- this.activeCssClass = this.makeActiveCssClass(activeType);
- setTimeout(() => {
- this.makeDraggable();
- });
- }
-
- @Input()
- set currentElements(value: PipelineElementUnion[]) {
- this._currentElements = value;
- this.elementFilter = '';
- this.currentlyFilteredElements = this._currentElements;
- }
-
- get currentElements() {
- return this._currentElements;
- }
-
- makeActiveCssClass(elementType: PipelineElementType): string {
- return PipelineElementTypeUtils.toCssShortHand(elementType);
- }
-
- makeDraggable() {
- setTimeout(() => {
- ($('.draggable-icon') as any).draggable({
- revert: 'invalid',
- helper: 'clone',
- stack: '.draggable-icon',
- start (el, ui) {
- ui.helper.appendTo('#content');
- $('#outerAssemblyArea').css('border', '3px dashed #39b54a');
- },
- stop (el, ui) {
- $('#outerAssemblyArea').css('border', '3px solid rgb(156, 156, 156)');
- }
- });
- });
- }
+ });
+ });
+ }
+
+ toggleOpen(availableType: any): void {
+ availableType.open = !availableType.open;
+ this.makeDraggable();
+ }
+
+ startCreatePipelineTour() {
+ this.startTourEmitter.emit();
+ }
+
+ changeSorting(availableType: any,
+ sortMode: string) {
+ availableType.sort = sortMode;
+ this.makeDraggable();
+ }
}
diff --git a/ui/src/app/editor/components/pipeline-element/pipeline-element.component.css b/ui/src/app/editor/components/pipeline-element/pipeline-element.component.css
index 41ecef0..85b4348 100644
--- a/ui/src/app/editor/components/pipeline-element/pipeline-element.component.css
+++ b/ui/src/app/editor/components/pipeline-element/pipeline-element.component.css
@@ -14,4 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- */
\ No newline at end of file
+ */
+
+.text-small {
+ font-size: 8pt;
+}
diff --git a/ui/src/app/editor/components/pipeline-element/pipeline-element.component.html b/ui/src/app/editor/components/pipeline-element/pipeline-element.component.html
index 2a758a9..60a30dc 100644
--- a/ui/src/app/editor/components/pipeline-element/pipeline-element.component.html
+++ b/ui/src/app/editor/components/pipeline-element/pipeline-element.component.html
@@ -17,6 +17,6 @@
-->
<img [src]="image" *ngIf="showImage" style="{{iconSizeCss()}}">
-<span *ngIf="!showImage" class="element-text-icon">
+<span *ngIf="!showImage" [ngClass]="iconStandSize ? 'text-small<' : 'element-text-icon'">
{{iconText}}
</span>
diff --git a/ui/src/app/editor/components/pipeline-element/pipeline-element.component.ts b/ui/src/app/editor/components/pipeline-element/pipeline-element.component.ts
index 84fc539..5b28e74 100644
--- a/ui/src/app/editor/components/pipeline-element/pipeline-element.component.ts
+++ b/ui/src/app/editor/components/pipeline-element/pipeline-element.component.ts
@@ -78,7 +78,7 @@ export class PipelineElementComponent implements OnInit {
} else if (this.preview) {
return 'width:50px;height:50px;';
} else if (this.iconStandSize) {
- return 'width:50px;height:50px;margin-top:-5px;';
+ return 'width:30px;height:30px;';
} else {
return 'width:70px;height:70px;';
}
diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.css b/ui/src/app/editor/components/pipeline/pipeline.component.css
index 41ecef0..13cbc4a 100644
--- a/ui/src/app/editor/components/pipeline/pipeline.component.css
+++ b/ui/src/app/editor/components/pipeline/pipeline.component.css
@@ -14,4 +14,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
- */
\ No newline at end of file
+ */
diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.html b/ui/src/app/editor/components/pipeline/pipeline.component.html
index 768997a..5a2def9 100644
--- a/ui/src/app/editor/components/pipeline/pipeline.component.html
+++ b/ui/src/app/editor/components/pipeline/pipeline.component.html
@@ -15,7 +15,6 @@
~ limitations under the License.
~
-->
-
<div [attr.data-jtk-managed]="pipelineElement.payload.dom"
id="{{pipelineElement.payload.dom}}"
style="{{getElementCss(pipelineElement.settings)}}"
@@ -44,7 +43,7 @@
</div>
<pipeline-element [pipelineElement]="pipelineElement.payload" [preview]="preview"></pipeline-element>
</div>
- <pipeline-element-options *ngIf="!preview && currentMouseOverElement==pipelineElement.payload.dom"
+ <pipeline-element-options *ngIf="!preview"
(delete)="handleDeleteOption($event)"
(customize)="showCustomizeDialog($event)"
[currentMouseOverElement]="currentMouseOverElement"
@@ -63,4 +62,3 @@
</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 4508749..e7c9b0b 100644
--- a/ui/src/app/editor/components/pipeline/pipeline.component.ts
+++ b/ui/src/app/editor/components/pipeline/pipeline.component.ts
@@ -200,7 +200,7 @@ export class PipelineComponent implements OnInit, OnDestroy {
drop: (element, ui) => {
const pipelineElementId = ui.draggable.data('pe');
const pipelineElement: PipelineElementUnion = this.findPipelineElementByElementId(pipelineElementId);
- if (ui.draggable.hasClass('draggable-icon')) {
+ if (ui.draggable.hasClass('draggable-pipeline-element')) {
this.editorService.makePipelineAssemblyEmpty(false);
const newElementId = pipelineElement.elementId + ':' + this.jsplumbService.makeId(5);
const pipelineElementConfig = this.jsplumbService.createNewPipelineElementConfig(pipelineElement,
@@ -213,7 +213,7 @@ export class PipelineComponent implements OnInit, OnDestroy {
this.showMixedStreamAlert();
} else {
this.rawPipelineModel.push(pipelineElementConfig);
- if (ui.draggable.hasClass('set')) {
+ if (pipelineElementConfig.type === 'set') {
setTimeout(() => {
this.editorService.updateDataSet(pipelineElementConfig.payload).subscribe(data => {
(pipelineElementConfig.payload as SpDataSet).eventGrounding = data.eventGrounding;
@@ -225,9 +225,9 @@ export class PipelineComponent implements OnInit, OnDestroy {
false);
});
}, 0);
- } else if (ui.draggable.hasClass('stream')) {
+ } else if (pipelineElementConfig.type === 'stream') {
this.checkTopicModel(pipelineElementConfig);
- } else if (ui.draggable.hasClass('sepa')) {
+ } else if (pipelineElementConfig.type === 'sepa') {
setTimeout(() => {
this.jsplumbService.dataProcessorDropped(
pipelineElementConfig.payload.dom,
@@ -236,7 +236,7 @@ export class PipelineComponent implements OnInit, OnDestroy {
false
);
}, 10);
- } else if (ui.draggable.hasClass('action')) {
+ } else if (pipelineElementConfig.type === 'action') {
setTimeout(() => {
this.jsplumbService.dataSinkDropped(
pipelineElementConfig.payload.dom,
diff --git a/ui/src/app/editor/editor.component.html b/ui/src/app/editor/editor.component.html
index 3ec9970..0a25281 100644
--- a/ui/src/app/editor/editor.component.html
+++ b/ui/src/app/editor/editor.component.html
@@ -17,43 +17,25 @@
-->
<div fxLayout="column" class="page-container">
- <div fxLayout="row" class="border sp-tab-bg editor-canvas-options" *ngIf="!pipelineCanvasMaximized">
- <div fxFlex="100" fxLayout="row" class="page-container-nav">
- <div fxFlex fxLayoutAlign="start center" [attr.id]="'peType'">
- <mat-tab-group [selectedIndex]="selectedIndex"
- (selectedIndexChange)="selectPipelineElements($event)" color="accent">
- <mat-tab
- *ngFor="let tab of tabs"
- [attr.id]="tab.shorthand"
- label="{{tab.title}}"></mat-tab>
- </mat-tab-group>
+ <div class="fixed-height" fxLayout="row" fxFlex="100">
+ <div fxFlex="250px">
+ <div fxFlex="100" fxLayout="column" fxLayoutAlign="center center" *ngIf="!allElementsLoaded">
+ <mat-spinner [diameter]="30" color="accent" mode="indeterminate"></mat-spinner>
+ <p>Loading pipeline elements...</p>
</div>
- <div fxFlex="30" fxLayout="row" fxLayoutAlign="end center" style="padding-left:10px;font-size:14px;line-height:24px;">
- <button mat-button mat-icon-button (click)="startCreatePipelineTour()"
- [matTooltip]="'Tutorial'" style="margin-right: 5px;">
- <i class="material-icons text-color">
- school
- </i>
- </button>
+ <div id="shepherd-test"
+ style="padding:0px;border-bottom:1px solid #ffffff;margin-right: 5px;">
+ <pipeline-element-icon-stand
+ [allElements]="allElements"
+ *ngIf="allElementsLoaded"
+ (startTourEmitter)="startCreatePipelineTour()">
+ </pipeline-element-icon-stand>
</div>
</div>
- </div>
-
- <div class="fixed-height" fxLayout="column" fxFlex="100">
- <div id="shepherd-test"
- style="padding:0px;border-bottom:1px solid #ffffff">
- <pipeline-element-icon-stand
- [activeType]="activeType"
- [currentElements]="currentElements"
- *ngIf="allElementsLoaded && !pipelineCanvasMaximized">
- </pipeline-element-icon-stand>
- </div>
- <pipeline-assembly fxFlex="1"
- class="pipeline-assembly-margin"
+ <pipeline-assembly fxFlex="100" style="margin-left: 10px;"
[rawPipelineModel]="rawPipelineModel"
[allElements]="allElements"
- [currentModifiedPipelineId]="currentModifiedPipelineId"
- (pipelineCanvasMaximizedEmitter)="togglePipelineCanvasMode($event)">
+ [currentModifiedPipelineId]="currentModifiedPipelineId">
</pipeline-assembly>
</div>
</div>
diff --git a/ui/src/app/editor/editor.component.scss b/ui/src/app/editor/editor.component.scss
index d21fab4..58b8fb3 100644
--- a/ui/src/app/editor/editor.component.scss
+++ b/ui/src/app/editor/editor.component.scss
@@ -30,10 +30,6 @@
border: 1px solid var(--color-bg-2);
}
-.pipeline-assembly-margin {
- margin-top: 10px;
-}
-
.editor-canvas-options {
padding: 0;
background-color: var(--color-bg-1);
diff --git a/ui/src/app/editor/editor.component.ts b/ui/src/app/editor/editor.component.ts
index f179da0..454c9ac 100644
--- a/ui/src/app/editor/editor.component.ts
+++ b/ui/src/app/editor/editor.component.ts
@@ -18,224 +18,149 @@
import { Component, OnInit } from '@angular/core';
import { EditorService } from './services/editor.service';
-import {
- DataProcessorInvocation,
- DataSinkInvocation,
- DataSourceDescription,
- SpDataSet,
- SpDataStream,
- PipelineElementService
-} from '@streampipes/platform-services';
-import {
- PipelineElementConfig,
- PipelineElementIdentifier,
- PipelineElementUnion,
- TabsModel
-} from './model/editor.model';
+import { DataSourceDescription, PipelineElementService, SpDataStream } from '@streampipes/platform-services';
+import { PipelineElementConfig, PipelineElementUnion } from './model/editor.model';
import { PanelType } from '../core-ui/dialog/base-dialog/base-dialog.model';
import { WelcomeTourComponent } from './dialog/welcome-tour/welcome-tour.component';
import { DialogService } from '../core-ui/dialog/base-dialog/base-dialog.service';
import { MissingElementsForTutorialComponent } from './dialog/missing-elements-for-tutorial/missing-elements-for-tutorial.component';
import { ShepherdService } from '../services/tour/shepherd.service';
import { ActivatedRoute } from '@angular/router';
-import { EditorConstants } from './constants/editor.constants';
import { AuthService } from '../services/auth.service';
+import { zip } from 'rxjs';
@Component({
- selector: 'editor',
- templateUrl: './editor.component.html',
- styleUrls: ['./editor.component.scss']
+ selector: 'editor',
+ templateUrl: './editor.component.html',
+ styleUrls: ['./editor.component.scss']
})
export class EditorComponent implements OnInit {
- selectedIndex = 1;
- activeType: PipelineElementIdentifier = EditorConstants.DATA_STREAM_IDENTIFIER;
- activeShorthand: string;
-
- availableDataSets: SpDataSet[] = [];
- availableDataStreams: SpDataStream[] = [];
- availableDataProcessors: DataProcessorInvocation[] = [];
- availableDataSinks: DataSinkInvocation[] = [];
-
- allElements: PipelineElementUnion[] = [];
- currentElements: (SpDataStream | DataProcessorInvocation | DataSinkInvocation)[] = [];
-
- rawPipelineModel: PipelineElementConfig[] = [];
- currentModifiedPipelineId: string;
-
- elementsLoaded = [false, false, false];
- allElementsLoaded = false;
-
- requiredStreamForTutorialAppId: any = 'org.apache.streampipes.sources.simulator.flowrate1';
- requiredProcessorForTutorialAppId: any = 'org.apache.streampipes.processors.filters.jvm.numericalfilter';
- requiredSinkForTutorialAppId: any = 'org.apache.streampipes.sinks.internal.jvm.dashboard';
- missingElementsForTutorial: any = [];
-
- pipelineCanvasMaximized = false;
-
- isTutorialOpen = false;
-
- tabs: TabsModel[] = [
- {
- title: 'Data Sets',
- type: EditorConstants.DATA_SET_IDENTIFIER,
- shorthand: 'set'
- },
- {
- title: 'Data Streams',
- type: EditorConstants.DATA_STREAM_IDENTIFIER,
- shorthand: 'stream'
- },
- {
- title: 'Data Processors',
- type: EditorConstants.DATA_PROCESSOR_IDENTIFIER,
- shorthand: 'sepa'
- },
- {
- title: 'Data Sinks',
- type: EditorConstants.DATA_SINK_IDENTIFIER,
- shorthand: 'action'
- }
- ];
-
- constructor(private editorService: EditorService,
- private pipelineElementService: PipelineElementService,
- private authService: AuthService,
- private dialogService: DialogService,
- private shepherdService: ShepherdService,
- private activatedRoute: ActivatedRoute) {
- }
-
- ngOnInit() {
- this.activatedRoute.queryParams.subscribe(params => {
- if (params['pipeline']) {
- this.currentModifiedPipelineId = params['pipeline'];
- }
- });
- this.pipelineElementService.getDataProcessors().subscribe(processors => {
- this.availableDataProcessors = processors;
- this.allElements = this.allElements.concat(processors);
- this.afterPipelineElementLoaded(0);
+ allElements: PipelineElementUnion[] = [];
+
+ rawPipelineModel: PipelineElementConfig[] = [];
+ currentModifiedPipelineId: string;
+
+ allElementsLoaded = false;
+
+ requiredStreamForTutorialAppId: any = 'org.apache.streampipes.sources.simulator.flowrate1';
+ requiredProcessorForTutorialAppId: any = 'org.apache.streampipes.processors.filters.jvm.numericalfilter';
+ requiredSinkForTutorialAppId: any = 'org.apache.streampipes.sinks.internal.jvm.dashboard';
+ missingElementsForTutorial: any = [];
+
+ isTutorialOpen = false;
+
+ constructor(private editorService: EditorService,
+ private pipelineElementService: PipelineElementService,
+ private authService: AuthService,
+ private dialogService: DialogService,
+ private shepherdService: ShepherdService,
+ private activatedRoute: ActivatedRoute) {
+ }
+
+ ngOnInit() {
+ this.activatedRoute.queryParams.subscribe(params => {
+ if (params['pipeline']) {
+ this.currentModifiedPipelineId = params['pipeline'];
+ }
+ });
+ zip(this.pipelineElementService.getDataStreams(),
+ this.pipelineElementService.getDataProcessors(),
+ this.pipelineElementService.getDataSinks()).subscribe(response => {
+ this.allElements = this.allElements
+ .concat(response[0])
+ .concat(response[1])
+ .concat(response[2])
+ .sort((a, b) => {
+ return a.name.localeCompare(b.name);
});
- this.pipelineElementService.getDataStreams().subscribe(streams => {
- // let allStreams = this.collectStreams(sources);
- this.availableDataStreams = streams.filter(s => !(s instanceof SpDataSet));
- this.availableDataSets = streams
- .filter(s => s instanceof SpDataSet)
- .map(s => s as SpDataSet);
- this.allElements = this.allElements.concat(this.availableDataStreams);
- this.allElements = this.allElements.concat(this.availableDataSets);
-
- this.selectPipelineElements(1);
- this.afterPipelineElementLoaded(1);
+ this.allElementsLoaded = true;
+ this.checkForTutorial();
+ });
+ }
+
+ checkForTutorial() {
+ const currentUser = this.authService.getCurrentUser();
+ if (currentUser.showTutorial && !this.isTutorialOpen) {
+ if (this.requiredPipelineElementsForTourPresent()) {
+ this.isTutorialOpen = true;
+ this.dialogService.open(WelcomeTourComponent, {
+ panelType: PanelType.STANDARD_PANEL,
+ title: 'Welcome to StreamPipes',
+ data: {
+ 'userInfo': currentUser
+ }
});
- this.pipelineElementService.getDataSinks().subscribe(sinks => {
- this.availableDataSinks = sinks;
- 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.checkForTutorial();
- }
- }
-
- checkForTutorial() {
- const currentUser = this.authService.getCurrentUser();
- if (currentUser.showTutorial && !this.isTutorialOpen) {
- if (this.requiredPipelineElementsForTourPresent()) {
- this.isTutorialOpen = true;
- this.dialogService.open(WelcomeTourComponent, {
- panelType: PanelType.STANDARD_PANEL,
- title: 'Welcome to StreamPipes',
- data: {
- 'userInfo': currentUser
- }
- });
- }
- }
- }
-
- collectStreams(sources: DataSourceDescription[]): SpDataStream[] {
- const streams: SpDataStream[] = [];
- sources.forEach(source => {
- source.spDataStreams.forEach(stream => {
- streams.push(stream);
- });
+ }
+
+ collectStreams(sources: DataSourceDescription[]): SpDataStream[] {
+ const streams: SpDataStream[] = [];
+ sources.forEach(source => {
+ source.spDataStreams.forEach(stream => {
+ streams.push(stream);
+ });
+ });
+ return streams;
+ }
+
+ selectPipelineElements(index: number) {
+ // this.shepherdService.trigger('select-' + this.activeShorthand);
+ }
+
+ startCreatePipelineTour() {
+ if (this.requiredPipelineElementsForTourPresent()) {
+ this.shepherdService.startCreatePipelineTour();
+ } else {
+ this.missingElementsForTutorial = [];
+ if (!this.requiredStreamForTourPresent()) {
+ this.missingElementsForTutorial.push({'name': 'Flow Rate 1', 'appId': this.requiredStreamForTutorialAppId});
+ }
+ if (!this.requiredProcessorForTourPresent()) {
+ this.missingElementsForTutorial.push({
+ 'name': 'Numerical Filter',
+ 'appId': this.requiredProcessorForTutorialAppId
});
- return streams;
- }
-
- selectPipelineElements(index: number) {
- this.selectedIndex = index;
- this.activeType = this.tabs[index].type;
- this.activeShorthand = this.tabs[index].shorthand;
- this.currentElements = this.allElements
- .filter(pe => pe['@class'] === this.activeType)
- .sort((a, b) => {
- return a.name.localeCompare(b.name);
- });
- this.shepherdService.trigger('select-' + this.activeShorthand);
- }
-
- startCreatePipelineTour() {
- if (this.requiredPipelineElementsForTourPresent()) {
- this.shepherdService.startCreatePipelineTour();
- } else {
- this.missingElementsForTutorial = [];
- if (!this.requiredStreamForTourPresent()) {
- this.missingElementsForTutorial.push({'name' : 'Flow Rate 1', 'appId' : this.requiredStreamForTutorialAppId });
- }
- if (!this.requiredProcessorForTourPresent()) {
- this.missingElementsForTutorial.push({'name' : 'Numerical Filter', 'appId' : this.requiredProcessorForTutorialAppId});
- }
- if (!this.requiredSinkForTourPresent()) {
- this.missingElementsForTutorial.push({'name' : 'Dashboard Sink', 'appId' : this.requiredSinkForTutorialAppId});
- }
-
- this.dialogService.open(MissingElementsForTutorialComponent, {
- panelType: PanelType.STANDARD_PANEL,
- title: 'Tutorial requires pipeline elements',
- data: {
- 'missingElementsForTutorial': this.missingElementsForTutorial
- }
- });
+ }
+ if (!this.requiredSinkForTourPresent()) {
+ this.missingElementsForTutorial.push({'name': 'Dashboard Sink', 'appId': this.requiredSinkForTutorialAppId});
+ }
+
+ this.dialogService.open(MissingElementsForTutorialComponent, {
+ panelType: PanelType.STANDARD_PANEL,
+ title: 'Tutorial requires pipeline elements',
+ data: {
+ 'missingElementsForTutorial': this.missingElementsForTutorial
}
+ });
}
-
- requiredPipelineElementsForTourPresent() {
- return this.requiredStreamForTourPresent() &&
- this.requiredProcessorForTourPresent() &&
- this.requiredSinkForTourPresent();
- }
-
- requiredStreamForTourPresent() {
- return this.requiredPeForTourPresent(this.allElements,
- this.requiredStreamForTutorialAppId);
- }
-
- requiredProcessorForTourPresent() {
- return this.requiredPeForTourPresent(this.allElements,
- this.requiredProcessorForTutorialAppId);
- }
-
- requiredSinkForTourPresent() {
- return this.requiredPeForTourPresent(this.allElements,
- this.requiredSinkForTutorialAppId);
- }
-
- requiredPeForTourPresent(list, appId) {
- return list && list.some(el => {
- return el.appId === appId;
- });
- }
-
- togglePipelineCanvasMode(maximize: boolean) {
- this.pipelineCanvasMaximized = maximize;
- }
+ }
+
+ requiredPipelineElementsForTourPresent() {
+ return this.requiredStreamForTourPresent() &&
+ this.requiredProcessorForTourPresent() &&
+ this.requiredSinkForTourPresent();
+ }
+
+ requiredStreamForTourPresent() {
+ return this.requiredPeForTourPresent(this.allElements,
+ this.requiredStreamForTutorialAppId);
+ }
+
+ requiredProcessorForTourPresent() {
+ return this.requiredPeForTourPresent(this.allElements,
+ this.requiredProcessorForTutorialAppId);
+ }
+
+ requiredSinkForTourPresent() {
+ return this.requiredPeForTourPresent(this.allElements,
+ this.requiredSinkForTutorialAppId);
+ }
+
+ requiredPeForTourPresent(list, appId) {
+ return list && list.some(el => {
+ return el.appId === appId;
+ });
+ }
}
diff --git a/ui/src/app/editor/editor.module.ts b/ui/src/app/editor/editor.module.ts
index 8caf08e..cf19419 100644
--- a/ui/src/app/editor/editor.module.ts
+++ b/ui/src/app/editor/editor.module.ts
@@ -67,6 +67,11 @@ import { PipelineElementPreviewComponent } from './components/pipeline-element-p
import { PipelineElementDiscoveryComponent } from './dialog/pipeline-element-discovery/pipeline-element-discovery.component';
import { PipelineStyleService } from './services/pipeline-style.service';
import { PlatformServicesModule } from '@streampipes/platform-services';
+import { PipelineElementIconStandRowComponent } from './components/pipeline-element-icon-stand-row/pipeline-element-icon-stand-row.component';
+import { PipelineElementTypeFilterPipe } from './services/pipeline-element-type-filter.pipe';
+import { PipelineElementNameFilterPipe } from "./services/pipeline-element-name-filter.pipe";
+import { PipelineElementGroupFilterPipe } from "./services/pipeline-element-group-filter.pipe";
+
@NgModule({
imports: [
@@ -102,10 +107,14 @@ import { PlatformServicesModule } from '@streampipes/platform-services';
PipelineElementDiscoveryComponent,
PipelineElementDocumentationComponent,
PipelineElementIconStandComponent,
+ PipelineElementIconStandRowComponent,
+ PipelineElementGroupFilterPipe,
+ PipelineElementNameFilterPipe,
PipelineElementOptionsComponent,
PipelineElementPreviewComponent,
PipelineElementRecommendationComponent,
PipelineElementTemplateConfigComponent,
+ PipelineElementTypeFilterPipe,
PipelineComponent,
PropertySelectionComponent,
SavePipelineComponent,
diff --git a/ui/src/app/editor/model/editor.model.ts b/ui/src/app/editor/model/editor.model.ts
index 8cc5059..45945be 100644
--- a/ui/src/app/editor/model/editor.model.ts
+++ b/ui/src/app/editor/model/editor.model.ts
@@ -16,12 +16,7 @@
*
*/
-import {
- DataProcessorInvocation,
- DataSinkInvocation,
- SpDataSet,
- SpDataStream
-} from '@streampipes/platform-services';
+import { DataProcessorInvocation, DataSinkInvocation, SpDataSet, SpDataStream } from '@streampipes/platform-services';
import { InjectionToken } from '@angular/core';
export interface PipelineElementHolder {
@@ -91,3 +86,9 @@ export type PipelineElementIdentifier = 'org.apache.streampipes.model.SpDataStre
| 'org.apache.streampipes.model.SpDataSet'
| 'org.apache.streampipes.model.graph.DataProcessorInvocation'
| 'org.apache.streampipes.model.graph.DataSinkInvocation';
+
+export interface PeCategory {
+ code: string;
+ label: string;
+ description: string;
+}
diff --git a/ui/src/app/editor/services/editor.service.ts b/ui/src/app/editor/services/editor.service.ts
index 7611431..659b081 100644
--- a/ui/src/app/editor/services/editor.service.ts
+++ b/ui/src/app/editor/services/editor.service.ts
@@ -27,12 +27,12 @@ import {
PipelineElementRecommendationMessage,
PipelineModificationMessage,
PipelinePreviewModel,
+ PlatformServicesCommons,
SpDataSet,
- SpDataStream,
- PlatformServicesCommons
+ SpDataStream
} from '@streampipes/platform-services';
import { Observable, Subject } from 'rxjs';
-import { PipelineElementConfig, PipelineElementUnion } from '../model/editor.model';
+import { PeCategory, PipelineElementConfig, PipelineElementUnion } from '../model/editor.model';
import { PanelType } from '../../core-ui/dialog/base-dialog/base-dialog.model';
import { DialogService } from '../../core-ui/dialog/base-dialog/base-dialog.service';
import { HelpComponent } from '../dialog/help/help.component';
@@ -106,16 +106,19 @@ export class EditorService {
}
}
- getEpCategories() {
- return this.http.get(this.platformServicesCommons.apiBasePath + '/categories/ep');
+ getEpCategories(): Observable<PeCategory[]> {
+ return this.http.get(this.platformServicesCommons.apiBasePath + '/categories/ep')
+ .pipe(map(response => response as PeCategory[]));
}
- getEpaCategories() {
- return this.http.get(this.platformServicesCommons.apiBasePath + '/categories/epa');
+ getEpaCategories(): Observable<PeCategory[]> {
+ return this.http.get(this.platformServicesCommons.apiBasePath + '/categories/epa')
+ .pipe(map(response => response as PeCategory[]));
}
- getEcCategories() {
- return this.http.get(this.platformServicesCommons.apiBasePath + '/categories/ec');
+ getEcCategories(): Observable<PeCategory[]> {
+ return this.http.get(this.platformServicesCommons.apiBasePath + '/categories/ec')
+ .pipe(map(response => response as PeCategory[]));
}
updateCachedPipeline(rawPipelineModel: any) {
diff --git a/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.scss b/ui/src/app/editor/services/pipeline-element-group-filter.pipe.ts
similarity index 56%
copy from ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.scss
copy to ui/src/app/editor/services/pipeline-element-group-filter.pipe.ts
index d5a2288..29e3ff7 100644
--- a/ui/src/app/editor/components/pipeline-element-icon-stand/pipeline-element-icon-stand.component.scss
+++ b/ui/src/app/editor/services/pipeline-element-group-filter.pipe.ts
@@ -16,23 +16,21 @@
*
*/
-@import '../../../../scss/_variables.scss';
+import { Pipe, PipeTransform } from '@angular/core';
+import { PeCategory, PipelineElementUnion } from '../model/editor.model';
-.menu-text-color {
- color: var(--color-accent);
- display: flex;
- align-items: center;
-}
+@Pipe({name: 'pipelineElementGroup'})
+export class PipelineElementGroupFilterPipe implements PipeTransform {
-.icon-stand {
- max-height: 200px;
- padding-bottom: 1%;
- overflow-y: auto;
- border-top: 0px;
- background: var(--color-bg-1);
-}
+ transform(pipelineElements: PipelineElementUnion[],
+ category: PeCategory): PipelineElementUnion[] {
+ return pipelineElements.filter(pe => {
+ if ((!pe.category || pe.category.length === 0) && category.code === 'UNCATEGORIZED') {
+ return true;
+ } else {
+ return pe.category.find(c => c === category.code) !== undefined;
+ }
+ });
+ }
-.border {
- border: 1px solid var(--color-bg-2);
- border-top: 0;
}
diff --git a/ui/src/app/editor/editor.component.scss b/ui/src/app/editor/services/pipeline-element-name-filter.pipe.ts
similarity index 57%
copy from ui/src/app/editor/editor.component.scss
copy to ui/src/app/editor/services/pipeline-element-name-filter.pipe.ts
index d21fab4..2d27fc1 100644
--- a/ui/src/app/editor/editor.component.scss
+++ b/ui/src/app/editor/services/pipeline-element-name-filter.pipe.ts
@@ -16,25 +16,22 @@
*
*/
-@import '../../scss/variables';
+import { Pipe, PipeTransform } from '@angular/core';
+import { PipelineElementUnion } from '../model/editor.model';
-.text-color {
- color: var(--color-accent);
-}
+@Pipe({name: 'pipelineElementName'})
+export class PipelineElementNameFilterPipe implements PipeTransform {
-.page-container {
- border: 0;
-}
+ transform(pipelineElements: PipelineElementUnion[],
+ filter: string): PipelineElementUnion[] {
+ return pipelineElements.filter(pe => {
+ return this.matchesText(filter, pe);
+ });
+ }
-.border {
- border: 1px solid var(--color-bg-2);
-}
-
-.pipeline-assembly-margin {
- margin-top: 10px;
-}
+ matchesText(filter: string,
+ el: PipelineElementUnion): boolean {
+ return filter === '' || el.name.toLowerCase().includes(filter.toLowerCase());
+ }
-.editor-canvas-options {
- padding: 0;
- background-color: var(--color-bg-1);
}
diff --git a/ui/src/app/editor/editor.component.scss b/ui/src/app/editor/services/pipeline-element-type-filter.pipe.ts
similarity index 56%
copy from ui/src/app/editor/editor.component.scss
copy to ui/src/app/editor/services/pipeline-element-type-filter.pipe.ts
index d21fab4..3a8507c 100644
--- a/ui/src/app/editor/editor.component.scss
+++ b/ui/src/app/editor/services/pipeline-element-type-filter.pipe.ts
@@ -16,25 +16,19 @@
*
*/
-@import '../../scss/variables';
+import { Pipe, PipeTransform } from '@angular/core';
+import { PipelineElementType, PipelineElementUnion } from '../model/editor.model';
+import { PipelineElementTypeUtils } from '../utils/editor.utils';
-.text-color {
- color: var(--color-accent);
-}
-
-.page-container {
- border: 0;
-}
+@Pipe({name: 'pipelineElementType'})
+export class PipelineElementTypeFilterPipe implements PipeTransform {
-.border {
- border: 1px solid var(--color-bg-2);
-}
-
-.pipeline-assembly-margin {
- margin-top: 10px;
-}
+ transform(pipelineElements: PipelineElementUnion[],
+ allowedTypes: PipelineElementType[]): PipelineElementUnion[] {
+ return pipelineElements.filter(pe => {
+ const peType = PipelineElementTypeUtils.fromClassName(pe['@class']);
+ return allowedTypes.find(t => t === peType) !== undefined;
+ });
+ }
-.editor-canvas-options {
- padding: 0;
- background-color: var(--color-bg-1);
}
diff --git a/ui/src/app/services/get-element-icon-text.service.ts b/ui/src/app/services/get-element-icon-text.service.ts
index ba833f3..eeff6a6 100644
--- a/ui/src/app/services/get-element-icon-text.service.ts
+++ b/ui/src/app/services/get-element-icon-text.service.ts
@@ -25,12 +25,12 @@ export class ElementIconText {
getElementIconText(s) {
let result = '';
- if (s.length <= 4) {
+ if (s.length <= 3) {
result = s;
} else {
const words = s.split(' ');
words.forEach((word, i) => {
- if (i < 4) {
+ if (i < 3) {
result += word.charAt(0);
}
});
diff --git a/ui/src/scss/sp/colors.scss b/ui/src/scss/sp/colors.scss
index 852dfd0..60379b9 100644
--- a/ui/src/scss/sp/colors.scss
+++ b/ui/src/scss/sp/colors.scss
@@ -112,3 +112,4 @@
.sp-tab-bg {
background-color: var(--color-bg-1);
}
+
diff --git a/ui/src/scss/sp/layout.scss b/ui/src/scss/sp/layout.scss
index f664ae2..bc20f94 100644
--- a/ui/src/scss/sp/layout.scss
+++ b/ui/src/scss/sp/layout.scss
@@ -116,7 +116,7 @@
.page-container-nav {
line-height:24px;
height: 50px;
- border-bottom:1px solid var(--color-tab-border);
+ border-bottom:2px solid var(--color-bg-3);
}
.text-center {
diff --git a/ui/src/scss/sp/main.scss b/ui/src/scss/sp/main.scss
index 326c2dd..1bde8fe 100644
--- a/ui/src/scss/sp/main.scss
+++ b/ui/src/scss/sp/main.scss
@@ -37,6 +37,12 @@ body {
font-family: 'Roboto', 'Arial', sans-serif !important;
height: auto !important;
width: 100%;
+
+ --color-set: #{$sp-color-set};
+ --color-stream: #{$sp-color-stream};
+ --color-processor: #{$sp-color-processor};
+ --color-sink: #{$sp-color-sink};
+ --color-tab-border: var(--color-bg-3);
}
pre.version {
@@ -892,6 +898,7 @@ md-select.md-default-theme .md-select-value.md-select-placeholder, md-select .md
/* border-bottom: 2px solid rgb(63,81,181); */
color: black;
background: var(--color-bg-1);
+ border-bottom: 1px solid var(--color-bg-3);
padding: 0px;
/* margin-top: 1%; */
}
diff --git a/ui/src/scss/sp/pipeline-element-options.scss b/ui/src/scss/sp/pipeline-element-options.scss
index 813ed34..014ca98 100644
--- a/ui/src/scss/sp/pipeline-element-options.scss
+++ b/ui/src/scss/sp/pipeline-element-options.scss
@@ -66,11 +66,8 @@
.help-button-icon-stand {
display: block;
cursor: pointer;
- position: relative;
- left: 20px;
- top: 40px;
- height: 40px;
- width: 40px;
+ height: 20px;
+ width: 20px;
border-radius: 50%;
background-color: $sp-color-accent;
color: rgba(255, 255, 255, 0.75);