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

zehnder pushed a commit to branch 3983-home
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to refs/heads/3983-home by this push:
     new ea536806b7 refactor: Migrate modules home, info, login, notifications 
and profile to control flow syntax
ea536806b7 is described below

commit ea536806b752955873e586ad0e1dc91095dd3fce
Author: Philipp Zehnder <[email protected]>
AuthorDate: Thu Nov 27 12:45:52 2025 +0100

    refactor: Migrate modules home, info, login, notifications and profile to 
control flow syntax
---
 ui/src/app/home/components/status.component.html   |  58 ++--
 ui/src/app/home/home.component.html                | 119 ++++----
 ui/src/app/info/versions/versions.component.html   | 164 +++++-----
 .../activate-account.component.html                |  76 ++---
 .../components/auth-box/auth-box.component.html    |  98 +++---
 .../login/components/login/login.component.html    | 173 ++++++-----
 .../components/register/register.component.html    | 192 ++++++------
 .../restore-password.component.html                | 145 ++++-----
 .../set-new-password.component.html                | 169 ++++++-----
 .../login/components/setup/setup.component.html    | 267 ++++++++--------
 .../app/notifications/notifications.component.html | 239 ++++++++-------
 .../general-profile-settings.component.html        | 219 ++++++-------
 .../token/token-management-settings.component.html | 337 ++++++++++-----------
 .../change-email-dialog.component.html             | 141 ++++-----
 .../change-password-dialog.component.html          | 137 +++++----
 ui/src/app/profile/profile.component.html          |  66 ++--
 16 files changed, 1328 insertions(+), 1272 deletions(-)

diff --git a/ui/src/app/home/components/status.component.html 
b/ui/src/app/home/components/status.component.html
index 6a7f46bd1f..a5e8d1c4a2 100644
--- a/ui/src/app/home/components/status.component.html
+++ b/ui/src/app/home/components/status.component.html
@@ -1,20 +1,20 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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
     fxFlex="100"
@@ -36,20 +36,18 @@
                 </div>
             </div>
             <div fxFlex="100" fxLayoutAlign="end end" class="w-100">
-                <div
-                    fxFlex="100"
-                    fxLayoutAlign="start center"
-                    *ngIf="showCreateLink"
-                >
-                    <a
-                        (click)="navigate(statusBox.createLink)"
-                        fxLayoutAlign="start center"
-                        class="status-container-create-link"
-                    >
-                        <i class="material-icons">add_circle</i>
-                        <span>&nbsp;{{ statusBox.createTitle }}</span>
-                    </a>
-                </div>
+                @if (showCreateLink) {
+                    <div fxFlex="100" fxLayoutAlign="start center">
+                        <a
+                            (click)="navigate(statusBox.createLink)"
+                            fxLayoutAlign="start center"
+                            class="status-container-create-link"
+                        >
+                            <i class="material-icons">add_circle</i>
+                            <span>&nbsp;{{ statusBox.createTitle }}</span>
+                        </a>
+                    </div>
+                }
             </div>
         </div>
     </div>
diff --git a/ui/src/app/home/home.component.html 
b/ui/src/app/home/home.component.html
index b85bc96c84..79ef640bc3 100644
--- a/ui/src/app/home/home.component.html
+++ b/ui/src/app/home/home.component.html
@@ -1,20 +1,20 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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.
+~
+-->
 
 <sp-basic-view [hideNavbar]="true">
     <div fxFlex fxLayout="row" fxLayoutAlign="start start">
@@ -24,20 +24,22 @@
                     <div class="welcome-text">Welcome!</div>
                 </div>
                 <div fxLayout="column" fxFlex="100" class="home-margin">
-                    <div
-                        fxFlex="100"
-                        fxLayout="row"
-                        fxLayoutAlign="start center"
-                        fxLayoutGap="10px"
-                        *ngIf="showStatus"
-                    >
-                        <sp-status
-                            [fxFlex]="100 / statusBoxes.length"
-                            [statusBox]="box"
-                            [currentUser]="currentUser"
-                            *ngFor="let box of statusBoxes"
-                        ></sp-status>
-                    </div>
+                    @if (showStatus) {
+                        <div
+                            fxFlex="100"
+                            fxLayout="row"
+                            fxLayoutAlign="start center"
+                            fxLayoutGap="10px"
+                        >
+                            @for (box of statusBoxes; track box) {
+                                <sp-status
+                                    [fxFlex]="100 / statusBoxes.length"
+                                    [statusBox]="box"
+                                    [currentUser]="currentUser"
+                                ></sp-status>
+                            }
+                        </div>
+                    }
                     <div fxFlex="100">
                         <sp-basic-inner-panel
                             innerPadding="0"
@@ -45,34 +47,37 @@
                         >
                             <div fxFlex="100" fxLayout="column">
                                 <mat-list class="modules-list">
-                                    <mat-list-item
-                                        *ngFor="let link of serviceLinks"
-                                        (click)="openLink(link)"
-                                        class="list-item"
-                                    >
-                                        <div
-                                            matListItemAvatar
-                                            class="pipeline-avatar 
sp-primary-bg"
-                                        >
-                                            <mat-icon>{{ link.icon 
}}</mat-icon>
-                                        </div>
-                                        <span
-                                            matListItemTitle
-                                            style="
-                                                font-weight: bold;
-                                                font-size: 14pt;
-                                            "
-                                        >
-                                            {{ link.name }}
-                                        </span>
-                                        <span
-                                            matListItemLine
-                                            class="module-description"
+                                    @for (link of serviceLinks; track link) {
+                                        <mat-list-item
+                                            (click)="openLink(link)"
+                                            class="list-item"
                                         >
-                                            {{ link.description }}
-                                        </span>
-                                        <mat-divider></mat-divider>
-                                    </mat-list-item>
+                                            <div
+                                                matListItemAvatar
+                                                class="pipeline-avatar 
sp-primary-bg"
+                                            >
+                                                <mat-icon>{{
+                                                    link.icon
+                                                }}</mat-icon>
+                                            </div>
+                                            <span
+                                                matListItemTitle
+                                                style="
+                                                    font-weight: bold;
+                                                    font-size: 14pt;
+                                                "
+                                            >
+                                                {{ link.name }}
+                                            </span>
+                                            <span
+                                                matListItemLine
+                                                class="module-description"
+                                            >
+                                                {{ link.description }}
+                                            </span>
+                                            <mat-divider></mat-divider>
+                                        </mat-list-item>
+                                    }
                                 </mat-list>
                             </div>
                         </sp-basic-inner-panel>
diff --git a/ui/src/app/info/versions/versions.component.html 
b/ui/src/app/info/versions/versions.component.html
index 7272c2bb4a..2a71870901 100644
--- a/ui/src/app/info/versions/versions.component.html
+++ b/ui/src/app/info/versions/versions.component.html
@@ -1,34 +1,36 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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="column" fxLayoutGap="10px">
     <sp-basic-header-title-component
         title="Info"
     ></sp-basic-header-title-component>
     <sp-basic-inner-panel panelTitle="Versions" fxFlex="90">
-        <div *ngIf="versionInfo">
-            <ul>
-                <li>
-                    <div fxFlex="30">Backend Version</div>
-                    <div fxFlex="70">{{ versionInfo.backendVersion }}</div>
-                </li>
-            </ul>
-        </div>
+        @if (versionInfo) {
+            <div>
+                <ul>
+                    <li>
+                        <div fxFlex="30">Backend Version</div>
+                        <div fxFlex="70">{{ versionInfo.backendVersion }}</div>
+                    </li>
+                </ul>
+            </div>
+        }
     </sp-basic-inner-panel>
     <sp-basic-inner-panel
         panelTitle="System Info"
@@ -36,61 +38,63 @@
         outerMargin="0"
         fxFlex="90"
     >
-        <div *ngIf="systemInfo">
-            <ul>
-                <li>
-                    <div fxFlex="30">Java VM Vendor</div>
-                    <div fxFlex="70">{{ systemInfo.javaVmVendor }}</div>
-                </li>
-                <li>
-                    <div fxFlex="30">Java VM Name</div>
-                    <div fxFlex="70">{{ systemInfo.javaVmName }}</div>
-                </li>
-                <li>
-                    <div fxFlex="30">Java VM Version</div>
-                    <div fxFlex="70">{{ systemInfo.javaVmVersion }}</div>
-                </li>
-                <li>
-                    <div fxFlex="30">Java Runtime Name</div>
-                    <div fxFlex="70">{{ systemInfo.javaRuntimeName }}</div>
-                </li>
-                <li>
-                    <div fxFlex="30">Java Runtime Version</div>
-                    <div fxFlex="70">
-                        {{ systemInfo.javaRuntimeVersion }}
-                    </div>
-                </li>
-                <li>
-                    <div fxFlex="30">CPU</div>
-                    <div fxFlex="70">{{ systemInfo.cpu }}</div>
-                </li>
-                <li>
-                    <div fxFlex="30">OS Name</div>
-                    <div fxFlex="70">{{ systemInfo.osName }}</div>
-                </li>
-                <li>
-                    <div fxFlex="30">OS Version</div>
-                    <div fxFlex="70">{{ systemInfo.osVersion }}</div>
-                </li>
-                <li>
-                    <div fxFlex="30">Total Memory</div>
-                    <div fxFlex="70">
-                        {{ systemInfo.totalMemory }} ({{
-                            systemInfo.totalMemoryKB
-                        }}
-                        KB)
-                    </div>
-                </li>
-                <li>
-                    <div fxFlex="30">Free Memory</div>
-                    <div fxFlex="70">
-                        {{ systemInfo.freeMemory }} ({{
-                            systemInfo.freeMemoryKB
-                        }}
-                        KB)
-                    </div>
-                </li>
-            </ul>
-        </div>
+        @if (systemInfo) {
+            <div>
+                <ul>
+                    <li>
+                        <div fxFlex="30">Java VM Vendor</div>
+                        <div fxFlex="70">{{ systemInfo.javaVmVendor }}</div>
+                    </li>
+                    <li>
+                        <div fxFlex="30">Java VM Name</div>
+                        <div fxFlex="70">{{ systemInfo.javaVmName }}</div>
+                    </li>
+                    <li>
+                        <div fxFlex="30">Java VM Version</div>
+                        <div fxFlex="70">{{ systemInfo.javaVmVersion }}</div>
+                    </li>
+                    <li>
+                        <div fxFlex="30">Java Runtime Name</div>
+                        <div fxFlex="70">{{ systemInfo.javaRuntimeName }}</div>
+                    </li>
+                    <li>
+                        <div fxFlex="30">Java Runtime Version</div>
+                        <div fxFlex="70">
+                            {{ systemInfo.javaRuntimeVersion }}
+                        </div>
+                    </li>
+                    <li>
+                        <div fxFlex="30">CPU</div>
+                        <div fxFlex="70">{{ systemInfo.cpu }}</div>
+                    </li>
+                    <li>
+                        <div fxFlex="30">OS Name</div>
+                        <div fxFlex="70">{{ systemInfo.osName }}</div>
+                    </li>
+                    <li>
+                        <div fxFlex="30">OS Version</div>
+                        <div fxFlex="70">{{ systemInfo.osVersion }}</div>
+                    </li>
+                    <li>
+                        <div fxFlex="30">Total Memory</div>
+                        <div fxFlex="70">
+                            {{ systemInfo.totalMemory }} ({{
+                                systemInfo.totalMemoryKB
+                            }}
+                            KB)
+                        </div>
+                    </li>
+                    <li>
+                        <div fxFlex="30">Free Memory</div>
+                        <div fxFlex="70">
+                            {{ systemInfo.freeMemory }} ({{
+                                systemInfo.freeMemoryKB
+                            }}
+                            KB)
+                        </div>
+                    </li>
+                </ul>
+            </div>
+        }
     </sp-basic-inner-panel>
 </div>
diff --git 
a/ui/src/app/login/components/activate-account/activate-account.component.html 
b/ui/src/app/login/components/activate-account/activate-account.component.html
index 0a0975d9b8..44abfce1d5 100644
--- 
a/ui/src/app/login/components/activate-account/activate-account.component.html
+++ 
b/ui/src/app/login/components/activate-account/activate-account.component.html
@@ -1,41 +1,43 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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.
+~
+-->
 
-<sp-auth-box [linkSettings]="loginSettings.linkSettings" *ngIf="configReady">
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
-        <h1>Account activation</h1>
-    </div>
-    <div fxLayout="column" fxFlex="100">
-        <div fxLayout="column" class="mt-10">
-            <div>
-                <h5 *ngIf="!activationPerformed">
-                    Verifying account activation...
-                </h5>
-                <h5 *ngIf="activationPerformed && activationSuccess">
-                    Account successfully activated.
-                </h5>
-                <h5 *ngIf="activationPerformed && !activationSuccess">
-                    Your account could not be activated.
-                </h5>
-            </div>
-            <div>
-                <a [routerLink]="['/login']">Go to login page</a>
+@if (configReady) {
+    <sp-auth-box [linkSettings]="loginSettings.linkSettings">
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
+            <h1>Account activation</h1>
+        </div>
+        <div fxLayout="column" fxFlex="100">
+            <div fxLayout="column" class="mt-10">
+                <div>
+                    @if (!activationPerformed) {
+                        <h5>Verifying account activation...</h5>
+                    }
+                    @if (activationPerformed && activationSuccess) {
+                        <h5>Account successfully activated.</h5>
+                    }
+                    @if (activationPerformed && !activationSuccess) {
+                        <h5>Your account could not be activated.</h5>
+                    }
+                </div>
+                <div>
+                    <a [routerLink]="['/login']">Go to login page</a>
+                </div>
             </div>
         </div>
-    </div>
-</sp-auth-box>
+    </sp-auth-box>
+}
diff --git a/ui/src/app/login/components/auth-box/auth-box.component.html 
b/ui/src/app/login/components/auth-box/auth-box.component.html
index 7a8f59f66a..84ad015c9d 100644
--- a/ui/src/app/login/components/auth-box/auth-box.component.html
+++ b/ui/src/app/login/components/auth-box/auth-box.component.html
@@ -1,20 +1,20 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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
     class="full-background sp-fade light-mode"
@@ -43,40 +43,38 @@
                 </div>
             </div>
             <div fxLayout="row" fxLayoutAlign="end end" 
class="auth-box-footer">
-                <a
-                    *ngIf="linkSettings.showDocumentationLinkOnStartScreen"
-                    class="footer-link"
-                    [href]="linkSettings.documentationUrl"
-                >
-                    {{ 'Documentation' | translate }}
-                </a>
-                <span
-                    style="margin-left: 10px; margin-right: 10px"
-                    *ngIf="linkSettings.showApiDocumentationLinkOnStartScreen"
-                >
-                    |
-                </span>
-                <a
-                    *ngIf="linkSettings.showApiDocumentationLinkOnStartScreen"
-                    class="footer-link"
-                    data-cy="view-api-docs-link"
-                    routerLink="/apidocs"
-                    routerLinkActive="active"
-                    >{{ 'API Documentation' | translate }}</a
-                >
-                <span
-                    style="margin-left: 10px; margin-right: 10px"
-                    *ngIf="linkSettings.showSupportUrlOnStartScreen"
-                >
-                    |
-                </span>
-                <a
-                    *ngIf="linkSettings.showSupportUrlOnStartScreen"
-                    class="footer-link"
-                    [href]="linkSettings.supportUrl"
-                >
-                    Support
-                </a>
+                @if (linkSettings.showDocumentationLinkOnStartScreen) {
+                    <a
+                        class="footer-link"
+                        [href]="linkSettings.documentationUrl"
+                    >
+                        {{ 'Documentation' | translate }}
+                    </a>
+                }
+                @if (linkSettings.showApiDocumentationLinkOnStartScreen) {
+                    <span style="margin-left: 10px; margin-right: 10px">
+                        |
+                    </span>
+                }
+                @if (linkSettings.showApiDocumentationLinkOnStartScreen) {
+                    <a
+                        class="footer-link"
+                        data-cy="view-api-docs-link"
+                        routerLink="/apidocs"
+                        routerLinkActive="active"
+                        >{{ 'API Documentation' | translate }}</a
+                    >
+                }
+                @if (linkSettings.showSupportUrlOnStartScreen) {
+                    <span style="margin-left: 10px; margin-right: 10px">
+                        |
+                    </span>
+                }
+                @if (linkSettings.showSupportUrlOnStartScreen) {
+                    <a class="footer-link" [href]="linkSettings.supportUrl">
+                        Support
+                    </a>
+                }
             </div>
         </div>
     </div>
diff --git a/ui/src/app/login/components/login/login.component.html 
b/ui/src/app/login/components/login/login.component.html
index 02ca813794..a986c215ce 100644
--- a/ui/src/app/login/components/login/login.component.html
+++ b/ui/src/app/login/components/login/login.component.html
@@ -1,20 +1,20 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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.
+~
+-->
 
 @if (configReady) {
     <sp-auth-box [linkSettings]="loginSettings.linkSettings">
@@ -55,75 +55,86 @@
                         (click)="doLogin()"
                         [disabled]="!parentForm.valid || loading"
                     >
-                        <span *ngIf="loading"
-                            >{{ 'Logging in' | translate }}...</span
-                        >
-                        <span *ngIf="!loading">{{ 'Login' | translate }}</span>
+                        @if (loading) {
+                            <span>{{ 'Logging in' | translate }}...</span>
+                        }
+                        @if (!loading) {
+                            <span>{{ 'Login' | translate }}</span>
+                        }
                     </button>
-                    <mat-spinner
-                        [mode]="'indeterminate'"
-                        [diameter]="20"
-                        *ngIf="loading"
-                        style="margin-top: 10px"
-                    ></mat-spinner>
-                    <div class="md-warn" *ngIf="authenticationFailed">
-                        <h5 class="login-error">
-                            {{
-                                'User not found or incorrect password 
provided.'
-                                    | translate
-                            }}<br />
-                            {{ 'Please try again' | translate }}
-                        </h5>
-                    </div>
-                    <div fxLayout="row" class="mt-10">
-                        <div *ngIf="loginSettings.allowPasswordRecovery">
-                            <a [routerLink]="['/restore-password']">{{
-                                'Forgot password?' | translate
-                            }}</a>
-                        </div>
-                        <span
-                            style="margin-left: 5px; margin-right: 5px"
-                            *ngIf="
-                                loginSettings.allowSelfRegistration &&
-                                loginSettings.allowPasswordRecovery
-                            "
-                        >
-                            |
-                        </span>
-                        <div *ngIf="loginSettings.allowSelfRegistration">
-                            <a [routerLink]="['/register']">{{
-                                'Create new account' | translate
-                            }}</a>
+                    @if (loading) {
+                        <mat-spinner
+                            [mode]="'indeterminate'"
+                            [diameter]="20"
+                            style="margin-top: 10px"
+                        ></mat-spinner>
+                    }
+                    @if (authenticationFailed) {
+                        <div class="md-warn">
+                            <h5 class="login-error">
+                                {{
+                                    'User not found or incorrect password 
provided.'
+                                        | translate
+                                }}<br />
+                                {{ 'Please try again' | translate }}
+                            </h5>
                         </div>
+                    }
+                    <div fxLayout="row" class="mt-10">
+                        @if (loginSettings.allowPasswordRecovery) {
+                            <div>
+                                <a [routerLink]="['/restore-password']">{{
+                                    'Forgot password?' | translate
+                                }}</a>
+                            </div>
+                        }
+                        @if (
+                            loginSettings.allowSelfRegistration &&
+                            loginSettings.allowPasswordRecovery
+                        ) {
+                            <span style="margin-left: 5px; margin-right: 5px">
+                                |
+                            </span>
+                        }
+                        @if (loginSettings.allowSelfRegistration) {
+                            <div>
+                                <a [routerLink]="['/register']">{{
+                                    'Create new account' | translate
+                                }}</a>
+                            </div>
+                        }
                     </div>
-                    <div
-                        fxLayout="column"
-                        class="mt-10"
-                        *ngIf="loginSettings.oAuthSettings?.enabled"
-                    >
-                        <div class="separator">
-                            <span>{{ 'or' | translate }}</span>
-                        </div>
-                        <div
-                            fxLayout="column"
-                            *ngFor="
-                                let provider of loginSettings.oAuthSettings
-                                    .supportedProviders
-                            "
-                            class="mt-10"
-                        >
-                            <button
-                                mat-flat-button
-                                data-cy="login-button"
-                                (click)="doOAuthLogin(provider.registrationId)"
-                            >
-                                <span *ngIf="!loading"
-                                    >{{ 'Login with' | translate }}
-                                    {{ provider.name }}</span
-                                >
-                            </button>
+                    @if (loginSettings.oAuthSettings?.enabled) {
+                        <div fxLayout="column" class="mt-10">
+                            <div class="separator">
+                                <span>{{ 'or' | translate }}</span>
+                            </div>
+                            @for (
+                                provider of loginSettings.oAuthSettings
+                                    .supportedProviders;
+                                track provider
+                            ) {
+                                <div fxLayout="column" class="mt-10">
+                                    <button
+                                        mat-flat-button
+                                        data-cy="login-button"
+                                        (click)="
+                                            doOAuthLogin(
+                                                provider.registrationId
+                                            )
+                                        "
+                                    >
+                                        @if (!loading) {
+                                            <span
+                                                >{{ 'Login with' | translate }}
+                                                {{ provider.name }}</span
+                                            >
+                                        }
+                                    </button>
+                                </div>
+                            }
                         </div>
-                    </div>
+                    }
                 </div>
             </form>
         </div>
diff --git a/ui/src/app/login/components/register/register.component.html 
b/ui/src/app/login/components/register/register.component.html
index 8268a73d63..d9a6bd5026 100644
--- a/ui/src/app/login/components/register/register.component.html
+++ b/ui/src/app/login/components/register/register.component.html
@@ -1,93 +1,107 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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.
+~
+-->
 
-<sp-auth-box [linkSettings]="loginSettings.linkSettings" *ngIf="configReady">
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
-        <h1>{{ 'Register' | translate }}</h1>
-    </div>
-    <div fxLayout="column" fxFlex="100">
-        <form [formGroup]="parentForm">
-            <div fxLayout="column">
-                <mat-form-field color="accent">
-                    <mat-label>{{ 'Email' | translate }}</mat-label>
-                    <input formControlName="username" fxFlex matInput />
-                    <mat-error *ngIf="parentForm.controls.username.errors"
-                        >Must be an email address.</mat-error
-                    >
-                </mat-form-field>
-                <mat-form-field color="accent">
-                    <mat-label>{{ 'Initial password' | translate }}</mat-label>
-                    <input
-                        formControlName="password"
-                        fxFlex
-                        type="password"
-                        matInput
-                        required
-                    />
-                </mat-form-field>
-                <mat-form-field color="accent">
-                    <mat-label>{{ 'Repeat password' | translate }}</mat-label>
-                    <input
-                        formControlName="repeatPassword"
-                        fxFlex
-                        type="password"
-                        matInput
-                        required
-                    />
-                </mat-form-field>
-                <mat-error *ngIf="parentForm.hasError('notMatching')">{{
-                    'Passwords do not match.' | translate
-                }}</mat-error>
-                <div class="form-actions" style="margin-top: 20px">
-                    <button
-                        mat-button
-                        mat-flat-button
-                        color="accent"
-                        (click)="registerUser()"
-                        [disabled]="!parentForm.valid"
-                        *ngIf="!registrationSuccess"
-                    >
-                        <span>{{ 'Register' | translate }}</span>
-                    </button>
-                    <mat-spinner
-                        [mode]="'indeterminate'"
-                        color="accent"
-                        [diameter]="20"
-                        *ngIf="registrationInProcess"
-                        style="margin-top: 10px"
-                    ></mat-spinner>
-                    <div class="md-warn" *ngIf="registrationError">
-                        <h5 class="info-box register-error">
-                            {{ registrationError }}
-                        </h5>
-                    </div>
-                    <div class="md-success" *ngIf="registrationSuccess">
-                        <h5 class="info-box register-success">
-                            {{ 'We've sent out a confirmation mail to this 
address.' | translate }}
-                        </h5>
-                    </div>
-                    <div class="mt-10">
-                        <a [routerLink]="['/login']">{{
-                            'Go to login page' | translate
-                        }}</a>
+@if (configReady) {
+    <sp-auth-box [linkSettings]="loginSettings.linkSettings">
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
+            <h1>{{ 'Register' | translate }}</h1>
+        </div>
+        <div fxLayout="column" fxFlex="100">
+            <form [formGroup]="parentForm">
+                <div fxLayout="column">
+                    <mat-form-field color="accent">
+                        <mat-label>{{ 'Email' | translate }}</mat-label>
+                        <input formControlName="username" fxFlex matInput />
+                        @if (parentForm.controls.username.errors) {
+                            <mat-error>Must be an email address.</mat-error>
+                        }
+                    </mat-form-field>
+                    <mat-form-field color="accent">
+                        <mat-label>{{
+                            'Initial password' | translate
+                        }}</mat-label>
+                        <input
+                            formControlName="password"
+                            fxFlex
+                            type="password"
+                            matInput
+                            required
+                        />
+                    </mat-form-field>
+                    <mat-form-field color="accent">
+                        <mat-label>{{
+                            'Repeat password' | translate
+                        }}</mat-label>
+                        <input
+                            formControlName="repeatPassword"
+                            fxFlex
+                            type="password"
+                            matInput
+                            required
+                        />
+                    </mat-form-field>
+                    @if (parentForm.hasError('notMatching')) {
+                        <mat-error>{{
+                            'Passwords do not match.' | translate
+                        }}</mat-error>
+                    }
+                    <div class="form-actions" style="margin-top: 20px">
+                        @if (!registrationSuccess) {
+                            <button
+                                mat-button
+                                mat-flat-button
+                                color="accent"
+                                (click)="registerUser()"
+                                [disabled]="!parentForm.valid"
+                            >
+                                <span>{{ 'Register' | translate }}</span>
+                            </button>
+                        }
+                        @if (registrationInProcess) {
+                            <mat-spinner
+                                [mode]="'indeterminate'"
+                                color="accent"
+                                [diameter]="20"
+                                style="margin-top: 10px"
+                            ></mat-spinner>
+                        }
+                        @if (registrationError) {
+                            <div class="md-warn">
+                                <h5 class="info-box register-error">
+                                    {{ registrationError }}
+                                </h5>
+                            </div>
+                        }
+                        @if (registrationSuccess) {
+                            <div class="md-success">
+                                <h5 class="info-box register-success">
+                                    {{ 'We've sent out a confirmation mail to 
this address.' | translate }}
+                                </h5>
+                            </div>
+                        }
+                        <div class="mt-10">
+                            <a [routerLink]="['/login']">{{
+                                'Go to login page' | translate
+                            }}</a>
+                        </div>
                     </div>
                 </div>
-            </div>
-        </form>
-    </div>
-</sp-auth-box>
+            </form>
+        </div>
+    </sp-auth-box>
+}
diff --git 
a/ui/src/app/login/components/restore-password/restore-password.component.html 
b/ui/src/app/login/components/restore-password/restore-password.component.html
index 60c4ebeba7..de05e8ac4a 100644
--- 
a/ui/src/app/login/components/restore-password/restore-password.component.html
+++ 
b/ui/src/app/login/components/restore-password/restore-password.component.html
@@ -1,76 +1,77 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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.
+~
+-->
 
-<sp-auth-box [linkSettings]="loginSettings.linkSettings" *ngIf="configReady">
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
-        <h1>{{ 'Restore password' | translate }}</h1>
-        <h5>
-            {{ 'Enter your mail address and we'll send you a link to restore 
your
-            password.' | translate }}
-        </h5>
-    </div>
-    <div fxLayout="column" fxFlex="100">
-        <form [formGroup]="parentForm">
-            <div fxLayout="column">
-                <mat-form-field color="accent">
-                    <mat-label>{{ 'Email' | translate }}</mat-label>
-                    <input formControlName="username" fxFlex matInput />
-                </mat-form-field>
-                <div class="form-actions" style="margin-top: 20px">
-                    <button
-                        mat-button
-                        mat-flat-button
-                        color="accent"
-                        (click)="sendRestorePasswordLink()"
-                        [disabled]="!parentForm.valid"
-                        *ngIf="!restoreSuccess"
-                    >
-                        <span>{{ 'Reset password' | translate }}</span>
-                    </button>
-                    <div
-                        class="md-warn"
-                        *ngIf="restoreCompleted && !restoreSuccess"
-                    >
-                        <h5 class="info-box register-error">
-                            {{
-                                'Unknown error - contact your administrator to 
check
-                            the mail settings.' | translate
-                            }}
-                        </h5>
-                    </div>
-                    <div
-                        class="md-success"
-                        *ngIf="restoreCompleted && restoreSuccess"
-                    >
-                        <h5 class="info-box register-success">
-                            {{
-                                "In case this account exists, you'll receive a 
mail with instructions to restore your password shortly."
-                                    | translate
-                            }}
-                        </h5>
-                    </div>
-                    <div class="mt-10">
-                        <a [routerLink]="['/login']">{{
-                            'Go to login page' | translate
-                        }}</a>
+@if (configReady) {
+    <sp-auth-box [linkSettings]="loginSettings.linkSettings">
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
+            <h1>{{ 'Restore password' | translate }}</h1>
+            <h5>
+                {{ 'Enter your mail address and we'll send you a link to 
restore your
+        password.' | translate }}
+            </h5>
+        </div>
+        <div fxLayout="column" fxFlex="100">
+            <form [formGroup]="parentForm">
+                <div fxLayout="column">
+                    <mat-form-field color="accent">
+                        <mat-label>{{ 'Email' | translate }}</mat-label>
+                        <input formControlName="username" fxFlex matInput />
+                    </mat-form-field>
+                    <div class="form-actions" style="margin-top: 20px">
+                        @if (!restoreSuccess) {
+                            <button
+                                mat-button
+                                mat-flat-button
+                                color="accent"
+                                (click)="sendRestorePasswordLink()"
+                                [disabled]="!parentForm.valid"
+                            >
+                                <span>{{ 'Reset password' | translate }}</span>
+                            </button>
+                        }
+                        @if (restoreCompleted && !restoreSuccess) {
+                            <div class="md-warn">
+                                <h5 class="info-box register-error">
+                                    {{
+                                        'Unknown error - contact your 
administrator to check
+                  the mail settings.' | translate
+                                    }}
+                                </h5>
+                            </div>
+                        }
+                        @if (restoreCompleted && restoreSuccess) {
+                            <div class="md-success">
+                                <h5 class="info-box register-success">
+                                    {{
+                                        "In case this account exists, you'll 
receive a mail with instructions to restore your password shortly."
+                                            | translate
+                                    }}
+                                </h5>
+                            </div>
+                        }
+                        <div class="mt-10">
+                            <a [routerLink]="['/login']">{{
+                                'Go to login page' | translate
+                            }}</a>
+                        </div>
                     </div>
                 </div>
-            </div>
-        </form>
-    </div>
-</sp-auth-box>
+            </form>
+        </div>
+    </sp-auth-box>
+}
diff --git 
a/ui/src/app/login/components/set-new-password/set-new-password.component.html 
b/ui/src/app/login/components/set-new-password/set-new-password.component.html
index b86960d495..be3eea3667 100644
--- 
a/ui/src/app/login/components/set-new-password/set-new-password.component.html
+++ 
b/ui/src/app/login/components/set-new-password/set-new-password.component.html
@@ -1,87 +1,90 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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.
+~
+-->
 
-<sp-auth-box [linkSettings]="loginSettings.linkSettings" *ngIf="configReady">
-    <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
-        <h1>Set new password</h1>
-    </div>
-    <div fxLayout="column" fxFlex="100">
-        <form [formGroup]="parentForm">
-            <div fxLayout="column">
-                <mat-form-field color="accent">
-                    <mat-label>New password</mat-label>
-                    <input
-                        formControlName="password"
-                        fxFlex
-                        type="password"
-                        matInput
-                        required
-                    />
-                </mat-form-field>
-                <mat-form-field color="accent">
-                    <mat-label>Repeat password</mat-label>
-                    <input
-                        formControlName="repeatPassword"
-                        fxFlex
-                        type="password"
-                        matInput
-                        required
-                    />
-                </mat-form-field>
-                <div class="form-actions" style="margin-top: 20px">
-                    <button
-                        mat-button
-                        mat-flat-button
-                        color="accent"
-                        (click)="setNewPassword()"
-                        [disabled]="!parentForm.valid"
-                        *ngIf="!resetSuccess"
-                    >
-                        <span>Set password</span>
-                    </button>
-                    <mat-spinner
-                        [mode]="'indeterminate'"
-                        color="accent"
-                        [diameter]="20"
-                        *ngIf="resetInProgress"
-                        style="margin-top: 10px"
-                    ></mat-spinner>
-                    <div
-                        class="md-warn"
-                        *ngIf="resetPerformed && !resetSuccess"
-                    >
-                        <h5 class="info-box register-error">
-                            There was an error while resetting your password.
-                        </h5>
-                    </div>
-                    <div
-                        class="md-success"
-                        *ngIf="resetPerformed && resetSuccess"
-                    >
-                        <h5 class="info-box register-success">
-                            Password successfully changed.
-                        </h5>
-                    </div>
-                    <div class="mt-10">
-                        <a [routerLink]="['/login']">Go to login page</a>
+@if (configReady) {
+    <sp-auth-box [linkSettings]="loginSettings.linkSettings">
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
+            <h1>Set new password</h1>
+        </div>
+        <div fxLayout="column" fxFlex="100">
+            <form [formGroup]="parentForm">
+                <div fxLayout="column">
+                    <mat-form-field color="accent">
+                        <mat-label>New password</mat-label>
+                        <input
+                            formControlName="password"
+                            fxFlex
+                            type="password"
+                            matInput
+                            required
+                        />
+                    </mat-form-field>
+                    <mat-form-field color="accent">
+                        <mat-label>Repeat password</mat-label>
+                        <input
+                            formControlName="repeatPassword"
+                            fxFlex
+                            type="password"
+                            matInput
+                            required
+                        />
+                    </mat-form-field>
+                    <div class="form-actions" style="margin-top: 20px">
+                        @if (!resetSuccess) {
+                            <button
+                                mat-button
+                                mat-flat-button
+                                color="accent"
+                                (click)="setNewPassword()"
+                                [disabled]="!parentForm.valid"
+                            >
+                                <span>Set password</span>
+                            </button>
+                        }
+                        @if (resetInProgress) {
+                            <mat-spinner
+                                [mode]="'indeterminate'"
+                                color="accent"
+                                [diameter]="20"
+                                style="margin-top: 10px"
+                            ></mat-spinner>
+                        }
+                        @if (resetPerformed && !resetSuccess) {
+                            <div class="md-warn">
+                                <h5 class="info-box register-error">
+                                    There was an error while resetting your
+                                    password.
+                                </h5>
+                            </div>
+                        }
+                        @if (resetPerformed && resetSuccess) {
+                            <div class="md-success">
+                                <h5 class="info-box register-success">
+                                    Password successfully changed.
+                                </h5>
+                            </div>
+                        }
+                        <div class="mt-10">
+                            <a [routerLink]="['/login']">Go to login page</a>
+                        </div>
                     </div>
                 </div>
-            </div>
-        </form>
-    </div>
-</sp-auth-box>
+            </form>
+        </div>
+    </sp-auth-box>
+}
diff --git a/ui/src/app/login/components/setup/setup.component.html 
b/ui/src/app/login/components/setup/setup.component.html
index 11948d7627..34f5dd47f1 100644
--- a/ui/src/app/login/components/setup/setup.component.html
+++ b/ui/src/app/login/components/setup/setup.component.html
@@ -1,20 +1,20 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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
     class="full-background setup-container light-mode"
@@ -38,129 +38,142 @@
                         setup might take some time)</span
                     >
                 </div>
-                <div
-                    fxFlex="100"
-                    fxLayout="column"
-                    *ngIf="!installationRunning"
-                >
-                    <div class="setup-inline-content">
-                        <h3>Initial User</h3>
-                        <div fxLayout="column">
-                            <mat-form-field fxFlex color="accent">
-                                <mat-label>Email</mat-label>
-                                <input
-                                    [(ngModel)]="setup.adminEmail"
-                                    matInput
-                                    type="email"
-                                    name="email"
-                                    class="sp"
-                                    required
-                                />
-                            </mat-form-field>
-                            <mat-form-field fxFlex color="accent">
-                                <mat-label>Password</mat-label>
-                                <input
-                                    [(ngModel)]="setup.adminPassword"
-                                    matInput
-                                    type="password"
-                                    name="password"
-                                    class="sp"
-                                    required
-                                />
-                            </mat-form-field>
-                            <mat-checkbox
-                                style="margin-bottom: 10px"
-                                color="accent"
-                                [(ngModel)]="setup.installPipelineElements"
-                                name="install"
-                                ><span
-                                    >Also install available data streams,
-                                    processors and sinks.</span
-                                >
-                            </mat-checkbox>
+                @if (!installationRunning) {
+                    <div fxFlex="100" fxLayout="column">
+                        <div class="setup-inline-content">
+                            <h3>Initial User</h3>
+                            <div fxLayout="column">
+                                <mat-form-field fxFlex color="accent">
+                                    <mat-label>Email</mat-label>
+                                    <input
+                                        [(ngModel)]="setup.adminEmail"
+                                        matInput
+                                        type="email"
+                                        name="email"
+                                        class="sp"
+                                        required
+                                    />
+                                </mat-form-field>
+                                <mat-form-field fxFlex color="accent">
+                                    <mat-label>Password</mat-label>
+                                    <input
+                                        [(ngModel)]="setup.adminPassword"
+                                        matInput
+                                        type="password"
+                                        name="password"
+                                        class="sp"
+                                        required
+                                    />
+                                </mat-form-field>
+                                <mat-checkbox
+                                    style="margin-bottom: 10px"
+                                    color="accent"
+                                    [(ngModel)]="setup.installPipelineElements"
+                                    name="install"
+                                    ><span
+                                        >Also install available data streams,
+                                        processors and sinks.</span
+                                    >
+                                </mat-checkbox>
+                            </div>
                         </div>
                     </div>
-                </div>
-                <div
-                    *ngIf="installationRunning"
-                    #scroll
-                    class="installation-status-container"
-                >
-                    <div fxLayout="column" class="setup-inline-content">
-                        <div *ngFor="let msg of installationResults">
-                            <div fxFlex fxLayout="row">
-                                <div fxFlex="80" style="width: 50%">
-                                    <h4>{{ msg.notifications[0].title }}</h4>
+                }
+                @if (installationRunning) {
+                    <div #scroll class="installation-status-container">
+                        <div fxLayout="column" class="setup-inline-content">
+                            @for (msg of installationResults; track msg) {
+                                <div>
+                                    <div fxFlex fxLayout="row">
+                                        <div fxFlex="80" style="width: 50%">
+                                            <h4>
+                                                {{ msg.notifications[0].title 
}}
+                                            </h4>
+                                        </div>
+                                        <div fxFlex="20" style="width: 50%">
+                                            @if (msg.success) {
+                                                <mat-icon
+                                                    class="md-accent"
+                                                    color="accent"
+                                                    style="
+                                                        width: 36px;
+                                                        height: 36px;
+                                                    "
+                                                    >done
+                                                </mat-icon>
+                                            }
+                                            @if (!msg.success) {
+                                                <mat-icon
+                                                    class="md-accent"
+                                                    color="accent"
+                                                    style="
+                                                        width: 36px;
+                                                        height: 36px;
+                                                    "
+                                                    >error
+                                                </mat-icon>
+                                            }
+                                        </div>
+                                    </div>
                                 </div>
-                                <div fxFlex="20" style="width: 50%">
-                                    <mat-icon
-                                        class="md-accent"
-                                        color="accent"
-                                        style="width: 36px; height: 36px"
-                                        *ngIf="msg.success"
-                                        >done
-                                    </mat-icon>
-                                    <mat-icon
-                                        class="md-accent"
-                                        color="accent"
-                                        style="width: 36px; height: 36px"
-                                        *ngIf="!msg.success"
-                                        >error
-                                    </mat-icon>
+                            }
+                            @if (nextTaskTitle !== '') {
+                                <div fxFlex fxLayout="row">
+                                    <div fxFlex="80" style="width: 50%">
+                                        <h4>{{ nextTaskTitle }}</h4>
+                                    </div>
+                                    <div fxFlex="20" style="width: 50%">
+                                        @if (loading) {
+                                            <mat-spinner
+                                                class="md-accent"
+                                                [mode]="'indeterminate'"
+                                                [diameter]="20"
+                                                style="margin-top: 10px"
+                                            ></mat-spinner>
+                                        }
+                                    </div>
                                 </div>
-                            </div>
-                        </div>
-                        <div fxFlex fxLayout="row" *ngIf="nextTaskTitle !== 
''">
-                            <div fxFlex="80" style="width: 50%">
-                                <h4>{{ nextTaskTitle }}</h4>
-                            </div>
-                            <div fxFlex="20" style="width: 50%">
-                                <mat-spinner
-                                    class="md-accent"
-                                    [mode]="'indeterminate'"
-                                    [diameter]="20"
-                                    style="margin-top: 10px"
-                                    *ngIf="loading"
-                                ></mat-spinner>
-                            </div>
+                            }
                         </div>
                     </div>
-                </div>
+                }
                 <mat-divider></mat-divider>
                 <div fxLayout="row" fxLayoutAlign="center center">
                     <div
                         fxLayout="row"
                         style="margin-top: 10px; margin-bottom: 10px"
                     >
-                        <button
-                            mat-button
-                            mat-flat-button
-                            color="accent"
-                            [disabled]="
-                                !setupForm.valid ||
-                                loading ||
-                                installationFinished
-                            "
-                            (click)="configure(0)"
-                            *ngIf="!installationFinished"
-                        >
-                            <span>{{
-                                !installationRunning
-                                    ? 'Install'
-                                    : 'Installing...'
-                            }}</span>
-                        </button>
-                        <button
-                            mat-button
-                            mat-flat-button
-                            color="accent"
-                            (click)="openLoginPage()"
-                            *ngIf="installationFinished"
-                            data-cy="sp-button-finish-installation"
-                        >
-                            <mat-icon>arrow_forward</mat-icon>
-                            <span>Go to login page</span>
-                        </button>
+                        @if (!installationFinished) {
+                            <button
+                                mat-button
+                                mat-flat-button
+                                color="accent"
+                                [disabled]="
+                                    !setupForm.valid ||
+                                    loading ||
+                                    installationFinished
+                                "
+                                (click)="configure(0)"
+                            >
+                                <span>{{
+                                    !installationRunning
+                                        ? 'Install'
+                                        : 'Installing...'
+                                }}</span>
+                            </button>
+                        }
+                        @if (installationFinished) {
+                            <button
+                                mat-button
+                                mat-flat-button
+                                color="accent"
+                                (click)="openLoginPage()"
+                                data-cy="sp-button-finish-installation"
+                            >
+                                <mat-icon>arrow_forward</mat-icon>
+                                <span>Go to login page</span>
+                            </button>
+                        }
                     </div>
                 </div>
             </form>
diff --git a/ui/src/app/notifications/notifications.component.html 
b/ui/src/app/notifications/notifications.component.html
index 3128fc704a..d15ad13f4c 100644
--- a/ui/src/app/notifications/notifications.component.html
+++ b/ui/src/app/notifications/notifications.component.html
@@ -1,20 +1,20 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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.
+~
+-->
 
 <sp-basic-view class="page-container-max-height">
     <div fxLayout="row" nav>
@@ -29,109 +29,120 @@
             </div>
         </div>
     </div>
-    <div
-        class="container-fluid marketplace-container"
-        *ngIf="notificationsLoading"
-        fxFlex="100"
-        fxLayoutAlign="center center"
-        fxLayout="column"
-    >
-        <mat-spinner [mode]="'indeterminate'" [diameter]="20"></mat-spinner>
-        <h4>Loading notifications...</h4>
-    </div>
-    <div
-        class="fixed-height page-container-padding-inner"
-        *ngIf="!notificationsLoading && !pipelinesWithNotificationsPresent"
-        fxFlex="100"
-        fxLayoutAlign="center center"
-        fxLayout="row"
-    >
-        <h4>
-            No notifications available. Create a new pipeline using the
-            Notification Sink to create your first notification!
-        </h4>
-    </div>
-    <div
-        class="fixed-height page-container-padding-inner"
-        fxLayout="row"
-        fxFlex="100"
-        *ngIf="!notificationsLoading && pipelinesWithNotificationsPresent"
-    >
-        <div fxFlex="30" class="notifications-overview scrolling-auto">
-            <mat-list>
-                <mat-list-item
-                    *ngFor="let existingNotification of existingNotifications"
-                    (click)="selectNotification(existingNotification)"
-                    class="list-item"
-                    [ngClass]="{
-                        'selected-notification':
-                            existingNotification.notificationId ===
-                            currentlySelectedNotificationId
-                    }"
-                >
+    @if (notificationsLoading) {
+        <div
+            class="container-fluid marketplace-container"
+            fxFlex="100"
+            fxLayoutAlign="center center"
+            fxLayout="column"
+        >
+            <mat-spinner [mode]="'indeterminate'" 
[diameter]="20"></mat-spinner>
+            <h4>Loading notifications...</h4>
+        </div>
+    }
+    @if (!notificationsLoading && !pipelinesWithNotificationsPresent) {
+        <div
+            class="fixed-height page-container-padding-inner"
+            fxFlex="100"
+            fxLayoutAlign="center center"
+            fxLayout="row"
+        >
+            <h4>
+                No notifications available. Create a new pipeline using the
+                Notification Sink to create your first notification!
+            </h4>
+        </div>
+    }
+    @if (!notificationsLoading && pipelinesWithNotificationsPresent) {
+        <div
+            class="fixed-height page-container-padding-inner"
+            fxLayout="row"
+            fxFlex="100"
+        >
+            <div fxFlex="30" class="notifications-overview scrolling-auto">
+                <mat-list>
+                    @for (
+                        existingNotification of existingNotifications;
+                        track existingNotification
+                    ) {
+                        <mat-list-item
+                            (click)="selectNotification(existingNotification)"
+                            class="list-item"
+                            [ngClass]="{
+                                'selected-notification':
+                                    existingNotification.notificationId ===
+                                    currentlySelectedNotificationId
+                            }"
+                        >
+                            <div
+                                matListItemAvatar
+                                class="notification-avatar sp-primary-bg"
+                                style="background: var(--color-primary)"
+                            >
+                                {{
+                                    elementIconText.getElementIconText(
+                                        existingNotification.pipelineName
+                                    )
+                                }}
+                            </div>
+                            <h4 matListItemTitle>
+                                {{ existingNotification.pipelineName }}
+                            </h4>
+                            <p matListItemLine>
+                                {{ existingNotification.notificationTitle }}
+                            </p>
+                            <div class="new-notification-info-panel">
+                                @if (
+                                    currentlySelectedNotificationId !==
+                                        existingNotification.notificationId &&
+                                    newNotificationInfo[
+                                        existingNotification.notificationId
+                                    ]
+                                ) {
+                                    <div class="new-notification-info"></div>
+                                }
+                            </div>
+                        </mat-list-item>
+                    }
+                </mat-list>
+            </div>
+            <div fxFlex="70" class="notifications-details">
+                <div class="notification-details-wrapper">
                     <div
-                        matListItemAvatar
-                        class="notification-avatar sp-primary-bg"
-                        style="background: var(--color-primary)"
+                        class="notification-header"
+                        fxLayout="column"
+                        fxLayoutAlign="center start"
                     >
-                        {{
-                            elementIconText.getElementIconText(
-                                existingNotification.pipelineName
-                            )
-                        }}
+                        <div class="notification-header-pipeline-name">
+                            {{ currentlySelectedNotification.pipelineName }}
+                        </div>
+                        <div class="notification-header-notification-name">
+                            {{
+                                currentlySelectedNotification.notificationTitle
+                            }}
+                        </div>
+                        <hr class="header-divider" />
                     </div>
-                    <h4 matListItemTitle>
-                        {{ existingNotification.pipelineName }}
-                    </h4>
-                    <p matListItemLine>
-                        {{ existingNotification.notificationTitle }}
-                    </p>
-                    <div class="new-notification-info-panel">
+                    @if (currentlySelectedNotificationId) {
                         <div
-                            class="new-notification-info"
-                            *ngIf="
-                                currentlySelectedNotificationId !==
-                                    existingNotification.notificationId &&
-                                newNotificationInfo[
-                                    existingNotification.notificationId
-                                ]
-                            "
-                        ></div>
-                    </div>
-                </mat-list-item>
-            </mat-list>
-        </div>
-        <div fxFlex="70" class="notifications-details">
-            <div class="notification-details-wrapper">
-                <div
-                    class="notification-header"
-                    fxLayout="column"
-                    fxLayoutAlign="center start"
-                >
-                    <div class="notification-header-pipeline-name">
-                        {{ currentlySelectedNotification.pipelineName }}
-                    </div>
-                    <div class="notification-header-notification-name">
-                        {{ currentlySelectedNotification.notificationTitle }}
-                    </div>
-                    <hr class="header-divider" />
-                </div>
-                <div
-                    #notificationPane
-                    class="notification-pane"
-                    (scroll)="onScroll()"
-                    *ngIf="currentlySelectedNotificationId"
-                >
-                    <sp-notification-item
-                        [notification]="notification"
-                        *ngFor="
-                            let notification of allNotifications.get(
-                                currentlySelectedNotificationId
-                            )
-                        "
-                    ></sp-notification-item>
+                            #notificationPane
+                            class="notification-pane"
+                            (scroll)="onScroll()"
+                        >
+                            @for (
+                                notification of allNotifications.get(
+                                    currentlySelectedNotificationId
+                                );
+                                track notification
+                            ) {
+                                <sp-notification-item
+                                    [notification]="notification"
+                                ></sp-notification-item>
+                            }
+                        </div>
+                    }
                 </div>
             </div>
         </div>
-    </div>
+    }
 </sp-basic-view>
diff --git 
a/ui/src/app/profile/components/general/general-profile-settings.component.html 
b/ui/src/app/profile/components/general/general-profile-settings.component.html
index f56c59865d..0ae9910f87 100644
--- 
a/ui/src/app/profile/components/general/general-profile-settings.component.html
+++ 
b/ui/src/app/profile/components/general/general-profile-settings.component.html
@@ -1,128 +1,129 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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="page-container-padding">
-    <div
-        fxFlex="100"
-        fxLayout="column"
-        fxLayoutAlign="start start"
-        *ngIf="profileLoaded"
-    >
-        <sp-split-section
-            [title]="'Profile' | translate"
-            [subtitle]="'Manage your basic profile settings here' | translate"
-        >
-            <sp-warning-box *ngIf="isExternalUser">
-                {{
-                    'Settings for externally-managed users cannot be changed'
-                        | translate
-                }}
-            </sp-warning-box>
-            <div fxLayout="row" fxLayoutAlign="start center">
-                <span>{{ userData.username }}</span>
-                <button
-                    [disabled]="isExternalUser"
-                    mat-button
-                    mat-flat-button
-                    color="accent"
-                    class="ml-15"
-                    (click)="openChangeEmailDialog()"
-                >
-                    {{ 'Change email' | translate }}
-                </button>
-            </div>
-            <mat-form-field fxFlex color="accent" class="mt-10 mb-10">
-                <mat-label>{{ 'Full name' | translate }}</mat-label>
-                <input
-                    [disabled]="isExternalUser"
-                    [(ngModel)]="userData.fullName"
-                    matInput
-                />
-            </mat-form-field>
-            <mat-form-field fxFlex color="accent" class="mt-10 mb-10">
-                <mat-label>{{ 'Language' | translate }}</mat-label>
-                <mat-select [(ngModel)]="selectedLanguage">
-                    <mat-option
-                        *ngFor="let lang of availableLanguages"
-                        [value]="lang.id"
-                    >
-                        {{ lang.label }}
-                    </mat-option>
-                </mat-select>
-            </mat-form-field>
-            <div fxLayout="row" fxLayoutAlign="start center">
-                <button
-                    mat-button
-                    mat-flat-button
-                    color="accent"
-                    (click)="saveProfileSettings()"
-                >
-                    {{ 'Update profile' | translate }}
-                </button>
-                <button
-                    [disabled]="isExternalUser"
-                    mat-button
-                    mat-flat-button
-                    color="accent"
-                    class="ml-15"
-                    (click)="openChangePasswordDialog()"
-                >
-                    {{ 'Change password' | translate }}
-                </button>
-            </div>
-        </sp-split-section>
-        <mat-divider></mat-divider>
-        <div fxLayout="row" fxFlex="100" class="mt-30">
+    @if (profileLoaded) {
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
             <sp-split-section
-                [title]="'Appearance' | translate"
+                [title]="'Profile' | translate"
                 [subtitle]="
-                    'Change the look and feel of your installation' | translate
+                    'Manage your basic profile settings here' | translate
                 "
             >
-                <label id="radio-group-label">Color Scheme</label>
-                <mat-radio-group
-                    [(ngModel)]="darkMode"
-                    aria-labelledby="radio-group-label"
-                    class="appearance-radio-group"
-                    (ngModelChange)="changeModePreview($event)"
-                >
-                    <mat-radio-button
-                        [value]="false"
-                        class="appearance-radio-button"
-                        >{{ 'Light mode' | translate }}</mat-radio-button
+                @if (isExternalUser) {
+                    <sp-warning-box>
+                        {{
+                            'Settings for externally-managed users cannot be 
changed'
+                                | translate
+                        }}
+                    </sp-warning-box>
+                }
+                <div fxLayout="row" fxLayoutAlign="start center">
+                    <span>{{ userData.username }}</span>
+                    <button
+                        [disabled]="isExternalUser"
+                        mat-button
+                        mat-flat-button
+                        color="accent"
+                        class="ml-15"
+                        (click)="openChangeEmailDialog()"
                     >
-                    <mat-radio-button
-                        [value]="true"
-                        class="appearance-radio-button"
-                        >{{ 'Dark mode' | translate }}</mat-radio-button
+                        {{ 'Change email' | translate }}
+                    </button>
+                </div>
+                <mat-form-field fxFlex color="accent" class="mt-10 mb-10">
+                    <mat-label>{{ 'Full name' | translate }}</mat-label>
+                    <input
+                        [disabled]="isExternalUser"
+                        [(ngModel)]="userData.fullName"
+                        matInput
+                    />
+                </mat-form-field>
+                <mat-form-field fxFlex color="accent" class="mt-10 mb-10">
+                    <mat-label>{{ 'Language' | translate }}</mat-label>
+                    <mat-select [(ngModel)]="selectedLanguage">
+                        @for (lang of availableLanguages; track lang) {
+                            <mat-option [value]="lang.id">
+                                {{ lang.label }}
+                            </mat-option>
+                        }
+                    </mat-select>
+                </mat-form-field>
+                <div fxLayout="row" fxLayoutAlign="start center">
+                    <button
+                        mat-button
+                        mat-flat-button
+                        color="accent"
+                        (click)="saveProfileSettings()"
                     >
-                </mat-radio-group>
-                <div>
+                        {{ 'Update profile' | translate }}
+                    </button>
                     <button
+                        [disabled]="isExternalUser"
                         mat-button
                         mat-flat-button
                         color="accent"
-                        (click)="updateAppearanceMode()"
+                        class="ml-15"
+                        (click)="openChangePasswordDialog()"
                     >
-                        {{ 'Save color schema' | translate }}
+                        {{ 'Change password' | translate }}
                     </button>
                 </div>
             </sp-split-section>
+            <mat-divider></mat-divider>
+            <div fxLayout="row" fxFlex="100" class="mt-30">
+                <sp-split-section
+                    [title]="'Appearance' | translate"
+                    [subtitle]="
+                        'Change the look and feel of your installation'
+                            | translate
+                    "
+                >
+                    <label id="radio-group-label">Color Scheme</label>
+                    <mat-radio-group
+                        [(ngModel)]="darkMode"
+                        aria-labelledby="radio-group-label"
+                        class="appearance-radio-group"
+                        (ngModelChange)="changeModePreview($event)"
+                    >
+                        <mat-radio-button
+                            [value]="false"
+                            class="appearance-radio-button"
+                            >{{ 'Light mode' | translate }}</mat-radio-button
+                        >
+                        <mat-radio-button
+                            [value]="true"
+                            class="appearance-radio-button"
+                            >{{ 'Dark mode' | translate }}</mat-radio-button
+                        >
+                    </mat-radio-group>
+                    <div>
+                        <button
+                            mat-button
+                            mat-flat-button
+                            color="accent"
+                            (click)="updateAppearanceMode()"
+                        >
+                            {{ 'Save color schema' | translate }}
+                        </button>
+                    </div>
+                </sp-split-section>
+            </div>
         </div>
-    </div>
+    }
 </div>
diff --git 
a/ui/src/app/profile/components/token/token-management-settings.component.html 
b/ui/src/app/profile/components/token/token-management-settings.component.html
index f32894612b..5db2d773c0 100644
--- 
a/ui/src/app/profile/components/token/token-management-settings.component.html
+++ 
b/ui/src/app/profile/components/token/token-management-settings.component.html
@@ -1,180 +1,179 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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="page-container-padding">
-    <div
-        fxFlex="100"
-        fxLayout="column"
-        fxLayoutAlign="start start"
-        *ngIf="profileLoaded"
-    >
-        <sp-split-section
-            [title]="'API Keys' | translate"
-            [subtitle]="
-                'Manage your API keys for third-party application access.'
-                    | translate
-            "
-        >
-            <div fxLayout="column" class="subsection">
-                <div class="subsection-title">
-                    {{ 'New API key' | translate }}
-                </div>
-                <mat-form-field fxFlex color="accent">
-                    <mat-label>{{ 'Name' | translate }}</mat-label>
-                    <input
-                        [(ngModel)]="newTokenName"
-                        matInput
-                        [formControl]="tokenNameFormControl"
-                    />
-                    <mat-error
-                        *ngIf="tokenNameFormControl.hasError('required')"
-                    >
-                        Token name is required.
-                    </mat-error>
-                    <mat-error
-                        *ngIf="
+    @if (profileLoaded) {
+        <div fxFlex="100" fxLayout="column" fxLayoutAlign="start start">
+            <sp-split-section
+                [title]="'API Keys' | translate"
+                [subtitle]="
+                    'Manage your API keys for third-party application access.'
+                        | translate
+                "
+            >
+                <div fxLayout="column" class="subsection">
+                    <div class="subsection-title">
+                        {{ 'New API key' | translate }}
+                    </div>
+                    <mat-form-field fxFlex color="accent">
+                        <mat-label>{{ 'Name' | translate }}</mat-label>
+                        <input
+                            [(ngModel)]="newTokenName"
+                            matInput
+                            [formControl]="tokenNameFormControl"
+                        />
+                        @if (tokenNameFormControl.hasError('required')) {
+                            <mat-error> Token name is required. </mat-error>
+                        }
+                        @if (
                             tokenNameFormControl.hasError('minlength') ||
                             tokenNameFormControl.hasError('pattern')
-                        "
-                    >
-                        {{
-                            'Token name must be at least 3 characters long and 
contain only alphanumeric ' +
-                                'characters, hyphens, or underscores.'
-                                | translate
-                        }}
-                    </mat-error>
-                </mat-form-field>
-                <div>
-                    <button
-                        class="mt-5"
-                        mat-button
-                        mat-flat-button
-                        color="accent"
-                        [disabled]="!tokenNameFormControl.valid"
-                        (click)="requestNewKey()"
-                    >
-                        {{ 'Create new API key' | translate }}
-                    </button>
-                </div>
-            </div>
-            <div
-                fxLayout="column"
-                class="subsection mt-10"
-                *ngIf="newTokenCreated"
-            >
-                <div class="subsection-title">
-                    {{ 'Key created' | translate }}
-                </div>
-                <div class="subsection-small">
-                    {{
-                        "Your new API key has been created. Please copy the 
key now - you won't be able to see the key again."
-                            | translate
-                    }}
+                        ) {
+                            <mat-error>
+                                {{
+                                    'Token name must be at least 3 characters 
long and contain only alphanumeric ' +
+                                        'characters, hyphens, or underscores.'
+                                        | translate
+                                }}
+                            </mat-error>
+                        }
+                    </mat-form-field>
+                    <div>
+                        <button
+                            class="mt-5"
+                            mat-button
+                            mat-flat-button
+                            color="accent"
+                            [disabled]="!tokenNameFormControl.valid"
+                            (click)="requestNewKey()"
+                        >
+                            {{ 'Create new API key' | translate }}
+                        </button>
+                    </div>
                 </div>
-                <div
-                    fxFlex="100"
-                    fxLayout="row"
-                    fxLayoutAlign="start center"
-                    class="new-token"
-                >
-                    <div class="token-name">
-                        {{ newlyCreatedToken.tokenName }}
+                @if (newTokenCreated) {
+                    <div fxLayout="column" class="subsection mt-10">
+                        <div class="subsection-title">
+                            {{ 'Key created' | translate }}
+                        </div>
+                        <div class="subsection-small">
+                            {{
+                                "Your new API key has been created. Please 
copy the key now - you won't be able to see the key again."
+                                    | translate
+                            }}
+                        </div>
+                        <div
+                            fxFlex="100"
+                            fxLayout="row"
+                            fxLayoutAlign="start center"
+                            class="new-token"
+                        >
+                            <div class="token-name">
+                                {{ newlyCreatedToken.tokenName }}
+                            </div>
+                            <div class="displayed-token">
+                                {{ newlyCreatedToken.rawToken }}
+                            </div>
+                            <button
+                                mat-button
+                                mat-flat-button
+                                color="accent"
+                                [cdkCopyToClipboard]="
+                                    newlyCreatedToken.rawToken
+                                "
+                            >
+                                Copy
+                            </button>
+                        </div>
                     </div>
-                    <div class="displayed-token">
-                        {{ newlyCreatedToken.rawToken }}
+                }
+                <mat-divider class="divider"></mat-divider>
+                <div fxLayout="column" class="subsection mt-10">
+                    <div class="subsection-title">
+                        {{ 'Existing API keys' | translate }}
                     </div>
-                    <button
-                        mat-button
-                        mat-flat-button
-                        color="accent"
-                        [cdkCopyToClipboard]="newlyCreatedToken.rawToken"
-                    >
-                        Copy
-                    </button>
-                </div>
-            </div>
-            <mat-divider class="divider"></mat-divider>
-            <div fxLayout="column" class="subsection mt-10">
-                <div class="subsection-title">
-                    {{ 'Existing API keys' | translate }}
+                    @if (userData.userApiTokens.length === 0) {
+                        <div>({{ 'no keys available' | translate }})</div>
+                    }
+                    @if (userData.userApiTokens.length > 0) {
+                        <table
+                            mat-table
+                            [dataSource]="apiKeyDataSource"
+                            class="mat-elevation-z0"
+                        >
+                            <ng-container matColumnDef="name">
+                                <th mat-header-cell *matHeaderCellDef>Name</th>
+                                <td mat-cell *matCellDef="let element">
+                                    {{ element.tokenName }}
+                                </td>
+                            </ng-container>
+                            <!-- Name Column -->
+                            <ng-container matColumnDef="action">
+                                <th mat-header-cell *matHeaderCellDef>
+                                    Action
+                                </th>
+                                <td mat-cell *matCellDef="let element">
+                                    <div fxLayout="end end">
+                                        <button
+                                            mat-button
+                                            mat-flat-button
+                                            class="btn-warn"
+                                            (click)="revokeApiKey(element)"
+                                        >
+                                            Revoke
+                                        </button>
+                                    </div>
+                                </td>
+                            </ng-container>
+                            <tr
+                                mat-header-row
+                                *matHeaderRowDef="displayedColumns"
+                            ></tr>
+                            <tr
+                                mat-row
+                                *matRowDef="let row; columns: displayedColumns"
+                            ></tr>
+                        </table>
+                    }
                 </div>
-                <div *ngIf="userData.userApiTokens.length === 0">
-                    ({{ 'no keys available' | translate }})
-                </div>
-                <table
-                    mat-table
-                    [dataSource]="apiKeyDataSource"
-                    class="mat-elevation-z0"
-                    *ngIf="userData.userApiTokens.length > 0"
-                >
-                    <ng-container matColumnDef="name">
-                        <th mat-header-cell *matHeaderCellDef>Name</th>
-                        <td mat-cell *matCellDef="let element">
-                            {{ element.tokenName }}
-                        </td>
-                    </ng-container>
-
-                    <!-- Name Column -->
-                    <ng-container matColumnDef="action">
-                        <th mat-header-cell *matHeaderCellDef>Action</th>
-                        <td mat-cell *matCellDef="let element">
-                            <div fxLayout="end end">
-                                <button
-                                    mat-button
-                                    mat-flat-button
-                                    class="btn-warn"
-                                    (click)="revokeApiKey(element)"
-                                >
-                                    Revoke
-                                </button>
-                            </div>
-                        </td>
-                    </ng-container>
-
-                    <tr mat-header-row 
*matHeaderRowDef="displayedColumns"></tr>
-                    <tr
-                        mat-row
-                        *matRowDef="let row; columns: displayedColumns"
-                    ></tr>
-                </table>
-            </div>
-        </sp-split-section>
-        <mat-divider></mat-divider>
-        <sp-split-section
-            [title]="'API Docs' | translate"
-            [subtitle]="
-                'View the documentation of the API. Here you can see all 
provided endpoints and how to query them.'
-                    | translate
-            "
-        >
-            <div fxLayout="column" class="subsection">
-                <div fxLayout="column" class="subsection mt-8"></div>
-                <div>
-                    <button
-                        mat-button
-                        mat-flat-button
-                        color="accent"
-                        routerLink="/apidocs"
-                    >
-                        {{ 'View API Docs' | translate }}
-                    </button>
+            </sp-split-section>
+            <mat-divider></mat-divider>
+            <sp-split-section
+                [title]="'API Docs' | translate"
+                [subtitle]="
+                    'View the documentation of the API. Here you can see all 
provided endpoints and how to query them.'
+                        | translate
+                "
+            >
+                <div fxLayout="column" class="subsection">
+                    <div fxLayout="column" class="subsection mt-8"></div>
+                    <div>
+                        <button
+                            mat-button
+                            mat-flat-button
+                            color="accent"
+                            routerLink="/apidocs"
+                        >
+                            {{ 'View API Docs' | translate }}
+                        </button>
+                    </div>
                 </div>
-            </div>
-        </sp-split-section>
-    </div>
+            </sp-split-section>
+        </div>
+    }
 </div>
diff --git 
a/ui/src/app/profile/dialog/change-email/change-email-dialog.component.html 
b/ui/src/app/profile/dialog/change-email/change-email-dialog.component.html
index d81fbf2173..0efe7a5134 100644
--- a/ui/src/app/profile/dialog/change-email/change-email-dialog.component.html
+++ b/ui/src/app/profile/dialog/change-email/change-email-dialog.component.html
@@ -1,79 +1,82 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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 class="sp-dialog-container">
     <div class="sp-dialog-content">
         <div fxFlex="100" fxLayout="column" class="p-15">
-            <form
-                [formGroup]="parentForm"
-                fxFlex="100"
-                fxLayout="column"
-                *ngIf="!operationApplied"
-            >
-                <div class="general-options-panel" fxLayout="column">
-                    <mat-form-field color="accent">
-                        <mat-label>New mail address</mat-label>
-                        <input
-                            formControlName="email"
-                            fxFlex
-                            matInput
-                            required
-                        />
-                        <mat-error>Must be a valid email address.</mat-error>
-                    </mat-form-field>
-                    <mat-form-field color="accent">
-                        <mat-label>Re-enter mail address</mat-label>
-                        <input
-                            formControlName="emailConfirm"
-                            fxFlex
-                            matInput
-                            required
-                        />
-                        <mat-error>Must be a valid email address.</mat-error>
-                    </mat-form-field>
-                    <mat-error *ngIf="parentForm.hasError('notMatching')"
-                        >Email does not match.</mat-error
+            @if (!operationApplied) {
+                <form [formGroup]="parentForm" fxFlex="100" fxLayout="column">
+                    <div class="general-options-panel" fxLayout="column">
+                        <mat-form-field color="accent">
+                            <mat-label>New mail address</mat-label>
+                            <input
+                                formControlName="email"
+                                fxFlex
+                                matInput
+                                required
+                            />
+                            <mat-error
+                                >Must be a valid email address.</mat-error
+                            >
+                        </mat-form-field>
+                        <mat-form-field color="accent">
+                            <mat-label>Re-enter mail address</mat-label>
+                            <input
+                                formControlName="emailConfirm"
+                                fxFlex
+                                matInput
+                                required
+                            />
+                            <mat-error
+                                >Must be a valid email address.</mat-error
+                            >
+                        </mat-form-field>
+                        @if (parentForm.hasError('notMatching')) {
+                            <mat-error>Email does not match.</mat-error>
+                        }
+                        <mat-form-field color="accent">
+                            <mat-label>Enter password</mat-label>
+                            <input
+                                formControlName="passwordConfirm"
+                                fxFlex
+                                matInput
+                                type="password"
+                                required
+                            />
+                        </mat-form-field>
+                    </div>
+                </form>
+            }
+            @if (operationApplied && error) {
+                <div>
+                    <div>Could not change email address.</div>
+                    <div>Reason: {{ errorMessage }}</div>
+                    <button
+                        class="mt-20"
+                        mat-button
+                        mat-flat-button
+                        color="accent"
+                        (click)="operationApplied = false"
                     >
-                    <mat-form-field color="accent">
-                        <mat-label>Enter password</mat-label>
-                        <input
-                            formControlName="passwordConfirm"
-                            fxFlex
-                            matInput
-                            type="password"
-                            required
-                        />
-                    </mat-form-field>
+                        Try again
+                    </button>
                 </div>
-            </form>
-            <div *ngIf="operationApplied && error">
-                <div>Could not change email address.</div>
-                <div>Reason: {{ errorMessage }}</div>
-                <button
-                    class="mt-20"
-                    mat-button
-                    mat-flat-button
-                    color="accent"
-                    (click)="operationApplied = false"
-                >
-                    Try again
-                </button>
-            </div>
+            }
         </div>
     </div>
     <mat-divider></mat-divider>
diff --git 
a/ui/src/app/profile/dialog/change-password/change-password-dialog.component.html
 
b/ui/src/app/profile/dialog/change-password/change-password-dialog.component.html
index 7c16e76273..a8fee51b40 100644
--- 
a/ui/src/app/profile/dialog/change-password/change-password-dialog.component.html
+++ 
b/ui/src/app/profile/dialog/change-password/change-password-dialog.component.html
@@ -1,79 +1,78 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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 class="sp-dialog-container">
     <div class="sp-dialog-content">
         <div fxFlex="100" fxLayout="column" class="p-15">
-            <form
-                [formGroup]="parentForm"
-                fxFlex="100"
-                fxLayout="column"
-                *ngIf="!operationApplied"
-            >
-                <div class="general-options-panel" fxLayout="column">
-                    <mat-form-field color="accent">
-                        <mat-label>Current password</mat-label>
-                        <input
-                            formControlName="currentPassword"
-                            fxFlex
-                            matInput
-                            type="password"
-                            required
-                        />
-                    </mat-form-field>
-                    <mat-form-field color="accent">
-                        <mat-label>New password</mat-label>
-                        <input
-                            formControlName="newPassword"
-                            fxFlex
-                            matInput
-                            type="password"
-                            required
-                        />
-                    </mat-form-field>
-                    <mat-form-field color="accent">
-                        <mat-label>New password</mat-label>
-                        <input
-                            formControlName="newPasswordConfirm"
-                            fxFlex
-                            matInput
-                            type="password"
-                            required
-                        />
-                    </mat-form-field>
-                    <mat-error *ngIf="parentForm.hasError('notMatching')"
-                        >Passwords do not match.</mat-error
+            @if (!operationApplied) {
+                <form [formGroup]="parentForm" fxFlex="100" fxLayout="column">
+                    <div class="general-options-panel" fxLayout="column">
+                        <mat-form-field color="accent">
+                            <mat-label>Current password</mat-label>
+                            <input
+                                formControlName="currentPassword"
+                                fxFlex
+                                matInput
+                                type="password"
+                                required
+                            />
+                        </mat-form-field>
+                        <mat-form-field color="accent">
+                            <mat-label>New password</mat-label>
+                            <input
+                                formControlName="newPassword"
+                                fxFlex
+                                matInput
+                                type="password"
+                                required
+                            />
+                        </mat-form-field>
+                        <mat-form-field color="accent">
+                            <mat-label>New password</mat-label>
+                            <input
+                                formControlName="newPasswordConfirm"
+                                fxFlex
+                                matInput
+                                type="password"
+                                required
+                            />
+                        </mat-form-field>
+                        @if (parentForm.hasError('notMatching')) {
+                            <mat-error>Passwords do not match.</mat-error>
+                        }
+                    </div>
+                </form>
+            }
+            @if (operationApplied && error) {
+                <div>
+                    <div>Could not change the password.</div>
+                    <div>Reason: {{ errorMessage }}</div>
+                    <button
+                        class="mt-20"
+                        mat-button
+                        mat-flat-button
+                        color="accent"
+                        (click)="operationApplied = false"
                     >
+                        Try again
+                    </button>
                 </div>
-            </form>
-            <div *ngIf="operationApplied && error">
-                <div>Could not change the password.</div>
-                <div>Reason: {{ errorMessage }}</div>
-                <button
-                    class="mt-20"
-                    mat-button
-                    mat-flat-button
-                    color="accent"
-                    (click)="operationApplied = false"
-                >
-                    Try again
-                </button>
-            </div>
+            }
         </div>
     </div>
     <mat-divider></mat-divider>
diff --git a/ui/src/app/profile/profile.component.html 
b/ui/src/app/profile/profile.component.html
index 0db10fb3e9..8de54d0c88 100644
--- a/ui/src/app/profile/profile.component.html
+++ b/ui/src/app/profile/profile.component.html
@@ -1,20 +1,20 @@
 <!--
-  ~ 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.
-  ~
-  -->
+~ 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.
+~
+-->
 
 <sp-basic-view>
     <div fxLayout="row" nav>
@@ -41,25 +41,19 @@
         fxLayout="column"
         fxFlex="100"
     >
-        <div
-            class="fixed-height"
-            fxLayout="column"
-            fxFlex="100"
-            *ngIf="selectedIndex === 0"
-        >
-            <sp-general-profile-settings
-                fxFlex="100"
-            ></sp-general-profile-settings>
-        </div>
-        <div
-            class="fixed-height"
-            fxLayout="column"
-            fxFlex="100"
-            *ngIf="selectedIndex === 1"
-        >
-            <sp-token-management-settings
-                fxFlex="100"
-            ></sp-token-management-settings>
-        </div>
+        @if (selectedIndex === 0) {
+            <div class="fixed-height" fxLayout="column" fxFlex="100">
+                <sp-general-profile-settings
+                    fxFlex="100"
+                ></sp-general-profile-settings>
+            </div>
+        }
+        @if (selectedIndex === 1) {
+            <div class="fixed-height" fxLayout="column" fxFlex="100">
+                <sp-token-management-settings
+                    fxFlex="100"
+                ></sp-token-management-settings>
+            </div>
+        }
     </div>
 </sp-basic-view>

Reply via email to