This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to refs/heads/dev by this push:
     new 75e4d76578 refactor: migrate core-ui components to signals (#4267)
75e4d76578 is described below

commit 75e4d765781f702ac82388898fbfdd6fe9450825
Author: Philipp Zehnder <[email protected]>
AuthorDate: Sat Mar 21 20:23:54 2026 +0100

    refactor: migrate core-ui components to signals (#4267)
---
 .../core-ui/error-hint/error-hint.component.html   | 30 +++++++++------------
 .../app/core-ui/error-hint/error-hint.component.ts | 22 +++++++--------
 .../loading-indicator.component.html               |  2 +-
 .../loading-indicator.component.ts                 |  7 +++--
 .../pipeline-operation-status.component.html       |  2 +-
 .../pipeline-operation-status.component.ts         |  7 ++---
 .../pipeline-started-status.component.html         | 26 +++++++++---------
 .../pipeline-started-status.component.ts           | 31 +++++++---------------
 .../status-indicator.component.html                |  6 ++---
 .../status-indicator/status-indicator.component.ts | 13 ++++-----
 10 files changed, 62 insertions(+), 84 deletions(-)

diff --git a/ui/src/app/core-ui/error-hint/error-hint.component.html 
b/ui/src/app/core-ui/error-hint/error-hint.component.html
index b86579b5ef..1507d70ad6 100644
--- a/ui/src/app/core-ui/error-hint/error-hint.component.html
+++ b/ui/src/app/core-ui/error-hint/error-hint.component.html
@@ -16,51 +16,47 @@
 ~
 -->
 <div class="error-hint-position">
-    @if (displayMessages) {
+    @if (displayMessages()) {
         <div
             class="pipeline-validation-summary {{
-                errorMessages.length > 0
-                    ? 'pipeline-validation-summary-error'
-                    : ''
+                hasErrorMessages() ? 'pipeline-validation-summary-error' : ''
             }}"
             (click)="toggleErrorMessagesDisplayed()"
         >
             <div fxLayout="row" fxLayoutAlign="center center">
                 <div fxLayout="row" fxLayoutAlign="start center">
-                    @if (errorMessages.length > 0) {
+                    @if (hasErrorMessages()) {
                         <i class="material-icons">notifications</i>
                     }
-                    @if (errorMessages.length === 0) {
+                    @if (!hasErrorMessages()) {
                         <i class="material-icons">done</i>
                     }
                 </div>
                 <div>
-                    @if (errorMessages.length === 0) {
-                        <span>{{ validationString }} ok</span>
+                    @if (!hasErrorMessages()) {
+                        <span>{{ validationString() }} ok</span>
                     }
-                    @if (errorMessages.length > 0) {
+                    @if (hasErrorMessages()) {
                         <span
-                            >{{ errorMessages.length }}
-                            {{
-                                errorMessages.length > 1 ? 'hints' : 'hint'
-                            }}</span
+                            >{{ errorCount() }}
+                            {{ errorCount() > 1 ? 'hints' : 'hint' }}</span
                         >
                     }
                 </div>
             </div>
         </div>
     }
-    @if (errorMessages.length > 0 && errorMessagesDisplayed) {
+    @if (hasErrorMessages() && errorMessagesDisplayed()) {
         <div class="editor-error-notifications">
             <h5 class="error-hint-color">
                 <b
-                    >{{ errorMessages.length }}
-                    {{ errorMessages.length === 1 ? 'error' : 'errors' }}
+                    >{{ errorCount() }}
+                    {{ errorCount() === 1 ? 'error' : 'errors' }}
                     found.</b
                 >
             </h5>
             <hr />
-            @for (errorMessage of errorMessages; track errorMessage) {
+            @for (errorMessage of errorMessages(); track errorMessage) {
                 <div>
                     <b>{{ errorMessage.title }}</b>
                     <div>{{ errorMessage.content }}</div>
diff --git a/ui/src/app/core-ui/error-hint/error-hint.component.ts 
b/ui/src/app/core-ui/error-hint/error-hint.component.ts
index 0994193416..7242135909 100644
--- a/ui/src/app/core-ui/error-hint/error-hint.component.ts
+++ b/ui/src/app/core-ui/error-hint/error-hint.component.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { Component, Input, OnInit } from '@angular/core';
+import { Component, computed, input, signal } from '@angular/core';
 import { UserErrorMessage } from '../../core-model/base/UserErrorMessage';
 import {
     LayoutAlignDirective,
@@ -29,20 +29,16 @@ import {
     styleUrls: ['./error-hint.component.scss'],
     imports: [LayoutDirective, LayoutAlignDirective],
 })
-export class ErrorHintComponent implements OnInit {
-    @Input() errorMessages: UserErrorMessage[];
-    @Input() displayMessages = true;
-    @Input() validationString: string;
+export class ErrorHintComponent {
+    readonly errorMessages = input<UserErrorMessage[]>([]);
+    readonly displayMessages = input(true);
+    readonly validationString = input('');
 
-    errorMessagesDisplayed: boolean;
-
-    constructor() {}
-
-    ngOnInit(): void {
-        this.errorMessagesDisplayed = false;
-    }
+    readonly errorMessagesDisplayed = signal(false);
+    readonly errorCount = computed(() => this.errorMessages().length);
+    readonly hasErrorMessages = computed(() => this.errorCount() > 0);
 
     public toggleErrorMessagesDisplayed() {
-        this.errorMessagesDisplayed = !this.errorMessagesDisplayed;
+        this.errorMessagesDisplayed.update(displayed => !displayed);
     }
 }
diff --git 
a/ui/src/app/core-ui/loading-indicator/loading-indicator.component.html 
b/ui/src/app/core-ui/loading-indicator/loading-indicator.component.html
index 3982ccb2ac..3be5c4666f 100644
--- a/ui/src/app/core-ui/loading-indicator/loading-indicator.component.html
+++ b/ui/src/app/core-ui/loading-indicator/loading-indicator.component.html
@@ -18,5 +18,5 @@
 
 <div fxLayout="column" fxFlex="100" fxLayoutAlign="center center">
     <mat-spinner [diameter]="30" color="accent"></mat-spinner>
-    <div class="message-text">{{ message }}</div>
+    <div class="message-text">{{ message() }}</div>
 </div>
diff --git 
a/ui/src/app/core-ui/loading-indicator/loading-indicator.component.ts 
b/ui/src/app/core-ui/loading-indicator/loading-indicator.component.ts
index 5821e78d3c..b96cf1100d 100644
--- a/ui/src/app/core-ui/loading-indicator/loading-indicator.component.ts
+++ b/ui/src/app/core-ui/loading-indicator/loading-indicator.component.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { Component, inject, Input } from '@angular/core';
+import { Component, inject, input } from '@angular/core';
 import { TranslateService } from '@ngx-translate/core';
 import {
     FlexDirective,
@@ -37,8 +37,7 @@ import { MatProgressSpinner } from 
'@angular/material/progress-spinner';
     ],
 })
 export class LoadingIndicatorComponent {
-    translateService = inject(TranslateService);
+    private readonly translateService = inject(TranslateService);
 
-    @Input()
-    message = this.translateService.instant('Loading');
+    readonly message = input(this.translateService.instant('Loading'));
 }
diff --git 
a/ui/src/app/core-ui/pipeline/pipeline-operation-status/pipeline-operation-status.component.html
 
b/ui/src/app/core-ui/pipeline/pipeline-operation-status/pipeline-operation-status.component.html
index 3424af07c4..88dde64932 100644
--- 
a/ui/src/app/core-ui/pipeline/pipeline-operation-status/pipeline-operation-status.component.html
+++ 
b/ui/src/app/core-ui/pipeline/pipeline-operation-status/pipeline-operation-status.component.html
@@ -16,7 +16,7 @@
 ~
 -->
 
-@for (msg of pipelineOperationStatus.elementStatus; track msg) {
+@for (msg of pipelineOperationStatus()?.elementStatus ?? []; track msg) {
     <div fxFlex="100" fxLayout="column" class="status-outer mt-10">
         <div fxFlex="100" fxLayout="column">
             <div
diff --git 
a/ui/src/app/core-ui/pipeline/pipeline-operation-status/pipeline-operation-status.component.ts
 
b/ui/src/app/core-ui/pipeline/pipeline-operation-status/pipeline-operation-status.component.ts
index 76489c92d6..cbfd29fe76 100644
--- 
a/ui/src/app/core-ui/pipeline/pipeline-operation-status/pipeline-operation-status.component.ts
+++ 
b/ui/src/app/core-ui/pipeline/pipeline-operation-status/pipeline-operation-status.component.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { Component, Input } from '@angular/core';
+import { Component, input } from '@angular/core';
 import { PipelineOperationStatus } from '@streampipes/platform-services';
 import {
     FlexDirective,
@@ -32,6 +32,7 @@ import { MatIcon } from '@angular/material/icon';
     imports: [FlexDirective, LayoutDirective, LayoutAlignDirective, MatIcon],
 })
 export class PipelineOperationStatusComponent {
-    @Input()
-    pipelineOperationStatus: PipelineOperationStatus;
+    readonly pipelineOperationStatus = input<
+        PipelineOperationStatus | undefined
+    >(undefined);
 }
diff --git 
a/ui/src/app/core-ui/pipeline/pipeline-started-status/pipeline-started-status.component.html
 
b/ui/src/app/core-ui/pipeline/pipeline-started-status/pipeline-started-status.component.html
index 8f41f26993..a73fb1e48e 100644
--- 
a/ui/src/app/core-ui/pipeline/pipeline-started-status/pipeline-started-status.component.html
+++ 
b/ui/src/app/core-ui/pipeline/pipeline-started-status/pipeline-started-status.component.html
@@ -25,20 +25,20 @@
         data-cy="sp-pipeline-started-dialog"
     >
         <div fxLayout="row">
-            @if (pipelineOperationStatus.success) {
+            @if (pipelineOperationStatus()?.success) {
                 <mat-icon data-cy="sp-pipeline-started-success" color="accent"
                     >done</mat-icon
                 >
             }
-            @if (!pipelineOperationStatus.success) {
+            @if (!pipelineOperationStatus()?.success) {
                 <mat-icon style="color: red">error</mat-icon>
             }
-            <span>&nbsp;{{ pipelineOperationStatus.title }}.</span>
+            <span>&nbsp;{{ pipelineOperationStatus()?.title }}.</span>
         </div>
         @if (
-            action === 1 &&
-            !pipelineOperationStatus.success &&
-            !forceStopDisabled
+            action() === 1 &&
+            !pipelineOperationStatus()?.success &&
+            !forceStopDisabled()
         ) {
             <span class="message-small">{{
                 'You can perform a forced stop, which will stop and reset the 
pipeline status.'
@@ -53,21 +53,21 @@
             class="mat-basic"
             (click)="toggleStatusDetailsVisible()"
         >
-            @if (!statusDetailsVisible) {
+            @if (!statusDetailsVisible()) {
                 <div>
                     {{ 'Show Details' | translate }}
                 </div>
             }
-            @if (statusDetailsVisible) {
+            @if (statusDetailsVisible()) {
                 <div>
                     {{ 'Hide Details' | translate }}
                 </div>
             }
         </button>
         @if (
-            action === 1 &&
-            !pipelineOperationStatus.success &&
-            !forceStopDisabled
+            action() === 1 &&
+            !pipelineOperationStatus()?.success &&
+            !forceStopDisabled()
         ) {
             <button
                 mat-button
@@ -81,11 +81,11 @@
         }
     </div>
 
-    @if (statusDetailsVisible) {
+    @if (statusDetailsVisible()) {
         <div fxFlex="100" fxLayout="column" class="w-100">
             <sp-pipeline-operation-status
                 fxLayout="column"
-                [pipelineOperationStatus]="pipelineOperationStatus"
+                [pipelineOperationStatus]="pipelineOperationStatus()"
             >
             </sp-pipeline-operation-status>
         </div>
diff --git 
a/ui/src/app/core-ui/pipeline/pipeline-started-status/pipeline-started-status.component.ts
 
b/ui/src/app/core-ui/pipeline/pipeline-started-status/pipeline-started-status.component.ts
index 6566904a9f..947e92d7b9 100644
--- 
a/ui/src/app/core-ui/pipeline/pipeline-started-status/pipeline-started-status.component.ts
+++ 
b/ui/src/app/core-ui/pipeline/pipeline-started-status/pipeline-started-status.component.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { Component, input, output, signal } from '@angular/core';
 import { PipelineOperationStatus } from '@streampipes/platform-services';
 import { PipelineAction } from '../../../pipelines/model/pipeline-model';
 import {
@@ -43,32 +43,21 @@ import { TranslatePipe } from '@ngx-translate/core';
         TranslatePipe,
     ],
 })
-export class PipelineStartedStatusComponent implements OnInit {
-    @Input()
-    pipelineOperationStatus: PipelineOperationStatus;
+export class PipelineStartedStatusComponent {
+    readonly pipelineOperationStatus = input<
+        PipelineOperationStatus | undefined
+    >(undefined);
+    readonly action = input<PipelineAction | undefined>(undefined);
+    readonly forceStopDisabled = input(false);
 
-    @Input()
-    action: PipelineAction;
-
-    @Input()
-    forceStopDisabled = false;
-
-    @Output()
-    forceStopPipelineEmitter = new EventEmitter();
-
-    statusDetailsVisible: boolean;
-
-    constructor() {}
-
-    ngOnInit(): void {
-        this.statusDetailsVisible = false;
-    }
+    readonly forceStopPipelineEmitter = output<void>();
+    readonly statusDetailsVisible = signal(false);
 
     forceStopPipeline() {
         this.forceStopPipelineEmitter.emit();
     }
 
     toggleStatusDetailsVisible() {
-        this.statusDetailsVisible = !this.statusDetailsVisible;
+        this.statusDetailsVisible.update(visible => !visible);
     }
 }
diff --git 
a/ui/src/app/core-ui/status-indicator/status-indicator.component.html 
b/ui/src/app/core-ui/status-indicator/status-indicator.component.html
index bbb27508b0..173b275c47 100644
--- a/ui/src/app/core-ui/status-indicator/status-indicator.component.html
+++ b/ui/src/app/core-ui/status-indicator/status-indicator.component.html
@@ -17,7 +17,7 @@
   -->
 
 <div fxLayout="column" fxFlex="100" fxLayoutAlign="center center">
-    <i class="material-icons status-icon">{{ icon }}</i>
-    <div class="status-text">{{ message }}</div>
-    <div class="status-subtext">{{ additionalDescription }}</div>
+    <i class="material-icons status-icon">{{ icon() }}</i>
+    <div class="status-text">{{ message() }}</div>
+    <div class="status-subtext">{{ additionalDescription() }}</div>
 </div>
diff --git a/ui/src/app/core-ui/status-indicator/status-indicator.component.ts 
b/ui/src/app/core-ui/status-indicator/status-indicator.component.ts
index 738494c2b8..acefc62920 100644
--- a/ui/src/app/core-ui/status-indicator/status-indicator.component.ts
+++ b/ui/src/app/core-ui/status-indicator/status-indicator.component.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { Component, inject, Input } from '@angular/core';
+import { Component, inject, input } from '@angular/core';
 import { TranslateService } from '@ngx-translate/core';
 import {
     FlexDirective,
@@ -31,14 +31,11 @@ import {
     imports: [LayoutDirective, FlexDirective, LayoutAlignDirective],
 })
 export class StatusIndicatorComponent {
-    translateService = inject(TranslateService);
+    private readonly translateService = inject(TranslateService);
 
-    @Input()
-    message = this.translateService.instant('Loading');
+    readonly message = input(this.translateService.instant('Loading'));
 
-    @Input()
-    additionalDescription = '';
+    readonly additionalDescription = input('');
 
-    @Input()
-    icon: string;
+    readonly icon = input<string | undefined>(undefined);
 }

Reply via email to