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	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/app.routes.ts	(working copy)
@@ -25,6 +25,9 @@
   VpnResourceGroupOverview
 } from './components/sub-components/vpn-resource-group-overview/vpn-resource-group-overview';
 import {DeviceSsl} from './components/device-ssl/device-ssl';
+import {DeviceSslOverview} from './components/sub-components/device-ssl-overview/device-ssl-overview';
+import {DeviceHaOverview} from './components/sub-components/device-ha-overview/device-ha-overview';
+import {DeviceHa} from './components/device-ha/device-ha';
 
 
 export const routes: Routes = [
@@ -98,10 +101,25 @@
         path: 'device',
         children: [
           {
+            path: 'ha',
+            component: DeviceHa,
+            data: {roles: ['super_admin', 'device_admin', 'common_admin']}
+          },
+          {
+            path: 'ha/details/:deviceName',
+            component: DeviceHaOverview,
+            data: {roles: ['super_admin', 'device_admin', 'common_admin']}
+          },
+          {
             path: 'ssl',
             component: DeviceSsl,
             data: {roles: ['super_admin', 'device_admin', 'common_admin']}
           },
+          {
+            path: 'ssl/details/:deviceName/:serviceName/:hostName',
+            component: DeviceSslOverview,
+            data: {roles: ['super_admin', 'device_admin', 'common_admin']}
+          },
         ]
       },
       {
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ha/device-ha.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ha/device-ha.html	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ha/device-ha.html	(working copy)
@@ -1 +1,80 @@
-<p>device-ha works!</p>
+<div class="table-container">
+  <table mat-table [dataSource]="dataSource" class="mat-elevation-z1">
+    <ng-container matColumnDef="serial">
+      <th mat-header-cell *matHeaderCellDef> No.</th>
+      <td mat-cell *matCellDef="let element; let i = index;"> {{ i | globalSerial:paginator }}</td>
+    </ng-container>
+    <ng-container matColumnDef="deviceName">
+      <th mat-header-cell *matHeaderCellDef> Device Name</th>
+      <td mat-cell *matCellDef="let element"><a class="details-page-link" (click)="goToDetails(element)">{{ element?.device_name }}</a></td>
+    </ng-container>
+    <ng-container matColumnDef="status">
+      <th mat-header-cell *matHeaderCellDef> HA Status</th>
+      <td mat-cell *matCellDef="let element">
+        @if (element?.enable) {
+          <fa-icon [icon]="['far', 'check-circle']" class="success-icon"></fa-icon>
+        } @else {
+          <fa-icon [icon]="['far', 'xmark-circle']" class="delete-icon"></fa-icon>
+        }
+      </td>
+    </ng-container>
+    <ng-container matColumnDef="interval">
+      <th mat-header-cell *matHeaderCellDef> ARP Interval</th>
+      <td mat-cell *matCellDef="let element">{{ element?.arp }}</td>
+    </ng-container>
+    <ng-container matColumnDef="syncConfig">
+      <th mat-header-cell *matHeaderCellDef> Runtime Sync Config</th>
+      <td mat-cell *matCellDef="let element">
+        @if (element?.sync_runtime) {
+          <fa-icon [icon]="['far', 'check-circle']" class="success-icon"></fa-icon>
+        } @else {
+          <fa-icon [icon]="['far', 'xmark-circle']" class="delete-icon"></fa-icon>
+        }
+      </td>
+    </ng-container>
+    <ng-container matColumnDef="logging">
+      <th mat-header-cell *matHeaderCellDef> HA Logging</th>
+      <td mat-cell *matCellDef="let element">
+        @if (element?.log_enable) {
+          <fa-icon [icon]="['far', 'check-circle']" class="success-icon"></fa-icon>
+        } @else {
+          <fa-icon [icon]="['far', 'xmark-circle']" class="delete-icon"></fa-icon>
+        }
+      </td>
+    </ng-container>
+    <ng-container matColumnDef="logLevel">
+      <th mat-header-cell *matHeaderCellDef> HA Log Level</th>
+      <td mat-cell *matCellDef="let element">{{ element?.log_level }}</td>
+    </ng-container>
+    <ng-container matColumnDef="floatingMac">
+      <th mat-header-cell *matHeaderCellDef> HA Floating MAC</th>
+      <td mat-cell *matCellDef="let element">
+        @if (element?.floatmac_enable) {
+          <fa-icon [icon]="['far', 'check-circle']" class="success-icon"></fa-icon>
+        } @else {
+          <fa-icon [icon]="['far', 'xmark-circle']" class="delete-icon"></fa-icon>
+        }
+      </td>
+    </ng-container>
+    <ng-container matColumnDef="ffoLink">
+      <th mat-header-cell *matHeaderCellDef> HA FFO Link</th>
+      <td mat-cell *matCellDef="let element">
+        @if (element?.link_ffo) {
+          <fa-icon [icon]="['far', 'check-circle']" class="success-icon"></fa-icon>
+        } @else {
+          <fa-icon [icon]="['far', 'xmark-circle']" class="delete-icon"></fa-icon>
+        }
+      </td>
+    </ng-container>
+    <tr mat-header-row *matHeaderRowDef="tableColumns"></tr>
+    <tr mat-row *matRowDef="let row; columns: tableColumns;"></tr>
+    <tr class="mat-row table-no-data" *matNoDataRow>
+      <td class="mat-cell" colspan="10">No results found.</td>
+    </tr>
+  </table>
+  <mat-paginator
+    [pageSizeOptions]="[10, 15, 20, 25]"
+    [length]="totalRecords"
+    showFirstLastButtons
+  ></mat-paginator>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ha/device-ha.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ha/device-ha.ts	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ha/device-ha.ts	(working copy)
@@ -1,11 +1,64 @@
-import { Component } from '@angular/core';
+import {ChangeDetectorRef, Component, inject, ViewChild} from '@angular/core';
+import {GlobalSerialPipe} from '../../pipes/global-serial-pipe';
+import {SharedModule} from '../../shared/shared-module';
+import {MatTableDataSource} from '@angular/material/table';
+import {MatPaginator} from '@angular/material/paginator';
+import {MatDialog, MatDialogConfig} from '@angular/material/dialog';
+import {DeviceService} from '../../services/device-service';
+import {NotificationService} from '../../services/notification';
+import {Router} from '@angular/router';
+import {take} from 'rxjs/operators';
 
 @Component({
   selector: 'app-device-ha',
-  imports: [],
+  imports: [
+    SharedModule,
+    GlobalSerialPipe,
+  ],
   templateUrl: './device-ha.html',
   styleUrl: './device-ha.scss'
 })
 export class DeviceHa {
 
+  totalRecords: number = 0;
+  tableColumns: string[] = ['serial', 'deviceName', 'status', 'interval', 'syncConfig', 'logging', 'logLevel', 'floatingMac', 'ffoLink'];
+  dataSource: MatTableDataSource<any> = new MatTableDataSource();
+  @ViewChild(MatPaginator) paginator!: MatPaginator;
+  dialog = inject(MatDialog);
+  dialogConfig = new MatDialogConfig();
+
+  constructor(
+    private _device: DeviceService,
+    private _cdRef: ChangeDetectorRef,
+    private _notification: NotificationService,
+    private _router: Router
+  ) {
+    this.getDeviceHAList();
+  }
+
+  getDeviceHAList() {
+    this.dataSource.data = [];
+    this._device.getDeviceHAList()
+      .pipe(take(1))
+      .subscribe({
+        next: (resp: any) => {
+          if (resp && resp?.device_ha) {
+            this.dataSource.data = resp.device_ha;
+            this.totalRecords = this.dataSource.data.length;
+            this.dataSource.paginator = this.paginator;
+          }
+          this._cdRef.detectChanges();
+        },
+        error: (error: any) => {
+          this._notification.showError(error.message);
+          this._cdRef.detectChanges();
+        }
+      });
+  }
+
+  goToDetails(device: any) {
+    this._router.navigate(['/device/ha/details', device?.device_name], {
+      state: {}
+    });
+  }
 }
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ssl/device-ssl.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ssl/device-ssl.html	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ssl/device-ssl.html	(working copy)
@@ -1 +1,65 @@
-<p>device-ssl works!</p>
+<mat-card class="page-card-1" appearance="filled">
+  <mat-card-header>
+    <div>
+      <button mat-raised-button (click)="checkCertificateExpiry()">Check Certificate Expiry</button>
+    </div>
+  </mat-card-header>
+  <mat-card-content>
+    <span>
+      SSL certificate display depends on APV version. For APV 10.3 version, the required version is 10.3.0.2 and later. For APV 10.3.1 version, the required version is 10.3.1.2 and later. For APV 8.6.1 version, the required version is 8.6.1.89 and later. Therefore, if you want to use the related functions of the SSL certificate, please update the corresponding APV version.
+    </span>
+  </mat-card-content>
+</mat-card>
+<div class="table-container">
+  <table mat-table [dataSource]="dataSource" class="mat-elevation-z1">
+    <ng-container matColumnDef="serial">
+      <th mat-header-cell *matHeaderCellDef> No.</th>
+      <td mat-cell *matCellDef="let element; let i = index;"> {{ i | globalSerial:paginator }}</td>
+    </ng-container>
+    <ng-container matColumnDef="serviceName">
+      <th mat-header-cell *matHeaderCellDef> Service Name</th>
+      <td mat-cell *matCellDef="let element">
+        <a class="details-page-link" (click)="goToDetails(element)">{{ element?.service_name }}</a>
+      </td>
+    </ng-container>
+    <ng-container matColumnDef="deviceName">
+      <th mat-header-cell *matHeaderCellDef> Device Name</th>
+      <td mat-cell *matCellDef="let element">{{ element?.device }}</td>
+    </ng-container>
+    <ng-container matColumnDef="deviceGroup">
+      <th mat-header-cell *matHeaderCellDef> Device Group</th>
+      <td mat-cell *matCellDef="let element">{{ element?.device_group }}</td>
+    </ng-container>
+    <ng-container matColumnDef="serviceType">
+      <th mat-header-cell *matHeaderCellDef> Service Type</th>
+      <td mat-cell *matCellDef="let element"> {{ element?.protocol }}</td>
+    </ng-container>
+    <ng-container matColumnDef="sslHostName">
+      <th mat-header-cell *matHeaderCellDef> SSL Hostname</th>
+      <td mat-cell *matCellDef="let element">{{ element?.host_name }}</td>
+    </ng-container>
+    <ng-container matColumnDef="status">
+      <th mat-header-cell *matHeaderCellDef> SSL Host Status</th>
+      <td mat-cell *matCellDef="let element">{{ element?.status }}</td>
+    </ng-container>
+    <ng-container matColumnDef="action">
+      <th mat-header-cell *matHeaderCellDef> Action</th>
+      <td mat-cell *matCellDef="let element">
+        <div class="row-action a-link">
+          <fa-icon [icon]="['far', 'edit']" size="lg" matTooltip="Edit"
+                   (click)="editSSL(element)"></fa-icon>
+        </div>
+      </td>
+    </ng-container>
+    <tr mat-header-row *matHeaderRowDef="tableColumns"></tr>
+    <tr mat-row *matRowDef="let row; columns: tableColumns;"></tr>
+    <tr class="mat-row table-no-data" *matNoDataRow>
+      <td class="mat-cell" colspan="10">No results found.</td>
+    </tr>
+  </table>
+  <mat-paginator
+    [pageSizeOptions]="[10, 15, 20, 25]"
+    [length]="totalRecords"
+    showFirstLastButtons
+  ></mat-paginator>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ssl/device-ssl.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ssl/device-ssl.scss	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ssl/device-ssl.scss	(working copy)
@@ -0,0 +1,21 @@
+.page-card-1 {
+  width: 100%;
+  border-radius: 0;
+  background-color: inherit;
+  font-size: 14px !important;
+
+  mat-card-header {
+    color: #1170cf;
+  }
+}
+
+mat-card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 4px 10px;
+}
+
+mat-card-title {
+  font-size: medium;
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ssl/device-ssl.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ssl/device-ssl.ts	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ssl/device-ssl.ts	(working copy)
@@ -1,11 +1,266 @@
-import { Component } from '@angular/core';
+import {ChangeDetectorRef, Component, inject, OnDestroy, OnInit, ViewChild} from '@angular/core';
+import {MatTableDataSource} from "@angular/material/table";
+import {SharedModule} from '../../shared/shared-module';
+import {MatPaginator} from '@angular/material/paginator';
+import {MAT_DIALOG_DATA, MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material/dialog';
+import {ActivatedRoute, Router} from '@angular/router';
+import {NotificationService} from '../../services/notification';
+import {Confirmation} from '../../services/confirmation';
+import {DeviceService} from '../../services/device-service';
+import {GlobalSerialPipe} from '../../pipes/global-serial-pipe';
+import {take} from 'rxjs/operators';
+import {Storage} from '../../services/storage';
+import {FormBuilder, FormGroup, Validators} from '@angular/forms';
+import {VpnService} from '../../services/vpn-service';
+import {SyncACLResourceGroupDialog} from '../sub-components/vpn-acl-resource-groups/vpn-acl-resource-groups';
 
 @Component({
   selector: 'app-device-ssl',
-  imports: [],
+  imports: [SharedModule, GlobalSerialPipe],
   templateUrl: './device-ssl.html',
   styleUrl: './device-ssl.scss'
 })
-export class DeviceSsl {
+export class DeviceSsl implements OnInit {
 
+  deviceName: string = '';
+  serviceName: string = '';
+  totalRecords: number = 0;
+  tableColumns: string[] = ['serial', 'serviceName', 'deviceName', 'deviceGroup', 'serviceType', 'sslHostName', 'status', 'action'];
+  dataSource: MatTableDataSource<any> = new MatTableDataSource();
+  @ViewChild(MatPaginator) paginator!: MatPaginator;
+  dialog = inject(MatDialog);
+  dialogConfig = new MatDialogConfig();
+  devices: any = [];
+  device_type_info: any = {};
+
+  constructor(
+    private _device: DeviceService,
+    private _route: ActivatedRoute,
+    private _cdRef: ChangeDetectorRef,
+    private _notification: NotificationService,
+    private _confirmation: Confirmation,
+    private _router: Router,
+    private _storage: Storage
+  ) {
+
+  }
+
+  ngOnInit() {
+    setTimeout(() => {
+      this.getDeviceGroups();
+      this.device_type_info = JSON.parse(<string>this._storage.getItem('deviceType'))
+      this.dataSource.paginator = this.paginator;
+    })
+  }
+
+  getDeviceGroups(): void {
+    this.devices = [];
+    // ToDo: Update with actual RoleId
+    let roleId = "0"
+    let rawPayload = new FormData();
+    rawPayload.set('action', 'FilterRoleDeviceGroups');
+    rawPayload.set('options', JSON.stringify({"role_id": roleId}));
+
+    let type_dict: any = {
+      "slb virtual tcps ": "TCPS",
+      "slb virtual https ": "HTTPS",
+      "slb virtual ftps ": "FTPS"
+    }
+    let ssl_result: any = [];
+    this.dataSource.data = [];
+
+    this._device.getDeviceGroups(rawPayload)
+      .pipe(take(1))
+      .subscribe({
+        next: (result: any) => {
+          if (result && result.length > 1) {
+            if (result[1] && 'result' in result[1]) {
+              let groups = result[1].result;
+              groups.forEach((group: any) => {
+                group?.device_list.forEach((device: any) => {
+                  this.devices.push(device);
+                })
+              })
+              this.devices.forEach((_device: any) => {
+                  if (this.device_type_info?.ADC_TYPE_LIST.includes(_device.type.toLowerCase())) {
+                    this._device.executeCLICommand(_device?.id, {cmd: "show slb virtual all"})
+                      .pipe(take(1))
+                      .subscribe({
+                        next: (result: any) => {
+                          if (result && result?.contents) {
+                            let conf_list = result?.contents.split('\n');
+                            conf_list.forEach((item: any) => {
+                              let _tmp = item.split("\"");
+                              if (_tmp[0] in type_dict) {
+                                ssl_result.push({
+                                  service_name: _tmp[1],
+                                  protocol: type_dict[_tmp[0]],
+                                  device: _device?.name,
+                                  device_group: _device?.device_group,
+                                  host_name: "",
+                                  status: "",
+                                })
+                              }
+                            })
+                          }
+                          let status_result: any = {}
+                          if (this.device_type_info?.ADC_TYPE_LIST.includes(_device.type.toLowerCase())) {
+                            this._device.executeCLICommand(_device?.id, {cmd: "show ssl host"})
+                              .pipe(take(1))
+                              .subscribe({
+                                next: (resp: any) => {
+                                  if (resp && resp?.contents) {
+                                    let conf_list = resp.contents.split("\n");
+                                    conf_list.forEach((item: any) => {
+                                      let _tmp = item.split("\"");
+                                      if (_tmp[0] == "ssl host virtual ") {
+                                        ssl_result.forEach((_item: any) => {
+                                          if (_item.device === _device.name && _item.service_name === _tmp[3]) {
+                                            _item.status = status_result[_tmp[1]] || '';
+                                            _item.host_name = _tmp[1]
+                                          }
+                                        })
+                                      }
+                                    })
+                                    this._device.executeCLICommand(_device?.id, {cmd: "show ssl status host"})
+                                      .pipe(take(1))
+                                      .subscribe({
+                                        next: (res: any) => {
+                                          if (res && res?.contents) {
+                                            let conf_list1 = res.contents.split("\n");
+                                            conf_list1.forEach((item1: any) => {
+                                              let tmp1: any = item1.split("\"");
+                                              let status_str = "";
+                                              if (tmp1[0] == "virtual host ") {
+                                                if (tmp1[2] == " is inactive") {
+                                                  status_str = "Inactive";
+                                                } else {
+                                                  status_str = "Active";
+                                                }
+                                                ssl_result.forEach((_item: any) => {
+                                                  if (_item?.device === _device?.name && _item?.host_name === tmp1[1]) {
+                                                    _item.status = status_str;
+                                                  }
+                                                });
+                                              }
+                                            })
+                                          }
+                                        },
+                                        error: (error: any) => {
+                                          this._notification.showError(error?.message);
+                                        }
+                                      });
+                                  }
+                                  this.dataSource.data = ssl_result
+                                  this.dataSource.paginator = this.paginator;
+                                  this.totalRecords = this.dataSource.data.length;
+                                },
+                                error: (error: any) => {
+                                  this._notification.showError(error?.message);
+                                }
+                              });
+                          }
+                        },
+                        error: (error: any) => {
+                          this._notification.showError(error?.message);
+                        }
+                      });
+                    console.log(ssl_result)
+                  }
+                }
+              )
+            }
+          }
+        }
+        ,
+        error: (error: { message: string; }) => {
+          this._notification.showError(error.message);
+        }
+      })
+  }
+
+  editSSL(_vs: any) {
+    this.dialogConfig.data = {
+      service: _vs
+    };
+    this.dialogConfig.disableClose = true;
+    const dialogRef = this.dialog.open(EditDeviceSSLDialog, this.dialogConfig);
+    dialogRef.afterClosed().subscribe((isAdded: boolean) => {
+      if (isAdded) {
+        this.getDeviceGroups();
+      }
+    })
+  }
+
+  checkCertificateExpiry() {
+  }
+
+  goToDetails(_ssl: any) {
+    this._router.navigate(['/device/ssl/details', _ssl.device, _ssl.service_name, _ssl.host_name], {
+      state: {}
+    });
+  }
 }
+
+@Component({
+  selector: 'edit-device-ssl',
+  templateUrl: './edit-device-ssl.html',
+  imports: [SharedModule]
+})
+export class EditDeviceSSLDialog implements OnInit {
+
+  readonly data = inject(MAT_DIALOG_DATA);
+  readonly dialogRef = inject(MatDialogRef<EditDeviceSSLDialog>);
+
+  configForm!: FormGroup;
+
+  constructor(
+    private _vpn: VpnService,
+    private _device: DeviceService,
+    private _notification: NotificationService,
+    private _fB: FormBuilder,
+    private _cdRef: ChangeDetectorRef,
+  ) {
+  }
+
+  ngOnInit(): void {
+    this.configForm = this._fB.group({
+      deviceName: [{value: '', disabled: true}, Validators.required],
+      serviceName: [{value: '', disabled: true}, Validators.required],
+      type: [{value: '', disabled: true}, Validators.required],
+      hostName: [{value: '', disabled: true}, Validators.required],
+      enableSSL: [false, Validators.required],
+    });
+    this.configForm.patchValue({
+      deviceName: this.data?.service?.device,
+      serviceName: this.data?.service?.service_name,
+      type: this.data?.service?.protocol,
+      hostName: this.data?.service?.host_name,
+      enableSSL: this.data?.service?.status === 'Active',
+    })
+  }
+
+  onSubmit(): void {
+    if (this.configForm.invalid) {
+      console.log(this.configForm.value);
+      this.configForm.markAllAsTouched();
+      return;
+    }
+    let _payload: any = {
+      host_status: this.configForm.value.enableSSL,
+    }
+    this._device.updateSSLVHost(this.data?.service?.device, _payload)
+      .pipe(take(1)).subscribe({
+      next: (resp: any) => {
+        this.dialogRef.close(true);
+      },
+      error: (error: any) => {
+      this._notification.showError(error?.message);
+      }
+    })
+  }
+
+  onCancel(): void {
+    this.dialogRef.close(false);
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ssl/edit-device-ssl.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ssl/edit-device-ssl.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/device-ssl/edit-device-ssl.html	(working copy)
@@ -0,0 +1,74 @@
+<h2 mat-dialog-title>Edit Device SSL Service</h2>
+<mat-dialog-content>
+  <form
+    (ngSubmit)="onSubmit()"
+    [formGroup]="configForm"
+    class="login-form">
+    <div class="form-field-wrapper">
+      <label for="deviceName" class="form-label">Device name</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <input
+          id="deviceName"
+          formControlName="deviceName"
+          matInput
+          placeholder="Device name"
+          type="text"
+        />
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="serviceName" class="form-label">Service name</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <input
+          id="serviceName"
+          formControlName="serviceName"
+          matInput
+          placeholder="Service name"
+          type="text"
+        />
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="type" class="form-label">Type</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <input
+          id="type"
+          formControlName="type"
+          matInput
+          placeholder="Type"
+          type="text"
+        />
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="hostName" class="form-label">Hostname</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <input
+          id="hostName"
+          formControlName="hostName"
+          matInput
+          placeholder="Hostname"
+          type="text"
+        />
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="enableSSL" class="form-label">Enable</label>
+      <mat-slide-toggle formControlName="enableSSL"></mat-slide-toggle>
+    </div>
+  </form>
+</mat-dialog-content>
+<mat-dialog-actions>
+  <button
+    mat-button
+    color="basic"
+    (click)="onCancel()">
+    Cancel
+  </button>
+  <button
+    mat-raised-button
+    color="primary"
+    (click)="onSubmit()">
+    Submit
+  </button>
+</mat-dialog-actions>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-details/device-details.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-details/device-details.scss	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-details/device-details.scss	(working copy)
@@ -28,9 +28,7 @@
 
 .device-config {
   padding: 20px;
-  //background-color: #f9f9f9;
   border-radius: 8px;
-  //box-shadow: 0 2px 5px rgba(0,0,0,0.1);
   max-width: 90vw;
   margin: 20px auto;
 }
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-details/device-details.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-details/device-details.ts	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-details/device-details.ts	(working copy)
@@ -75,7 +75,7 @@
         }
       }
     }
-    console.log(this.deviceData);
+
     Object.keys(this.deviceData).forEach(key => {
       const value = this.deviceData[key as keyof typeof this.deviceData];
       if (['license_date', 'license_feature', 'license_key', 'license_limit'].includes(key)) {
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-base-settings/device-ha-base-settings.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-base-settings/device-ha-base-settings.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-base-settings/device-ha-base-settings.html	(working copy)
@@ -0,0 +1,66 @@
+<form
+  (ngSubmit)="onSubmit()"
+  [formGroup]="configForm"
+  class="common-form"
+>
+  <div class="form-field-wrapper">
+    <label for="enable" class="form-label">HA Status</label>
+    <mat-slide-toggle formControlName="enable"></mat-slide-toggle>
+  </div>
+  <div class="form-field-wrapper">
+    <label for="arp" class="form-label">ARP Interval</label>
+    <mat-form-field appearance="outline" subscriptSizing="dynamic">
+      <input
+        id="arp"
+        formControlName="arp"
+        matInput
+        placeholder="ARP Interval"
+        type="number"
+      />
+    </mat-form-field>
+  </div>
+  <div class="form-field-wrapper">
+    <label for="sync_bootup" class="form-label">Bootup Sync Config</label>
+    <mat-slide-toggle formControlName="sync_bootup"></mat-slide-toggle>
+  </div>
+  <div class="form-field-wrapper">
+    <label for="sync_runtime" class="form-label">Runtime Sync Config</label>
+    <mat-slide-toggle formControlName="sync_runtime"></mat-slide-toggle>
+  </div>
+  <div class="form-field-wrapper">
+    <label for="log_enable" class="form-label">HA Logging</label>
+    <mat-slide-toggle formControlName="log_enable"></mat-slide-toggle>
+  </div>
+  <div class="form-field-wrapper">
+    <label for="log_level" class="form-label">HA Log Level</label>
+    <mat-form-field appearance="outline" subscriptSizing="dynamic">
+      <input
+        id="log_level"
+        formControlName="log_level"
+        matInput
+        placeholder="HA Log Level"
+        type="text"
+      />
+    </mat-form-field>
+  </div>
+  <div class="form-field-wrapper">
+    <label for="floatmac_enable" class="form-label">HA Floating MAC</label>
+    <mat-slide-toggle formControlName="floatmac_enable"></mat-slide-toggle>
+  </div>
+  <div class="form-field-wrapper">
+    <label for="link_ffo" class="form-label">HA FFO Link</label>
+    <mat-slide-toggle formControlName="link_ffo"></mat-slide-toggle>
+  </div>
+  <div class="form-field-wrapper">
+    <label for="link_network" class="form-label">HA Network Link</label>
+    <mat-slide-toggle formControlName="link_network"></mat-slide-toggle>
+  </div>
+  <div class="form-field-wrapper">
+    <label for="ha_consistency" class="form-label">HA Consistency Check</label>
+    <mat-slide-toggle formControlName="ha_consistency"></mat-slide-toggle>
+  </div>
+  <div class="form-field-wrapper">
+    <label for="ha_checkpeer" class="form-label">HA Peer Check</label>
+    <mat-slide-toggle formControlName="ha_checkpeer"></mat-slide-toggle>
+  </div>
+</form>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-base-settings/device-ha-base-settings.scss	(added)
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-base-settings/device-ha-base-settings.scss	(revision 0)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-base-settings/device-ha-base-settings.scss	(revision 0)
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-base-settings/device-ha-base-settings.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-base-settings/device-ha-base-settings.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-base-settings/device-ha-base-settings.spec.ts	(working copy)
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DeviceHaBaseSettings } from './device-ha-base-settings';
+
+describe('DeviceHaBaseSettings', () => {
+  let component: DeviceHaBaseSettings;
+  let fixture: ComponentFixture<DeviceHaBaseSettings>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [DeviceHaBaseSettings]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(DeviceHaBaseSettings);
+    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/sub-components/device-ha-base-settings/device-ha-base-settings.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-base-settings/device-ha-base-settings.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-base-settings/device-ha-base-settings.ts	(working copy)
@@ -0,0 +1,69 @@
+import {ChangeDetectorRef, Component, OnInit} from '@angular/core';
+import {FormBuilder, FormGroup} from '@angular/forms';
+import {ActivatedRoute} from '@angular/router';
+import {DeviceService} from '../../../services/device-service';
+import {take} from 'rxjs/operators';
+import {NotificationService} from '../../../services/notification';
+import {SharedModule} from '../../../shared/shared-module';
+
+@Component({
+  selector: 'app-device-ha-base-settings',
+  imports: [SharedModule],
+  templateUrl: './device-ha-base-settings.html',
+  styleUrl: './device-ha-base-settings.scss'
+})
+export class DeviceHaBaseSettings implements OnInit {
+
+  deviceName: string | null = null;
+  configForm!: FormGroup;
+
+  constructor(
+    private _fB: FormBuilder,
+    private _cdRef: ChangeDetectorRef,
+    private _route: ActivatedRoute,
+    private _device: DeviceService,
+    private _notification: NotificationService
+  ) {
+    this.deviceName = this._route.snapshot.paramMap.get('deviceName');
+  }
+
+  ngOnInit() {
+    this.configForm = this._fB.group({
+      enable: [{value: false, disabled: true}],
+      arp: [{value: '', disabled: true}],
+      sync_bootup: [{value: false, disabled: true}],
+      sync_runtime: [{value: false, disabled: true}],
+      log_enable: [{value: false, disabled: true}],
+      log_level: [{value: '', disabled: true}],
+      floatmac_enable: [{value: false, disabled: true}],
+      link_ffo: [{value: false, disabled: true}],
+      link_network: [{value: false, disabled: true}],
+      ha_consistency: [{value: false, disabled: true}],
+      ha_checkpeer: [{value: false, disabled: true}],
+    })
+    setTimeout(() => {
+      this.getDeviceHAConfiguration();
+    })
+  }
+
+  getDeviceHAConfiguration() {
+    let payload = new FormData();
+    payload.set('device_name', JSON.stringify(this.deviceName))
+    this._device.getDeviceHAConfigByName(this.deviceName, payload)
+      .pipe(take(1)).subscribe({
+      next: (result: any) => {
+        if (result && result.device_ha) {
+          this.configForm.patchValue(result.device_ha);
+        }
+        this._cdRef.detectChanges();
+      },
+      error: error => {
+        this._notification.showError(`Error: ${error?.message}`);
+        this._cdRef.detectChanges();
+      }
+    })
+  }
+
+  onSubmit() {
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-group.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-group.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-group.html	(working copy)
@@ -0,0 +1,49 @@
+<mat-card class="page-card-1" appearance="filled">
+  <mat-card-header>
+    <div>
+      <button mat-raised-button (click)="switchHAGroup()">Switch</button>
+    </div>
+  </mat-card-header>
+</mat-card>
+<div class="table-container">
+  <table mat-table [dataSource]="dataSource" class="mat-elevation-z1">
+    <ng-container matColumnDef="serial">
+      <th mat-header-cell *matHeaderCellDef> No.</th>
+      <td mat-cell *matCellDef="let element; let i = index;"> {{ i | globalSerial:paginator }}</td>
+    </ng-container>
+    <ng-container matColumnDef="id">
+      <th mat-header-cell *matHeaderCellDef> Group Id</th>
+      <td mat-cell *matCellDef="let element">{{ element?.id }}</td>
+    </ng-container>
+    <ng-container matColumnDef="group">
+      <th mat-header-cell *matHeaderCellDef>HA Group</th>
+      <td mat-cell *matCellDef="let element">
+        @if (element?.enable) {
+          <fa-icon [icon]="['far', 'check-circle']" class="success-icon"></fa-icon>
+        } @else {
+          <fa-icon [icon]="['far', 'xmark-circle']" class="delete-icon"></fa-icon>
+        }
+      </td>
+    </ng-container>
+    <ng-container matColumnDef="mode">
+      <th mat-header-cell *matHeaderCellDef>Preemption Mode</th>
+      <td mat-cell *matCellDef="let element">
+        @if (element?.preempt) {
+          <fa-icon [icon]="['far', 'check-circle']" class="success-icon"></fa-icon>
+        } @else {
+          <fa-icon [icon]="['far', 'xmark-circle']" class="delete-icon"></fa-icon>
+        }
+      </td>
+    </ng-container>
+    <tr mat-header-row *matHeaderRowDef="tableColumns"></tr>
+    <tr mat-row *matRowDef="let row; columns: tableColumns;"></tr>
+    <tr class="mat-row table-no-data" *matNoDataRow>
+      <td class="mat-cell" colspan="10">No results found.</td>
+    </tr>
+  </table>
+  <mat-paginator
+    [pageSizeOptions]="[10, 15, 20, 25]"
+    [length]="totalRecords"
+    showFirstLastButtons
+  ></mat-paginator>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-group.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-group.scss	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-group.scss	(working copy)
@@ -0,0 +1,21 @@
+.page-card-1 {
+  width: 100%;
+  border-radius: 0;
+  background-color: inherit;
+  font-size: 14px !important;
+
+  mat-card-header {
+    color: #1170cf;
+  }
+}
+
+mat-card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 4px 10px;
+}
+
+mat-card-title {
+  font-size: medium;
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-group.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-group.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-group.spec.ts	(working copy)
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DeviceHaGroup } from './device-ha-group';
+
+describe('DeviceHaGroup', () => {
+  let component: DeviceHaGroup;
+  let fixture: ComponentFixture<DeviceHaGroup>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [DeviceHaGroup]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(DeviceHaGroup);
+    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/sub-components/device-ha-group/device-ha-group.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-group.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-group.ts	(working copy)
@@ -0,0 +1,165 @@
+import {ChangeDetectorRef, Component, inject, OnInit, ViewChild} from '@angular/core';
+import {MatTableDataSource} from '@angular/material/table';
+import {MatPaginator} from '@angular/material/paginator';
+import {ActivatedRoute} from '@angular/router';
+import {DeviceService} from '../../../services/device-service';
+import {NotificationService} from '../../../services/notification';
+import {take} from 'rxjs/operators';
+import {SharedModule} from '../../../shared/shared-module';
+import {GlobalSerialPipe} from '../../../pipes/global-serial-pipe';
+import {MAT_DIALOG_DATA, MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material/dialog';
+import {FormBuilder, FormGroup, Validators} from '@angular/forms';
+import {ImportDeviceSSLCertificateDialog} from '../device-ssl-certificates/device-ssl-certificates';
+
+@Component({
+  selector: 'app-device-ha-group',
+  imports: [SharedModule, GlobalSerialPipe],
+  templateUrl: './device-ha-group.html',
+  styleUrl: './device-ha-group.scss'
+})
+export class DeviceHaGroup implements OnInit {
+
+  deviceName: string | null = null;
+  totalRecords: number = 0;
+  tableColumns: string[] = ['serial', 'id', 'group', 'mode',];
+  dataSource: MatTableDataSource<any> = new MatTableDataSource();
+@ViewChild(MatPaginator) paginator!: MatPaginator;
+
+  constructor(
+    private _cdRef: ChangeDetectorRef,
+    private _route: ActivatedRoute,
+    private _device: DeviceService,
+    private _notification: NotificationService
+) {
+    this.deviceName = this._route.snapshot.paramMap.get('deviceName');
+  }
+
+  ngOnInit() {
+    this.dataSource.paginator = this.paginator;
+    setTimeout(() => {
+      this.getDeviceHAGroups();
+      this.getDeviceHAUnits();
+    })
+  }
+
+  getDeviceHAGroups() {
+    this.dataSource.data = [];
+    let payload = new FormData();
+    payload.set('device_name', JSON.stringify(this.deviceName))
+    this._device.getDeviceHAGroupsByName(this.deviceName, payload)
+      .pipe(take(1)).subscribe({
+      next: (result: any) => {
+        if (result && result.data) {
+          console.log(result.data);
+          this.dataSource.data = result.data;
+          this.totalRecords = this.dataSource.data.length;
+          this.dataSource.paginator = this.paginator;
+        }
+        this._cdRef.detectChanges();
+      },
+      error: error => {
+        this._notification.showError(`Error: ${error?.message}`);
+        this._cdRef.detectChanges();
+      }
+    })
+  }
+
+  deviceHAUnits: any = [];
+  getDeviceHAUnits() {
+    this.deviceHAUnits = [];
+    let payload = new FormData();
+    payload.set('device_name', JSON.stringify(this.deviceName))
+    this._device.getDeviceHAUnitsByName(this.deviceName, payload)
+      .pipe(take(1)).subscribe({
+      next: (result: any) => {
+        if (result && result.data) {
+          this.deviceHAUnits = result.data;
+        }
+        this._cdRef.detectChanges();
+      },
+      error: error => {
+        this._notification.showError(`Error: ${error?.message}`);
+        this._cdRef.detectChanges();
+      }
+    })
+  }
+  dialog = inject(MatDialog);
+  dialogConfig = new MatDialogConfig();
+
+  switchHAGroup() {
+    this.dialogConfig.data = {
+      deviceName: this.deviceName,
+      deviceHAUnits: this.deviceHAUnits,
+    };
+    const dialogRef = this.dialog.open(SwitchHAGroupDialog, this.dialogConfig);
+    dialogRef.afterClosed().subscribe(isAdded => {
+      if (isAdded) {
+        this.getDeviceHAGroups();
+      }
+    })
+  }
+}
+@Component({
+  selector: 'device-ha-switch-group',
+  templateUrl: './device-ha-switch-group.html',
+  imports: [SharedModule]
+})
+export class SwitchHAGroupDialog implements OnInit {
+
+  readonly data = inject(MAT_DIALOG_DATA);
+  readonly dialogRef = inject(MatDialogRef<SwitchHAGroupDialog>);
+  configForm!: FormGroup;
+
+  domains: any = [];
+
+  constructor(
+    private _fB: FormBuilder,
+    private _device: DeviceService,
+    private _cdRef: ChangeDetectorRef,
+    private _notification: NotificationService,
+  ) {
+
+  }
+
+  ngOnInit() {
+    this.configForm = this._fB.group({
+      unitName: ['', Validators.required],
+      groupId: [0, Validators.required],
+    })
+  }
+
+  onSubmit() {
+    if (this.configForm.invalid) {
+      console.log(this.configForm.value);
+      this.configForm.markAllAsTouched();
+      return;
+    }
+    let payload: any = new FormData();
+    payload.set('post_data', JSON.stringify({
+      device_name: this.data?.deviceName,
+      unit_name: this.configForm.value?.unitName,
+      group_id: this.configForm.value?.groupId,
+    }));
+    this._device.switchHAGroup(payload)
+      .pipe(take(1))
+      .subscribe({
+        next: (resp: any) => {
+          if (resp && resp?.state) {
+            this.dialogRef.close(true);
+            this._notification.showSuccess(`The SSL certificate backup has been created successfully.`);
+          } else {
+            this._notification.showError(resp?.msg);
+          }
+          this._cdRef.detectChanges();
+        },
+        error: (error: any) => {
+          this._notification.showError(error.message);
+          this._cdRef.detectChanges();
+        }
+      });
+  }
+
+  onCancel() {
+    this.dialogRef.close(false);
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-switch-group.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-switch-group.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-group/device-ha-switch-group.html	(working copy)
@@ -0,0 +1,66 @@
+<h2 mat-dialog-title>Switch Group - Forcibly</h2>
+<p class="common-form">
+  This function is used to switch the specified floating IP group to the specified HA unit. If the value 1024 is set for
+  Group ID, all floating IP groups in the active state will be switched.
+</p>
+<mat-dialog-content>
+  <form
+    (ngSubmit)="onSubmit()"
+    [formGroup]="configForm"
+  >
+    <div class="form-field-wrapper">
+      <label for="unitName" class="form-label">HA Unit Name</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <mat-select formControlName="unitName">
+          @for (_unit of data?.deviceHAUnits; track _unit) {
+            <mat-option [value]="_unit?.name">{{ _unit?.name }}</mat-option>
+          }
+        </mat-select>
+        @if (configForm.get('unitName')?.invalid && configForm.get('unitName')?.touched) {
+          <mat-error>
+            @if (configForm.get('unitName')?.errors?.['required']) {
+              HA unit is required.
+            } @else {
+              Invalid HA unit name format.
+            }
+          </mat-error>
+        }
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="groupId" class="form-label">Group Id</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <input
+          id="groupId"
+          formControlName="groupId"
+          matInput
+          placeholder="Group Id"
+          type="number"
+        />
+        @if (configForm.get('groupId')?.invalid && configForm.get('groupId')?.touched) {
+          <mat-error>
+            @if (configForm.get('groupId')?.errors?.['required']) {
+              Group id is required.
+            } @else {
+              Invalid group id format.
+            }
+          </mat-error>
+        }
+      </mat-form-field>
+    </div>
+  </form>
+</mat-dialog-content>
+<mat-dialog-actions>
+  <button
+    mat-button
+    color="basic"
+    (click)="onCancel()">
+    Cancel
+  </button>
+  <button
+    mat-raised-button
+    color="primary"
+    (click)="onSubmit()">
+    Submit
+  </button>
+</mat-dialog-actions>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-overview/device-ha-overview.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-overview/device-ha-overview.html	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-overview/device-ha-overview.html	(working copy)
@@ -1 +1,35 @@
-<p>device-ha-overview works!</p>
+<mat-card class="page-card-1" appearance="filled">
+  <mat-card-header>
+    <mat-card-title>
+      <a class="back-to-main-page" (click)="managedHADevices()">
+        <fa-icon [icon]="['far', 'circle-left']"></fa-icon>
+        Managed HA Devices - {{ deviceName }}
+      </a>
+    </mat-card-title>
+  </mat-card-header>
+</mat-card>
+<div class="tab-container">
+  <mat-tab-group animationDuration="0ms" [selectedIndex]="selectedTabIndex" (selectedTabChange)="onTabChange($event)">
+    <mat-tab label="Base Settings">
+      <ng-template matTabContent>
+        <div class="tab-content">
+          <app-device-ha-base-settings/>
+        </div>
+      </ng-template>
+    </mat-tab>
+    <mat-tab label="HA Unit">
+      <ng-template matTabContent>
+        <div class="tab-content">
+          <app-device-ha-unit/>
+        </div>
+      </ng-template>
+    </mat-tab>
+    <mat-tab label="HA Group">
+      <ng-template matTabContent>
+        <div class="tab-content">
+          <app-device-ha-group/>
+        </div>
+      </ng-template>
+    </mat-tab>
+  </mat-tab-group>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-overview/device-ha-overview.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-overview/device-ha-overview.scss	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-overview/device-ha-overview.scss	(working copy)
@@ -0,0 +1,21 @@
+.page-card-1 {
+  width: 100%;
+  border-radius: 0;
+  background-color: inherit;
+  font-size: 14px !important;
+
+  mat-card-header {
+    color: #1170cf;
+  }
+}
+
+mat-card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 4px 10px;
+}
+
+mat-card-title {
+  font-size: medium;
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-overview/device-ha-overview.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-overview/device-ha-overview.ts	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-overview/device-ha-overview.ts	(working copy)
@@ -1,11 +1,72 @@
-import { Component } from '@angular/core';
+import {Component, OnInit} from '@angular/core';
+import {SharedModule} from '../../../shared/shared-module';
+import {ActivatedRoute, Router} from '@angular/router';
+import {MatTabChangeEvent} from '@angular/material/tabs';
+import {DeviceHaBaseSettings} from '../device-ha-base-settings/device-ha-base-settings';
+import {DeviceHaUnit} from '../device-ha-unit/device-ha-unit';
+import {DeviceHaGroup} from '../device-ha-group/device-ha-group';
 
 @Component({
   selector: 'app-device-ha-overview',
-  imports: [],
+  imports: [
+    SharedModule,
+    DeviceHaBaseSettings,
+    DeviceHaUnit,
+    DeviceHaGroup,
+
+  ],
   templateUrl: './device-ha-overview.html',
   styleUrl: './device-ha-overview.scss'
 })
-export class DeviceHaOverview {
+export class DeviceHaOverview implements OnInit {
 
+  selectedTabIndex: number = 0;
+  private tabNames: string[] = [
+    'Base Settings',
+    'HA Unit',
+    'HA Group',
+  ];
+
+  deviceName: string | null = null;
+
+  constructor(private route: ActivatedRoute, private router: Router) {
+    this.deviceName = this.route.snapshot.paramMap.get('deviceName');
+  }
+
+  managedHADevices(): void {
+    this.router.navigate(['/device/ha']);
+  }
+
+  ngOnInit(): void {
+    this.route.queryParams.subscribe(params => {
+      const tabParam = params['tab'];
+      if (tabParam) {
+        const index = this.tabNames.indexOf(tabParam);
+        if (index !== -1) {
+          this.selectedTabIndex = index;
+        } else {
+          this.selectedTabIndex = 0;
+        }
+      } else {
+        this.updateQueryParams(this.selectedTabIndex);
+      }
+    });
+  }
+
+  onTabChange(event: MatTabChangeEvent): void {
+    this.selectedTabIndex = event.index;
+    this.updateQueryParams(event.index);
+  }
+
+  private updateQueryParams(tabIndex: number): void {
+    const tabName = this.tabNames[tabIndex];
+    if (tabName) {
+      this.router.navigate([], {
+        relativeTo: this.route,
+        queryParams: {tab: tabName},
+        queryParamsHandling: 'merge'
+      });
+    }
+  }
+
 }
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-unit/device-ha-unit.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-unit/device-ha-unit.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-unit/device-ha-unit.html	(working copy)
@@ -0,0 +1,30 @@
+<div class="table-container">
+  <table mat-table [dataSource]="dataSource" class="mat-elevation-z1">
+    <ng-container matColumnDef="serial">
+      <th mat-header-cell *matHeaderCellDef> No.</th>
+      <td mat-cell *matCellDef="let element; let i = index;"> {{ i | globalSerial:paginator }}</td>
+    </ng-container>
+    <ng-container matColumnDef="name">
+      <th mat-header-cell *matHeaderCellDef> Unit Name</th>
+      <td mat-cell *matCellDef="let element">{{ element?.name }}</td>
+    </ng-container>
+    <ng-container matColumnDef="ip">
+      <th mat-header-cell *matHeaderCellDef> Primary Link IP</th>
+      <td mat-cell *matCellDef="let element">{{ element?.ip }}</td>
+    </ng-container>
+    <ng-container matColumnDef="port">
+      <th mat-header-cell *matHeaderCellDef> Primary Link Port</th>
+      <td mat-cell *matCellDef="let element">{{ element?.port }}</td>
+    </ng-container>
+    <tr mat-header-row *matHeaderRowDef="tableColumns"></tr>
+    <tr mat-row *matRowDef="let row; columns: tableColumns;"></tr>
+    <tr class="mat-row table-no-data" *matNoDataRow>
+      <td class="mat-cell" colspan="10">No results found.</td>
+    </tr>
+  </table>
+  <mat-paginator
+    [pageSizeOptions]="[10, 15, 20, 25]"
+    [length]="totalRecords"
+    showFirstLastButtons
+  ></mat-paginator>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-unit/device-ha-unit.scss	(added)
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-unit/device-ha-unit.scss	(revision 0)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-unit/device-ha-unit.scss	(revision 0)
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-unit/device-ha-unit.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-unit/device-ha-unit.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-unit/device-ha-unit.spec.ts	(working copy)
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DeviceHaUnit } from './device-ha-unit';
+
+describe('DeviceHaUnit', () => {
+  let component: DeviceHaUnit;
+  let fixture: ComponentFixture<DeviceHaUnit>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [DeviceHaUnit]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(DeviceHaUnit);
+    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/sub-components/device-ha-unit/device-ha-unit.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-unit/device-ha-unit.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ha-unit/device-ha-unit.ts	(working copy)
@@ -0,0 +1,61 @@
+import {ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';
+import {take} from 'rxjs/operators';
+import {ActivatedRoute} from '@angular/router';
+import {DeviceService} from '../../../services/device-service';
+import {NotificationService} from '../../../services/notification';
+import {SharedModule} from '../../../shared/shared-module';
+import {GlobalSerialPipe} from '../../../pipes/global-serial-pipe';
+import {MatTableDataSource} from '@angular/material/table';
+import {MatPaginator} from '@angular/material/paginator';
+
+@Component({
+  selector: 'app-device-ha-unit',
+  imports: [SharedModule, GlobalSerialPipe],
+  templateUrl: './device-ha-unit.html',
+  styleUrl: './device-ha-unit.scss'
+})
+export class DeviceHaUnit implements OnInit {
+
+  deviceName: string | null = null;
+  totalRecords: number = 0;
+  tableColumns: string[] = ['serial', 'name', 'ip', 'port',];
+  dataSource: MatTableDataSource<any> = new MatTableDataSource();
+  @ViewChild(MatPaginator) paginator!: MatPaginator;
+
+  constructor(
+    private _cdRef: ChangeDetectorRef,
+    private _route: ActivatedRoute,
+    private _device: DeviceService,
+    private _notification: NotificationService
+  ) {
+    this.deviceName = this._route.snapshot.paramMap.get('deviceName');
+  }
+
+  ngOnInit() {
+    this.dataSource.paginator = this.paginator;
+    setTimeout(() => {
+      this.getDeviceHAUnits();
+    })
+  }
+
+  getDeviceHAUnits() {
+    this.dataSource.data = [];
+    let payload = new FormData();
+    payload.set('device_name', JSON.stringify(this.deviceName))
+    this._device.getDeviceHAUnitsByName(this.deviceName, payload)
+      .pipe(take(1)).subscribe({
+      next: (result: any) => {
+        if (result && result.data) {
+          this.dataSource.data = result.data;
+          this.totalRecords = this.dataSource.data.length;
+          this.dataSource.paginator = this.paginator;
+        }
+        this._cdRef.detectChanges();
+      },
+      error: error => {
+        this._notification.showError(`Error: ${error?.message}`);
+        this._cdRef.detectChanges();
+      }
+    })
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/backup-ssl-certificate.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/backup-ssl-certificate.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/backup-ssl-certificate.html	(working copy)
@@ -0,0 +1,110 @@
+<h2 mat-dialog-title>Backup SSL Certificate</h2>
+<mat-dialog-content>
+  <form
+    (ngSubmit)="onSubmit()"
+    [formGroup]="configForm"
+    class="login-form"
+  >
+    <div class="form-field-wrapper">
+      <label for="filename" class="form-label">Filename *</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <input
+          id="filename"
+          formControlName="filename"
+          matInput
+          placeholder="Filename"
+          type="text"
+        />
+        @if (configForm.get('filename')?.invalid && configForm.get('filename')?.touched) {
+          <mat-error>
+            @if (configForm.get('filename')?.errors?.['required']) {
+              File name is required.
+            } @else {
+              Invalid file name format.
+            }
+          </mat-error>
+        }
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="domain_name" class="form-label">Domain Name</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <mat-select formControlName="domain_name">
+          @for (_domain of domains; track _domain) {
+            <mat-option [value]="_domain?.domain_name">{{ _domain?.domain_name }}</mat-option>
+          }
+        </mat-select>
+        @if (configForm.get('domain_name')?.invalid && configForm.get('domain_name')?.touched) {
+          <mat-error>
+            @if (configForm.get('domain_name')?.errors?.['required']) {
+              Domain name is required.
+            } @else {
+              Invalid domain name format.
+            }
+          </mat-error>
+        }
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="password" class="form-label">Password *</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <input
+          id="password"
+          formControlName="password"
+          matInput
+          placeholder="Password"
+          type="password"
+        />
+        @if (configForm.get('password')?.invalid && configForm.get('password')?.touched) {
+          <mat-error>
+            @if (configForm.get('password')?.errors?.['required']) {
+              Password is required.
+            } @else if (configForm.get('password')?.errors) {
+              Invalid password format.
+            }
+          </mat-error>
+        }
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="confirm_password" class="form-label">Confirm Password *</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <input
+          id="confirm_password"
+          formControlName="confirm_password"
+          matInput
+          placeholder="Password"
+          type="password"
+        />
+        @if (configForm.get('confirm_password')?.invalid && configForm.get('confirm_password')?.touched) {
+          <mat-error>
+            @if (configForm.get('confirm_password')?.errors?.['required']) {
+              Confirm password is required.
+            } @else if (configForm.get('confirm_password')?.errors) {
+              Invalid confirm password format.
+            }
+          </mat-error>
+        }
+      </mat-form-field>
+    </div>
+    @if (configForm.hasError('passwordMismatch')) {
+      <mat-error>
+        The password and confirm password fields do not match.
+      </mat-error>
+    }
+  </form>
+</mat-dialog-content>
+<mat-dialog-actions>
+  <button
+    mat-button
+    color="basic"
+    (click)="onCancel()">
+    Cancel
+  </button>
+  <button
+    mat-raised-button
+    color="primary"
+    (click)="onSubmit()">
+    Submit
+  </button>
+</mat-dialog-actions>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore.html	(working copy)
@@ -0,0 +1,46 @@
+<mat-card class="page-card-1" appearance="filled">
+  <mat-card-header>
+    <div>
+      <button mat-raised-button (click)="addBackupSSLCertificate()">Add</button>
+    </div>
+  </mat-card-header>
+</mat-card>
+<div class="table-container">
+  <table mat-table [dataSource]="dataSource" class="mat-elevation-z1">
+    <ng-container matColumnDef="serial">
+      <th mat-header-cell *matHeaderCellDef> No.</th>
+      <td mat-cell *matCellDef="let element; let i = index;"> {{ i | globalSerial:paginator }}</td>
+    </ng-container>
+    <ng-container matColumnDef="domain">
+      <th mat-header-cell *matHeaderCellDef> Domain Name</th>
+      <td mat-cell *matCellDef="let element">{{ element?.domain_name }}</td>
+    </ng-container>
+    <ng-container matColumnDef="filename">
+      <th mat-header-cell *matHeaderCellDef> Filename</th>
+      <td mat-cell *matCellDef="let element">{{ element?.filename }}</td>
+    </ng-container>
+    <ng-container matColumnDef="action">
+      <th mat-header-cell *matHeaderCellDef> Action</th>
+      <td mat-cell *matCellDef="let element">
+        <div class="row-action a-link">
+          <fa-icon [icon]="['fas', 'gears']" size="lg" matTooltip="Restore Certificate"
+                   (click)="restoreBackupSSLCertificate(element)"></fa-icon>
+<!--          <fa-icon [icon]="['far', 'circle-down']" size="lg" matTooltip="Download Certificate"-->
+<!--                   (click)="downloadBackupSSLCertificate(element)"></fa-icon>-->
+          <fa-icon [icon]="['far', 'trash-can']" size="lg" class="delete-icon" matTooltip="Delete Certificate"
+                   (click)="deleteBackupSSLCertificate(element)"></fa-icon>
+        </div>
+      </td>
+    </ng-container>
+    <tr mat-header-row *matHeaderRowDef="tableColumns"></tr>
+    <tr mat-row *matRowDef="let row; columns: tableColumns;"></tr>
+    <tr class="mat-row table-no-data" *matNoDataRow>
+      <td class="mat-cell" colspan="10">No results found.</td>
+    </tr>
+  </table>
+  <mat-paginator
+    [pageSizeOptions]="[10, 15, 20, 25]"
+    [length]="totalRecords"
+    showFirstLastButtons
+  ></mat-paginator>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore.scss	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore.scss	(working copy)
@@ -0,0 +1,21 @@
+.page-card-1 {
+  width: 100%;
+  border-radius: 0;
+  background-color: inherit;
+  font-size: 14px !important;
+
+  mat-card-header {
+    color: #1170cf;
+  }
+}
+
+mat-card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 4px 10px;
+}
+
+mat-card-title {
+  font-size: medium;
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore.spec.ts	(working copy)
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DeviceSslCertificateBackupRestore } from './device-ssl-certificate-backup-restore';
+
+describe('DeviceSslCertificateBackupRestore', () => {
+  let component: DeviceSslCertificateBackupRestore;
+  let fixture: ComponentFixture<DeviceSslCertificateBackupRestore>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [DeviceSslCertificateBackupRestore]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(DeviceSslCertificateBackupRestore);
+    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/sub-components/device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore.ts	(working copy)
@@ -0,0 +1,310 @@
+import {ChangeDetectorRef, Component, inject, OnInit, ViewChild} from '@angular/core';
+import {MatTableDataSource} from '@angular/material/table';
+import {MatPaginator} from '@angular/material/paginator';
+import {MAT_DIALOG_DATA, MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material/dialog';
+import {DeviceService} from '../../../services/device-service';
+import {ActivatedRoute} from '@angular/router';
+import {NotificationService} from '../../../services/notification';
+import {take} from 'rxjs/operators';
+import {GlobalSerialPipe} from '../../../pipes/global-serial-pipe';
+import {SharedModule} from '../../../shared/shared-module';
+import {FormBuilder, FormGroup, Validators} from '@angular/forms';
+import {CustomValidators} from '../../../utils/custom-validators';
+import {Confirmation} from '../../../services/confirmation';
+
+@Component({
+  selector: 'app-device-ssl-certificate-backup-restore',
+  imports: [
+    SharedModule,
+    GlobalSerialPipe
+  ],
+  templateUrl: './device-ssl-certificate-backup-restore.html',
+  styleUrl: './device-ssl-certificate-backup-restore.scss'
+})
+export class DeviceSslCertificateBackupRestore implements OnInit {
+
+  deviceName: string | null = '';
+  serviceName: string | null = '';
+  hostName: string | null = '';
+  totalRecords: number = 0;
+  tableColumns: string[] = ['serial', 'domain', 'filename', 'action'];
+  dataSource: MatTableDataSource<any> = new MatTableDataSource();
+  @ViewChild(MatPaginator) paginator!: MatPaginator;
+  dialog = inject(MatDialog);
+  dialogConfig = new MatDialogConfig();
+
+  constructor(
+    private _device: DeviceService,
+    private _route: ActivatedRoute,
+    private _notification: NotificationService,
+    private _cdRef: ChangeDetectorRef,
+    private _confirmation: Confirmation,
+  ) {
+  }
+
+  ngOnInit() {
+    this.deviceName = this._route.snapshot.paramMap.get('deviceName');
+    this.serviceName = this._route.snapshot.paramMap.get('serviceName');
+    this.hostName = this._route.snapshot.paramMap.get('hostName');
+    this.dataSource.paginator = this.paginator;
+    setTimeout(() => {
+      this.getSSLBackupCertificates();
+      this.getSSLVHostSNI();
+    })
+  }
+
+  getSSLBackupCertificates() {
+    this.dataSource.data = [];
+    this._device.getSSLBackupCertificates(this.deviceName, this.hostName)
+      .pipe(take(1))
+      .subscribe({
+        next: (resp: any) => {
+          if (resp && resp?.SSLVirtualHost && resp.SSLVirtualHost.backup_certs) {
+            this.dataSource.data = resp.SSLVirtualHost.backup_certs;
+            this.totalRecords = this.dataSource.data.length;
+            this.dataSource.paginator = this.paginator;
+          }
+          this._cdRef.detectChanges();
+        },
+        error: (error: any) => {
+          this._notification.showError(error.message);
+          this._cdRef.detectChanges();
+        }
+      });
+  }
+
+  sslVHostSNI: any = [];
+
+  getSSLVHostSNI() {
+    this.sslVHostSNI = [];
+    this._device.getSSLVHostSNI(this.deviceName, this.hostName)
+      .pipe(take(1))
+      .subscribe({
+        next: (resp: any) => {
+          if (resp && resp?.SSLVirtualHost && resp.SSLVirtualHost?.ssl_sni) {
+            this.sslVHostSNI = resp.SSLVirtualHost.ssl_sni;
+          }
+          this._cdRef.detectChanges();
+        },
+        error: (error: any) => {
+          this._notification.showError(error.message);
+          this._cdRef.detectChanges();
+        }
+      });
+  }
+
+  addBackupSSLCertificate() {
+    this.dialogConfig.data = {
+      domains: this.sslVHostSNI,
+      deviceName: this.deviceName,
+      hostName: this.hostName,
+    };
+    const dialogRef = this.dialog.open(BackupSSLCertificateDialog, this.dialogConfig);
+    dialogRef.afterClosed().subscribe(isAdded => {
+      if (isAdded) {
+        this.getSSLBackupCertificates();
+      }
+    })
+  }
+
+  restoreBackupSSLCertificate(_cert: any) {
+    this.dialogConfig.data = {
+      cert: _cert,
+      deviceName: this.deviceName,
+      hostName: this.hostName,
+    };
+    const dialogRef = this.dialog.open(RestoreSSLCertificateDialog, this.dialogConfig);
+    dialogRef.afterClosed().subscribe(isAdded => {
+      if (isAdded) {
+        this.getSSLBackupCertificates();
+      }
+    })
+  }
+
+  downloadBackupSSLCertificate(_cert: any) {
+    let payload: any = {
+      asso_targets: this.hostName + '-' + _cert?.filename + '-',
+      targets: this.hostName,
+    };
+    // ToDo: Fix the SSL download certificate - https://arraynetworks.atlassian.net/browse/AE-2098
+    // this._device.downloadSSLCertificate(this.deviceName, payload)
+    //   .pipe(take(1))
+    //   .subscribe({
+    //     next: (resp: any) => {
+    //       if (resp) {
+    //         console.log(resp);
+    //         let blob = new Blob([resp], {type: "application/octet-stream"});
+    //         let link = document.createElement("a");
+    //         link.href = window.URL.createObjectURL(blob);
+    //         link.download = _cert?.filename;
+    //         document.body.appendChild(link);
+    //         link.click();
+    //         document.body.removeChild(link);
+    //       }
+    //       this._cdRef.detectChanges();
+    //     },
+    //     error: (error: any) => {
+    //       this._notification.showError(error.message);
+    //       this._cdRef.detectChanges();
+    //     }
+    //   });
+  }
+
+  deleteBackupSSLCertificate(_cert: any) {
+    let deviceName = _cert?.filename;
+    let confirmMsg = `Are you sure you want to delete "${_cert?.filename}"?`
+    this._confirmation.openConfirmDialog({
+      title: `Delete ${deviceName}?`,
+      message: confirmMsg,
+      confirmButtonText: 'Yes, Delete It',
+      cancelButtonText: 'No, Keep It',
+      confirmButtonColor: 'warn',
+      cancelButtonColor: 'primary'
+    }).subscribe(result => {
+      if (result) {
+        let payload: any = {
+          asso_targets: this.hostName + '-' + _cert?.filename + '-',
+          targets: this.hostName,
+        }
+        this._device.deleteSSLCertificate(this.deviceName, payload)
+          .pipe(take(1))
+          .subscribe({
+            next: (resp: any) => {
+              if (resp && resp?.config_change) {
+                this.getSSLBackupCertificates();
+                this._notification.showSuccess(`The SSL Backup certificate was successfully deleted.`);
+              }
+            },
+            error: (error: any) => {
+              this._notification.showError(error.message);
+            }
+          });
+      }
+    })
+  }
+}
+
+@Component({
+  selector: 'backup-ssl-certificate',
+  templateUrl: './backup-ssl-certificate.html',
+  imports: [SharedModule]
+})
+export class BackupSSLCertificateDialog implements OnInit {
+
+  readonly data = inject(MAT_DIALOG_DATA);
+  readonly dialogRef = inject(MatDialogRef<BackupSSLCertificateDialog>);
+  configForm!: FormGroup;
+
+  domains: any = [];
+
+  constructor(
+    private _fB: FormBuilder,
+    private _device: DeviceService,
+    private _cdRef: ChangeDetectorRef,
+    private _notification: NotificationService,
+  ) {
+
+  }
+
+  ngOnInit() {
+    this.configForm = this._fB.group({
+      filename: ['', Validators.required],
+      domain_name: [''],
+      password: ['', Validators.required],
+      confirm_password: ['', [Validators.required]],
+    }, {validators: [CustomValidators.passwordMatchValidator()]})
+    this.domains = this.data?.domains;
+  }
+
+  onCancel() {
+    this.dialogRef.close(false);
+  }
+
+  onSubmit() {
+    if (this.configForm.invalid) {
+      console.log(this.configForm.value);
+      this.configForm.markAllAsTouched();
+      return;
+    }
+    let payload: any = {
+      domain_name: this.configForm.value.domain_name,
+      filename: this.configForm.value.filename,
+      pwd_key: this.configForm.value.password,
+      targets: this.data?.hostName
+    };
+    this._device.backupSSLCertificate(this.data?.deviceName, payload)
+      .pipe(take(1))
+      .subscribe({
+        next: (resp: any) => {
+          if (resp && resp?.config_change) {
+            this.dialogRef.close(true);
+            this._notification.showSuccess(`The SSL certificate backup has been created successfully.`);
+          }
+          this._cdRef.detectChanges();
+        },
+        error: (error: any) => {
+          this._notification.showError(error.message);
+          this._cdRef.detectChanges();
+        }
+      });
+  }
+}
+
+@Component({
+  selector: 'restore-ssl-certificate',
+  templateUrl: './restore-ssl-certificate.html',
+  imports: [SharedModule]
+})
+export class RestoreSSLCertificateDialog implements OnInit {
+
+  readonly data = inject(MAT_DIALOG_DATA);
+  readonly dialogRef = inject(MatDialogRef<RestoreSSLCertificateDialog>);
+  configForm!: FormGroup;
+
+  constructor(
+    private _fB: FormBuilder,
+    private _device: DeviceService,
+    private _cdRef: ChangeDetectorRef,
+    private _notification: NotificationService,
+  ) {
+
+  }
+
+  ngOnInit() {
+    this.configForm = this._fB.group({
+      password: ['', Validators.required],
+    })
+  }
+
+  onCancel() {
+    this.dialogRef.close(false);
+  }
+
+  onSubmit() {
+    if (this.configForm.invalid) {
+      console.log(this.configForm.value);
+      this.configForm.markAllAsTouched();
+      return;
+    }
+    let payload: any = {
+      asso_targets: this.data?.hostName + '-' + this.data?.cert?.filename + '-',
+      pwd_key: this.configForm.value.password,
+      targets: this.data?.hostName
+    };
+    this._device.restoreSSLCertificate(this.data?.deviceName, payload)
+      .pipe(take(1))
+      .subscribe({
+        next: (resp: any) => {
+          if (resp && resp?.config_change) {
+            this.dialogRef.close(true);
+            this._notification.showSuccess(`The SSL certificate has been restored.`);
+          }
+          this._cdRef.detectChanges();
+        },
+        error: (error: any) => {
+          this._notification.showError(error.message);
+          this._cdRef.detectChanges();
+        }
+      });
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/restore-ssl-certificate.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/restore-ssl-certificate.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificate-backup-restore/restore-ssl-certificate.html	(working copy)
@@ -0,0 +1,44 @@
+<h2 mat-dialog-title>Restore SSL Certificate</h2>
+<mat-dialog-content>
+  <form
+    (ngSubmit)="onSubmit()"
+    [formGroup]="configForm"
+    class="login-form"
+  >
+    <div class="form-field-wrapper">
+      <label for="password" class="form-label">Password *</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <input
+          id="password"
+          formControlName="password"
+          matInput
+          placeholder="Password"
+          type="password"
+        />
+        @if (configForm.get('password')?.invalid && configForm.get('password')?.touched) {
+          <mat-error>
+            @if (configForm.get('password')?.errors?.['required']) {
+              Password is required.
+            } @else if (configForm.get('password')?.errors) {
+              Invalid password format.
+            }
+          </mat-error>
+        }
+      </mat-form-field>
+    </div>
+  </form>
+</mat-dialog-content>
+<mat-dialog-actions>
+  <button
+    mat-button
+    color="basic"
+    (click)="onCancel()">
+    Cancel
+  </button>
+  <button
+    mat-raised-button
+    color="primary"
+    (click)="onSubmit()">
+    Submit
+  </button>
+</mat-dialog-actions>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/device-ssl-certificates.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/device-ssl-certificates.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/device-ssl-certificates.html	(working copy)
@@ -0,0 +1,75 @@
+<mat-card class="page-card-1" appearance="filled">
+  <mat-card-header>
+    <div>
+      <button mat-raised-button (click)="addSSLCertificate()">Add</button>
+    </div>
+  </mat-card-header>
+</mat-card>
+<div class="table-container">
+  <table mat-table [dataSource]="dataSource" class="mat-elevation-z1">
+    <ng-container matColumnDef="serial">
+      <th mat-header-cell *matHeaderCellDef> No.</th>
+      <td mat-cell *matCellDef="let element; let i = index;"> {{ i | globalSerial:paginator }}</td>
+    </ng-container>
+    <ng-container matColumnDef="domain">
+      <th mat-header-cell *matHeaderCellDef> Domain Name</th>
+      <td mat-cell *matCellDef="let element">{{ element?.domain_name }}</td>
+    </ng-container>
+    <ng-container matColumnDef="index">
+      <th mat-header-cell *matHeaderCellDef> Index</th>
+      <td mat-cell *matCellDef="let element">{{ element?.index }}</td>
+    </ng-container>
+    <ng-container matColumnDef="type">
+      <th mat-header-cell *matHeaderCellDef> Type</th>
+      <td mat-cell *matCellDef="let element">{{ element?.type }}</td>
+    </ng-container>
+    <ng-container matColumnDef="status">
+      <th mat-header-cell *matHeaderCellDef> Status</th>
+      <td mat-cell *matCellDef="let element">{{ element?.status }}</td>
+    </ng-container>
+    <ng-container matColumnDef="astate">
+      <th mat-header-cell *matHeaderCellDef> Activated State</th>
+      <td mat-cell *matCellDef="let element">
+        @if (element?.activated_state) {
+          <fa-icon [icon]="['far', 'check-circle']" class="success-icon"></fa-icon>
+        } @else {
+          <fa-icon [icon]="['far', 'xmark-circle']" class="delete-icon"></fa-icon>
+        }
+      </td>
+    </ng-container>
+    <ng-container matColumnDef="subject">
+      <th mat-header-cell *matHeaderCellDef> Subject</th>
+      <td mat-cell *matCellDef="let element">{{ element?.subject }}</td>
+    </ng-container>
+    <ng-container matColumnDef="etime">
+      <th mat-header-cell *matHeaderCellDef> Expiry Time</th>
+      <td mat-cell *matCellDef="let element">{{ element?.validity_not_after }}</td>
+    </ng-container>
+    <ng-container matColumnDef="action">
+      <th mat-header-cell *matHeaderCellDef> Action</th>
+      <td mat-cell *matCellDef="let element">
+        <div class="row-action a-link">
+          @if (element?.activated_state) {
+            <fa-icon [icon]="['far', 'stop-circle']" size="lg" matTooltip="Deactivate Certificate"
+                     (click)="deactivateSSLCertificate(element)"></fa-icon>
+          } @else {
+            <fa-icon [icon]="['far', 'play-circle']" size="lg" matTooltip="Activate Certificate"
+                     (click)="activateSSLCertificate(element)"></fa-icon>
+          }
+          <fa-icon [icon]="['far', 'trash-can']" size="lg" class="delete-icon" matTooltip="Delete"
+                   (click)="deleteSSLCertificate(element)"></fa-icon>
+        </div>
+      </td>
+    </ng-container>
+    <tr mat-header-row *matHeaderRowDef="tableColumns"></tr>
+    <tr mat-row *matRowDef="let row; columns: tableColumns;"></tr>
+    <tr class="mat-row table-no-data" *matNoDataRow>
+      <td class="mat-cell" colspan="10">No results found.</td>
+    </tr>
+  </table>
+  <mat-paginator
+    [pageSizeOptions]="[10, 15, 20, 25]"
+    [length]="totalRecords"
+    showFirstLastButtons
+  ></mat-paginator>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/device-ssl-certificates.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/device-ssl-certificates.scss	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/device-ssl-certificates.scss	(working copy)
@@ -0,0 +1,21 @@
+.page-card-1 {
+  width: 100%;
+  border-radius: 0;
+  background-color: inherit;
+  font-size: 14px !important;
+
+  mat-card-header {
+    color: #1170cf;
+  }
+}
+
+mat-card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 4px 10px;
+}
+
+mat-card-title {
+  font-size: medium;
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/device-ssl-certificates.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/device-ssl-certificates.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/device-ssl-certificates.spec.ts	(working copy)
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DeviceSslCertificates } from './device-ssl-certificates';
+
+describe('DeviceSslCertificates', () => {
+  let component: DeviceSslCertificates;
+  let fixture: ComponentFixture<DeviceSslCertificates>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [DeviceSslCertificates]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(DeviceSslCertificates);
+    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/sub-components/device-ssl-certificates/device-ssl-certificates.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/device-ssl-certificates.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/device-ssl-certificates.ts	(working copy)
@@ -0,0 +1,263 @@
+import {ChangeDetectorRef, Component, inject, OnInit, ViewChild} from '@angular/core';
+import {DeviceService} from '../../../services/device-service';
+import {NotificationService} from '../../../services/notification';
+import {take} from 'rxjs/operators';
+import {ActivatedRoute} from '@angular/router';
+import {MatTableDataSource} from '@angular/material/table';
+import {MatPaginator} from '@angular/material/paginator';
+import {MAT_DIALOG_DATA, MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material/dialog';
+import {SharedModule} from '../../../shared/shared-module';
+import {GlobalSerialPipe} from '../../../pipes/global-serial-pipe';
+import {FormBuilder, FormGroup, Validators} from '@angular/forms';
+import {Confirmation} from '../../../services/confirmation';
+
+@Component({
+  selector: 'app-device-ssl-certificates',
+  imports: [SharedModule, GlobalSerialPipe,],
+  templateUrl: './device-ssl-certificates.html',
+  styleUrl: './device-ssl-certificates.scss'
+})
+export class DeviceSslCertificates implements OnInit {
+
+  deviceName: string | null = '';
+  serviceName: string | null = '';
+  hostName: string | null = '';
+  totalRecords: number = 0;
+  tableColumns: string[] = ['serial', 'domain', 'index', 'type', 'status', 'astate', 'subject', 'etime', 'action'];
+  dataSource: MatTableDataSource<any> = new MatTableDataSource();
+  @ViewChild(MatPaginator) paginator!: MatPaginator;
+  dialog = inject(MatDialog);
+  dialogConfig = new MatDialogConfig();
+  sslVHostSNI: any = [];
+
+  constructor(
+    private _device: DeviceService,
+    private _route: ActivatedRoute,
+    private _notification: NotificationService,
+    private _cdRef: ChangeDetectorRef,
+    private _confirmation: Confirmation,
+  ) {
+  }
+
+  ngOnInit() {
+    this.deviceName = this._route.snapshot.paramMap.get('deviceName');
+    this.serviceName = this._route.snapshot.paramMap.get('serviceName');
+    this.hostName = this._route.snapshot.paramMap.get('hostName');
+    this.dataSource.paginator = this.paginator;
+    setTimeout(() => {
+      this.getSSLCertificates();
+      this.getSSLVHostSNI()
+    })
+  }
+
+  getSSLCertificates() {
+    this.dataSource.data = [];
+    this._device.getSSLCertificates(this.deviceName, this.hostName)
+      .pipe(take(1))
+      .subscribe({
+        next: (resp: any) => {
+          if (resp && resp?.SSLVirtualHost && resp.SSLVirtualHost.certs) {
+            this.dataSource.data = resp.SSLVirtualHost.certs;
+            this.totalRecords = this.dataSource.data.length;
+            this.dataSource.paginator = this.paginator;
+          }
+          this._cdRef.detectChanges();
+        },
+        error: (error: any) => {
+          this._notification.showError(error.message);
+          this._cdRef.detectChanges();
+        }
+      });
+  }
+
+  getSSLVHostSNI() {
+    this.sslVHostSNI = [];
+    this._device.getSSLVHostSNI(this.deviceName, this.hostName)
+      .pipe(take(1))
+      .subscribe({
+        next: (resp: any) => {
+          if (resp && resp?.SSLVirtualHost && resp.SSLVirtualHost?.ssl_sni) {
+            this.sslVHostSNI = resp.SSLVirtualHost.ssl_sni;
+          }
+          this._cdRef.detectChanges();
+        },
+        error: (error: any) => {
+          this._notification.showError(error.message);
+          this._cdRef.detectChanges();
+        }
+      });
+  }
+
+  addSSLCertificate() {
+    this.dialogConfig.data = {
+      domains: this.sslVHostSNI,
+      deviceName: this.deviceName,
+      hostName: this.hostName,
+    };
+    const dialogRef = this.dialog.open(ImportDeviceSSLCertificateDialog, this.dialogConfig);
+    dialogRef.afterClosed().subscribe(isAdded => {
+      if (isAdded) {
+        this.getSSLCertificates();
+      }
+    })
+  }
+
+  activateSSLCertificate(_cert: any) {
+    let payload: any = {
+      asso_targets: _cert?.index + '-' + _cert?.type + '-' + this.hostName + '-',
+      targets: this.hostName
+    }
+    this._device.activateSSLCertificate(this.deviceName, payload)
+      .pipe(take(1))
+      .subscribe({
+        next: (resp: any) => {
+          if (resp) {
+            if (resp && resp?.msg) {
+              this._notification.showSuccess(resp?.msg);
+            } else {
+              this._notification.showSuccess(`The SSL certificate has been activated successfully.`);
+            }
+          }
+          this.getSSLCertificates();
+          this._cdRef.detectChanges();
+        },
+        error: (error: any) => {
+          this._notification.showError(error.message);
+          this._cdRef.detectChanges();
+        }
+      });
+  }
+
+  deactivateSSLCertificate(_cert: any) {
+    let payload: any = {
+      asso_targets: _cert?.index + '-' + _cert?.type + '-' + this.hostName + '-',
+      targets: this.hostName
+    }
+    this._device.deactivateSSLCertificate(this.deviceName, payload)
+      .pipe(take(1))
+      .subscribe({
+        next: (resp: any) => {
+          if (resp) {
+            if (resp && resp?.msg) {
+              this._notification.showSuccess(resp?.msg);
+            } else {
+              this._notification.showSuccess(`The SSL certificate has been activated successfully.`);
+            }
+          }
+          this.getSSLCertificates();
+          this._cdRef.detectChanges();
+        },
+        error: (error: any) => {
+          this._notification.showError(error.message);
+          this._cdRef.detectChanges();
+        }
+      });
+  }
+
+  deleteSSLCertificate(_cert: any) {
+    let deviceName = _cert?.filename;
+    let confirmMsg = `Are you sure you want to delete "${_cert?.filename}"?`
+    this._confirmation.openConfirmDialog({
+      title: `Delete ${deviceName}?`,
+      message: confirmMsg,
+      confirmButtonText: 'Yes, Delete It',
+      cancelButtonText: 'No, Keep It',
+      confirmButtonColor: 'warn',
+      cancelButtonColor: 'primary'
+    }).subscribe((result: any) => {
+      if (result) {
+        let payload: any = {
+          asso_targets: _cert?.index + '-' + _cert?.type + '-' + this.hostName + '-',
+          targets: this.hostName
+        }
+        this._device.deleteVHostSSLCertificate(this.deviceName, payload)
+          .pipe(take(1))
+          .subscribe({
+            next: (resp: any) => {
+              if (resp && resp?.config_change) {
+                this.getSSLCertificates();
+                this._notification.showSuccess(`The SSL certificate was successfully deleted.`);
+              }
+            },
+            error: (error: any) => {
+              this._notification.showError(error.message);
+            }
+          });
+      }
+    })
+  }
+}
+
+@Component({
+  selector: 'import-device-ssl-certificate',
+  templateUrl: './import-device-ssl-certificate.html',
+  imports: [SharedModule]
+})
+export class ImportDeviceSSLCertificateDialog implements OnInit {
+
+  readonly data = inject(MAT_DIALOG_DATA);
+  readonly dialogRef = inject(MatDialogRef<ImportDeviceSSLCertificateDialog>);
+  configForm!: FormGroup;
+
+  domains: any = [];
+
+  constructor(
+    private _fB: FormBuilder,
+    private _device: DeviceService,
+    private _cdRef: ChangeDetectorRef,
+    private _notification: NotificationService,
+  ) {
+
+  }
+
+  ngOnInit() {
+    this.configForm = this._fB.group({
+      index: ['1', [Validators.required]],
+      domain_name: [''],
+      content: ['', Validators.required],
+      private_key: ['', [Validators.required]],
+      password: [''],
+    },)
+    this.domains = this.data?.domains;
+  }
+
+  onCancel() {
+    this.dialogRef.close(false);
+  }
+
+  onSubmit() {
+    if (this.configForm.invalid) {
+      console.log(this.configForm.value);
+      this.configForm.markAllAsTouched();
+      return;
+    }
+    let payload: any = {
+      targets: this.data?.hostName,
+      using: {
+        manual_input: {
+          cert_content: this.configForm.value.content,
+          domain_name: this.configForm.value.domain_name,
+          index: this.configForm.value.index,
+          key: this.configForm.value.private_key,
+          key_passphrase: this.configForm.value.password,
+        }
+      }
+    };
+    this._device.importSSLCertificate(this.data?.deviceName, payload)
+      .pipe(take(1))
+      .subscribe({
+        next: (resp: any) => {
+          if (resp && resp?.config_change) {
+            this.dialogRef.close(true);
+            this._notification.showSuccess(`The SSL certificate backup has been created successfully.`);
+          }
+          this._cdRef.detectChanges();
+        },
+        error: (error: any) => {
+          this._notification.showError(error.message);
+          this._cdRef.detectChanges();
+        }
+      });
+  }
+}
+
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/import-device-ssl-certificate.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/import-device-ssl-certificate.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-certificates/import-device-ssl-certificate.html	(working copy)
@@ -0,0 +1,95 @@
+<h2 mat-dialog-title>Import SSL Certificate</h2>
+<mat-dialog-content>
+  <form
+    (ngSubmit)="onSubmit()"
+    [formGroup]="configForm"
+    class="login-form"
+  >
+    <div class="form-field-wrapper">
+      <label for="index" class="form-label">Index *</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <mat-select formControlName="index">
+          <mat-option value='1'>1</mat-option>
+          <mat-option value='2'>2</mat-option>
+          <mat-option value='3'>3</mat-option>
+        </mat-select>
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="domain_name" class="form-label">Domain Name</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <mat-select formControlName="domain_name">
+          <mat-option value=""></mat-option>
+          @for (_domain of domains; track _domain) {
+            <mat-option [value]="_domain?.domain_name">{{ _domain?.domain_name }}</mat-option>
+          }
+        </mat-select>
+        @if (configForm.get('domain_name')?.invalid && configForm.get('domain_name')?.touched) {
+          <mat-error>
+            @if (configForm.get('domain_name')?.errors?.['required']) {
+              Domain name is required.
+            } @else {
+              Invalid domain name format.
+            }
+          </mat-error>
+        }
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="content" class="form-label">Cert Content *</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <textarea matInput formControlName="content"></textarea>
+        @if (configForm.get('content')?.invalid && configForm.get('content')?.touched) {
+          <mat-error>
+            @if (configForm.get('content')?.errors?.['required']) {
+              Certificate content is required.
+            } @else {
+              Invalid certificate content format.
+            }
+          </mat-error>
+        }
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="private_key" class="form-label">Private Key *</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <textarea matInput formControlName="private_key"></textarea>
+        @if (configForm.get('private_key')?.invalid && configForm.get('private_key')?.touched) {
+          <mat-error>
+            @if (configForm.get('private_key')?.errors?.['required']) {
+              Private key is required.
+            } @else {
+              Invalid private key format.
+            }
+          </mat-error>
+        }
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="password" class="form-label">Key Passphrase</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <input
+          id="password"
+          formControlName="password"
+          matInput
+          placeholder="Passphrase"
+          type="password"
+        />
+      </mat-form-field>
+    </div>
+  </form>
+</mat-dialog-content>
+<mat-dialog-actions>
+  <button
+    mat-button
+    color="basic"
+    (click)="onCancel()">
+    Cancel
+  </button>
+  <button
+    mat-raised-button
+    color="primary"
+    (click)="onSubmit()">
+    Submit
+  </button>
+</mat-dialog-actions>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates.html	(working copy)
@@ -0,0 +1,40 @@
+<mat-card class="page-card-1" appearance="filled">
+  <mat-card-header>
+    <div>
+      <button mat-raised-button (click)="addIntermediateCA()">Add</button>
+    </div>
+  </mat-card-header>
+</mat-card>
+<div class="table-container">
+  <table mat-table [dataSource]="dataSource" class="mat-elevation-z1">
+    <ng-container matColumnDef="serial">
+      <th mat-header-cell *matHeaderCellDef> No.</th>
+      <td mat-cell *matCellDef="let element; let i = index;"> {{ i | globalSerial:paginator }}</td>
+    </ng-container>
+    <ng-container matColumnDef="domain">
+      <th mat-header-cell *matHeaderCellDef> Domain Name</th>
+      <td mat-cell *matCellDef="let element">{{ element?.domain_name }}</td>
+    </ng-container>
+    <ng-container matColumnDef="filename">
+      <th mat-header-cell *matHeaderCellDef> Filename</th>
+      <td mat-cell *matCellDef="let element">{{ element?.filename }}</td>
+    </ng-container>
+    <ng-container matColumnDef="action">
+      <th mat-header-cell *matHeaderCellDef> Action</th>
+      <td mat-cell *matCellDef="let element">
+        <div class="row-action a-link">
+        </div>
+      </td>
+    </ng-container>
+    <tr mat-header-row *matHeaderRowDef="tableColumns"></tr>
+    <tr mat-row *matRowDef="let row; columns: tableColumns;"></tr>
+    <tr class="mat-row table-no-data" *matNoDataRow>
+      <td class="mat-cell" colspan="10">No results found.</td>
+    </tr>
+  </table>
+  <mat-paginator
+    [pageSizeOptions]="[10, 15, 20, 25]"
+    [length]="totalRecords"
+    showFirstLastButtons
+  ></mat-paginator>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates.scss	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates.scss	(working copy)
@@ -0,0 +1,21 @@
+.page-card-1 {
+  width: 100%;
+  border-radius: 0;
+  background-color: inherit;
+  font-size: 14px !important;
+
+  mat-card-header {
+    color: #1170cf;
+  }
+}
+
+mat-card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 4px 10px;
+}
+
+mat-card-title {
+  font-size: medium;
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates.spec.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates.spec.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates.spec.ts	(working copy)
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DeviceSslInterCaCertificates } from './device-ssl-inter-ca-certificates';
+
+describe('DeviceSslInterCaCertificates', () => {
+  let component: DeviceSslInterCaCertificates;
+  let fixture: ComponentFixture<DeviceSslInterCaCertificates>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [DeviceSslInterCaCertificates]
+    })
+    .compileComponents();
+
+    fixture = TestBed.createComponent(DeviceSslInterCaCertificates);
+    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/sub-components/device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates.ts	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates.ts	(working copy)
@@ -0,0 +1,75 @@
+import {ChangeDetectorRef, Component, inject, OnInit, ViewChild} from '@angular/core';
+import {GlobalSerialPipe} from '../../../pipes/global-serial-pipe';
+import {SharedModule} from '../../../shared/shared-module';
+import {MatTableDataSource} from '@angular/material/table';
+import {MatPaginator} from '@angular/material/paginator';
+import {MatDialog, MatDialogConfig} from '@angular/material/dialog';
+import {DeviceService} from '../../../services/device-service';
+import {ActivatedRoute} from '@angular/router';
+import {NotificationService} from '../../../services/notification';
+import {Confirmation} from '../../../services/confirmation';
+import {take} from 'rxjs/operators';
+
+
+@Component({
+  selector: 'app-device-ssl-inter-ca-certificates',
+  imports: [
+    SharedModule,
+    GlobalSerialPipe,
+  ],
+  templateUrl: './device-ssl-inter-ca-certificates.html',
+  styleUrl: './device-ssl-inter-ca-certificates.scss'
+})
+export class DeviceSslInterCaCertificates implements OnInit {
+
+  deviceName: string | null = '';
+  serviceName: string | null = '';
+  hostName: string | null = '';
+  totalRecords: number = 0;
+  tableColumns: string[] = ['serial', 'domain', 'filename', 'action'];
+  dataSource: MatTableDataSource<any> = new MatTableDataSource();
+  @ViewChild(MatPaginator) paginator!: MatPaginator;
+  dialog = inject(MatDialog);
+  dialogConfig = new MatDialogConfig();
+
+  constructor(
+    private _device: DeviceService,
+    private _route: ActivatedRoute,
+    private _notification: NotificationService,
+    private _cdRef: ChangeDetectorRef,
+    private _confirmation: Confirmation,
+  ) {
+  }
+
+  ngOnInit() {
+    this.deviceName = this._route.snapshot.paramMap.get('deviceName');
+    this.serviceName = this._route.snapshot.paramMap.get('serviceName');
+    this.hostName = this._route.snapshot.paramMap.get('hostName');
+    this.dataSource.paginator = this.paginator;
+    setTimeout(() => {
+      this.getIntermediateCACertificates();
+    })
+  }
+
+  getIntermediateCACertificates() {
+    this.dataSource.data = [];
+    this._device.getSSLInterCACertificates(this.deviceName, this.hostName)
+      .pipe(take(1))
+      .subscribe({
+        next: (resp: any) => {
+          if (resp && resp?.SSLVirtualHost && resp.SSLVirtualHost.interca_certs) {
+            this.dataSource.data = resp.SSLVirtualHost.interca_certs;
+            this.totalRecords = this.dataSource.data.length;
+            this.dataSource.paginator = this.paginator;
+          }
+          this._cdRef.detectChanges();
+        },
+        error: (error: any) => {
+          this._notification.showError(error.message);
+          this._cdRef.detectChanges();
+        }
+      });
+  }
+
+  addIntermediateCA() {}
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-overview/device-ssl-overview.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-overview/device-ssl-overview.html	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-overview/device-ssl-overview.html	(working copy)
@@ -1 +1,35 @@
-<p>device-ssl-overview works!</p>
+<mat-card class="page-card-1" appearance="filled">
+  <mat-card-header>
+    <mat-card-title>
+      <a class="back-to-main-page" (click)="backToSSLCertificateManagement()">
+        <fa-icon [icon]="['far', 'circle-left']"></fa-icon>
+        Virtual Site - {{ serviceName }}
+      </a>
+    </mat-card-title>
+  </mat-card-header>
+</mat-card>
+<div class="tab-container">
+  <mat-tab-group animationDuration="0ms" [selectedIndex]="selectedTabIndex" (selectedTabChange)="onTabChange($event)">
+    <mat-tab label="Certificate List">
+      <ng-template matTabContent>
+        <div class="tab-content">
+          <app-device-ssl-certificates/>
+        </div>
+      </ng-template>
+    </mat-tab>
+    <mat-tab label="Immediate CA Certificate List">
+      <ng-template matTabContent>
+        <div class="tab-content">
+          <app-device-ssl-inter-ca-certificates/>
+        </div>
+      </ng-template>
+    </mat-tab>
+    <mat-tab label="Certificate Backup/Restore">
+      <ng-template matTabContent>
+        <div class="tab-content">
+          <app-device-ssl-certificate-backup-restore/>
+        </div>
+      </ng-template>
+    </mat-tab>
+  </mat-tab-group>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-overview/device-ssl-overview.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-overview/device-ssl-overview.scss	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-overview/device-ssl-overview.scss	(working copy)
@@ -0,0 +1,21 @@
+.page-card-1 {
+  width: 100%;
+  border-radius: 0;
+  background-color: inherit;
+  font-size: 14px !important;
+
+  mat-card-header {
+    color: #1170cf;
+  }
+}
+
+mat-card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 4px 10px;
+}
+
+mat-card-title {
+  font-size: medium;
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-overview/device-ssl-overview.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-overview/device-ssl-overview.ts	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/device-ssl-overview/device-ssl-overview.ts	(working copy)
@@ -1,11 +1,71 @@
-import { Component } from '@angular/core';
+import {Component, OnInit} from '@angular/core';
+import {MatTabChangeEvent} from '@angular/material/tabs';
+import {SharedModule} from '../../../shared/shared-module';
+import {ActivatedRoute, Router} from '@angular/router';
+import {DeviceSslCertificates} from '../device-ssl-certificates/device-ssl-certificates';
+import {DeviceSslInterCaCertificates} from '../device-ssl-inter-ca-certificates/device-ssl-inter-ca-certificates';
+import {
+  DeviceSslCertificateBackupRestore
+} from '../device-ssl-certificate-backup-restore/device-ssl-certificate-backup-restore';
 
 @Component({
   selector: 'app-device-ssl-overview',
-  imports: [],
+  imports: [SharedModule, DeviceSslCertificates, DeviceSslInterCaCertificates, DeviceSslCertificateBackupRestore],
   templateUrl: './device-ssl-overview.html',
   styleUrl: './device-ssl-overview.scss'
 })
-export class DeviceSslOverview {
+export class DeviceSslOverview implements OnInit {
 
+  selectedTabIndex: number = 0;
+  deviceName: string | null = '';
+  serviceName: string | null = '';
+  hostName: string | null = '';
+  private tabNames: string[] = [
+    'Certificate List',
+    'Immediate CA Certificate List',
+    'Certificate Backup/Restore',
+  ];
+
+  constructor(private _route: ActivatedRoute, private _router: Router) {
+  }
+
+  ngOnInit(): void {
+    this.deviceName = this._route.snapshot.paramMap.get('deviceName');
+    this.serviceName = this._route.snapshot.paramMap.get('serviceName');
+    this.hostName = this._route.snapshot.paramMap.get('hostName');
+
+    this._route.queryParams.subscribe(params => {
+      const tabParam = params['tab'];
+      if (tabParam) {
+        const index = this.tabNames.indexOf(tabParam);
+        if (index !== -1) {
+          this.selectedTabIndex = index;
+        } else {
+          this.selectedTabIndex = 0;
+        }
+      } else {
+        this.updateQueryParams(this.selectedTabIndex);
+      }
+    });
+  }
+
+  onTabChange(event: MatTabChangeEvent): void {
+    this.selectedTabIndex = event.index;
+    this.updateQueryParams(event.index);
+  }
+
+  backToSSLCertificateManagement(): void {
+    this._router.navigate(['/device/ssl']);
+  }
+
+  private updateQueryParams(tabIndex: number): void {
+    const tabName = this.tabNames[tabIndex];
+    if (tabName) {
+      this._router.navigate([], {
+        relativeTo: this._route,
+        queryParams: {tab: tabName},
+        queryParamsHandling: 'merge'
+      });
+    }
+  }
 }
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/vpn-acl-resource-groups/vpn-acl-resource-groups.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/vpn-acl-resource-groups/vpn-acl-resource-groups.ts	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/vpn-acl-resource-groups/vpn-acl-resource-groups.ts	(working copy)
@@ -175,7 +175,6 @@
   }
 
   syncGroup(_group: any) {
-    console.log('syncGroup', _group);
     this.dialogConfig.data = {
       serviceName: this.serviceName,
       deviceName: this.deviceName,
@@ -560,14 +559,12 @@
       'no acl resourcegroup "' + base_acl + '"',
       'acl resourcegroup ' + data.base_acl.type + ' "' + base_acl + '" "' + data.base_acl.desc + '"'
     ];
-    console.log(result, data);
     let all_dict: any = {}
     let post_data: any = {'cmd': 'show acl resource "' + base_acl + '"', 'vsite_name': base_vsite};
     this._vpn.executeAGCLICommand(this.data?.deviceName, post_data)
       .pipe(take(1)).subscribe({
       next: (res: any) => {
         if (res) {
-          console.log(res);
           let conf_list: any = res?.contents;
           conf_list.forEach((item: any) => {
             if (item?.cmdid == 'acl resource') {
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/constants/api_urls.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/constants/api_urls.ts	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/constants/api_urls.ts	(working copy)
@@ -133,4 +133,22 @@
   UPLOAD_DEVICE_BUILD_URL: `${PREFIX}/api/cm/configuration/update/Update/_perform`,
   UPDATE_DEVICE_BUILD_URL: `${PREFIX}/api/cm/configuration/update/Update/_perform`,
   DEVICE_CLI_EXTEND_URL: `${PREFIX}/proxy_req_dev/rest/ag/global/cli_extend`,
+  UPDATE_DEVICE_VHOST_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost/vh1/host_status`,
+  GET_SSL_VHOST_CERTIFICATES_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost`,
+  GET_SSL_VHOST_BACKUP_CERTIFICATES_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost`,
+  GET_SSL_VHOST_INTERMEDIATE_CA_CERTIFICATES_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost/vh1/interca_certs`,
+  GET_SSL_VHOST_SNI_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost`,
+  BACKUP_SSL_VHOST_CERTIFICATE_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost/_Backup`,
+  RESTORE_SSL_VHOST_CERTIFICATE_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost/_Restore`,
+  DELETE_SSL_VHOST_BACKUP_CERTIFICATE_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost/_Delete_BackupCert`,
+  DOWNLOAD_SSL_VHOST_BACKUP_CERTIFICATE_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost/_DownloadSavedFile`,
+  IMPORT_SSL_CERTIFICATE_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost/_Import_Cert`,
+  ACTIVATE_SSL_CERTIFICATE_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost/_Activate`,
+  DEACTIVATE_SSL_CERTIFICATE_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost/_Deactivate`,
+  DELETE_SSL_CERTIFICATE_URL: `${PREFIX}/proxy_req_dev/rest/loadbalancing/slb/ssl/SSLVirtualHost/_Delete_Cert`,
+  GET_DEVICE_HA_LIST_URL: `${PREFIX}/cm/get_device_ha_list`,
+  GET_DEVICE_HA_CONFIG_BY_NAME_URL: `${PREFIX}/cm/get_device_ha_list`,
+  GET_DEVICE_HA_UNITS_BY_NAME_URL: `${PREFIX}/cm/get_device_ha_units`,
+  GET_DEVICE_HA_GROUPS_BY_NAME_URL: `${PREFIX}/cm/get_device_ha_groups`,
+  SWITCH_DEVICE_HA_GROUP_URL: `${PREFIX}/cm/swith_ha_group`,
 } as const; // Makes properties readonly
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/device-service.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/device-service.ts	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/device-service.ts	(working copy)
@@ -279,5 +279,194 @@
       isFormData: true,
       csrfInFormData: true
     });
+  }
+
+  executeCLICommand(aGName: string, rawPayload: any) {
+    return this.http.post(URLS.DEVICE_CLI_EXTEND_URL, rawPayload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: aGName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
+  }
+
+  updateSSLVHost(aGName: string, rawPayload: any) {
+    return this.http.put(URLS.UPDATE_DEVICE_VHOST_URL, rawPayload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: aGName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
+  }
+
+  getSSLCertificates(aGName: string | null, vhost: string | null) {
+    return this.http.get(`${URLS.GET_SSL_VHOST_CERTIFICATES_URL}/${vhost}/certs`, {},
+      [{name: 'Cm-Data', value: aGName}, {name: 'Cm-Type', value: 'device'}]);
+  }
+
+  getSSLBackupCertificates(aGName: string | null, vhost: string | null) {
+    return this.http.get(`${URLS.GET_SSL_VHOST_BACKUP_CERTIFICATES_URL}/${vhost}/backup_certs`, {},
+      [{name: 'Cm-Data', value: aGName}, {name: 'Cm-Type', value: 'device'}]);
+  }
+
+  getSSLInterCACertificates(aGName: string | null, vhost: string | null) {
+    return this.http.get(`${URLS.GET_SSL_VHOST_INTERMEDIATE_CA_CERTIFICATES_URL}/${vhost}/backup_certs`, {},
+      [{name: 'Cm-Data', value: aGName}, {name: 'Cm-Type', value: 'device'}]);
+  }
+
+  getSSLVHostSNI(aGName: string | null, vhost: string | null) {
+    return this.http.get(`${URLS.GET_SSL_VHOST_SNI_URL}/${vhost}/ssl_sni`, {},
+      [{name: 'Cm-Data', value: aGName}, {name: 'Cm-Type', value: 'device'}]);
+  }
+
+  backupSSLCertificate(deviceName: string | null, rawPayload: any) {
+    return this.http.post(URLS.BACKUP_SSL_VHOST_CERTIFICATE_URL, rawPayload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: deviceName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
   }
+
+  restoreSSLCertificate(deviceName: string | null, rawPayload: any) {
+    return this.http.post(URLS.RESTORE_SSL_VHOST_CERTIFICATE_URL, rawPayload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: deviceName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
+  }
+
+  deleteSSLCertificate(deviceName: string | null, rawPayload: any) {
+    return this.http.post(URLS.DELETE_SSL_VHOST_BACKUP_CERTIFICATE_URL, rawPayload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: deviceName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
+  }
+
+  importSSLCertificate(deviceName: string | null, rawPayload: any) {
+    return this.http.post(URLS.IMPORT_SSL_CERTIFICATE_URL, rawPayload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: deviceName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
+  }
+
+  activateSSLCertificate(deviceName: string | null, rawPayload: any) {
+    return this.http.post(URLS.ACTIVATE_SSL_CERTIFICATE_URL, rawPayload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: deviceName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
+  }
+
+  deactivateSSLCertificate(deviceName: string | null, rawPayload: any) {
+    return this.http.post(URLS.DEACTIVATE_SSL_CERTIFICATE_URL, rawPayload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: deviceName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
+  }
+
+  deleteVHostSSLCertificate(deviceName: string | null, rawPayload: any) {
+    return this.http.post(URLS.DELETE_SSL_CERTIFICATE_URL, rawPayload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: deviceName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
+  }
+
+  downloadSSLCertificate(aGName: string | null, rawPayload: any) {
+    return this.http.post(URLS.DOWNLOAD_SSL_VHOST_BACKUP_CERTIFICATE_URL, rawPayload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: aGName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
+  }
+
+  getDeviceHAList() {
+    return this.http.get(URLS.GET_DEVICE_HA_LIST_URL);
+  }
+
+  getDeviceHAConfigByName(deviceName: any, payload: any) {
+    return this.http.post(URLS.GET_DEVICE_HA_CONFIG_BY_NAME_URL, payload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: deviceName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
+  }
+
+  getDeviceHAUnitsByName(deviceName: any, payload: any) {
+    return this.http.post(URLS.GET_DEVICE_HA_UNITS_BY_NAME_URL, payload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: deviceName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
+  }
+
+  getDeviceHAGroupsByName(deviceName: any, payload: any) {
+    return this.http.post(URLS.GET_DEVICE_HA_GROUPS_BY_NAME_URL, payload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }, [
+        {name: 'Cm-Data', value: deviceName},
+        {name: 'Cm-Type', value: 'device'}
+      ]
+    );
+  }
+
+  switchHAGroup(payload: any) {
+    return this.http.post(URLS.SWITCH_DEVICE_HA_GROUP_URL, payload, {
+        csrf: true,
+        isFormData: true,
+        csrfInFormData: true
+      }
+    );
+  }
 }
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/http.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/http.ts	(revision 2692)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/http.ts	(working copy)
@@ -52,8 +52,15 @@
     return data; // JSON by default
   }
 
-  get<T>(url: string, options?: HttpOptions): Observable<T> {
-    return this.http.get<T>(url, this.buildOptions(options));
+  get<T>(url: string, options?: HttpOptions, headers: any = null): Observable<T> {
+    const opts = this.buildOptions(options);
+
+    if (headers !== null) {
+      headers.forEach((header: any) => {
+        opts.headers = opts.headers.append(header.name, header.value);
+      });
+    }
+    return this.http.get<T>(url, opts);
   }
 
   post<T>(url: string, data: any, options?: HttpOptions, headers: any = null): Observable<T> {
@@ -69,11 +76,10 @@
         opts.headers = opts.headers.append(header.name, header.value);
       })
     }
-
     return this.http.post<T>(url, this.prepareBody(data, options), opts);
   }
 
-  put<T>(url: string, data: any, options?: HttpOptions): Observable<T> {
+  put<T>(url: string, data: any, options?: HttpOptions, headers: any = null): Observable<T> {
     const opts = this.buildOptions(options);
 
     if (options?.isForm) {
@@ -81,7 +87,11 @@
     } else if (!options?.isFormData) {
       opts.headers = opts.headers.set('Content-Type', 'application/json');
     }
-
+    if (headers !== null){
+      headers.forEach((header: any) => {
+        opts.headers = opts.headers.append(header.name, header.value);
+      })
+    }
     return this.http.put<T>(url, this.prepareBody(data, options), opts);
   }
 
