This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch 3121-add-live-preview-to-pipeline-details
in repository https://gitbox.apache.org/repos/asf/streampipes.git
The following commit(s) were added to
refs/heads/3121-add-live-preview-to-pipeline-details by this push:
new c93729f676 feat(#3121): Add live preview to pipeline details
c93729f676 is described below
commit c93729f67691d73ca8a8990fc40e97f0c938ba69
Author: Dominik Riemer <[email protected]>
AuthorDate: Fri Aug 9 20:58:50 2024 +0200
feat(#3121): Add live preview to pipeline details
---
.../streampipes/rest/impl/PipelineMonitoring.java | 8 ++++-
.../connect/editAdapterSettingsAndPipeline.spec.ts | 8 ++---
.../src/lib/apis/pipeline-monitoring.service.ts | 9 ++++--
.../pipeline-assembly-drawing-area.component.ts | 4 +--
.../pipeline-assembly.component.ts | 2 +-
.../pipeline-element-options.component.html | 6 ----
.../pipeline-element-options.component.ts | 6 ++--
.../dropped-pipeline-element.component.html | 3 ++
.../pipeline-details-toolbar.component.html | 13 ++++++++
.../pipeline-details-toolbar.component.ts | 6 ++++
.../preview/pipeline-preview.component.html | 3 +-
.../preview/pipeline-preview.component.ts | 9 ++++++
.../pipeline-details.component.html | 3 ++
.../pipeline-details/pipeline-details.component.ts | 37 ++++++++++++++++------
.../pipeline-overview.component.html | 2 +-
15 files changed, 87 insertions(+), 32 deletions(-)
diff --git
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineMonitoring.java
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineMonitoring.java
index 450643499a..f772754391 100644
---
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineMonitoring.java
+++
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineMonitoring.java
@@ -18,6 +18,7 @@
package org.apache.streampipes.rest.impl;
import
org.apache.streampipes.manager.monitoring.pipeline.ExtensionsLogProvider;
+import
org.apache.streampipes.manager.monitoring.pipeline.ExtensionsServiceLogExecutor;
import org.apache.streampipes.model.monitoring.SpLogEntry;
import org.apache.streampipes.model.monitoring.SpMetricsEntry;
@@ -26,6 +27,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@@ -43,7 +45,11 @@ public class PipelineMonitoring extends
AbstractMonitoringResource {
@GetMapping(value = "/pipeline/{pipelineId}/metrics", produces =
MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Map<String, SpMetricsEntry>> getMetricsInfoForPipeline(
- @PathVariable("pipelineId") String pipelineId) {
+ @PathVariable("pipelineId") String pipelineId,
+ @RequestParam(value = "forceUpdate", required = false, defaultValue =
"false") boolean forceUpdate) {
+ if (forceUpdate) {
+ new ExtensionsServiceLogExecutor().triggerUpdate();
+ }
return
ok(ExtensionsLogProvider.INSTANCE.getMetricInfosForPipeline(pipelineId));
}
diff --git a/ui/cypress/tests/connect/editAdapterSettingsAndPipeline.spec.ts
b/ui/cypress/tests/connect/editAdapterSettingsAndPipeline.spec.ts
index da5089a227..c30f355474 100644
--- a/ui/cypress/tests/connect/editAdapterSettingsAndPipeline.spec.ts
+++ b/ui/cypress/tests/connect/editAdapterSettingsAndPipeline.spec.ts
@@ -72,7 +72,7 @@ describe('Test Edit Adapter and Pipeline', () => {
}).should('be.visible');
ConnectBtns.updateAndMigratePipelines().click();
ConnectUtils.closeAdapterPreview();
- cy.wait(1000);
+ cy.wait(2000);
// Go to pipelines, check for warning icon and edit pipeline
PipelineUtils.goToPipelines();
@@ -90,9 +90,9 @@ describe('Test Edit Adapter and Pipeline', () => {
cy.dataCy('number-mapping').contains('pressure').click({ force: true
});
cy.dataCy('sp-element-configuration-save').click({ force: true });
cy.dataCy('sp-editor-save-pipeline').click();
- cy.dataCy('sp-editor-save').click();
- cy.dataCy('start-pipeline-button').click();
- cy.dataCy('sp-pipeline-dialog-close').click();
+
cy.dataCy('sp-editor-checkbox-navigate-to-overview').children().click();
+ cy.dataCy('sp-editor-apply').click();
+ cy.dataCy('sp-navigate-to-pipeline-overview').click();
// Visit dashboard
cy.wait(1000);
diff --git
a/ui/projects/streampipes/platform-services/src/lib/apis/pipeline-monitoring.service.ts
b/ui/projects/streampipes/platform-services/src/lib/apis/pipeline-monitoring.service.ts
index 3e7addffb1..dc336c6d1e 100644
---
a/ui/projects/streampipes/platform-services/src/lib/apis/pipeline-monitoring.service.ts
+++
b/ui/projects/streampipes/platform-services/src/lib/apis/pipeline-monitoring.service.ts
@@ -17,7 +17,7 @@
*/
import { Injectable } from '@angular/core';
-import { HttpClient } from '@angular/common/http';
+import { HttpClient, HttpContext } from '@angular/common/http';
import { Observable } from 'rxjs';
import {
PipelineMonitoringInfo,
@@ -27,6 +27,7 @@ import {
import { PlatformServicesCommons } from './commons.service';
import { map } from 'rxjs/operators';
import { AbstractMonitoringService } from './abstract-monitoring.service';
+import { NGX_LOADING_BAR_IGNORED } from '@ngx-loading-bar/http-client';
@Injectable({
providedIn: 'root',
@@ -49,9 +50,13 @@ export class PipelineMonitoringService extends
AbstractMonitoringService {
getMetricsInfoForPipeline(
pipelineId: string,
+ forceUpdate = false,
): Observable<Record<string, SpMetricsEntry>> {
return this.http
- .get(this.metricsUrl(pipelineId))
+ .get(this.metricsUrl(pipelineId), {
+ params: { forceUpdate },
+ context: new HttpContext().set(NGX_LOADING_BAR_IGNORED, true),
+ })
.pipe(map(response => response as Record<string, SpMetricsEntry>));
}
diff --git
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.ts
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.ts
index 5169abe08e..c461f67e10 100644
---
a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.ts
+++
b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component.ts
@@ -144,7 +144,7 @@ export class PipelineAssemblyDrawingAreaComponent
implements OnInit {
});
}
- initiatePipelineElementPreview() {
+ togglePipelineElementLivePreview() {
if (!this.previewModeActive) {
const pipeline = this.objectProvider.makePipeline(
this.rawPipelineModel,
@@ -176,7 +176,7 @@ export class PipelineAssemblyDrawingAreaComponent
implements OnInit {
.subscribe(() => {
this.previewModeActive = false;
if (resume) {
- this.initiatePipelineElementPreview();
+ this.togglePipelineElementLivePreview();
}
});
}
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 3486572eaa..bda501b04a 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
@@ -147,7 +147,7 @@ export class PipelineAssemblyComponent implements
AfterViewInit {
togglePreview(): void {
this.previewModeActive = !this.previewModeActive;
- this.drawingAreaComponent.initiatePipelineElementPreview();
+ this.drawingAreaComponent.togglePipelineElementLivePreview();
}
triggerCacheUpdate(): void {
diff --git
a/ui/src/app/editor/components/pipeline-element-options/pipeline-element-options.component.html
b/ui/src/app/editor/components/pipeline-element-options/pipeline-element-options.component.html
index 22b03f6b1b..2951de354d 100644
---
a/ui/src/app/editor/components/pipeline-element-options/pipeline-element-options.component.html
+++
b/ui/src/app/editor/components/pipeline-element-options/pipeline-element-options.component.html
@@ -124,12 +124,6 @@
</button>
</span>
</div>
- <div
- class="editor-pe-info"
- [ngClass]="'pe-info-' + pipelineElementCssType"
- >
- {{ pipelineElement.payload.name }}
- </div>
</div>
<sp-pipeline-element-recommendation
[rawPipelineModel]="rawPipelineModel"
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 ea1e5dc40c..1b77d8958a 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
@@ -56,7 +56,6 @@ export class PipelineElementOptionsComponent implements
OnInit, OnDestroy {
possibleElements: PipelineElementUnion[];
recommendedElements: PipelineElementUnion[];
recommendationsShown: any = false;
- pipelineElementCssType: string;
isDataSource: boolean;
@Input()
@@ -124,7 +123,6 @@ export class PipelineElementOptionsComponent implements
OnInit, OnDestroy {
}
},
);
- this.pipelineElementCssType = this.pipelineElement.type;
this.isDataSource = this.pipelineElement.type === 'stream';
@@ -191,7 +189,7 @@ export class PipelineElementOptionsComponent implements
OnInit, OnDestroy {
},
});
- dialogRef.afterClosed().subscribe(c => {});
+ dialogRef.afterClosed().subscribe(() => {});
}
showRecommendations(e) {
@@ -208,6 +206,6 @@ export class PipelineElementOptionsComponent implements
OnInit, OnDestroy {
}
ngOnDestroy(): void {
- this.pipelineElementConfiguredObservable.unsubscribe();
+ this.pipelineElementConfiguredObservable?.unsubscribe();
}
}
diff --git
a/ui/src/app/editor/components/pipeline/dropped-pipeline-element/dropped-pipeline-element.component.html
b/ui/src/app/editor/components/pipeline/dropped-pipeline-element/dropped-pipeline-element.component.html
index 6004bdcb46..6cf404f42d 100644
---
a/ui/src/app/editor/components/pipeline/dropped-pipeline-element/dropped-pipeline-element.component.html
+++
b/ui/src/app/editor/components/pipeline/dropped-pipeline-element/dropped-pipeline-element.component.html
@@ -62,6 +62,9 @@
[pipelineElement]="pipelineElementConfig.payload"
></sp-pipeline-element>
</div>
+<div class="editor-pe-info" [ngClass]="'pe-info-' +
pipelineElementConfig.type">
+ {{ pipelineElementConfig.payload.name }}
+</div>
<sp-pipeline-element-statistics
*ngIf="metricsInfo"
[pipelineElement]="pipelineElementConfig.payload"
diff --git
a/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.html
b/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.html
index d740252a3f..4a6192901c 100644
---
a/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.html
+++
b/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.html
@@ -17,6 +17,19 @@
-->
<div fxFlex="100" fxLayout="row" fxLayoutAlign="start center">
+ <button
+ mat-button
+ color="accent"
+ matTooltip="Data Preview"
+ [matTooltipPosition]="'above'"
+ (click)="togglePreviewEmitter.emit()"
+ >
+ <div fxLayoutAlign="start center" fxLayout="row">
+ <i class="material-icons">visibility</i>
+ <span *ngIf="!previewModeActive"> Enable live preview</span>
+ <span *ngIf="previewModeActive"> Disable live preview</span>
+ </div>
+ </button>
<div fxFlex></div>
<div fxLayoutAlign="end center">
<button
diff --git
a/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.ts
b/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.ts
index 3ef8b9218c..9b8417ecc7 100644
---
a/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.ts
+++
b/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.ts
@@ -26,9 +26,15 @@ export class PipelineDetailsToolbarComponent {
@Input()
autoRefresh: boolean;
+ @Input()
+ previewModeActive: boolean;
+
@Output()
autoRefreshChange = new EventEmitter<boolean>();
@Output()
reloadMetricsEmitter: EventEmitter<void> = new EventEmitter();
+
+ @Output()
+ togglePreviewEmitter: EventEmitter<void> = new EventEmitter();
}
diff --git
a/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
b/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
index 6ff4085506..9a8ea603f9 100644
---
a/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
+++
b/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.html
@@ -19,6 +19,7 @@
<div class="outer-assembly-preview" fxFlex="100">
<div class="outerAssembly" fxFlex="100">
<sp-pipeline-assembly-drawing-area
+ #pipelineDrawingAreaComponent
*ngIf="rawPipelineModel"
fxFlex="100"
style="position: relative"
@@ -27,7 +28,7 @@
[rawPipelineModel]="rawPipelineModel"
[pipelineCanvasMetadata]="pipelineCanvasMetadata"
[pipelineCanvasMetadataAvailable]="
- pipelineCanvasMetadata !== undefined
+ pipelineCanvasMetadata?.pipelineElementMetadata !== undefined
"
[readonly]="true"
></sp-pipeline-assembly-drawing-area>
diff --git
a/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.ts
b/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.ts
index 3bea243bef..d791e40a49 100644
---
a/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.ts
+++
b/ui/src/app/pipeline-details/components/preview/pipeline-preview.component.ts
@@ -23,6 +23,7 @@ import {
Input,
OnInit,
Output,
+ ViewChild,
} from '@angular/core';
import {
Pipeline,
@@ -35,6 +36,7 @@ import {
} from '../../../editor/model/editor.model';
import { JsplumbService } from '../../../editor/services/jsplumb.service';
import { JsplumbBridge } from
'../../../editor/services/jsplumb-bridge.service';
+import { PipelineAssemblyDrawingAreaComponent } from
'../../../editor/components/pipeline-assembly/pipeline-assembly-drawing-area/pipeline-assembly-drawing-area.component';
@Component({
selector: 'sp-pipeline-preview',
@@ -57,6 +59,9 @@ export class PipelinePreviewComponent implements OnInit,
AfterViewInit {
selectedElementEmitter: EventEmitter<PipelineElementUnion> =
new EventEmitter<PipelineElementUnion>();
+ @ViewChild('pipelineDrawingAreaComponent')
+ pipelineDrawingAreaComponent: PipelineAssemblyDrawingAreaComponent;
+
jsPlumbBridge: JsplumbBridge;
constructor(private jsplumbService: JsplumbService) {}
@@ -71,4 +76,8 @@ export class PipelinePreviewComponent implements OnInit,
AfterViewInit {
true,
);
}
+
+ toggleLivePreview(): void {
+ this.pipelineDrawingAreaComponent?.togglePipelineElementLivePreview();
+ }
}
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.html
b/ui/src/app/pipeline-details/pipeline-details.component.html
index 9e38234ea6..7a9dd181f3 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.html
+++ b/ui/src/app/pipeline-details/pipeline-details.component.html
@@ -25,6 +25,8 @@
<sp-pipeline-details-toolbar
fxFlex="100"
[autoRefresh]="autoRefresh"
+ [previewModeActive]="previewModeActive"
+ (togglePreviewEmitter)="toggleLivePreview()"
(autoRefreshChange)="autoRefresh = $event"
(reloadMetricsEmitter)="triggerReload()"
>
@@ -32,6 +34,7 @@
</div>
<div fxFlex="100" fxLayout="column">
<sp-pipeline-preview
+ #pipelinePreviewComponent
[metricsInfo]="metricsInfo"
[pipeline]="pipeline"
[pipelineCanvasMetadata]="pipelineCanvasMetadata"
diff --git a/ui/src/app/pipeline-details/pipeline-details.component.ts
b/ui/src/app/pipeline-details/pipeline-details.component.ts
index b56bf65f70..4887f37aeb 100644
--- a/ui/src/app/pipeline-details/pipeline-details.component.ts
+++ b/ui/src/app/pipeline-details/pipeline-details.component.ts
@@ -16,7 +16,7 @@
*
*/
-import { Component, OnDestroy, OnInit } from '@angular/core';
+import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AuthService } from '../services/auth.service';
import {
@@ -35,8 +35,9 @@ import {
} from '@streampipes/shared-ui';
import { SpPipelineRoutes } from '../pipelines/pipelines.routes';
import { UserPrivilege } from '../_enums/user-privilege.enum';
-import { forkJoin, interval, Observable, Subscription } from 'rxjs';
-import { filter, switchMap } from 'rxjs/operators';
+import { forkJoin, interval, Observable, of, Subscription } from 'rxjs';
+import { catchError, filter, switchMap } from 'rxjs/operators';
+import { PipelinePreviewComponent } from
'./components/preview/pipeline-preview.component';
@Component({
selector: 'sp-pipeline-details-overview-component',
@@ -57,10 +58,14 @@ export class SpPipelineDetailsComponent implements OnInit,
OnDestroy {
autoRefresh = false;
metricsInfo: Record<string, SpMetricsEntry> = {};
logInfo: Record<string, SpLogEntry[]> = {};
+ previewModeActive = false;
currentUserSub: Subscription;
autoRefreshSub: Subscription;
+ @ViewChild('pipelinePreviewComponent')
+ pipelinePreviewComponent: PipelinePreviewComponent;
+
constructor(
private activatedRoute: ActivatedRoute,
private pipelineService: PipelineService,
@@ -90,9 +95,13 @@ export class SpPipelineDetailsComponent implements OnInit,
OnDestroy {
loadPipeline(): void {
forkJoin([
this.pipelineService.getPipelineById(this.currentPipelineId),
- this.pipelineCanvasService.getPipelineCanvasMetadata(
- this.currentPipelineId,
- ),
+ this.pipelineCanvasService
+ .getPipelineCanvasMetadata(this.currentPipelineId)
+ .pipe(
+ catchError(() => {
+ return of(new PipelineCanvasMetadata());
+ }),
+ ),
]).subscribe(res => {
this.pipeline = res[0];
this.pipelineCanvasMetadata = res[1];
@@ -119,14 +128,14 @@ export class SpPipelineDetailsComponent implements
OnInit, OnDestroy {
this.autoRefreshSub = interval(5000)
.pipe(
filter(() => this.autoRefresh),
- switchMap(() => this.getMonitoringObservables()),
+ switchMap(() => this.getMonitoringObservables(true)),
)
.subscribe(res => this.onMonitoringResultAvailable(res));
}
- getMonitoringObservables(): Observable<any> {
+ getMonitoringObservables(forceUpdate: boolean): Observable<any> {
return forkJoin([
- this.getMetricsObservable(),
+ this.getMetricsObservable(forceUpdate),
this.getLogsObservable(),
]);
}
@@ -147,9 +156,12 @@ export class SpPipelineDetailsComponent implements OnInit,
OnDestroy {
this.logInfo = res[1];
}
- getMetricsObservable(): Observable<Record<string, SpMetricsEntry>> {
+ getMetricsObservable(
+ forceUpdate = false,
+ ): Observable<Record<string, SpMetricsEntry>> {
return this.pipelineMonitoringService.getMetricsInfoForPipeline(
this.currentPipelineId,
+ forceUpdate,
);
}
@@ -159,6 +171,11 @@ export class SpPipelineDetailsComponent implements OnInit,
OnDestroy {
);
}
+ toggleLivePreview(): void {
+ this.previewModeActive = !this.previewModeActive;
+ this.pipelinePreviewComponent?.toggleLivePreview();
+ }
+
ngOnDestroy() {
this.currentUserSub?.unsubscribe();
this.autoRefreshSub?.unsubscribe();
diff --git
a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
index 924a9e1004..78d0c8a4c4 100644
---
a/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
+++
b/ui/src/app/pipelines/components/pipeline-overview/pipeline-overview.component.html
@@ -142,7 +142,7 @@
</ng-container>
<ng-container matColumnDef="lastModified">
- <th mat-header-cell mat-sort-header *matHeaderCellDef>Created</th>
+ <th mat-header-cell mat-sort-header *matHeaderCellDef>Last
modified</th>
<td mat-cell *matCellDef="let pipeline">
<h5>{{ pipeline.createdAt | date: 'dd.MM.yyyy HH:mm' }}</h5>
</td>