You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metron.apache.org by sa...@apache.org on 2019/08/23 15:17:10 UTC

[metron] branch master updated: METRON-2179 [UI] Make navigation in both UIs consistent (sardell) closes apache/metron#1464

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

sardell pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/metron.git


The following commit(s) were added to refs/heads/master by this push:
     new 4ab1fdb  METRON-2179 [UI] Make navigation in both UIs consistent (sardell) closes apache/metron#1464
4ab1fdb is described below

commit 4ab1fdba2f93cfb90dea55d315fb7f45c63d2fa6
Author: sardell <sh...@gmail.com>
AuthorDate: Fri Aug 23 17:16:48 2019 +0200

    METRON-2179 [UI] Make navigation in both UIs consistent (sardell) closes apache/metron#1464
---
 .../common-services/METRON/CURRENT/metainfo.xml    |   2 +
 .../package/templates/alerts-ui-app-config.json.j2 |   4 +-
 .../templates/management-ui-app-config.json.j2     |   4 +-
 metron-interface/metron-alerts/package-lock.json   |  61 +++++++++++++++++-
 metron-interface/metron-alerts/package.json        |   2 +
 .../metron-alerts/src/app/app.component.html       |  69 ++++++++++++++-------
 .../metron-alerts/src/app/app.component.scss       |  31 +++++++--
 .../metron-alerts/src/app/app.component.spec.ts    |  37 ++++++++++-
 .../metron-alerts/src/app/app.component.ts         |  37 ++++++++++-
 .../metron-alerts/src/app/app.module.ts            |  28 +++++++--
 .../src/app/service/app-config.service.ts          |  14 +++++
 .../metron-alerts/src/assets/app-config.json       |   4 +-
 .../metron-alerts/src/assets/images/logo-name.png  | Bin 0 -> 3760 bytes
 .../src/assets/images/logo-symbol.png              | Bin 0 -> 19063 bytes
 metron-interface/metron-alerts/src/styles.scss     |  64 +++++++++++++++++++
 metron-interface/metron-config/package-lock.json   |  55 ++++++++++++++++
 metron-interface/metron-config/package.json        |   1 +
 .../metron-config/src/app/app.component.html       |  69 ++++++++++++++++-----
 .../metron-config/src/app/app.component.scss       |  23 +++++++
 .../metron-config/src/app/app.component.ts         |  37 ++++++++++-
 .../metron-config/src/app/app.module.ts            |  21 ++++++-
 .../src/app/navbar/navbar.component.scss           |  10 +++
 .../metron-config/src/app/navbar/navbar.html       |   8 +--
 .../src/app/service/app-config.service.ts          |  14 +++++
 .../src/app/service/mock.app-config.service.ts     |   9 +++
 .../metron-config/src/assets/app-config.json       |   4 +-
 .../metron-config/src/assets/images/logo-name.png  | Bin 0 -> 3760 bytes
 .../src/assets/images/logo-symbol.png              | Bin 0 -> 19063 bytes
 metron-interface/metron-config/src/styles.scss     |  66 ++++++++++++++++++++
 29 files changed, 611 insertions(+), 63 deletions(-)

diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/metainfo.xml b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/metainfo.xml
index cb044c2..417c225 100644
--- a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/metainfo.xml
+++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/metainfo.xml
@@ -375,6 +375,7 @@
                 <config-type>metron-security-env</config-type>
                 <config-type>metron-rest-env</config-type>
                 <config-type>metron-management-ui-env</config-type>
+                <config-type>metron-alerts-ui-env</config-type>
             </configuration-dependencies>
         </component>
         <component>
@@ -401,6 +402,7 @@
           <configuration-dependencies>
             <config-type>metron-security-env</config-type>
             <config-type>metron-rest-env</config-type>
+            <config-type>metron-management-ui-env</config-type>
             <config-type>metron-alerts-ui-env</config-type>
           </configuration-dependencies>
         </component>
diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/templates/alerts-ui-app-config.json.j2 b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/templates/alerts-ui-app-config.json.j2
index cdc064e..192e830 100644
--- a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/templates/alerts-ui-app-config.json.j2
+++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/templates/alerts-ui-app-config.json.j2
@@ -1,5 +1,7 @@
 {
   "apiRoot": "{{metron_rest_path}}",
   "loginPath": "{{metron_alerts_ui_login_path}}",
-  "contextMenuConfigURL": "{{metron_alerts_ui_context_menu_config_url}}"
+  "contextMenuConfigURL": "{{metron_alerts_ui_context_menu_config_url}}",
+  "managementUIHost": "{{metron_management_ui_host}}",
+  "managementUIPort": "{{metron_management_ui_port}}"
 }
\ No newline at end of file
diff --git a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/templates/management-ui-app-config.json.j2 b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/templates/management-ui-app-config.json.j2
index 12c3168..c03a35f 100644
--- a/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/templates/management-ui-app-config.json.j2
+++ b/metron-deployment/packaging/ambari/metron-mpack/src/main/resources/common-services/METRON/CURRENT/package/templates/management-ui-app-config.json.j2
@@ -1,4 +1,6 @@
 {
   "apiRoot": "{{metron_rest_path}}",
-  "loginPath": "{{metron_management_ui_login_path}}"
+  "loginPath": "{{metron_management_ui_login_path}}",
+  "alertsUIHost": "{{metron_alerts_ui_host}}",
+  "alertsUIPort": "{{metron_alerts_ui_port}}"
 }
\ No newline at end of file
diff --git a/metron-interface/metron-alerts/package-lock.json b/metron-interface/metron-alerts/package-lock.json
index 0860f0e..e97967c 100644
--- a/metron-interface/metron-alerts/package-lock.json
+++ b/metron-interface/metron-alerts/package-lock.json
@@ -719,6 +719,31 @@
         }
       }
     },
+    "@angular/animations": {
+      "version": "7.2.15",
+      "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-7.2.15.tgz",
+      "integrity": "sha512-8oBt3HLgd2+kyJHUgsd7OzKCCss67t2sch15XNoIWlOLfxclqU+EfFE6t/vCzpT8/+lpZS6LU9ZrTnb+UBj5jg==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
+    "@angular/cdk": {
+      "version": "7.3.7",
+      "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-7.3.7.tgz",
+      "integrity": "sha512-xbXxhHHKGkVuW6K7pzPmvpJXIwpl0ykBnvA2g+/7Sgy5Pd35wCC+UtHD9RYczDM/mkygNxMQtagyCErwFnDtQA==",
+      "requires": {
+        "parse5": "^5.0.0",
+        "tslib": "^1.7.1"
+      },
+      "dependencies": {
+        "parse5": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
+          "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
+          "optional": true
+        }
+      }
+    },
     "@angular/cli": {
       "version": "7.3.9",
       "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-7.3.9.tgz",
@@ -1399,6 +1424,23 @@
         "tslib": "^1.9.0"
       }
     },
+    "@ant-design/colors": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-3.1.0.tgz",
+      "integrity": "sha512-Td7g1P53sNFyT4Gya6836e70TrhoVZ+HjZs6mpWIHrxl4/VqsjjOyzj/8ktOuw0lCx+BfYu9UO1CiJ0MoYYfhg==",
+      "requires": {
+        "tinycolor2": "^1.4.1"
+      }
+    },
+    "@ant-design/icons-angular": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@ant-design/icons-angular/-/icons-angular-2.1.0.tgz",
+      "integrity": "sha512-FDOtuxPKm2CaxWBWFqP2a5abtrrlVz8HzBdLEJJD68bW9ombWQKH71ZMp1Iw53Koqn1KTUCy0jPqSuSwx5wcrA==",
+      "requires": {
+        "@ant-design/colors": "^3.1.0",
+        "tslib": "^1.9.0"
+      }
+    },
     "@babel/code-frame": {
       "version": "7.0.0-beta.51",
       "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.51.tgz",
@@ -5897,8 +5939,7 @@
     "date-fns": {
       "version": "1.29.0",
       "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz",
-      "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==",
-      "dev": true
+      "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw=="
     },
     "date-format": {
       "version": "1.2.0",
@@ -11964,6 +12005,17 @@
       "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
       "dev": true
     },
+    "ng-zorro-antd": {
+      "version": "7.5.1",
+      "resolved": "https://registry.npmjs.org/ng-zorro-antd/-/ng-zorro-antd-7.5.1.tgz",
+      "integrity": "sha512-0V/LoARoluFjiPUX4Q7x+G7hVA+k+x4g4OyYaLLUAoPpK3o1kriR3VzjdKsuKl73gBoRHHq4SNDRSiqzfOWDeA==",
+      "requires": {
+        "@angular/cdk": "^7.0.0",
+        "@ant-design/icons-angular": "^2.1.0",
+        "date-fns": "^1.29.0",
+        "tslib": "^1.9.0"
+      }
+    },
     "ng2-dragula": {
       "version": "1.5.0",
       "resolved": "https://registry.npmjs.org/ng2-dragula/-/ng2-dragula-1.5.0.tgz",
@@ -16108,6 +16160,11 @@
         "setimmediate": "^1.0.4"
       }
     },
+    "tinycolor2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz",
+      "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g="
+    },
     "tmp": {
       "version": "0.0.33",
       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
diff --git a/metron-interface/metron-alerts/package.json b/metron-interface/metron-alerts/package.json
index 91f43e4..d1e662e 100644
--- a/metron-interface/metron-alerts/package.json
+++ b/metron-interface/metron-alerts/package.json
@@ -18,6 +18,7 @@
   },
   "private": true,
   "dependencies": {
+    "@angular/animations": "^7.2.15",
     "@angular/common": "^7.2.15",
     "@angular/compiler": "^7.2.15",
     "@angular/core": "^7.2.15",
@@ -36,6 +37,7 @@
     "font-awesome": "^4.7.0",
     "jquery": "^3.3.1",
     "moment": "^2.22.2",
+    "ng-zorro-antd": "^7.5.1",
     "ng2-dragula": "^1.5.0",
     "pikaday-time": "^1.6.1",
     "popper.js": "^1.14.7",
diff --git a/metron-interface/metron-alerts/src/app/app.component.html b/metron-interface/metron-alerts/src/app/app.component.html
index a531dc8..ce7e201 100644
--- a/metron-interface/metron-alerts/src/app/app.component.html
+++ b/metron-interface/metron-alerts/src/app/app.component.html
@@ -11,27 +11,54 @@
 	OR CONDITIONS OF ANY KIND, either express or implied. See the License for
   the specific language governing permissions and limitations under the License.
   -->
-<div class="container-fluid px-0" [class.notransition]="noTransition">
-    <nav class="navbar" *ngIf="loggedIn">
-        <a class="" href="#">
-            <img alt="" src="assets/images/logo.png" width="135" height="45">
-        </a>
-        <ul class="nav ml-4 h-100">
-            <li class="nav-item" routerLinkActive="active">
-                <a class="nav-link " routerLink="/alerts-list" routerLinkActive="active">Alerts</a>
-            </li>
-            <li class="nav-item" routerLinkActive="active">
-                <a class="nav-link" routerLink="/pcap" routerLinkActive="active">PCAP</a>
-            </li>
-        </ul>
-        <div class="logout ml-auto">Logged in as {{authService.currentUser}} - <span class="logout-link" (click)="authService.logout()">Logout</span></div>
-    </nav>
-    <div class="container-fluid">
-        <router-outlet></router-outlet>
-    </div>
-    <router-outlet name="dialog" ></router-outlet>
-    <app-metron-dialog></app-metron-dialog>
-</div>
+
+<nz-layout>
+    <nz-sider *ngIf="loggedIn" nzCollapsible [(nzCollapsed)]="isCollapsed" nzWidth="200px">
+        <div class="logo" style="height: 50px;">
+            <img class="icon logo-symbol h-100" src="assets/images/logo-symbol.png" alt="">
+            <img class="icon logo-name h-100" src="assets/images/logo-name.png" alt="">
+        </div>
+        <nav>
+            <ul nz-menu nzMode="inline" [nzInlineCollapsed]="isCollapsed" nzTheme="dark">
+                <li nz-submenu nzOpen *ngFor="let link of centralNavLinks; let i = index" routerLinkActive="ant-menu-item-selected">
+                    <span title><i nz-icon [nzType]="link.iconClass"></i><span class="nav-text">{{ link.linkName }}</span></span>
+                    <ng-container *ngIf="link.subLinks">
+                        <ul>
+                            <li *ngFor="let subLink of link.subLinks"
+                                nz-menu-item
+                                routerLinkActive="ant-menu-item-selected">
+                                <a *ngIf="!subLink.externalLink"
+                                    [routerLink]="subLink.routerLink"
+                                    routerLinkActive="active">
+                                    {{ subLink.linkName }}
+                                </a>
+                                <a *ngIf="subLink.externalLink"
+                                    href="http://{{hostname}}{{subLink.routerLink}}">
+                                    {{ subLink.linkName }}
+                                </a>
+                            </li>
+                        </ul>
+                    </ng-container>
+                </li>
+            </ul>
+        </nav>
+    </nz-sider>
+    <nz-layout>
+        <nz-content>
+        <div class="container-fluid px-0" [class.notransition]="noTransition">
+            <div class="page-header" *ngIf="loggedIn">
+                <div class="logout ml-auto">Logged in as {{authService.currentUser}} - <span class="logout-link" (click)="authService.logout()">Logout</span></div>
+            </div>
+            <div class="container-fluid">
+                <router-outlet></router-outlet>
+            </div>
+            <router-outlet name="dialog" ></router-outlet>
+            <app-metron-dialog></app-metron-dialog>
+        </div>
+    </nz-content>
+    </nz-layout>
+
+</nz-layout>
 
 
 
diff --git a/metron-interface/metron-alerts/src/app/app.component.scss b/metron-interface/metron-alerts/src/app/app.component.scss
index 8505ee8..332976f 100644
--- a/metron-interface/metron-alerts/src/app/app.component.scss
+++ b/metron-interface/metron-alerts/src/app/app.component.scss
@@ -17,14 +17,14 @@
  */
 @import "../variables";
 
-.navbar
-{
-  flex-direction: row;
+.page-header {
   background: $nav-bar-bg;
-  padding: 0rem 1rem;
+  display: flex;
+  flex-direction: row;
   height: 50px;
   line-height: 50px;
   max-height: 50px;
+  padding: 0rem 1rem;
 }
 
 .nav-link
@@ -53,3 +53,26 @@
   color: $all-ports;
   cursor: pointer;
 }
+
+.ant-layout-sider { background-color: #2E2E2E; }
+.ant-menu { background-color: transparent; }
+.logo {
+  background-color: #3C3C3C;
+  display: flex;
+  justify-content: center;
+  padding: .25rem;
+}
+
+.logo-name {
+  transition: opacity .3s cubic-bezier(.645,.045,.355,1),width .3s cubic-bezier(.645,.045,.355,1);
+  .ant-layout-sider-collapsed & {
+    display: inline-block;
+    max-width: 0;
+    opacity: 0;
+  }
+}
+
+.logo-symbol {
+  padding-left: .5rem;
+  padding-right: .5rem;
+}
diff --git a/metron-interface/metron-alerts/src/app/app.component.spec.ts b/metron-interface/metron-alerts/src/app/app.component.spec.ts
index 1485904..0009f4d 100644
--- a/metron-interface/metron-alerts/src/app/app.component.spec.ts
+++ b/metron-interface/metron-alerts/src/app/app.component.spec.ts
@@ -23,10 +23,38 @@ import { AuthenticationService } from './service/authentication.service';
 import { of } from 'rxjs';
 import { DialogService } from './service/dialog.service';
 import { MetronDialogComponent } from './shared/metron-dialog/metron-dialog.component';
+import { RouterTestingModule } from '@angular/router/testing';
+import {
+  NzLayoutModule,
+  NzMenuModule,
+  NgZorroAntdModule,
+  NZ_ICONS
+} from 'ng-zorro-antd';
+import {
+  ToolOutline,
+  WarningOutline,
+  FileOutline
+} from '@ant-design/icons-angular/icons';
+import { IconDefinition } from '@ant-design/icons-angular';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import {AppConfigService} from "./service/app-config.service";
+
+const icons: IconDefinition[] = [ ToolOutline, WarningOutline, FileOutline ];
 
 @Component({ selector: 'router-outlet', template: '' })
 class RouterOutletStubComponent {}
 
+class FakeAppConfigService {
+
+  getManagementUIHost() {
+    return 'localhost';
+  }
+
+  getManagementUIPort() {
+    return '4200'
+  }
+}
+
 describe('AppComponent', () => {
   let component: AppComponent;
   let fixture: ComponentFixture<AppComponent>;
@@ -35,13 +63,20 @@ describe('AppComponent', () => {
     TestBed.configureTestingModule({
       providers: [
         DialogService,
-        { provide: AuthenticationService, useValue: { onLoginEvent: of(true) } }
+        { provide: AuthenticationService, useValue: { onLoginEvent: of(true) } },
+        { provide: AppConfigService, useClass: FakeAppConfigService },
+        { provide: NZ_ICONS, useValue: icons }
       ],
       declarations: [
         AppComponent,
         MetronDialogComponent,
         RouterOutletStubComponent,
       ],
+      imports: [
+        NzLayoutModule,
+        NzMenuModule,
+        BrowserAnimationsModule,
+        NgZorroAntdModule, RouterTestingModule ]
     }).compileComponents();
   }));
 
diff --git a/metron-interface/metron-alerts/src/app/app.component.ts b/metron-interface/metron-alerts/src/app/app.component.ts
index e2fc0f8..7d2fa7c 100644
--- a/metron-interface/metron-alerts/src/app/app.component.ts
+++ b/metron-interface/metron-alerts/src/app/app.component.ts
@@ -18,6 +18,7 @@
 import { Component, OnInit } from '@angular/core';
 import {AuthenticationService} from './service/authentication.service';
 import { environment } from 'environments/environment';
+import {AppConfigService} from './service/app-config.service';
 
 @Component({
   selector: 'metron-alerts-root',
@@ -27,8 +28,42 @@ import { environment } from 'environments/environment';
 export class AppComponent implements OnInit {
   loggedIn = false;
   noTransition = false;
+  isCollapsed = false;
+  hostname = this.appConfigService.getManagementUIHost();
+  centralNavLinks = [
+    {
+      linkName: 'Alerts',
+      iconClass: 'warning',
+      subLinks: [
+        {
+          linkName: 'Overview',
+          routerLink: '/alerts-list'
+        },
+        {
+          linkName: 'PCAP',
+          routerLink: '/pcap'
+        }
+      ]
+    },
+    {
+      linkName: 'Management',
+      iconClass: 'tool',
+      subLinks: [
+        {
+          linkName: 'Sensors',
+          routerLink: ':' + this.appConfigService.getManagementUIPort() + '/sensors',
+          externalLink: true
+        },
+        {
+          linkName: 'General Settings',
+          routerLink: ':' + this.appConfigService.getManagementUIPort() + '/general-settings',
+          externalLink: true
+        }
+      ]
+    }
+  ]
 
-  constructor(private authService: AuthenticationService) {
+  constructor(private authService: AuthenticationService, private appConfigService: AppConfigService) {
     this.authService.onLoginEvent.subscribe(result => {
       this.loggedIn = result;
     });
diff --git a/metron-interface/metron-alerts/src/app/app.module.ts b/metron-interface/metron-alerts/src/app/app.module.ts
index 560171e..efba0e3 100644
--- a/metron-interface/metron-alerts/src/app/app.module.ts
+++ b/metron-interface/metron-alerts/src/app/app.module.ts
@@ -21,6 +21,7 @@ import { NgModule } from '@angular/core';
 import { FormsModule } from '@angular/forms';
 import {HttpClientModule, HTTP_INTERCEPTORS} from '@angular/common/http';
 import { APP_INITIALIZER } from '@angular/core';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 
 import { AppComponent } from './app.component';
 import {MetronAlertsRoutingModule} from './app-routing.module';
@@ -41,19 +42,33 @@ import {AuthenticationService} from './service/authentication.service';
 import {LoginGuard} from './shared/login-guard';
 import {UpdateService} from './service/update.service';
 import {MetaAlertService} from './service/meta-alert.service';
-import {MetaAlertsModule} from './alerts/meta-alerts/meta-alerts.module';
-import {SearchService} from './service/search.service';
+import { MetaAlertsModule } from './alerts/meta-alerts/meta-alerts.module';
+import { SearchService } from './service/search.service';
 import { GlobalConfigService } from './service/global-config.service';
 import { DefaultHeadersInterceptor } from './http-interceptors/default-headers.interceptor';
 import { DialogService } from './service/dialog.service';
 import { MetronDialogComponent } from './shared/metron-dialog/metron-dialog.component';
-import {PcapModule} from './pcap/pcap.module';
+import { PcapModule } from './pcap/pcap.module';
 import { AppConfigService } from './service/app-config.service';
+import {
+  NzLayoutModule,
+  NzMenuModule,
+  NgZorroAntdModule,
+  NZ_ICONS
+} from 'ng-zorro-antd';
+import {
+  ToolOutline,
+  WarningOutline,
+  FileOutline
+} from '@ant-design/icons-angular/icons';
+import { IconDefinition } from '@ant-design/icons-angular';
 
 export function initConfig(appConfigService: AppConfigService) {
   return () => appConfigService.loadAppConfig();
 }
 
+const icons: IconDefinition[] = [ ToolOutline, WarningOutline, FileOutline ];
+
 @NgModule({
   declarations: [
     AppComponent,
@@ -72,11 +87,16 @@ export function initConfig(appConfigService: AppConfigService) {
     ConfigureRowsModule,
     SaveSearchModule,
     SavedSearchesModule,
-    PcapModule
+    PcapModule,
+    NzLayoutModule,
+    NzMenuModule,
+    BrowserAnimationsModule,
+    NgZorroAntdModule,
   ],
   providers: [{ provide: APP_INITIALIZER, useFactory: initConfig, deps: [AppConfigService], multi: true },
               { provide: DataSource, useClass: ElasticSearchLocalstorageImpl },
               { provide: HTTP_INTERCEPTORS, useClass: DefaultHeadersInterceptor, multi: true },
+              { provide: NZ_ICONS, useValue: icons },
               AppConfigService,
               AuthenticationService,
               AuthGuard,
diff --git a/metron-interface/metron-alerts/src/app/service/app-config.service.ts b/metron-interface/metron-alerts/src/app/service/app-config.service.ts
index 97a18f5..4d5ac22 100644
--- a/metron-interface/metron-alerts/src/app/service/app-config.service.ts
+++ b/metron-interface/metron-alerts/src/app/service/app-config.service.ts
@@ -59,4 +59,18 @@ export class AppConfigService {
     }
     return AppConfigService.appConfigStatic['contextMenuConfigURL'];
   }
+
+  getManagementUIHost() {
+      if (AppConfigService.appConfigStatic['managementUIHost'] === undefined) {
+          console.error('[AppConfigService] managementUIHost entry is missing from /assets/app-config.json');
+      }
+      return AppConfigService.appConfigStatic['managementUIHost'];
+  }
+
+  getManagementUIPort() {
+      if (AppConfigService.appConfigStatic['managementUIPort'] === undefined) {
+          console.error('[AppConfigService] managementUIPort entry is missing from /assets/app-config.json');
+      }
+      return AppConfigService.appConfigStatic['managementUIPort'];
+  }
 }
diff --git a/metron-interface/metron-alerts/src/assets/app-config.json b/metron-interface/metron-alerts/src/assets/app-config.json
index 04dbc54..a664dcb 100644
--- a/metron-interface/metron-alerts/src/assets/app-config.json
+++ b/metron-interface/metron-alerts/src/assets/app-config.json
@@ -1,5 +1,7 @@
 {
   "apiRoot": "/api/v1",
   "loginPath": "/login",
-  "contextMenuConfigURL": "/assets/context-menu.conf.json"
+  "contextMenuConfigURL": "/assets/context-menu.conf.json",
+  "managementUIHost": "localhost",
+  "managementUIPort": "4200"
 }
\ No newline at end of file
diff --git a/metron-interface/metron-alerts/src/assets/images/logo-name.png b/metron-interface/metron-alerts/src/assets/images/logo-name.png
new file mode 100644
index 0000000..f91970d
Binary files /dev/null and b/metron-interface/metron-alerts/src/assets/images/logo-name.png differ
diff --git a/metron-interface/metron-alerts/src/assets/images/logo-symbol.png b/metron-interface/metron-alerts/src/assets/images/logo-symbol.png
new file mode 100644
index 0000000..297f0f1
Binary files /dev/null and b/metron-interface/metron-alerts/src/assets/images/logo-symbol.png differ
diff --git a/metron-interface/metron-alerts/src/styles.scss b/metron-interface/metron-alerts/src/styles.scss
index 4b1ce8a..3aa4a18 100644
--- a/metron-interface/metron-alerts/src/styles.scss
+++ b/metron-interface/metron-alerts/src/styles.scss
@@ -23,6 +23,8 @@
 @import "../node_modules/pikaday-time/scss/pikaday.scss";
 @import "hexagon";
 @import "confirm-popover.scss";
+@import "~ng-zorro-antd/layout/style/index.min.css"; /* Import styles of the component */
+@import "~ng-zorro-antd/menu/style/index.min.css"; /* Import styles of the component */
 
 body,
 button {
@@ -358,3 +360,65 @@ $background_color_3: #2196F3;
   cursor: not-allowed;
   pointer-events: all;
 }
+
+.ant-layout {
+  background: transparent;
+  min-height: 100vh;
+}
+
+.ant-layout-sider-trigger { background: #3C3C3C; }
+
+.cdk-overlay-pane {
+  position: absolute;
+  z-index: 1000;
+}
+
+.cdk-overlay-connected-position-bounding-box {
+  display: flex;
+  flex-direction: column;
+  min-height: 1px;
+  min-width: 1px;
+  position: absolute;
+  z-index: 1000;
+}
+
+.cdk-overlay-container {
+  height: 100%;
+  left: 0;
+  pointer-events: none;
+  position: fixed;
+  top: 0;
+  width: 100%;
+  z-index: 1000;
+}
+
+.ant-menu-dark .ant-menu-sub {
+  background: #2e2e2e;
+}
+
+.ant-menu.ant-menu-dark :not(ant-menu-submenu-open) .ant-menu-item-selected,
+.ant-menu.ant-menu-dark .ant-menu-sub .ant-menu-item-selected {
+  background-color: rgba(255, 255, 255, .1);
+}
+
+.ant-menu.ant-menu-dark .ant-menu-item-selected {
+  background-color: transparent;
+}
+
+.ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-selected {
+  background-color: rgba(255, 255, 255, .1);
+}
+
+.ant-menu-dark .ant-menu-inline.ant-menu-sub {
+  background: #2e2e2e;
+  box-shadow: none;
+}
+
+.ant-menu-submenu-title {
+  color: rgba(255,255,255,.65);
+}
+
+.ant-menu-submenu-arrow::before,
+.ant-menu-submenu-arrow::after {
+  background: rgba(255,255,255,.65);
+}
\ No newline at end of file
diff --git a/metron-interface/metron-config/package-lock.json b/metron-interface/metron-config/package-lock.json
index 7527925..deb333d 100644
--- a/metron-interface/metron-config/package-lock.json
+++ b/metron-interface/metron-config/package-lock.json
@@ -339,6 +339,23 @@
         "tslib": "^1.9.0"
       }
     },
+    "@angular/cdk": {
+      "version": "7.3.7",
+      "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-7.3.7.tgz",
+      "integrity": "sha512-xbXxhHHKGkVuW6K7pzPmvpJXIwpl0ykBnvA2g+/7Sgy5Pd35wCC+UtHD9RYczDM/mkygNxMQtagyCErwFnDtQA==",
+      "requires": {
+        "parse5": "^5.0.0",
+        "tslib": "^1.7.1"
+      },
+      "dependencies": {
+        "parse5": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
+          "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
+          "optional": true
+        }
+      }
+    },
     "@angular/cli": {
       "version": "7.3.9",
       "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-7.3.9.tgz",
@@ -1342,6 +1359,23 @@
         "tslib": "^1.9.0"
       }
     },
+    "@ant-design/colors": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-3.1.0.tgz",
+      "integrity": "sha512-Td7g1P53sNFyT4Gya6836e70TrhoVZ+HjZs6mpWIHrxl4/VqsjjOyzj/8ktOuw0lCx+BfYu9UO1CiJ0MoYYfhg==",
+      "requires": {
+        "tinycolor2": "^1.4.1"
+      }
+    },
+    "@ant-design/icons-angular": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@ant-design/icons-angular/-/icons-angular-2.1.0.tgz",
+      "integrity": "sha512-FDOtuxPKm2CaxWBWFqP2a5abtrrlVz8HzBdLEJJD68bW9ombWQKH71ZMp1Iw53Koqn1KTUCy0jPqSuSwx5wcrA==",
+      "requires": {
+        "@ant-design/colors": "^3.1.0",
+        "tslib": "^1.9.0"
+      }
+    },
     "@ngtools/webpack": {
       "version": "7.3.9",
       "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-7.3.9.tgz",
@@ -3623,6 +3657,11 @@
         "assert-plus": "^1.0.0"
       }
     },
+    "date-fns": {
+      "version": "1.30.1",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
+      "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw=="
+    },
     "date-format": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz",
@@ -7897,6 +7936,17 @@
       "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
       "dev": true
     },
+    "ng-zorro-antd": {
+      "version": "7.5.1",
+      "resolved": "https://registry.npmjs.org/ng-zorro-antd/-/ng-zorro-antd-7.5.1.tgz",
+      "integrity": "sha512-0V/LoARoluFjiPUX4Q7x+G7hVA+k+x4g4OyYaLLUAoPpK3o1kriR3VzjdKsuKl73gBoRHHq4SNDRSiqzfOWDeA==",
+      "requires": {
+        "@angular/cdk": "^7.0.0",
+        "@ant-design/icons-angular": "^2.1.0",
+        "date-fns": "^1.29.0",
+        "tslib": "^1.9.0"
+      }
+    },
     "nice-try": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
@@ -11176,6 +11226,11 @@
         "setimmediate": "^1.0.4"
       }
     },
+    "tinycolor2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz",
+      "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g="
+    },
     "tmp": {
       "version": "0.0.33",
       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
diff --git a/metron-interface/metron-config/package.json b/metron-interface/metron-config/package.json
index 28bd758..633d69c 100644
--- a/metron-interface/metron-config/package.json
+++ b/metron-interface/metron-config/package.json
@@ -46,6 +46,7 @@
     "font-awesome": "^4.6.3",
     "jquery": "^3.3.1",
     "karma-phantomjs-launcher": "^1.0.4",
+    "ng-zorro-antd": "^7.5.1",
     "popper.js": "^1.14.4",
     "puppeteer": "^1.8.0",
     "rxjs": "6.5.2",
diff --git a/metron-interface/metron-config/src/app/app.component.html b/metron-interface/metron-config/src/app/app.component.html
index 6825ddc..18f678c 100644
--- a/metron-interface/metron-config/src/app/app.component.html
+++ b/metron-interface/metron-config/src/app/app.component.html
@@ -1,25 +1,60 @@
 <!--
   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
+  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
+  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
+  OR CONDITIONS OF ANY KIND, either express or implied. See the License for
   the specific language governing permissions and limitations under the License.
   -->
-<div class="container-fluid header" *ngIf="loggedIn">
-  <metron-config-navbar></metron-config-navbar>
-</div>
-<div [ngClass]="{'container-fluid body-fill px-0': loggedIn, 'fill': !loggedIn}">
-  <div [ngClass]="{'card-group ': loggedIn}" class="fill">
-    <div  *ngIf="loggedIn" class="fill navigation" ><metron-config-vertical-navbar></metron-config-vertical-navbar></div>
-    <div [ngClass]="{'fill content px-0 ' : loggedIn , 'fill': !loggedIn}"><router-outlet></router-outlet></div>
-  </div>
-</div>
-<router-outlet name="dialog" ></router-outlet>
+<nz-layout>
+  <nz-sider *ngIf="loggedIn" nzCollapsible [(nzCollapsed)]="isCollapsed" nzWidth="200px">
+    <div class="logo" style="height: 50px;">
+        <img class="icon logo-symbol h-100" src="assets/images/logo-symbol.png" alt="">
+        <img class="icon logo-name h-100" src="assets/images/logo-name.png" alt="">
+    </div>
+    <nav>
+      <ul nz-menu nzMode="inline" [nzInlineCollapsed]="isCollapsed" nzTheme="dark">
+        <li nz-submenu nzOpen *ngFor="let link of centralNavLinks; let i = index" routerLinkActive="ant-menu-item-selected">
+          <span title><i nz-icon [nzType]="link.iconClass"></i><span class="nav-text">{{ link.linkName }}</span></span>
+          <ng-container *ngIf="link.subLinks">
+            <ul>
+              <li *ngFor="let subLink of link.subLinks"
+              nz-menu-item
+              routerLinkActive="ant-menu-item-selected">
+                <a *ngIf="!subLink.externalLink"
+                [routerLink]="subLink.routerLink"
+                routerLinkActive="active">
+                {{ subLink.linkName }}
+                </a>
+                <a *ngIf="subLink.externalLink"
+                href="http://{{hostname}}{{subLink.routerLink}}">
+                {{ subLink.linkName }}
+                </a>
+              </li>
+            </ul>
+          </ng-container>
+        </li>
+      </ul>
+    </nav>
+  </nz-sider>
+  <nz-layout>
+    <nz-content>
+      <div class="header" *ngIf="loggedIn">
+        <metron-config-navbar></metron-config-navbar>
+      </div>
+      <div [ngClass]="{'container-fluid body-fill px-0': loggedIn, 'fill': !loggedIn}">
+        <div [ngClass]="{'card-group ': loggedIn}" class="fill">
+          <div [ngClass]="{'fill content px-0 ' : loggedIn , 'fill': !loggedIn}"><router-outlet></router-outlet></div>
+        </div>
+      </div>
+      <router-outlet name="dialog" ></router-outlet>
+    </nz-content>
+  </nz-layout>
+</nz-layout>
diff --git a/metron-interface/metron-config/src/app/app.component.scss b/metron-interface/metron-config/src/app/app.component.scss
index 6060e89..9f7f672 100644
--- a/metron-interface/metron-config/src/app/app.component.scss
+++ b/metron-interface/metron-config/src/app/app.component.scss
@@ -33,3 +33,26 @@
   border: none;
   flex: 1;
 }
+
+.ant-layout-sider { background-color: #2E2E2E; }
+.ant-menu { background-color: transparent; }
+.logo {
+  background-color: #3C3C3C;
+  display: flex;
+  justify-content: center;
+  padding: .25rem;
+}
+
+ .logo-name {
+  transition: opacity .3s cubic-bezier(.645,.045,.355,1),width .3s cubic-bezier(.645,.045,.355,1);
+  .ant-layout-sider-collapsed & {
+    display: inline-block;
+    max-width: 0;
+    opacity: 0;
+  }
+}
+
+ .logo-symbol {
+  padding-left: .5rem;
+  padding-right: .5rem;
+}
diff --git a/metron-interface/metron-config/src/app/app.component.ts b/metron-interface/metron-config/src/app/app.component.ts
index 591f0b0..61e50a0 100644
--- a/metron-interface/metron-config/src/app/app.component.ts
+++ b/metron-interface/metron-config/src/app/app.component.ts
@@ -17,6 +17,7 @@
  */
 import {Component} from '@angular/core';
 import {AuthenticationService} from './service/authentication.service';
+import {AppConfigService} from './service/app-config.service';
 
 
 @Component({
@@ -28,8 +29,42 @@ import {AuthenticationService} from './service/authentication.service';
 export class AppComponent {
 
   loggedIn = false;
+  isCollapsed = false;
+  hostname = this.appConfigService.getAlertsUIHost();
+  centralNavLinks = [
+    {
+      linkName: 'Alerts',
+      iconClass: 'warning',
+      subLinks: [
+        {
+          linkName: 'Overview',
+          routerLink: ':' + this.appConfigService.getAlertsUIPort() + '/alerts-list',
+          externalLink: true
+        },
+        {
+          linkName: 'PCAP',
+          routerLink: ':' + this.appConfigService.getAlertsUIPort() + '/pcap',
+          externalLink: true
+        }
+      ]
+    },
+    {
+      linkName: 'Management',
+      iconClass: 'tool',
+      subLinks: [
+        {
+          linkName: 'Sensors',
+          routerLink: '/sensors',
+        },
+        {
+          linkName: 'General Settings',
+          routerLink: '/general-settings'
+        }
+      ]
+    }
+  ];
 
-  constructor(private authService: AuthenticationService) {
+  constructor(private authService: AuthenticationService, private appConfigService: AppConfigService) {
     this.authService.onLoginEvent.subscribe(result => {
       this.loggedIn = result;
     });
diff --git a/metron-interface/metron-config/src/app/app.module.ts b/metron-interface/metron-config/src/app/app.module.ts
index 89aa937..a0e1ea4 100644
--- a/metron-interface/metron-config/src/app/app.module.ts
+++ b/metron-interface/metron-config/src/app/app.module.ts
@@ -20,6 +20,7 @@ import {FormsModule, ReactiveFormsModule} from '@angular/forms';
 import {BrowserModule} from '@angular/platform-browser';
 import {HttpClientModule, HTTP_INTERCEPTORS} from '@angular/common/http';
 import { Router } from '@angular/router';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 import {AppComponent} from './app.component';
 import {SensorParserConfigService} from './service/sensor-parser-config.service';
 import {KafkaService} from './service/kafka.service';
@@ -46,21 +47,37 @@ import {SensorIndexingConfigService} from './service/sensor-indexing-config.serv
 import {HdfsService} from './service/hdfs.service';
 import { DefaultHeadersInterceptor } from './http-interceptors/default-headers.interceptor';
 import {AppConfigService} from './service/app-config.service';
+import {
+  NzLayoutModule,
+  NzMenuModule,
+  NgZorroAntdModule,
+  NZ_ICONS
+} from 'ng-zorro-antd';
+import {
+  ToolOutline,
+  WarningOutline,
+  FileOutline
+} from '@ant-design/icons-angular/icons';
+import { IconDefinition } from '@ant-design/icons-angular';
 
 export function initConfig(appConfigService: AppConfigService) {
   return () => appConfigService.loadAppConfig();
 }
 
+const icons: IconDefinition[] = [ ToolOutline, WarningOutline, FileOutline ];
+
 @NgModule({
   imports: [ BrowserModule, FormsModule, ReactiveFormsModule, HttpClientModule, SensorParserListModule,
-    SensorParserConfigModule, SensorParserConfigReadonlyModule, GeneralSettingsModule, MetronConfigRoutingModule ],
+    SensorParserConfigModule, SensorParserConfigReadonlyModule, GeneralSettingsModule, MetronConfigRoutingModule,NzLayoutModule,
+    NzMenuModule, BrowserAnimationsModule, NgZorroAntdModule ],
   declarations: [ AppComponent, NavbarComponent, VerticalNavbarComponent ],
   providers: [  AppConfigService, AuthenticationService, AuthGuard, LoginGuard, SensorParserConfigService,
     SensorParserConfigHistoryService, SensorEnrichmentConfigService, SensorIndexingConfigService,
     StormService, KafkaService, GrokValidationService, StellarService, HdfsService,
     GlobalConfigService, MetronAlerts, MetronDialogBox,
     { provide: HTTP_INTERCEPTORS, useClass: DefaultHeadersInterceptor, multi: true },
-    { provide: APP_INITIALIZER, useFactory: initConfig, deps: [AppConfigService], multi: true }
+    { provide: APP_INITIALIZER, useFactory: initConfig, deps: [AppConfigService], multi: true },
+    { provide: NZ_ICONS, useValue: icons },
     ],
   bootstrap:    [ AppComponent ]
 })
diff --git a/metron-interface/metron-config/src/app/navbar/navbar.component.scss b/metron-interface/metron-config/src/app/navbar/navbar.component.scss
index 5a0b0be..d30602d 100644
--- a/metron-interface/metron-config/src/app/navbar/navbar.component.scss
+++ b/metron-interface/metron-config/src/app/navbar/navbar.component.scss
@@ -26,3 +26,13 @@
   color: $form-button-border;
   cursor: pointer;
 }
+
+.page-header {
+  background-color: #2E2E2E;
+  display: flex;
+  flex-direction: row;
+  height: 50px;
+  line-height: 50px;
+  max-height: 50px;
+  padding: 0rem 1rem;
+}
diff --git a/metron-interface/metron-config/src/app/navbar/navbar.html b/metron-interface/metron-config/src/app/navbar/navbar.html
index 49f4a20..3c0cb1b 100644
--- a/metron-interface/metron-config/src/app/navbar/navbar.html
+++ b/metron-interface/metron-config/src/app/navbar/navbar.html
@@ -13,13 +13,9 @@
 	OR CONDITIONS OF ANY KIND, either express or implied. See the License for
   the specific language governing permissions and limitations under the License.
   -->
-<nav class="metron-nav navbar navbar-dark justify-content-between">
+<nav class="metron-nav page-header navbar-dark justify-content-between">
 
-  <div class="navbar-toggleable-xs" id="exCollapsingNavbar">
-    <a class="navbar-brand" href="#"><img src="assets/images/logo.png" alt="Logo" width=110></a>
-  </div>
-
-  <div class="form-inline">
+  <div class="form-inline ml-auto">
     <i class="fa fa-user " style="padding-left: 11px" aria-hidden="true"></i>
     <div *ngIf="currentUser != null" class="fa logout">Logged in as {{currentUser}} - <span class="logout-link" (click)="logout()">Logout</span></div>
   </div>
diff --git a/metron-interface/metron-config/src/app/service/app-config.service.ts b/metron-interface/metron-config/src/app/service/app-config.service.ts
index 6081ea2..f3ca4c5 100644
--- a/metron-interface/metron-config/src/app/service/app-config.service.ts
+++ b/metron-interface/metron-config/src/app/service/app-config.service.ts
@@ -43,6 +43,20 @@ export class AppConfigService {
     return AppConfigService.appConfigStatic['loginPath'];
   }
 
+  getAlertsUIHost() {
+    if (AppConfigService.appConfigStatic['alertsUIHost'] === undefined) {
+      console.error('[AppConfigService] alertsUIHost entry is missing from /assets/app-config.json');
+    }
+    return AppConfigService.appConfigStatic['alertsUIHost'];
+  }
+
+  getAlertsUIPort() {
+    if (AppConfigService.appConfigStatic['alertsUIPort'] === undefined) {
+      console.error('[AppConfigService] alertsUIPort entry is missing from /assets/app-config.json');
+    }
+    return AppConfigService.appConfigStatic['alertsUIPort'];
+  }
+
   static getAppConfigStatic() {
     return AppConfigService.appConfigStatic;
   }
diff --git a/metron-interface/metron-config/src/app/service/mock.app-config.service.ts b/metron-interface/metron-config/src/app/service/mock.app-config.service.ts
index 66f41e4..683ee25 100644
--- a/metron-interface/metron-config/src/app/service/mock.app-config.service.ts
+++ b/metron-interface/metron-config/src/app/service/mock.app-config.service.ts
@@ -26,4 +26,13 @@ export class MockAppConfigService extends AppConfigService {
   getLoginPath() {
     return '/login'
   }
+
+  getAlertsUIHost() {
+    return 'localhost';
+  }
+
+  getAlertsUIPort() {
+    return '4201'
+  }
+
 }
\ No newline at end of file
diff --git a/metron-interface/metron-config/src/assets/app-config.json b/metron-interface/metron-config/src/assets/app-config.json
index e485071..7c9132c 100644
--- a/metron-interface/metron-config/src/assets/app-config.json
+++ b/metron-interface/metron-config/src/assets/app-config.json
@@ -1,4 +1,6 @@
 {
   "apiRoot": "/api/v1",
-  "loginPath": "/login"
+  "loginPath": "/login",
+  "alertsUIHost": "localhost",
+  "alertsUIPort": "4201"
 }
\ No newline at end of file
diff --git a/metron-interface/metron-config/src/assets/images/logo-name.png b/metron-interface/metron-config/src/assets/images/logo-name.png
new file mode 100644
index 0000000..f91970d
Binary files /dev/null and b/metron-interface/metron-config/src/assets/images/logo-name.png differ
diff --git a/metron-interface/metron-config/src/assets/images/logo-symbol.png b/metron-interface/metron-config/src/assets/images/logo-symbol.png
new file mode 100644
index 0000000..297f0f1
Binary files /dev/null and b/metron-interface/metron-config/src/assets/images/logo-symbol.png differ
diff --git a/metron-interface/metron-config/src/styles.scss b/metron-interface/metron-config/src/styles.scss
index 26bb57c..8a12d5f 100644
--- a/metron-interface/metron-config/src/styles.scss
+++ b/metron-interface/metron-config/src/styles.scss
@@ -18,6 +18,8 @@
 /* You can add global styles to this file, and also import other style files */
 @import "app/_variables.scss";
 @import "app/_fonts.scss";
+@import "~ng-zorro-antd/layout/style/index.min.css"; /* Import styles of the component */
+@import "~ng-zorro-antd/menu/style/index.min.css"; /* Import styles of the component */
 
 $height: 60px;
 
@@ -737,3 +739,67 @@ button
     color: #999;
   }
 }
+
+// Ant layout overrides
+
+.ant-layout {
+  background: transparent;
+  min-height: 100vh;
+}
+
+ .ant-layout-sider-trigger { background: #3C3C3C; }
+
+ .cdk-overlay-pane {
+  position: absolute;
+  z-index: 1000;
+}
+
+ .cdk-overlay-connected-position-bounding-box {
+  display: flex;
+  flex-direction: column;
+  min-height: 1px;
+  min-width: 1px;
+  position: absolute;
+  z-index: 1000;
+}
+
+ .cdk-overlay-container {
+  height: 100%;
+  left: 0;
+  pointer-events: none;
+  position: fixed;
+  top: 0;
+  width: 100%;
+  z-index: 1000;
+}
+
+ .ant-menu-dark .ant-menu-sub {
+  background: #2e2e2e;
+}
+
+ .ant-menu.ant-menu-dark :not(ant-menu-submenu-open) .ant-menu-item-selected,
+.ant-menu.ant-menu-dark .ant-menu-sub .ant-menu-item-selected {
+  background-color: rgba(255, 255, 255, .1);
+}
+
+ .ant-menu.ant-menu-dark .ant-menu-item-selected {
+  background-color: transparent;
+}
+
+ .ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-selected {
+  background-color: rgba(255, 255, 255, .1);
+}
+
+ .ant-menu-dark .ant-menu-inline.ant-menu-sub {
+  background: #2e2e2e;
+  box-shadow: none;
+}
+
+ .ant-menu-submenu-title {
+  color: rgba(255,255,255,.65);
+}
+
+ .ant-menu-submenu-arrow::before,
+.ant-menu-submenu-arrow::after {
+  background: rgba(255,255,255,.65);
+}