Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/.editorconfig
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/.editorconfig	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/.editorconfig	(working copy)
@@ -0,0 +1,17 @@
+# Editor configuration, see https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.ts]
+quote_type = single
+ij_typescript_use_double_quotes = false
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/.gitignore
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/.gitignore	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/.gitignore	(working copy)
@@ -0,0 +1,42 @@
+# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
+
+# Compiled output
+/dist
+/tmp
+/out-tsc
+/bazel-out
+
+# Node
+/node_modules
+npm-debug.log
+yarn-error.log
+
+# IDEs and editors
+.idea/
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# Visual Studio Code
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+.history/*
+
+# Miscellaneous
+/.angular/cache
+.sass-cache/
+/connect.lock
+/coverage
+/libpeerconnection.log
+testem.log
+/typings
+
+# System files
+.DS_Store
+Thumbs.db
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/README.md
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/README.md	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/README.md	(working copy)
@@ -0,0 +1,59 @@
+# Gui
+
+This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.0.2.
+
+## Development server
+
+To start a local development server, run:
+
+```bash
+ng serve
+```
+
+Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
+
+## Code scaffolding
+
+Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
+
+```bash
+ng generate component component-name
+```
+
+For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
+
+```bash
+ng generate --help
+```
+
+## Building
+
+To build the project run:
+
+```bash
+ng build
+```
+
+This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
+
+## Running unit tests
+
+To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
+
+```bash
+ng test
+```
+
+## Running end-to-end tests
+
+For end-to-end (e2e) testing, run:
+
+```bash
+ng e2e
+```
+
+Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
+
+## Additional Resources
+
+For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/angular.json
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/angular.json	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/angular.json	(working copy)
@@ -0,0 +1,101 @@
+{
+  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
+  "version": 1,
+  "newProjectRoot": "projects",
+  "projects": {
+    "gui": {
+      "projectType": "application",
+      "schematics": {
+        "@schematics/angular:component": {
+          "style": "scss"
+        }
+      },
+      "root": "",
+      "sourceRoot": "src",
+      "prefix": "app",
+      "architect": {
+        "build": {
+          "builder": "@angular/build:application",
+          "options": {
+            "browser": "src/main.ts",
+            "polyfills": [
+              "zone.js"
+            ],
+            "tsConfig": "tsconfig.app.json",
+            "inlineStyleLanguage": "scss",
+            "assets": [
+              "src/favicon.ico",
+              "src/assets"
+            ],
+            "styles": [
+              "src/styles.scss"
+            ],
+            "server": "src/main.server.ts",
+            "outputMode": "server",
+            "ssr": {
+              "entry": "src/server.ts"
+            }
+          },
+          "configurations": {
+            "production": {
+              "budgets": [
+                {
+                  "type": "initial",
+                  "maximumWarning": "500kB",
+                  "maximumError": "1MB"
+                },
+                {
+                  "type": "anyComponentStyle",
+                  "maximumWarning": "4kB",
+                  "maximumError": "8kB"
+                }
+              ],
+              "outputHashing": "all"
+            },
+            "development": {
+              "optimization": false,
+              "extractLicenses": false,
+              "sourceMap": true
+            }
+          },
+          "defaultConfiguration": "production"
+        },
+        "serve": {
+          "builder": "@angular/build:dev-server",
+          "configurations": {
+            "production": {
+              "buildTarget": "gui:build:production"
+            },
+            "development": {
+              "buildTarget": "gui:build:development"
+            }
+          },
+          "defaultConfiguration": "development"
+        },
+        "extract-i18n": {
+          "builder": "@angular/build:extract-i18n"
+        },
+        "test": {
+          "builder": "@angular/build:karma",
+          "options": {
+            "polyfills": [
+              "zone.js",
+              "zone.js/testing"
+            ],
+            "tsConfig": "tsconfig.spec.json",
+            "inlineStyleLanguage": "scss",
+            "assets": [
+              {
+                "glob": "**/*",
+                "input": "public"
+              }
+            ],
+            "styles": [
+              "src/styles.scss"
+            ]
+          }
+        }
+      }
+    }
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/package.json
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/package.json	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/package.json	(working copy)
@@ -0,0 +1,46 @@
+{
+  "name": "gui",
+  "version": "0.0.0",
+  "scripts": {
+    "ng": "ng",
+    "start": "ng serve",
+    "build": "ng build",
+    "watch": "ng build --watch --configuration development",
+    "test": "ng test",
+    "serve:ssr:gui": "node dist/gui/server/server.mjs"
+  },
+  "private": true,
+  "dependencies": {
+    "@angular/common": "^20.0.0",
+    "@angular/compiler": "^20.0.0",
+    "@angular/core": "^20.0.0",
+    "@angular/forms": "^20.0.0",
+    "@angular/platform-browser": "^20.0.0",
+    "@angular/platform-server": "^20.0.0",
+    "@angular/router": "^20.0.0",
+    "@angular/ssr": "^20.0.2",
+    "express": "^5.1.0",
+    "rxjs": "~7.8.0",
+    "tslib": "^2.3.0",
+    "zone.js": "~0.15.0",
+    "@fortawesome/angular-fontawesome": "^2.0.1",
+    "@fortawesome/fontawesome-svg-core": "^6.7.2",
+    "@fortawesome/free-solid-svg-icons": "^6.7.2",
+    "@angular/material": "^20.0.0"
+  },
+  "devDependencies": {
+    "@angular/build": "^20.0.2",
+    "@angular/cli": "^20.0.2",
+    "@angular/compiler-cli": "^20.0.0",
+    "@types/express": "^5.0.1",
+    "@types/jasmine": "~5.1.0",
+    "@types/node": "^20.17.19",
+    "jasmine-core": "~5.7.0",
+    "karma": "~6.4.0",
+    "karma-chrome-launcher": "~3.2.0",
+    "karma-coverage": "~2.2.0",
+    "karma-jasmine": "~5.1.0",
+    "karma-jasmine-html-reporter": "~2.1.0",
+    "typescript": "~5.8.2"
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/public/favicon.ico
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: src/webui/webui/htdocs/new/src/gui/public/favicon.ico
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.config.server.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.config.server.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.config.server.ts	(working copy)
@@ -0,0 +1,12 @@
+import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
+import { provideServerRendering, withRoutes } from '@angular/ssr';
+import { appConfig } from './app.config';
+import { serverRoutes } from './app.routes.server';
+
+const serverConfig: ApplicationConfig = {
+  providers: [
+    provideServerRendering(withRoutes(serverRoutes))
+  ]
+};
+
+export const config = mergeApplicationConfig(appConfig, serverConfig);
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.config.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.config.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.config.ts	(working copy)
@@ -0,0 +1,13 @@
+import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core';
+import { provideRouter } from '@angular/router';
+
+import { routes } from './app.routes';
+import { provideClientHydration, withEventReplay } from '@angular/platform-browser';
+
+export const appConfig: ApplicationConfig = {
+  providers: [
+    provideBrowserGlobalErrorListeners(),
+    provideZoneChangeDetection({ eventCoalescing: true }),
+    provideRouter(routes), provideClientHydration(withEventReplay())
+  ]
+};
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.html	(working copy)
@@ -0,0 +1,10 @@
+<div class="app-wrapper" [class.sidebar-collapsed]="isSidebarCollapsed">
+  @if (currentUser) {
+    <app-navigation></app-navigation>
+  }
+  <div class="main-content" [class.no-navigation-margin]="!currentUser">
+    <div class="main-content-inner">
+      <router-outlet></router-outlet>
+    </div>
+  </div>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.routes.server.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.routes.server.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.routes.server.ts	(working copy)
@@ -0,0 +1,8 @@
+import { RenderMode, ServerRoute } from '@angular/ssr';
+
+export const serverRoutes: ServerRoute[] = [
+  {
+    path: '**',
+    renderMode: RenderMode.Prerender
+  }
+];
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.routes.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.routes.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.routes.ts	(working copy)
@@ -0,0 +1,18 @@
+import { Routes } from '@angular/router';
+import {Login} from './components/login/login';
+import {AuthGuard} from './guards/auth-guard';
+import {Dashboard} from './components/dashboard/dashboard';
+
+export const routes: Routes = [
+  {path: 'login', component: Login},
+  {
+    path: '',
+    canActivate: [AuthGuard],
+    children: [
+      {path: 'dashboard', component: Dashboard, data: {roles: ['super_admin', 'device_admin', 'common_admin']}},
+      {path: '', redirectTo: 'dashboard', pathMatch: 'full'},
+      { path: '**', redirectTo: 'dashboard' }
+    ]
+  },
+  {path: '**', redirectTo: 'login'}
+];
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.scss	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.scss	(working copy)
@@ -0,0 +1,38 @@
+.app-wrapper {
+  display: flex;
+  flex-direction: column;
+  min-height: 100vh;
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+
+.main-content {
+  flex-grow: 1;
+  padding: 20px;
+  transition: margin-left 0.3s ease, margin-top 0.3s ease;
+  margin-top: 60px;
+  margin-left: 250px;
+  width: calc(100% - 250px);
+  box-sizing: border-box;
+  overflow-y: auto; /* Allow vertical scroll only if needed */
+  height: calc(100vh - 60px); /* Account for top bar */
+}
+
+.app-wrapper.sidebar-collapsed .main-content {
+  margin-left: 60px;
+  width: calc(100% - 60px);
+}
+
+.main-content.no-navigation-margin {
+  margin: 0 !important;
+  width: 100% !important;
+  height: 100vh !important;
+  max-height: 100vh; /* Prevent exceeding viewport */
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 0 !important;
+  overflow: hidden;
+}
+
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.spec.ts	(working copy)
@@ -0,0 +1,23 @@
+import { TestBed } from '@angular/core/testing';
+import { App } from './app';
+
+describe('App', () => {
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [App],
+    }).compileComponents();
+  });
+
+  it('should create the app', () => {
+    const fixture = TestBed.createComponent(App);
+    const app = fixture.componentInstance;
+    expect(app).toBeTruthy();
+  });
+
+  it('should render title', () => {
+    const fixture = TestBed.createComponent(App);
+    fixture.detectChanges();
+    const compiled = fixture.nativeElement as HTMLElement;
+    expect(compiled.querySelector('h1')?.textContent).toContain('Hello, gui');
+  });
+});
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.ts	(working copy)
@@ -0,0 +1,49 @@
+import {Component, OnDestroy, OnInit} from '@angular/core';
+import {RouterOutlet} from '@angular/router';
+import {Auth} from './services/auth';
+import {Subscription} from 'rxjs';
+import {Navigation} from './components/navigation/navigation';
+import {FontAwesomeModule} from '@fortawesome/angular-fontawesome';
+import {User} from './models/user';
+
+@Component({
+  selector: 'app-root',
+  imports: [RouterOutlet, Navigation, FontAwesomeModule],
+  templateUrl: './app.html',
+  styleUrl: './app.scss'
+})
+export class App implements OnInit, OnDestroy {
+  protected title = 'Array Management Platform';
+  currentUser: User | null = null;
+  private authSubscription!: Subscription;
+
+  isSidebarCollapsed: boolean = false;
+
+  constructor(private authService: Auth) {
+  }
+
+  ngOnInit(): void {
+    // Subscribe to authentication status changes
+    this.authSubscription = this.authService.currentUser.subscribe(user => {
+      this.currentUser = user;
+    })
+    // this.authSubscription = this.authService.isLoggedIn.subscribe((loggedInStatus: boolean) => {
+    //   this.isLoggedIn = loggedInStatus;
+    //   // If logged out, reset sidebar state (optional, but good practice)
+    //   if (!loggedInStatus) {
+    //     this.isSidebarCollapsed = false;
+    //   }
+    // });
+  }
+
+  ngOnDestroy(): void {
+    // Unsubscribe to prevent memory leaks
+    if (this.authSubscription) {
+      this.authSubscription.unsubscribe();
+    }
+  }
+
+  onSidebarToggle(collapsed: boolean): void {
+    this.isSidebarCollapsed = collapsed;
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/dashboard/dashboard.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/dashboard/dashboard.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/dashboard/dashboard.html	(working copy)
@@ -0,0 +1 @@
+<p>dashboard works!</p>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/dashboard/dashboard.scss	(added)
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/dashboard/dashboard.scss	(revision 0)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/dashboard/dashboard.scss	(revision 0)
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/dashboard/dashboard.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/dashboard/dashboard.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/dashboard/dashboard.spec.ts	(working copy)
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { Dashboard } from './dashboard';
+
+describe('Dashboard', () => {
+  let component: Dashboard;
+  let fixture: ComponentFixture<Dashboard>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [Dashboard]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(Dashboard);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/dashboard/dashboard.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/dashboard/dashboard.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/dashboard/dashboard.ts	(working copy)
@@ -0,0 +1,11 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'app-dashboard',
+  imports: [],
+  templateUrl: './dashboard.html',
+  styleUrl: './dashboard.scss'
+})
+export class Dashboard {
+
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/login/login.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/login/login.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/login/login.html	(working copy)
@@ -0,0 +1,74 @@
+<div class="login-container">
+  <div class="box-content">
+    <mat-grid-list cols="5" rowHeight="65px">
+      <mat-grid-tile colspan="3" rowspan="5">
+        <mat-grid-tile-header class="array-avatar">
+          <div class="card-login-logo" mat-card-avatar></div>
+          <span class="login-title">Array Management Platform</span>
+        </mat-grid-tile-header>
+        @if (systemStatus != null) {
+          <div class="text-left text-white">
+            <p>Software: {{ systemStatus?.softwareVersion }}</p>
+            <p>Hostname: {{ systemStatus?.hostname }}</p>
+            <p>Serial Number: {{ systemStatus?.serialNumber }}</p>
+          </div>
+        }
+      </mat-grid-tile>
+      <mat-grid-tile colspan="2" rowspan="1">
+        <div class="text-center text-3xl">
+          <span>Welcome</span>
+        </div>
+      </mat-grid-tile>
+      <mat-grid-tile class="form-dense-3" colspan="2" rowspan="4">
+        <form
+          (ngSubmit)="onLogin()"
+          [formGroup]="loginForm"
+          class="login-form"
+        >
+          <div>
+            <mat-form-field appearance="outline" subscriptSizing="dynamic">
+              <mat-label>Username</mat-label>
+              <input
+                formControlName="username"
+                matInput
+                placeholder="Username"
+                type="text"
+              />
+            </mat-form-field>
+          </div>
+          <div>
+            <mat-form-field appearance="outline" subscriptSizing="dynamic">
+              <mat-label>Password</mat-label>
+              <input
+                formControlName="password"
+                matInput
+                placeholder="Password"
+                type="password"
+              />
+            </mat-form-field>
+          </div>
+          <p class="text-center login-error">
+            @if (isError) {
+              <span>{{ errorMessage }}</span>
+            } @else {
+              <span></span>
+            }
+          </p>
+          <button
+            matButton="filled"
+            color="primary"
+            type="submit"
+          >
+            Login
+          </button>
+        </form>
+      </mat-grid-tile>
+    </mat-grid-list>
+
+  </div>
+  <div class="copyright">
+    <span>© {{ copyRightYear }} Array Networks, Inc.</span>
+    <br/>
+    <span>All Rights reserved.</span>
+  </div>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/login/login.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/login/login.scss	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/login/login.scss	(working copy)
@@ -0,0 +1,133 @@
+.login-container {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100vh;
+  width: 100%;
+  background-color: #fff;
+  overflow: hidden;
+  margin: 0;
+  flex-direction: column;
+  box-sizing: border-box;
+}
+
+.box-content {
+  width: 680px;
+  min-height: 400px;
+  margin: 0 auto;
+  background-image: url('/assets/images/login-bg.png');
+  background-size: cover;
+  background-repeat: no-repeat;
+  background-color: rgba(255, 255, 255, 0.9);
+  border-radius: 15px;
+  padding: 20px;
+  box-sizing: border-box;
+}
+
+mat-grid-list {
+  width: 100%;
+}
+
+.login-container .copyright {
+  position: absolute;
+  bottom: 25px;
+  text-align: center;
+  font-weight: 500;
+  font-size: 14px;
+  line-height: 20px;
+  width: 100%;
+  left: 0;
+  color: #000;
+}
+
+.card-login-logo {
+  background: url('/assets/images/array_logo.png') no-repeat;
+  background-size: cover;
+  width: 55px;
+  height: 37px;
+  margin-right: 10px;
+}
+
+.array-avatar {
+  background: none !important;
+  display: flex;
+  align-items: center;
+  padding: 10px;
+}
+
+.login-title {
+  line-height: 30px;
+  margin-left: 3px !important;
+  font-size: 20px !important;
+  letter-spacing: 1px;
+  color: #fff;
+}
+
+.login-btn {
+  width: 100px;
+}
+
+.login-form {
+  padding: 20px;
+  width: 100%;
+  box-sizing: border-box;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.login-form > div {
+  width: 100%;
+  margin-bottom: 15px;
+}
+
+.login-form > div:last-child {
+  margin-bottom: 0;
+}
+
+mat-form-field {
+  width: 100%;
+}
+
+#images {
+  width: 100%;
+  height: 200px;
+  overflow: hidden;
+  position: relative;
+}
+
+#images img {
+  height: 100%;
+  position: absolute;
+  top: 0;
+  left: 50%;
+  transform: translateX(-50%);
+}
+
+.login-error {
+  color: #dc3545;
+  font-size: 1.1em;
+  text-align: center;
+  margin-bottom: 15px;
+  min-height: 20px;
+}
+
+.login {
+  background-color: transparent;
+}
+
+.text-left.text-white p {
+  margin: 5px 0;
+  font-size: 14px;
+  color: #333;
+}
+
+.text-center.text-3xl {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 100%;
+  height: 100%;
+  font-size: 1.4rem;
+  line-height: 2.25rem;
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/login/login.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/login/login.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/login/login.spec.ts	(working copy)
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { Login } from './login';
+
+describe('Login', () => {
+  let component: Login;
+  let fixture: ComponentFixture<Login>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [Login]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(Login);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/login/login.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/login/login.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/login/login.ts	(working copy)
@@ -0,0 +1,63 @@
+import {ChangeDetectionStrategy, Component} from '@angular/core';
+import {Auth} from '../../services/auth';
+import {SharedModule} from '../../shared/shared-module';
+import {FormBuilder, FormGroup, Validators} from '@angular/forms';
+import {ActivatedRoute, Router} from '@angular/router';
+import {take} from 'rxjs/operators';
+
+@Component({
+  selector: 'app-login',
+  imports: [
+    SharedModule,
+  ],
+  templateUrl: './login.html',
+  styleUrl: './login.scss',
+  changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class Login {
+  isError = false;
+  errorMessage = '';
+  loading = false;
+  submitting = false;
+  returnUrl: string;
+  loginForm: FormGroup;
+
+  systemStatus: any = null;
+  copyRightYear: number = new Date().getUTCFullYear();
+
+  constructor(private authService: Auth, private formBuilder: FormBuilder, private router: Router, private route: ActivatedRoute) {
+    if (this.authService.currentUserValue) {
+      this.router.navigate(['/dashboard']);
+    }
+
+    this.loginForm = this.formBuilder.group({
+      username: ['', Validators.required],
+      password: ['', Validators.required],
+    });
+
+    this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/dashboard';
+  }
+
+  get f() { return this.loginForm.controls; }
+
+  onLogin(): void | null {
+    this.submitting = true;
+    this.errorMessage = ''; // Clear previous errors
+    if (!this.loginForm.valid) {
+      this.isError = true;
+      this.errorMessage = 'Invalid login credentials.';
+      return null;
+    }
+    this.loading = true;
+    this.authService.login(this.f['username'].value, this.f['password'].value).pipe(take(1)).subscribe({
+      next: result => {
+        this.router.navigate([this.returnUrl]);
+      },
+      error: error => {
+        this.errorMessage = error;
+        this.loading = false;
+        this.submitting = false;
+      }
+    })
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/navigation/navigation.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/navigation/navigation.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/navigation/navigation.html	(working copy)
@@ -0,0 +1,111 @@
+<div class="navigation-container">
+  <div class="top-navbar">
+    <div class="top-left">
+      <button class="menu-toggle" (click)="toggleSidebar()">
+        <fa-icon [icon]="['fas', 'bars']"></fa-icon>
+      </button>
+      <span class="app-branding">Array </span><span class="app-platform">Management Platform</span>
+    </div>
+    <div class="top-right">
+      <fa-icon [icon]="['fas', 'question-circle']" size="2x"></fa-icon> &nbsp;
+      <fa-icon [icon]="['fas', 'bell']" size="2x"></fa-icon> &nbsp;
+      <div class="user-dropdown-container">
+        <fa-icon [icon]="['fas', 'user-circle']" size="2x" (click)="toggleUserDropdown($event)"></fa-icon> &nbsp;
+        @if (isUserDropdownOpen) {
+          <div class="user-dropdown-menu" [class.open]="isUserDropdownOpen">
+            <a href="#" (click)="isUserDropdownOpen = false">
+              <fa-icon [icon]="['fas', 'cog']"></fa-icon>
+              User Manual
+            </a>
+            <a href="#" (click)="isUserDropdownOpen = false">
+              <fa-icon [icon]="['fas', 'cog']"></fa-icon>
+              CLI Admin Handbook
+            </a>
+            <a href="#" (click)="isUserDropdownOpen = false">
+              <fa-icon [icon]="['fas', 'cog']"></fa-icon>
+              Large Screen Display
+            </a>
+            <a href="#" (click)="isUserDropdownOpen = false">
+              <fa-icon [icon]="['fas', 'cog']"></fa-icon>
+              AMP Web Console
+            </a>
+            <a href="#" (click)="isUserDropdownOpen = false">
+              <fa-icon [icon]="['fas', 'cog']"></fa-icon>
+              Save Configurations
+            </a>
+            <div class="dropdown-divider"></div>
+            <button class="logout-button-dropdown" (click)="logout()">
+              <fa-icon [icon]="['fas', 'sign-out-alt']"></fa-icon>
+              Logout
+            </button>
+          </div>
+        }
+      </div>
+    </div>
+  </div>
+  <div class="sidebar" [class.collapsed]="isSidebarCollapsed">
+    <div class="sidebar-header">
+      <span class="app-title">Array Management Platform</span>
+    </div>
+
+    <nav class="sidebar-nav">
+      <ul>
+        @if (filteredMenu$ | async; as menuItems) {
+          @for (item of menuItems; track item) {
+            @if (!item.children) {
+              <li>
+                <a [routerLink]="item.routerLink" routerLinkActive="active"
+                   (click)="isSidebarCollapsed && toggleSidebar()">
+                  @if (item.icon != '') {
+                    <fa-icon [icon]="['fas', item.icon]"></fa-icon>
+                  }
+                  <span>{{ item?.label }}</span>
+                </a>
+              </li>
+            } @else {
+              <li>
+                <a (click)="toggleSubMenu(item)" routerLinkActive="active">
+                  @if (item.icon != '') {
+                    <fa-icon [icon]="['fas', item.icon]"></fa-icon>
+                  }
+                  <span>{{ item?.label }}</span>
+                  <fa-icon [icon]="['fas', 'chevron-right']"></fa-icon>
+                </a>
+                @if (item.expanded) {
+                  <ul>
+                    @for (child of item.children; track child) {
+                      <li>
+                        <a [routerLink]="child.routerLink" routerLinkActive="active">
+                          @if (child.icon != '') {
+                            <fa-icon [icon]="['fas', child.icon]"></fa-icon>
+                          }
+                          <span>{{ child?.label }}</span>
+                        </a>
+                      </li>
+                    }
+                  </ul>
+                }
+              </li>
+            }
+          }
+        }
+      </ul>
+    </nav>
+
+    <div class="sidebar-footer">
+      <a routerLink="/demo" routerLinkActive="active" (click)="isSidebarCollapsed && toggleSidebar()">
+        <fa-icon [icon]="['fas', 'user-circle']" size="1x"></fa-icon>
+        @if (!isSidebarCollapsed) {
+          &nbsp;&nbsp;<span>Peri</span>
+        }
+      </a>
+      <button class="toggle-button" (click)="toggleSidebar();">
+        @if (isSidebarCollapsed) {
+          <fa-icon [icon]="['fas', 'angle-double-right']" [class.rotated]="isSidebarCollapsed"></fa-icon>
+        } @else {
+          <fa-icon [icon]="['fas', 'angle-double-left']" [class.rotated]="isSidebarCollapsed"></fa-icon>
+        }
+      </button>
+    </div>
+  </div>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/navigation/navigation.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/navigation/navigation.scss	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/navigation/navigation.scss	(working copy)
@@ -0,0 +1,417 @@
+.navigation-container {
+  display: flex;
+  flex-direction: column;
+  height: 100vh;
+  position: fixed;
+  left: 0;
+  top: 0;
+  z-index: 1000;
+  overflow: hidden; /* Prevent container overflow */
+}
+
+.top-navbar {
+  background-color: #222f31;
+  color: #fff;
+  height: 45px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 0 20px;
+  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
+  width: 100vw;
+  z-index: 1001;
+  box-sizing: border-box; /* Ensure padding doesn't cause overflow */
+}
+
+.top-left {
+  display: flex;
+  align-items: center;
+}
+
+.top-left .menu-toggle {
+  background: none;
+  border: none;
+  font-size: 1.5em;
+  cursor: pointer;
+  margin-right: 15px;
+  color: #555;
+  transition: color 0.2s ease;
+}
+
+.top-left .menu-toggle:hover {
+  color: #007bff;
+}
+
+.top-left .app-branding {
+  line-height: 45px;
+  color: #1170cf;
+  margin-left: 15px;
+  font-size: 18px;
+  letter-spacing: 1px;
+  font-weight: 500;
+}
+
+.top-left .app-platform {
+  line-height: 45px;
+  color: #fff;
+  margin-left: 15px;
+  font-size: 16px;
+  letter-spacing: 1px;
+}
+
+.top-right {
+  display: flex;
+  align-items: center;
+}
+
+.top-right .search-bar {
+  padding: 8px 12px;
+  border: 1px solid #ccc;
+  border-radius: 20px;
+  margin-right: 20px;
+  width: 200px;
+  outline: none;
+  transition: border-color 0.2s ease;
+}
+
+.top-right .search-bar:focus {
+  border-color: #007bff;
+}
+
+.top-right .icon {
+  font-size: 1.3em;
+  margin-left: 20px;
+  cursor: pointer;
+  color: #555;
+  transition: color 0.2s ease;
+}
+
+.top-right .icon:hover {
+  color: #007bff;
+}
+
+.top-right .logout-button {
+  background: none;
+  border: 1px solid #007bff;
+  color: #007bff;
+  padding: 8px 15px;
+  border-radius: 20px;
+  font-size: 0.9em;
+  cursor: pointer;
+  margin-left: 20px;
+  transition: background-color 0.2s ease, color 0.2s ease;
+}
+
+.top-right .logout-button:hover {
+  background-color: #007bff;
+  color: white;
+}
+
+.top-right .logout-button i {
+  margin-right: 5px;
+}
+
+.sidebar {
+  width: 250px;
+  background-color: #2c3e50;
+  color: #ecf0f1;
+  height: calc(100vh - 45px);
+  position: fixed;
+  top: 45px;
+  left: 0;
+  display: flex;
+  flex-direction: column;
+  box-shadow: 2px 0 5px rgba(0, 0, 0, 0.2);
+  transition: width 0.3s ease, transform 0.3s ease;
+  overflow-y: auto; /* Allow scroll only if needed */
+  box-sizing: border-box; /* Include padding in height/width */
+  max-height: calc(100vh - 45px); /* Cap height to viewport minus top bar */
+}
+
+.sidebar.collapsed {
+  width: 60px;
+}
+
+.sidebar-header {
+  padding: 15px;
+  display: flex;
+  align-items: center;
+  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+  flex-shrink: 0; /* Prevent header from shrinking */
+}
+
+.sidebar-header .logo {
+  width: 30px;
+  height: 30px;
+  margin-right: 10px;
+}
+
+.sidebar-header .app-title {
+  font-size: 1.2em;
+  font-weight: bold;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.sidebar.collapsed .sidebar-header .app-title {
+  display: none;
+}
+
+.sidebar-nav {
+  flex-grow: 1;
+  padding: 10px 0;
+  overflow-y: auto; /* Scroll only nav if needed */
+}
+
+.sidebar-nav ul {
+  list-style: none;
+  padding: 0;
+  margin: 0;
+}
+
+.sidebar-nav li {
+  margin-bottom: 5px;
+}
+
+.sidebar-nav a {
+  display: flex;
+  align-items: center;
+  padding: 10px 15px;
+  color: #ecf0f1;
+  text-decoration: none;
+  transition: background-color 0.2s ease;
+  position: relative;
+}
+
+.sidebar-nav a:hover {
+  background-color: #34495e;
+}
+
+.sidebar-nav a.active {
+  background-color: #007bff;
+  color: white;
+}
+
+.sidebar-nav a .icon {
+  margin-right: 15px;
+  font-size: 1.2em;
+  min-width: 20px;
+}
+
+.sidebar-nav a span {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.sidebar.collapsed .sidebar-nav a span {
+  display: none;
+}
+
+/* Original .arrow styles - replaced by .fa-chevron-right */
+/* .sidebar-nav a .arrow {
+  margin-left: auto;
+  font-size: 0.8em;
+  opacity: 0.7;
+}
+
+.sidebar.collapsed .sidebar-nav a .arrow {
+  display: none;
+} */
+
+.sidebar-footer {
+  padding: 15px;
+  border-top: 1px solid rgba(255, 255, 255, 0.1);
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  flex-shrink: 0; /* Prevent footer from shrinking */
+}
+
+.sidebar-footer a {
+  color: #ecf0f1;
+  text-decoration: none;
+  display: flex;
+  align-items: center;
+}
+
+.sidebar-footer a .icon {
+  margin-right: 10px;
+}
+
+.sidebar-footer a span {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.sidebar.collapsed .sidebar-footer a span {
+  display: none;
+}
+
+.sidebar-footer .toggle-button {
+  background: none;
+  border: none;
+  color: #ecf0f1;
+  cursor: pointer;
+  font-size: 1.2em;
+  padding: 5px;
+  display: flex;
+  align-items: center;
+}
+
+.sidebar-footer .toggle-button .fas.fa-angle-double-left.rotated {
+  transform: rotate(180deg);
+}
+
+---
+  /* --- ADDITIONS FOR SUBMENU EXPANSION --- */
+
+.sidebar-nav ul ul {
+  /* Initial state: Hidden and collapsed */
+  list-style: none; /* Remove bullet points for nested lists */
+  padding: 0;
+  margin: 0;
+  background-color: #2c3e50; /* Match parent background or slightly different */
+  max-height: 0; /* Starts collapsed */
+  overflow: hidden; /* Hides content that exceeds max-height */
+  transition: max-height 0.3s ease-in-out; /* Smooth animation for expansion/collapse */
+}
+
+/* Indent child items for visual hierarchy */
+.sidebar-nav ul ul li a {
+  padding-left: 35px; /* Adjust as needed for desired indentation */
+  background-color: #34495e; /* Slightly darker for nested items or use parent color */
+}
+
+/* Hover state for child items */
+.sidebar-nav ul ul li a:hover {
+  background-color: #3f556d; /* Darker hover for child items */
+}
+
+/* Active state for child items (if applicable) */
+.sidebar-nav ul ul li a.active {
+  background-color: #007bff; /* Keep active color consistent */
+  color: white;
+}
+
+/* --- Styles for Chevron Icon Rotation --- */
+
+.sidebar-nav a .fa-chevron-right {
+  /* Positioning and default state for the chevron icon */
+  margin-left: auto; /* Pushes the icon to the right */
+  font-size: 0.8em;
+  opacity: 0.7;
+  transition: transform 0.3s ease; /* Smooth rotation transition */
+}
+
+/* Rotate the chevron icon when the parent menu item is expanded */
+.sidebar-nav a.expanded .fa-chevron-right {
+  transform: rotate(90deg); /* Rotates the icon to point down */
+  opacity: 1; /* Make it fully visible when expanded */
+}
+
+/* Hide the chevron icon when the sidebar itself is collapsed */
+.sidebar.collapsed .sidebar-nav a .fa-chevron-right {
+  display: none;
+}
+
+/* --- Ensuring the Submenu Expands Correctly --- */
+/*
+  This rule applies max-height to the <ul> child when its preceding <a>
+  sibling has the 'expanded' class, triggering the transition.
+*/
+.sidebar-nav li a.expanded + ul {
+  max-height: 500px; /* Adjust this value if your submenus are taller.
+                        It needs to be large enough to contain all child items. */
+}
+
+.user-dropdown-container {
+  position: relative;
+  display: inline-block;
+  cursor: pointer;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  padding: 0 5px;
+  border-radius: 4px;
+  transition: background-color 0.2s ease;
+}
+
+.user-dropdown-container:hover {
+  background-color: #34495e;
+}
+
+.user-dropdown-menu {
+  position: absolute;
+  top: calc(100% + 10px);
+  right: 0;
+  background-color: #34495e;
+  border: 1px solid rgba(255, 255, 255, 0.1);
+  border-radius: 5px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
+  min-width: 200px;
+  z-index: 1002;
+  padding: 5px 0;
+
+  /* Initial state for transition: hidden */
+  opacity: 0;
+  transform: translateY(-10px) scale(0.95); /* Add scale for a slight zoom effect */
+  transition: opacity 0.2s ease-out, transform 0.2s ease-out;
+  pointer-events: none; /* Prevent interactions when hidden */
+}
+
+/* State when the dropdown is open (when the 'open' class is applied) */
+.user-dropdown-menu.open {
+  opacity: 1;
+  transform: translateY(0) scale(1);
+  pointer-events: auto; /* Allow interactions when visible */
+}
+
+/* Styling for individual links within the dropdown */
+.user-dropdown-menu a,
+.user-dropdown-menu .logout-button-dropdown {
+  display: flex;
+  align-items: center;
+  padding: 10px 15px;
+  color: #ecf0f1;
+  text-decoration: none;
+  font-size: 0.95em;
+  white-space: nowrap;
+  transition: background-color 0.2s ease, color 0.2s ease;
+  width: 100%;
+  box-sizing: border-box;
+  border: none;
+  background: none;
+  text-align: left;
+  cursor: pointer;
+}
+
+.user-dropdown-menu a:hover,
+.user-dropdown-menu .logout-button-dropdown:hover {
+  background-color: #3f556d;
+  color: #007bff;
+}
+
+.user-dropdown-menu a fa-icon,
+.user-dropdown-menu .logout-button-dropdown fa-icon {
+  margin-right: 10px;
+  min-width: 20px;
+  text-align: center;
+}
+
+.dropdown-divider {
+  height: 1px;
+  background-color: rgba(255, 255, 255, 0.1);
+  margin: 5px 0;
+}
+
+.user-dropdown-menu .logout-button-dropdown {
+  color: #e74c3c;
+}
+
+.user-dropdown-menu .logout-button-dropdown:hover {
+  background-color: #c0392b;
+  color: white;
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/navigation/navigation.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/navigation/navigation.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/navigation/navigation.spec.ts	(working copy)
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { Navigation } from './navigation';
+
+describe('Navigation', () => {
+  let component: Navigation;
+  let fixture: ComponentFixture<Navigation>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [Navigation]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(Navigation);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/navigation/navigation.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/navigation/navigation.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/navigation/navigation.ts	(working copy)
@@ -0,0 +1,84 @@
+import {Component, HostListener, OnInit} from '@angular/core';
+
+import {Auth} from '../../services/auth';
+import {SharedModule} from '../../shared/shared-module';
+import {MenuItem} from '../../models/menu-item';
+import {Observable} from 'rxjs';
+import {MENU_ITEMS} from '../../constants/menu';
+import {map} from 'rxjs/operators';
+import {Router} from '@angular/router';
+
+@Component({
+  selector: 'app-navigation', imports: [SharedModule,], templateUrl: './navigation.html', styleUrl: './navigation.scss'
+})
+export class Navigation implements OnInit {
+  isSidebarCollapsed: boolean = false;
+  isUserDropdownOpen: boolean = false;
+
+  filteredMenu$: Observable<MenuItem[]> | undefined;
+
+  constructor(private authService: Auth, private router: Router) {
+  }
+
+  ngOnInit() {
+    this.filteredMenu$ = this.authService.currentUser.pipe(map(user => this.filteredMenuItems(MENU_ITEMS, user)),)
+  }
+
+  toggleSidebar(): void {
+    this.isSidebarCollapsed = !this.isSidebarCollapsed;
+  }
+
+  toggleSubMenu(item: MenuItem) {
+    item.expanded = !item.expanded;
+  }
+
+  toggleUserDropdown(event: Event): void {
+    event.stopPropagation();
+    this.isUserDropdownOpen = !this.isUserDropdownOpen;
+  }
+
+  // Close the dropdown if a click occurs outside of it
+  @HostListener('document:click', ['$event'])
+  onDocumentClick(event: Event): void {
+    const target = event.target as HTMLElement;
+    if (this.isUserDropdownOpen && !target.closest('.user-dropdown-container')) {
+      this.isUserDropdownOpen = false;
+    }
+  }
+
+  logout(): void {
+    this.isUserDropdownOpen = false;
+    this.authService.logout(); // Call logout from Auth Service
+    this.router.navigate(['/login']);
+  }
+
+  private filteredMenuItems(menuItems: MenuItem[], user: any | null): MenuItem[] {
+    if (!user) {
+      return [];
+    }
+
+    return menuItems.filter(menuItem => {
+      if (menuItem.roles && menuItem.roles.length > 0) {
+        const hasRole = menuItem.roles.some(role => this.authService.hasRole(role));
+        if (!hasRole) {
+          return false;
+        }
+      }
+
+      if (menuItem.permissions && menuItem.permissions.length > 0) {
+        const hasPermission = menuItem.permissions.some(permission => this.authService.hasPermission(permission));
+        if (!hasPermission) {
+          return false;
+        }
+      }
+
+      if (menuItem.children) {
+        menuItem.children = this.filteredMenuItems(menuItem.children, user);
+        return menuItem.children.length > 0 || (!menuItem.children && (menuItem.roles || menuItem.permissions));
+      }
+
+      return true;
+    })
+
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/constants/menu.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/constants/menu.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/constants/menu.ts	(working copy)
@@ -0,0 +1,256 @@
+import {MenuItem} from '../models/menu-item';
+
+export const MENU_ITEMS: MenuItem[] = [
+  {
+    label: 'Dashboard',
+    icon: '',
+    routerLink: '/dashboard',
+    roles: ['super_admin', 'device_admin', 'common_admin'],
+    permissions: ['Dashboard'],
+  },
+  {
+    label: 'Inventory',
+    icon: '',
+    expanded: false,
+    children: [
+      {
+        label: 'Devices',
+        icon: '',
+        routerLink: '/inventory/devices',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['iDevices']
+      },
+      {
+        label: 'Device Groups',
+        icon: '',
+        routerLink: '/inventory/device-groups',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['iDeviceGroups']
+      },
+    ]
+  },
+  {
+    label: 'System',
+    icon: '',
+    expanded: false,
+    children: [
+      {
+        label: 'General Settings',
+        icon: '',
+        routerLink: '/system/general',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['sGeneralSettings']
+      },
+      {
+        label: 'Storage',
+        icon: '',
+        routerLink: '/system/storage',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['sStorage']
+      },
+      {
+        label: 'Tasks',
+        icon: '',
+        routerLink: '/system/tasks',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['sTasks']
+      },
+      {
+        label: 'Admin Tools',
+        icon: '',
+        routerLink: '/system/storage',
+        roles: ['super_admin'],
+        permissions: ['sAdminTools']
+      },
+      {
+        label: 'Notifications',
+        icon: '',
+        routerLink: '/system/notifications',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['sNotifications']
+      }
+    ]
+  },
+  {
+    label: 'Device Services',
+    icon: '',
+    expanded: false,
+    children: [
+      {
+        label: 'HA Management',
+        icon: '',
+        routerLink: '/device/ha',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['dHA']
+      },
+      {
+        label: 'SSL Management',
+        icon: '',
+        routerLink: '/device/ssl',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['dSSL']
+      },
+    ]
+  },
+  {
+    label: 'Upgrade Centre',
+    icon: '',
+    routerLink: '/upgrade-centre',
+    roles: ['super_admin'],
+    permissions: ['UpgradeCentre']
+  },
+  {
+    label: 'Configuration Hub',
+    icon: '',
+    routerLink: '/configuration-hub',
+    roles: ['super_admin', 'device_admin'],
+    permissions: ['ConfigurationHub']
+  },
+  {
+    label: 'Topology',
+    icon: '',
+    expanded: false,
+    children: [
+      {
+        label: 'SLB Topology',
+        icon: '',
+        routerLink: '/topology/slb',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['tSLB']
+      }
+    ]
+  },
+  {
+    label: 'AVX Management',
+    icon: '',
+    expanded: false,
+    children: [
+      {
+        label: 'Devices',
+        icon: '',
+        routerLink: '/avx/devices',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['aDevices']
+      },
+      {
+        label: 'Instances',
+        icon: '',
+        routerLink: '/avx/instances',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['aInstances']
+      },
+    ]
+  },
+  {
+    label: 'Volume License',
+    icon: '',
+    expanded: false,
+    children: [
+      {
+        label: 'Licenses',
+        icon: '',
+        routerLink: '/volume-license/license',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['vLicenses']
+      },
+      {
+        label: 'Devices',
+        icon: '',
+        routerLink: '/avx/devices',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['vDevices']
+      },
+    ]
+  },
+  {
+    label: 'VPN Management',
+    icon: '',
+    routerLink: '/vpn-management',
+    roles: ['super_admin', 'device_admin', 'common_admin'],
+    permissions: ['VPN']
+  },
+  {
+    label: 'Monitoring',
+    icon: '',
+    expanded: false,
+    children: [
+      {
+        label: 'Resources',
+        icon: '',
+        routerLink: '/monitoring/resources',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['mResources']
+      },
+      {
+        label: 'Events',
+        icon: '',
+        routerLink: '/monitoring/events',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['mEvents']
+      },
+    ]
+  },
+  {
+    label: 'Alerting',
+    icon: '',
+    expanded: false,
+    children: [
+      {
+        label: 'Alert Logs',
+        icon: '',
+        routerLink: '/alerting/logs',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['aLogs']
+      },
+      {
+        label: 'Alert Rules',
+        icon: '',
+        routerLink: '/alerting/rules',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['aRules']
+      },
+      {
+        label: 'Default Alerts',
+        icon: '',
+        routerLink: '/alerting/default',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['aDefault']
+      },
+    ]
+  },
+  {
+    label: 'Reports',
+    icon: '',
+    routerLink: '/reports',
+    roles: ['super_admin', 'device_admin', 'common_admin'],
+    permissions: ['Reports']
+  },
+  {
+    label: 'Log Analysis',
+    icon: '',
+    expanded: false,
+    children: [
+      {
+        label: 'SSL Services',
+        icon: '',
+        routerLink: '/log-analysis/ssl',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['lSSL']
+      },
+      {
+        label: 'SSL VPN Services',
+        icon: '',
+        routerLink: '/log-analysis/vpn',
+        roles: ['super_admin', 'device_admin', 'common_admin'],
+        permissions: ['lVPN']
+      }
+    ]
+  },
+  {
+    label: 'Observability',
+    icon: '',
+    routerLink: '/observability',
+    roles: ['super_admin', 'device_admin', 'common_admin'],
+    permissions: ['Observability']
+  }
+]
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/guards/auth-guard.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/guards/auth-guard.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/guards/auth-guard.spec.ts	(working copy)
@@ -0,0 +1,17 @@
+import { TestBed } from '@angular/core/testing';
+import { CanActivateFn } from '@angular/router';
+
+import { authGuard } from './auth-guard';
+
+describe('authGuard', () => {
+  const executeGuard: CanActivateFn = (...guardParameters) => 
+      TestBed.runInInjectionContext(() => authGuard(...guardParameters));
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+  });
+
+  it('should be created', () => {
+    expect(executeGuard).toBeTruthy();
+  });
+});
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/guards/auth-guard.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/guards/auth-guard.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/guards/auth-guard.ts	(working copy)
@@ -0,0 +1,54 @@
+import { Injectable } from '@angular/core';
+import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
+import { Observable } from 'rxjs';
+import { Auth } from '../services/auth';
+import { map, take } from 'rxjs/operators';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class AuthGuard implements CanActivate {
+  constructor(private authService: Auth, private router: Router) {}
+
+  canActivate(
+    route: ActivatedRouteSnapshot,
+    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
+
+    const user = this.authService.currentUserValue;
+
+    if (user) {
+      if (route.data['roles']) {
+        const requiredRoles = route.data['roles'] as string[];
+        const hasRequiredRoles = requiredRoles.some((role) => this.authService.hasRole(role));
+        if (!hasRequiredRoles) {
+          return this.router.createUrlTree(['/login']);
+        }
+      }
+
+      if (route.data['permissions']) {
+        const requiredPermissions = route.data['permissions'] as string[];
+        const hasPermissions = requiredPermissions.some((permission) => this.authService.hasPermission(permission));
+        if (!hasPermissions) {
+          return this.router.createUrlTree(['/login']);
+        }
+      }
+
+      return true; // The User is logged in and has required roles/permissions.
+    }
+
+    return this.router.createUrlTree(['/login'], { queryParams: { returnUrl: state.url} });
+    // return this.authService.isLoggedIn.pipe(
+    //   take(1), // Take the first value and complete
+    //   map((isLoggedIn: boolean) => {
+    //     if (isLoggedIn) {
+    //       return true; // User is logged in, allow access
+    //     } else {
+    //       // User is not logged in, redirect to login page
+    //       // return this.router.createUrlTree(['/login']);
+    //       this.authService.logout();
+    //       return false;
+    //     }
+    //   })
+    // );
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/models/menu-item.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/models/menu-item.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/models/menu-item.ts	(working copy)
@@ -0,0 +1,9 @@
+export interface MenuItem {
+  label: string;
+  routerLink?: string;
+  icon: string;
+  roles?: string[];
+  permissions?: string[];
+  children?: MenuItem[];
+  expanded?: boolean;
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/models/user.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/models/user.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/models/user.ts	(working copy)
@@ -0,0 +1,6 @@
+export interface User {
+  id: string;
+  username: string;
+  roles: string[];
+  permissions: string[];
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/auth.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/auth.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/auth.spec.ts	(working copy)
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { Auth } from './auth';
+
+describe('Auth', () => {
+  let service: Auth;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(Auth);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/auth.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/auth.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/auth.ts	(working copy)
@@ -0,0 +1,76 @@
+import {Injectable} from '@angular/core';
+import {BehaviorSubject, Observable} from 'rxjs';
+import {Router} from '@angular/router';
+import {Storage} from './storage'
+import {User} from '../models/user';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class Auth {
+
+  private currentUserSubject: BehaviorSubject<User | null>;
+  public currentUser: Observable<User | null>;
+
+  constructor(private router: Router, private storage: Storage) {
+    this.currentUserSubject = new BehaviorSubject<User | null>(JSON.parse(storage.getItem('currentUser') || 'null'));
+    this.currentUser = this.currentUserSubject.asObservable();
+  }
+
+  public get currentUserValue(): User | null {
+    return this.currentUserSubject.value;
+  }
+
+  // ToDo: fetch from API
+  private permissions: string[] = [
+    'Dashboard',
+    'iDevices',
+    'iDeviceGroups',
+    'sGeneralSettings',
+    'sStorage',
+    'sTasks',
+    'sAdminTools',
+    'sNotifications',
+    'dHA',
+    'dSSL',
+    'UpgradeCentre',
+    'ConfigurationHub',
+    'tSLB',
+    'aDevices',
+    'aInstances',
+    'vLicenses',
+    'vDevices',
+    'VPN',
+    'mResources',
+    'mEvents',
+    'aLogs',
+    'aRules',
+    'aDefault',
+    'Reports',
+    'lSSL',
+    'lVPN',
+    'Observability',
+  ]
+
+  login(username: string, password: string): Observable<User> {
+    const user: User = {id: '1', username: 'array', roles: ['device_admin', 'super_admin', 'common_admin'], permissions: this.permissions};
+    this.storage.setItem('currentUser', JSON.stringify(user));
+    this.currentUserSubject.next(user);
+    return new BehaviorSubject(user).asObservable();
+  }
+
+  logout(): void {
+    this.storage.removeItem('currentUser');
+    this.currentUserSubject.next(null);
+  }
+
+  hasRole(role: string): boolean {
+    const user = this.currentUserValue;
+    return user ? user.roles.includes(role) : false;
+  }
+
+  hasPermission(permission: string): boolean {
+    const user = this.currentUserValue;
+    return user ? user.permissions.includes(permission) : false;
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/storage.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/storage.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/storage.spec.ts	(working copy)
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { Storage } from './storage';
+
+describe('Storage', () => {
+  let service: Storage;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(Storage);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/storage.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/storage.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/storage.ts	(working copy)
@@ -0,0 +1,38 @@
+import {Injectable} from '@angular/core';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class Storage {
+
+  private isBrowser: boolean;
+
+  constructor() {
+    this.isBrowser = typeof window !== 'undefined' && !!window.localStorage;
+  }
+
+  setItem(key: string, value: string): void {
+    if (this.isBrowser) {
+      localStorage.setItem(key, value);
+    }
+  }
+
+  getItem(key: string): string | null {
+    if (this.isBrowser) {
+      return localStorage.getItem(key);
+    }
+    return null;
+  }
+
+  removeItem(key: string): void {
+    if (this.isBrowser) {
+      localStorage.removeItem(key);
+    }
+  }
+
+  clear(): void {
+    if (this.isBrowser) {
+      localStorage.clear();
+    }
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/shared/shared-module.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/shared/shared-module.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/shared/shared-module.ts	(working copy)
@@ -0,0 +1,97 @@
+import {NgModule} from '@angular/core';
+import {CommonModule} from '@angular/common';
+import {FormsModule, ReactiveFormsModule} from '@angular/forms';
+import {RouterModule} from '@angular/router';
+import {FaIconLibrary, FontAwesomeModule} from '@fortawesome/angular-fontawesome';
+import {
+  faBars,
+  faQuestionCircle,
+  faBell,
+  faCog,
+  faUserCircle,
+  faSignOutAlt,
+  faPencilRuler,
+  faFileAlt,
+  faCogs,
+  faShieldAlt,
+  faSitemap,
+  faTools,
+  faCubes,
+  faClipboardList,
+  faChartBar,
+  faCompass,
+  faChevronRight,
+  faAngleDoubleLeft,
+  faAngleDoubleRight
+} from '@fortawesome/free-solid-svg-icons';
+import {MatGridListModule} from '@angular/material/grid-list';
+import {MatFormFieldModule} from '@angular/material/form-field';
+import {MatCardModule} from '@angular/material/card';
+import {MatButtonModule} from '@angular/material/button';
+import {MatInputModule} from '@angular/material/input';
+import {MatListModule, MatNavList} from '@angular/material/list';
+import {MatExpansionModule} from '@angular/material/expansion';
+import {MatIconModule} from '@angular/material/icon';
+
+
+@NgModule({
+  declarations: [],
+  imports: [
+    CommonModule,
+    FormsModule,
+    ReactiveFormsModule,
+    RouterModule,
+    FontAwesomeModule,
+    MatGridListModule,
+    MatFormFieldModule,
+    MatCardModule,
+    MatButtonModule,
+    MatInputModule,
+    MatNavList,
+    MatIconModule,
+    MatExpansionModule,
+    MatListModule,
+  ],
+  exports: [
+    CommonModule,
+    FormsModule,
+    ReactiveFormsModule,
+    RouterModule,
+    FontAwesomeModule,
+    MatGridListModule,
+    MatFormFieldModule,
+    MatCardModule,
+    MatButtonModule,
+    MatInputModule,
+    MatNavList,
+    MatIconModule,
+    MatExpansionModule,
+    MatListModule,
+
+  ]
+})
+export class SharedModule {
+  constructor(library: FaIconLibrary) {
+    library.addIcons(
+      faBars,
+      faQuestionCircle,
+      faBell,
+      faCog,
+      faUserCircle,
+      faSignOutAlt,
+      faPencilRuler,
+      faFileAlt,
+      faCogs,
+      faShieldAlt,
+      faSitemap,
+      faTools,
+      faCubes,
+      faClipboardList,
+      faChartBar,
+      faCompass,
+      faChevronRight,
+      faAngleDoubleLeft,
+      faAngleDoubleRight
+    );
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/assets/favicon.ico
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: src/webui/webui/htdocs/new/src/gui/src/assets/favicon.ico
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/assets/images/array_logo.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: src/webui/webui/htdocs/new/src/gui/src/assets/images/array_logo.png
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/assets/images/array_logo_white.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: src/webui/webui/htdocs/new/src/gui/src/assets/images/array_logo_white.png
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/assets/images/favicon.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: src/webui/webui/htdocs/new/src/gui/src/assets/images/favicon.png
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/assets/images/login-bg.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: src/webui/webui/htdocs/new/src/gui/src/assets/images/login-bg.png
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/assets/images/logo.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: src/webui/webui/htdocs/new/src/gui/src/assets/images/logo.png
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/index.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/index.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/index.html	(working copy)
@@ -0,0 +1,13 @@
+<!doctype html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <title>Array Management Platform</title>
+  <base href="/">
+  <meta name="viewport" content="width=device-width, initial-scale=1">
+  <link rel="icon" type="image/x-icon" href="favicon.ico">
+</head>
+<body>
+  <app-root></app-root>
+</body>
+</html>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/main.server.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/main.server.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/main.server.ts	(working copy)
@@ -0,0 +1,7 @@
+import { bootstrapApplication } from '@angular/platform-browser';
+import { App } from './app/app';
+import { config } from './app/app.config.server';
+
+const bootstrap = () => bootstrapApplication(App, config);
+
+export default bootstrap;
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/main.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/main.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/main.ts	(working copy)
@@ -0,0 +1,6 @@
+import { bootstrapApplication } from '@angular/platform-browser';
+import { appConfig } from './app/app.config';
+import { App } from './app/app';
+
+bootstrapApplication(App, appConfig)
+  .catch((err) => console.error(err));
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/server.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/server.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/server.ts	(working copy)
@@ -0,0 +1,68 @@
+import {
+  AngularNodeAppEngine,
+  createNodeRequestHandler,
+  isMainModule,
+  writeResponseToNodeResponse,
+} from '@angular/ssr/node';
+import express from 'express';
+import { join } from 'node:path';
+
+const browserDistFolder = join(import.meta.dirname, '../browser');
+
+const app = express();
+const angularApp = new AngularNodeAppEngine();
+
+/**
+ * Example Express Rest API endpoints can be defined here.
+ * Uncomment and define endpoints as necessary.
+ *
+ * Example:
+ * ```ts
+ * app.get('/api/{*splat}', (req, res) => {
+ *   // Handle API request
+ * });
+ * ```
+ */
+
+/**
+ * Serve static files from /browser
+ */
+app.use(
+  express.static(browserDistFolder, {
+    maxAge: '1y',
+    index: false,
+    redirect: false,
+  }),
+);
+
+/**
+ * Handle all other requests by rendering the Angular application.
+ */
+app.use((req, res, next) => {
+  angularApp
+    .handle(req)
+    .then((response) =>
+      response ? writeResponseToNodeResponse(response, res) : next(),
+    )
+    .catch(next);
+});
+
+/**
+ * Start the server if this module is the main entry point.
+ * The server listens on the port defined by the `PORT` environment variable, or defaults to 4000.
+ */
+if (isMainModule(import.meta.url)) {
+  const port = process.env['PORT'] || 4000;
+  app.listen(port, (error) => {
+    if (error) {
+      throw error;
+    }
+
+    console.log(`Node Express server listening on http://localhost:${port}`);
+  });
+}
+
+/**
+ * Request handler used by the Angular CLI (for dev-server and during build) or Firebase Cloud Functions.
+ */
+export const reqHandler = createNodeRequestHandler(app);
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/styles.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/styles.scss	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/styles.scss	(working copy)
@@ -0,0 +1,14 @@
+/* You can add global styles to this file, and also import other style files */
+@import '@angular/material/prebuilt-themes/azure-blue.css';
+
+html, body {
+  margin: 0;
+  padding: 0;
+  height: 100%; /* Ensure html and body explicitly take full height */
+  overflow: hidden; /* Prevent global scrollbar if app-wrapper is handling it */
+}
+
+body {
+  font-family: 'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;
+  font-size: 12px
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/tsconfig.app.json
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/tsconfig.app.json	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/tsconfig.app.json	(working copy)
@@ -0,0 +1,17 @@
+/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
+/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "outDir": "./out-tsc/app",
+    "types": [
+      "node"
+    ]
+  },
+  "include": [
+    "src/**/*.ts"
+  ],
+  "exclude": [
+    "src/**/*.spec.ts"
+  ]
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/tsconfig.json
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/tsconfig.json	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/tsconfig.json	(working copy)
@@ -0,0 +1,34 @@
+/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
+/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
+{
+  "compileOnSave": false,
+  "compilerOptions": {
+    "strict": true,
+    "noImplicitOverride": true,
+    "noPropertyAccessFromIndexSignature": true,
+    "noImplicitReturns": true,
+    "noFallthroughCasesInSwitch": true,
+    "skipLibCheck": true,
+    "isolatedModules": true,
+    "experimentalDecorators": true,
+    "importHelpers": true,
+    "target": "ES2022",
+    "module": "preserve"
+  },
+  "angularCompilerOptions": {
+    "enableI18nLegacyMessageIdFormat": false,
+    "strictInjectionParameters": true,
+    "strictInputAccessModifiers": true,
+    "typeCheckHostBindings": true,
+    "strictTemplates": true
+  },
+  "files": [],
+  "references": [
+    {
+      "path": "./tsconfig.app.json"
+    },
+    {
+      "path": "./tsconfig.spec.json"
+    }
+  ]
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/tsconfig.spec.json
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/tsconfig.spec.json	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/tsconfig.spec.json	(working copy)
@@ -0,0 +1,14 @@
+/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
+/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "outDir": "./out-tsc/spec",
+    "types": [
+      "jasmine"
+    ]
+  },
+  "include": [
+    "src/**/*.ts"
+  ]
+}
Index: /branches/amp_4_0
===================================================================
--- /branches/amp_4_0	(revision 2653)
+++ /branches/amp_4_0	(working copy)

Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1 ##
+src/webui/webui/htdocs/new/src/gui/node_modules
