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">&nbsp;Enable live preview</span>
+            <span *ngIf="previewModeActive">&nbsp;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>

Reply via email to