projects/cobbler-frontend/src/app/items/network-interface/overview/network-interface-overview.component.ts

Implements

OnInit OnDestroy AfterViewInit

Metadata

Relationships

Used by

No results matching.

Depends on

Index

Properties
Methods

Constructor

constructor()

Methods

addNetworkInterface
addNetworkInterface()
Returns : void
deleteInterface
deleteInterface(interfaceName: string)
Parameters :
Name Type Optional
interfaceName string No
Returns : void
ngAfterViewInit
ngAfterViewInit()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
renameInterface
renameInterface(name: string)
Parameters :
Name Type Optional
name string No
Returns : void
Private retrieveInterfaces
retrieveInterfaces()
Returns : void
showInterface
showInterface(name: string)
Parameters :
Name Type Optional
name string No
Returns : void

Properties

Private _snackBar
Type : unknown
Default value : inject(MatSnackBar)
Private cobblerApiService
Type : unknown
Default value : inject(CobblerApiService)
dataSource
Type : unknown
Default value : new MatTableDataSource<NetworkInterfacePair>([])
Readonly dialog
Type : unknown
Default value : inject<MatDialog>(MatDialog)
displayedColumns
Type : string[]
Default value : [ 'name', 'mac_address', 'ipv4_address', 'ipv6_address', 'actions', ]
Private ngUnsubscribe
Type : unknown
Default value : new Subject<void>()
paginator
Type : MatPaginator
Decorators :
@ViewChild(MatPaginator)
Private route
Type : unknown
Default value : inject(ActivatedRoute)
Private router
Type : unknown
Default value : inject(Router)
systemName
Type : string
table
Type : MatTable<System>
Decorators :
@ViewChild(MatTable)
Private userService
Type : unknown
Default value : inject(UserService)
import {
  AfterViewInit,
  Component,
  OnDestroy,
  OnInit,
  ViewChild,
  inject,
} from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { MatSnackBar } from '@angular/material/snack-bar';
import {
  MatTable,
  MatTableDataSource,
  MatTableModule,
} from '@angular/material/table';
import { MatTooltip } from '@angular/material/tooltip';
import { ActivatedRoute, Router } from '@angular/router';
import { CobblerApiService, NetworkInterface, System } from 'cobbler-api';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { DialogConfirmCancelData } from '../../../common/dialog-box-confirm-cancel-edit/dialog-box-confirm-cancel-edit.component';
import { DialogItemRenameComponent } from '../../../common/dialog-item-rename/dialog-item-rename.component';
import { UserService } from '../../../services/user.service';
import Utils from '../../../utils';
import { TemplateCreateComponent } from '../../template/create/template-create.component';
import { NetworkInterfaceCreateComponent } from '../create/network-interface-create.component';
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';

interface NetworkInterfacePair {
  interfaceName: string;
  networkInterface: NetworkInterface;
}

@Component({
  selector: 'cobbler-network-interface-overview',
  imports: [
    MatTableModule,
    MatMenuModule,
    MatIconModule,
    MatButtonModule,
    MatTooltip,
    MatPaginatorModule,
  ],
  templateUrl: './network-interface-overview.component.html',
  styleUrl: './network-interface-overview.component.scss',
})
export class NetworkInterfaceOverviewComponent
  implements OnInit, OnDestroy, AfterViewInit
{
  private route = inject(ActivatedRoute);
  private userService = inject(UserService);
  private cobblerApiService = inject(CobblerApiService);
  private router = inject(Router);
  private _snackBar = inject(MatSnackBar);
  readonly dialog = inject<MatDialog>(MatDialog);

  // Unsubscribe
  private ngUnsubscribe = new Subject<void>();

  // Table
  displayedColumns: string[] = [
    'name',
    'mac_address',
    'ipv4_address',
    'ipv6_address',
    'actions',
  ];
  dataSource = new MatTableDataSource<NetworkInterfacePair>([]);
  systemName: string;

  @ViewChild(MatTable) table: MatTable<System>;
  @ViewChild(MatPaginator) paginator!: MatPaginator;

  constructor() {
    this.systemName = this.route.snapshot.paramMap.get('name');
  }

  ngOnInit(): void {
    this.retrieveInterfaces();
  }

  ngAfterViewInit(): void {
    this.dataSource.paginator = this.paginator;
  }

  ngOnDestroy(): void {
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }

  private retrieveInterfaces(): void {
    this.cobblerApiService
      .get_system(this.systemName, false, false, this.userService.token)
      .pipe(takeUntil(this.ngUnsubscribe))
      .subscribe((cobblerSystem) => {
        const result = new Array<NetworkInterfacePair>();
        cobblerSystem.interfaces.forEach(
          (networkInterfaceMap, networkInterfaceName) => {
            const networkInterfaceObject = Object.fromEntries(
              networkInterfaceMap,
            ) as NetworkInterface;
            result.push({
              interfaceName: networkInterfaceName,
              networkInterface: networkInterfaceObject,
            });
          },
        );
        this.dataSource.data = result;
      });
  }

  addNetworkInterface(): void {
    const dialogRef = this.dialog.open(NetworkInterfaceCreateComponent, {
      width: '40%',
      data: { systemName: this.systemName },
    });
    dialogRef.afterClosed().subscribe((result) => {
      if (typeof result === 'string') {
        this.router.navigate([
          '/items',
          'system',
          this.systemName,
          'interface',
          result,
        ]);
      }
    });
  }

  showInterface(name: string): void {
    this.router.navigate([
      '/items',
      'system',
      this.systemName,
      'interface',
      name,
    ]);
  }

  renameInterface(name: string): void {
    const dialogRef = this.dialog.open(DialogItemRenameComponent, {
      data: {
        itemType: 'NetworkInterface',
        itemName: name,
        itemUid: '',
      },
    });

    dialogRef.afterClosed().subscribe((newItemName) => {
      if (newItemName === undefined) {
        // Cancel means we don't need to rename the system
        return;
      }
      this.cobblerApiService
        .get_system_handle(this.systemName, this.userService.token)
        .pipe(takeUntil(this.ngUnsubscribe))
        .subscribe({
          next: (systemHandle) => {
            const interfaceMap = new Map<string, string>();
            interfaceMap.set('interface', name);
            interfaceMap.set('rename_interface', newItemName);
            this.cobblerApiService
              .modify_system(
                systemHandle,
                'rename_interface',
                interfaceMap,
                this.userService.token,
              )
              .pipe(takeUntil(this.ngUnsubscribe))
              .subscribe({
                next: (value) => {
                  this.cobblerApiService
                    .save_system(systemHandle, this.userService.token)
                    .pipe(takeUntil(this.ngUnsubscribe))
                    .subscribe({
                      next: () => {
                        this.retrieveInterfaces();
                      },
                      error: (error) => {
                        // HTML encode the error message since it originates from XML
                        this._snackBar.open(
                          Utils.toHTML(error.message),
                          $localize`:@@snackbar.action.close:Close`,
                        );
                      },
                    });
                },
                error: (error) => {
                  // HTML encode the error message since it originates from XML
                  this._snackBar.open(
                    Utils.toHTML(error.message),
                    $localize`:@@snackbar.action.close:Close`,
                  );
                },
              });
          },
          error: (error) => {
            // HTML encode the error message since it originates from XML
            this._snackBar.open(
              Utils.toHTML(error.message),
              $localize`:@@snackbar.action.close:Close`,
            );
          },
        });
    });
  }

  deleteInterface(interfaceName: string): void {
    this.cobblerApiService
      .get_system_handle(this.systemName, this.userService.token)
      .pipe(takeUntil(this.ngUnsubscribe))
      .subscribe({
        next: (systemHandle) => {
          this.cobblerApiService
            .modify_system(
              systemHandle,
              'delete_interface',
              interfaceName,
              this.userService.token,
            )
            .pipe(takeUntil(this.ngUnsubscribe))
            .subscribe({
              next: (value) => {
                if (value) {
                  this.cobblerApiService
                    .save_system(systemHandle, this.userService.token)
                    .pipe(takeUntil(this.ngUnsubscribe))
                    .subscribe({
                      next: () => {
                        this.retrieveInterfaces();
                      },
                      error: (error) => {
                        // HTML encode the error message since it originates from XML
                        this._snackBar.open(
                          Utils.toHTML(error.message),
                          $localize`:@@snackbar.action.close:Close`,
                        );
                      },
                    });
                } else {
                  this._snackBar.open(
                    $localize`:@@error.delete-failed:Delete failed! Check server logs for more information.`,
                    $localize`:@@snackbar.action.close:Close`,
                  );
                }
              },
              error: (err) => {
                // HTML encode the error message since it originates from XML
                this._snackBar.open(
                  Utils.toHTML(err.message),
                  $localize`:@@snackbar.action.close:Close`,
                );
              },
            });
        },
        error: (err) => {
          // HTML encode the error message since it originates from XML
          this._snackBar.open(
            Utils.toHTML(err.message),
            $localize`:@@snackbar.action.close:Close`,
          );
        },
      });
  }
}
<div class="title-table">
  <div class="title-row">
    <h1 class="title title-cell-text" i18n="@@network-interface.overview.title">
      INTERFACES FOR SYSTEM - {{ systemName }}
    </h1>
    <span class="title-cell-button">
      <button
        mat-icon-button
        data-testid="item-add-button"
        (click)="this.addNetworkInterface()"
        matTooltip="Add Network Interface"
        i18n-matTooltip="@@network-interface.overview.add-tooltip"
      >
        <mat-icon>add</mat-icon>
      </button></span
    >
  </div>
</div>

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  <!-- Name Column -->
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef i18n="@@table.col.name">Name</th>
    <td mat-cell *matCellDef="let element">{{ element.interfaceName }}</td>
  </ng-container>

  <!-- MAC Column -->
  <ng-container matColumnDef="mac_address">
    <th
      mat-header-cell
      *matHeaderCellDef
      i18n="@@network-interface.overview.col.mac-address"
    >
      MAC Address
    </th>
    <td mat-cell *matCellDef="let element">
      {{ element.networkInterface.mac_address }}
    </td>
  </ng-container>

  <!-- IPv4 Address Column -->
  <ng-container matColumnDef="ipv4_address">
    <th
      mat-header-cell
      *matHeaderCellDef
      i18n="@@network-interface.overview.col.ipv4-address"
    >
      IPv4 Address
    </th>
    <td mat-cell *matCellDef="let element">
      {{ element.networkInterface.ip }}
    </td>
  </ng-container>

  <!-- IPv6 Address Column -->
  <ng-container matColumnDef="ipv6_address">
    <th
      mat-header-cell
      *matHeaderCellDef
      i18n="@@network-interface.overview.col.ipv6-address"
    >
      IPv6 Address
    </th>
    <td mat-cell *matCellDef="let element">
      {{ element.networkInterface.ipv6_address }}
    </td>
  </ng-container>

  <ng-container matColumnDef="actions">
    <th mat-header-cell *matHeaderCellDef></th>
    <td mat-cell *matCellDef="let element">
      <button mat-icon-button [matMenuTriggerFor]="menu">
        <mat-icon>more_vert</mat-icon>
      </button>
      <mat-menu #menu="matMenu">
        <button mat-menu-item (click)="showInterface(element.interfaceName)">
          <mat-icon>visibility</mat-icon>
          <span i18n="@@item.action.show-details">Show details</span>
        </button>
        <button mat-menu-item (click)="renameInterface(element.interfaceName)">
          <mat-icon>edit</mat-icon>
          <span i18n="@@item.action.rename">Rename</span>
        </button>
        <button mat-menu-item (click)="deleteInterface(element.interfaceName)">
          <mat-icon>delete</mat-icon>
          <span i18n="@@item.action.delete">Delete</span>
        </button>
      </mat-menu>
    </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
<mat-paginator
  [length]="100"
  [pageSize]="10"
  [pageSizeOptions]="[5, 10, 25, 100]"
  aria-label="Select page"
  i18n-aria-label="@@paginator.select-page"
>
</mat-paginator>

./network-interface-overview.component.scss

.title-table {
  display: table;
  width: 100%;
}

.title-row {
  display: table-cell;
  width: 100%;
}

.title-cell-text {
  display: table-cell;
  width: 100%;
  vertical-align: middle;
}

.title-cell-button {
  display: table-cell;
}

.form-replicate {
  min-width: 150px;
  max-width: 600px;
  width: 100%;
}

.form-field-full-width {
  width: 100%;
}

table.mat-mdc-table {
  border-radius: 14px 14px 0 0;
  box-shadow: none;
  overflow: hidden;
  background-color: white;
}

// Table cell
.mat-mdc-header-cell {
  border-bottom: 1px solid #cbcbcb;
}

.mat-mdc-cell {
  border-bottom: 1px solid #cbcbcb;
}

.mat-mdc-paginator {
  border-radius: 0 0 12px 12px;
  background-color: white;
}

:host-context(.dark-theme) .mat-mdc-table {
  background-color: #1a1b1f;
}

:host-context(.dark-theme) .mat-mdc-paginator {
  background-color: #1a1b1f;
}

:host-context(.dark-theme) .mat-mdc-header-cell {
  border-bottom: 1px solid #555555;
}

:host-context(.dark-theme) .mat-mdc-cell {
  border-bottom: 1px solid #555555;
}

:host-context(.dark-theme) a {
  color: white;
}

:host-context(.dark-theme) .link-icon {
  color: rgba(255, 255, 255, 0.372);
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""