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

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


The following commit(s) were added to refs/heads/dev by this push:
     new 4b37c0e6ec feat(#2975): Add configurable documentation links (#2978)
4b37c0e6ec is described below

commit 4b37c0e6ecd8a6cb32f140fe6a81fad965ced99b
Author: Dominik Riemer <[email protected]>
AuthorDate: Sun Jun 30 22:14:44 2024 +0200

    feat(#2975): Add configurable documentation links (#2978)
    
    * feat(#2975): Add documentation links to model, modify info view
    
    * feat(#2975): Add configurable application links
    
    * Fix checkstyle
    
    ---------
    
    Co-authored-by: Dominik Riemer <[email protected]>
---
 .idea/runConfigurations/ui.xml                     |   2 +-
 .../model/configuration/DefaultGeneralConfig.java  |  17 +-
 .../model/configuration/DefaultLinkSettings.java   |  22 +-
 .../configuration/DefaultSpCoreConfiguration.java  |   2 +-
 .../model/configuration/GeneralConfig.java         |   9 +
 .../model/configuration/LinkSettings.java          |  19 +-
 .../streampipes/rest/impl/Authentication.java      |   1 +
 .../core/migrations/AvailableMigrations.java       |   4 +-
 .../migrations/v970/AddLinkSettingsMigration.java  |  52 +++++
 ui/package-lock.json                               |   4 +-
 .../src/lib/model/config/general-config.model.ts   |   3 +
 .../src/lib/model/gen/streampipes-model.ts         |  97 +++++----
 ui/src/app/configuration/configuration.module.ts   |   2 +
 .../general-configuration.component.html           |  59 +++---
 .../general-configuration.component.ts             |  50 +++++
 .../link-settings/link-settings.component.html     |  49 +++++
 .../link-settings/link-settings.component.ts}      |  13 +-
 .../core/components/toolbar/toolbar.component.html |   1 +
 .../core/components/toolbar/toolbar.component.ts   |  12 +-
 ui/src/app/info/about/about.component.html         | 198 ------------------
 ui/src/app/info/info.component.html                |  23 +--
 ui/src/app/info/info.component.ts                  |   7 -
 ui/src/app/info/info.module.ts                     |  11 +-
 ui/src/app/info/license/license.component.html     | 226 ---------------------
 ui/src/app/info/license/license.component.scss     |  23 ---
 ui/src/app/info/versions/versions.component.html   | 160 +++++++--------
 ui/src/app/info/versions/versions.component.scss   |  27 ---
 ui/src/app/info/versions/versions.component.ts     |   1 -
 .../activate-account.component.html                |   2 +-
 .../activate-account/activate-account.component.ts |  21 +-
 .../components/auth-box/auth-box.component.html    |  24 ++-
 .../components/auth-box/auth-box.component.ts      |   6 +-
 .../components/base-login-page.directive.ts}       |  30 +--
 .../login/components/login/login.component.html    |   9 +-
 .../app/login/components/login/login.component.ts  |  53 +++--
 ui/src/app/login/components/login/login.model.ts   |   3 +
 .../components/register/register.component.html    |   2 +-
 .../components/register/register.component.ts      |  45 ++--
 .../restore-password.component.html                |   2 +-
 .../restore-password/restore-password.component.ts |  33 +--
 .../set-new-password.component.html                |   2 +-
 .../set-new-password/set-new-password.component.ts |  13 +-
 ui/src/app/login/services/login.service.ts         |   2 +-
 43 files changed, 527 insertions(+), 814 deletions(-)

diff --git a/.idea/runConfigurations/ui.xml b/.idea/runConfigurations/ui.xml
index ce35c11692..b2d00f6ceb 100644
--- a/.idea/runConfigurations/ui.xml
+++ b/.idea/runConfigurations/ui.xml
@@ -1,6 +1,6 @@
 <component name="ProjectRunConfigurationManager">
   <configuration default="false" name="ui" type="js.build_tools.npm">
-    <package-json 
value="$PROJECT_DIR$/../incubator-streampipes/ui/package.json" />
+    <package-json value="$PROJECT_DIR$/ui/package.json" />
     <command value="start" />
     <node-interpreter value="project" />
     <envs />
diff --git a/ui/src/app/info/about/about.component.scss 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/DefaultGeneralConfig.java
similarity index 75%
rename from ui/src/app/info/about/about.component.scss
rename to 
streampipes-model/src/main/java/org/apache/streampipes/model/configuration/DefaultGeneralConfig.java
index d7d2abed43..c0b97cfd22 100644
--- a/ui/src/app/info/about/about.component.scss
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/DefaultGeneralConfig.java
@@ -16,16 +16,13 @@
  *
  */
 
-.about-logo {
-    width: 300px;
-}
+package org.apache.streampipes.model.configuration;
 
-.about-container {
-    margin-top: 20px;
-    margin-left: auto;
-    margin-right: auto;
-}
+public class DefaultGeneralConfig {
 
-.p-10 {
-    padding: 10px;
+  public GeneralConfig make() {
+    var generalConfig = new GeneralConfig();
+    generalConfig.setLinkSettings(new DefaultLinkSettings().make());
+    return generalConfig;
+  }
 }
diff --git a/ui/src/app/info/info.component.scss 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/DefaultLinkSettings.java
similarity index 75%
rename from ui/src/app/info/info.component.scss
rename to 
streampipes-model/src/main/java/org/apache/streampipes/model/configuration/DefaultLinkSettings.java
index 06b4a2ecdf..6165a601d6 100644
--- a/ui/src/app/info/info.component.scss
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/DefaultLinkSettings.java
@@ -16,14 +16,18 @@
  *
  */
 
-.pageheadbar {
-    padding: 0 0 0 10px;
-    background-color: #f6f6f6;
-    font-size: 14px;
-    line-height: 24px;
-    border-bottom: 1px solid #ccc;
-}
+package org.apache.streampipes.model.configuration;
+
+public class DefaultLinkSettings {
 
-.margin-top {
-    margin-top: 5px;
+  public LinkSettings make() {
+    return new LinkSettings(
+        "https://streampipes.apache.org";,
+        "",
+        true,
+        true,
+        false,
+        true
+    );
+  }
 }
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/DefaultSpCoreConfiguration.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/DefaultSpCoreConfiguration.java
index 4f654bd992..b669b3e4b7 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/DefaultSpCoreConfiguration.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/DefaultSpCoreConfiguration.java
@@ -29,7 +29,7 @@ public class DefaultSpCoreConfiguration {
   public SpCoreConfiguration make() {
     var coreCfg = new SpCoreConfiguration();
 
-    coreCfg.setGeneralConfig(new GeneralConfig());
+    coreCfg.setGeneralConfig(new DefaultGeneralConfig().make());
     coreCfg.setMessagingSettings(new DefaultMessagingSettings().make());
     coreCfg.setEmailConfig(EmailConfig.fromDefaults());
     coreCfg.setEmailTemplateConfig(new 
DefaultEmailTemplateConfiguration().getDefaultTemplates());
diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/GeneralConfig.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/GeneralConfig.java
index 2f3968d966..188590a196 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/GeneralConfig.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/GeneralConfig.java
@@ -31,6 +31,7 @@ public class GeneralConfig {
   private boolean allowPasswordRecovery;
 
   private List<String> defaultUserRoles;
+  private LinkSettings linkSettings;
 
   public GeneralConfig() {
   }
@@ -104,4 +105,12 @@ public class GeneralConfig {
   public void setAppName(String appName) {
     this.appName = appName;
   }
+
+  public LinkSettings getLinkSettings() {
+    return linkSettings;
+  }
+
+  public void setLinkSettings(LinkSettings linkSettings) {
+    this.linkSettings = linkSettings;
+  }
 }
diff --git a/ui/src/app/info/about/about.component.ts 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/LinkSettings.java
similarity index 61%
rename from ui/src/app/info/about/about.component.ts
rename to 
streampipes-model/src/main/java/org/apache/streampipes/model/configuration/LinkSettings.java
index 9fc711462f..1c798007ce 100644
--- a/ui/src/app/info/about/about.component.ts
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/configuration/LinkSettings.java
@@ -16,13 +16,14 @@
  *
  */
 
-import { Component } from '@angular/core';
+package org.apache.streampipes.model.configuration;
 
-@Component({
-    selector: 'sp-about',
-    templateUrl: './about.component.html',
-    styleUrls: ['./about.component.scss'],
-})
-export class AboutComponent {
-    constructor() {}
-}
+import org.apache.streampipes.model.shared.annotation.TsModel;
+
+@TsModel
+public record LinkSettings(String documentationUrl,
+                           String supportUrl,
+                           boolean showDocumentationLinkOnStartScreen,
+                           boolean showApiDocumentationLinkOnStartScreen,
+                           boolean showSupportUrlOnStartScreen,
+                           boolean showDocumentationLinkInProfileMenu) {}
diff --git 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java
 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java
index cfbc17722f..2401ee61da 100644
--- 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java
+++ 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Authentication.java
@@ -138,6 +138,7 @@ public class Authentication extends AbstractRestResource {
     Map<String, Object> response = new HashMap<>();
     response.put("allowSelfRegistration", config.isAllowSelfRegistration());
     response.put("allowPasswordRecovery", config.isAllowPasswordRecovery());
+    response.put("linkSettings", config.getLinkSettings());
 
     return ok(response);
   }
diff --git 
a/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/migrations/AvailableMigrations.java
 
b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/migrations/AvailableMigrations.java
index 2ee78fea02..8b21c7575a 100644
--- 
a/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/migrations/AvailableMigrations.java
+++ 
b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/migrations/AvailableMigrations.java
@@ -26,6 +26,7 @@ import 
org.apache.streampipes.service.core.migrations.v090.UpdateUsernameViewMig
 import org.apache.streampipes.service.core.migrations.v093.AdapterMigration;
 import 
org.apache.streampipes.service.core.migrations.v093.StoreEmailTemplatesMigration;
 import 
org.apache.streampipes.service.core.migrations.v095.MergeFilenamesAndRenameDuplicatesMigration;
+import 
org.apache.streampipes.service.core.migrations.v970.AddLinkSettingsMigration;
 
 import java.util.Arrays;
 import java.util.List;
@@ -40,7 +41,8 @@ public class AvailableMigrations {
         new UpdateUsernameViewMigration(),
         new AdapterMigration(),
         new StoreEmailTemplatesMigration(),
-        new MergeFilenamesAndRenameDuplicatesMigration()
+        new MergeFilenamesAndRenameDuplicatesMigration(),
+        new AddLinkSettingsMigration()
     );
   }
 }
diff --git 
a/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/migrations/v970/AddLinkSettingsMigration.java
 
b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/migrations/v970/AddLinkSettingsMigration.java
new file mode 100644
index 0000000000..d472fc0f42
--- /dev/null
+++ 
b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/migrations/v970/AddLinkSettingsMigration.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.streampipes.service.core.migrations.v970;
+
+import org.apache.streampipes.model.configuration.DefaultLinkSettings;
+import org.apache.streampipes.service.core.migrations.Migration;
+import org.apache.streampipes.storage.api.ISpCoreConfigurationStorage;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+
+import java.io.IOException;
+
+public class AddLinkSettingsMigration implements Migration {
+
+  private final ISpCoreConfigurationStorage coreConfigStore = StorageDispatcher
+      .INSTANCE
+      .getNoSqlStore()
+      .getSpCoreConfigurationStorage();
+
+  @Override
+  public boolean shouldExecute() {
+    return coreConfigStore.get().getGeneralConfig().getLinkSettings() == null;
+  }
+
+  @Override
+  public void executeMigration() throws IOException {
+    var linkSettings = new DefaultLinkSettings().make();
+    var coreConfig = coreConfigStore.get();
+    coreConfig.getGeneralConfig().setLinkSettings(linkSettings);
+    coreConfigStore.updateElement(coreConfig);
+  }
+
+  @Override
+  public String getDescription() {
+    return "Adding link settings to general config";
+  }
+}
diff --git a/ui/package-lock.json b/ui/package-lock.json
index ebd86a4ffe..93f1538f42 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "apache-streampipes",
-  "version": "0.95.0-SNAPSHOT",
+  "version": "0.97.0-SNAPSHOT",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "apache-streampipes",
-      "version": "0.95.0-SNAPSHOT",
+      "version": "0.97.0-SNAPSHOT",
       "dependencies": {
         "@ali-hm/angular-tree-component": "12.0.5",
         "@angular-architects/native-federation": "^17.1.8",
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/config/general-config.model.ts
 
b/ui/projects/streampipes/platform-services/src/lib/model/config/general-config.model.ts
index bf1f9fc93c..fbc6db7798 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/model/config/general-config.model.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/model/config/general-config.model.ts
@@ -16,6 +16,8 @@
  *
  */
 
+import { LinkSettings } from '../gen/streampipes-model';
+
 export interface GeneralConfigModel {
     hostname: string;
     port: number;
@@ -25,4 +27,5 @@ export interface GeneralConfigModel {
     allowSelfRegistration: boolean;
     defaultUserRoles: string[];
     appName: string;
+    linkSettings: LinkSettings;
 }
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index dac76da020..cf79d51045 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -20,7 +20,7 @@
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2024-06-27 
15:00:50.
+// Generated using typescript-generator version 3.2.1263 on 2024-06-30 
09:10:19.
 
 export class NamedStreamPipesEntity implements Storable {
     '@class':
@@ -30,8 +30,8 @@ export class NamedStreamPipesEntity implements Storable {
         | 'org.apache.streampipes.model.base.VersionedNamedStreamPipesEntity'
         | 'org.apache.streampipes.model.connect.adapter.AdapterDescription'
         | 'org.apache.streampipes.model.base.InvocableStreamPipesEntity'
-        | 'org.apache.streampipes.model.graph.DataProcessorInvocation'
-        | 'org.apache.streampipes.model.graph.DataSinkInvocation';
+        | 'org.apache.streampipes.model.graph.DataSinkInvocation'
+        | 'org.apache.streampipes.model.graph.DataProcessorInvocation';
     'appId': string;
     'connectedTo': string[];
     'description': string;
@@ -81,8 +81,8 @@ export class VersionedNamedStreamPipesEntity extends 
NamedStreamPipesEntity {
         | 'org.apache.streampipes.model.base.VersionedNamedStreamPipesEntity'
         | 'org.apache.streampipes.model.connect.adapter.AdapterDescription'
         | 'org.apache.streampipes.model.base.InvocableStreamPipesEntity'
-        | 'org.apache.streampipes.model.graph.DataProcessorInvocation'
-        | 'org.apache.streampipes.model.graph.DataSinkInvocation';
+        | 'org.apache.streampipes.model.graph.DataSinkInvocation'
+        | 'org.apache.streampipes.model.graph.DataProcessorInvocation';
     'version': number;
 
     static 'fromData'(
@@ -1169,8 +1169,8 @@ export class InvocableStreamPipesEntity
 {
     '@class':
         | 'org.apache.streampipes.model.base.InvocableStreamPipesEntity'
-        | 'org.apache.streampipes.model.graph.DataProcessorInvocation'
-        | 'org.apache.streampipes.model.graph.DataSinkInvocation';
+        | 'org.apache.streampipes.model.graph.DataSinkInvocation'
+        | 'org.apache.streampipes.model.graph.DataProcessorInvocation';
     'belongsTo': string;
     'configured': boolean;
     'correspondingPipeline': string;
@@ -1359,32 +1359,6 @@ export class EdgeValidationStatus {
     }
 }
 
-export class ElementComposition {
-    description: string;
-    name: string;
-    sepas: DataProcessorInvocation[];
-    streams: SpDataStream[];
-
-    static fromData(
-        data: ElementComposition,
-        target?: ElementComposition,
-    ): ElementComposition {
-        if (!data) {
-            return data;
-        }
-        const instance = target || new ElementComposition();
-        instance.description = data.description;
-        instance.name = data.name;
-        instance.sepas = __getCopyArrayFn(DataProcessorInvocation.fromData)(
-            data.sepas,
-        );
-        instance.streams = __getCopyArrayFn(SpDataStream.fromData)(
-            data.streams,
-        );
-        return instance;
-    }
-}
-
 export interface EndpointSelectable {
     correspondingPipeline: string;
     detachPath: string;
@@ -1817,9 +1791,10 @@ export class FieldStatusInfo {
     }
 }
 
-export class FileMetadata {
+export class FileMetadata implements Storable {
     createdAt: number;
     createdByUser: string;
+    elementId: string;
     fileId: string;
     filename: string;
     filetype: string;
@@ -1833,6 +1808,7 @@ export class FileMetadata {
         const instance = target || new FileMetadata();
         instance.createdAt = data.createdAt;
         instance.createdByUser = data.createdByUser;
+        instance.elementId = data.elementId;
         instance.fileId = data.fileId;
         instance.filename = data.filename;
         instance.filetype = data.filetype;
@@ -2117,6 +2093,32 @@ export class KeepOutputStrategy extends OutputStrategy {
     }
 }
 
+export class LinkSettings {
+    documentationUrl: string;
+    showApiDocumentationLinkOnStartScreen: boolean;
+    showDocumentationLinkInProfileMenu: boolean;
+    showDocumentationLinkOnStartScreen: boolean;
+    showSupportUrlOnStartScreen: boolean;
+    supportUrl: string;
+
+    static fromData(data: LinkSettings, target?: LinkSettings): LinkSettings {
+        if (!data) {
+            return data;
+        }
+        const instance = target || new LinkSettings();
+        instance.documentationUrl = data.documentationUrl;
+        instance.showApiDocumentationLinkOnStartScreen =
+            data.showApiDocumentationLinkOnStartScreen;
+        instance.showDocumentationLinkInProfileMenu =
+            data.showDocumentationLinkInProfileMenu;
+        instance.showDocumentationLinkOnStartScreen =
+            data.showDocumentationLinkOnStartScreen;
+        instance.showSupportUrlOnStartScreen = 
data.showSupportUrlOnStartScreen;
+        instance.supportUrl = data.supportUrl;
+        return instance;
+    }
+}
+
 export class ListOutputStrategy extends OutputStrategy {
     '@class': 'org.apache.streampipes.model.output.ListOutputStrategy';
     'propertyName': string;
@@ -2447,18 +2449,24 @@ export class PageResult extends DataSeries {
     }
 }
 
-export class Pipeline extends ElementComposition {
+export class Pipeline implements Storable {
     _id: string;
     _rev: string;
     actions: DataSinkInvocation[];
     createdAt: number;
     createdByUser: string;
+    description: string;
+    elementId: string;
     healthStatus: PipelineHealthStatus;
+    name: string;
     pipelineNotifications: string[];
     publicElement: boolean;
     restartOnSystemReboot: boolean;
+    rev: string;
     running: boolean;
+    sepas: DataProcessorInvocation[];
     startedAt: number;
+    streams: SpDataStream[];
     valid: boolean;
 
     static fromData(data: Pipeline, target?: Pipeline): Pipeline {
@@ -2466,7 +2474,6 @@ export class Pipeline extends ElementComposition {
             return data;
         }
         const instance = target || new Pipeline();
-        super.fromData(data, instance);
         instance._id = data._id;
         instance._rev = data._rev;
         instance.actions = __getCopyArrayFn(DataSinkInvocation.fromData)(
@@ -2474,14 +2481,24 @@ export class Pipeline extends ElementComposition {
         );
         instance.createdAt = data.createdAt;
         instance.createdByUser = data.createdByUser;
+        instance.description = data.description;
+        instance.elementId = data.elementId;
         instance.healthStatus = data.healthStatus;
+        instance.name = data.name;
         instance.pipelineNotifications = 
__getCopyArrayFn(__identity<string>())(
             data.pipelineNotifications,
         );
         instance.publicElement = data.publicElement;
         instance.restartOnSystemReboot = data.restartOnSystemReboot;
+        instance.rev = data.rev;
         instance.running = data.running;
+        instance.sepas = __getCopyArrayFn(DataProcessorInvocation.fromData)(
+            data.sepas,
+        );
         instance.startedAt = data.startedAt;
+        instance.streams = __getCopyArrayFn(SpDataStream.fromData)(
+            data.streams,
+        );
         instance.valid = data.valid;
         return instance;
     }
@@ -3562,8 +3579,9 @@ export class SpQueryResult {
     }
 }
 
-export class SpServiceConfiguration {
+export class SpServiceConfiguration implements Storable {
     configs: ConfigItem[];
+    elementId: string;
     rev: string;
     serviceGroup: string;
     serviceName: string;
@@ -3577,6 +3595,7 @@ export class SpServiceConfiguration {
         }
         const instance = target || new SpServiceConfiguration();
         instance.configs = __getCopyArrayFn(ConfigItem.fromData)(data.configs);
+        instance.elementId = data.elementId;
         instance.rev = data.rev;
         instance.serviceGroup = data.serviceGroup;
         instance.serviceName = data.serviceName;
@@ -3584,7 +3603,8 @@ export class SpServiceConfiguration {
     }
 }
 
-export class SpServiceRegistration {
+export class SpServiceRegistration implements Storable {
+    elementId: string;
     firstTimeSeenUnhealthy: number;
     healthCheckPath: string;
     host: string;
@@ -3607,6 +3627,7 @@ export class SpServiceRegistration {
             return data;
         }
         const instance = target || new SpServiceRegistration();
+        instance.elementId = data.elementId;
         instance.firstTimeSeenUnhealthy = data.firstTimeSeenUnhealthy;
         instance.healthCheckPath = data.healthCheckPath;
         instance.host = data.host;
diff --git a/ui/src/app/configuration/configuration.module.ts 
b/ui/src/app/configuration/configuration.module.ts
index 4d61b1726f..305a667d6d 100644
--- a/ui/src/app/configuration/configuration.module.ts
+++ b/ui/src/app/configuration/configuration.module.ts
@@ -78,6 +78,7 @@ import { SpExtensionsInstallationDialogComponent } from 
'./dialog/extensions-ins
 import { EndpointItemComponent } from 
'./extensions-installation/endpoint-item/endpoint-item.component';
 import { SpExtensionsInstallationComponent } from 
'./extensions-installation/extensions-installation.component';
 import { MatMenuModule } from '@angular/material/menu';
+import { SpConfigurationLinkSettingsComponent } from 
'./general-configuration/link-settings/link-settings.component';
 
 @NgModule({
     imports: [
@@ -173,6 +174,7 @@ import { MatMenuModule } from '@angular/material/menu';
         SecurityServiceConfigComponent,
         MessagingConfigurationComponent,
         DatalakeConfigurationComponent,
+        SpConfigurationLinkSettingsComponent,
         SpDataExportImportComponent,
         SpDataExportDialogComponent,
         SpDataExportItemComponent,
diff --git 
a/ui/src/app/configuration/general-configuration/general-configuration.component.html
 
b/ui/src/app/configuration/general-configuration/general-configuration.component.html
index 0b4e2bcd72..b35d761cab 100644
--- 
a/ui/src/app/configuration/general-configuration/general-configuration.component.html
+++ 
b/ui/src/app/configuration/general-configuration/general-configuration.component.html
@@ -52,11 +52,11 @@
                                     formControlName="protocol"
                                 >
                                     <mat-button-toggle value="http"
-                                        >http</mat-button-toggle
-                                    >
+                                        >http
+                                    </mat-button-toggle>
                                     <mat-button-toggle value="https"
-                                        >https</mat-button-toggle
-                                    >
+                                        >https
+                                    </mat-button-toggle>
                                 </mat-button-toggle-group>
                             </div>
                             <mat-form-field color="accent" class="ml-10">
@@ -82,22 +82,7 @@
                             </mat-form-field>
                         </div>
                     </div>
-                    <div class="mt-10">
-                        <button
-                            mat-button
-                            mat-raised-button
-                            color="accent"
-                            (click)="updateConfig()"
-                            style="margin-right: 10px"
-                            [disabled]="!parentForm.valid"
-                            data-cy="sp-element-general-config-save"
-                        >
-                            <i class="material-icons">save</i
-                            ><span>&nbsp;Save</span>
-                        </button>
-                    </div>
                 </sp-split-section>
-                <mat-divider></mat-divider>
                 <sp-split-section
                     title="Registration"
                     subtitle="Registration process"
@@ -143,20 +128,28 @@
                         <mat-checkbox formControlName="allowPasswordRecovery"
                             >Allow self-service password recovery
                         </mat-checkbox>
-
-                        <div class="mt-10">
-                            <button
-                                mat-button
-                                mat-raised-button
-                                color="accent"
-                                (click)="updateConfig()"
-                                style="margin-right: 10px"
-                                
data-cy="sp-element-general-registration-config-save"
-                            >
-                                <i class="material-icons">save</i
-                                ><span>&nbsp;Save</span>
-                            </button>
-                        </div>
+                    </div>
+                </sp-split-section>
+                <sp-configuration-link-settings
+                    [parentForm]="parentForm"
+                    [linkSettings]="generalConfig.linkSettings"
+                    (updateConfigEmitter)="updateConfig()"
+                >
+                </sp-configuration-link-settings>
+                <sp-split-section>
+                    <div class="mt-10">
+                        <button
+                            mat-button
+                            mat-raised-button
+                            color="accent"
+                            (click)="updateConfig()"
+                            style="margin-right: 10px"
+                            [disabled]="!parentForm.valid"
+                            data-cy="sp-element-general-config-save"
+                        >
+                            <i class="material-icons">save</i
+                            ><span>&nbsp;Save</span>
+                        </button>
                     </div>
                 </sp-split-section>
             </form>
diff --git 
a/ui/src/app/configuration/general-configuration/general-configuration.component.ts
 
b/ui/src/app/configuration/general-configuration/general-configuration.component.ts
index e770dba8d2..d80da2b8e0 100644
--- 
a/ui/src/app/configuration/general-configuration/general-configuration.component.ts
+++ 
b/ui/src/app/configuration/general-configuration/general-configuration.component.ts
@@ -90,6 +90,7 @@ export class GeneralConfigurationComponent implements OnInit {
                     allowPasswordRecovery: false,
                     defaultUserRoles: [UserRole.ROLE_PIPELINE_USER],
                     appName: this.appConstants.APP_NAME,
+                    linkSettings: undefined,
                 };
             }
             this.mailConfig = configs[1];
@@ -141,6 +142,44 @@ export class GeneralConfigurationComponent implements 
OnInit {
                     Validators.required,
                 ),
             );
+
+            this.parentForm.addControl(
+                'documentationUrl',
+                new UntypedFormControl(
+                    this.generalConfig.linkSettings.documentationUrl,
+                ),
+            );
+            this.parentForm.addControl(
+                'showDocumentationLinkOnStartScreen',
+                new UntypedFormControl(
+                    
this.generalConfig.linkSettings.showDocumentationLinkOnStartScreen,
+                ),
+            );
+            this.parentForm.addControl(
+                'showDocumentationLinkInProfileMenu',
+                new UntypedFormControl(
+                    
this.generalConfig.linkSettings.showDocumentationLinkInProfileMenu,
+                ),
+            );
+            this.parentForm.addControl(
+                'supportUrl',
+                new UntypedFormControl(
+                    this.generalConfig.linkSettings.supportUrl,
+                ),
+            );
+            this.parentForm.addControl(
+                'showSupportUrlOnStartScreen',
+                new UntypedFormControl(
+                    
this.generalConfig.linkSettings.showSupportUrlOnStartScreen,
+                ),
+            );
+            this.parentForm.addControl(
+                'showApiDocumentationLinkOnStartScreen',
+                new UntypedFormControl(
+                    
this.generalConfig.linkSettings.showApiDocumentationLinkOnStartScreen,
+                ),
+            );
+
             this.parentForm.valueChanges.subscribe(v => {
                 this.generalConfig.appName = v.appName;
                 this.generalConfig.protocol = v.protocol;
@@ -153,6 +192,17 @@ export class GeneralConfigurationComponent implements 
OnInit {
                 this.generalConfig.defaultUserRoles = v.defaultUserRoles.map(
                     r => UserRole[r],
                 );
+                this.generalConfig.linkSettings.documentationUrl =
+                    v.documentationUrl;
+                this.generalConfig.linkSettings.supportUrl = v.supportUrl;
+                
this.generalConfig.linkSettings.showApiDocumentationLinkOnStartScreen =
+                    v.showApiDocumentationLinkOnStartScreen;
+                this.generalConfig.linkSettings.showSupportUrlOnStartScreen =
+                    v.showSupportUrlOnStartScreen;
+                
this.generalConfig.linkSettings.showDocumentationLinkInProfileMenu =
+                    v.showDocumentationLinkInProfileMenu;
+                
this.generalConfig.linkSettings.showDocumentationLinkOnStartScreen =
+                    v.showDocumentationLinkOnStartScreen;
             });
 
             this.formReady = true;
diff --git 
a/ui/src/app/configuration/general-configuration/link-settings/link-settings.component.html
 
b/ui/src/app/configuration/general-configuration/link-settings/link-settings.component.html
new file mode 100644
index 0000000000..673315bf9b
--- /dev/null
+++ 
b/ui/src/app/configuration/general-configuration/link-settings/link-settings.component.html
@@ -0,0 +1,49 @@
+<!--
+  ~ 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-split-section
+    title="Links"
+    subtitle="Configure application links"
+    [formGroup]="parentForm"
+>
+    <div class="subsection-title">Documentation Link</div>
+    <mat-form-field color="accent" class="ml-10">
+        <mat-label>Documentation URL</mat-label>
+        <input formControlName="documentationUrl" fxFlex matInput />
+    </mat-form-field>
+    <mat-checkbox formControlName="showDocumentationLinkOnStartScreen"
+        >Show documentation link on login page
+    </mat-checkbox>
+    <mat-checkbox formControlName="showDocumentationLinkInProfileMenu"
+        >Show documentation link in user menu
+    </mat-checkbox>
+
+    <div class="subsection-title mt-10">API Documentation Link</div>
+    <mat-checkbox formControlName="showApiDocumentationLinkOnStartScreen"
+        >Show API documentation link on login page
+    </mat-checkbox>
+
+    <div class="subsection-title mt-10">Support Link</div>
+    <mat-form-field color="accent" class="ml-10">
+        <mat-label>Support URL</mat-label>
+        <input formControlName="supportUrl" fxFlex matInput />
+    </mat-form-field>
+    <mat-checkbox formControlName="showSupportUrlOnStartScreen"
+        >Show support link on login page
+    </mat-checkbox>
+</sp-split-section>
diff --git a/ui/src/app/info/license/license.component.ts 
b/ui/src/app/configuration/general-configuration/link-settings/link-settings.component.ts
similarity index 74%
rename from ui/src/app/info/license/license.component.ts
rename to 
ui/src/app/configuration/general-configuration/link-settings/link-settings.component.ts
index a0acad09d8..e8ac67246d 100644
--- a/ui/src/app/info/license/license.component.ts
+++ 
b/ui/src/app/configuration/general-configuration/link-settings/link-settings.component.ts
@@ -16,13 +16,14 @@
  *
  */
 
-import { Component } from '@angular/core';
+import { Component, Input } from '@angular/core';
+import { FormGroup } from '@angular/forms';
 
 @Component({
-    selector: 'sp-license',
-    templateUrl: './license.component.html',
-    styleUrls: ['./license.component.scss'],
+    selector: 'sp-configuration-link-settings',
+    templateUrl: './link-settings.component.html',
 })
-export class LicenseComponent {
-    constructor() {}
+export class SpConfigurationLinkSettingsComponent {
+    @Input()
+    parentForm: FormGroup;
 }
diff --git a/ui/src/app/core/components/toolbar/toolbar.component.html 
b/ui/src/app/core/components/toolbar/toolbar.component.html
index aee0ff8ef3..febf2638b9 100644
--- a/ui/src/app/core/components/toolbar/toolbar.component.html
+++ b/ui/src/app/core/components/toolbar/toolbar.component.html
@@ -149,6 +149,7 @@
                         Info
                     </button>
                     <button
+                        *ngIf="documentationLinkActive"
                         mat-menu-item
                         (click)="openDocumentation()"
                         style="min-width: 0px"
diff --git a/ui/src/app/core/components/toolbar/toolbar.component.ts 
b/ui/src/app/core/components/toolbar/toolbar.component.ts
index fb74374423..d8e2a0cba3 100644
--- a/ui/src/app/core/components/toolbar/toolbar.component.ts
+++ b/ui/src/app/core/components/toolbar/toolbar.component.ts
@@ -30,6 +30,7 @@ import { Subscription, timer } from 'rxjs';
 import { exhaustMap } from 'rxjs/operators';
 import { NotificationCountService } from 
'../../../services/notification-count-service';
 import { CurrentUserService } from '@streampipes/shared-ui';
+import { LoginService } from '../../../login/services/login.service';
 
 @Component({
     selector: 'sp-toolbar',
@@ -51,9 +52,13 @@ export class ToolbarComponent
     unreadNotificationCount = 0;
     unreadNotificationsSubscription: Subscription;
 
+    documentationLinkActive = false;
+    documentationLink = '';
+
     constructor(
         router: Router,
         authService: AuthService,
+        private loginService: LoginService,
         private profileService: ProfileService,
         private restApi: RestApi,
         private overlay: OverlayContainer,
@@ -93,6 +98,11 @@ export class ToolbarComponent
                     this.modifyAppearance(userInfo.darkMode);
                 });
         });
+        this.loginService.fetchLoginSettings().subscribe(res => {
+            this.documentationLinkActive =
+                res.linkSettings?.showDocumentationLinkInProfileMenu;
+            this.documentationLink = res.linkSettings?.documentationUrl || '';
+        });
 
         this.appearanceControl = new UntypedFormControl(
             this.currentUserService.darkMode$.getValue(),
@@ -115,7 +125,7 @@ export class ToolbarComponent
     }
 
     openDocumentation() {
-        window.open('https://streampipes.apache.org/docs', '_blank');
+        window.open(this.documentationLink, '_blank');
     }
 
     openInfo() {
diff --git a/ui/src/app/info/about/about.component.html 
b/ui/src/app/info/about/about.component.html
deleted file mode 100644
index 519957d526..0000000000
--- a/ui/src/app/info/about/about.component.html
+++ /dev/null
@@ -1,198 +0,0 @@
-<!--
-  ~ 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 wrap"
-    fxFlex="90"
-    fxLayoutAlign="center center"
-    class="about-container"
->
-    <div
-        fxFlex="50"
-        fxLayoutAlign="center center"
-        fxLayout="column"
-        style="color: white"
-    >
-        <img alt="icon" src="assets/img/sp/logo.png" class="about-logo" />
-    </div>
-
-    <div
-        fxFlex="100"
-        fxLayout="row wrap"
-        fxLayoutAlign="start stretch"
-        style="margin-top: 20px"
-    >
-        <div fxFlex="100">
-            <div class="assemblyOptions sp-blue-bg" style="padding: 5px">
-                <h4>Resources</h4>
-            </div>
-            <div class="sp-blue-border p-10">
-                <ul>
-                    <li>
-                        <div fxLayout="row fill" fxFlex="100">
-                            <div fxFlex="5" fxLayoutAlign="start center">
-                                <mat-icon>description</mat-icon>
-                            </div>
-                            <div fxFlex="95" fxLayoutAlign="start center">
-                                <h5>
-                                    Find the documentation at
-                                    <a
-                                        
href="https://streampipes.apache.org/docs/";
-                                        
>https://streampipes.apache.org/docs/</a
-                                    >
-                                </h5>
-                            </div>
-                        </div>
-                    </li>
-                    <li>
-                        <div fxLayout="row fill" fxFlex="100">
-                            <div fxFlex="5" fxLayoutAlign="start center">
-                                <mat-icon>language</mat-icon>
-                            </div>
-                            <div fxFlex="95" fxLayoutAlign="start center">
-                                <h5>
-                                    Find our website at
-                                    <a href="https://streampipes.apache.org";
-                                        >https://streampipes.apache.org</a
-                                    >
-                                </h5>
-                            </div>
-                        </div>
-                    </li>
-                    <li>
-                        <div fxLayout="row fill" fxFlex="100">
-                            <div fxFlex="5" fxLayoutAlign="start center">
-                                <mat-icon>code</mat-icon>
-                            </div>
-                            <div fxFlex="95" fxLayoutAlign="start center">
-                                <h5>
-                                    Find the source code at
-                                    <a
-                                        
href="https://github.com/apache/streampipes";
-                                        
>https://github.com/apache/streampipes</a
-                                    >
-                                </h5>
-                            </div>
-                        </div>
-                    </li>
-                    <li>
-                        <div fxLayout="row fill" fxFlex="100">
-                            <div fxFlex="5" fxLayoutAlign="start center">
-                                <mat-icon>local_shipping</mat-icon>
-                            </div>
-                            <div fxFlex="95" fxLayoutAlign="start center">
-                                <h5>
-                                    Find the docker images at
-                                    <a
-                                        
href="https://hub.docker.com/u/apachestreampipes";
-                                        
>https://hub.docker.com/u/apachestreampipes</a
-                                    >
-                                </h5>
-                            </div>
-                        </div>
-                    </li>
-                </ul>
-            </div>
-        </div>
-        <div fxFlex="100" style="margin-top: 10px">
-            <div class="assemblyOptions sp-blue-bg" style="padding: 5px">
-                <h4>Community & Support</h4>
-            </div>
-            <div class="sp-blue-border p-10">
-                <ul>
-                    <li>
-                        <div fxLayout="row fill" fxFlex="100">
-                            <div fxFlex="5" fxLayoutAlign="start center">
-                                <mat-icon>chat</mat-icon>
-                            </div>
-                            <div fxFlex="95" fxLayoutAlign="start center">
-                                <h5>
-                                    Follow us on
-                                    <a href="https://twitter.com/streampipes";
-                                        >Twitter</a
-                                    >
-                                    and
-                                    <a
-                                        
href="https://www.linkedin.com/company/apache-streampipes";
-                                        >LinkedIn</a
-                                    >
-                                    to get the latest news!
-                                </h5>
-                            </div>
-                        </div>
-                    </li>
-                    <li>
-                        <div fxLayout="row fill" fxFlex="100">
-                            <div fxFlex="5" fxLayoutAlign="start center">
-                                <mat-icon>email</mat-icon>
-                            </div>
-                            <div fxFlex="95" fxLayoutAlign="start center">
-                                <h5>
-                                    Drop us an email if you'd like to give
-                                    <a
-                                        
href="mailto:[email protected]";
-                                        >feedback</a
-                                    >
-                                    or get in touch with us via
-                                    <a
-                                        
href="https://github.com/apache/streampipes/discussions";
-                                        >GitHub discussions</a
-                                    >!
-                                </h5>
-                            </div>
-                        </div>
-                    </li>
-                    <li>
-                        <div fxLayout="row fill" fxFlex="100">
-                            <div fxFlex="5" fxLayoutAlign="start center">
-                                <mat-icon>star_rate</mat-icon>
-                            </div>
-                            <div fxFlex="95" fxLayoutAlign="start center">
-                                <h5>
-                                    If you like StreamPipes, give us a star on
-                                    <a
-                                        
href="https://github.com/apache/streampipes";
-                                        >Github</a
-                                    >
-                                </h5>
-                            </div>
-                        </div>
-                    </li>
-                    <li>
-                        <div fxLayout="row fill" fxFlex="100">
-                            <div fxFlex="5" fxLayoutAlign="start center">
-                                <mat-icon>bug_report</mat-icon>
-                            </div>
-                            <div fxFlex="95" fxLayoutAlign="start center">
-                                <h5>
-                                    If you find a bug within StreamPipes, we
-                                    welcome any report on that. Just file us an
-                                    <a
-                                        
href="https://github.com/apache/streampipes/issues/new/choose";
-                                        >Github issue</a
-                                    >
-                                    with a description of the observed bug.
-                                </h5>
-                            </div>
-                        </div>
-                    </li>
-                </ul>
-            </div>
-        </div>
-    </div>
-</div>
diff --git a/ui/src/app/info/info.component.html 
b/ui/src/app/info/info.component.html
index 3be56d585f..58f99d8e2f 100644
--- a/ui/src/app/info/info.component.html
+++ b/ui/src/app/info/info.component.html
@@ -16,23 +16,6 @@
   ~
   -->
 
-<div class="page-container page-container-padding">
-    <div class="page-container-nav">
-        <mat-tab-group (selectedTabChange)="tabChanged($event)" color="accent">
-            <mat-tab label="About"> </mat-tab>
-            <mat-tab label="System Info"> </mat-tab>
-            <mat-tab label="License"> </mat-tab>
-        </mat-tab-group>
-    </div>
-    <div class="container-fluid margin-top">
-        <div *ngIf="currentTabIndex === 0">
-            <sp-about></sp-about>
-        </div>
-        <div *ngIf="currentTabIndex === 1">
-            <sp-versions></sp-versions>
-        </div>
-        <div *ngIf="currentTabIndex === 2">
-            <sp-license></sp-license>
-        </div>
-    </div>
-</div>
+<sp-basic-view [showBackLink]="false" [padding]="true">
+    <sp-versions></sp-versions>
+</sp-basic-view>
diff --git a/ui/src/app/info/info.component.ts 
b/ui/src/app/info/info.component.ts
index b05a79be47..ca65ab3e08 100644
--- a/ui/src/app/info/info.component.ts
+++ b/ui/src/app/info/info.component.ts
@@ -22,18 +22,11 @@ import { SpBreadcrumbService } from 
'@streampipes/shared-ui';
 
 @Component({
     templateUrl: './info.component.html',
-    styleUrls: ['./info.component.scss'],
 })
 export class InfoComponent implements OnInit {
-    currentTabIndex = 0;
-
     constructor(private breadcrumbService: SpBreadcrumbService) {}
 
     ngOnInit() {
         this.breadcrumbService.updateBreadcrumb([{ label: 'Info' }]);
     }
-
-    tabChanged(tabChangeEvent: MatTabChangeEvent): void {
-        this.currentTabIndex = tabChangeEvent.index;
-    }
 }
diff --git a/ui/src/app/info/info.module.ts b/ui/src/app/info/info.module.ts
index e31210f93d..b69aaf94ec 100644
--- a/ui/src/app/info/info.module.ts
+++ b/ui/src/app/info/info.module.ts
@@ -30,10 +30,9 @@ import { CommonModule } from '@angular/common';
 import { FormsModule } from '@angular/forms';
 
 import { InfoComponent } from './info.component';
-import { LicenseComponent } from './license/license.component';
-import { AboutComponent } from './about/about.component';
 import { VersionsComponent } from './versions/versions.component';
 import { MatTabsModule } from '@angular/material/tabs';
+import { SharedUiModule } from '@streampipes/shared-ui';
 
 @NgModule({
     imports: [
@@ -48,13 +47,9 @@ import { MatTabsModule } from '@angular/material/tabs';
         MatTooltipModule,
         FormsModule,
         MatDividerModule,
+        SharedUiModule,
     ],
-    declarations: [
-        InfoComponent,
-        LicenseComponent,
-        VersionsComponent,
-        AboutComponent,
-    ],
+    declarations: [InfoComponent, VersionsComponent],
     providers: [],
 })
 export class InfoModule {}
diff --git a/ui/src/app/info/license/license.component.html 
b/ui/src/app/info/license/license.component.html
deleted file mode 100644
index 030ea87aec..0000000000
--- a/ui/src/app/info/license/license.component.html
+++ /dev/null
@@ -1,226 +0,0 @@
-<!--
-  ~ 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.
-  ~
-  -->
-
-<h1>Apache License, Version 2.0</h1>
-
-<p>
-    January 2004<br />
-    <a href="http://www.apache.org/licenses/";
-        >http://www.apache.org/licenses/</a
-    >
-</p>
-<p>TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION</p>
-<p>
-    <strong><a name="definitions">1. Definitions</a></strong
-    >.
-</p>
-<p>
-    "License" shall mean the terms and conditions for use, reproduction, and
-    distribution as defined by Sections 1 through 9 of this document.
-</p>
-<p>
-    "Licensor" shall mean the copyright owner or entity authorized by the
-    copyright owner that is granting the License.
-</p>
-<p>
-    "Legal Entity" shall mean the union of the acting entity and all other
-    entities that control, are controlled by, or are under common control with
-    that entity. For the purposes of this definition, "control" means (i) the
-    power, direct or indirect, to cause the direction or management of such
-    entity, whether by contract or otherwise, or (ii) ownership of fifty 
percent
-    (50%) or more of the outstanding shares, or (iii) beneficial ownership of
-    such entity.
-</p>
-<p>
-    "You" (or "Your") shall mean an individual or Legal Entity exercising
-    permissions granted by this License.
-</p>
-<p>
-    "Source" form shall mean the preferred form for making modifications,
-    including but not limited to software source code, documentation source, 
and
-    configuration files.
-</p>
-<p>
-    "Object" form shall mean any form resulting from mechanical transformation
-    or translation of a Source form, including but not limited to compiled
-    object code, generated documentation, and conversions to other media types.
-</p>
-<p>
-    "Work" shall mean the work of authorship, whether in Source or Object form,
-    made available under the License, as indicated by a copyright notice that 
is
-    included in or attached to the work (an example is provided in the Appendix
-    below).
-</p>
-<p>
-    "Derivative Works" shall mean any work, whether in Source or Object form,
-    that is based on (or derived from) the Work and for which the editorial
-    revisions, annotations, elaborations, or other modifications represent, as 
a
-    whole, an original work of authorship. For the purposes of this License,
-    Derivative Works shall not include works that remain separable from, or
-    merely link (or bind by name) to the interfaces of, the Work and Derivative
-    Works thereof.
-</p>
-<p>
-    "Contribution" shall mean any work of authorship, including the original
-    version of the Work and any modifications or additions to that Work or
-    Derivative Works thereof, that is intentionally submitted to Licensor for
-    inclusion in the Work by the copyright owner or by an individual or Legal
-    Entity authorized to submit on behalf of the copyright owner. For the
-    purposes of this definition, "submitted" means any form of electronic,
-    verbal, or written communication sent to the Licensor or its
-    representatives, including but not limited to communication on electronic
-    mailing lists, source code control systems, and issue tracking systems that
-    are managed by, or on behalf of, the Licensor for the purpose of discussing
-    and improving the Work, but excluding communication that is conspicuously
-    marked or otherwise designated in writing by the copyright owner as "Not a
-    Contribution."
-</p>
-<p>
-    "Contributor" shall mean Licensor and any individual or Legal Entity on
-    behalf of whom a Contribution has been received by Licensor and 
subsequently
-    incorporated within the Work.
-</p>
-<p>
-    <strong><a name="copyright">2. Grant of Copyright License</a></strong
-    >. Subject to the terms and conditions of this License, each Contributor
-    hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
-    royalty-free, irrevocable copyright license to reproduce, prepare 
Derivative
-    Works of, publicly display, publicly perform, sublicense, and distribute 
the
-    Work and such Derivative Works in Source or Object form.
-</p>
-<p>
-    <strong><a name="patent">3. Grant of Patent License</a></strong
-    >. Subject to the terms and conditions of this License, each Contributor
-    hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
-    royalty-free, irrevocable (except as stated in this section) patent license
-    to make, have made, use, offer to sell, sell, import, and otherwise 
transfer
-    the Work, where such license applies only to those patent claims licensable
-    by such Contributor that are necessarily infringed by their Contribution(s)
-    alone or by combination of their Contribution(s) with the Work to which 
such
-    Contribution(s) was submitted. If You institute patent litigation against
-    any entity (including a cross-claim or counterclaim in a lawsuit) alleging
-    that the Work or a Contribution incorporated within the Work constitutes
-    direct or contributory patent infringement, then any patent licenses 
granted
-    to You under this License for that Work shall terminate as of the date such
-    litigation is filed.
-</p>
-<p>
-    <strong><a name="redistribution">4. Redistribution</a></strong
-    >. You may reproduce and distribute copies of the Work or Derivative Works
-    thereof in any medium, with or without modifications, and in Source or
-    Object form, provided that You meet the following conditions:
-</p>
-<ol style="list-style: lower-latin">
-    <li>
-        You must give any other recipients of the Work or Derivative Works a
-        copy of this License; and
-    </li>
-
-    <li>
-        You must cause any modified files to carry prominent notices stating
-        that You changed the files; and
-    </li>
-
-    <li>
-        You must retain, in the Source form of any Derivative Works that You
-        distribute, all copyright, patent, trademark, and attribution notices
-        from the Source form of the Work, excluding those notices that do not
-        pertain to any part of the Derivative Works; and
-    </li>
-
-    <li>
-        If the Work includes a "NOTICE" text file as part of its distribution,
-        then any Derivative Works that You distribute must include a readable
-        copy of the attribution notices contained within such NOTICE file,
-        excluding those notices that do not pertain to any part of the
-        Derivative Works, in at least one of the following places: within a
-        NOTICE text file distributed as part of the Derivative Works; within 
the
-        Source form or documentation, if provided along with the Derivative
-        Works; or, within a display generated by the Derivative Works, if and
-        wherever such third-party notices normally appear. The contents of the
-        NOTICE file are for informational purposes only and do not modify the
-        License. You may add Your own attribution notices within Derivative
-        Works that You distribute, alongside or as an addendum to the NOTICE
-        text from the Work, provided that such additional attribution notices
-        cannot be construed as modifying the License.
-        <br />
-        <br />
-        You may add Your own copyright statement to Your modifications and may
-        provide additional or different license terms and conditions for use,
-        reproduction, or distribution of Your modifications, or for any such
-        Derivative Works as a whole, provided Your use, reproduction, and
-        distribution of the Work otherwise complies with the conditions stated
-        in this License.
-    </li>
-</ol>
-
-<p>
-    <strong><a name="contributions">5. Submission of Contributions</a></strong
-    >. Unless You explicitly state otherwise, any Contribution intentionally
-    submitted for inclusion in the Work by You to the Licensor shall be under
-    the terms and conditions of this License, without any additional terms or
-    conditions. Notwithstanding the above, nothing herein shall supersede or
-    modify the terms of any separate license agreement you may have executed
-    with Licensor regarding such Contributions.
-</p>
-<p>
-    <strong><a name="trademarks">6. Trademarks</a></strong
-    >. This License does not grant permission to use the trade names,
-    trademarks, service marks, or product names of the Licensor, except as
-    required for reasonable and customary use in describing the origin of the
-    Work and reproducing the content of the NOTICE file.
-</p>
-<p>
-    <strong><a name="no-warranty">7. Disclaimer of Warranty</a></strong
-    >. Unless required by applicable law or agreed to in writing, Licensor
-    provides the Work (and each Contributor provides its Contributions) on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-    or implied, including, without limitation, any warranties or conditions of
-    TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR
-    PURPOSE. You are solely responsible for determining the appropriateness of
-    using or redistributing the Work and assume any risks associated with Your
-    exercise of permissions under this License.
-</p>
-<p>
-    <strong><a name="no-liability">8. Limitation of Liability</a></strong
-    >. In no event and under no legal theory, whether in tort (including
-    negligence), contract, or otherwise, unless required by applicable law 
(such
-    as deliberate and grossly negligent acts) or agreed to in writing, shall 
any
-    Contributor be liable to You for damages, including any direct, indirect,
-    special, incidental, or consequential damages of any character arising as a
-    result of this License or out of the use or inability to use the Work
-    (including but not limited to damages for loss of goodwill, work stoppage,
-    computer failure or malfunction, or any and all other commercial damages or
-    losses), even if such Contributor has been advised of the possibility of
-    such damages.
-</p>
-<p>
-    <strong
-        ><a name="additional"
-            >9. Accepting Warranty or Additional Liability</a
-        ></strong
-    >. While redistributing the Work or Derivative Works thereof, You may 
choose
-    to offer, and charge a fee for, acceptance of support, warranty, indemnity,
-    or other liability obligations and/or rights consistent with this License.
-    However, in accepting such obligations, You may act only on Your own behalf
-    and on Your sole responsibility, not on behalf of any other Contributor, 
and
-    only if You agree to indemnify, defend, and hold each Contributor harmless
-    for any liability incurred by, or claims asserted against, such Contributor
-    by reason of your accepting any such warranty or additional liability.
-</p>
-<p>END OF TERMS AND CONDITIONS</p>
diff --git a/ui/src/app/info/license/license.component.scss 
b/ui/src/app/info/license/license.component.scss
deleted file mode 100644
index 8fafb2eeac..0000000000
--- a/ui/src/app/info/license/license.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.
- *
- */
-
-.license-info {
-    background: white;
-    border-radius: 0px;
-    border: 0px;
-}
diff --git a/ui/src/app/info/versions/versions.component.html 
b/ui/src/app/info/versions/versions.component.html
index 1617b796c1..7272c2bb4a 100644
--- a/ui/src/app/info/versions/versions.component.html
+++ b/ui/src/app/info/versions/versions.component.html
@@ -16,91 +16,81 @@
   ~
   -->
 
-<div
-    fxLayout="row wrap"
-    fxFlex="90"
-    fxLayoutAlign="center center"
-    class="about-container"
->
-    <div
-        fxFlex="100"
-        fxLayout="row wrap"
-        fxLayoutAlign="center center"
-        style="margin-top: 20px"
-    >
-        <div fxFlex="100">
-            <div class="assemblyOptions sp-blue-bg" style="padding: 5px">
-                <h4>Versions</h4>
-            </div>
-            <div class="sp-blue-border md-padding" *ngIf="versionInfo">
-                <ul>
-                    <li>
-                        <div fxFlex="30">Backend Version</div>
-                        <div fxFlex="70">{{ versionInfo.backendVersion }}</div>
-                    </li>
-                </ul>
-            </div>
+<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>
-        <div fxFlex="100" style="margin-top: 10px">
-            <div class="assemblyOptions sp-blue-bg" style="padding: 5px">
-                <h4>System Info</h4>
-            </div>
-            <div class="sp-blue-border md-padding" *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>
+    </sp-basic-inner-panel>
+    <sp-basic-inner-panel
+        panelTitle="System Info"
+        innerPadding="0"
+        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>
-    </div>
+    </sp-basic-inner-panel>
 </div>
diff --git a/ui/src/app/info/versions/versions.component.scss 
b/ui/src/app/info/versions/versions.component.scss
deleted file mode 100644
index 0572bd7b90..0000000000
--- a/ui/src/app/info/versions/versions.component.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.
- *
- */
-
-.about-container {
-    margin-top: 20px;
-    margin-left: auto;
-    margin-right: auto;
-}
-
-.md-padding {
-    padding: 10px;
-}
diff --git a/ui/src/app/info/versions/versions.component.ts 
b/ui/src/app/info/versions/versions.component.ts
index 08985b59bc..815f64e435 100644
--- a/ui/src/app/info/versions/versions.component.ts
+++ b/ui/src/app/info/versions/versions.component.ts
@@ -24,7 +24,6 @@ import { RestApi } from '../../services/rest-api.service';
 @Component({
     selector: 'sp-versions',
     templateUrl: './versions.component.html',
-    styleUrls: ['./versions.component.scss'],
 })
 export class VersionsComponent {
     versionInfo: VersionInfo;
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 b9d61e8959..0a0975d9b8 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
@@ -16,7 +16,7 @@
   ~
   -->
 
-<sp-auth-box>
+<sp-auth-box [linkSettings]="loginSettings.linkSettings" *ngIf="configReady">
     <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
         <h1>Account activation</h1>
     </div>
diff --git 
a/ui/src/app/login/components/activate-account/activate-account.component.ts 
b/ui/src/app/login/components/activate-account/activate-account.component.ts
index 8bc81272f7..f7eb1ac92c 100644
--- a/ui/src/app/login/components/activate-account/activate-account.component.ts
+++ b/ui/src/app/login/components/activate-account/activate-account.component.ts
@@ -16,16 +16,18 @@
  *
  */
 
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
 import { AccountActivationService } from 
'../../services/account-activation.service';
 import { ActivatedRoute, Router } from '@angular/router';
+import { BaseLoginPageDirective } from '../base-login-page.directive';
+import { LoginService } from '../../services/login.service';
 
 @Component({
     selector: 'sp-activate-account',
     templateUrl: './activate-account.component.html',
     styleUrls: ['../login/login.component.scss'],
 })
-export class ActivateAccountComponent implements OnInit {
+export class ActivateAccountComponent extends BaseLoginPageDirective {
     activationCode: string;
     activationSuccess: boolean;
     activationPerformed = false;
@@ -34,9 +36,16 @@ export class ActivateAccountComponent implements OnInit {
         private accountActivationService: AccountActivationService,
         private route: ActivatedRoute,
         private router: Router,
-    ) {}
+        protected loginService: LoginService,
+    ) {
+        super(loginService);
+    }
+
+    navigateToLoginPage() {
+        this.router.navigate(['/login']);
+    }
 
-    ngOnInit(): void {
+    onSettingsAvailable(): void {
         this.route.queryParams.subscribe(params => {
             this.activationCode = params['activationCode'];
             if (this.activationCode) {
@@ -56,8 +65,4 @@ export class ActivateAccountComponent implements OnInit {
             }
         });
     }
-
-    navigateToLoginPage() {
-        this.router.navigate(['/login']);
-    }
 }
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 d3d29b4add..3f300d2209 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
@@ -44,19 +44,39 @@
             </div>
             <div fxLayout="row" fxLayoutAlign="end end" 
class="auth-box-footer">
                 <a
+                    *ngIf="linkSettings.showDocumentationLinkOnStartScreen"
                     class="footer-link"
-                    
href="https://streampipes.apache.org/docs/user-guide-introduction";
+                    [href]="linkSettings.documentationUrl"
                 >
                     Documentation
                 </a>
-                <span style="margin-left: 10px; margin-right: 10px"> | </span>
+                <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</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>
             </div>
         </div>
     </div>
diff --git a/ui/src/app/login/components/auth-box/auth-box.component.ts 
b/ui/src/app/login/components/auth-box/auth-box.component.ts
index cae0835d61..5996c400d9 100644
--- a/ui/src/app/login/components/auth-box/auth-box.component.ts
+++ b/ui/src/app/login/components/auth-box/auth-box.component.ts
@@ -16,8 +16,9 @@
  *
  */
 
-import { Component } from '@angular/core';
+import { Component, Input } from '@angular/core';
 import { AppConstants } from '../../../services/app.constants';
+import { LinkSettings } from '@streampipes/platform-services';
 
 @Component({
     selector: 'sp-auth-box',
@@ -25,5 +26,8 @@ import { AppConstants } from 
'../../../services/app.constants';
     styleUrls: ['./auth-box.component.scss'],
 })
 export class AuthBoxComponent {
+    @Input()
+    linkSettings: LinkSettings;
+
     constructor(public appConstants: AppConstants) {}
 }
diff --git a/ui/src/app/info/info.component.ts 
b/ui/src/app/login/components/base-login-page.directive.ts
similarity index 56%
copy from ui/src/app/info/info.component.ts
copy to ui/src/app/login/components/base-login-page.directive.ts
index b05a79be47..c572a18e5e 100644
--- a/ui/src/app/info/info.component.ts
+++ b/ui/src/app/login/components/base-login-page.directive.ts
@@ -16,24 +16,24 @@
  *
  */
 
-import { Component, OnInit } from '@angular/core';
-import { MatTabChangeEvent } from '@angular/material/tabs';
-import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { Directive, OnInit } from '@angular/core';
+import { LoginService } from '../services/login.service';
+import { LoginModel } from './login/login.model';
 
-@Component({
-    templateUrl: './info.component.html',
-    styleUrls: ['./info.component.scss'],
-})
-export class InfoComponent implements OnInit {
-    currentTabIndex = 0;
+@Directive()
+export abstract class BaseLoginPageDirective implements OnInit {
+    protected loginSettings: LoginModel;
+    protected configReady = false;
 
-    constructor(private breadcrumbService: SpBreadcrumbService) {}
+    protected constructor(protected loginService: LoginService) {}
 
-    ngOnInit() {
-        this.breadcrumbService.updateBreadcrumb([{ label: 'Info' }]);
+    ngOnInit(): void {
+        this.loginService.fetchLoginSettings().subscribe(result => {
+            this.loginSettings = result;
+            this.configReady = true;
+            this.onSettingsAvailable();
+        });
     }
 
-    tabChanged(tabChangeEvent: MatTabChangeEvent): void {
-        this.currentTabIndex = tabChangeEvent.index;
-    }
+    abstract onSettingsAvailable(): void;
 }
diff --git a/ui/src/app/login/components/login/login.component.html 
b/ui/src/app/login/components/login/login.component.html
index 97a1e8937a..5cd150ce02 100644
--- a/ui/src/app/login/components/login/login.component.html
+++ b/ui/src/app/login/components/login/login.component.html
@@ -16,17 +16,12 @@
   ~
   -->
 
-<sp-auth-box>
+<sp-auth-box [linkSettings]="loginSettings.linkSettings" *ngIf="configReady">
     <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
         <h1>Login</h1>
     </div>
     <div fxFlex="100" fxLayout="column" class="mt-10">
-        <form
-            [formGroup]="parentForm"
-            fxFlex="100"
-            fxLayout="column"
-            *ngIf="configReady"
-        >
+        <form [formGroup]="parentForm" fxFlex="100" fxLayout="column">
             <div fxFlex="100" fxLayout="column">
                 <mat-form-field fxFlex color="accent">
                     <mat-label>Email</mat-label>
diff --git a/ui/src/app/login/components/login/login.component.ts 
b/ui/src/app/login/components/login/login.component.ts
index 17f2364b13..af50a53337 100644
--- a/ui/src/app/login/components/login/login.component.ts
+++ b/ui/src/app/login/components/login/login.component.ts
@@ -16,69 +16,44 @@
  *
  */
 
-import { ShepherdService } from '../../../services/tour/shepherd.service';
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
 import { LoginService } from '../../services/login.service';
 import { ActivatedRoute, Router } from '@angular/router';
 import { AuthService } from '../../../services/auth.service';
-import { LoginModel } from './login.model';
 import {
     UntypedFormBuilder,
     UntypedFormControl,
     UntypedFormGroup,
     Validators,
 } from '@angular/forms';
+import { BaseLoginPageDirective } from '../base-login-page.directive';
 
 @Component({
     selector: 'sp-login',
     templateUrl: './login.component.html',
     styleUrls: ['./login.component.scss'],
 })
-export class LoginComponent implements OnInit {
+export class LoginComponent extends BaseLoginPageDirective {
     parentForm: UntypedFormGroup;
-    configReady = false;
     loading: boolean;
     authenticationFailed: boolean;
     credentials: any;
 
-    loginSettings: LoginModel;
     returnUrl: string;
 
     constructor(
-        private loginService: LoginService,
+        loginService: LoginService,
         private router: Router,
         private route: ActivatedRoute,
-        private shepherdService: ShepherdService,
         private authService: AuthService,
         private fb: UntypedFormBuilder,
     ) {
+        super(loginService);
         this.loading = false;
         this.authenticationFailed = false;
         this.credentials = {};
     }
 
-    ngOnInit() {
-        this.loginService.fetchLoginSettings().subscribe(result => {
-            this.loginSettings = result;
-            this.configReady = true;
-            this.parentForm = this.fb.group({});
-            this.parentForm.addControl(
-                'username',
-                new UntypedFormControl('', Validators.required),
-            );
-            this.parentForm.addControl(
-                'password',
-                new UntypedFormControl('', Validators.required),
-            );
-
-            this.parentForm.valueChanges.subscribe(v => {
-                this.credentials.username = v.username;
-                this.credentials.password = v.password;
-            });
-            this.returnUrl = this.route.snapshot.queryParams.returnUrl || '';
-        });
-    }
-
     logIn() {
         this.authenticationFailed = false;
         this.loading = true;
@@ -96,4 +71,22 @@ export class LoginComponent implements OnInit {
             },
         );
     }
+
+    onSettingsAvailable(): void {
+        this.parentForm = this.fb.group({});
+        this.parentForm.addControl(
+            'username',
+            new UntypedFormControl('', Validators.required),
+        );
+        this.parentForm.addControl(
+            'password',
+            new UntypedFormControl('', Validators.required),
+        );
+
+        this.parentForm.valueChanges.subscribe(v => {
+            this.credentials.username = v.username;
+            this.credentials.password = v.password;
+        });
+        this.returnUrl = this.route.snapshot.queryParams.returnUrl || '';
+    }
 }
diff --git a/ui/src/app/login/components/login/login.model.ts 
b/ui/src/app/login/components/login/login.model.ts
index 15e2b3b6c4..fc28a3a4fc 100644
--- a/ui/src/app/login/components/login/login.model.ts
+++ b/ui/src/app/login/components/login/login.model.ts
@@ -16,7 +16,10 @@
  *
  */
 
+import { LinkSettings } from '@streampipes/platform-services';
+
 export interface LoginModel {
     allowSelfRegistration: boolean;
     allowPasswordRecovery: boolean;
+    linkSettings: LinkSettings;
 }
diff --git a/ui/src/app/login/components/register/register.component.html 
b/ui/src/app/login/components/register/register.component.html
index 3a5f40d23a..c4cbac9b3c 100644
--- a/ui/src/app/login/components/register/register.component.html
+++ b/ui/src/app/login/components/register/register.component.html
@@ -16,7 +16,7 @@
   ~
   -->
 
-<sp-auth-box>
+<sp-auth-box [linkSettings]="loginSettings.linkSettings" *ngIf="configReady">
     <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
         <h1>Register</h1>
     </div>
diff --git a/ui/src/app/login/components/register/register.component.ts 
b/ui/src/app/login/components/register/register.component.ts
index 6be4c59838..8a210d3939 100644
--- a/ui/src/app/login/components/register/register.component.ts
+++ b/ui/src/app/login/components/register/register.component.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
 import {
     UntypedFormBuilder,
     UntypedFormControl,
@@ -26,13 +26,14 @@ import {
 import { RegistrationModel } from './registration.model';
 import { LoginService } from '../../services/login.service';
 import { checkPasswords } from '../../utils/check-password';
+import { BaseLoginPageDirective } from '../base-login-page.directive';
 
 @Component({
     selector: 'sp-register-user',
     templateUrl: './register.component.html',
     styleUrls: ['../login/login.component.scss'],
 })
-export class RegisterComponent implements OnInit {
+export class RegisterComponent extends BaseLoginPageDirective {
     parentForm: UntypedFormGroup;
 
     registrationData: RegistrationModel;
@@ -43,10 +44,28 @@ export class RegisterComponent implements OnInit {
 
     constructor(
         private fb: UntypedFormBuilder,
-        private loginService: LoginService,
-    ) {}
+        loginService: LoginService,
+    ) {
+        super(loginService);
+    }
+
+    registerUser() {
+        this.registrationError = undefined;
+        this.registrationInProcess = true;
+        this.loginService.registerUser(this.registrationData).subscribe(
+            response => {
+                this.registrationInProcess = false;
+                this.registrationSuccess = true;
+            },
+            error => {
+                this.registrationInProcess = false;
+                this.registrationSuccess = false;
+                this.registrationError = error.error.notifications[0].title;
+            },
+        );
+    }
 
-    ngOnInit(): void {
+    onSettingsAvailable(): void {
         this.parentForm = this.fb.group({});
         this.parentForm.addControl(
             'username',
@@ -69,20 +88,4 @@ export class RegisterComponent implements OnInit {
             };
         });
     }
-
-    registerUser() {
-        this.registrationError = undefined;
-        this.registrationInProcess = true;
-        this.loginService.registerUser(this.registrationData).subscribe(
-            response => {
-                this.registrationInProcess = false;
-                this.registrationSuccess = true;
-            },
-            error => {
-                this.registrationInProcess = false;
-                this.registrationSuccess = false;
-                this.registrationError = error.error.notifications[0].title;
-            },
-        );
-    }
 }
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 5d3cf40e55..a73d778d6b 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
@@ -16,7 +16,7 @@
   ~
   -->
 
-<sp-auth-box>
+<sp-auth-box [linkSettings]="loginSettings.linkSettings" *ngIf="configReady">
     <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
         <h1>Restore password</h1>
         <h5>
diff --git 
a/ui/src/app/login/components/restore-password/restore-password.component.ts 
b/ui/src/app/login/components/restore-password/restore-password.component.ts
index 53d2dbe764..d0fd1a0404 100644
--- a/ui/src/app/login/components/restore-password/restore-password.component.ts
+++ b/ui/src/app/login/components/restore-password/restore-password.component.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
 import {
     UntypedFormBuilder,
     UntypedFormControl,
@@ -24,13 +24,14 @@ import {
     Validators,
 } from '@angular/forms';
 import { LoginService } from '../../services/login.service';
+import { BaseLoginPageDirective } from '../base-login-page.directive';
 
 @Component({
     selector: 'sp-restore-password',
     templateUrl: './restore-password.component.html',
     styleUrls: ['../login/login.component.scss'],
 })
-export class RestorePasswordComponent implements OnInit {
+export class RestorePasswordComponent extends BaseLoginPageDirective {
     parentForm: UntypedFormGroup;
     restoreSuccess = false;
     restoreCompleted = false;
@@ -39,19 +40,9 @@ export class RestorePasswordComponent implements OnInit {
 
     constructor(
         private fb: UntypedFormBuilder,
-        private loginService: LoginService,
-    ) {}
-
-    ngOnInit(): void {
-        this.parentForm = this.fb.group({});
-        this.parentForm.addControl(
-            'username',
-            new UntypedFormControl('', Validators.required),
-        );
-
-        this.parentForm.valueChanges.subscribe(result => {
-            this.username = result.username;
-        });
+        protected loginService: LoginService,
+    ) {
+        super(loginService);
     }
 
     sendRestorePasswordLink() {
@@ -67,4 +58,16 @@ export class RestorePasswordComponent implements OnInit {
             },
         );
     }
+
+    onSettingsAvailable(): void {
+        this.parentForm = this.fb.group({});
+        this.parentForm.addControl(
+            'username',
+            new UntypedFormControl('', Validators.required),
+        );
+
+        this.parentForm.valueChanges.subscribe(result => {
+            this.username = result.username;
+        });
+    }
 }
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 425f109784..3e35bbd317 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
@@ -16,7 +16,7 @@
   ~
   -->
 
-<sp-auth-box>
+<sp-auth-box [linkSettings]="loginSettings.linkSettings" *ngIf="configReady">
     <div fxFlex="100" fxLayout="column" fxLayoutAlign="center start">
         <h1>Set new password</h1>
     </div>
diff --git 
a/ui/src/app/login/components/set-new-password/set-new-password.component.ts 
b/ui/src/app/login/components/set-new-password/set-new-password.component.ts
index 65d7eb15f4..8bce1b4de8 100644
--- a/ui/src/app/login/components/set-new-password/set-new-password.component.ts
+++ b/ui/src/app/login/components/set-new-password/set-new-password.component.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { Component, OnInit } from '@angular/core';
+import { Component } from '@angular/core';
 import { RestorePasswordService } from 
'../../services/restore-password.service';
 import {
     UntypedFormBuilder,
@@ -27,13 +27,15 @@ import {
 import { checkPasswords } from '../../utils/check-password';
 import { RegistrationModel } from '../register/registration.model';
 import { ActivatedRoute, Router } from '@angular/router';
+import { BaseLoginPageDirective } from '../base-login-page.directive';
+import { LoginService } from '../../services/login.service';
 
 @Component({
     selector: 'sp-set-new-password',
     templateUrl: './set-new-password.component.html',
     styleUrls: ['../login/login.component.scss'],
 })
-export class SetNewPasswordComponent implements OnInit {
+export class SetNewPasswordComponent extends BaseLoginPageDirective {
     parentForm: UntypedFormGroup;
     registrationModel: RegistrationModel;
     recoveryCode: string;
@@ -47,9 +49,12 @@ export class SetNewPasswordComponent implements OnInit {
         private restorePasswordService: RestorePasswordService,
         private route: ActivatedRoute,
         private router: Router,
-    ) {}
+        protected loginService: LoginService,
+    ) {
+        super(loginService);
+    }
 
-    ngOnInit(): void {
+    onSettingsAvailable(): void {
         this.route.queryParams.subscribe(params => {
             this.recoveryCode = params['recoveryCode'];
             if (this.recoveryCode) {
diff --git a/ui/src/app/login/services/login.service.ts 
b/ui/src/app/login/services/login.service.ts
index fe8ed8a7cb..7c2e12ba10 100644
--- a/ui/src/app/login/services/login.service.ts
+++ b/ui/src/app/login/services/login.service.ts
@@ -16,7 +16,7 @@
  *
  */
 
-import { Injectable, OnInit } from '@angular/core';
+import { Injectable } from '@angular/core';
 import { HttpClient, HttpContext } from '@angular/common/http';
 import { PlatformServicesCommons } from '@streampipes/platform-services';
 import { Observable } from 'rxjs';


Reply via email to